﻿/* ==========================================================================
   naregua.css — design system do produto, sobre o Bootstrap 5.

   Sem build step: tokens em CSS custom properties + override das classes do
   Bootstrap, para o design valer em toda view sem reescrever cada uma.
   Ordem de carga: bootstrap.min.css -> naregua.css -> TemaPublico (por tenant).

   Azul e acento, nao banho de cor: superficies em branco/cinza, azul em acao
   primaria, foco, selecao e dado. Toda superficie de marca sai de
   var(--cor-marca) — nenhum hex de marca hard-coded — e as derivadas (hover,
   active, suave, chip) saem de color-mix, entao trocar a cor do tenant
   recalcula tudo.

   Secoes: 1 tokens · 2 base · 3 Bootstrap · 4 componentes · 5 landing
           6 publico · 7 painel
   ========================================================================== */

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

:root {
    /* Escala azul. */
    --azul-50: #EFF6FF;    /* superficie suave, hover de linha, fundo de badge */
    --azul-100: #DBEAFE;   /* borda suave, chip */
    --azul-300: #93C5FD;   /* disabled de marca */
    --azul-500: #3B82F6;   /* hover */
    --azul-600: #2563EB;   /* PRIMARIA — botao, link, foco */
    --azul-700: #1D4ED8;   /* active / pressed */
    --azul-900: #172554;   /* titulos, alto contraste */

    /* Escala cinza. */
    --branco: #FFFFFF;
    --cinza-50: #F8FAFC;   /* fundo da pagina */
    --cinza-100: #F1F5F9;
    --cinza-150: #EDF1F7;  /* divisor interno de card */
    --cinza-200: #E2E8F0;  /* divisor / borda */
    --cinza-300: #CBD5E1;  /* borda tracejada, disabled */
    /* Só borda, placeholder, :disabled e texto sobre fundo escuro: 2,56:1 sobre
       branco reprova no AA. Texto em superfície clara usa --cinza-500 (4,69:1). */
    --cinza-400: #94A3B8;
    --cinza-500: #64748B;  /* texto secundario */
    --cinza-600: #475569;
    --cinza-700: #334155;  /* label de campo */
    --cinza-800: #1E293B;  /* texto principal */
    --cinza-900: #0F172A;  /* chrome do realm admin */

    /* Semantica. Nunca derivada da marca do tenant. */
    --sucesso: #16A34A;
    --atencao: #D97706;
    --perigo: #DC2626;

    /* Marca do tenant. O TemaPublico sobrescreve so --cor-marca; as derivadas
       recalculam sozinhas. No painel e no admin cai no azul da plataforma. */
    --cor-marca: var(--azul-600);
    --cor-marca-hover: color-mix(in oklab, var(--cor-marca) 86%, #fff);
    --cor-marca-active: color-mix(in oklab, var(--cor-marca) 80%, #000);
    --cor-marca-suave: color-mix(in oklab, var(--cor-marca) 8%, #fff);
    --cor-marca-chip: color-mix(in oklab, var(--cor-marca) 16%, #fff);
    --cor-marca-escura: color-mix(in oklab, var(--cor-marca) 72%, var(--azul-900));

    /* 🔴 A tinta por CIMA da cor da marca. A cor e livre e o banco ja tem tenant
       com marca clara: `color: var(--branco)` fixo sobre ela e branco sobre
       claro. Quem decide e o CorDeMarca.EhClara (limiar 0,1791, nao 0,5), no
       servidor, e o TemaPublico sobrescreve este token. O default e --branco
       porque o padrao sem tenant e o azul da plataforma, que e escuro. */
    --tinta-sobre-marca: var(--branco);

    /* A marca quando ela e TINTA (link, botao de contorno) e nao superficie. No
       claro e a propria marca; no escuro sobe em direcao ao branco — ver §6.0. */
    --cor-marca-acento: var(--cor-marca);

    /* Familia do nome do estabelecimento. O TemaPublico sobrescreve com a
       escolha do lojista, sempre a partir de uma tabela estatica indexada por
       enum — nunca de texto do usuario. */
    --fonte-display: var(--fonte);

    /* Espaco: multiplos de 4px. */
    --esp-1: 4px;
    --esp-2: 8px;
    --esp-3: 12px;
    --esp-4: 16px;
    --esp-5: 20px;
    --esp-6: 28px;
    --esp-7: 36px;
    --esp-8: 48px;

    /* Raio: controles 10–12px, cards 14–16px. */
    --raio-controle: 10px;
    --raio-controle-lg: 12px;
    --raio-card: 14px;
    --raio-card-lg: 16px;
    --raio-pill: 999px;

    /* Sombra unica do sistema. */
    --sombra: 0 1px 3px rgba(15, 23, 42, .06), 0 8px 24px rgba(15, 23, 42, .04);
    --sombra-flutuante: 0 12px 32px rgba(15, 23, 42, .16);

    /* Tipografia. */
    --fonte: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    --fonte-mono: ui-monospace, Menlo, Consolas, monospace;
    --folga-caps: .06em;

    /* Alvo de toque: 44px no publico, 38px no painel. */
    --toque: 44px;
    --toque-painel: 38px;

    /* Larguras de leitura. */
    --largura-app: 1080px;
    --largura-form: 520px;
    --largura-texto: 560px;

    /* Movimento. Uma linguagem so, num eixo so: o fluxo publico anda na
       horizontal. Duracoes curtas — o cliente esta agendando, nao assistindo. */
    --mov-1: .16s;           /* micro: hover, active, opacidade */
    --mov-2: .24s;           /* selecao, trilho, estados */
    --mov-3: .34s;           /* colapso da bio, entrada do voltar */
    --mov-etapa: .32s;       /* entrada do conteudo ao trocar de etapa */
    /* Desaceleracao suave. A curva anterior (.16,.84,.44,1) gastava 85% do
       percurso nos primeiros 90ms: a animacao acabava antes de ser percebida. */
    --curva-entrada: cubic-bezier(.22, .61, .36, 1);
    --passo-cascata: 42ms;   /* atraso entre blocos que entram em sequencia */
    --desloca-etapa: 18px;   /* de quanto o conteudo chega deslocado */
}

/* --- 1.1 Superficie da pagina publica (tokens --pp-*) -------------------
   Uma camada so de tokens para tudo o que o cliente final ve. No :root eles
   valem EXATAMENTE o que a folha ja pintava, entao esta secao sozinha nao muda
   um pixel: quem troca e o seletor [data-tema-publico="escuro"] da §6.0.

   Por que uma camada nova em vez de remapear --branco e --cinza-*: aqueles
   tambem sao usados como tinta LITERAL sobre superficie colorida (o branco do
   .btn-danger, do .nr-toast), e remapea-los pintaria texto escuro sobre
   vermelho. A fronteira aqui e "superficie/tinta da pagina publica", nao "cor
   clara".
   ----------------------------------------------------------------------- */

:root {
    --pp-fundo: var(--cinza-50);
    --pp-superficie: var(--branco);
    --pp-superficie-2: var(--cinza-50);
    --pp-tinta: var(--cinza-800);
    --pp-tinta-forte: var(--azul-900);
    --pp-tinta-suave: var(--cinza-500);
    /* 🔴 A tinta suave quando a superficie embaixo dela e TINGIDA com a marca do
       tenant (--cor-marca-suave: o cartao .nr-opcao escolhido). Existe porque o
       --pp-tinta-suave foi medido contra --pp-superficie e --pp-fundo, que sao
       fixos, e a superficie do cartao escolhido NAO e: ela muda com o hex do
       lojista, e o numero muda junto.

       A tinta e DERIVADA do fundo, e nao escolhida — mesmo raciocinio do
       --cor-marca-acento da §6.0 e do AcentoEscurecido do TemaPublicoViewModel:
       `color-mix()` em direcao a um polo FIXO e monotono, entao o pior fundo que
       a formula consegue produzir e computavel de uma vez, e a tinta que passa
       nele passa em qualquer hex. No claro sao 8% da marca dentro de #fff, e o
       extremo e a marca #000000: MEDIDO no Chrome, o cartao computa #E4E4E4.

       Contra esse #E4E4E4, --cinza-500 dava 3,74:1 (reprova) e --cinza-600 da
       5,96:1. Continua um degrau abaixo do nome do cartao (--pp-tinta, 14,24:1
       ali), que e o que a hierarquia pede.

       ⚠️ NAO e o --tinta-sobre-marca do CorDeMarca.EhClara, e nao da pra
       reaproveita-lo aqui: aquele responde "que tinta vai por cima de 100% da
       marca". Com marca escura ele vale var(--branco) — branco sobre um cartao
       #EDF3FF, 1,06:1. Seria pior que o defeito que este token conserta. */
    --pp-tinta-suave-na-marca: var(--cinza-600);
    --pp-borda: var(--cinza-200);
    /* A tinta da textura do fundo. Fraca de proposito e FIXA aqui: quem escolhe a
       textura escolhe o desenho, nunca a forca dela. */
    --pp-textura: rgb(15 23 42 / .045);
    --pp-borda-forte: var(--cinza-300);
    --pp-divisor: var(--cinza-150);
    /* Verde do "Aberto". Era #166534 hard-coded e reprova em AA no escuro. */
    --pp-aberto: #166534;
    /* Anel/fundo da logo — o "passe-partout" que a separa da capa. */
    --pp-anel-logo: var(--branco);
}

/* --- 2. Base ------------------------------------------------------------ */

body {
    font-family: var(--fonte);
    color: var(--cinza-800);
    -webkit-font-smoothing: antialiased;
}

a {
    color: var(--cor-marca-acento);
}

a:hover {
    color: var(--cor-marca-active);
}

/* Foco sempre visivel, na cor da marca. */
*:focus-visible {
    outline: 2px solid var(--cor-marca);
    outline-offset: 2px;
    border-radius: 4px;
}

@keyframes nr-shimmer {
    0% { background-position: 100% 0; }
    100% { background-position: -100% 0; }
}

@keyframes nr-girar {
    to { transform: rotate(360deg); }
}

@keyframes nr-subir {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: none; }
}

/* Entrada do fluxo em etapas. O conteudo chega pelo lado para onde o cliente
   esta indo: pela direita quando avanca, pela esquerda quando volta. A carga
   inicial sobe, porque nao veio de etapa nenhuma. */
@keyframes fl-entra-frente {
    from { opacity: 0; transform: translate3d(var(--desloca-etapa), 0, 0); }
    to { opacity: 1; transform: none; }
}

@keyframes fl-entra-tras {
    from { opacity: 0; transform: translate3d(calc(var(--desloca-etapa) * -1), 0, 0); }
    to { opacity: 1; transform: none; }
}

@keyframes fl-entra-carga {
    from { opacity: 0; transform: translate3d(0, 14px, 0); }
    to { opacity: 1; transform: none; }
}

/* Logo do estabelecimento assentando sobre a capa. */
@keyframes fl-assentar {
    from { opacity: 0; transform: scale(1.06); }
    to { opacity: 1; transform: none; }
}

/* Valor que acabou de mudar. */
@keyframes fl-trocar {
    from { opacity: 0; transform: translate3d(0, -5px, 0); }
    to { opacity: 1; transform: none; }
}

/* --- 3. Override do Bootstrap ------------------------------------------
   Materializa o design nas classes que as views ja usam.
   ----------------------------------------------------------------------- */

.btn {
    --bs-btn-focus-box-shadow: none;
    min-height: 42px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--esp-2);
    padding: 0 18px;
    border-radius: var(--raio-controle);
    font-size: .88rem;
    font-weight: 600;
    line-height: 1;
}

.btn-sm {
    min-height: 36px;
    padding: 0 13px;
    font-size: .8rem;
    border-radius: 8px;
}

.btn-lg {
    min-height: var(--toque);
    padding: 0 22px;
    font-size: .95rem;
    border-radius: var(--raio-controle-lg);
}

/* 🔴 A tinta sai de --tinta-sobre-marca, e nao de --branco: com marca clara o
   branco fixo dava branco sobre claro na pagina publica. Sao TRES ocorrencias
   que trocam (repouso, hover e active) — a quarta, do :disabled logo abaixo,
   pinta sobre --azul-300 e NAO pode trocar: aquele fundo e da plataforma, nao
   do tenant, e continua exigindo branco. */
.btn-primary {
    background-color: var(--cor-marca);
    border-color: var(--cor-marca);
    color: var(--tinta-sobre-marca);
}

.btn-primary:hover,
.btn-primary:focus {
    background-color: var(--cor-marca-hover);
    border-color: var(--cor-marca-hover);
    color: var(--tinta-sobre-marca);
}

.btn-primary:active {
    background-color: var(--cor-marca-active);
    border-color: var(--cor-marca-active);
    color: var(--tinta-sobre-marca);
}

.btn-primary:disabled,
.btn-primary.disabled {
    background-color: var(--azul-300);
    border-color: var(--azul-300);
    color: var(--branco);
    opacity: 1;
}

.btn-outline-primary {
    border: 1.5px solid var(--cor-marca-acento);
    background-color: var(--pp-superficie);
    color: var(--cor-marca-acento);
}

.btn-outline-primary:hover,
.btn-outline-primary:focus {
    background-color: var(--cor-marca-suave);
    border-color: var(--cor-marca-acento);
    color: var(--cor-marca-acento);
}

/* Neutro — a acao que nao e primaria nem destrutiva. */
.btn-outline-secondary {
    border: 1px solid var(--cinza-200);
    background-color: var(--branco);
    color: var(--cinza-600);
}

.btn-outline-secondary:hover,
.btn-outline-secondary:focus {
    background-color: var(--cinza-50);
    border-color: var(--cinza-400);
    color: var(--cinza-800);
}

.btn-danger {
    background-color: var(--perigo);
    border-color: var(--perigo);
    color: var(--branco);
}

.btn-danger:hover,
.btn-danger:focus {
    background-color: #B91C1C;
    border-color: #B91C1C;
    color: var(--branco);
}

/* Destrutivo em repouso: contorno, nao bloco vermelho. */
.btn-outline-danger {
    border: 1.5px solid #FECACA;
    background-color: var(--branco);
    color: var(--perigo);
}

.btn-outline-danger:hover,
.btn-outline-danger:focus {
    background-color: #FEF2F2;
    border-color: var(--perigo);
    color: var(--perigo);
}

.btn-outline-success {
    border: 1.5px solid #BBF7D0;
    background-color: var(--branco);
    color: #166534;
}

.btn-outline-success:hover,
.btn-outline-success:focus {
    background-color: #F0FDF4;
    border-color: var(--sucesso);
    color: #166534;
}

.btn-outline-warning {
    border: 1.5px solid #FDE68A;
    background-color: var(--branco);
    color: #92400E;
}

.btn-outline-warning:hover,
.btn-outline-warning:focus {
    background-color: #FFFBEB;
    border-color: var(--atencao);
    color: #92400E;
}

.btn-dark {
    background-color: var(--azul-900);
    border-color: var(--azul-900);
    color: var(--branco);
}

.btn-dark:hover,
.btn-dark:focus {
    background-color: #1E3A8A;
    border-color: #1E3A8A;
    color: var(--branco);
}

.btn-outline-dark {
    border: 1.5px solid var(--cinza-200);
    background-color: var(--branco);
    color: var(--azul-900);
}

.btn-outline-dark:hover,
.btn-outline-dark:focus {
    background-color: var(--cinza-50);
    border-color: var(--azul-900);
    color: var(--azul-900);
}

/* 🔴 `--cor-marca-acento`, e NAO `--cor-marca` crua — a marca como TINTA sempre passa pelo acento.
   Medido no Bloco 58: os botoes "Alterar" do resumo do /agendar saiam em 2,51 no tema escuro
   (minimo AA 4,5). Ninguem tinha visto porque a etapa 5 nasce `hidden`, e o coletor de contraste
   pula `display: none` — o defeito so aparecia para quem chegasse na confirmacao, que e o passo
   anterior a converter. E a MESMA doutrina ja escrita na §6.0 desta folha: a marca `#000000` que
   existe no banco viraria texto invisivel no escuro, e o acento existe exatamente para isso.
   No claro `--cor-marca-acento` e o acento que o servidor calcula para fundo claro. */
.btn-link {
    min-height: auto;
    padding: 4px;
    color: var(--cor-marca-acento);
    font-weight: 600;
    text-decoration: none;
}

/* --- Formularios: tinta e superficie em --pp-*, NUNCA em --cinza-* ------
   🔴 ESTE BLOCO INTEIRO FOI REPINTADO NO BLOCO 58, E O DEFEITO ESTAVA EM PRODUCAO.
   Os rotulos de `/carteirinha/entrar` no tema ESCURO saiam em rgb(51,65,85) sobre
   rgb(15,23,42): contraste 1,57 contra o minimo AA de 4,5 — texto quase invisivel,
   e o dono viu no celular dele. A causa nao era da carteirinha: era daqui. A
   familia `--cinza-*` e a paleta CRUA e nao remapeia no tema escuro publico; quem
   remapeia e a familia `--pp-*` da §1.1 (e a §6.0 troca os valores dela). O mesmo
   defeito alcancava /meus-dados e /agendar, que usam as mesmas classes.

   ⚠️ O PAINEL NAO E ALCANCADO, e isso e medido e nao esperado: o painel.css
   sobrescreve `.form-label` e `.form-control` inteiros sob `:is(.pn-shell, .ad-body)`,
   com especificidade maior e folha carregada depois.

   ⚠️ No tema CLARO a troca e quase um no-op por construcao: --pp-tinta-suave E
   --cinza-500, --pp-superficie E --branco, --pp-borda E --cinza-200 (§1.1). O
   unico deslocamento real e o rotulo, que fica MAIS escuro — logo, mais contraste.

   🔴 O FUNDO DO CAMPO E OBRIGATORIO, nao enfeite. So trocar a tinta para --pp-tinta
   deixaria texto quase branco sobre o branco que o Bootstrap pinta em .form-control
   (--bs-body-bg): trocaria um contraste de 1,57 por um de 1,1. Conserto pela metade
   e pior que nenhum, porque parece feito.
   ----------------------------------------------------------------------- */

.form-control,
.form-select {
    min-height: var(--toque);
    padding: 0 13px;
    border: 1.5px solid var(--pp-borda);
    border-radius: var(--raio-controle);
    font-size: .92rem;
    background-color: var(--pp-superficie);
    color: var(--pp-tinta);
}

/* textarea nao pode centralizar verticalmente como os campos de uma linha. */
textarea.form-control {
    padding: 12px 13px;
    line-height: 1.5;
}

.form-control::placeholder {
    color: var(--pp-tinta-suave);
}

.form-control:focus,
.form-select:focus {
    border-color: var(--cor-marca);
    box-shadow: none;
}

.form-control:disabled,
.form-select:disabled {
    background-color: var(--pp-superficie-2);
    color: var(--pp-tinta-suave);
}

/* O rosa de erro e claro por natureza; sobre ele a tinta tem que ser a ESCURA, e
   nao a --pp-tinta (que vira quase branca no escuro). Fixar as duas juntas e o que
   mantem o par legivel nos dois temas sem um override por tema. */
.form-control.is-invalid,
.form-select.is-invalid {
    border-color: var(--perigo);
    background-color: #FEF2F2;
    color: var(--cinza-800);
}

.form-control-sm,
.form-select-sm {
    min-height: var(--toque-painel);
    padding: 0 12px;
    font-size: .85rem;
    border-radius: 9px;
}

/* 🔴 O RÓTULO É O DEFEITO QUE FOI PARA PRODUÇÃO — 1,57 no tema escuro. Ver o bloco
   longo acima do `.form-control`. `--pp-tinta`, jamais `--cinza-700`. */
.form-label {
    margin-bottom: 6px;
    font-size: .8rem;
    font-weight: 600;
    color: var(--pp-tinta);
}

.form-text {
    font-size: .76rem;
    color: var(--pp-tinta-suave);
}

.form-check-input {
    border: 2px solid var(--pp-borda-forte);
}

.form-check-input:checked {
    background-color: var(--cor-marca);
    border-color: var(--cor-marca);
}

.form-check-input:focus {
    border-color: var(--cor-marca);
    box-shadow: none;
}

.card {
    background: var(--branco);
    border: 1px solid var(--cinza-200);
    border-radius: var(--raio-card);
    box-shadow: var(--sombra);
}

.card-title {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--azul-900);
}

/* Alerts: fundo suave, borda no mesmo tom, texto escuro legivel. */
.alert {
    border-radius: 11px;
    border-width: 1px;
    padding: 11px 14px;
    font-size: .84rem;
    font-weight: 500;
}

.alert-success {
    background-color: #F0FDF4;
    border-color: #BBF7D0;
    color: #166534;
}

.alert-warning {
    background-color: #FFFBEB;
    border-color: #FDE68A;
    color: #92400E;
}

/* 🔴 A TINTA NAO E `--perigo`, E ISSO E MEDIDO: #DC2626 sobre #FEF2F2 da 4,41,
   contra o minimo AA de 4,5. Reprovava em TODA tela publica que mostra recusa
   — /carteirinha/entrar e /carteirinha/criar estao em producao assim — e nos
   DOIS temas, porque o alerta e claro nos dois: nao e defeito do tema escuro.

   ⚠️ O que denuncia ser descuido e nao escolha: os tres alertas irmaos usam
   tinta 700/800 (#166534, #92400E, #1D4ED8) e passam com folga (6,8 / 6,8 /
   6,2). So o danger herdou o token de 600, que existe para ser FUNDO com texto
   branco por cima (.btn-danger), nao tinta sobre superficie clara.

   #B91C1C mede 5,91 — mesma familia, mesma leitura de "vermelho de erro".
   O token `--perigo` fica intocado de proposito: ele e fundo em outros lugares,
   e mexer nele para consertar uma tinta teria raio de alcance muito maior que o
   defeito. */
.alert-danger {
    background-color: #FEF2F2;
    border-color: #FECACA;
    color: #B91C1C;
}

.alert-info {
    background-color: var(--azul-50);
    border-color: var(--azul-100);
    color: var(--azul-700);
}

.table {
    --bs-table-bg: transparent;
    color: var(--cinza-800);
}

.table > thead th {
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--folga-caps);
    color: var(--cinza-500);
    border-bottom-color: var(--cinza-150);
}

.table > tbody td {
    border-bottom-color: var(--cinza-100);
}

/* --- 4. Componentes ---------------------------------------------------- */

.nr-titulo-pagina {
    margin: 0;
    font-size: 1.45rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--pp-tinta-forte);
}

.nr-titulo-secao {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--pp-tinta-forte);
}

.nr-meta {
    font-size: .8rem;
    font-weight: 500;
    color: var(--pp-tinta-suave);
}

/* Rotulo de grupo em maiuscula. */
.nr-eyebrow {
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: var(--folga-caps);
    text-transform: uppercase;
    color: var(--pp-tinta-suave);
}

.nr-mono {
    font-family: var(--fonte-mono);
    font-size: .85rem;
}

.nr-card {
    background: var(--pp-superficie);
    border: 1px solid var(--pp-borda);
    border-radius: var(--raio-card);
    box-shadow: var(--sombra);
    padding: var(--esp-5);
}

/* Avatar de iniciais — profissional, estabelecimento, usuario. */
.nr-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: var(--azul-50);
    color: var(--azul-700);
    font-size: .8rem;
    font-weight: 700;
}

/* Quadrado arredondado: identidade do estabelecimento. */
.nr-avatar--quadrado {
    border-radius: var(--raio-controle);
}

/* Badge de status: ponto + texto, nunca so cor (§acessibilidade). */
.nr-badge {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 11px;
    border-radius: var(--raio-pill);
    font-size: .74rem;
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
}

.nr-badge::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

.nr-badge--pendente { background: #FEF3C7; color: #92400E; }
.nr-badge--confirmado { background: var(--azul-100); color: var(--azul-700); }
.nr-badge--concluido { background: #DCFCE7; color: #166534; }
.nr-badge--cancelado { background: var(--cinza-100); color: var(--pp-tinta-suave); }
.nr-badge--faltou { background: #FEE2E2; color: #B91C1C; }
.nr-badge--ativo { background: #DCFCE7; color: #166534; }
.nr-badge--inativo { background: var(--cinza-100); color: var(--pp-tinta-suave); }

/* Trilho da timeline da agenda — a cor cheia do status. */
.nr-trilho--pendente { background: #F59E0B; }
.nr-trilho--confirmado { background: var(--azul-600); }
.nr-trilho--concluido { background: var(--sucesso); }
.nr-trilho--cancelado { background: var(--pp-borda-forte); }
.nr-trilho--faltou { background: #FCA5A5; }

/* Chip de horario livre. Alvo de 44px: e a decisao final do cliente. */
.nr-chip-hora {
    min-width: 72px;
    min-height: var(--toque);
    padding: 0 var(--esp-3);
    border: 1.5px solid var(--pp-borda);
    border-radius: var(--raio-controle);
    background: var(--pp-superficie);
    color: var(--pp-tinta);
    font-size: .92rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color var(--mov-1), background var(--mov-1),
                color var(--mov-1), box-shadow var(--mov-1), transform var(--mov-1);
}

.nr-chip-hora:hover {
    border-color: var(--cor-marca);
}

/* Toque com resposta: o chip afunda sob o dedo. */
.nr-chip-hora:active {
    transform: scale(.96);
}

/* Escolher o horario e a decisao final do cliente — e a unica coisa da tela
   que sai do plano do papel. */
.nr-chip-hora[aria-pressed="true"] {
    background: var(--cor-marca);
    border-color: var(--cor-marca);
    color: var(--tinta-sobre-marca);
    box-shadow: 0 4px 12px color-mix(in oklab, var(--cor-marca) 30%, transparent);
}

/* Cartao selecionavel: servico, profissional, dia. */
.nr-opcao {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    width: 100%;
    text-align: left;
    padding: var(--esp-3) var(--esp-4);
    border: 1.5px solid var(--pp-borda);
    border-radius: var(--raio-controle-lg);
    background: var(--pp-superficie);
    cursor: pointer;
    transition: border-color var(--mov-1), background var(--mov-1),
                box-shadow var(--mov-1), transform var(--mov-1);
}

/* Elevacao no hover, afundada no toque: o cartao responde antes de mudar de
   estado, entao o cliente sabe que ele e clicavel. */
.nr-opcao:hover {
    border-color: var(--cor-marca);
    box-shadow: 0 2px 10px rgba(15, 23, 42, .07);
}

.nr-opcao:active {
    transform: scale(.98);
}

.nr-opcao[aria-pressed="true"] {
    border-color: var(--cor-marca);
    background: var(--cor-marca-suave);
}

/* Estado vazio: diz o porque e oferece o proximo passo. */
.nr-vazio {
    padding: var(--esp-6) var(--esp-5);
    border: 1.5px dashed var(--pp-borda-forte);
    border-radius: var(--raio-controle-lg);
    background: var(--pp-superficie-2);
    text-align: center;
}

.nr-vazio-titulo {
    margin: 0 0 3px;
    font-size: .95rem;
    font-weight: 600;
    color: var(--pp-tinta);
}

.nr-vazio-texto {
    margin: 0;
    font-size: .84rem;
    color: var(--pp-tinta-suave);
}

/* Skeleton — qualquer carga acima de ~200ms. */
.nr-skeleton {
    display: block;
    border-radius: 6px;
    background: linear-gradient(90deg, var(--pp-divisor) 25%, var(--pp-borda) 50%, var(--pp-divisor) 75%);
    background-size: 200% 100%;
    animation: nr-shimmer 1.2s linear infinite;
}

.nr-spinner {
    display: inline-block;
    width: 15px;
    height: 15px;
    border: 2px solid color-mix(in oklab, currentColor 35%, transparent);
    border-top-color: currentColor;
    border-radius: 50%;
    animation: nr-girar .7s linear infinite;
}

/* Toast — feedback de acao concluida. */
.nr-toast {
    background: var(--azul-900);
    color: var(--branco);
    border-radius: var(--raio-controle);
    padding: 11px 18px;
    font-size: .88rem;
    font-weight: 500;
    box-shadow: 0 8px 24px rgba(15, 23, 42, .25);
    animation: nr-subir .25s ease;
}

.nr-emoji-grande {
    font-size: 4rem;
    line-height: 1;
}

/* Depois dos componentes, para vencer por ordem em vez de por !important. */
@media (prefers-reduced-motion: reduce) {
    .nr-skeleton,
    .nr-toast {
        animation: none;
    }

    /* O spinner e o unico sinal de que algo esta em curso, entao continua
       girando — so que devagar. */
    .nr-spinner {
        animation-duration: 2s;
    }
}

/* --- 5. Landing (apex) -------------------------------------------------- */

.lp-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    max-width: var(--largura-app);
    margin: 0 auto;
    padding: var(--esp-4) var(--esp-5);
}

.lp-brand {
    font-size: 1.3rem;
    font-weight: 800;
    letter-spacing: -.02em;
    color: var(--azul-900);
}

.lp-wrap {
    max-width: var(--largura-app);
    margin: 0 auto;
    padding: 0 var(--esp-5);
}

.lp-footer {
    text-align: center;
    color: var(--cinza-500);
    padding: var(--esp-7) var(--esp-4);
    font-size: .9rem;
}

.lp-hero {
    text-align: center;
    padding: var(--esp-8) var(--esp-5);
    max-width: 760px;
    margin: 0 auto;
}

.lp-hero h1 {
    font-size: 2.5rem;
    font-weight: 800;
    letter-spacing: -.03em;
    line-height: 1.1;
    color: var(--azul-900);
}

.lp-hero p {
    color: var(--cinza-500);
    font-size: 1.15rem;
    margin: var(--esp-4) auto var(--esp-6);
    max-width: var(--largura-texto);
}

.lp-features {
    max-width: var(--largura-app);
    margin: 0 auto;
    padding: var(--esp-4) var(--esp-5) var(--esp-8);
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--esp-5);
}

.lp-feature {
    background: var(--branco);
    border: 1px solid var(--cinza-200);
    border-radius: var(--raio-card);
    padding: var(--esp-5);
}

.lp-feature .ico {
    font-size: 1.8rem;
}

.lp-feature h3 {
    font-size: 1.05rem;
    font-weight: 700;
    margin: var(--esp-2) 0 var(--esp-1);
    color: var(--azul-900);
}

.lp-feature p {
    color: var(--cinza-500);
    font-size: .95rem;
    margin: 0;
}

.lp-pricing {
    background: var(--cinza-50);
    padding: var(--esp-8) var(--esp-5);
}

.lp-pricing h2 {
    text-align: center;
    font-weight: 800;
    letter-spacing: -.02em;
    margin-bottom: var(--esp-1);
    color: var(--azul-900);
}

.lp-pricing .sub {
    text-align: center;
    color: var(--cinza-500);
    margin-bottom: var(--esp-7);
}

.lp-plans {
    max-width: 1000px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--esp-5);
    align-items: start;
}

.lp-plan {
    background: var(--branco);
    border: 1px solid var(--cinza-200);
    border-radius: var(--raio-card-lg);
    padding: var(--esp-6);
    position: relative;
}

.lp-plan--popular {
    border-color: var(--azul-600);
    box-shadow: 0 8px 30px rgba(37, 99, 235, .12);
}

.lp-badge {
    position: absolute;
    top: -12px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--azul-600);
    color: var(--branco);
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    padding: var(--esp-1) var(--esp-3);
    border-radius: var(--raio-pill);
}

.lp-plan h3 {
    font-weight: 800;
    margin-bottom: var(--esp-1);
    color: var(--azul-900);
}

.lp-price {
    font-size: 2rem;
    font-weight: 800;
    color: var(--azul-900);
}

.lp-price small {
    font-size: .95rem;
    font-weight: 500;
    color: var(--cinza-500);
}

.lp-plan ul {
    list-style: none;
    padding: 0;
    margin: var(--esp-4) 0;
}

.lp-plan li {
    padding: var(--esp-1) 0;
    color: var(--cinza-600);
    display: flex;
    gap: var(--esp-2);
}

.lp-plan li::before {
    content: "\2713";
    color: var(--sucesso);
    font-weight: 700;
}

/* --- 6.0 Tema ESCURO da pagina publica ---------------------------------
   Escolha do LOJISTA (recurso Premium), servida a todo anonimo — nao e o
   cookie `nr-tema` do painel. Por isso o atributo e `data-tema-publico`: o
   `data-tema` ja tem dono e o painel.css casa com ele em seletor sem prefixo.

   O escopo e o elemento raiz, e so o _LayoutPublico o escreve — o _LayoutAdmin
   e o _LayoutSimples carregam esta mesma folha e continuam claros.

   🔴 O PROBLEMA QUE O ESCURO CRIA E QUE NINGUEM ANTECIPA: cor de marca como
   TEXTO. `a { color: var(--cor-marca) }` com a marca #000000 que o banco ja
   tem seria link invisivel no fundo escuro. A saida nao precisa de C#: aqui a
   marca vira --cor-marca-acento misturada com branco, e misturar em direcao ao
   branco SO AUMENTA a luminancia — entao o pior caso e computavel de uma vez.
   MEDIDO no Chrome, e nao estimado: a marca #000000 computa para
   `oklab(0.65 0 0)`, ou seja #8F8F8F — 5,03:1 sobre --pp-superficie e 5,52:1
   sobre --pp-fundo. Passa em AA, e se o pior caso passa, qualquer hex passa.
   (O medir-contraste.js precisou aprender a ler `oklab()` para enxergar isto:
   ate entao ele PULAVA o link em silencio.)

   A marca continua sendo --cor-marca onde ela e SUPERFICIE (fundo de botao):
   la a legibilidade e do --tinta-sobre-marca, que o servidor calcula.
   ----------------------------------------------------------------------- */

[data-tema-publico="escuro"] {
    color-scheme: dark;

    --pp-fundo: #0F172A;
    --pp-superficie: #172033;
    --pp-superficie-2: #1E2A42;
    --pp-tinta: #E8EDF7;
    --pp-tinta-forte: #F8FAFC;
    --pp-tinta-suave: #A9B4C8;
    /* Mesma regra do :root, outro polo: aqui a mistura vai em direcao ao
       --pp-fundo (#0F172A) a 22%, entao o pior fundo e o CLARO — a marca
       #FFFFFF, que MEDIDA no Chrome da #3B4354. A --pp-tinta-suave passa nele
       com 4,75:1, entao no escuro a tinta nao muda: so quem estava quebrado
       muda de cor. Ainda assim o token existe nos dois temas, senao o valor do
       :root (uma tinta ESCURA) desceria pro cartao escuro. */
    --pp-tinta-suave-na-marca: var(--pp-tinta-suave);
    --pp-borda: #2C3A57;
    /* No escuro a textura CLAREIA — a mesma tinta escura do tema claro seria
       invisivel sobre #0F172A, e a escolha do lojista nao produziria nada. */
    --pp-textura: rgb(255 255 255 / .04);
    --pp-borda-forte: #3D4E70;
    --pp-divisor: #232E45;
    --pp-aberto: #4ADE80;
    --pp-anel-logo: #22304C;

    --cor-marca-acento: color-mix(in oklab, var(--cor-marca) 35%, #fff);
    /* As derivadas "suaves" nasceram misturando com BRANCO — no escuro elas
       viravam superficie quase branca com tinta clara por cima. Aqui elas
       misturam com o fundo. */
    --cor-marca-suave: color-mix(in oklab, var(--cor-marca) 22%, var(--pp-fundo));
    --cor-marca-chip: color-mix(in oklab, var(--cor-marca) 30%, var(--pp-fundo));
    --cor-marca-escura: var(--cor-marca-acento);
}

[data-tema-publico="escuro"] body {
    color: var(--pp-tinta);
}

[data-tema-publico="escuro"] a:hover {
    color: color-mix(in oklab, var(--cor-marca-acento) 80%, #fff);
}

/* Botao de marca sobre fundo escuro: com a marca #000000 o bloco desapareceria
   no fundo (1,06:1 de contraste de forma). O anel nao depende da marca, entao
   o botao continua sendo um botao para qualquer hex. */
[data-tema-publico="escuro"] .btn-primary {
    box-shadow: 0 0 0 1px color-mix(in oklab, var(--pp-tinta) 30%, transparent);
}

/* A sombra do sistema foi desenhada para papel branco: sobre fundo escuro ela
   nao aparece, e o cartao perde a borda. */
[data-tema-publico="escuro"] .nr-card,
[data-tema-publico="escuro"] .form-card,
[data-tema-publico="escuro"] .fl-resumo,
[data-tema-publico="escuro"] .hm-info {
    box-shadow: none;
}

/* A SETA do <select> e um SVG embutido pelo Bootstrap com o traco fixo em #343a40:
   sobre o campo escuro (--pp-superficie) ela pratica­mente some. Aqui ela e
   redesenhada com traco claro.
   ⚠️ Nao e hex de MARCA — e a tinta de um icone de interface, e a restricao do
   projeto ("nenhum hex de marca hard-coded") e sobre a paleta do lojista. Um
   `var()` nao atravessa um data URI, entao o valor tem de ser literal.
   O <option> aberto ja vem escuro pelo `color-scheme: dark` do bloco acima. */
[data-tema-publico="escuro"] .form-select {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23A9B4C8' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

/* --- 6. Publico (pagina do estabelecimento) ---------------------------- */

/* Veu na cor do tenant, so no topo e so no que o cliente final ve. E o que
   faz a pagina parecer da barbearia desde o primeiro pixel, sem virar banho
   de cor: sai de color-mix sobre --cor-marca, entao acompanha o tema. */
.publico-body {
    background-color: var(--pp-fundo);
    background-image: radial-gradient(
        130% 62% at 50% -12%,
        color-mix(in oklab, var(--cor-marca) 13%, transparent),
        transparent 68%);
    background-repeat: no-repeat;
    background-size: 100% 460px;
}

.publico-wrap {
    max-width: var(--largura-form);
    margin: 0 auto;
    padding: var(--esp-5) var(--esp-4) var(--esp-8);
}

.form-card {
    background: var(--pp-superficie);
    border: 1px solid var(--pp-borda);
    border-radius: var(--raio-card);
    box-shadow: var(--sombra);
    padding: var(--esp-5);
}




/* Sobrepoe metade do logo na capa. */

.estab-nome {
    text-align: center;
    /* A familia escolhida pelo lojista, ou a do sistema quando ele nao escolheu.
       So o NOME veste a fonte display: corpo de texto em Anton nao se le. */
    font-family: var(--fonte-display);
    font-size: 1.55rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--pp-tinta-forte);
    margin: var(--esp-3) 0 var(--esp-1);
}

.estab-bio {
    text-align: center;
    color: var(--pp-tinta-suave);
    font-size: .95rem;
    line-height: 1.5;
    margin: 0 auto var(--esp-1);
    max-width: 420px;
}

.estab-sub {
    text-align: center;
    margin-bottom: var(--esp-4);
}

.servicos {
    border-top: 1px solid var(--pp-divisor);
    margin-top: var(--esp-1);
}

.servico-item {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    padding: var(--esp-2) var(--esp-1);
    border-bottom: 1px solid var(--pp-divisor);
    cursor: pointer;
    margin: 0;
}

.servico-nome {
    font-weight: 600;
}

.servico-meta {
    margin-left: auto;
    color: var(--pp-tinta-suave);
    font-size: .88rem;
    white-space: nowrap;
}

.btn-confirmar {
    min-height: 48px;
    border-radius: var(--raio-controle-lg);
    font-size: .95rem;
    font-weight: 600;
}

/* Cor de marca do WhatsApp — não do tema do tenant, de propósito: o botão precisa ser
   reconhecível como "isto abre o WhatsApp" antes mesmo de ler o rótulo. */
.btn-whatsapp {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    background: #25D366;
    border: 1px solid #25D366;
    color: #fff;
}

.btn-whatsapp:hover,
.btn-whatsapp:focus-visible {
    background: #1EBE5A;
    border-color: #1EBE5A;
    color: #fff;
}

/* --- 6.1 Fluxo de agendamento em etapas -------------------------------
   O input nativo continua no DOM dentro do .nr-opcao (sem JS o formulario
   funciona inteiro); o cartao so veste o controle.
   ----------------------------------------------------------------------- */

/* Input real: invisivel mas focavel, para teclado e leitor de tela. */
.nr-opcao input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    margin: 0;
}

/* Anel na cor do tenant: le como escolhido mesmo de relance, sem depender
   so da mudanca de fundo. */
.nr-opcao:has(input:checked) {
    border-color: var(--cor-marca);
    background: var(--cor-marca-suave);
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--cor-marca) 14%, transparent);
}

.nr-opcao:has(input:focus-visible) {
    outline: 2px solid var(--cor-marca);
    outline-offset: 2px;
}

.nr-opcao-nome {
    display: block;
    font-size: .95rem;
    font-weight: 600;
    color: var(--pp-tinta);
}

.nr-opcao-meta {
    display: block;
    margin-top: 2px;
    font-size: .8rem;
    font-weight: 500;
    color: var(--pp-tinta-suave);
}

/* 🔴 O cartao ESCOLHIDO troca de superficie (--cor-marca-suave), entao a tinta
   suave dele tem de ser medida contra a superficie NOVA — ver o
   --pp-tinta-suave-na-marca na §1.1. Medido em 23/08/2026 no /meus-dados, tema
   claro, onde o primeiro cartao ja nasce marcado: marca #2563EB dava 4,28:1,
   #E11D48 4,30, #8A8A8A 4,36 e #000000 3,74 — quatro de seis hexes reprovando
   em AA, e o numero mudando com a barbearia. O nome do cartao nao entra aqui
   porque usa --pp-tinta, que passa em qualquer um deles.

   Os dois seletores: `:has(input:checked)` e o cartao de radio/checkbox
   (/meus-dados, /agendar) e `[aria-pressed]` e o botao-cartao — os dois pintam
   o MESMO --cor-marca-suave logo acima, e deixar um de fora seria consertar
   metade das telas. */
.nr-opcao:has(input:checked) .nr-opcao-meta,
.nr-opcao[aria-pressed="true"] .nr-opcao-meta {
    color: var(--pp-tinta-suave-na-marca);
}

/* Marcador do cartao: quadrado para servico (multipla), circulo para
   profissional (unica) — a forma diz o tipo de escolha. */
.nr-marcador {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border: 2px solid var(--pp-borda-forte);
    border-radius: 7px;
    transition: background .12s, border-color .12s;
}

.nr-marcador--circulo {
    width: 20px;
    height: 20px;
    border-radius: 50%;
}

.nr-marcador svg,
.nr-marcador span {
    opacity: 0;
    transition: opacity var(--mov-1);
}

/* Entrada do "certo": cresce e aparece junto com o traco sendo desenhado. */
.nr-marcador svg {
    transform: scale(.7);
    transition: opacity var(--mov-1), transform var(--mov-2) var(--curva-entrada);
}

.nr-opcao:has(input:checked) .nr-marcador svg {
    transform: none;
}

/* O "certo" e riscado, nao ligado: o traco desenha da esquerda para a direita
   assim que o cartao e marcado. Comprimento do polyline ~11,7 unidades. */
.nr-marcador svg polyline {
    stroke-dasharray: 12;
    stroke-dashoffset: 12;
    transition: stroke-dashoffset var(--mov-2) var(--curva-entrada) 40ms;
}

.nr-opcao:has(input:checked) .nr-marcador svg polyline {
    stroke-dashoffset: 0;
}

.nr-opcao:has(input:checked) .nr-marcador {
    border-color: var(--cor-marca);
    background: var(--cor-marca);
}

.nr-opcao:has(input:checked) .nr-marcador--circulo {
    background: var(--pp-superficie);
}

.nr-opcao:has(input:checked) .nr-marcador svg,
.nr-opcao:has(input:checked) .nr-marcador span {
    opacity: 1;
}

/* Ponto interno do marcador circular. Cresce ao ser escolhido — escolha
   unica merece um gesto diferente da multipla. */
.nr-marcador--circulo span {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--cor-marca);
    transform: scale(.3);
    transition: opacity var(--mov-1), transform var(--mov-2) var(--curva-entrada);
}

.nr-opcao:has(input:checked) .nr-marcador--circulo span {
    transform: none;
}

/* --- 6.1.0 Header de marca do fluxo ------------------------------------
   Um header IDENTICO nas cinco etapas: a marca e o unico ponto de referencia
   fixo do fluxo, e era mover esse ponto a cada etapa que desorientava. Nada
   encolhe, nada troca de eixo, nada se realinha.

   So a bio recolhe da etapa 2 em diante, e ela fica ABAIXO de tudo: nada acima
   dela se desloca.

   🔴 A FACHADA NAO MORA MAIS AQUI, e a mudanca e o conserto de uma divergencia
   medida. Este bloco tinha desenho PROPRIO — `.mk-capa` de `height: 150px` com
   raio nos quatro cantos, `.mk-barra` empilhando, `.mk-logo` de 84px pendurada
   na emenda por `margin-top: -42px` e `.mk-nome` sobre o fundo da pagina — e a
   home, repaginada no Bloco 48, tinha outro: proporcao 4/3 com teto de 340px,
   sangria ate a borda da janela, dois degrades com o pior caso em 6,74:1 e o
   nome SOBRE a foto. A mesma barbearia, duas caras em duas telas seguidas.

   As seis regras foram APAGADAS, e a remocao e o conserto: quem desenha a
   fachada nas duas telas agora e `.hm-fachada` (secao "Bloco 48"), consumida
   pelo partial `_FachadaPublica.cshtml`. Deixa-las aqui como orfas seria pior
   que churn — na proxima repaginacao alguem editaria a copia morta.

   O que sobrou e o que e SO do fluxo: a bio que recolhe e o voltar que entra.
   O `.mk--com-capa` sumiu junto: ele so existia para pendurar a `.mk-logo`.
   ----------------------------------------------------------------------- */

.mk {
    margin-bottom: var(--esp-3);
}

.mk-bio {
    /* --esp-4, o MESMO respiro que a `.hm-bio` da home usa: a fachada agora e a mesma nas duas
       telas, e com capa o nome termina sobre a foto — a bio colada nela lia como legenda. Editado
       no lugar, e nao sobrescrito no fim da folha, de proposito: `.mk--apos-abertura .mk-bio` zera
       este margin-top para recolher, e um seletor de MESMA especificidade la embaixo venceria o
       zero e deixaria uma folga de 24px onde a bio ja tinha sumido. */
    margin: var(--esp-4) auto 0;
    max-width: 420px;
    overflow: hidden;
    text-align: center;
    font-size: .95rem;
    line-height: 1.5;
    color: var(--pp-tinta-suave);
    /* A altura natural e medida na abertura pelo agendar.js: max-height nao
       anima a partir de `none`, e chutar um teto cortaria bio comprida. */
    max-height: var(--mk-bio-altura, 8rem);
    transition: max-height var(--mov-3) var(--curva-entrada),
                opacity var(--mov-2),
                margin var(--mov-3) var(--curva-entrada);
}

/* Da etapa 2 em diante a bio sai: e apresentacao, nao ajuda a escolher. */
.mk--apos-abertura .mk-bio {
    max-height: 0;
    margin-top: 0;
    opacity: 0;
}

/* Fixo na janela: mesma posicao em toda etapa e em qualquer rolagem — pelo
   mesmo motivo do Continuar fixo no rodape. Acao que troca de lugar obriga o
   usuario a procurar o botao de novo a cada passo. */
.mk-voltar {
    position: fixed;
    top: var(--esp-3);
    left: var(--esp-3);
    z-index: 40;
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--toque);
    height: var(--toque);
    border: 1px solid var(--pp-borda);
    border-radius: 50%;
    background: var(--pp-superficie);
    color: var(--pp-tinta);
    cursor: pointer;
    box-shadow: var(--sombra-flutuante);
    /* Ausente na etapa 1 — nao ha para onde voltar. `visibility` em vez de
       `display` para poder animar a entrada e para sair do foco de teclado. */
    opacity: 0;
    visibility: hidden;
    transform: translateX(-8px);
    transition: opacity var(--mov-3),
                transform var(--mov-3) var(--curva-entrada),
                visibility var(--mov-3),
                border-color var(--mov-1),
                color var(--mov-1);
}

.mk--apos-abertura .mk-voltar {
    opacity: 1;
    visibility: visible;
    transform: none;
}

/* "Início" dentro do fluxo de agendamento (ver o comentário em Agendar/_Marca.cshtml) — o
   inverso exato do `.mk-voltar` acima: visível na etapa 1 (quando não há voltar nenhum),
   recolhe assim que `.mk--apos-abertura` entra. Fora do `.mk` (_TabbarCliente, nas outras
   telas públicas) o `.cl-inicio` não herda nada disto e continua sempre visível — a regra é
   escopada ao fluxo de propósito. */
.mk .cl-inicio {
    transition: opacity var(--mov-3), visibility var(--mov-3);
}

.mk--apos-abertura .cl-inicio {
    opacity: 0;
    visibility: hidden;
}

.mk-voltar:hover {
    border-color: var(--cor-marca);
    color: var(--cor-marca);
}

.mk--apos-abertura .mk-voltar:active {
    transform: scale(.94);
}

.fl-progresso {
    display: flex;
    gap: 5px;
}

/* O trilho preenche no mesmo sentido em que o conteudo entra: avancar corre a
   tinta para a direita, voltar drena de volta. Sao 5 botoes (alvo de clique e
   rotulo de leitor de tela); a tinta e um ::after que escala. */
.fl-segmento {
    position: relative;
    flex: 1;
    height: 5px;
    padding: 0;
    border: none;
    border-radius: 3px;
    background: var(--pp-borda);
}

/* A barra tem 5px — alvo de toque impossivel. Este ::before estende a area
   clicavel para 45px sem ocupar layout nenhum (por isso nao ha overflow
   hidden no segmento: ele cortaria justamente este alvo).
   Assimetrico de proposito: acima do trilho fica o header compacto, que e
   sticky e ganha o hit-test — entao o alvo cresce para baixo, onde so ha
   texto. 10px + 5px + 30px = 45px. */
.fl-segmento::before {
    content: "";
    position: absolute;
    inset: -10px 0 -30px;
}

.fl-segmento::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--cor-marca);
    transform: scaleX(0);
    transform-origin: left;
    /* Atrasa um pouco: o conteudo da etapa entra, ai o trilho acompanha. */
    transition: transform var(--mov-2) var(--curva-entrada) 80ms;
}

.fl-segmento--ativo::after {
    transform: scaleX(1);
}

.fl-segmento[disabled] {
    cursor: default;
}

.fl-legenda {
    margin: 7px 0 var(--esp-4);
    font-size: .78rem;
    font-weight: 500;
    color: var(--pp-tinta-suave);
}

.fl-secao-titulo {
    margin: var(--esp-2) 0 2px;
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--pp-tinta-forte);
}

.fl-secao-texto {
    margin: 0 0 var(--esp-3);
    font-size: .85rem;
    line-height: 1.4;
    color: var(--pp-tinta-suave);
}

.fl-opcoes {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* --- Servicos em GRADE ----------------------------------------------------
   So entra quando TODO servico tem foto (a view decide — ver o comentario la).
   A lista continua sendo a forma padrao, e continua sendo a certa: sem foto,
   uma grade seria uma vitrine de retangulos vazios.

   minmax(0, 1fr) e nao `1fr` solto: coluna `fr` tem min-width auto e nao encolhe
   abaixo do conteudo — nome de servico longo estouraria a grade a 320px. E o
   mesmo motivo que o dashboard ja documenta no gradil dele. */
.fl-opcoes--grade {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}

/* 🔴 `--raio-card`, e NAO o `--raio-controle-lg` que a `.nr-opcao` usa na lista.
   Medido com o preset de cantos em pilula: na lista a opcao tem ~60px de altura
   e 999px de raio produz a capsula horizontal esperada; na GRADE ela tem 188px,
   e o mesmo raio a transforma num circulo — foto cortada em arco e o nome
   escapando do arredondado. A caixa mudou de forma, entao o token que a veste
   tambem muda. E o mesmo motivo pelo qual o preset ja segurava o cartao em 22px:
   faltava aplicar a regra aqui, onde uma opcao PASSA A SER cartao. */
.fl-opcoes--grade .nr-opcao {
    position: relative;
    flex-direction: column;
    align-items: stretch;
    gap: var(--esp-2);
    padding: 0 0 var(--esp-3);
    border-radius: var(--raio-card);
    overflow: hidden;
}

/* A foto passa a ser a face da celula. `aspect-ratio` em vez de altura fixa: a
   linha inteira precisa ter celulas da mesma altura, e altura em px quebraria
   isso quando o nome ocupasse duas linhas numa e uma noutra. */
.fl-opcoes--grade .fl-servico-foto {
    width: 100%;
    height: auto;
    /* 🔴 4:3, e nao 16:9. 16:9 e razao de VIDEO, e o assunto destas fotos e uma PESSOA: em 16:9 o
       recorte decapita a cabeca ou corta os ombros em quase todo enquadramento de rosto. O
       `object-position: center 35%` completa a conta — puxa a janela do recorte para cima do
       centro geometrico, que e onde o rosto fica numa foto de corte de cabelo.

       ⚠️ A celula fica ~33% mais alta. E o preco de a foto valer alguma coisa, e quem paga a
       conta e o `loading="lazy"` do <img> mais o `content-visibility` do cartao logo abaixo. */
    aspect-ratio: 4 / 3;
    object-position: center 35%;
    border-radius: 0;
}

.fl-opcoes--grade .nr-opcao > span:not(.nr-marcador) {
    padding-inline: var(--esp-3);
}

/* O marcador sai do fluxo e vai para cima da foto — no rodape da celula ele
   competiria com o preco pelo mesmo canto. O veu atras garante que ele apareca
   sobre foto clara: sem isso a borda branca sumiria numa toalha branca. */
.fl-opcoes--grade .nr-marcador {
    position: absolute;
    top: var(--esp-2);
    right: var(--esp-2);
    background: rgb(15 23 42 / .38);
    border-color: rgb(255 255 255 / .85);
}

/* Uma coluna abaixo de 380px: duas celulas de 170px transformam a foto em
   selo e o nome em duas linhas quebradas. Ai a lista serve melhor, e e para
   ela que a grade colapsa. */
@media (max-width: 380px) {
    .fl-opcoes--grade {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Faixa de dias: rola na horizontal sem barra visivel. */
.fl-dias {
    display: flex;
    gap: var(--esp-2);
    overflow-x: auto;
    padding: 10px 2px var(--esp-1);
    scrollbar-width: none;
}

.fl-dias::-webkit-scrollbar {
    display: none;
}

.fl-dia {
    flex: none;
    min-width: 60px;
    padding: 9px var(--esp-2) var(--esp-2);
    border: 1.5px solid var(--pp-borda);
    border-radius: var(--raio-controle-lg);
    background: var(--pp-superficie);
    text-align: center;
    cursor: pointer;
    transition: border-color var(--mov-1), background var(--mov-1), box-shadow var(--mov-1);
}

.fl-dia:hover {
    border-color: var(--cor-marca);
}

/* Mesmo gesto do chip de horario: dia e hora sao a mesma decisao, em dois
   tempos — entao levantam do papel do mesmo jeito. */
.fl-dia[aria-pressed="true"] {
    background: var(--cor-marca);
    border-color: var(--cor-marca);
    box-shadow: 0 4px 12px color-mix(in oklab, var(--cor-marca) 30%, transparent);
}

.fl-dia-semana {
    display: block;
    font-size: .66rem;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--pp-tinta-suave);
}

.fl-dia-numero {
    display: block;
    margin-top: var(--esp-1);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--pp-tinta-forte);
}

.fl-dia-mes {
    display: block;
    margin-top: 2px;
    font-size: .66rem;
    font-weight: 500;
    color: var(--pp-tinta-suave);
}

.fl-dia[aria-pressed="true"] .fl-dia-semana,
.fl-dia[aria-pressed="true"] .fl-dia-mes {
    color: color-mix(in oklab, var(--tinta-sobre-marca) 85%, transparent);
}

.fl-dia[aria-pressed="true"] .fl-dia-numero {
    color: var(--tinta-sobre-marca);
}

.fl-grupos {
    display: flex;
    flex-direction: column;
    gap: var(--esp-3);
    margin-top: var(--esp-2);
}

.fl-grupo-titulo {
    margin: 0 0 var(--esp-2);
    font-size: .78rem;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--pp-tinta-suave);
}

.fl-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--esp-2);
}

/* Cartao de resumo da ultima etapa. */
.fl-resumo {
    background: var(--pp-superficie);
    border: 1px solid var(--pp-borda);
    border-radius: var(--raio-card);
    box-shadow: var(--sombra);
    overflow: hidden;
}

.fl-resumo-bloco {
    padding: var(--esp-3) var(--esp-4);
    border-bottom: 1px solid var(--pp-divisor);
}

.fl-resumo-bloco:last-child {
    border-bottom: none;
}

.fl-resumo-cabecalho {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}

.fl-resumo-valor {
    margin-top: 3px;
    font-size: .95rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--pp-tinta);
}

.fl-resumo-linha {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    font-size: .9rem;
    line-height: 1.4;
    color: var(--pp-tinta);
}

.fl-resumo-total {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px dashed var(--pp-borda);
    display: flex;
    justify-content: space-between;
    font-size: 1rem;
    font-weight: 700;
    color: var(--pp-tinta-forte);
}

/* --- A cobertura da mensalidade no resumo (Bloco 58) ---------------------
   🔴 A coluna da direita TROCA DE VOZ, e nao ganha um selo ao lado do preco. O
   olho ja varre aquela coluna procurando dinheiro; encontrar uma PALAVRA ali E
   a informacao. Um chip colorido seria decoracao competindo com o numero que
   ele explica — e a marca ja tem um uso reservado nesta pagina (o `.hm-cta`).

   ⚠️ `--cor-marca-acento`, jamais `--cor-marca` crua: a marca #000000 existe no
   banco e viraria texto invisivel no tema escuro. O acento existe para isto.
   ----------------------------------------------------------------------- */
.fl-resumo-incluido {
    color: var(--cor-marca-acento);
    /* Nao pode ser SO a cor: quem nao distingue matiz precisa da palavra, e a
       palavra ja esta la. A caixa baixa mantem o tom de nota, nao de anuncio. */
    font-variant-caps: all-small-caps;
    letter-spacing: .04em;
    white-space: nowrap;
}

/* A cota e do CICLO, nao do servico — por isso entra uma vez so, recuada sob a
   linha que a motivou, no tamanho de nota de rodape. */
.fl-resumo-cota {
    margin-top: 2px;
    font-size: .78rem;
    line-height: 1.35;
    color: var(--pp-tinta-suave);
}

/* O aviso e uma CONDICAO PERMANENTE, nao um erro: a cobertura e decidida no dia
   do atendimento. Por isso e uma linha quieta e nao um `.alert` — vermelho ali
   diria que algo deu errado, e nada deu. */
.fl-cobertura-aviso {
    margin: 8px 0 0;
    font-size: .78rem;
    line-height: 1.35;
    color: var(--pp-tinta-suave);
}

/* Variacao TEXTO do sinal de atencao (U+26A0 + U+FE0E): sem o seletor de
   variacao o Android pinta um emoji amarelo, que grita mais que a frase. */
.fl-cobertura-aviso::before {
    content: "\26A0\FE0E\A0";
}

/* Acao textual dentro do texto: mesmo peso do `.btn-link` do resumo, sem virar
   um segundo botao competindo com o Continuar da barra fixa. */
.fl-trocar-conta {
    padding: 0;
    min-height: auto;
    vertical-align: baseline;
    text-decoration: underline;
}

/* Presa ao rodape da JANELA, nao ao fim do conteudo.
   Como `sticky`, ela parava na altura em que a etapa terminava — y=570 numa
   etapa, y=342 na outra — e o usuario tinha de procurar o mesmo botao em
   lugar diferente a cada passo. Fixa, o Continuar nunca sai do lugar. */
.fl-barra {
    position: fixed;
    left: 50%;
    bottom: 0;
    z-index: 20;
    width: 100%;
    max-width: var(--largura-form);
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    padding: var(--esp-3) var(--esp-4);
    /* Fica acima da faixa de gestos no iOS. */
    padding-bottom: calc(var(--esp-3) + env(safe-area-inset-bottom, 0px));
    background: var(--pp-superficie);
    border-top: 1px solid var(--pp-borda);
}

/* Espaco para o conteudo nao terminar escondido atras da barra fixa. */
.publico-wrap:has(.fl-barra) {
    padding-bottom: 124px;
}

.fl-barra-total {
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--pp-tinta-forte);
}

/* O total muda longe de onde o dedo tocou (o cartao esta la em cima), entao
   ele se anuncia. So quando o valor realmente muda — o agendar.js compara. */
.fl-barra-total--mudou {
    animation: fl-trocar var(--mov-2) var(--curva-entrada);
}

.fl-barra-resumo {
    font-size: .78rem;
    font-weight: 500;
    line-height: 1.3;
    color: var(--pp-tinta-suave);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fl-avancar {
    flex: none;
    min-height: 48px;
    padding: 0 22px;
    border-radius: var(--raio-controle-lg);
    font-size: .95rem;
    font-weight: 600;
    transition: opacity var(--mov-1), background var(--mov-1);
}

/* Ainda falta algo nesta etapa. Nao usa [disabled] de proposito: clicar
   precisa continuar disparando a mensagem que diz o que falta — botao morto
   nao explica nada. */
.fl-avancar--aguardando {
    opacity: .45;
}

/* --- 6.1.1 Movimento do fluxo -------------------------------------------
   Uma linguagem so, num eixo so. O conteudo de cada etapa entra pelo lado
   para onde o cliente esta indo, bloco a bloco (--i escalona o atraso), em
   vez de a etapa inteira aparecer de uma vez. Quem aplica as classes e o
   agendar.js; sem JS nada disto existe e o formulario e unico.
   ------------------------------------------------------------------------ */

/* `backwards`, nao `both`: o bloco precisa ficar invisivel durante o atraso da
   cascata, mas nao pode reter o estado final. Animacao vence estilo inline na
   cascata — com `both`, o `transform: none` do ultimo quadro anularia para
   sempre o transform que o morph do header aplica, e a opacidade retida em 1
   impediria a bio de sumir. */
.fl-entra {
    animation-duration: var(--mov-etapa);
    animation-timing-function: var(--curva-entrada);
    animation-delay: calc(var(--i, 0) * var(--passo-cascata));
    animation-fill-mode: backwards;
}

.fl-entra--frente { animation-name: fl-entra-frente; }
.fl-entra--tras { animation-name: fl-entra-tras; }
.fl-entra--carga { animation-name: fl-entra-carga; }

/* A marca do estabelecimento e a primeira coisa que o cliente ve na etapa 1:
   a logo assenta sobre a capa depois dela, em vez de chegarem juntas.

   ⚠️ Era `.mk-logo`. Passou a `.hm-fachada-logo` porque o header do fluxo renderiza a MESMA
   fachada da home (partial `_FachadaPublica`) — o gesto e o mesmo, so o nome do alvo mudou. As
   classes `fl-entra--*` so existem no /agendar (quem as poe e o agendar.js), entao isto continua
   sem alcancar a pagina publica. */
.fl-entra--carga .hm-fachada-logo {
    animation: fl-assentar var(--mov-3) var(--curva-entrada) 140ms backwards;
}

/* Ate o agendar.js falar, o documento ja vem marcado — assim o cliente nunca
   ve o formulario inteiro piscar antes de virar etapas. A marca sai quando o
   script termina a montagem OU quando ele falha (degradar()), e nos dois
   casos o estado final e coerente. */
.nr-com-js [data-fluxo-etapa]:not([data-fluxo-etapa="0"]) {
    display: none;
}

/* Movimento desligado, fade mantido: o escalonamento continua dizendo em que
   ordem as coisas chegaram, sem nada deslizando pela tela. */
@keyframes fl-entra-parado {
    from { opacity: 0; }
    to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .fl-entra,
    .fl-entra--carga .hm-fachada-logo,
    .fl-barra-total--mudou {
        animation-name: fl-entra-parado;
    }

    .fl-segmento::after,
    .fl-dia,
    .mk-bio,
    .mk-voltar,
    .nr-opcao,
    .nr-chip-hora,
    .nr-marcador,
    .nr-marcador svg,
    .nr-marcador svg polyline,
    .nr-marcador--circulo span {
        transition-duration: .01ms;
    }

    /* Nada afunda nem escala sob o dedo. */
    .fl-dia:active,
    .mk-voltar:active,
    .nr-opcao:active,
    .nr-chip-hora:active {
        transform: none;
    }
}

/* --- 6.2 Confirmacao e cancelamento ------------------------------------ */

.cf-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: #DCFCE7;
    margin: 0 auto var(--esp-3);
}

/* Mesmo circulo, tom ambar: assinatura pendente pede acao, nao e falha. */
.cf-icone--aviso {
    background: #FEF3C7;
}

/* Mesmo circulo, tom neutro: link invalido nao e erro do cliente. */
.cf-icone--neutro {
    background: var(--cinza-100);
    color: var(--cinza-500);
    font-size: 26px;
    font-weight: 700;
}

/* Faixa do "quando" no topo do card: veste a marca do estabelecimento. */
.cf-quando {
    padding: var(--esp-4);
    background: var(--cor-marca-suave);
    border-bottom: 1px solid var(--pp-divisor);
}

.cf-quando .nr-eyebrow {
    color: var(--cor-marca-escura);
}

.cf-quando-valor {
    margin-top: 3px;
    font-size: 1.1rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--pp-tinta-forte);
}

/* Bloco do link de cancelamento — em ambar porque e a instrucao que o
   cliente precisa guardar, nao um aviso de erro. */
.cf-guarde {
    background: #FFFBEB;
    border: 1px solid #FDE68A;
    border-radius: var(--raio-card);
    padding: var(--esp-3) var(--esp-4);
}

/* O aviso de que o link nao se compartilha. Fica DENTRO do bloco ambar, colado
   ao link, e nao no rodape da pagina: aviso longe do que ele protege nao e
   lido. */
.cf-guarde-aviso {
    margin: var(--esp-1) 0 var(--esp-2);
    font-size: .82rem;
    font-weight: 600;
    color: #92400E;
}

/* --- O COMPROVANTE --------------------------------------------------------
   O cartao que a pessoa fotografa. Veste a cor da marca da barbearia, porque um
   print sem identidade nao diz de onde veio — que e a unica razao de alguem
   mandar a foto para outra pessoa.

   🔴 O que ele NAO carrega esta documentado na view: nem link nem codigo de
   cancelamento. Nao mexa nisso sem ler o comentario de la.

   `--raio-card` e nao um raio proprio: o comprovante acompanha os cantos que o
   lojista escolheu, como todo o resto da pagina. */
.cf-comprovante {
    margin-top: var(--esp-5);
    border: 1px solid var(--pp-borda);
    border-radius: var(--raio-card);
    background: var(--pp-superficie);
    overflow: hidden;
}

.cf-comprovante-topo {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--esp-3);
    padding: var(--esp-3) var(--esp-4);
    background: var(--cor-marca);
    color: var(--tinta-sobre-marca);
}

.cf-comprovante-marca {
    font-weight: 700;
    font-size: .95rem;
    /* Nome longo nao empurra o selo para fora: ele encolhe e corta. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cf-comprovante-selo {
    flex: none;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    padding: 3px 9px;
    border-radius: var(--raio-pill);
    /* Contorno em `currentColor`, e nao um fundo translucido: o selo herda a
       tinta que o servidor ja decidiu para cima da marca, entao funciona com
       marca clara E escura sem uma segunda variavel.

       🔴 Nao troque por `rgb(from var(--tinta-sobre-marca) r g b / .16)`. Cor
       relativa e CSS Color 5 (Chrome 119+, Safari 16.4+, Firefox 128+) e falha
       em SILENCIO: em celular antigo o selo simplesmente perde o fundo. Esta
       tela e o fim do fluxo de agendamento de um cliente anonimo qualquer. */
    border: 1px solid currentColor;
}

.cf-comprovante-quando {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--esp-4);
}

/* A serrilha do cupom: dois circulos da cor do FUNDO da pagina mordendo as
   laterais, e um tracejado entre eles. Sem imagem — e a mesma doutrina da
   textura do fundo. */
.cf-comprovante-serrilha {
    position: relative;
    height: 1px;
    margin: 0 var(--esp-4);
    border-top: 1px dashed var(--pp-borda);
}

.cf-comprovante-serrilha::before,
.cf-comprovante-serrilha::after {
    content: "";
    position: absolute;
    top: -8px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--pp-fundo);
}

.cf-comprovante-serrilha::before { left: calc(var(--esp-4) * -1 - 8px); }
.cf-comprovante-serrilha::after { right: calc(var(--esp-4) * -1 - 8px); }

.cf-comprovante-total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--esp-3);
    padding: var(--esp-4);
    font-weight: 700;
    color: var(--pp-tinta-forte);
}

.cf-comprovante-total strong {
    font-size: 1.35rem;
    font-variant-numeric: tabular-nums;
}

.cf-guarde-titulo {
    font-size: .85rem;
    font-weight: 600;
    line-height: 1.3;
    color: #92400E;
}

.cf-link-caixa {
    display: flex;
    align-items: stretch;
    gap: var(--esp-2);
    margin-top: var(--esp-2);
}

.cf-link {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    min-height: var(--toque);
    padding: 0 var(--esp-3);
    border: 1px solid #FDE68A;
    border-radius: var(--raio-controle);
    background: var(--branco);
    font-family: var(--fonte-mono);
    font-size: .78rem;
    color: var(--cinza-600);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* --- 6.2.1 Vitrine de PRODUTOS na confirmacao (Bloco 42) ---------------
   Atencao ao nome: "vitrine" ja significava a home do tenant (6.3 abaixo) e a
   tabela de precos da landing. Estas classes sao `vt-`, das outras duas, e o
   glossario reserva o termo. Ver o §13 do handoff.

   Sem grade e sem imagem de proposito: o Bloco 42 nao tem foto de produto, e
   uma lista de nome+preco cai em uma coluna a 320px sem media query nenhuma. */

.vt-produtos {
    border-top: 1px solid var(--pp-borda);
    padding-top: 1rem;
}

.vt-lista {
    list-style: none;
    margin: .5rem 0 0;
    padding: 0;
}

.vt-item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: .6rem 0;
    border-bottom: 1px solid var(--pp-borda);
}

.vt-item:last-child {
    border-bottom: 0;
}

.vt-item-texto {
    display: flex;
    flex-direction: column;
    /* Sem isto, um nome longo empurra o preco para fora do cartao a 320px em vez
       de quebrar. Medido no Bloco 24 na linha de horario, mesma forma. */
    min-width: 0;
}

.vt-item-nome {
    font-weight: 600;
    color: var(--pp-tinta-forte);
    overflow-wrap: anywhere;
}

.vt-item-descricao {
    font-size: .85rem;
    color: var(--pp-tinta-suave);
    overflow-wrap: anywhere;
}

.vt-item-preco {
    font-weight: 700;
    color: var(--pp-tinta-forte);
    white-space: nowrap;
}

/* O botão "Adicionar" do carrinho do cliente (Bloco 59, ComCarrinho=true). Só existe em
   /carteirinha/produtos — o `.vt-item` do balão de /agendar/confirmado nunca o recebe, então
   `flex-wrap` aqui não muda nada de quem já usava esta classe sem carrinho. */
.vt-item-adicionar {
    flex: 1 0 100%;
    margin-top: .4rem;
    padding: .4rem .9rem;
    border: 1.5px solid var(--cor-marca-acento);
    border-radius: 999px;
    background: transparent;
    color: var(--cor-marca-acento);
    font-size: .8125rem;
    font-weight: 700;
    cursor: pointer;
}

.vt-item:has(.vt-item-adicionar) {
    flex-wrap: wrap;
}

/* --- 6.3 Pagina publica do estabelecimento ("/" no host do tenant) -----
   As classes continuam `hm-` de proposito: o termo canonico para codigo NOVO e
   PaginaPublica (ver o glossario), mas renomear prefixo CSS e churn puro. */

.hm-info {
    background: var(--pp-superficie);
    border: 1px solid var(--pp-borda);
    border-radius: var(--raio-card);
    box-shadow: var(--sombra);
    text-align: left;
    overflow: hidden;
}

.hm-linha {
    display: flex;
    justify-content: space-between;
    gap: var(--esp-3);
    padding: 13px var(--esp-4);
    border-bottom: 1px solid var(--pp-divisor);
    font-size: .88rem;
    line-height: 1.4;
}

.hm-linha:last-child {
    border-bottom: none;
}

.hm-rotulo {
    color: var(--pp-tinta-suave);
    flex: none;
}

.hm-valor {
    color: var(--pp-tinta);
    text-align: right;
}

.hm-aberto {
    font-weight: 600;
    color: var(--pp-aberto);
}

.hm-fechado {
    font-weight: 600;
    color: var(--pp-tinta-suave);
}

/* Horario da semana inteira. <details> NATIVO: zero JS, acessivel por teclado,
   progressivo — e o <summary> E a linha "Hoje" que ja existia, entao fechado
   nada empurra endereco e WhatsApp para baixo. */
.hm-horario {
    border-bottom: 1px solid var(--pp-divisor);
}

/* Barbearia com grade mas sem endereco nem WhatsApp: o <details> e o unico filho
   do cartao, e o divisor sobraria encostado na borda de baixo. As `.hm-linha` ja
   tinham a mesma regra; o <details> nao herda a delas. */
.hm-horario:last-child {
    border-bottom: none;
}

.hm-horario > summary {
    cursor: pointer;
    list-style: none;
    /* Sem isto o marcador do Safari aparece ANTES do rotulo e desalinha a
       linha em relacao a endereco e WhatsApp. */
    border-bottom: none;
}

.hm-horario > summary::-webkit-details-marker {
    display: none;
}

.hm-horario > summary:hover .hm-rotulo {
    color: var(--pp-tinta);
}

/* Seta propria: gira ao abrir e diz que a linha e clicavel. */
.hm-seta {
    flex: none;
    width: 8px;
    height: 8px;
    margin-left: 2px;
    border-right: 1.5px solid var(--pp-tinta-suave);
    border-bottom: 1.5px solid var(--pp-tinta-suave);
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform var(--mov-1);
}

.hm-horario[open] .hm-seta {
    transform: rotate(-135deg) translate(-2px, -2px);
}

.hm-semana {
    background: var(--pp-superficie-2);
}

.hm-semana .hm-linha:last-child {
    border-bottom: none;
}

/* O dia de hoje se destaca dentro da lista aberta — senao o cliente tem de
   contar as linhas para achar onde esta. */
.hm-linha--hoje .hm-rotulo,
.hm-linha--hoje .hm-valor {
    color: var(--pp-tinta);
    font-weight: 600;
}

/* 🔴 O BLOCO DE COMODIDADES QUE MORAVA AQUI FOI APAGADO, e a remocao e o conserto — nao faxina.
   Era o desenho anterior (nuvem de chips centralizada que quebrava em varias linhas), superado
   pela linha rolante do Bloco 48 mais abaixo. As duas regras tinham a MESMA especificidade, entao
   a de baixo vencia propriedade a propriedade... menos as que ela nao declarava. Sobrevivia
   `justify-content: center` — e num flex container que ESTOURA, centralizar joga o excedente para
   os DOIS lados. O que sai pela esquerda fica inalcancavel: `scrollLeft` nao vai a negativo.
   Medido: a primeira comodidade nascia em x = -52px com `scrollLeft` ja em 0, cortada para sempre,
   e arrastar nao trazia ela de volta. Ver `.hm-comodidades` na secao "Comodidades". */

/* Formato da logo, valendo na pagina publica E no header de marca do fluxo: o atributo mora no
   <html>, entao as duas telas mostram o MESMO recorte. `redonda` nao precisa de regra — e o
   border-radius: 50% que a folha ja pintava, e nao ter regra e o que torna o padrao inerte.

   ⚠️ O seletor `.mk-logo` SAIU daqui, e nao e regressao: as duas telas passaram a renderizar a
   MESMA `.hm-fachada-logo` (partial `_FachadaPublica`), entao um seletor so cobre as duas. Era
   por isso que existiam dois. */
[data-formato-logo="arredondada"] .hm-fachada-logo { border-radius: 18px; }

[data-formato-logo="quadrada"] .hm-fachada-logo { border-radius: 4px; }

/* ==========================================================================
   ACABAMENTO DA PAGINA (cantos, textura, hover)

   Os tres moram no <html>, como o formato da logo, e pelo mesmo motivo: valem
   para a home E para o fluxo de agendamento.

   🔴 O PADRAO DE CADA UM NAO TEM REGRA. `suave`, `nenhuma` e `sutil` sao o que
   a folha ja fazia — nao ter seletor e o que torna a escolha default inerte, e
   e o que faz a migration nao mudar um pixel em tenant nenhum.
   ========================================================================== */

/* --- Cantos ---------------------------------------------------------------
   Reescreve os TRES tokens de raio que a folha ja consumia (--raio-controle,
   --raio-card, --raio-pill), e nao cada componente. Foi por isso que esta ficou
   a mudanca mais barata da lista: o encanamento ja estava pronto desde sempre.

   ⚠️ `--raio-pill` fica em 999px nos tres: pilula ja e o maximo, e chip/badge
   nao deve virar retangulo so porque o dono escolheu canto reto para cartao. */
[data-cantos="reto"] {
    --raio-controle: 0px;
    --raio-controle-lg: 0px;
    --raio-card: 0px;
    --raio-card-lg: 0px;
}

[data-cantos="pilula"] {
    --raio-controle: var(--raio-pill);
    --raio-controle-lg: var(--raio-pill);
    --raio-card: 22px;
    --raio-card-lg: 26px;
}

/* 🔴 Cartao NAO vira pilula. Um raio de 999px numa caixa alta produz duas
   laterais completamente circulares e o conteudo escapa do arredondado — e por
   isso o preset para no 22px. "Pilula" descreve o BOTAO, que e o que o dono
   reconhece; o cartao so acompanha o tom. */

/* --- Textura do fundo -----------------------------------------------------
   Desenhada em CSS, nunca imagem: arquivo somaria peso a uma pagina anonima e
   pediria abertura no img-src da CSP.

   🔴 As opacidades sao BAIXAS e FIXAS aqui, fora do alcance de quem escolhe.
   Textura atras de texto e risco de contraste, e este produto ja mediu 1,01,
   4,21 e 1,00 em tres ocasioes diferentes. A textura veste o FUNDO da pagina
   (--pp-fundo); as superficies de conteudo continuam opacas por cima dela, que
   e o que garante que nenhum texto passe a depender do desenho.

   `background-attachment: fixed` de proposito: sem ele o padrao rola junto e o
   olho persegue a listra em vez de ler. */
[data-textura="listras"] body,
[data-textura="xadrez"] body,
[data-textura="pontos"] body {
    background-attachment: fixed;
}

[data-textura="listras"] body {
    background-image: repeating-linear-gradient(
        45deg,
        var(--pp-textura) 0 2px,
        transparent 2px 14px
    );
}

[data-textura="xadrez"] body {
    background-image:
        repeating-linear-gradient(0deg, var(--pp-textura) 0 1px, transparent 1px 22px),
        repeating-linear-gradient(90deg, var(--pp-textura) 0 1px, transparent 1px 22px);
}

[data-textura="pontos"] body {
    background-image: radial-gradient(var(--pp-textura) 1.2px, transparent 1.2px);
    background-size: 18px 18px;
}

/* --- Hover ----------------------------------------------------------------
   🔴 SO hover. O indicador de :focus-visible nao aparece em nenhuma regra deste
   bloco e nao deve aparecer: foco e acessibilidade, nao decoracao, e uma opcao
   "contorno" que o alcancasse deixaria o lojista apagar a navegacao por teclado
   da propria pagina sem saber o que apagou.

   Tudo sob @media (hover: hover): em telefone nao ha ponteiro, e :hover ali
   gruda no ultimo elemento tocado — o cartao ficaria elevado ate o proximo
   toque, parecendo selecionado.

   🔴 ALVO UNICO: `.nr-opcao`. Sao os cartoes que o cliente de fato aponta —
   servico, profissional e horario, o fluxo inteiro de agendar. `.ct-cartao`
   (clubes) ficou de fora de proposito: ele vive no carteirinha.css, que a
   pagina publica carrega CONDICIONALMENTE, e uma regra aqui que dependesse de
   outra folha estar presente e do peso do seletor para vencer seria acoplamento
   fragil — funciona ate alguem trocar a ordem dos <link>. Se o hover precisar
   alcancar os clubes um dia, a regra nasce naquela folha, nao nesta. */
@media (hover: hover) {
    [data-hover="elevacao"] .nr-opcao:hover {
        transform: translateY(-2px);
        box-shadow: 0 6px 18px -8px rgb(15 23 42 / .28);
    }

    [data-hover="contorno"] .nr-opcao:hover {
        border-color: var(--cor-marca);
        box-shadow: inset 0 0 0 1px var(--cor-marca);
    }
}

/* `.nr-opcao` JA declara `transition` com transform e box-shadow na lista (ver a
   regra base), entao nao ha transicao a acrescentar aqui — repetir a
   propriedade so criaria um segundo lugar para manter. O que falta e o respeito
   ao movimento reduzido no que ESTE bloco introduz. */
@media (prefers-reduced-motion: reduce) {
    [data-hover="elevacao"] .nr-opcao:hover {
        transform: none;
    }
}

/* Bloco de identidade da pagina publica: capa, logo, nome, bio e o CTA. */

/* Posicao da logo. Move o bloco INTEIRO, e nao so a imagem: logo a esquerda com
   nome centralizado abaixo fica desalinhado, e a escolha do dono e sobre a
   identidade. O CTA e `w-100`, entao ele nao se desloca. */



/* Dialogo de confirmacao — nativo, sem lib. O fundo era o branco DO NAVEGADOR
   (o UA pinta `dialog`), o que no tema escuro deixaria titulo claro sobre papel
   branco. Declarado aqui, ele acompanha a superficie da pagina. */
.nr-dialogo {
    background: var(--pp-superficie);
    color: var(--pp-tinta);
    width: calc(100% - 40px);
    max-width: 360px;
    border: none;
    border-radius: var(--raio-card-lg);
    box-shadow: 0 24px 60px rgba(15, 23, 42, .3);
    padding: 22px;
    animation: nr-subir .2s ease;
}

.nr-dialogo::backdrop {
    background: rgba(15, 23, 42, .45);
}

.nr-dialogo-titulo {
    margin: 0 0 6px;
    font-size: 1.1rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--pp-tinta-forte);
}

.nr-dialogo-texto {
    margin: 0 0 var(--esp-5);
    font-size: .88rem;
    line-height: 1.5;
    color: var(--pp-tinta-suave);
}

.nr-dialogo-acoes {
    display: flex;
    gap: 9px;
}

.nr-dialogo-acoes > * {
    flex: 1;
}

/* Faixa de toast das paginas publicas (rodape, nao canto). */
.nr-toast-faixa {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 18px;
    z-index: 90;
    display: flex;
    justify-content: center;
    pointer-events: none;
}

/* --- 6.4 Barra do cliente (Fase A do menu do cliente, 22/08/2026) -------
   Mesmo molde visual do .pn-tabbar do painel (pilula flutuante + FAB
   central) — mas com o vocabulario de cor da PAGINA PUBLICA (--pp- e
   --cor-marca), nunca o do painel (--pn-): o cliente nao pode sentir que
   caiu na tela do dono. Ao contrario do painel (onde a sidebar cobre o
   desktop e a pilula so aparece <768px), aqui nao ha shell de desktop
   nenhum para o cliente — a pilula fica sempre visivel, em qualquer
   largura, porque e a UNICA navegacao que esta area tem.
   ------------------------------------------------------------------------ */

/* "Início" (Bloco 60) — MESMA receita do `.mk-voltar` do fluxo de agendamento
   (§ Agendar/_Marca.cshtml): fixo no canto superior esquerdo, em qualquer
   etapa e qualquer rolagem, para nunca precisar procurar a saída de novo. Ao
   contrario dele, nunca fica escondido — nao e "passo anterior" de um
   formulario, e link de verdade para a vitrine, faz sentido em toda tela.

   `top` soma a safe-area: e o PRIMEIRO elemento fixo que este cliente ve, na
   PRIMEIRA rolagem (scroll 0) de toda pagina publica — diferente do
   `.mk-voltar`, que so aparece a partir da etapa 2. Sem o `env()` ele nasceria
   colado a 12px do topo REAL da tela, debaixo do notch/Dynamic Island de
   qualquer iPhone recente. A pilula la embaixo ja soma o mesmo em
   `env(safe-area-inset-bottom)` — aqui e o mesmo raciocinio, no topo. */
.cl-inicio {
    position: fixed;
    top: calc(var(--esp-3) + env(safe-area-inset-top, 0px));
    left: var(--esp-3);
    z-index: 40;
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--toque);
    height: var(--toque);
    border: 1px solid var(--pp-borda);
    border-radius: 50%;
    background: var(--pp-superficie);
    color: var(--pp-tinta-suave);
    text-decoration: none;
    box-shadow: var(--sombra-flutuante);
    transition: border-color var(--mov-1), color var(--mov-1);
}

.cl-inicio:hover {
    border-color: var(--cor-marca);
    color: var(--cor-marca);
}

/* Mesmo par cor+fundo do `.cl-tab[aria-current="page"]` — ainda é a mesma
   pergunta ("onde eu estou"), só que fora da pílula agora. */
.cl-inicio[aria-current="page"] {
    color: var(--cor-marca);
    border-color: var(--cor-marca);
}

.cl-tabbar {
    display: flex;
    align-items: center;
    position: fixed;
    left: 50%;
    width: calc(100vw - 28px);
    max-width: 420px;
    transform: translateX(-50%);
    bottom: calc(10px + env(safe-area-inset-bottom, 0px));
    z-index: 40;
    gap: 2px;
    height: 64px;
    padding: 0 8px;
    background: var(--pp-superficie);
    border: 1px solid var(--pp-borda);
    border-radius: var(--raio-pill);
    box-shadow: var(--sombra-flutuante);
}

/* Espaco para o conteudo nao terminar escondido atras da pilula flutuante.

   🔴 O SELETOR NAO PODE SER `.publico-wrap:has(.cl-tabbar)`, e essa foi a
   armadilha: `:has()` so enxerga DESCENDENTE, e a `.cl-tabbar` e renderizada
   no _LayoutPublico como IRMA do `.publico-wrap`, nao dentro dele. A regra
   nascia morta e a barra cobria o fim de toda pagina publica (as redes
   sociais da home do tenant, entre outras). A tecnica foi copiada do
   `.publico-wrap:has(.fl-barra)` acima, que funciona porque a `.fl-barra`
   mora dentro do RenderBody (Agendar/Index) — dentro do wrap, portanto.
   Aqui a pergunta tem de ser feita a partir do ANCESTRAL COMUM: o `body`.

   O teto: 10px de folga do fundo + 64px de pilula + 10px que o FAB projeta
   acima dela = 84px de rastro, mais o `env()` para nao brigar com a faixa de
   gestos do iOS. Os 96px deixam 12px de respiro. */
body:has(.cl-tabbar) .publico-wrap {
    padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px));
}

.cl-tab {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 58px;
    border: 0;
    border-radius: 18px;
    background: none;
    color: var(--pp-tinta-suave);
    text-decoration: none;
    cursor: pointer;
}

.cl-tab-icone {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    transition: background var(--mov-1), color var(--mov-1), transform var(--mov-1);
}

.cl-tab:active .cl-tab-icone {
    transform: scale(.88);
}

/* O número do carrinho (Bloco 59.1) — mesma pintura do FAB (marca cheia + tinta decidida pela
   luminância), porque é o mesmo tipo de sinal: "algo te espera aqui". A borda na cor da
   superfície separa o círculo do ícone atrás dele, senão os dois se fundem quando o tab está
   ativo (--cor-marca-suave por trás). Nasce `hidden`/"0" — só o JS (localStorage) decide se
   aparece, o servidor não sabe o que está no carrinho de ninguém. */
.cl-tab-contagem {
    position: absolute;
    top: -2px;
    right: -2px;
    min-width: 16px;
    height: 16px;
    padding: 0 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    border: 2px solid var(--pp-superficie);
    background: var(--cor-marca);
    color: var(--tinta-sobre-marca);
    font-size: 0.625rem;
    font-weight: 700;
    line-height: 1;
}

/* Mesmo par cor+fundo do .nr-opcao[aria-pressed="true"] (§4) — é a mesma
   pergunta ("o que está selecionado"), só que numa pílula em vez de um
   cartão. Um terceiro desenho de "ativo" ensinaria o olho a procurar dois
   sinais diferentes na mesma tela. */
.cl-tab[aria-current="page"] {
    color: var(--cor-marca);
}

.cl-tab[aria-current="page"] .cl-tab-icone {
    background: var(--cor-marca-suave);
}

/* FAB — mesma proporção do .pn-fab (58×58, flutuando acima da pílula), na
   cor de marca do TENANT em vez do acento fixo do painel: é o mesmo gesto
   ("a ação que importa fica elevada"), com a paleta certa para cada lado. */
.cl-fab {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 58px;
    height: 58px;
    margin-top: -26px;
    border-radius: 20px;
    background: var(--cor-marca);
    color: var(--tinta-sobre-marca);
    box-shadow: var(--sombra-flutuante);
    text-decoration: none;
    transition: box-shadow var(--mov-1), transform var(--mov-1);
}

.cl-fab:active {
    transform: scale(.94);
    color: var(--tinta-sobre-marca);
}

/* fim — barra do cliente */

/* --- 7. Painel (shell) -------------------------------------------------
   Sidebar fixa no desktop; no mobile ela sai e entra a tab bar inferior.
   O painel mantem a marca da plataforma: --cor-marca cai no azul porque o
   _LayoutPainel nao invoca o TemaPublico.
   ----------------------------------------------------------------------- */

.pn-body {
    background-color: var(--cinza-50);
}

.pn-shell {
    display: grid;
    grid-template-columns: 232px minmax(0, 1fr);
    min-height: 100vh;
}

.pn-side {
    background: var(--branco);
    border-right: 1px solid var(--cinza-200);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
}

.pn-identidade {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
    padding: 18px var(--esp-4);
    border-bottom: 1px solid var(--cinza-150);
    min-width: 0;
}

.pn-identidade-nome {
    display: block;
    font-size: .88rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--azul-900);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-decoration: none;
}

/* Trunca junto com o nome: host de tenant longo (barbeariacentenario.localhost:5123)
   transbordava a sidebar e ia por cima do conteudo. */
.pn-identidade-host {
    display: block;
    font-family: var(--fonte-mono);
    font-size: .72rem;
    color: var(--cinza-500);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* O filho do flex precisa poder encolher para o ellipsis valer. */
.pn-identidade-texto {
    min-width: 0;
    overflow: hidden;
}

.pn-nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--esp-2) var(--esp-2);
}

.pn-link {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
    padding: 10px var(--esp-3);
    border-radius: 9px;
    color: var(--cinza-600);
    text-decoration: none;
    font-size: .88rem;
    font-weight: 500;
}

.pn-link:hover,
.pn-link:focus {
    background: var(--cinza-50);
    color: var(--cinza-800);
}

.pn-link[aria-current="page"] {
    background: var(--azul-50);
    color: var(--azul-700);
    font-weight: 600;
}

.pn-link .ico {
    flex: none;
    width: 18px;
    height: 18px;
    opacity: .55;
}

.pn-link[aria-current="page"] .ico {
    opacity: 1;
}

.pn-rodape {
    margin-top: auto;
    display: flex;
    align-items: center;
    gap: var(--esp-2);
    padding: var(--esp-3) var(--esp-4);
    border-top: 1px solid var(--cinza-150);
}

.pn-usuario {
    flex: 1;
    min-width: 0;
}

.pn-usuario-nome {
    display: block;
    font-size: .8rem;
    font-weight: 600;
    color: var(--cinza-800);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pn-usuario-papel {
    display: block;
    font-size: .72rem;
    color: var(--cinza-500);
}

/* Topo com a marca — so aparece no mobile, onde a sidebar sai. */
.pn-topo {
    display: none;
}

.pn-main {
    padding: var(--esp-6) var(--esp-6);
    min-width: 0;
}

.pn-conteudo {
    max-width: var(--largura-app);
}

.pn-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--esp-3);
    margin-bottom: var(--esp-5);
}

.pn-tabbar {
    display: none;
}

/* Aviso de trial / assinatura. */
.pn-aviso {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--esp-3);
    background: #FFFBEB;
    border: 1px solid #FDE68A;
    border-radius: 11px;
    padding: 11px var(--esp-4);
    margin-bottom: var(--esp-5);
    font-size: .88rem;
    color: #92400E;
}

/* Toast do painel: canto superior direito, some por JS. */
.pn-toast {
    position: fixed;
    top: var(--esp-5);
    right: var(--esp-5);
    z-index: 90;
    max-width: 320px;
    display: flex;
    align-items: flex-start;
    gap: var(--esp-2);
    background: var(--branco);
    border: 1px solid #BBF7D0;
    border-left: 4px solid var(--sucesso);
    border-radius: 11px;
    box-shadow: var(--sombra-flutuante);
    padding: var(--esp-3) var(--esp-4);
    font-size: .84rem;
    font-weight: 500;
    color: var(--cinza-800);
    animation: nr-subir .25s ease;
}

@media (max-width: 767.98px) {
    .pn-shell {
        grid-template-columns: minmax(0, 1fr);
    }

    .pn-side {
        display: none;
    }

    .pn-topo {
        display: flex;
        align-items: center;
        gap: var(--esp-2);
        background: var(--branco);
        border-bottom: 1px solid var(--cinza-200);
        padding: var(--esp-3) var(--esp-4);
    }

    .pn-main {
        /* Folga inferior para a tab bar fixa nao cobrir o conteudo. */
        padding: var(--esp-4) var(--esp-4) 88px;
    }

    .pn-tabbar {
        display: flex;
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 10;
        background: var(--branco);
        border-top: 1px solid var(--cinza-200);
        padding-bottom: env(safe-area-inset-bottom);
    }

    .pn-toast {
        top: auto;
        bottom: 92px;
        left: var(--esp-4);
        right: var(--esp-4);
        max-width: none;
    }
}

/* Tab bar: indicador de barra no topo do item ativo. */
.pn-tab,
.pn-mais > summary {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 10px 0 12px;
    color: var(--cinza-500);
    text-decoration: none;
    font-size: .68rem;
    font-weight: 600;
    cursor: pointer;
}

.pn-tab::before,
.pn-mais > summary::before {
    content: "";
    width: 22px;
    height: 4px;
    border-radius: 3px;
    margin-bottom: 6px;
    background: transparent;
}

.pn-tab[aria-current="page"] {
    color: var(--azul-700);
}

.pn-tab[aria-current="page"]::before,
.pn-mais[open] > summary::before {
    background: var(--azul-600);
}

.pn-mais {
    flex: 1;
    position: relative;
}

.pn-mais > summary {
    list-style: none;
}

.pn-mais > summary::-webkit-details-marker {
    display: none;
}

.pn-mais[open] > summary {
    color: var(--azul-700);
}

.pn-mais-menu {
    position: absolute;
    bottom: 100%;
    right: var(--esp-2);
    min-width: 210px;
    background: var(--branco);
    border: 1px solid var(--cinza-200);
    border-radius: 11px;
    box-shadow: var(--sombra-flutuante);
    padding: 5px;
    margin-bottom: var(--esp-2);
}

.pn-mais-menu .pn-link {
    font-size: .85rem;
}

/* Agenda do dia. */

.ag-navegacao {
    display: flex;
    align-items: center;
    gap: 6px;
}

.ag-navegacao input[type="date"] {
    width: auto;
}

.ag-lista {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.ag-item {
    display: flex;
    gap: var(--esp-3);
    align-items: stretch;
}

/* Finalizado (concluido, cancelado, faltou) rebaixa sem desaparecer. */
.ag-item--mudo {
    opacity: .62;
}

.ag-hora {
    width: 52px;
    flex: none;
    text-align: right;
    padding-top: var(--esp-3);
    font-size: .92rem;
    font-weight: 700;
    color: var(--azul-900);
}

/* Finalizado ja e rebaixado pelo opacity do .ag-item--mudo; a cor nao precisa
   somar mais perda de contraste. */
.ag-item--mudo .ag-hora {
    color: var(--cinza-500);
}

.ag-trilho {
    width: 3px;
    flex: none;
    border-radius: 2px;
}

.ag-cartao {
    flex: 1;
    min-width: 0;
    background: var(--branco);
    border: 1px solid var(--cinza-200);
    border-radius: var(--raio-controle-lg);
    box-shadow: 0 1px 3px rgba(15, 23, 42, .05);
    padding: var(--esp-3) var(--esp-4);
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    flex-wrap: wrap;
}

.ag-cliente {
    font-size: .95rem;
    font-weight: 600;
    color: var(--cinza-800);
}

/* Telefone do cliente: dado operacional que o barbeiro precisa ler, entao tinta
   que passa no AA — nao o cinza de placeholder. */
.ag-tel {
    font-size: .78rem;
    color: var(--cinza-500);
}

.ag-servicos {
    margin-top: var(--esp-1);
    font-size: .82rem;
    color: var(--cinza-500);
}

.ag-total {
    font-weight: 600;
    color: var(--cinza-700);
}

.ag-acoes {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
    flex-wrap: wrap;
    margin-left: auto;
}

/* Chips de contagem do dia + previsao. */
.ag-resumo {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
    flex-wrap: wrap;
    margin-bottom: var(--esp-5);
}

.ag-previsao {
    margin-left: auto;
    font-size: .8rem;
    font-weight: 500;
    color: var(--cinza-500);
}

.ag-previsao strong {
    color: var(--azul-900);
}

/* Tabela do painel. Cada tabela declara suas colunas em --colunas; no mobile
   a linha empilha e o cabecalho sai (os valores viram texto corrido). */
.tb {
    background: var(--branco);
    border: 1px solid var(--cinza-200);
    border-radius: var(--raio-card);
    box-shadow: var(--sombra);
    overflow: hidden;
}

/* O `overflow: hidden` acima existe para o canto arredondado nao vazar sob as
   linhas — mas cortava o painel de confirmacao de exclusao, que e absoluto e
   desce para fora da tabela. Solta o clip SO enquanto o painel esta aberto:
   fora disso o arredondamento continua valendo. */
.tb:has(.us-remover[open]) {
    overflow: visible;
}

.tb-cabecalho,
.tb-linha {
    display: grid;
    grid-template-columns: var(--colunas);
    gap: var(--esp-3);
    align-items: center;
    padding: 13px var(--esp-4);
}

.tb-cabecalho {
    border-bottom: 1px solid var(--cinza-150);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: var(--folga-caps);
    text-transform: uppercase;
    color: var(--cinza-500);
}

.tb-linha {
    border-bottom: 1px solid var(--cinza-100);
}

.tb-linha:last-child {
    border-bottom: none;
}

/* Inativo continua visivel: inativar nao e excluir. */
.tb-linha--inativa {
    opacity: .55;
}

.tb-linha--editando {
    background: var(--azul-50);
    border-left: 3px solid var(--azul-600);
    padding-left: calc(var(--esp-4) - 3px);
}

.tb-nome {
    font-size: .92rem;
    font-weight: 600;
    color: var(--cinza-800);
}

.tb-valor {
    font-size: .88rem;
    color: var(--cinza-600);
}

.tb-valor--forte {
    font-weight: 600;
    color: var(--cinza-700);
}

.tb-acoes {
    display: flex;
    gap: var(--esp-2);
    justify-content: flex-end;
}

.tb-rodape {
    padding: var(--esp-3) var(--esp-4);
    border-top: 1px solid var(--cinza-150);
    font-size: .78rem;
    color: var(--cinza-500);
}

@media (max-width: 767.98px) {
    .tb-cabecalho {
        display: none;
    }

    .tb-linha {
        grid-template-columns: minmax(0, 1fr);
        gap: 6px;
    }

    .tb-acoes {
        justify-content: flex-start;
        margin-top: var(--esp-1);
    }

    /* O cabecalho some aqui e cada celula vira uma linha solta — um "1" ou uma data
       perdem o significado que a coluna dava no desktop. `data-rotulo` devolve esse
       significado, e SO no mobile: no desktop quem explica e o cabecalho. E opt-in por
       celula, entao as tabelas cujos valores ja se explicam ("30 min", "R$ 45,00")
       continuam iguais. */
    .tb-linha [data-rotulo]::before {
        content: attr(data-rotulo) ": ";
        color: var(--cinza-500);
    }
}

/* Tiles de destaque. Nasceram na tela de relatorios (Bloco 19) e sobreviveram a
   ela — quem os usa hoje e a ficha do cliente, que e tela de painel e por isso le a
   versao da `painel.css`, nao esta. */

.rp-destaques {
    display: grid;
    grid-template-columns: 1.4fr 1fr;
    gap: var(--esp-3);
    margin-bottom: var(--esp-3);
}

@media (max-width: 767.98px) {
    .rp-destaques {
        grid-template-columns: minmax(0, 1fr);
    }
}

.rp-tile {
    position: relative;
    overflow: hidden;
    background: var(--branco);
    border: 1px solid var(--cinza-200);
    border-radius: var(--raio-card);
    box-shadow: var(--sombra);
    padding: var(--esp-5);
}

/* Faixa de acento no tile principal. */
.rp-tile--principal::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 3px;
    background: var(--azul-600);
}

.rp-tile-rotulo {
    font-size: .76rem;
    font-weight: 600;
    letter-spacing: var(--folga-caps);
    text-transform: uppercase;
    color: var(--cinza-500);
}

/* Figuras proporcionais: tabular-nums deixa numero grande frouxo. */
.rp-tile-valor {
    margin-top: 6px;
    font-size: 2.1rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--azul-900);
}

.rp-tile--secundario .rp-tile-valor {
    font-size: 1.75rem;
}

.rp-tile-nota {
    margin-top: var(--esp-1);
    font-size: .8rem;
    line-height: 1.4;
    color: var(--cinza-500);
}

/* Aparencia: editor a esquerda, preview da pagina publica a direita. */
.ap-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 380px;
    gap: 18px;
    align-items: start;
}

@media (max-width: 991.98px) {
    .ap-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.ap-swatches {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.ap-swatch {
    width: 34px;
    height: 34px;
    padding: 0;
    border: 2.5px solid transparent;
    border-radius: var(--raio-controle);
    cursor: pointer;
}

.ap-swatch[aria-pressed="true"] {
    border-color: var(--branco);
    box-shadow: 0 0 0 2px var(--azul-900);
}

.ap-hex {
    display: flex;
    align-items: center;
    min-height: var(--toque-painel);
    padding: 0 var(--esp-3);
    border: 1.5px solid var(--cinza-200);
    border-radius: 9px;
    font-family: var(--fonte-mono);
    font-size: .82rem;
    font-weight: 500;
    color: var(--cinza-600);
}

.ap-contador {
    margin-top: 6px;
    text-align: right;
    font-family: var(--fonte-mono);
    font-size: .74rem;
    font-weight: 500;
    color: var(--cinza-500);
}

.ap-contador--cheio {
    color: var(--perigo);
}

/* 🔴 O PREVIEW DESENHADO A MAO QUE MORAVA AQUI FOI APAGADO (`.pv-card` e companhia), e ele ja
   estava morto duas vezes: o painel nao carrega esta folha (ver o cabecalho do painel.css), entao
   estas regras nunca pintaram nada — e a copia que pintava, no painel.css, tambem saiu. A previa
   de /painel/aparencia passou a ser um <iframe> com esta pagina dentro. */

/* Grade semanal do horario de funcionamento. */
.hr-linha {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    flex-wrap: wrap;
    padding: 9px 0;
    border-bottom: 1px solid var(--cinza-100);
}

.hr-linha:last-of-type {
    border-bottom: none;
}

.hr-dia {
    width: 96px;
    font-size: .88rem;
    font-weight: 600;
    color: var(--cinza-800);
    cursor: pointer;
}

.hr-linha--fechado .hr-dia {
    color: var(--cinza-500);
}

.hr-horas {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
}

/* Hora em mono: alinha os digitos entre as sete linhas. */
.hr-horas input[type="time"] {
    width: auto;
    font-family: var(--fonte-mono);
    font-weight: 500;
}

.hr-ate {
    font-size: .85rem;
    color: var(--cinza-500);
}

.hr-fechado {
    font-size: .85rem;
    font-weight: 500;
    color: var(--cinza-500);
}

/* Menu das acoes secundarias. <details> para nao depender de JS. */
.ag-menu {
    position: relative;
    flex: none;
}

.ag-menu > summary {
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--toque-painel);
    height: var(--toque-painel);
    border: 1px solid var(--cinza-200);
    border-radius: 9px;
    background: var(--branco);
    color: var(--cinza-500);
    cursor: pointer;
    list-style: none;
}

.ag-menu > summary::-webkit-details-marker {
    display: none;
}

.ag-menu > summary:hover {
    border-color: var(--cinza-400);
    color: var(--cinza-800);
}

.ag-menu-lista {
    position: absolute;
    right: 0;
    top: calc(var(--toque-painel) + 6px);
    z-index: 10;
    width: 210px;
    background: var(--branco);
    border: 1px solid var(--cinza-200);
    border-radius: 11px;
    box-shadow: var(--sombra-flutuante);
    padding: 5px;
}

.ag-menu-lista button {
    display: block;
    width: 100%;
    text-align: left;
    padding: 9px var(--esp-3);
    border: none;
    border-radius: 7px;
    background: none;
    font-size: .85rem;
    font-weight: 500;
    color: var(--cinza-800);
    cursor: pointer;
}

.ag-menu-lista button:hover {
    background: var(--cinza-50);
}

.ag-menu-lista button.ag-menu-perigo {
    color: var(--perigo);
}

.ag-menu-lista button.ag-menu-perigo:hover {
    background: #FEF2F2;
}


/* --- 8.2 Remarcar (um formulario por linha da agenda) ------------------
   Deliberadamente NAO posicionado. O .ag-cartao e flex com flex-wrap, entao
   um filho width:100% cai para a linha de baixo e empurra o cartao — o
   formulario expande dentro da propria linha. Numa agenda cheia sao N
   formularios, e popover absoluto por linha multiplicaria o risco de o
   painel escapar da tela (o bug de 181px do Bloco 13).
   ----------------------------------------------------------------------- */

.ag-remarcar {
    width: 100%;
}

.ag-remarcar > summary {
    width: fit-content;
    margin-left: auto;
    padding: 2px 6px;
    border-radius: 6px;
    font-size: .8rem;
    font-weight: 500;
    color: var(--cinza-500);
    cursor: pointer;
    list-style: none;
}

.ag-remarcar > summary::-webkit-details-marker {
    display: none;
}

.ag-remarcar > summary:hover {
    background: var(--cinza-50);
    color: var(--cinza-800);
}

.ag-remarcar-form {
    margin-top: var(--esp-3);
    padding-top: var(--esp-3);
    border-top: 1px solid var(--cinza-200);
}

.ag-remarcar-campos {
    display: grid;
    /* minmax(0,...) e nao 1fr: coluna fr tem min-width auto e um <select> com nome
       longo estoura a grade. Foi o que causou 190px de overflow no Bloco 11. */
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--esp-3);
}

.ag-remarcar-aviso {
    margin: var(--esp-3) 0 0;
    font-size: .82rem;
    color: var(--cinza-500);
}

.ag-remarcar-acoes {
    display: flex;
    justify-content: flex-end;
    margin-top: var(--esp-3);
}

@media (max-width: 560px) {
    .ag-remarcar-campos { grid-template-columns: 1fr; }
}


/* --- 9. Onboarding do painel ("vamos montar sua pagina") ---------------
   O aviso no topo da agenda e a tela /painel/comecar. Existe porque uma
   barbearia recem-criada tem pagina publica no ar RECUSANDO tudo — falta
   servico, profissional ou horario — e nada no painel dizia isso.
   ----------------------------------------------------------------------- */

.ob-aviso {
    display: flex;
    align-items: flex-start;
    gap: var(--esp-5);
    flex-wrap: wrap;
    margin-bottom: var(--esp-5);
    padding: var(--esp-5);
    border: 1px solid var(--azul-200, #BFDBFE);
    border-left: 3px solid var(--azul-600);
    border-radius: var(--raio-card);
    background: var(--azul-50, #EFF6FF);
}

.ob-aviso-texto { flex: 1; min-width: 260px; }

.ob-aviso-titulo {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    color: var(--cinza-900);
}

.ob-aviso-sub {
    margin: 4px 0 0;
    font-size: .85rem;
    color: var(--cinza-600);
}

.ob-aviso .btn { flex: none; }

.ob-passos {
    list-style: none;
    margin: var(--esp-4) 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.ob-passo {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .875rem;
    color: var(--cinza-700);
}

.ob-passo svg { flex: none; color: var(--cinza-400); }

/* Feito sai do caminho: risca, esmaece e para de convidar ao clique. */
.ob-passo--feito { color: var(--cinza-500); text-decoration: line-through; }
.ob-passo--feito svg { color: var(--sucesso, #16A34A); }

/* --- a tela --- */

.ob-intro {
    max-width: 62ch;
    margin-bottom: var(--esp-6);
    font-size: .95rem;
    line-height: 1.6;
    color: var(--cinza-600);
}

.ob-form { max-width: 780px; }

.ob-bloco {
    padding: var(--esp-5) 0;
    border-top: 1px solid var(--cinza-200);
}

.ob-bloco:first-of-type { border-top: 0; padding-top: 0; }

.ob-bloco-titulo {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    flex-wrap: wrap;
    margin: 0;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--cinza-900);
}

.ob-bloco-sub {
    max-width: 62ch;
    margin: 6px 0 0;
    font-size: .875rem;
    line-height: 1.55;
    color: var(--cinza-600);
}

.ob-opcional {
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--cinza-500);
}

.ob-bloco--opcional { background: var(--cinza-50); border-radius: var(--raio-card); padding: var(--esp-5); }

.ob-servicos {
    display: flex;
    flex-direction: column;
    gap: var(--esp-3);
    margin-top: var(--esp-4);
}

/* Grade: [checkbox] [nome flexivel] [duracao] [preco]. As duas ultimas tem
   largura fixa porque o numero e curto e alinhado entre as linhas le melhor. */
.ob-servico {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) 108px 128px;
    align-items: end;
    gap: var(--esp-3);
    padding: var(--esp-3);
    border: 1px solid var(--cinza-200);
    border-radius: var(--raio-card);
    background: var(--branco);
}

.ob-servico-incluir {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    margin: 0;
    cursor: pointer;
}

.ob-servico-incluir input { width: 18px; height: 18px; cursor: pointer; }

.ob-campo label {
    display: block;
    margin-bottom: 4px;
    font-size: .78rem;
    font-weight: 500;
    color: var(--cinza-600);
}

/* Sufixo/prefixo colado ao campo: "min" e "R$" pertencem ao numero, nao ao rotulo. */
.ob-sufixo { display: flex; align-items: center; gap: 6px; }
.ob-sufixo span { flex: none; font-size: .85rem; color: var(--cinza-500); }
.ob-sufixo .form-control { min-width: 0; }

.ob-acoes {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    flex-wrap: wrap;
    margin-top: var(--esp-6);
}

.ob-acoes .btn-confirmar { min-width: 220px; }

@media (max-width: 720px) {
    /* Empilha: em 390px quatro colunas viram quatro campos ilegiveis. */
    .ob-servico { grid-template-columns: auto minmax(0, 1fr); }
    .ob-campo--nome { grid-column: 2; }
    .ob-servico .ob-campo:not(.ob-campo--nome) { grid-column: 2; }
    .ob-acoes .btn-confirmar { flex: 1; min-width: 0; }
}
/* O campo solto ("quem atende") precisa do mesmo respiro que a lista de servicos
   ganha pelo margin-top dela. */
.ob-bloco-sub + .ob-campo { margin-top: var(--esp-4); }
/* Bloqueio que ja passou: fica na lista como historico, sem competir com o que
   ainda vale. */
.tb-linha.bl-passado { opacity: .55; }
/* --- 7.1 Encaixe pelo balcao -------------------------------------------
   Formulario de novo agendamento dentro da propria agenda: <details> nativo,
   entao o clique ABRE o painel e a agenda continua sendo o assunto da tela.
   ----------------------------------------------------------------------- */

.ag-encaixe { position: relative; }
.ag-encaixe summary { list-style: none; cursor: pointer; }
.ag-encaixe summary::-webkit-details-marker { display: none; }

.ag-encaixe-caixa {
    position: absolute;
    right: 0;
    top: calc(100% + 6px);
    z-index: 30;
    width: min(520px, calc(100vw - 32px));
    padding: var(--esp-5);
    text-align: left;
    background: var(--branco);
    border: 1px solid var(--cinza-200);
    border-radius: var(--raio-card);
    box-shadow: 0 16px 40px rgba(0, 0, 0, .18);
}

.ag-encaixe-linha {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--esp-4);
    margin-bottom: var(--esp-4);
}

.ag-campo { min-width: 0; }

.ag-encaixe-servicos {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0 0 var(--esp-4);
    padding: 0;
    border: 0;
    max-height: 190px;
    overflow-y: auto;
}

.ag-servico-opcao {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    min-height: 40px;
    padding: 0 var(--esp-2);
    border-radius: var(--esp-2);
    font-size: .9rem;
    cursor: pointer;
}

.ag-servico-opcao:hover { background: var(--cinza-50); }
.ag-servico-opcao input { flex: none; width: 16px; height: 16px; cursor: pointer; }
.ag-servico-opcao .nr-meta { margin-left: auto; white-space: nowrap; }

.ag-encaixe-nota {
    margin: 0 0 var(--esp-4);
    font-size: .78rem;
    line-height: 1.5;
    color: var(--cinza-500);
}

.ag-encaixe-aviso { margin: 0; font-size: .88rem; line-height: 1.5; color: var(--cinza-600); }

@media (max-width: 560px) {
    /* Duas colunas em 390px viram quatro campos ilegiveis. */
    .ag-encaixe-linha { grid-template-columns: 1fr; }

    /* `fixed`, e nao `left: 0`: absoluto ancora no <details>, que fica no meio do
       header flex — em 390px o painel comecava em x=213 e estourava 181px para
       fora da tela. Em tela pequena ele deixa de ser popover e vira folha. */
    .ag-encaixe-caixa {
        position: fixed;
        left: 16px;
        right: 16px;
        top: auto;
        bottom: 16px;
        width: auto;
        max-height: calc(100vh - 32px);
        overflow-y: auto;
    }
}

/* --- 7.2 Usuarios do painel (dono da acesso a recepcao) ----------------
   Formulario de criacao + lista de quem entra. A confirmacao de remocao e
   <details> nativo: sem JS, e um clique acidental so ABRE a caixa.
   ----------------------------------------------------------------------- */

.us-titulo {
    margin: 0 0 var(--esp-2);
    font-size: 1rem;
    font-weight: 600;
    color: var(--cinza-800);
}

.us-nota {
    margin: 0 0 var(--esp-4);
    font-size: .82rem;
    line-height: 1.5;
    color: var(--cinza-500);
}

.us-form {
    display: grid;
    /* minmax(0,...) e nao 1fr: coluna fr tem min-width auto e o input de e-mail
       com placeholder longo estoura a grade (mesmo bug do Bloco 11). */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) minmax(0, 1fr) auto;
    gap: var(--esp-3);
    align-items: end;
    margin-bottom: var(--esp-3);
}

/* Segunda linha do nome: e-mail e como a pessoa entra, entao fica visivel na lista. */
.us-email {
    display: block;
    margin-top: 2px;
    font-size: .8rem;
    font-weight: 400;
    color: var(--cinza-500);
    overflow-wrap: anywhere;
}

.us-voce {
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--cinza-100);
    font-size: .7rem;
    font-weight: 500;
    color: var(--cinza-600);
}

/* Papel NAO e status, entao nao usa .nr-badge: aquela escala e verde/cinza de
   ativo/inativo, e o resultado na tela era um "Dono" verde ao lado de uma
   "Recepcao" cinza — que se le como conta desativada. Os dois chips sao
   neutros; a diferenca e de PESO, nao de cor, e a informacao esta no rotulo.
   Sem ponto (o ::before do nr-badge existe para status nao depender de cor).
   Contraste medido: 6.84:1 e 11.86:1 sobre os proprios fundos. */
.us-papel {
    display: inline-flex;
    align-items: center;
    padding: 5px 11px;
    border-radius: var(--raio-pill);
    background: var(--cinza-100);
    font-size: .74rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--cinza-600);
}

.us-papel--dono {
    background: var(--cinza-200);
    color: var(--cinza-800);
}

.us-remover { position: relative; }
.us-remover > summary { list-style: none; cursor: pointer; }
.us-remover > summary::-webkit-details-marker { display: none; }

.us-remover > summary {
    padding: 2px 8px;
    border-radius: 6px;
    font-size: .8rem;
    font-weight: 500;
    color: var(--cinza-500);
}

.us-remover > summary:hover {
    background: var(--cinza-50);
    color: var(--cinza-800);
}

/* Ancorada a DIREITA para crescer para dentro da tela: a coluna de acoes fica
   colada na borda direita da tabela, e `left: 0` jogaria a caixa para fora
   (foi o bug de 181px do Bloco 13). */
.us-remover-caixa {
    position: absolute;
    right: 0;
    top: calc(100% + 6px);
    z-index: 20;
    width: 260px;
    padding: var(--esp-4);
    background: var(--branco);
    border: 1px solid var(--cinza-200);
    border-radius: var(--raio-card);
    box-shadow: var(--sombra-alta, var(--sombra));
    text-align: left;
}

.us-remover-texto {
    margin: 0 0 var(--esp-3);
    font-size: .82rem;
    line-height: 1.5;
    color: var(--cinza-600);
}

/* Variante para quando o <details> vive SOLTO num card, e nao na coluna de acoes
   de uma tabela. Duas coisas mudam, e as duas por medicao:

   1. O `summary` padrao e cinza discreto de proposito — na celula de acoes o
      contexto ja diz que aquilo e um botao. Solto num card ele vira texto inerte
      que ninguem percebe que clica.
   2. A caixa padrao e um popover ancorado a DIREITA (`position: absolute`), o que
      faz sentido colado na borda de uma tabela e nenhum sentido no meio de um card
      largo, onde ela flutua longe do gatilho.

   Usada em /painel/fidelidade e /painel/conta. */
.us-remover--bloco > summary {
    display: inline-block;
    padding: 5px 12px;
    border: 1px solid var(--cinza-300);
    color: var(--cinza-700);
}

.us-remover--bloco > summary:hover {
    border-color: #FCA5A5;
    background: #FEF2F2;
    color: #B91C1C;
}

.us-remover--bloco .us-remover-caixa {
    position: static;
    width: auto;
    max-width: 460px;
    margin-top: var(--esp-2);
    box-shadow: none;
}

@media (max-width: 767.98px) {
    .us-form { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 560px) {
    /* Em tela pequena deixa de ser popover e vira folha no rodape — mesma
       correcao do encaixe do balcao. */
    .us-remover-caixa {
        position: fixed;
        left: 16px;
        right: 16px;
        top: auto;
        bottom: 16px;
        width: auto;
    }
}


/* ═══ Bloco 48 — a página pública repaginada ════════════════════════════════════
   O problema que este bloco resolve não é "está feio": é que o chassi precisa fazer
   QUALQUER cor de marca parecer intencional, e o desenho anterior pintava o elemento
   mais largo da tela com a cor crua do lojista. Marca premium usa a cor como acento
   sobre terreno neutro; como preenchimento, ela lê como barato — e com ~2 mil cores
   diferentes no banco, "escolher uma cor bonita" não é uma opção disponível.

   Por isso a marca aparece em UM lugar: o preenchimento do CTA. O status usa cor
   semântica, e o resto é neutro.

   As classes seguem `hm-` de propósito: o termo canônico para código novo é
   PaginaPublica (ver o glossário), mas renomear prefixo CSS é churn puro. */

/* ── A fachada ──────────────────────────────────────────────────────────────── */

/* 🔴 O `[hidden]` do navegador vale `display: none` na FOLHA DO UA, entao qualquer `display`
   declarado numa classe o vence — silenciosamente. Sao exatamente os elementos que a PREVIA de
   /painel/aparencia nasce escondendo para depois revelar (capa, logo, bio e cada comodidade); sem
   estas linhas, a barbearia sem capa veria o veu escuro cobrindo o hero e as oito comodidades
   todas acesas. Na pagina anonima nenhum deles sai com `hidden` — a regra e inerte la. */
.hm-fachada-capa[hidden],
.hm-fachada-veu[hidden],
.hm-fachada-logo[hidden],
.hm-bio[hidden],
.hm-comodidades[hidden],
.hm-comodidade[hidden] {
    display: none;
}

.hm-fachada {
    position: relative;
    /* Sangra até a borda da janela: o `publico-wrap` tem padding lateral, e uma capa
       com margem dos dois lados vira "uma foto na página" em vez de uma fachada. */
    margin: calc(var(--esp-5) * -1) calc(var(--esp-4) * -1) 0;
    border-radius: 0 0 var(--raio-card-lg) var(--raio-card-lg);
    overflow: hidden;
    isolation: isolate;
}

/* Sem capa não há o que sangrar: o hero volta para dentro da coluna e a tipografia
   carrega sozinha. Nada de retângulo colorido fingindo ser foto. */
.hm-fachada:not(.hm-fachada--capa) {
    margin: 0;
    border-radius: 0;
}

.hm-fachada-capa {
    display: block;
    width: 100%;
    /* Retrato curto no celular, mais panorâmico à medida que a tela cresce: é a
       proporção que mostra uma fachada sem empurrar o CTA para fora da dobra. */
    aspect-ratio: 4 / 3;
    max-height: 340px;
    object-fit: cover;
}

/* 🔴 O VÉU é o que torna o contraste previsível. O nome sai em branco sobre uma foto
   que a plataforma nunca viu; sem um degradê opaco embaixo, uma capa clara deixaria o
   título ilegível e não há como medir isso em ~2 mil barbearias. Com ele, o pior caso
   é conhecido: o texto sempre pousa sobre pelo menos 78% de preto. */
/* 🔴 O VÉU COBRE A CAPA INTEIRA, e o topo é o ponto. Ele começava em `.04` — transparente na
   prática —, então os ~58px de cima da foto ficavam CRUS enquanto o resto da capa vinha escuro:
   dava uma borda horizontal visível no meio do banner, que lê como "a tela escurecida não cobre
   tudo". Não era ilusão: o degradê do corpo entra em `.62` de uma vez, e o salto de ~.06 para
   ~.65 acontece num pixel. Agora o véu abre em `.40` e sobe até `.68`, e quem some é o salto —
   o degradê do corpo passou a nascer em ZERO na borda de cima dele (ver logo abaixo).

   O véu continua sendo AMBIENTE e não a garantia de contraste: nenhum texto pousa aqui. Mas ele
   agora carrega piso: da metade da capa para baixo já entrega `.62` sozinho, que é exatamente o
   número que o corpo prometia. */
.hm-fachada-veu {
    position: absolute;
    inset: 0;
    background: linear-gradient(
        to bottom,
        rgba(3, 7, 18, .40) 0%,
        rgba(3, 7, 18, .50) 22%,
        rgba(3, 7, 18, .62) 46%,
        rgba(3, 7, 18, .68) 100%);
}

.hm-fachada-corpo {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 10px;
}

/* 🔴 O DEGRADÊ QUE GARANTE O CONTRASTE MORA AQUI, no próprio container do texto — e não só no
   véu acima. Duas razões, e as duas foram medidas:

   1. GARANTIA POR CONSTRUÇÃO. No véu, a opacidade sob o texto dependia de ONDE o texto caísse:
      um nome de três linhas subia para a faixa clara do degradê e o contraste caía junto. Aqui o
      degradê é do bloco de texto, então ele acompanha o texto por definição — hero mais alto ou
      nome mais longo não mudam nada.
   2. MENSURABILIDADE. O `medir-contraste.js` sobe pelos ANCESTRAIS procurando fundo; o véu é um
      IRMÃO, então ele era invisível para o medidor, que caía no fundo claro da página e acusava
      1,05 no nome. Era falso positivo — mas de um jeito que não dava para distinguir de um
      defeito real, e "o medidor não enxerga" é o começo de toda tela que passa sem ser medida.

   🔴 A ÚLTIMA PARADA É ZERO, e é ela que apaga a emenda. Antes o degradê nascia em `.62` na
   borda de cima do corpo — uma linha horizontal no meio da capa, onde a escuridão começava do
   nada. Terminando em transparente, o corpo não tem mais borda visível: ele só SOMA sobre o véu,
   que já vem escuro de cima. O piso de `.62` sob o texto não se perdeu; mudou de dono — quem o
   entrega agora é o véu, que a essa altura da capa já está em `.62`.

   O PIOR CASO, recalculado sobre uma capa BRANCA (o extremo possível) e no arranjo mais
   desfavorável (sem logo, nome de uma linha — o texto o mais alto que ele consegue ficar): véu
   `.515` compondo com corpo `.298` dá `.659`, que resulta em ~#595B63 e **6,74:1** contra o
   branco. Era 5,77:1 no desenho anterior. Como escurecer a capa só aumenta o contraste, o número
   vale para toda foto que qualquer barbearia subir. */
.hm-fachada--capa .hm-fachada-corpo {
    position: absolute;
    inset: auto 0 0;
    /* Folga no topo para o degradê ter onde desvanecer antes de encostar no texto. */
    padding: 76px var(--esp-4) var(--esp-4);
    background-image: linear-gradient(
        to top,
        rgba(3, 7, 18, .78) 0%,
        rgba(3, 7, 18, .62) 46%,
        rgba(3, 7, 18, 0) 100%);
}

.hm-fachada--capa .hm-fachada-nome,
.hm-fachada--capa .hm-fachada-status,
.hm-fachada--capa .hm-fachada-nota,
.hm-fachada--capa .hm-fachada-nota-contagem {
    color: #FFFFFF;
}

/* Sem capa: o mesmo conteúdo, nas tintas da página. */
.hm-fachada:not(.hm-fachada--capa) .hm-fachada-corpo {
    padding: var(--esp-5) 0 0;
}

/* 🔴 MEDIDO NO CELULAR: sem capa, um nome de barbearia comprido o bastante para quebrar linha
   (ex.: "Barbearia Central de Bauru e Região") ficava com a PRIMEIRA linha por baixo do ícone
   fixo "Início" (Bloco 60, `.cl-inicio`) — texto centralizado não "sabe" que há um círculo de
   44px pousado no canto. Só existe onde o ícone existe (nunca no /agendar, que optou por fora
   da barra do cliente — `body:has()` enxerga qualquer descendente, então a mesma técnica do
   padding-bottom da pílula serve aqui). Empurra o BLOCO INTEIRO para baixo do ícone, em vez de
   reservar só a coluna esquerda: funciona para qualquer nome, curto ou comprido, em qualquer
   largura de tela — um nome curto centralizado também podia, por acaso, começar bem à esquerda. */
body:has(.cl-inicio) .hm-fachada:not(.hm-fachada--capa) .hm-fachada-corpo {
    padding-top: calc(var(--esp-3) + var(--toque) + var(--esp-2));
}

/* Posição da logo move o bloco INTEIRO, e não só a imagem: logo à esquerda com nome
   centralizado fica desalinhado, e a escolha do dono é sobre a identidade. */
.hm-fachada--esquerda .hm-fachada-corpo {
    align-items: flex-start;
    text-align: left;
}

.hm-fachada-logo {
    display: block;
    width: 72px;
    height: 72px;
    border-radius: 50%;
    object-fit: cover;
    background: var(--pp-anel-logo);
    /* O anel claro separa a logo da foto atrás dela seja qual for a foto — é o mesmo
       papel do véu, no tamanho de uma borda. */
    border: 2px solid rgba(255, 255, 255, .92);
    box-shadow: 0 4px 14px rgba(3, 7, 18, .34);
}

.hm-fachada:not(.hm-fachada--capa) .hm-fachada-logo {
    border-color: var(--pp-borda);
    box-shadow: var(--sombra);
}

.hm-fachada-nome {
    /* A família escolhida pelo lojista, ou a do sistema. Só o NOME veste a display:
       corpo de texto em Anton não se lê. `clamp` porque um nome comprido em 320px não
       pode quebrar em quatro linhas dentro do véu. */
    font-family: var(--fonte-display);
    font-size: clamp(1.6rem, 7vw, 2.3rem);
    font-weight: 700;
    /* Tracking apertado: é o que separa "título grande" de "letreiro". */
    letter-spacing: -.02em;
    line-height: 1.08;
    color: var(--pp-tinta-forte);
    margin: 0;
    text-wrap: balance;
}

/* 🔴 A LINHA DOS FATOS — status e nota lado a lado, quebrando só quando não cabem.
   Não é preferência de layout: com capa, o `.hm-fachada-corpo` é `position: absolute`
   dentro de uma capa de proporção FIXA (4/3, teto de 340px), e o `.hm-fachada` tem
   `overflow: hidden`. Cada linha nova sai do orçamento de altura da capa, e quem some
   primeiro é a LOGO, no topo do bloco. Um parágrafo empilhado custaria a linha sempre;
   este arranjo custa só onde ela já não cabia.

   Sem separador de pseudo-elemento entre os dois, de propósito — ver o comentário na
   marcação (`_FachadaPublica.cshtml`) e a §3 do `scripts/medir-contraste.js`. */
.hm-fachada-fatos {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    /* Linha e coluna diferentes: apertado na vertical quando quebra, folgado na
       horizontal, que é o que separa os dois fatos sem precisar de um "·". */
    gap: var(--esp-1) var(--esp-3);
}

.hm-fachada--esquerda .hm-fachada-fatos {
    justify-content: flex-start;
}

.hm-fachada-status {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin: 0;
    font-size: .88rem;
    font-weight: 600;
    color: var(--pp-tinta);
}

/* A nota da casa no topo. Mesmo corpo e mesmo peso do status: são dois fatos do mesmo
   nível sobre a barbearia, e um deles em destaque leria como anúncio. */
.hm-fachada-nota {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin: 0;
    font-size: .88rem;
    font-weight: 600;
    color: var(--pp-tinta);
}

/* 🔴 SEM COR PRÓPRIA — `currentColor`, herdado do parágrafo. O âmbar `--av-estrela`
   mede 2,05:1 sobre o branco do tema claro (item 5 da fila do handoff), e sobre a capa
   ele pousaria numa foto que a plataforma nunca viu: o contraste passaria a depender do
   tenant, que é exatamente o que o véu existe para impedir. A estrela aqui é DESENHO —
   quem carrega a nota é o número ao lado, e a frase do `RotuloDaNota` a diz por inteiro
   para quem usa leitor de tela. */
.hm-fachada-estrela {
    font-size: 1rem;
    line-height: 1;
    /* O glifo tem folga interna própria e desalinha da linha de base do número. */
    transform: translateY(-1px);
}

.hm-fachada-nota-contagem {
    font-weight: 500;
    color: var(--pp-tinta-suave);
}

/* 🔴 O ponto é SEMÂNTICO, e não em cor de marca — há tenant com marca `#000000` no
   banco, e um ponto preto sobre o véu escuro seria invisível exatamente onde mais
   importa. A cor de marca fica reservada ao CTA. E o texto anda sempre junto: status
   nunca se diz só por cor. */
.hm-pulso {
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

.hm-pulso--aberto {
    background: #22C55E;
    box-shadow: 0 0 0 0 rgba(34, 197, 94, .6);
    animation: hm-pulsar 2.4s ease-out infinite;
}

.hm-pulso--fechado {
    background: var(--pp-tinta-suave);
    opacity: .7;
}

/* Movimento infinito é exatamente o que a preferência de menos movimento pede para
   desligar — e o texto ao lado já diz tudo o que o ponto diz. */
@media (prefers-reduced-motion: reduce) {
    .hm-pulso--aberto { animation: none; }
}

@keyframes hm-pulsar {
    70% { box-shadow: 0 0 0 7px rgba(34, 197, 94, 0); }
    100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0); }
}

/* O convite de instalar o app (PWA, ver _InstalarCliente.cshtml e pwa-instalar.js) — bloco
   ESTÁTICO no fim do conteúdo de cada página, não mais chip flutuante no canto (achado do dono,
   24/09/2026: o chip fixo nascia oculto e revelava com atraso, e o efeito percebido era "o botão
   some e reaparece"). Nasce e permanece visível: sem `opacity`/`pointer-events` condicionais,
   sem transição de entrada. Quem muda é só o RÓTULO e o que o clique faz (ver pwa-instalar.js) —
   nunca a presença do bloco. */
.pwa-instalar-rodape {
    position: relative;
    display: flex;
    justify-content: center;
    margin-top: var(--esp-6);
}

/* Esconde ANTES do primeiro paint quem já roda como app instalado — sem isso o bloco (agora
   sempre visível por padrão) apareceria por um instante dentro do próprio app antes do JS
   conseguir escondê-lo de volta (ver pwa-instalar.js, que cobre o caminho legado do iOS que este
   media query pode não pegar). */
@media (display-mode: standalone) {
    .pwa-instalar-rodape {
        display: none;
    }
}

.pwa-instalar-rodape-botao {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
    height: var(--toque);
    padding: 0 var(--esp-4);
    border: 1px solid var(--pp-borda);
    border-radius: var(--raio-pill);
    background: var(--pp-superficie);
    color: var(--pp-tinta-suave);
    font: inherit;
    font-size: .875rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color var(--mov-1), color var(--mov-1);
}

.pwa-instalar-rodape-botao:hover {
    border-color: var(--cor-marca);
    color: var(--cor-marca);
}

/* RÓTULO COM LARGURA TRAVADA abaixo de 400px — não mais um círculo mudo (achado do dono,
   22/09/2026: numa tela estreita ele não reconheceu NENHUM botão de instalar; um ícone de
   download sozinho, sem nome, não é um símbolo universalmente lido como "instalar app" — fica
   ambíguo com "baixar arquivo"/"exportar"). Continua valendo no bloco estático: o botão sozinho,
   centralizado, ainda pode ficar espremido numa tela de 360px com fonte do sistema aumentada. */
@media (max-width: 400px) {
    #pwa-instalar-rotulo {
        max-width: 160px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}

/* Popover pequeno ANCORADO no botão, ABRINDO PRA CIMA (`bottom: 100%`, e não `top` como no chip
   de canto antigo): o bloco mora perto do fim da página, e abrir para baixo empurraria o popover
   para debaixo da tabbar fixa ou para fora da viewport. */
.pwa-instalar-popover {
    position: absolute;
    bottom: calc(100% + var(--esp-2));
    left: 50%;
    transform: translateX(-50%);
    width: 240px;
    max-width: calc(100vw - var(--esp-6));
    padding: var(--esp-3);
    border: 1px solid var(--pp-borda);
    border-radius: var(--raio-card);
    background: var(--pp-superficie);
    color: var(--pp-tinta);
    box-shadow: var(--sombra-flutuante);
    font-size: .875rem;
}

.pwa-instalar-popover ol {
    margin: 0 0 var(--esp-3);
    padding-left: 1.1em;
}

.pwa-instalar-popover li + li {
    margin-top: var(--esp-1);
}

/* O texto dos modos "manual" e "já instalado" — mesmo respiro do <ol> de passos ao lado (nunca
   mais de um visível ao mesmo tempo, ver pwa-instalar.js), só que sem lista. */
.pwa-instalar-popover-texto {
    margin: 0 0 var(--esp-3);
    line-height: 1.45;
}

.pwa-instalar-popover-fechar {
    width: 100%;
    height: 36px;
    border: none;
    border-radius: var(--raio-pill);
    background: var(--cor-marca);
    color: var(--tinta-sobre-marca);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.hm-bio {
    text-align: center;
    color: var(--pp-tinta-suave);
    font-size: .95rem;
    line-height: 1.5;
    margin: var(--esp-4) auto 0;
    max-width: 420px;
}

.hm-fachada--esquerda + .hm-bio {
    text-align: left;
    margin-left: 0;
}

/* ── O CTA ──────────────────────────────────────────────────────────────────── */

/* Gruda no rodapé da janela ao rolar: alcance do polegar, que é o gesto de app que
   esta página não tinha. `sticky` puro — sem JS, sem observer — e ele para sozinho no
   fim do conteúdo, porque o contexto de rolagem é o próprio documento. */
.hm-acao {
    position: sticky;
    bottom: var(--esp-4);
    z-index: 5;
    margin-top: var(--esp-5);
}

.hm-cta {
    display: block;
    width: 100%;
    text-align: center;
    padding: 14px 20px;
    font-size: 1rem;
    font-weight: 700;
    border-radius: var(--raio-card);
    /* A ÚNICA aparição da cor de marca como preenchimento na página. A elevação é o
       que a separa do fundo sem precisar de mais saturação. */
    box-shadow: 0 4px 14px color-mix(in oklab, var(--cor-marca) 26%, transparent);
}

/* Folga no fim da página para o CTA grudado nunca cobrir o link de privacidade de
   forma permanente. */
.hm-privacidade {
    margin-top: var(--esp-6);
}

/* O canal do titular e obrigacao legal, nao chamada: em cor de marca e sublinhado ele competia
   com o unico botao da pagina. Continua link, continua alcancavel por teclado, e o sublinhado
   volta no hover e no foco — o que se tira e o peso em repouso. */
.hm-privacidade a {
    color: var(--pp-tinta-suave);
    text-decoration: none;
    font-size: .82rem;
}

.hm-privacidade a:hover,
.hm-privacidade a:focus-visible {
    color: var(--pp-tinta);
    text-decoration: underline;
}

/* ── Comodidades ────────────────────────────────────────────────────────────── */

/* 🔴 AS REGRAS DA LINHA ROLANTE FORAM APAGADAS DAQUI, e a remocao e o conserto — nao faxina.
   Era `display:flex` + `flex-wrap:nowrap` + `overflow-x:auto` + um `@supports` com mascara de
   esmaecimento na ponta. O desenho caiu por medida, nao por gosto: em teste de usabilidade a
   pessoa NAO percebe que ha o que arrastar e simplesmente pula o conteudo (Baymard registrou "eu
   nao vi isso"; a NN/g mediu que ate setas proeminentes sao ignoradas). Metade das comodidades
   nascia fora da tela — e o que fica fora da tela nao informa ninguem.

   🔴 APAGADAS, e nao sobrescritas no fim da folha, e este arquivo ja pagou por saber a diferenca:
   duas regras de MESMA especificidade se resolvem propriedade a propriedade, e a de baixo so vence
   o que ela DECLARA. Sobreviveria aqui exatamente o que a grade nao declara — foi assim que um
   `justify-content: center` orfao sobreviveu a uma repaginacao inteira e deixou a primeira
   comodidade em x = -52px, inalcancavel (ver o registro por volta da secao de horarios).

   O desenho novo — grade que quebra linha — mora no bloco do FIM da folha, com o cartao de Wi-Fi
   que nasceu junto. */

/* ── O carrossel ────────────────────────────────────────────────────────────── */

/* 🔴 BLOCO ÚNICO, e antes eram DOIS. Havia um `.ga-*` na §6.2.1 (Bloco 41b, o carrossel de
   rolagem nativa) e este aqui, escrito depois para o desenho novo. O segundo vencia só nas
   propriedades que declarava, e as do primeiro seguiam vivas por baixo sem aparecer em lugar
   nenhum: `flex: 0 0 auto`, `list-style`, `display: flex`, `gap`, `overflow-x` e
   `overscroll-behavior-x` continuavam mandando de lá, enquanto `aspect-ratio: 1/1`,
   `width: min(62%, 215px)`, `scroll-snap-align: start`, a borda e o `border-radius:
   var(--raio-card)` eram letra morta que ainda parecia regra ao ler o arquivo. É a receita
   exata do defeito que esta folha já autopsiou uma vez: quem fosse mexer teria de saber, de
   cabeça, qual das duas cópias estava lendo.

   ABSORVIDO do bloco antigo e ainda valendo: `list-style: none`, a margem de topo,
   `display: flex`, `gap`, `overflow-x: auto`, `overscroll-behavior-x: contain`,
   `scroll-snap-type`, o `:focus-visible` do scroller, `flex: 0 0 auto` no slide e
   `display/width/height/object-fit` na imagem.

   DESCARTADO por já estar sobrescrito: a linha de topo e o `padding-top` da seção, o
   `padding-bottom` do scroller, o quadrado 1:1, a largura de 215px, o alinhamento `start`, a
   borda e o raio pequeno da foto.

   O `aspect-ratio` + `object-fit: cover` continuam sendo o que substitui redimensionar no
   servidor — decisão travada no 41b: o servidor NUNCA decodifica imagem (vetor de RCE e de
   decompression bomb). Foto de proporção estranha vira recorte, e não layout torto. */

.ga-vitrine {
    margin-top: var(--esp-6);

    /* 🔴 AS DUAS MEDIDAS MORAM NA SEÇÃO, e não na lista, porque o CONTADOR precisa delas e
       ele é IRMÃO da lista — custom property só desce por herança. Declaradas na lista, o
       contador ancoraria na borda da COLUNA em vez da borda da foto, e a pílula flutuaria no
       vazio ao lado dela (a coluna é mais larga que o slide em toda tela acima de ~440px). */
    --ga-slide: min(82vw, 400px);
    --ga-folga-topo: .5rem;
}

/* O quadro existe só para dar contexto de posicionamento ao contador, e não recorta nada: o
   carrossel sangra para fora dele nos dois lados, e no modo palco quem recorta o leque já é o
   `overflow: hidden` da própria lista. */
.ga-quadro {
    position: relative;
}

/* 🔴 O CONTADOR NASCE `hidden` NO HTML e é o script que o revela — sem JS não há índice para
   contar (a rolagem nativa não numera nada), e um "1 / 7" parado enquanto o dedo arrasta mente
   sobre a posição. Mesma regra da barra de progresso, que não é desenhada onde
   `animation-timeline` não existe.

   O véu escuro atrás não é estética: o número sai em branco sobre uma foto que o lojista
   escolheu e que a plataforma nunca viu — sem fundo próprio, o contraste dependeria da foto, e
   não há como medir isso em ~2 mil barbearias. `tabular-nums` para a pílula não mudar de
   largura ao passar de 9 para 10. */
.ga-contador {
    position: absolute;
    /* Acima do cartão da frente, que o `galeria-publica.js` deixa em `z-index: 4`. */
    z-index: 5;
    /* 🔴 Ancorado na FOTO, e não na coluna. A foto da frente é centrada no quadro com
       `var(--ga-slide)` de largura, então a borda direita dela está a `50% - --ga-slide/2` da
       borda direita do quadro — sem esta conta a pílula encostaria na margem da página e, no
       desktop (coluna de 520px, foto de 400px), ficaria 60px FORA da imagem, sobre o fundo.
       O topo segue a mesma lógica: a lista desce `--ga-folga-topo` antes de a foto começar. */
    top: calc(var(--ga-folga-topo) + var(--esp-3));
    right: calc(50% - var(--ga-slide) / 2 + var(--esp-3));
    margin: 0;
    padding: 4px 10px;
    border-radius: var(--raio-pill);
    background: rgb(3 7 18 / .62);
    color: #fff;
    font-size: .78rem;
    font-weight: 600;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
    /* O contador fica SOBRE a foto, e a foto é onde se arrasta o palco. Sem isto a pílula
       comeria o `pointerdown` no canto superior direito e o gesto morreria ali. */
    pointer-events: none;
}

/* A barra de rolagem NATIVA aparecia crua na tela e era o detalhe que mais entregava
   "não terminado". Ela sai; o espiar da próxima foto continua sendo a afordância, e a
   barra de progresso abaixo passa a dizer onde se está. */
.ga-carrossel {
    /* A largura do slide vira VARIÁVEL porque a folga lateral depende dela: para a primeira e a
       última foto conseguirem chegar ao centro, o scroller precisa de meia tela sobrando de cada
       lado. Sem essa folga, `scroll-snap-align: center` clampa nos extremos e as duas pontas
       nunca centralizam — o carrossel "pula" a primeira e a última.

       🔴 82vw / 400px, e não os 70vw / 260px de antes. A queixa do dono foi "está muito
       simples a mostragem", comparando com um rival cuja foto ocupa a largura toda. 82vw
       mantém o espiar das vizinhas — que é o sinal de que há mais fotos, e a razão pela qual
       isto não vira 100vw — e o teto de 400px é o que a coluna de 520px comporta com a sangria
       dos dois lados. A conta de requisições não muda: continuam ~3 fotos com caixa na primeira
       visita, o resto por `loading="lazy"`. */
    list-style: none;
    /* A folga de topo do bloco antigo, mais a sangria para os DOIS lados: a foto vizinha some
       no corte da tela em vez de terminar numa margem, que é o que faz a faixa parecer
       contínua. */
    margin: var(--ga-folga-topo) calc(var(--esp-4) * -1) 0;
    display: flex;
    gap: var(--esp-3);
    overflow-x: auto;
    /* Rolagem horizontal com dedo não pode sequestrar a rolagem vertical da página quando o
       carrossel chega ao fim. */
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    padding-block: 0;
    /* 🔴 `50%` em padding resolve contra o PAI, não contra o próprio elemento — e o scroller é o
       pai mais as duas sangrias, daí o `+ var(--esp-4)`. Escrito assim a conta fecha igual no
       celular e no desktop com `max-width`, sem depender de `vw` (que conta a barra de rolagem e
       ignora a coluna). Resultado: `scrollLeft = 0` centraliza a primeira foto, e o passo entre
       centros é exatamente a largura do slide mais o `gap` — é dessa igualdade que o
       `galeria-publica.js` depende para navegar por índice. */
    padding-inline: calc(50% + var(--esp-4) - var(--ga-slide) / 2);
}

.ga-carrossel::-webkit-scrollbar { display: none; }

.ga-carrossel:focus-visible {
    outline: 2px solid var(--cor-marca-acento);
    outline-offset: 2px;
}

/* CENTRO, e não `start`: o pedido do dono é uma foto sempre no meio da tela, com as vizinhas
   espiando dos dois lados. `start` alinhava tudo à esquerda e a faixa lia como uma lista. */
.ga-slide {
    scroll-snap-align: center;
    /* `flex: 0 0 auto` para o item não ser espremido pelo container: sem isto o flex encolheria
       as oito fotos até caberem, e o carrossel não rolaria. */
    flex: 0 0 auto;
    width: var(--ga-slide);
}

.ga-slide img {
    display: block;
    width: 100%;
    height: auto;
    /* Retrato, e não quadrado: corte de cabelo é uma pessoa em pé. O quadrado cortava
       cabeça ou ombros em toda foto vertical. */
    aspect-ratio: 3 / 4;
    object-fit: cover;
    border-radius: var(--raio-card-lg);
    background: var(--pp-superficie-2);
}

/* Sem suporte a `animation-timeline`, a barra não é desenhada — melhor nenhum
   indicador que um indicador que mente sobre a posição. */
.ga-progresso { display: none; }

/* ── O modo PALCO: uma foto na frente, as outras em leque atrás, dos DOIS lados ──────────────
   🔴 É UMA MELHORIA PROGRESSIVA, e a ordem importa: o HTML nasce como o carrossel de rolagem
   nativa acima, e o `galeria-publica.js` promove a lista a palco marcando `data-palco` na seção.
   Sem JS a galeria continua sendo uma faixa que arrasta com o dedo, com todas as fotos visíveis —
   que é o oposto do que renderizar o palco direto no servidor faria (uma foto visível e o resto
   empilhado atrás, dependendo de script para existir). Mesma doutrina do balão do Bloco 49.

   A profundidade é `translateZ` + `rotateY` sob `perspective`, e não `scale` sozinho: o leque
   inclina as laterais PARA DENTRO da pilha; encolher só achata. Copiado do `.lp-carrossel` da
   landing de propósito — é a mesma ideia visual, e duas gramáticas para o mesmo gesto seriam
   duas coisas para manter. */
.ga-vitrine[data-palco] .ga-carrossel {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    /* A altura tem de ser fixa porque os filhos saem do fluxo. Vem da própria largura do slide
       com o `aspect-ratio: 3/4` das fotos — assim o palco acompanha a tela sem número mágico. */
    height: calc(var(--ga-slide) * 4 / 3);
    padding-inline: 0;
    /* Corta o leque nas bordas: sem isto os cartões girados estouram a largura da página. */
    overflow: hidden;
    perspective: 1400px;
    /* O arraste horizontal é nosso; o vertical continua sendo da página. */
    touch-action: pan-y;
    cursor: grab;
    scroll-snap-type: none;
}

.ga-vitrine[data-palco] .ga-carrossel:active { cursor: grabbing; }

/* ⚠️ O marcador mora na SEÇÃO, e não na lista — é ela que o script promove, porque a barra de
   progresso a ser escondida é irmã da lista, não filha. Escrever `.ga-carrossel[data-palco]` aqui
   compila, não casa com nada e falha em SILÊNCIO: os cartões continuam em linha e só os estilos
   inline do script pegam, jogando a pilha inteira para a direita. Aconteceu; medido e corrigido. */
.ga-vitrine[data-palco] .ga-slide {
    position: absolute;
    transition: transform .55s cubic-bezier(.2, .7, .3, 1), opacity .55s ease, filter .55s ease;
    transform-style: preserve-3d;
}

@media (prefers-reduced-motion: reduce) {
    .ga-vitrine[data-palco] .ga-slide { transition: none; }
}

/* A barra de progresso é dirigida pela ROLAGEM, e no palco não há rolagem: ela ficaria parada
   mentindo uma posição. Quem diz onde se está passam a ser os pontos, que o script cria. */
.ga-vitrine[data-palco] .ga-progresso { display: none; }

.ga-pontos {
    display: flex;
    align-items: center;
    gap: 2px;
}

/* 24px de alvo, e não os 6px do ponto desenhado: WCAG 2.5.8 (Target Size, AA) pede 24×24 CSS px.
   O ponto é o `::before`; o botão é a área de toque em volta dele. */
.ga-ponto {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    cursor: pointer;
}

.ga-ponto::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--pp-divisor);
    transition: background .2s ease, transform .2s ease;
}

.ga-ponto[aria-current="true"]::before {
    background: var(--pp-tinta-suave);
    transform: scale(1.5);
}

.ga-ponto:focus-visible {
    outline: 2px solid var(--cor-marca-acento);
    outline-offset: -1px;
}

/* A linha de rodapé do carrossel: a barra de progresso e o botão de pausa lado a lado. Ela existe
   MESMO onde a barra não é desenhada (navegador sem `animation-timeline`), porque o botão precisa
   de casa própria — e ele não é opcional. Ver `galeria-publica.js`. */
.ga-rodape {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--esp-3);
    margin-top: var(--esp-3);
    min-height: 26px;
}

/* 🔴 O BOTÃO NASCE NO JS, e por isso não há regra que o esconda: sem script nada se move, e um
   controle de pausa sobre uma faixa parada é um controle que mente. Ele fica monocromático como
   as comodidades — a cor de marca segue reservada ao CTA. */
.ga-controle {
    display: inline-flex;
    align-items: center;
    padding: 4px 12px;
    border: 1px solid var(--pp-divisor);
    border-radius: var(--raio-pill);
    background: transparent;
    color: var(--pp-tinta-suave);
    font-size: .72rem;
    font-weight: 500;
    line-height: 1.2;
    cursor: pointer;
}

.ga-controle:hover { color: var(--pp-tinta); }

.ga-controle:focus-visible {
    outline: 2px solid var(--cor-marca-acento);
    outline-offset: 2px;
}

/* 🔴 A ANIMAÇÃO É DIRIGIDA PELA ROLAGEM, com zero JavaScript. Não é enfeite gratuito:
   a CSP deste projeto não aceita handler inline e o fluxo público é sem-JS por
   decisão, então a alternativa scriptada não estava disponível. `view()` mede a
   posição do próprio slide dentro do scroller; onde o navegador não suporta, o
   `@supports` não aplica nada e a faixa continua exatamente como está. */
@supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
        /* 🔴 `:not([data-palco])` NÃO é zelo: `view()` precisa de um scroller, e no modo palco não
           há rolagem nenhuma. Sem a exclusão a animação congelaria no quadro inicial — todas as
           fotos em `opacity: .42; scale(.88)`, inclusive a da frente. Falha muda e feia. */
        .ga-vitrine:not([data-palco]) .ga-slide img {
            /* O intervalo agora é o `cover` inteiro (entrada → saída), e não só a entrada: é o que
               transforma "as bordas desbotam" em "a do centro é a protagonista". 50% da linha do
               tempo é, por definição, o momento em que o slide está centralizado no scroller. */
            animation: ga-centro linear both;
            animation-timeline: view(inline);
        }
    }
}

@supports (animation-timeline: scroll()) and (timeline-scope: --ga-rolagem) {
    /* 🔴 `scroll(nearest inline)` NAO servia aqui, e o print foi quem mostrou: a barra e IRMA do
       carrossel, nao descendente dele, entao "nearest" subia ate o documento — que nao rola na
       horizontal. Sem linha do tempo, a animacao fica inerte e o elemento mantem o estado base:
       uma barra CHEIA, que na tela lia como um filete divisor grosso em vez de progresso.

       A correcao e nomear a linha do tempo no scroller e emprestá-la ao irmao pelo
       `timeline-scope` do pai comum. E por isso o `@supports` testa as DUAS features: sem
       `timeline-scope` o nome nao atravessa e voltariamos a barra cheia, agora em silencio. */
    .ga-vitrine { timeline-scope: --ga-rolagem; }

    .ga-carrossel { scroll-timeline: --ga-rolagem inline; }

    .ga-progresso {
        display: block;
        height: 2px;
        width: 64px;
        /* A margem saiu: quem posiciona agora é o `.ga-rodape`, que segura a barra e o botão na
           mesma linha. Mantê-la aqui empurraria a barra para baixo do botão. */
        margin: 0;
        border-radius: var(--raio-pill);
        background: var(--pp-divisor);
        overflow: hidden;
    }

    .ga-progresso-barra {
        display: block;
        height: 100%;
        width: 100%;
        border-radius: inherit;
        background: var(--pp-tinta-suave);
        transform-origin: left center;
        animation: ga-progredir linear both;
        animation-timeline: --ga-rolagem;
    }
}

/* O PLATÔ entre 42% e 58% é o que faz a foto do centro ASSENTAR. Sem ele, o pico é um instante
   só e a faixa vira um aquário — o slide central nunca fica parado tempo suficiente para ser
   olhado, que é justamente o que "uma imagem sempre ao centro" quer dizer. */
@keyframes ga-centro {
    0%, 100% { opacity: .42; transform: scale(.88); }
    42%, 58% { opacity: 1; transform: scale(1); }
}

@keyframes ga-progredir {
    from { transform: scaleX(.18); }
    to { transform: scaleX(1); }
}

/* ── Horário e contato ──────────────────────────────────────────────────────── */

.hm-info {
    margin-top: var(--esp-6);
}

/* ═══ Bloco 49 — a foto no agendamento e o balão de produtos ════════════════════ */

/* 🔴 MINIATURA, e não banner. A prioridade é o celular, e a etapa é uma LISTA de escolha: uma foto
   grande por serviço empurraria a terceira opção para fora da dobra e transformaria escolher em
   rolar. 44px é a altura da própria linha — a foto entra sem mudar o ritmo dela. */
.fl-servico-foto {
    flex: none;
    width: 44px;
    height: 44px;
    /* 🔴 Era `var(--raio-sm, 8px)`, e `--raio-sm` NUNCA EXISTIU nesta folha — ele mora no
       `painel.css`, que é a folha do DONO e não desce na página pública. É assim que o defeito
       nasceu: o token veio junto com a linha, de uma folha onde ele resolve. O efeito não era
       visível numa tela só: a miniatura caía sempre nos 8px do fallback e IGNORAVA o preset de
       cantos do dono (Reto / Suave / Pílula), enquanto a mesma foto, na grade, obedecia — porque
       lá o raio vem de `--raio-card`, que o preset reescreve. Duas caixas da mesma tela com
       cantos diferentes, e nenhuma delas escolhida por ninguém.

       `--raio-controle` é o token certo aqui: é o que veste os controles de linha (o mesmo que a
       `.nr-opcao` desta lista usa em `--raio-controle-lg`), e ele muda com o preset. */
    border-radius: var(--raio-controle);
    object-fit: cover;
    background: var(--pp-superficie-2);
}

/* ── O balão de produtos ────────────────────────────────────────────────────── */

/* O <dialog> nativo. O fundo era o BRANCO DO NAVEGADOR (o UA pinta `dialog`), o que no tema
   escuro deixaria a lista clara sobre papel branco — mesma armadilha que o `.nr-dialogo` já
   documentava. */
.vt-balao {
    position: fixed;
    /* Colado no rodapé no celular, centrado a partir de 560px: é a diferença entre um balão que
       o polegar alcança e um que obriga a esticar a mão até o meio da tela. */
    inset: auto 0 0;
    width: 100%;
    max-width: none;
    max-height: 82svh;
    margin: 0;
    padding: var(--esp-5) var(--esp-4) var(--esp-5);
    border: none;
    border-radius: var(--raio-card-lg) var(--raio-card-lg) 0 0;
    background: var(--pp-superficie);
    color: var(--pp-tinta);
    overflow-y: auto;
    /* Rolar a lista do balão não pode arrastar a página atrás dele. */
    overscroll-behavior: contain;
    box-shadow: 0 -12px 40px rgba(3, 7, 18, .28);
}

.vt-balao::backdrop {
    background: rgba(3, 7, 18, .58);
}

@media (min-width: 560px) {
    .vt-balao {
        inset: 0;
        width: min(480px, calc(100% - 2 * var(--esp-4)));
        max-height: 78svh;
        margin: auto;
        border-radius: var(--raio-card-lg);
    }
}

/* Grudado no topo ao rolar a lista: com muitos produtos, o botão de fechar sumiria para cima e a
   única saída do balão ficaria fora de alcance. */
.vt-balao-fechar {
    position: sticky;
    top: calc(var(--esp-5) * -1);
    z-index: 1;
    display: block;
    margin-left: auto;
    /* 44px é o alvo mínimo de toque da casa. */
    width: 44px;
    height: 44px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: var(--pp-superficie-2);
    color: var(--pp-tinta);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
}

.vt-balao-fechar:hover { background: var(--pp-borda); }

.vt-balao .vt-produtos { margin-top: 0; }

/* ── A lista de produtos ────────────────────────────────────────────────────── */

/* Sem a linha de topo: ela separava a vitrine do resto da confirmação, e dentro do balão ela
   ficaria pendurada logo abaixo do botão de fechar, sem nada para separar. */
.vt-produtos {
    border-top: none;
    padding-top: 0;
    margin-top: var(--esp-5);
}

.vt-titulo {
    font-family: var(--fonte-display);
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: -.01em;
    color: var(--pp-tinta-forte);
    margin: 0 0 var(--esp-3);
}

/* A foto obriga a trocar o alinhamento: com `baseline` (o de antes, sem foto) a miniatura de 64px
   pendura o nome pela primeira linha de texto e a linha inteira desalinha. E o texto precisa de
   `flex: 1` para o preço continuar encostado na direita agora que há três colunas e não duas. */
.vt-item {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: var(--esp-3);
}

.vt-item-texto {
    flex: 1;
    min-width: 0;
}

.vt-item-preco {
    flex: none;
    white-space: nowrap;
}

.vt-item-foto {
    flex: none;
    width: 64px;
    height: 64px;
    border-radius: var(--raio-card);
    object-fit: cover;
    background: var(--pp-superficie-2);
}

/* O lugar da foto continua ocupado quando ela não existe: sem isso, uma lista com dois produtos
   com foto e um sem vira três larguras de texto diferentes, e a coluna de preço deixa de alinhar. */
.vt-item-foto--vazia {
    display: block;
    border: 1px dashed var(--pp-divisor);
    background: transparent;
}

/* ══════════════════════════════════════════════════════════════════════════════
   FOTO DO PROFISSIONAL — vitrine e escolha no wizard (onda 1, frente 2)

   UM bloco, no FIM do arquivo, sem editar nada acima: outra worktree mexe nesta
   mesma folha na mesma onda, e o merge tem de ser trivial.

   🔴 GRADE QUE QUEBRA LINHA, NUNCA CARROSSEL. As duas metades da decisao sao
   medidas, nao gosto: (1) em carrossel no celular a maioria das pessoas para no
   TERCEIRO item (NN/g) — o quarto barbeiro de uma equipe de seis simplesmente nao
   e visto; (2) truncar nome proprio e PIOR que nao ter nome, porque dois
   "Guilherme ..." viram itens indistinguiveis (Baymard). A grade resolve as duas:
   tudo aparece de uma vez, e o nome vai inteiro em ate duas linhas.

   `auto-fill` com `minmax(6.5rem, 1fr)`: a coluna nasce do espaco disponivel, e
   nao de um numero de colunas escolhido a mao — 320px da duas, um tablet da cinco,
   e nenhuma media query precisa saber disso.
   ══════════════════════════════════════════════════════════════════════════════ */

.eq-secao {
    margin-top: var(--esp-6);
}

.eq-grade {
    display: grid;
    /* minmax(6.5rem, 1fr) e nao `1fr` solto: coluna `fr` tem min-width auto e nao
       encolhe abaixo do conteudo — um nome longo estouraria a grade a 320px. */
    grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
    gap: .75rem;
    margin: var(--esp-3) 0 0;
    padding: 0;
    list-style: none;
}

/* Cartao RETANGULAR com avatar circular dentro: o circulo diz "pessoa", e o
   retangulo e o que da ao nome duas linhas de largura previsivel. Um cartao
   circular obrigaria o nome a caber num arco. */
.eq-cartao {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--esp-2);
    padding: var(--esp-3) var(--esp-2);
    border: 1px solid var(--pp-borda);
    border-radius: var(--raio-card);
    background: var(--pp-superficie);
    text-align: center;
}

.eq-foto {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    border-radius: 50%;
    /* O servidor NUNCA redimensiona imagem: o enquadramento e problema da
       apresentacao, e `cover` e o que impede um retrato 3:4 de virar oval. */
    object-fit: cover;
    background: var(--pp-superficie-2);
}

/* O placeholder e o MESMO avatar de iniciais que a tela ja usa, so que no tamanho
   da foto: sem foto o cartao nao pode ficar PIOR do que estava antes desta frente. */
.eq-iniciais {
    background: var(--azul-50);
    color: var(--azul-700);
    font-size: 1.35rem;
    font-weight: 700;
}

/* 🔴 NOME COMPLETO, em ate duas linhas. `line-clamp` corta na terceira, que so
   acontece com nome muito longo — e ai o corte cai depois de ja haver o bastante
   para distinguir duas pessoas, que e o defeito que o truncamento em UMA linha
   produz. `break-word` para um sobrenome enorme nao estourar a coluna. */
.eq-nome {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    font-size: .85rem;
    font-weight: 600;
    line-height: 1.25;
    color: var(--pp-tinta);
    overflow-wrap: break-word;
}

/* ── A MESMA grade na etapa "com quem voce quer cortar?" ─────────────────────
   Reusa `.nr-opcao` (borda, fundo, foco, marcador) e so troca a caixa de linha
   para celula — o mesmo caminho que `.fl-opcoes--grade` ja abriu para servicos. */

.fl-opcoes--equipe {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
    gap: .75rem;
}

.fl-opcoes--equipe .eq-opcao {
    position: relative;
    flex-direction: column;
    align-items: center;
    gap: var(--esp-2);
    padding: var(--esp-3) var(--esp-2);
    text-align: center;
    /* 🔴 2px, e nao os 1.5px da lista: a borda e UM dos TRES sinais de selecao
       (borda + icone de check + fundo), e a WCAG 1.4.1 e sobre nao depender de cor
       — uma borda que so muda de MATIZ, na mesma espessura, e cor disfarcada de
       forma. Nasce 2px para o cartao nao mudar de tamanho ao ser escolhido. */
    border-width: 2px;
}

/* O alvo de toque e o cartao inteiro (~104x150), muito acima do minimo de 44x44 —
   o `min-height` so garante isso quando o nome cabe numa linha so. */
.fl-opcoes--equipe .eq-opcao { min-height: 44px; }

/* O marcador sai do fluxo e vai para o canto: no rodape da celula ele empurraria
   o nome e faria celulas da mesma linha ficarem de alturas diferentes. */
.fl-opcoes--equipe .nr-marcador {
    position: absolute;
    top: var(--esp-2);
    right: var(--esp-2);
}

/* O nome dentro da opcao segue a mesma regra de duas linhas da vitrine — sem isto
   ele herdaria o `display: block` de `.nr-opcao-nome` e o clamp nao valeria. */
.fl-opcoes--equipe .eq-nome {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}
/* ═══════════════════════════════════════════════════════════════════════════════
   AVALIAÇÕES — a frente das notas de atendimento (fase 28)

   🔴 BLOCO ACRESCENTADO NO FIM, E NADA ACIMA FOI TOCADO. Nasceu numa worktree
   paralela a outras duas frentes que mexem nesta mesma folha; editar um bloco
   existente transformaria o merge num conflito de resolução manual. Se alguma
   regra daqui tiver de mudar um seletor de cima, faça isso num commit próprio,
   depois do merge — nunca dentro deste bloco.

   Cobre três telas: o formulário público de avaliar (`/avaliar/{token}`), o bloco
   de reputação da vitrine (`Home/Tenant`) e a moderação do painel
   (`/painel/avaliacoes`).
   ═══════════════════════════════════════════════════════════════════════════════ */

:root {
    /* 🔴 A estrela NÃO é cor de marca, e a razão é a mesma do ponto verde de "aberto
       agora": a marca é livre e o banco já tem tenant com #000000. Estrela preta é
       estrela apagada — a nota da barbearia sumiria justamente onde ela vale mais.
       Âmbar fixo, como o resto da semântica da folha, que nunca deriva da marca. */
    --av-estrela: #F59E0B;
    --av-estrela-vazia: var(--pp-borda);
}

[data-tema-publico="escuro"] {
    /* O âmbar do tema claro escurece demais contra #172033; este clareia até ficar
       visível sobre a superfície escura sem virar amarelo de aviso. */
    --av-estrela: #FBBF24;
    --av-estrela-vazia: var(--pp-borda-forte);
}

/* ── O formulário público ──────────────────────────────────────────────────── */

.av-servicos {
    list-style: none;
    padding: 0;
    margin: var(--esp-3) 0 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--esp-2);
}

.av-servicos li {
    padding: 4px 10px;
    border: 1px solid var(--pp-borda);
    border-radius: 999px;
    font-size: .82rem;
    color: var(--pp-tinta-suave);
}

.av-estrelas-campo {
    border: 0;
    padding: 0;
    margin: 0 0 var(--esp-5);
}

.av-estrelas {
    display: flex;
    gap: var(--esp-2);
    margin-top: var(--esp-2);
}

/* O radio some da tela mas NÃO do fluxo de acessibilidade: `display:none` o tiraria
   da navegação por teclado e do leitor de tela, e a tela viraria cinco caracteres
   decorativos que ninguém consegue marcar sem mouse. */
.av-estrela-radio {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.av-estrela {
    cursor: pointer;
    font-size: 2.4rem;
    line-height: 1;
    color: var(--av-estrela-vazia);
    transition: color var(--mov-1), transform var(--mov-1);
    /* Alvo de toque: a estrela é o único controle desta tela, e ela é usada de pé,
       no celular, na porta da barbearia. */
    min-width: 44px;
    text-align: center;
}

/* 🔴 O PREENCHIMENTO INTEIRO SEM UMA LINHA DE JS, e sem o `row-reverse` do truque
   clássico: `label:has(~ input:checked)` alcança as estrelas ANTERIORES à marcada,
   que é exatamente o que "4 de 5" significa. Por isso o HTML pode ficar em ordem
   crescente — e a ordem do DOM volta a ser a que o teclado e o leitor de tela
   percorrem. */
.av-estrela-radio:checked + .av-estrela,
.av-estrela:has(~ .av-estrela-radio:checked) {
    color: var(--av-estrela);
}

/* O foco tem de aparecer no LABEL, porque o input está escondido — sem isto, quem
   navega por teclado marca estrelas às cegas. */
.av-estrela-radio:focus-visible + .av-estrela {
    outline: 2px solid var(--cor-marca);
    outline-offset: 2px;
    border-radius: 4px;
}

.av-estrela-radio:checked + .av-estrela {
    transform: scale(1.04);
}

.av-sem-nota {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
    margin-top: var(--esp-3);
    font-size: .85rem;
    color: var(--pp-tinta-suave);
    cursor: pointer;
}

/* ── O bloco de reputação da vitrine ───────────────────────────────────────── */

.av-vitrine {
    margin-top: var(--esp-6);
    text-align: left;
}

.av-nota {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--esp-3);
    margin-top: var(--esp-2);
}

.av-nota-numero {
    font-family: var(--fonte-display);
    font-size: 2.2rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -.02em;
    color: var(--pp-tinta-forte);
    margin: 0;
}

.av-nota-estrelas {
    margin: 0;
    font-size: 1.1rem;
    letter-spacing: 1px;
    color: var(--av-estrela-vazia);
}

.av-estrela-vitrine.is-cheia {
    color: var(--av-estrela);
}

/* Meia estrela de verdade: âmbar até a metade, vazio depois. `background-clip: text`
   sobre um gradiente de corte duro — sem SVG, sem segundo caractere sobreposto. */
.av-estrela-vitrine.is-meia {
    background: linear-gradient(90deg, var(--av-estrela) 50%, var(--av-estrela-vazia) 50%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.av-nota-contagem {
    margin: 0;
    font-size: .85rem;
    color: var(--pp-tinta-suave);
}

/* Sem média não há estrela nenhuma nem número: a contagem fica sozinha e ganha o
   peso de uma frase, em vez de parecer legenda de algo que não foi desenhado. */
.av-nota-contagem--sozinha {
    font-size: .92rem;
}

.av-barbeiros {
    list-style: none;
    padding: 0;
    margin: var(--esp-4) 0 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--esp-2);
}

.av-barbeiro {
    display: flex;
    align-items: baseline;
    gap: 6px;
    padding: 6px 12px;
    background: var(--pp-superficie);
    border: 1px solid var(--pp-borda);
    border-radius: 999px;
    font-size: .85rem;
}

.av-barbeiro-nome {
    color: var(--pp-tinta);
    font-weight: 600;
}

.av-barbeiro-nota {
    color: var(--av-estrela);
    font-weight: 600;
    white-space: nowrap;
}

/* A lista fica num <details>, como o horário da semana — e reusa `.hm-linha` no
   <summary> para que as duas dobras da página abram do mesmo jeito. */
.av-lista {
    margin-top: var(--esp-4);
    background: var(--pp-superficie);
    border: 1px solid var(--pp-borda);
    border-radius: var(--raio-card);
    box-shadow: var(--sombra);
    overflow: hidden;
}

.av-lista > summary {
    cursor: pointer;
    list-style: none;
    border-bottom: none;
}

.av-lista > summary::-webkit-details-marker {
    display: none;
}

.av-lista[open] > summary {
    border-bottom: 1px solid var(--pp-divisor);
}

.av-lista[open] .hm-seta {
    transform: rotate(-135deg) translate(-2px, -2px);
}

.av-depoimentos {
    list-style: none;
    padding: 0;
    margin: 0;
    background: var(--pp-superficie-2);
}

.av-depoimento {
    padding: var(--esp-3) var(--esp-4);
    border-bottom: 1px solid var(--pp-divisor);
}

.av-depoimento:last-child {
    border-bottom: none;
}

.av-depoimento-topo {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--esp-3);
    margin: 0;
}

.av-depoimento-nome {
    font-weight: 600;
    color: var(--pp-tinta-forte);
    font-size: .9rem;
}

.av-depoimento-estrelas {
    flex: none;
    color: var(--av-estrela);
    font-size: .85rem;
    letter-spacing: 1px;
    white-space: nowrap;
}

/* `overflow-wrap` porque o comentário é texto livre de cliente: uma palavra sem
   espaço (um link colado, um "kkkkkk..." de trinta caracteres) estouraria o cartão
   e daria rolagem horizontal na página inteira. */
.av-depoimento-texto {
    margin: 6px 0 0;
    font-size: .88rem;
    line-height: 1.5;
    color: var(--pp-tinta);
    overflow-wrap: anywhere;
}

.av-depoimento-data {
    margin: 6px 0 0;
    font-size: .75rem;
    color: var(--pp-tinta-suave);
}

.av-lista-teto {
    padding: var(--esp-3) var(--esp-4);
    margin: 0;
}

/* ── A moderação no painel ─────────────────────────────────────────────────── */

.av-resumo {
    text-align: center;
}

.av-resumo-nota {
    font-family: var(--fonte-display);
    font-size: 2.6rem;
    font-weight: 700;
    line-height: 1;
    margin: 0 0 6px;
    color: var(--pp-tinta-forte);
}

/* O travessão de "ainda não há nota" não pode ter o peso de uma nota: ele é a
   AUSÊNCIA de número, e desenhá-lo em preto forte diria que a barbearia tirou zero. */
.av-resumo-nota--vazia {
    color: var(--pp-tinta-suave);
    font-weight: 400;
}

.av-estrelas-texto {
    flex: none;
    color: var(--av-estrela);
    letter-spacing: 1px;
    white-space: nowrap;
}

.av-comentario {
    font-size: .9rem;
    line-height: 1.5;
    color: var(--pp-tinta);
    overflow-wrap: anywhere;
}

/* A avaliação escondida continua legível — ela não foi apagada, e o dono precisa
   conseguir reler o que tirou do ar para decidir se devolve. O que muda é o peso:
   ela recua, com uma faixa e uma etiqueta que dizem o estado sem depender só da cor. */
.av-linha--oculta {
    opacity: .72;
    border-left: 3px solid var(--pp-tinta-suave);
}

.av-etiqueta {
    padding: 3px 8px;
    border-radius: 999px;
    background: var(--pp-superficie-2);
    border: 1px solid var(--pp-borda);
}
/* ===============================================================================
   VITRINE: A GALERIA, OS CARDS DE SERVICO E A ESTRELA DO PROFISSIONAL (fase 28)

   BLOCO ACRESCENTADO NO FIM. Outras duas frentes desta onda mexem nesta mesma
   folha; o que teve de mudar acima esta listado no relatorio da frente, uma linha
   por edicao. Se alguma regra daqui tiver de alterar um seletor de cima, faca isso
   num commit proprio, depois do merge -- nunca dentro deste bloco.

   Cobre tres telas: a galeria e o cartao da equipe na pagina publica
   (`Home/Tenant`) e os passos 1 e 2 do wizard (`Agendar/Index`).
   =============================================================================== */

/* --- O titulo de secao da vitrine ------------------------------------------

   O `.nr-eyebrow` (0,72rem, caixa alta, cinza suave) foi desenhado para ROTULAR
   um bloco de dados -- e e o certo em "Horario e contato". Sobre a galeria ele
   virava legenda de anexo: a queixa do dono foi, literalmente, "o titulo tambem
   pequeno e sem graca".

   A distincao que este token faz e a que faltava: secao que EXPOE (o trabalho, a
   equipe) ganha manchete; secao que INFORMA continua com rotulo. Nao e escala
   aleatoria -- e a mesma familia display que o nome da barbearia usa no hero,
   dois degraus abaixo dele para nao competir. */
.nr-vitrine-titulo {
    margin: 0;
    font-family: var(--fonte-display);
    font-size: 1.45rem;
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -.01em;
    text-transform: none;
    color: var(--pp-tinta-forte);
}

/* --- O CARD DE SERVICO -----------------------------------------------------

   O corpo do cartao: nome + duracao de um lado, preco do outro, casados pela
   BASELINE. `align-items: baseline` alinha o preco com a PRIMEIRA linha do nome
   (a baseline de uma caixa multilinha e a da primeira linha), que e onde o olho
   pousa ao varrer a lista de cima para baixo -- e nao com o centro do bloco, que
   deslocaria o preco para baixo em todo cartao de titulo longo.

   A mesma marcacao serve a lista e a grade de proposito: sao a mesma escolha
   vista de duas distancias, e duas marcacoes divergiriam no dia em que uma delas
   ganhasse um campo. */
.fl-servico-corpo {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--esp-3);
}

.fl-servico-texto {
    flex: 1;
    min-width: 0;
}

/* DUAS linhas, e nao uma. Truncar em uma linha faz "Corte + barba + sobrancelha"
   e "Corte + barba + pezinho" virarem o mesmo item na tela -- o mesmo defeito que
   o nome do profissional ja documenta logo abaixo. `break-word` para um nome sem
   espacos nao estourar a coluna a 320px. */
.fl-servico-corpo .nr-opcao-nome {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    font-size: 1.0625rem;
    line-height: 1.25;
    overflow-wrap: break-word;
}

/* A duracao recua: ela qualifica a escolha, nao a decide. */
.fl-servico-corpo .nr-opcao-meta {
    font-size: .8125rem;
}

/* O preco estava enterrado no fim da linha de meta, no mesmo 0,8rem cinza da
   duracao -- a informacao que decide a compra com o peso de uma nota de rodape.
   Aqui ele vira tipo proprio, com `tabular-nums` para a coluna da direita nao
   dancar de cartao para cartao.

   Na LISTA ele fica do tamanho do titulo: a linha de lista le como um cardapio, e
   ali nome e preco tem o mesmo peso de decisao. Quem sobe para 1.375rem e a
   GRADE, logo abaixo -- porque no cartao com foto o titulo divide a atencao com a
   imagem, e sem a ancora o preco desaparece. */
.fl-servico-preco {
    flex: none;
    font-size: 1.0625rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--pp-tinta-forte);
    font-variant-numeric: tabular-nums;
}

.fl-opcoes--grade .fl-servico-preco {
    font-size: 1.375rem;
    line-height: 1.1;
}

/* A foto 4:3 deixa a celula ~33% mais alta que a de 16:9, e uma barbearia com
   doze servicos passa a ter varias telas de cartoes fora da dobra. `auto` na
   forma de duas partes e a que nao arrisca: enquanto a celula nunca foi medida o
   navegador usa 260px, e depois disso ele LEMBRA o tamanho real -- e por isso a
   barra de rolagem nao pula quando a pessoa volta. Onde nao houver suporte, nada
   acontece: o `loading="lazy"` do <img> ja cobre o custo de rede sozinho. */
.fl-opcoes--grade .nr-opcao {
    content-visibility: auto;
    contain-intrinsic-size: auto 260px;
}

/* --- A ESTRELA NO CARTAO DO PROFISSIONAL -----------------------------------

   A mesma linha nas tres telas: vitrine, cartao da equipe e passo 2 do wizard.
   Ela so nasce quando ha media -- abaixo do piso de amostra a view nao renderiza
   nada, e nao ha regra aqui para "estrela apagada" justamente porque esse estado
   nao deve existir. */
.eq-nota {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 4px;
    font-size: .85rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--pp-tinta);
    font-variant-numeric: tabular-nums;
}

/* A estrela e o unico ponto de cor do cartao, e e a MESMA cor do bloco de
   reputacao logo abaixo (`--av-estrela`): duas notas da mesma pagina pintadas de
   amarelos diferentes leriam como duas escalas diferentes. */
.eq-estrela {
    color: var(--av-estrela);
    font-size: .95rem;
    line-height: 1;
}

/* O cartao ESCOLHIDO troca de superficie para `--cor-marca-suave`, e a tinta
   suave sobre ela reprova em AA em quatro das seis cores de marca medidas em
   23/08/2026 (ver o `--pp-tinta-suave-na-marca` na secao 1.1). A contagem entre
   parenteses usa `.nr-meta`, que e tinta suave -- entao ela entra na mesma
   correcao que a `.nr-opcao-meta` ja recebeu. O numero da nota nao precisa: usa
   `--pp-tinta`, que passa em qualquer uma delas. */
.nr-opcao:has(input:checked) .eq-nota .nr-meta {
    color: var(--pp-tinta-suave-na-marca);
}

/* fim -- galeria, cards de servico e a estrela do profissional */


/* ═══ Frente: COMODIDADES EM GRADE, WI-FI COPIÁVEL E A FACHADA UNIFICADA ═════════
   (fase 28 — nasceu em worktree paralela a outras duas frentes que também tocam esta
   folha. Bloco ÚNICO, no fim, para o merge não fatorar chave de fechamento.)

   Três coisas, e as três substituem desenho que já existia:
   1. a linha de comodidades que rolava para o lado virou GRADE que quebra linha;
   2. o cartão de Wi-Fi, que copia a senha sem ela nunca estar no HTML;
   3. a fachada, que agora é UMA (`.hm-fachada`) e serve a home e o /agendar — as
      regras próprias do header do fluxo foram apagadas lá em cima (ver §6.1.0).
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── A grade de comodidades ──────────────────────────────────────────────────── */

/* A seção ganhou TÍTULO. Antes a linha de chips flutuava solta entre o CTA e a galeria:
   sem rótulo, oito ícones cinzas em fila são um enfeite, e ninguém para para lê-los. */
.hm-comodidades-secao {
    margin-top: var(--esp-5);
}

/* 🔴 GRADE, e a troca é o conserto de um antipadrão MEDIDO. Rolagem horizontal em vitrine
   faz o usuário PULAR o conteúdo — ele não percebe que há o que arrastar (Baymard "I
   overlooked it"), e a NN/g mediu que nem seta proeminente resolve. Metade das comodidades
   nascia fora da tela.

   `minmax(9.5rem, 1fr)` dá DUAS colunas a 390px e três no desktop, que é o mesmo arranjo
   de Booking e Airbnb. `auto-fill` (e não `auto-fit`) de propósito: com duas comodidades
   marcadas, `auto-fit` esticaria cada uma até meia tela, e um item de 9,5rem de conteúdo
   numa caixa de 24rem lê como layout quebrado. */
.hm-comodidades {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
    gap: .5rem .75rem;
    margin: var(--esp-3) 0 0;
    padding: 0;
    list-style: none;
}

/* 🔴 O RÓTULO ANDA SEMPRE JUNTO DO ÍCONE, e é regra e não estilo: ícone sozinho não
   comunica — só casa, lupa e impressora têm reconhecimento universal (NN/g Icon
   Usability). `min-height` no alvo de toque mesmo sem ser clicável: é o que dá à linha
   a altura de leitura confortável e mantém o ritmo vertical da grade.

   A pílula de borda saiu junto com a faixa rolante. Numa grade, oito contornos viram
   oito caixas competindo com o único botão da página; o que informa aqui é o par
   ícone + palavra, e não a moldura. */
.hm-comodidade {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: var(--toque);
    color: var(--pp-tinta);
    font-size: .875rem;
    font-weight: 500;
    line-height: 1.3;
}

/* 20px, contra os 16 que o atributo do SVG declara: numa grade o ícone deixa de ser
   ornamento de chip e passa a ser a âncora visual da linha. Monocromático de propósito —
   oito acentos coloridos roubariam a atenção do CTA. */
.hm-comodidade-ico {
    flex: none;
    width: 20px;
    height: 20px;
    color: currentColor;
    opacity: .75;
}

/* ── O cartão do Wi-Fi ──────────────────────────────────────────────────────── */

/* 🔴 NASCE `hidden` NO HTML e quem revela é o `wifi.js`: sem JavaScript não há como
   buscar a senha (ela não está na página) nem como copiar, e botão que não faz nada é
   pior que botão nenhum. A regra explícita de `[hidden]` existe porque o `hidden` do
   navegador vale `display: none` na FOLHA DO UA — qualquer `display` de classe o venceria
   em silêncio, que é o defeito já registrado para a capa e para as comodidades. */
.hm-wifi {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    margin-top: var(--esp-4);
}

.hm-wifi[hidden] {
    display: none;
}

/* `<button>` de verdade, e o cartão inteiro é o alvo: o rival deixa tocar no cartão, e um
   ícone de "copiar" de 16px no canto seria o mesmo recurso com um décimo do alcance.
   Mínimo de 44px (SC 2.5.5). */
.hm-wifi-cartao {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: var(--toque);
    padding: 10px 14px;
    border: 1px solid var(--pp-borda);
    border-radius: var(--raio-card);
    background: var(--pp-superficie);
    color: var(--pp-tinta);
    text-align: left;
    cursor: pointer;
    transition: border-color var(--mov-1), background var(--mov-1);
}

.hm-wifi-cartao:hover {
    border-color: var(--pp-tinta-suave);
    background: var(--pp-superficie-2);
}

.hm-wifi-cartao:active {
    transform: scale(.995);
}

.hm-wifi-texto {
    display: flex;
    flex: 1;
    min-width: 0;
    flex-direction: column;
    gap: 2px;
}

.hm-wifi-rotulo {
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: var(--folga-caps);
    text-transform: uppercase;
    color: var(--pp-tinta-suave);
}

/* Monoespaçada porque é senha: `l`, `1` e `I` precisam se distinguir na hora de digitar
   à mão, que é a saída quando as duas vias de cópia falham. `anywhere` porque o teto do
   domínio são 64 caracteres e uma senha longa não pode estourar o cartão. */
.hm-wifi-valor {
    font-family: var(--fonte-mono);
    font-size: 1rem;
    font-weight: 700;
    color: var(--pp-tinta-forte);
    overflow-wrap: anywhere;
}

/* 🔴 EM TINTA, e não na cor de marca: o `.hm-cta` é "a ÚNICA aparição da cor de marca
   como preenchimento na página", e há tenant com marca `#000000` no banco — um rótulo
   nessa cor sobre a superfície escura sumiria justamente no elemento que muda de texto
   para confirmar a cópia. O retorno aqui é a PALAVRA ("Copiado ✓"), nunca a cor. */
.hm-wifi-acao {
    flex: none;
    font-size: .82rem;
    font-weight: 700;
    color: var(--pp-tinta-forte);
    white-space: nowrap;
}

/* Segunda ação, deliberadamente mais fraca que a primeira: quem chegou aqui quer a senha
   no teclado do celular, não na tela. Some assim que a senha aparece. */
.hm-wifi-mostrar {
    display: inline-flex;
    align-items: center;
    min-height: var(--toque);
    padding: 0 2px;
    border: none;
    background: none;
    color: var(--pp-tinta-suave);
    font-size: .82rem;
    font-weight: 600;
    text-decoration: underline;
    cursor: pointer;
}

.hm-wifi-mostrar:hover {
    color: var(--pp-tinta);
}

/* Só ganha texto quando as DUAS vias de cópia falharam (contexto inseguro e `execCommand`
   recusado) e a saída passa a ser "toque e segure". Não é erro do sistema — é instrução —,
   então não veste vermelho. */
.hm-wifi-dica {
    margin: 0;
    font-size: .82rem;
    color: var(--pp-tinta-suave);
}

/* ── A fachada nas duas telas ────────────────────────────────────────────────── */

/* 🔴 A SANGRIA DA CAPA PRECISA DE UM PAI SEM CAIXA PRÓPRIA, e no /agendar o pai passou a
   ser o `.mk`. As margens negativas de `.hm-fachada--capa` (–esp-5 no topo, –esp-4 nas
   laterais) foram calculadas contra o padding do `.publico-wrap`; com o `.mk` no meio do
   caminho, a margem do topo COLAPSA através dele — e deixaria de colapsar no dia em que o
   `.mk` ganhasse borda ou padding, empurrando a capa para dentro da coluna. A declaração
   explícita é o que trava isso: o header do fluxo só empilha fachada, bio e voltar. */
.mk {
    padding: 0;
    border: none;
}

/* fim — comodidades, wifi e fachada */

/* ==========================================================================
   FASE 28 — REDES SOCIAIS E MAPA
   Bloco apendado no FIM do arquivo, e ele TERMINA numa linha de comentário —
   nunca num `}` solto. Motivo medido: dois blocos apendados que terminam na
   mesma linha fazem o git fatorar esse `}` como sufixo comum e deixar UMA
   cópia só; o primeiro bloco fica sem fechar, engole o segundo e o build
   passa. O comentário no fim é o que impede a fatoração.
   ========================================================================== */

/* ── O MAPA ────────────────────────────────────────────────────────────────
   Vive dentro do `.hm-info` na página pública (colado no endereço) e numa
   seção própria no /agendar. Por isso as regras não dependem de nenhum dos
   dois containers. */

.mp-bloco {
    display: flex;
    flex-direction: column;
    gap: var(--esp-3);
    padding: var(--esp-4);
    border-bottom: 1px solid var(--pp-divisor);
}

/* Dentro do .hm-info o bloco é a última coisa quando não há telefone — e ali
   a linha divisória do fim ficaria pendurada sem nada embaixo. */
.mp-bloco:last-child {
    border-bottom: none;
}

/* 🔴 A moldura tem PROPORÇÃO, e não altura fixa: o iframe é um retângulo de
   terceiro, e altura em px faria o mapa virar uma tira no celular e uma
   janela desperdiçada no desktop. 4/3 é o recorte que mostra a quadra e as
   ruas em volta nas duas larguras. */
.mp-moldura {
    position: relative;
    aspect-ratio: 4 / 3;
    max-height: 320px;
    border-radius: var(--raio-controle-lg);
    border: 1px solid var(--pp-borda);
    /* O iframe pinta os cantos quadrados por cima do raio da moldura se ele
       não for recortado aqui. */
    overflow: hidden;
    background: var(--pp-superficie-2);
}

.mp-mapa {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
}

/* Contorno, e não preenchimento: o `.hm-cta` é "a ÚNICA aparição da cor de
   marca como preenchimento na página", e um segundo botão cheio competiria
   com "Agendar horário" — a conversão que paga a casa. */
.mp-como-chegar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    align-self: flex-start;
    gap: var(--esp-2);
    /* 44px de alvo de toque no celular, e não a altura do texto. */
    min-height: 44px;
    padding: 10px var(--esp-4);
    border: 1px solid var(--pp-borda-forte);
    border-radius: var(--raio-controle);
    color: var(--pp-tinta);
    font-size: .88rem;
    font-weight: 600;
    text-decoration: none;
    background: var(--pp-superficie);
}

.mp-como-chegar:hover,
.mp-como-chegar:focus-visible {
    color: var(--pp-tinta-forte);
    border-color: var(--pp-tinta-suave);
}

/* A seção "Onde fica" do /agendar — a página pública não usa este cabeçalho,
   porque lá o endereço já é uma linha rotulada da tabela de contato. */
.mp-onde {
    margin-top: var(--esp-6);
    padding: var(--esp-4);
    background: var(--pp-superficie);
    border: 1px solid var(--pp-borda);
    border-radius: var(--raio-card);
    text-align: left;
}

.mp-titulo {
    margin: 0 0 var(--esp-2);
    font-size: 1rem;
    font-weight: 700;
    color: var(--pp-tinta-forte);
}

.mp-endereco {
    margin: 0 0 var(--esp-3);
    font-size: .88rem;
    line-height: 1.45;
    color: var(--pp-tinta);
    overflow-wrap: anywhere;
}

/* Dentro da seção do /agendar o bloco não precisa da moldura interna nem da
   linha divisória: quem já desenha a caixa é o `.mp-onde`. */
.mp-onde .mp-bloco {
    padding: 0;
    border-bottom: none;
}

/* ── OS ÍCONES DAS REDES ───────────────────────────────────────────────────
   Centralizados e no fim da página: aqui embaixo o ícone é o convite para
   continuar acompanhando depois de já ter agendado, não um concorrente do
   CTA. */

.rs-redes {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--esp-3);
    margin: var(--esp-5) 0 var(--esp-6);
}

/* 44x44 é alvo de toque, e não o tamanho do desenho (que tem 20px): um ícone
   de 20px é impossível de acertar com o polegar. */
.rs-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: var(--raio-pill);
    border: 1px solid var(--pp-borda);
    background: var(--pp-superficie);
    /* O ícone herda daqui via `currentColor`. */
    color: var(--pp-tinta-suave);
    text-decoration: none;
}

.rs-link:hover,
.rs-link:focus-visible {
    color: var(--pp-tinta-forte);
    border-color: var(--pp-tinta-suave);
}

.rs-ico {
    display: block;
}

/* fim — redes sociais e mapa */
