/* ------------------------------------------------------------------
   Tipografia própria — fontes variáveis servidas do próprio domínio.

   Por que self-hosted e não Google Fonts: a CSP declara `font-src 'self'`
   e o bundle do app Android precisa funcionar offline. Todas são SIL
   Open Font License, que permite hospedagem própria.

   Playfair Display → títulos: serifa de alto contraste, o tom editorial
                      da referência visual do projeto.
   Inter            → texto: legibilidade em corpo pequeno e tela escura.
   Outfit           → apoio: números, rótulos e navegação.
   ------------------------------------------------------------------ */

@font-face {
    font-family: "Playfair Display";
    font-style: normal;
    font-weight: 400 900;      /* eixo variável: um arquivo cobre todos os pesos */
    font-display: swap;
    src: url("/assets/fonts/playfair-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                   U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                   U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("/assets/fonts/inter-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                   U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                   U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Outfit";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("/assets/fonts/outfit-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                   U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                   U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ------------------------------------------------------------------
   Tokens — a única fonte de cor, espaçamento e tipografia.

   DIREÇÃO VISUAL (referência de 24/08/2026, em `referenciavisual/`):
   editorial e sóbrio. Azul profundo, laranja sólido como único acento,
   títulos em serifa e CANTO VIVO — nada de arredondamento.

   As três cores da cidade (--brand-*) continuam vindo de city_settings.
   Aqui elas TINGEM as superfícies: o fundo é um neutro escuro misturado
   com a cor primária da cidade. Trocar de cidade troca o clima inteiro
   sem tocar em CSS — é o mesmo mecanismo, com outro resultado.
   ------------------------------------------------------------------ */

:root {
    /* As cores CRUAS da cidade, injetadas no HTML por `city_settings`. Os
       valores aqui são só o fallback de quem não tem cidade resolvida.

       Elas e os tokens que o CSS usa têm nomes distintos de propósito: o
       tema claro precisa derivar um laranja mais escuro do laranja da
       cidade, e `--brand-2: color-mix(..., var(--brand-2), ...)` é um ciclo.
       Ciclo em custom property invalida a propriedade — o acento sumiria. */
    --cidade-brand: #123A5A;      /* azul profundo — base das superfícies */
    --cidade-acento: #F5821F;     /* laranja — acento único, sempre chapado */
    --cidade-acento-2: #E2641B;

    --brand: var(--cidade-brand);
    --brand-2: var(--cidade-acento);
    --brand-3: var(--cidade-acento-2);

    /* O acento é sólido. O nome permanece por compatibilidade com o CSS
       existente, mas não há mais degradê na interface. */
    --gradient: var(--brand-2);
    --gradient-soft: color-mix(in srgb, var(--brand-2) 16%, transparent);

    /* Superfícies: neutro escuro tingido pela cor da cidade */
    --bg: color-mix(in srgb, var(--brand) 34%, #060B12);
    --bg-soft: color-mix(in srgb, var(--brand) 46%, #070D15);
    --surface: color-mix(in srgb, var(--brand) 58%, #08101A);
    --surface-2: color-mix(in srgb, var(--brand) 72%, #0A1420);
    --border: color-mix(in srgb, var(--brand) 82%, #16273A);
    /* O contorno que identifica um campo ou um botão fantasma tinha 1,8:1
       sobre a superfície — desenho, não affordance. O mínimo da norma para
       isso é 3:1, e é o que ele passa a ter. */
    --border-strong: color-mix(in srgb, var(--text) 38%, var(--surface));

    /* Campo do sinal da marca quando a cidade tem logo próprio, e o mesmo que
       build/make-icons.php aplica no ícone de app — a aba do navegador e o
       cabeçalho têm de mostrar a mesma coisa.

       Era azul-profundo por causa do logo anterior, que tinha uma ponte branca
       e sumiria sobre claro. O logo de Natal é o oposto: o "R" é azul-marinho
       e desaparecia nesse mesmo campo — a 32px sobravam a letra ciano e um
       caco do mapa. Quem decide agora é a tinta do logo, medida pelo gerador;
       este valor é o lado claro dessa decisão e não muda entre os temas, pelo
       mesmo motivo de antes: o campo pertence à marca, não à página.

       A suíte de tema confere que o pixel do favicon gerado bate com este
       token — é o que impede os dois de divergirem em silêncio. */
    --campo-marca: var(--l-neutro);

    /* Texto.

       O terciário e a borda forte foram CORRIGIDOS em 25/08/2026, quando o
       teste de contraste passou a existir e mediu o que ninguém tinha medido:
       `--text-3` estava em 4,2:1 sobre a superfície e 3,8:1 sobre a superfície
       elevada, abaixo dos 4,5:1 que corpo de texto exige. Ele veste `.hint`,
       `.muted-2` e os metadados dos cards — texto pequeno, que é justamente
       onde a falta de contraste dói mais.

       Como o claro, os níveis derivam do texto principal caminhando para a
       superfície: um cinza escolhido à parte não acompanha `--brand`. */
    --text: #F2F5F8;
    --text-2: #A9BACB;
    --text-3: color-mix(in srgb, var(--text) 58%, var(--surface));
    --text-on-brand: #0B1420;

    --focus: var(--brand-2);
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
    --shadow: 0 2px 6px rgba(0, 0, 0, .3), 0 14px 30px rgba(0, 0, 0, .35);
    --shadow-lg: 0 6px 14px rgba(0, 0, 0, .32), 0 30px 60px rgba(0, 0, 0, .45);
    --shadow-glow: 0 10px 24px rgba(0, 0, 0, .4);
    --ring: color-mix(in srgb, var(--brand-2) 60%, transparent);

    /* Tipografia */
    --font: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
    --font-display: "Playfair Display", Georgia, "Times New Roman", serif;
    --font-ui: "Outfit", "Inter", ui-sans-serif, system-ui, sans-serif;
    --step--1: clamp(.82rem, .8rem + .1vw, .875rem);
    --step-0: clamp(1rem, .97rem + .15vw, 1.06rem);
    --step-1: clamp(1.15rem, 1.1rem + .3vw, 1.35rem);
    --step-2: clamp(1.45rem, 1.3rem + .65vw, 1.9rem);
    --step-3: clamp(1.85rem, 1.55rem + 1.3vw, 2.7rem);
    --step-4: clamp(2.2rem, 1.6rem + 2.6vw, 3.8rem);

    /* Ritmo */
    --space-1: .25rem;
    --space-2: .5rem;
    --space-3: .75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-7: 3rem;
    --space-8: 4.5rem;

    /* CANTO VIVO. Os tokens existem para manter um único ponto de decisão:
       se um dia o arredondamento voltar, muda aqui e vale para tudo. */
    --radius-sm: 0;
    --radius: 0;
    --radius-lg: 0;
    --radius-full: 0;
    --radius-circle: 50%;   /* só para o que é geometricamente redondo */

    --wrap: 74rem;
    --wrap-narrow: 46rem;
    --header-h: 4rem;

    --ease: cubic-bezier(.2, .7, .3, 1);
}

/* Tema claro: para quem usa o sistema em claro, e para impressão. */
/* ------------------------------------------------------------------
   TEMA CLARO

   Construído como o escuro: **nenhuma cor escrita à mão**. As superfícies são
   um neutro tingido por `--brand`, e os três níveis de texto são uma tinta só
   caminhando em direção ao fundo. Trocar `--brand` muda os dois temas juntos —
   é o que faz a segunda cidade caber sem tocar em CSS.

   O neutro é QUENTE (`#FDFCFA`, não `#FFFFFF`). Branco puro contra texto quase
   preto é contraste de folha de papel: passa em qualquer medida de
   acessibilidade e cansa em tela. Leveza não é clarear — é reduzir contraste
   sem cair abaixo do mínimo.

   OS VALORES SÃO MEDIDOS, NÃO ESTIMADOS. `build/smoke-tema.php` resolve cada
   token e calcula a razão de contraste de cada par texto/fundo dos dois temas;
   nenhum passa abaixo do mínimo. Foi a medida que revelou o que a versão
   anterior escondia: no claro, o laranja da marca tinha **2,4:1** como texto e
   o branco sobre o botão laranja, **2,6:1** — muito abaixo dos 4,5:1 exigidos,
   ou seja, ilegível para muita gente, no botão mais clicado do guia.

   Os valores moram aqui uma vez só. Antes eram copiados no bloco da media
   query e no do `[data-theme]`, e as duas cópias já tinham divergido — uma
   trazia as sombras, a outra não. */

:root {
    /* Os dois extremos de onde tudo deriva. */
    --l-neutro: #FDFCFA;
    --l-tinta: #0E1A24;

    --l-bg: color-mix(in srgb, var(--brand) 8%, var(--l-neutro));
    --l-bg-soft: color-mix(in srgb, var(--brand) 14%, var(--l-neutro));
    --l-surface: color-mix(in srgb, var(--brand) 0%, var(--l-neutro));
    --l-surface-2: color-mix(in srgb, var(--brand) 11%, var(--l-neutro));
    --l-border: color-mix(in srgb, var(--brand) 28%, var(--l-neutro));

    --l-text: color-mix(in srgb, var(--brand) 30%, var(--l-tinta));

    /* Secundário e terciário são a MESMA tinta caminhando para o fundo. Um
       cinza escolhido à parte perderia o tom da cidade e, pior, deixaria de
       acompanhar quando `--brand` mudasse. */
    --l-text-2: color-mix(in srgb, var(--l-text) 76%, var(--l-bg));
    --l-text-3: color-mix(in srgb, var(--l-text) 66%, var(--l-bg));

    /* Borda de controle: 3:1 é o mínimo para o contorno que identifica um
       campo ou um botão fantasma. A borda anterior tinha 1,6:1 — desenho, não
       affordance. */
    --l-border-strong: color-mix(in srgb, var(--l-text) 58%, var(--l-bg));

    /* O laranja escurece e o matiz permanece: misturar com preto mexe na
       luminosidade, que é o que o olho lê como estridência — e é também o que
       decide a legibilidade. O guia usa este token como COR DE TEXTO em 60
       lugares e como fundo em 19; quem decide é o uso maior. */
    --l-brand-2: color-mix(in srgb, var(--cidade-acento) 61%, #000);
}

@media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) {
        --bg: var(--l-bg);
        --bg-soft: var(--l-bg-soft);
        --surface: var(--l-surface);
        --surface-2: var(--l-surface-2);
        --border: var(--l-border);
        --border-strong: var(--l-border-strong);
    
        --text: var(--l-text);
        --text-2: var(--l-text-2);
        --text-3: var(--l-text-3);
    
        --brand-2: var(--l-brand-2);
        --gradient: var(--l-brand-2);
        --gradient-soft: color-mix(in srgb, var(--l-brand-2) 14%, transparent);
        --text-on-brand: #FFFFFF;
        --ring: color-mix(in srgb, var(--l-brand-2) 55%, transparent);
    
        --shadow-sm: 0 1px 2px rgba(14, 26, 36, .06);
        --shadow: 0 2px 4px rgba(14, 26, 36, .05), 0 10px 26px rgba(14, 26, 36, .07);
        --shadow-lg: 0 4px 10px rgba(14, 26, 36, .06), 0 24px 52px rgba(14, 26, 36, .10);
        --shadow-glow: 0 10px 24px rgba(14, 26, 36, .10);
    }
}

:root[data-theme="light"] {
    --bg: var(--l-bg);
    --bg-soft: var(--l-bg-soft);
    --surface: var(--l-surface);
    --surface-2: var(--l-surface-2);
    --border: var(--l-border);
    --border-strong: var(--l-border-strong);

    --text: var(--l-text);
    --text-2: var(--l-text-2);
    --text-3: var(--l-text-3);

    --brand-2: var(--l-brand-2);
    --gradient: var(--l-brand-2);
    --gradient-soft: color-mix(in srgb, var(--l-brand-2) 14%, transparent);
    --text-on-brand: #FFFFFF;
    --ring: color-mix(in srgb, var(--l-brand-2) 55%, transparent);

    --shadow-sm: 0 1px 2px rgba(14, 26, 36, .06);
    --shadow: 0 2px 4px rgba(14, 26, 36, .05), 0 10px 26px rgba(14, 26, 36, .07);
    --shadow-lg: 0 4px 10px rgba(14, 26, 36, .06), 0 24px 52px rgba(14, 26, 36, .10);
    --shadow-glow: 0 10px 24px rgba(14, 26, 36, .10);
}

/* ------------------------------------------------------------------
   Base — reset enxuto, tipografia e layout de página.
   ------------------------------------------------------------------ */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--font);
    font-size: var(--step-0);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
    font-family: var(--font-display);
    font-weight: 700;
    line-height: 1.08;
    letter-spacing: -.03em;
    margin: 0 0 var(--space-3);
    text-wrap: balance;
}
h1 { font-weight: 800; letter-spacing: -.038em; }
h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }
p { margin: 0 0 var(--space-4); text-wrap: pretty; }

/* Link NÃO se pinta por padrão.
   A regra anterior era `a:not([class])`, que pegava tudo que não tivesse
   classe — inclusive o menu do cabeçalho, a trilha de navegação e o rodapé,
   que apareciam sublinhados em teal. Agora o destaque é explícito: vale
   dentro de texto corrido (.prose) ou com a classe .link. */
a { color: inherit; text-decoration: none; }

.prose a,
a.link {
    color: color-mix(in srgb, var(--brand-2) 82%, var(--text));
    text-decoration: underline;
    text-underline-offset: .18em;
    text-decoration-thickness: .08em;
    text-decoration-color: color-mix(in srgb, var(--brand-2) 45%, transparent);
}
.prose a:hover,
a.link:hover { text-decoration-color: currentColor; }

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

/* O `[hidden]` do navegador é `display: none` na folha do UA — e QUALQUER
   regra de autor com `display` vence dele. Como `.campo` é `display: block`
   e `.conta__menu` é `flex`, o atributo virava decoração: o elemento ficava
   visível com `hidden` no HTML. O `!important` é o tratamento padrão de
   qualquer reset, e é aqui para não precisar de um remendo por componente. */
[hidden] { display: none !important; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible {
    outline: 2.5px solid var(--focus);
    outline-offset: 3px;
    border-radius: 4px;
}

/* Ícone duotone: a forma cheia entra com opacidade baixa, o traço vem por cima. */
/* `display: inline-block` desfaz, só para os ícones, o `svg { display: block }`
   do reset acima. Sem isso um ícone no meio de um parágrafo quebra a linha e
   fica sozinho em cima do texto — que era o que acontecia em toda nota de
   formulário. Dentro de flex ou grid não muda nada: item de flex/grid é
   blocado de qualquer forma, e `vertical-align` é ignorado ali. O
   deslocamento negativo alinha o traço do ícone com a altura-x da fonte. */
.icon {
    width: 1.25em; height: 1.25em;
    display: inline-block;
    vertical-align: -.18em;
    fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
    flex: none;
}
/* A forma cheia dos ícones duotone vem por ATRIBUTO dentro do sprite:
   seletor de fora não alcança o shadow tree criado por <use>. */
.icon--lg { width: 1.6em; height: 1.6em; stroke-width: 1.55; }
.icon--xl { width: 2.2em; height: 2.2em; stroke-width: 1.4; }

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--space-5); }
.wrap--narrow { max-width: var(--wrap-narrow); }
.section { padding-block: var(--space-7); }
.section--tight { padding-block: var(--space-6); }
.stack > * + * { margin-top: var(--space-4); }

.skip-link {
    position: absolute; left: -9999px; top: 0; z-index: 100;
    background: var(--brand); color: var(--text-on-brand);
    padding: var(--space-3) var(--space-4); border-radius: 0 0 var(--radius) 0;
}
.skip-link:focus { left: 0; }

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

/* ---------------------------------------------------------- cabeçalho */

.site-header {
    position: sticky; top: 0; z-index: 50;
    background: color-mix(in srgb, var(--surface) 88%, transparent);
    backdrop-filter: saturate(1.4) blur(12px);
    border-bottom: 1px solid var(--border);
}
.site-header__inner {
    height: var(--header-h);
    display: flex; align-items: center; gap: var(--space-5);
}
.brand { display: flex; align-items: center; gap: var(--space-3); font-weight: 700; letter-spacing: -.02em; }
.brand__mark {
    width: 2rem; height: 2rem; border-radius: 9px; flex: none;
    background: linear-gradient(135deg, var(--brand), var(--brand-2));
    display: grid; place-items: center; color: #fff;
}
.brand__mark .icon { width: 1.1rem; height: 1.1rem; }
.brand__text { font-size: 1.02rem; }
.brand__text span { color: var(--text-3); font-weight: 500; }

.site-nav { margin-left: auto; display: flex; align-items: center; gap: var(--space-2); }
.site-nav a {
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-full);
    font-size: var(--step--1); font-weight: 550; color: var(--text-2);
    transition: background .18s var(--ease), color .18s var(--ease);
}
.site-nav a:hover, .site-nav a[aria-current="page"] { background: var(--surface-2); color: var(--text); }

.header-search { margin-left: auto; }
@media (max-width: 860px) {
    .site-nav { display: none; }
    .site-nav--mobile {
        display: flex; margin: 0; overflow-x: auto; gap: var(--space-1);
        padding: var(--space-2) var(--space-5) var(--space-3);
        border-bottom: 1px solid var(--border); background: var(--surface);
        scrollbar-width: none;
    }
    .site-nav--mobile::-webkit-scrollbar { display: none; }
    .site-nav--mobile a { white-space: nowrap; }
}
@media (min-width: 861px) { .site-nav--mobile { display: none; } }

/* ------------------------------------------------------------- rodapé */

.site-footer {
    margin-top: var(--space-8);
    background: var(--surface);
    border-top: 1px solid var(--border);
    padding-block: var(--space-6) var(--space-5);
    font-size: var(--step--1);
    color: var(--text-2);
}
.site-footer__grid {
    display: grid; gap: var(--space-5);
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    margin-bottom: var(--space-5);
}
.site-footer h4 { font-size: var(--step--1); text-transform: uppercase; letter-spacing: .08em; color: var(--text-3); margin-bottom: var(--space-2); }
.site-footer li + li { margin-top: var(--space-1); }
.site-footer a:hover { color: var(--brand); }
.site-footer__bottom {
    border-top: 1px solid var(--border); padding-top: var(--space-4);
    display: flex; flex-wrap: wrap; gap: var(--space-3); justify-content: space-between;
    color: var(--text-3);
}

/* ------------------------------------------------------ ajustes mobile */

/* Ícone dentro de link/botão é inline: senão o reset `svg { display:block }`
   quebra a linha e empilha ícone e texto. */
.site-nav a, .site-footer a, .breadcrumbs a { display: inline-flex; align-items: center; gap: .4em; }

@media (max-width: 860px) {
    /* No celular a busca vive no hero e na página /busca — no cabeçalho ela
       só rouba largura e empurra o layout para fora da viewport.
       Especificidade dupla de propósito: `.search { display: flex }` mora em
       components.css, que é concatenado DEPOIS, e venceria um seletor simples. */
    .site-header .search--header { display: none; }
    .site-header__inner { gap: var(--space-3); }
    .brand__text { font-size: .95rem; }
}

/* Rede de segurança: nenhuma página deve rolar na horizontal. */
html, body { max-width: 100%; overflow-x: clip; }

/* ------------------------------------------------------------------
   Componentes — as mesmas classes usadas pelo canal Web (PHP) e pelo
   app Android (JS). Este arquivo é a fronteira comum entre os dois.
   ------------------------------------------------------------------ */

/* ------------------------------------------------------------- mídia */

.media {
    position: relative; overflow: hidden; margin: 0;
    background: var(--surface-2); border-radius: var(--radius);
}
.media img { width: 100%; height: 100%; object-fit: cover; }
.media--16x9 { aspect-ratio: 16 / 9; }
.media--4x3 { aspect-ratio: 4 / 3; }
.media--3x2 { aspect-ratio: 3 / 2; }
.media--1x1 { aspect-ratio: 1 / 1; }

/* Placeholder: enquanto não há acervo, a falta de foto vira desenho —
   nunca um quadrado cinza quebrado. */
.media--empty {
    display: grid; place-items: center;
    background:
        radial-gradient(120% 100% at 15% 0%, color-mix(in srgb, var(--brand-2) 38%, transparent), transparent 60%),
        linear-gradient(135deg, var(--brand), color-mix(in srgb, var(--brand) 55%, var(--brand-3)));
}
.media--empty::after {
    content: ""; position: absolute; inset: auto -10% -25% -10%; height: 60%;
    background: radial-gradient(60% 100% at 50% 100%, rgba(255, 255, 255, .22), transparent 70%);
}
.media__icon { width: 30%; height: 30%; max-width: 4.5rem; color: rgba(255, 255, 255, .62); stroke-width: 1.2; }

/* ------------------------------------------------------------- botões */

.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
    padding: .68rem 1.15rem; border-radius: var(--radius-full);
    border: 1px solid transparent; background: var(--gradient); color: #14100A;
    font-size: var(--step--1); font-weight: 600; cursor: pointer;
    transition: transform .15s var(--ease), box-shadow .18s var(--ease), background .18s var(--ease);
}
.btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-glow); }
.btn:active { transform: translateY(0); }
.btn--ghost { background: transparent; border-color: var(--border-strong); color: var(--text); }
.btn--ghost:hover { border-color: var(--brand); color: var(--brand); }
.btn--light { background: rgba(255, 255, 255, .16); color: #fff; border-color: rgba(255, 255, 255, .3); backdrop-filter: blur(6px); }
.btn--block { width: 100%; }
.btn--sm { padding: .42rem .8rem; }

/* ------------------------------------------------------------ badges */

.badge {
    display: inline-flex; align-items: center; gap: .35em;
    padding: .22em .7em; border-radius: var(--radius-full);
    font-size: .74rem; font-weight: 650; letter-spacing: .02em;
    background: var(--surface-2); color: var(--text-2); border: 1px solid var(--border);
}
.badge--brand { background: color-mix(in srgb, var(--brand) 12%, transparent); color: var(--brand); border-color: transparent; }
.badge--accent { background: color-mix(in srgb, var(--brand-2) 20%, transparent); color: color-mix(in srgb, var(--brand-2) 70%, var(--text)); border-color: transparent; }
.badge--float { position: absolute; top: var(--space-3); left: var(--space-3); background: rgba(0, 0, 0, .55); color: #fff; border: 0; backdrop-filter: blur(4px); }
.badge .icon { width: 1em; height: 1em; }

/* -------------------------------------------------------------- hero */

.hero { position: relative; isolation: isolate; color: #fff; overflow: hidden; }
.hero__bg { position: absolute; inset: 0; z-index: -2; }
.hero__bg .media, .hero__bg figure { width: 100%; height: 100%; aspect-ratio: auto; border-radius: 0; }
.hero::after {
    content: ""; position: absolute; inset: 0; z-index: -1;
    background:
        linear-gradient(100deg, rgba(0, 0, 0, .72) 0%, rgba(0, 0, 0, .45) 42%, rgba(0, 0, 0, .12) 75%),
        linear-gradient(180deg, rgba(0, 0, 0, .35) 0%, rgba(0, 0, 0, .1) 40%, rgba(0, 0, 0, .68) 100%);
}
.hero__inner { padding-block: clamp(3.5rem, 10vw, 7rem); }
.hero__eyebrow {
    display: inline-flex; align-items: center; gap: .5em; margin-bottom: var(--space-3);
    font-size: var(--step--1); font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
    color: rgba(255, 255, 255, .85);
}
.hero h1 { color: #fff; max-width: 18ch; }
.hero__lead { font-size: var(--step-1); max-width: 46ch; color: rgba(255, 255, 255, .92); margin-bottom: var(--space-5); }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.hero--page .hero__inner { padding-block: clamp(2.5rem, 7vw, 4.5rem); }
.hero--page h1 { max-width: 24ch; font-size: var(--step-3); }

/* ------------------------------------------------------------- busca */

.search {
    display: flex; align-items: center; gap: var(--space-2);
    background: var(--surface); border: 1px solid var(--border-strong);
    border-radius: var(--radius-full); padding: .5rem .5rem .5rem 1rem;
    box-shadow: var(--shadow-sm); position: relative;
}
.search:focus-within { border-color: var(--brand); box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand) 15%, transparent); }
.search input {
    flex: 1; border: 0; background: transparent; outline: none; min-width: 0;
    padding: .35rem 0; color: var(--text);
}
.search input::placeholder { color: var(--text-3); }
.search .icon { color: var(--text-3); }
.search--hero { max-width: 34rem; box-shadow: var(--shadow-lg); border-color: transparent; }
/* A busca do cabeçalho tem de ter a MESMA altura do botão de entrar.
   Ela vinha 12px mais alta (50 contra 38) porque somava o próprio padding
   vertical ao do `input` — dois recuos empilhados —, e o resultado era uma
   caixa pesada e visivelmente fora de linha com o botão ao lado. O recuo
   vertical passa a viver só no input, com o mesmo valor de `.btn--sm`. */
.search--header { padding: 0 .3rem 0 .8rem; max-width: 18rem; }
.search--header input {
    /* Mesmo recuo e mesmo corpo de letra do `.btn--sm`: era a diferença de
       tamanho da fonte (16,96px herdados contra 14px do botão) que sobrava
       como 5px de altura depois de igualar os recuos.

       Encolher a fonte só é seguro AQUI: a busca do cabeçalho não existe
       abaixo de 860px (ver base.css), e é no celular que input com menos de
       16px faz o iOS dar zoom ao focar. Não repita isto em `.search--hero`
       nem em `.search--page`. */
    padding-block: .42rem;
    font-size: var(--step--1);
}

.suggest {
    position: absolute; top: calc(100% + .5rem); left: 0; right: 0; z-index: 40;
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    box-shadow: var(--shadow-lg); overflow: hidden; display: none;
}
.suggest[data-open="true"] { display: block; }
.suggest__item { display: flex; align-items: center; gap: var(--space-3); padding: .6rem var(--space-4); color: var(--text); }
.suggest__item:hover, .suggest__item[aria-selected="true"] { background: var(--surface-2); }
.suggest__item small { color: var(--text-3); margin-left: auto; font-size: .78rem; }
.suggest__empty { padding: var(--space-4); color: var(--text-3); font-size: var(--step--1); }

/* -------------------------------------------------------------- grid */

.grid { display: grid; gap: var(--space-5); }
.grid--cards { grid-template-columns: repeat(auto-fill, minmax(15.5rem, 1fr)); }
.grid--wide { grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr)); }
.grid--cats { grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: var(--space-3); }

.section-head {
    display: flex; align-items: end; justify-content: space-between;
    gap: var(--space-4); margin-bottom: var(--space-5);
    flex-wrap: wrap;
}

/* O bloco de título pede a linha inteira antes de deixar o H1 quebrar.
   Sem isto, o flex espreme o título para caber os controles ao lado, e
   "Explorar Natal" vira duas linhas com 400 px de espaço sobrando à direita.
   O `min-width: 0` é o que permite ao bloco encolher abaixo do conteúdo —
   sem ele, o padrão `min-width: auto` do flex ignora a base. */
.section-head > :first-child { flex: 1 1 20rem; min-width: 0; }

/* Os controles cabem inteiros quando há espaço e encolhem quando não há —
   `0 1 auto` com `min-width: 0`. Com `0 0 auto` eles manteriam a largura
   natural e vazariam para fora da tela em vez de quebrar por dentro. */
.section-head > :first-child ~ * { flex: 0 1 auto; min-width: 0; }
.section-head p { color: var(--text-2); margin: var(--space-1) 0 0; max-width: 60ch; }
.section-head h2 { margin: 0; }
.section-head__link { color: var(--brand); font-weight: 600; font-size: var(--step--1); white-space: nowrap; display: inline-flex; align-items: center; gap: .3em; }
.section-head__link:hover .icon { transform: translateX(2px); }
.section-head__link .icon { transition: transform .18s var(--ease); }

/* ------------------------------------------------------------- cards */

.card {
    position: relative; display: flex; flex-direction: column;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); overflow: hidden;
    transition: transform .2s var(--ease), box-shadow .2s var(--ease), border-color .2s var(--ease);
}
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: var(--border-strong); }
.card .media { border-radius: 0; }
.card__body { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); flex: 1; }
.card__eyebrow {
    display: flex; align-items: center; gap: .4em;
    font-size: .76rem; font-weight: 650; letter-spacing: .04em; text-transform: uppercase;
    color: color-mix(in srgb, var(--brand-2) 78%, var(--text));
}
.card__eyebrow .icon { width: .95em; height: .95em; }
.card__title { font-size: var(--step-1); margin: 0; letter-spacing: -.02em; }
.card__title a::after { content: ""; position: absolute; inset: 0; }
.card__desc { color: var(--text-2); font-size: var(--step--1); margin: 0; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.card__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: auto; padding-top: var(--space-2); color: var(--text-3); font-size: .8rem; }
.card__meta .icon { width: .95em; height: .95em; }
.card__meta span { display: inline-flex; align-items: center; gap: .3em; }

.card--cat {
    align-items: center; text-align: center; padding: var(--space-4) var(--space-3);
    gap: var(--space-2); border-radius: var(--radius);
}
.card--cat .card__icon {
    width: 2.9rem; height: 2.9rem; border-radius: var(--radius-sm); display: grid; place-items: center;
    background: color-mix(in srgb, var(--brand) 10%, transparent); color: var(--brand);
}
.card--cat .card__icon .icon { width: 1.4rem; height: 1.4rem; }
.card--cat strong { font-size: var(--step-0); letter-spacing: -.01em; }
.card--cat small { color: var(--text-3); font-size: .78rem; }

.card--route .card__days {
    position: absolute; top: var(--space-3); right: var(--space-3);
    background: var(--surface); color: var(--text); border-radius: var(--radius-full);
    padding: .2rem .65rem; font-size: .76rem; font-weight: 700; box-shadow: var(--shadow-sm);
}

/* A faixa horizontal (.rail) e suas setas vivem em refinements.css. */

/* ----------------------------------------------------------- filtros */

.filters { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.chip {
    display: inline-flex; align-items: center; gap: .4em;
    padding: .42rem .85rem; border-radius: var(--radius-full);
    border: 1px solid var(--border-strong); background: var(--surface);
    font-size: var(--step--1); font-weight: 550; color: var(--text-2); cursor: pointer;
    transition: all .16s var(--ease); white-space: nowrap;
}
.chip:hover { border-color: var(--brand); color: var(--brand); }
.chip[aria-pressed="true"], .chip.is-active { background: var(--gradient); border-color: transparent; color: #14100A; box-shadow: var(--shadow-glow); }
.chip .icon { width: 1em; height: 1em; }
.chip small { opacity: .7; font-weight: 500; }

.filter-bar {
    position: sticky; top: var(--header-h); z-index: 30;
    background: color-mix(in srgb, var(--bg) 92%, transparent);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--border);
    padding-block: var(--space-3);
}
/* Os filtros QUEBRAM a linha, não rolam.

   Rolagem horizontal serve a uma lista que se percorre — cards, fotos. Um
   conjunto de filtros é outra coisa: para escolher, é preciso VER todas as
   opções. Escondidas atrás de uma rolagem sem barra e sem seta, no desktop,
   elas simplesmente não existem para quem usa mouse — foi o que acontecia
   aqui, com dez bairros inalcançáveis.

   Quebrar em duas ou três linhas custa 40px de altura e devolve o conjunto
   inteiro. Não precisa de JavaScript nem de seta. */
.filter-bar__scroll { display: flex; flex-wrap: wrap; gap: var(--space-2); }

@media (max-width: 860px) {
    /* No toque a conta se inverte: altura é cara, e arrastar é natural.
       Aqui a rolagem horizontal é a escolha certa — e o gesto existe. */
    .filter-bar__scroll {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
        /* Encosta o primeiro chip na borda ao rolar, em vez de parar no meio. */
        scroll-snap-type: x proximity;
    }
    .filter-bar__scroll::-webkit-scrollbar { display: none; }
    .filter-bar__scroll > * { scroll-snap-align: start; }
}

/* -------------------------------------------------------------- mapa */

.map {
    position: relative; overflow: hidden; border-radius: var(--radius);
    background: var(--surface-2); border: 1px solid var(--border);
    touch-action: none; user-select: none; cursor: grab;
}
.map:active { cursor: grabbing; }
.map--full { height: min(70vh, 40rem); }
.map--panel { height: 22rem; }
.map__tiles { position: absolute; inset: 0; }
.map__tiles img { position: absolute; width: 256px; height: 256px; max-width: none; pointer-events: none; }
.map__markers { position: absolute; inset: 0; pointer-events: none; }
.map__marker {
    position: absolute; transform: translate(-50%, -100%); pointer-events: auto;
    display: grid; place-items: center; width: 2rem; height: 2rem; border-radius: 50% 50% 50% 0;
    rotate: -45deg; background: var(--brand); border: 2px solid #fff; box-shadow: var(--shadow);
    cursor: pointer; transition: scale .15s var(--ease);
}
.map__marker:hover, .map__marker.is-active { scale: 1.18; z-index: 5; }
.map__marker .icon { rotate: 45deg; width: 1rem; height: 1rem; color: #fff; }
.map__marker--accent { background: var(--brand-3); }
.map__controls { position: absolute; right: var(--space-3); top: var(--space-3); display: grid; gap: var(--space-1); z-index: 6; }
.map__btn {
    width: 2.2rem; height: 2.2rem; border-radius: var(--radius-sm); border: 1px solid var(--border);
    background: var(--surface); color: var(--text); display: grid; place-items: center; cursor: pointer;
    box-shadow: var(--shadow-sm); font-size: 1.1rem; line-height: 1;
}
.map__btn:hover { border-color: var(--brand); color: var(--brand); }
.map__attribution {
    position: absolute; right: 0; bottom: 0; z-index: 6;
    background: color-mix(in srgb, var(--surface) 85%, transparent);
    font-size: .68rem; color: var(--text-3); padding: .15rem .5rem; border-top-left-radius: var(--radius-sm);
}
.map__popup {
    position: absolute; z-index: 7; transform: translate(-50%, calc(-100% - 2.4rem));
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg); padding: var(--space-3); width: 15rem; display: none;
}
.map__popup[data-open="true"] { display: block; }
.map__popup strong { display: block; font-size: var(--step--1); margin-bottom: .2rem; }
.map__popup small { color: var(--text-3); font-size: .76rem; }

/* --------------------------------------------------------- explorar */

.explore { display: grid; gap: var(--space-5); }
@media (min-width: 1020px) {
    .explore { grid-template-columns: minmax(0, 1fr) minmax(22rem, 40%); align-items: start; }
    .explore__map { position: sticky; top: calc(var(--header-h) + 4.5rem); }
}
.view-toggle { display: inline-flex; background: var(--surface-2); border-radius: var(--radius-full); padding: 3px; gap: 2px; }
.view-toggle button { border: 0; background: transparent; padding: .35rem .9rem; border-radius: var(--radius-full); font-size: var(--step--1); font-weight: 600; color: var(--text-2); cursor: pointer; }
.view-toggle button[aria-pressed="true"] { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }
@media (min-width: 1020px) { .view-toggle { display: none; } }
@media (max-width: 1019px) {
    /* O atributo vive no wrapper [data-explore], que envolve filtros e lista. */
    [data-view="map"] .explore__list { display: none; }
    [data-view="list"] .explore__map { display: none; }
}

/* ----------------------------------------------------------- página */

.page-head { padding-block: var(--space-6) var(--space-4); }
.breadcrumbs { display: flex; flex-wrap: wrap; gap: .4rem; font-size: var(--step--1); color: var(--text-3); margin-bottom: var(--space-3); }
.breadcrumbs a:hover { color: var(--brand); }
.breadcrumbs li:not(:last-child)::after { content: "/"; margin-left: .4rem; color: var(--border-strong); }
.breadcrumbs li { display: inline-flex; align-items: center; }

.prose { max-width: 66ch; }
.prose p { color: var(--text-2); }
.prose h2 { font-size: var(--step-2); margin-top: var(--space-6); }
.prose > *:first-child { margin-top: 0; }

.detail { display: grid; gap: var(--space-6); }
@media (min-width: 960px) { .detail { grid-template-columns: minmax(0, 1fr) 20rem; align-items: start; } }
.detail__aside { display: grid; gap: var(--space-4); position: sticky; top: calc(var(--header-h) + var(--space-4)); }

.panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-4); }
.panel h3 { font-size: var(--step-0); margin-bottom: var(--space-3); }
.data-list { display: grid; gap: var(--space-3); font-size: var(--step--1); }
.data-list > div { display: flex; gap: var(--space-3); align-items: start; }
.data-list .icon { color: var(--text-3); margin-top: .15em; }
.data-list dt { color: var(--text-3); font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; }
.data-list dd { margin: 0; }

.gallery { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }

/* --------------------------------------------------------- timeline */

.timeline { position: relative; display: grid; gap: var(--space-4); }
.timeline::before {
    content: ""; position: absolute; left: 1.1rem; top: .6rem; bottom: .6rem; width: 2px;
    background: linear-gradient(var(--brand), color-mix(in srgb, var(--brand) 20%, transparent));
}
.timeline__item { position: relative; display: grid; grid-template-columns: 2.6rem minmax(0, 1fr); gap: var(--space-3); align-items: start; }
.timeline__dot {
    width: 2.2rem; height: 2.2rem; border-radius: 50%; display: grid; place-items: center;
    background: var(--surface); border: 2px solid var(--brand); color: var(--brand); z-index: 1;
    font-size: .78rem; font-weight: 700;
}
.timeline__card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-4); position: relative; }
.timeline__card:hover { border-color: var(--border-strong); }
.timeline__time { font-size: .78rem; font-weight: 700; color: var(--brand); letter-spacing: .04em; }
.timeline__note { font-size: var(--step--1); color: var(--text-2); border-left: 2px solid var(--border-strong); padding-left: var(--space-3); margin-top: var(--space-3); }
.day-head { display: flex; align-items: baseline; gap: var(--space-3); margin: var(--space-6) 0 var(--space-4); }
.day-head__number { font-size: var(--step-2); font-weight: 800; color: var(--brand); letter-spacing: -.03em; }

/* ------------------------------------------------------------ estado */

.empty {
    text-align: center; padding: var(--space-7) var(--space-4);
    border: 1px dashed var(--border-strong); border-radius: var(--radius); color: var(--text-2);
}
.empty .icon { width: 2.2rem; height: 2.2rem; color: var(--text-3); margin: 0 auto var(--space-3); }

.skeleton { background: linear-gradient(90deg, var(--surface-2) 25%, var(--bg-soft) 37%, var(--surface-2) 63%); background-size: 400% 100%; animation: shimmer 1.3s ease infinite; border-radius: var(--radius); }
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }
.is-loading { opacity: .55; transition: opacity .15s var(--ease); }

.pagination { display: flex; gap: var(--space-2); justify-content: center; align-items: center; margin-top: var(--space-6); }
.pagination a, .pagination span {
    min-width: 2.4rem; height: 2.4rem; padding-inline: .6rem; border-radius: var(--radius-sm);
    display: inline-grid; place-items: center; border: 1px solid var(--border);
    background: var(--surface); font-size: var(--step--1); color: var(--text-2);
}
.pagination a:hover { border-color: var(--brand); color: var(--brand); }
.pagination [aria-current="page"] { background: var(--gradient); border-color: transparent; color: #14100A; font-weight: 700; }

.note {
    display: flex; gap: var(--space-3); padding: var(--space-4);
    background: color-mix(in srgb, var(--brand-2) 12%, var(--surface));
    border: 1px solid color-mix(in srgb, var(--brand-2) 30%, transparent);
    border-radius: var(--radius); font-size: var(--step--1); color: var(--text-2);
}
.note .icon { color: color-mix(in srgb, var(--brand-2) 75%, var(--text)); flex: none; }

.tag-list { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* --------------------------------------------------- modo rascunho */

.preview-bar {
    display: flex; align-items: center; gap: var(--space-3); justify-content: center;
    background: color-mix(in srgb, var(--brand-3) 14%, var(--surface));
    border-bottom: 1px solid color-mix(in srgb, var(--brand-3) 35%, transparent);
    color: var(--text-2); font-size: var(--step--1);
    padding: var(--space-2) var(--space-5); text-align: center;
}
.preview-bar .icon { color: var(--brand-3); flex: none; }
body[data-preview="true"] .card--place[data-draft="true"]::before {
    content: "rascunho"; position: absolute; z-index: 2; top: var(--space-3); right: var(--space-3);
    background: var(--brand-3); color: #fff; font-size: .68rem; font-weight: 700;
    padding: .15rem .5rem; border-radius: var(--radius-full); letter-spacing: .03em;
}

/* ------------------------------------------------------ crédito de foto */

.credit {
    font-size: .72rem; color: var(--text-3);
    display: flex; align-items: center; gap: .4em;
}
.hero .credit {
    position: absolute; right: var(--space-4); bottom: var(--space-3);
    color: rgba(255, 255, 255, .82); z-index: 2;
}
.hero .credit .icon { width: .9em; height: .9em; }

/* Badge sobre o hero: participa do fluxo, ao contrário de .badge--float */
.badge--hero {
    background: rgba(255, 255, 255, .16);
    border-color: rgba(255, 255, 255, .28);
    color: #fff;
    backdrop-filter: blur(6px);
    padding: .38em .85em;
}

/* Num telefone o canto de baixo do hero é justamente onde terminam os selos
   e os botões, e a atribuição caía por cima deles. Crédito ilegível não
   cumpre a licença — então, em tela estreita, o crédito sai do canto e entra
   no fluxo, na linha logo abaixo do conteúdo do hero. Empurrar o hero para
   abrir folga não resolveria: o crédito está preso ao rodapé do hero e
   desceria junto. */
@media (max-width: 640px) {
    .hero .credit {
        position: static;
        justify-content: flex-end;
        text-align: right;
        padding: 0 var(--space-4) var(--space-4);
        margin-top: calc(var(--space-4) * -1);
    }
}

/* ------------------------------------------------------- abertura em faixa

   Uma faixa com `scroll-snap`, não um carrossel de biblioteca. A rolagem é o
   gesto nativo do toque e já funciona sem JavaScript nenhum; o script só
   acrescenta a passagem automática. */

.abertura { position: absolute; inset: 0; overflow: hidden; }

.abertura__faixa {
    display: flex; height: 100%;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    /* A barra de rolagem some, mas a rolagem fica: é uma faixa de imagens de
       tela cheia, e uma barra atravessada nela seria ruído. */
    scrollbar-width: none;
}
.abertura__faixa::-webkit-scrollbar { display: none; }

.abertura__quadro {
    position: relative; flex: 0 0 100%; width: 100%; height: 100%; margin: 0;
    scroll-snap-align: center;
    /* Recorta o que for posto dentro. O crédito é absoluto e media o texto
       contra a moldura, não contra a tela: sem este recorte, um crédito longo
       escapava pela direita e a parte cortada era o nome da licença. */
    overflow: hidden;
}
.abertura__quadro img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* O crédito é POR IMAGEM e fica sobre ela: parte do acervo é CC BY, que exige
   atribuição junto da obra — e esta é a primeira tela do guia.

   Ancorado nos DOIS lados e com quebra permitida. Preso só pela direita, ele
   media o texto sem teto e transbordava a moldura: um crédito de 66
   caracteres saía da tela pela direita, e a parte cortada era justamente o
   nome da licença. Crédito ilegível não cumpre a atribuição. */
.hero .abertura__credito {
    position: absolute; z-index: 2;
    left: 0; right: 0; bottom: var(--space-3);
    padding-inline: var(--space-4);
    justify-content: flex-end; flex-wrap: wrap; text-align: right;
    color: rgba(255, 255, 255, .82);
}

.abertura__pontos {
    position: absolute; left: 0; right: 0; bottom: var(--space-4);
    display: flex; justify-content: center; gap: var(--space-2); z-index: 3;
}
.abertura__pontos a {
    width: 2.2rem; height: .2rem; display: block;
    background: rgba(255, 255, 255, .35);
    transition: background .2s var(--ease);
}
.abertura__pontos a:hover { background: rgba(255, 255, 255, .6); }
.abertura__pontos a[aria-current="true"] { background: var(--brand-2); }

/* Alvo de toque de verdade sem engordar o traço: a área clicável cresce por
   pseudo-elemento, o desenho continua fino. */
.abertura__pontos a::before {
    content: ""; position: absolute; inset-block: -.7rem; width: 2.2rem;
}

@media (prefers-reduced-motion: reduce) {
    /* Rolagem suave também é movimento. Quem pediu menos movimento recebe o
       salto seco — e a passagem automática nem começa (ver 04-app.js). */
    .abertura__faixa { scroll-behavior: auto; }
}

/* ==================================================================
   REFINAMENTO VISUAL — direção editorial.

   Camada final do design system, carregada depois de components.css.
   Referência: `referenciavisual/` — azul profundo, laranja chapado,
   títulos em serifa, canto vivo e nenhum efeito de brilho.

   O que SAIU nesta revisão, e por quê: degradê em texto e em botão,
   borda que acendia no hover, manchas de luz desfocadas e cantos
   arredondados. A referência pede foco, não brilho.
   ================================================================== */

/* ------------------------------------------------------ decoração de fundo */

/* No lugar das manchas de luz: arcos concêntricos finos, como no material
   de referência. Ficam atrás de tudo e não recebem evento de mouse. */
.aurora { position: relative; isolation: isolate; }
.aurora::before {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    top: -14rem; right: -10rem; width: 34rem; height: 34rem;
    border-radius: var(--radius-circle);
    background:
        repeating-radial-gradient(circle at 50% 50%,
            transparent 0 3.4rem,
            var(--arco) 3.4rem 3.5rem);
    opacity: var(--arco-opacidade);
}
.aurora::after { content: none; }

/* Os arcos são a assinatura da direção editorial e ficam nos DOIS temas.
   Precisam de força própria em cada um: calculados sobre `--text`, no claro
   viravam um cinza claríssimo sobre fundo claríssimo e sumiam — o adereço
   existia no CSS e não na tela. */
:root {
    --arco: color-mix(in srgb, var(--text) 7%, transparent);
    --arco-opacidade: .55;
}
:root[data-theme="light"] {
    --arco: color-mix(in srgb, var(--brand) 22%, transparent);
    --arco-opacidade: .5;
}
@media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) {
        --arco: color-mix(in srgb, var(--brand) 22%, transparent);
        --arco-opacidade: .5;
    }
}

/* Arco de rodapé — o mesmo motivo, espelhado, atrás do rodapé. Fecha a
   página com a mesma geometria que a abre. */
.site-footer { position: relative; isolation: isolate; overflow: hidden; }
.site-footer::before {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    bottom: -18rem; left: -12rem; width: 38rem; height: 38rem;
    border-radius: var(--radius-circle);
    background:
        repeating-radial-gradient(circle at 50% 50%,
            transparent 0 3.4rem,
            var(--arco) 3.4rem 3.5rem);
    opacity: var(--arco-opacidade);
}

/* ------------------------------------------------ ornamentos geométricos

   Os arcos sozinhos bastavam no tema escuro, onde o fundo já tem
   profundidade própria. No claro a página é quase uma folha em branco e as
   seções se perdem umas nas outras — daí um segundo e um terceiro motivo, na
   mesma família: traço fino, nunca massa, sempre atrás de tudo.

   São VARIANTES, e não um adereço em toda `.aurora`. A home tem três seções
   com essa classe, e repetir a mesma forma nas três é o que transformaria
   discrição em papel de parede.

   Pseudo-elemento não entra na árvore de acessibilidade, então não há o que
   esconder de leitor de tela; `pointer-events: none` deixa o clique passar. */

.aurora--quadrado::after,
.aurora--triangulo::after {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    opacity: var(--arco-opacidade);
}

/* Quadrado inclinado — o canto vivo da direção editorial, sozinho. */
.aurora--quadrado::after {
    left: -7rem; bottom: -9rem; width: 22rem; height: 22rem;
    border: 1px solid var(--arco);
    transform: rotate(12deg);
}

/* Triângulo em CONTORNO.

   `evenodd` é o que abre o miolo: o caminho de fora e o de dentro se
   cancelam e sobra o anel. Sem a regra de preenchimento o navegador usaria
   `nonzero`, os dois caminhos somariam e o triângulo sairia chapado — massa,
   que é justamente o que esta direção visual recusa. */
.aurora--triangulo::after {
    left: -5rem; bottom: -7rem; width: 20rem; height: 20rem;
    background: var(--arco);
    /* O caminho de dentro NÃO é o de fora recuado em porcentagem — recuar
       assim engorda o traço perto do ápice e o afina na base. É o triângulo
       semelhante em torno do incentro, o único que fica paralelo aos três
       lados: a 20rem isso dá cerca de 1,5px, o mesmo peso da borda do
       quadrado. Recuo simples deixava o traço em 10px — contorno no nome,
       massa na tela. */
    clip-path: polygon(evenodd,
        50% 0%, 100% 100%, 0% 100%, 50% 0%,
        50% 1.05%, 99.25% 99.5%, 0.75% 99.5%, 50% 1.05%);
}

/* Em tela estreita o ornamento come metade da coluna de leitura sem
   acrescentar nada: encolhe e recua. */
@media (max-width: 640px) {
    .aurora--quadrado::after { width: 13rem; height: 13rem; left: -5rem; bottom: -5rem; }
    .aurora--triangulo::after { width: 12rem; height: 12rem; left: -4rem; bottom: -4rem; }
}

/* Linha de horizonte — um traço fino no acento separando o hero do conteúdo,
   ecoando o horizonte da marca. Um traço, não uma sombra: D14 continua
   valendo, e sombra é o que a direção visual recusou.

   VAI NO `::before`, e não no `::after`.

   O `::after` do hero é o VÉU que escurece a foto para o texto branco ficar
   legível. Escrever a linha de horizonte nele apagou o véu — mesmo seletor,
   declaração posterior — e o título sumiu em cima de qualquer foto clara.
   Foi assim que o hero do MADA, sobre a Arena das Dunas, ficou ilegível. */
.hero { position: relative; }
.hero::before {
    content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
    z-index: 1; background: var(--brand-2); opacity: .85; pointer-events: none;
}

/* ------------------------------------------------------------- títulos */

/* Serifa, sem degradê: o título é peso e contorno, não efeito. */
h1, h2, h3,
.title-lg, .title-md, .title-sm,
.section-head h2, .card__title, .day-head__number {
    font-family: var(--font-display);
    background: none;
    -webkit-background-clip: border-box;
    background-clip: border-box;
    color: var(--text);
    letter-spacing: -.012em;
    font-weight: 600;
}
h1, .title-lg { font-weight: 700; }
.hero h1 { text-shadow: 0 2px 24px rgba(0, 0, 0, .4); }

/* Sobrelinha: rótulo curto em caixa alta, no laranja da marca. */
.eyebrow {
    display: inline-flex; align-items: center; gap: .5em;
    font-family: var(--font-ui);
    font-size: .74rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
    color: var(--brand-2);
}
.card__eyebrow {
    font-family: var(--font-ui);
    color: var(--brand-2);
    letter-spacing: .1em;
    font-weight: 600;
}

/* ------------------------------------------------------- card fotográfico */

/* Variante da referência: a foto É o card e o texto vive sobre ela. */
.card--overlay {
    border: 0; min-height: 20rem; justify-content: flex-end; background: var(--surface-2);
}
.card--overlay .media { position: absolute; inset: 0; z-index: 0; height: 100%; aspect-ratio: auto; }
.card--overlay .media img { transition: transform .7s var(--ease); }
.card--overlay:hover .media img { transform: scale(1.06); }
.card--overlay::after {
    content: ""; position: absolute; inset: 0; z-index: 1;
    background: linear-gradient(180deg, rgba(6, 14, 24, .05) 18%, rgba(6, 14, 24, .6) 62%, rgba(6, 14, 24, .93) 100%);
}
.card--overlay .card__body { position: relative; z-index: 2; gap: var(--space-2); flex: 0 0 auto; }
.card--overlay .card__title { color: #fff; }
.card--overlay .card__desc { color: rgba(255, 255, 255, .82); -webkit-line-clamp: 2; }
.card--overlay .card__meta { color: rgba(255, 255, 255, .74); margin-top: var(--space-2); padding-top: 0; }

/* --------------------------------------------------------------- cards */

/* Sem borda acesa, sem halo: o card sobe um fio e a foto respira. */
.card { transition: transform .2s var(--ease), border-color .2s var(--ease), box-shadow .2s var(--ease); }
.card::before { content: none; }
.card:hover { transform: translateY(-2px); box-shadow: var(--shadow); border-color: var(--brand-2); }
.card--place .media img, .card--route .media img { transition: transform .6s var(--ease); }
.card--place:hover .media img, .card--route:hover .media img { transform: scale(1.04); }

/* Selo quadrado encostado no canto da imagem, como no material de referência.

   No canto ESQUERDO: o direito é do coração de favoritar, que fica por cima
   (z-index 3) e cobria o selo inteiro — a duração do roteiro sumia atrás de um
   botão. Ação à direita, informação à esquerda, que é a mesma divisão dos
   cards de local (`.badge--float`).

   Seletor com a mesma especificidade de `.card--route .card__days`, em
   components.css: um `.card__days` simples perderia a posição e a cor para
   ele, e o selo continuaria laranja só no comentário. */
.card--route .card__days {
    border-radius: 0; top: 0; right: auto; left: 0; padding: .3rem .7rem;
    background: var(--brand-2); color: var(--text-on-brand);
    font-family: var(--font-ui); box-shadow: none;
}
.badge--float {
    border-radius: 0; top: 0; left: 0;
    background: rgba(6, 14, 24, .72); box-shadow: none;
    font-family: var(--font-ui);
}

/* ---------------------------------------------------- categoria em relevo */

.card--cat {
    padding: var(--space-5) var(--space-3);
    background: var(--surface);
    transition: transform .2s var(--ease), border-color .2s var(--ease);
}
.card--cat .card__icon {
    width: 3rem; height: 3rem; border-radius: 0;
    background: color-mix(in srgb, var(--brand-2) 14%, transparent);
    color: var(--brand-2);
    box-shadow: none;
    transition: background .2s var(--ease), color .2s var(--ease);
}
.card--cat .card__icon .icon { width: 1.6rem; height: 1.6rem; }
.card--cat strong { font-family: var(--font-display); font-weight: 600; }

/* A contagem de locais fica na MESMA linha em todos os cards da fileira.
   "Pontos turísticos" quebra em duas linhas e os outros não, e o `small`
   daquele card descia junto — desalinhando a fileira inteira.

   Ancorar no rodapé, e não reservar altura fixa para o título: os cards já
   esticam para a mesma altura dentro da fileira (é o padrão do grid), então
   `margin-top: auto` empurra a contagem para baixo em todos igualmente. Um
   título de três linhas continua cabendo, sem número mágico para revisar. */
.card--cat {
    display: flex;
    flex-direction: column;
    align-items: center;
    height: 100%;
}
.card--cat small { margin-top: auto; padding-top: var(--space-2); }
.card--cat small { font-family: var(--font-ui); }
.card--cat:hover { transform: translateY(-2px); border-color: var(--brand-2); }
.card--cat:hover .card__icon { background: var(--brand-2); color: var(--text-on-brand); }

/* -------------------------------------------------------------- botões */

/* Retângulo sólido, sem varredura de luz. */
.btn {
    position: relative; overflow: hidden; border-radius: 0;
    font-family: var(--font-ui); font-weight: 600; letter-spacing: .01em;
    background: var(--brand-2); color: var(--text-on-brand);
}
.btn::after { content: none; }
.btn:hover { transform: none; background: var(--brand-3); box-shadow: none; }
.btn--ghost { background: transparent; border-color: var(--border-strong); color: var(--text); }
.btn--ghost:hover { background: transparent; border-color: var(--brand-2); color: var(--brand-2); }
.btn--light { background: rgba(255, 255, 255, .12); border-color: rgba(255, 255, 255, .28); color: #fff; }
.btn--light:hover { background: rgba(255, 255, 255, .2); }

/* ---------------------------------------------------------- cabeçalho */

.site-header { transition: background .3s var(--ease), box-shadow .3s var(--ease); }
.site-header[data-scrolled="true"] {
    background: color-mix(in srgb, var(--surface) 96%, transparent);
    box-shadow: 0 1px 0 var(--border);
}
.brand__text { font-family: var(--font-display); font-weight: 700; letter-spacing: -.01em; }
.brand__mark { border-radius: 0; overflow: hidden; background: var(--brand-2); box-shadow: none; }
.brand__mark::after { content: none; }
.brand__mark .icon { color: var(--text-on-brand); }

/* Cidade com logo próprio troca o campo laranja pelo azul-profundo — o mesmo
   que build/make-icons.php usa no ícone de app, para que a aba do navegador e
   o cabeçalho não sejam duas marcas diferentes.

   O campo é fixo nos dois temas de propósito: a ponte do logo é branca, e
   sobre o fundo claro ela sumiria. O canto vivo continua — ele é a assinatura
   da plataforma, não da cidade. */
/* O selo segue a PROPORÇÃO do logo, em vez de forçá-lo num quadrado.

   A marca de Natal é 1,63:1. Espremida no quadrado de 2rem, a arte encolhia
   para caber na altura e sobrava campo vazio dos dois lados — o mapa e as
   letras ficavam menores do que o cabeçalho tinha espaço para mostrar. A
   altura é que manda, porque é ela que o cabeçalho fixa; a largura acompanha.

   Cidade com logo quadrado continua com selo quadrado: `aspect-ratio` não
   força nada, só deixa de impedir. */
/* O selo segue a proporção da arte: a altura é a que o cabeçalho fixa, a
   largura vem da imagem. Forçar o quadrado encolhia o desenho para caber na
   altura e deixava transparência sobrando dos lados. */
.brand__mark--logo {
    background: var(--campo-marca);
    padding: 2px;
    width: fit-content;
}
/* A ALTURA manda e a largura vem da imagem.

   E a altura é um COMPRIMENTO, não `100%`. Com `100%` o cálculo entra em
   ciclo: a largura do selo depende da imagem, a largura da imagem depende da
   altura dela, e a altura depende do selo — o navegador desiste da
   porcentagem e usa o tamanho natural do arquivo, que é o que fazia a arte
   vazar do cabeçalho e ser cortada pelo `overflow`. Um comprimento fixo
   quebra o ciclo. */
.brand__mark--logo img,
.adm-marca__sinal--logo img {
    height: calc(2rem - 4px); width: auto;
    object-fit: contain;
    display: block;
}
.site-nav a { font-family: var(--font-ui); border-radius: 0; }
.site-nav a[aria-current="page"] {
    background: transparent; color: var(--brand-2);
    box-shadow: inset 0 -2px 0 var(--brand-2);
}

/* ---------------------------------------------------------- movimento */

/* Entrada ao rolar — discreta. A classe só ganha estado inicial quando o
   JS confirma suporte; sem script, o conteúdo aparece normalmente. */
.js-motion .reveal { opacity: 0; transform: translateY(14px); }
.js-motion .reveal.is-in {
    opacity: 1; transform: none;
    transition: opacity .5s var(--ease), transform .5s var(--ease);
}
.js-motion .reveal:nth-child(2) { transition-delay: .05s; }
.js-motion .reveal:nth-child(3) { transition-delay: .1s; }
.js-motion .reveal:nth-child(4) { transition-delay: .15s; }
.js-motion .reveal:nth-child(5) { transition-delay: .2s; }
.js-motion .reveal:nth-child(6) { transition-delay: .25s; }

.hero__bg { will-change: transform; }
.hero::after {
    background:
        linear-gradient(100deg, rgba(6, 14, 24, .84) 0%, rgba(6, 14, 24, .52) 45%, rgba(6, 14, 24, .16) 78%),
        linear-gradient(180deg, rgba(6, 14, 24, .3) 0%, rgba(6, 14, 24, .1) 40%, rgba(6, 14, 24, .72) 90%, rgba(6, 14, 24, .88) 100%);
}

/* A cauda extra nos ultimos 10% existe por causa do CREDITO, que mora
   exatamente ali. O credito e branco translucido sobre uma FOTOGRAFIA, e
   fotografia varia: medido, o acervo de hoje passa com folga, mas uma foto
   futura estourada no rodape - areia ao meio-dia, ceu branco - derrubaria a
   atribuicao para baixo de 4,5:1. Atribuicao que ninguem le nao cumpre a
   licenca, entao o piso nao pode depender de qual foto entrou. */

@media (prefers-reduced-motion: reduce) {
    .js-motion .reveal, .js-motion .reveal.is-in { opacity: 1; transform: none; transition: none; }
}

/* --------------------------------------------------------- barra inferior */

.tabbar { display: none; }

@media (max-width: 860px) {
    .tabbar {
        position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
        display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
        background: var(--surface);
        border-top: 1px solid var(--border);
        padding: .4rem .3rem calc(.4rem + env(safe-area-inset-bottom));
    }
    .tabbar a {
        display: flex; flex-direction: column; align-items: center; gap: .18rem;
        padding: .35rem 0; font-size: .68rem; font-weight: 600; color: var(--text-3);
        font-family: var(--font-ui);
    }
    .tabbar a .icon { width: 1.35rem; height: 1.35rem; }
    .tabbar a[aria-current="page"] { color: var(--brand-2); }
    body { padding-bottom: 4.4rem; }
    .site-nav--mobile { display: none; }
}

/* --------------------------------------------------------- acabamentos */

.timeline::before { background: var(--border-strong); }
.timeline__dot {
    background: var(--surface); border-radius: var(--radius-circle);
    border-color: var(--brand-2); color: var(--brand-2);
    box-shadow: none; font-family: var(--font-ui);
}
.timeline__item:hover .timeline__dot { background: var(--brand-2); color: var(--text-on-brand); }
.timeline__card { transition: border-color .2s var(--ease); }
.timeline__item:hover .timeline__card { border-color: var(--brand-2); }
.timeline__time { font-family: var(--font-ui); color: var(--brand-2); }
.day-head__number { font-size: var(--step-3); color: var(--brand-2); }

.panel { background: var(--surface); }
.chip {
    font-family: var(--font-ui); font-weight: 500; border-radius: 0;
    transition: background .18s var(--ease), color .18s var(--ease), border-color .18s var(--ease);
}
.chip:hover { transform: none; border-color: var(--brand-2); color: var(--brand-2); }
.chip[aria-pressed="true"], .chip.is-active {
    background: var(--brand-2); border-color: var(--brand-2);
    color: var(--text-on-brand); box-shadow: none;
}
.badge { border-radius: 0; font-family: var(--font-ui); }
.badge--brand { background: color-mix(in srgb, var(--brand-2) 14%, transparent); color: var(--brand-2); }
.search, .suggest, .view-toggle, .view-toggle button,
.pagination a, .pagination span,
.media, .card, .panel, .map, .empty, .skeleton, .map__btn, .map__popup { border-radius: 0; }
.search--hero { box-shadow: var(--shadow-lg); }
.pagination [aria-current="page"] { background: var(--brand-2); border-color: var(--brand-2); color: var(--text-on-brand); }
.section-head__link { color: var(--brand-2); font-family: var(--font-ui); }
.credit { font-family: var(--font-ui); }
.note {
    background: color-mix(in srgb, var(--brand-2) 8%, var(--surface));
    border-color: color-mix(in srgb, var(--brand-2) 28%, transparent);
    border-radius: 0;
}
.note .icon { color: var(--brand-2); }
.preview-bar {
    background: color-mix(in srgb, var(--brand-2) 12%, var(--surface));
    border-color: color-mix(in srgb, var(--brand-2) 30%, transparent);
}
.preview-bar .icon { color: var(--brand-2); }

/* ------------------------------------------------- mosaico de destaques */

.feature-grid { display: grid; gap: var(--space-4); }
.feature-grid__side { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); }
.feature-grid .card--overlay { min-height: 15rem; height: 100%; }

@media (min-width: 900px) {
    .feature-grid { grid-template-columns: 1.15fr 1fr; align-items: stretch; }
    .feature-grid__main { display: grid; }
    .feature-grid__main .card--overlay { min-height: 30rem; }
    .feature-grid__side { grid-template-columns: 1fr 1fr; }
    .feature-grid__side .card--overlay { min-height: 14.2rem; }
}

.rail .card--overlay { min-height: 16rem; }
.panel h3 { display: flex; align-items: center; gap: .5em; font-family: var(--font-display); }
.panel h3 .icon { color: var(--brand-2); }

/* ---------------------------------------------------------- ordenação */

/* "Sort by / Price" da referência: rótulo discreto, valor no laranja. */
.sort {
    display: inline-flex; align-items: center; gap: .5em;
    padding: .34rem .5rem .34rem .8rem;
    border: 1px solid var(--border-strong); border-radius: 0;
    background: transparent; color: var(--text-3);
    font-size: var(--step--1); font-family: var(--font-ui); font-weight: 500;
}
.sort:focus-within { border-color: var(--brand-2); }
.sort .icon { color: var(--text-3); }
.sort select {
    border: 0; background: transparent; outline: none; cursor: pointer;
    padding: .28rem 1.4rem .28rem 0; color: var(--brand-2); font-weight: 600;
    appearance: none;
    background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: right .55rem center, right .3rem center;
    background-size: .3rem .3rem, .3rem .3rem;
    background-repeat: no-repeat;
}
/* O menu nativo abre com o fundo do sistema: forçar o tema nas opções. */
.sort select option { background: var(--surface); color: var(--text); }

/* ---------------------------------------------- acabamento de links */

.card__title a, .data-list a, .suggest__item, .timeline__card h3 a, .tabbar a {
    color: inherit; text-decoration: none;
}
.card__title a:hover,
.card--overlay .card__title a:hover,
.timeline__card h3 a:hover { color: var(--brand-2); }

/* ============================ marcador do mapa ============================ */

/* A PONTA do pin cai exatamente sobre a coordenada: ela é um triângulo
   DENTRO da caixa, e translate(-50%, -100%) ancora a base no ponto. */
.map__marker {
    position: absolute; width: 2rem; height: 2.5rem;
    background: none; border: 0; padding: 0; display: block;
    rotate: none; cursor: pointer; filter: drop-shadow(0 3px 6px rgba(0, 0, 0, .5));
    transition: scale .15s var(--ease);
}
.map__marker::before {
    content: ""; position: absolute; inset: 0 0 .5rem 0; border-radius: var(--radius-circle);
    background: var(--brand-2); border: 2px solid #fff;
}
.map__marker::after {
    content: ""; position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
    border-left: .34rem solid transparent; border-right: .34rem solid transparent;
    border-top: .6rem solid #fff;
}
.map__marker .icon {
    position: absolute; left: 50%; top: 1rem; transform: translate(-50%, -50%);
    width: 1.05rem; height: 1.05rem; color: var(--text-on-brand); rotate: none;
}
.map__marker:hover, .map__marker.is-active { scale: 1.15; z-index: 5; }
.map__marker.is-active::before { border-color: var(--brand-2); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-2) 40%, transparent); }
.map__marker--accent::before { background: var(--brand-3); }
.map__popup { transform: translate(-50%, calc(-100% - 2.9rem)); }

/* Fileira de categorias: altura uniforme. Um rótulo que quebra em duas
   linhas ("Pontos turísticos") esticava só o seu bloco e desalinhava a fileira. */
.grid--cats { grid-auto-rows: 1fr; }
.card--cat { justify-content: flex-start; min-height: 10.5rem; }
.card--cat strong { display: flex; align-items: center; min-height: 2.6em; text-align: center; }
.card--cat small { margin-top: auto; }

/* ==================================================================
   MAPA — acabamento no tom do template.

   Os tiles do OpenStreetMap vêm no estilo padrão, colorido e claro:
   ao lado do azul profundo eles gritam. Em vez de trocar de provedor
   (custo e dependência), o mapa é tingido por filtro CSS até cair na
   paleta do guia. É reversível e não muda uma linha de JavaScript.
   ================================================================== */

.map {
    background: var(--bg-soft);
    border: 1px solid var(--border);
}
.map__tiles {
    /* invert + hue-rotate é o par que transforma um mapa claro em escuro
       mantendo a leitura; o resto ajusta o resultado ao azul do tema. */
    filter: invert(1) hue-rotate(188deg) brightness(1.05) contrast(.85) saturate(.45);
}
/* A camada de tinta cobre o que o filtro não alcança e amarra o mapa ao fundo. */
.map::after {
    content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
    background: color-mix(in srgb, var(--brand) 30%, transparent);
    mix-blend-mode: color;
}
.map__markers, .map__controls, .map__popup, .map__attribution { z-index: 2; }

/* Marcador: quadrado de canto vivo com a ponta embaixo, como o resto do template. */
.map__marker::before { border-radius: 0; border-width: 1px; }
.map__marker::after { border-top-color: var(--brand-2); }
.map__marker--accent::after { border-top-color: var(--brand-3); }

/* Controles: mesmos retângulos do resto da interface. */
.map__controls { top: 0; right: 0; gap: 0; }
.map__btn {
    width: 2.4rem; height: 2.4rem; border-radius: 0;
    background: var(--surface); border-color: var(--border);
    color: var(--text-2); box-shadow: none;
    font-family: var(--font-ui); font-size: 1.2rem;
}
.map__btn + .map__btn { border-top: 0; }
.map__btn:hover { background: var(--brand-2); border-color: var(--brand-2); color: var(--text-on-brand); }

.map__attribution {
    background: color-mix(in srgb, var(--surface) 88%, transparent);
    color: var(--text-3); border-radius: 0; font-family: var(--font-ui);
    padding: .18rem .5rem;
}
.map__attribution a { color: var(--text-3); }

.map__popup {
    background: var(--surface); border-color: var(--brand-2);
    box-shadow: var(--shadow-lg);
}
.map__popup strong { font-family: var(--font-display); font-size: var(--step-0); }
.map__popup small { font-family: var(--font-ui); }

/* ==================================================================
   FAIXA COM SETAS

   A faixa continua rolável no toque (é o gesto natural no celular),
   mas no desktop a navegação é por seta: rolagem horizontal com mouse
   é desconfortável e, pior, invisível — nada indica que há mais conteúdo
   à direita. As setas só aparecem quando existe o que rolar, e somem
   quando a faixa chega ao fim.
   ================================================================== */

.rail-wrap { position: relative; }

.rail {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(16rem, 1fr);
    gap: var(--space-4);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;              /* a navegação é pela seta */
    padding-bottom: var(--space-2);
}
.rail::-webkit-scrollbar { display: none; }
.rail > * { scroll-snap-align: start; }
.rail:focus-visible { outline-offset: 6px; }

@media (min-width: 861px) {
    .rail { grid-auto-columns: minmax(18rem, 1fr); }
}

/* Seta: retângulo de canto vivo, no mesmo vocabulário dos botões. */
.rail__nav {
    position: absolute;
    top: calc(50% - var(--space-2));
    transform: translateY(-50%);
    z-index: 4;
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 3.5rem;
    padding: 0;
    border: 1px solid var(--border-strong);
    border-radius: 0;
    background: color-mix(in srgb, var(--surface) 92%, transparent);
    backdrop-filter: blur(6px);
    color: var(--text);
    cursor: pointer;
    transition: background .18s var(--ease), color .18s var(--ease),
                border-color .18s var(--ease), opacity .18s var(--ease);
}
.rail__nav .icon { width: 1.3rem; height: 1.3rem; }
.rail__nav:hover {
    background: var(--brand-2);
    border-color: var(--brand-2);
    color: var(--text-on-brand);
}
.rail__nav:disabled { opacity: .3; cursor: default; }
.rail__nav:disabled:hover {
    background: color-mix(in srgb, var(--surface) 92%, transparent);
    border-color: var(--border-strong);
    color: var(--text);
}

/* As setas invadem um pouco a faixa, como no material de referência. */
.rail__nav--prev { left: calc(var(--space-4) * -1); }
.rail__nav--next { right: calc(var(--space-4) * -1); }

/* Em telas onde a faixa encosta na borda da viewport, a seta volta para dentro. */
@media (max-width: 1200px) {
    .rail__nav--prev { left: 0; }
    .rail__nav--next { right: 0; }
}

/* No toque a rolagem é o gesto esperado: as setas saem de cena. A largura entra
   na conta porque nem todo navegador móvel reporta `hover: none` corretamente,
   e numa tela estreita a seta cobriria o card. */
@media (hover: none), (max-width: 860px) {
    .rail__nav { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .rail { scroll-behavior: auto; }
}

/* Card fotográfico curto: os filhos do corpo não podem encolher.
   Com flex-shrink padrão, num card baixo o título comprimia sobre a
   sobrelinha e os dois textos se sobrepunham. */
.card--overlay .card__body > * { flex: none; min-height: 0; }
.card--overlay .card__body { justify-content: flex-end; }

/* No card pequeno do mosaico, a descrição cede lugar ao essencial. */
@media (min-width: 900px) {
    .feature-grid__side .card--overlay .card__desc { display: none; }
}

/* Legibilidade sobre foto clara: o degradê escurece antes de chegar ao
   texto, e a sobrelinha ganha sombra própria. Sem isso, o laranja da
   categoria some numa foto de céu claro ou areia. */
.card--overlay::after {
    background: linear-gradient(180deg,
        rgba(6, 14, 24, .05) 0%,
        rgba(6, 14, 24, .35) 42%,
        rgba(6, 14, 24, .82) 70%,
        rgba(6, 14, 24, .96) 100%);
}
.card--overlay .card__eyebrow { text-shadow: 0 1px 10px rgba(6, 14, 24, .9); }
.card--overlay .card__meta { text-shadow: 0 1px 8px rgba(6, 14, 24, .8); }

/* ==================================================================
   DOCUMENTO LEGAL

   Privacidade e termos são textos longos que as pessoas leem de fato
   quando precisam. Aqui o objetivo é legibilidade: medida de linha
   controlada, hierarquia clara e tabela que não estoura a página.
   ================================================================== */

.legal { max-width: 70ch; }
.legal h2 {
    font-size: var(--step-2);
    margin: var(--space-7) 0 var(--space-3);
    padding-top: var(--space-4);
    border-top: 1px solid var(--border);
    scroll-margin-top: calc(var(--header-h) + var(--space-4));
}
.legal h2:first-child { margin-top: 0; border-top: 0; padding-top: 0; }
.legal h3 { font-size: var(--step-1); margin: var(--space-5) 0 var(--space-2); }
.legal p, .legal li { color: var(--text-2); }
.legal ul, .legal ol { margin: 0 0 var(--space-4); padding-left: 1.3rem; }
.legal ul { list-style: disc; }
.legal ol { list-style: decimal; }
.legal li { margin-bottom: var(--space-2); }
.legal li::marker { color: var(--brand-2); }
.legal hr { border: 0; border-top: 1px solid var(--border); margin: var(--space-6) 0; }
.legal blockquote {
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-left: 3px solid var(--brand-2);
    background: var(--surface);
    color: var(--text-2);
}
.legal code {
    background: var(--surface-2);
    padding: .1rem .35rem;
    font-size: .9em;
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
}

/* Tabela: rola dentro da própria caixa, nunca empurra a página. */
.table-wrap { overflow-x: auto; margin: 0 0 var(--space-5); border: 1px solid var(--border); }
.table-wrap table { border-collapse: collapse; width: 100%; font-size: var(--step--1); }
.table-wrap th, .table-wrap td {
    padding: var(--space-3);
    text-align: left;
    vertical-align: top;
    border-bottom: 1px solid var(--border);
}
.table-wrap th {
    background: var(--surface-2);
    color: var(--text);
    font-family: var(--font-ui);
    font-weight: 600;
    white-space: nowrap;
}
.table-wrap td { color: var(--text-2); }
.table-wrap tr:last-child td { border-bottom: 0; }

/* Índice do documento na coluna lateral. */
.toc a { font-size: var(--step--1); }
.toc a[aria-current="page"] { color: var(--brand-2); }

/* ------------------------------------------------------------------ conta
   Entrar, sair e o menu do cabeçalho. O menu é um popover simples: sem
   JavaScript ele fica visível ao receber foco, então continua utilizável. */

.site-header__conta { flex-shrink: 0; }
.site-header__conta .icon,
.conta__botao .icon { width: 1.05em; height: 1.05em; }

.conta { position: relative; flex-shrink: 0; }
.conta__botao { max-width: 11rem; }
.conta__botao span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.conta__menu {
    position: absolute;
    right: 0;
    top: calc(100% + .5rem);
    z-index: 40;
    min-width: 13rem;
    padding: var(--space-2);
    background: var(--surface-1);
    border: 1px solid var(--border-strong);
    box-shadow: var(--shadow-lg, 0 12px 32px rgba(0, 0, 0, .35));
}

.conta__email {
    display: block;
    padding: var(--space-2) var(--space-3);
    font-size: var(--step--2);
    color: var(--text-3);
    border-bottom: 1px solid var(--border);
    margin-bottom: var(--space-2);
    overflow: hidden;
    text-overflow: ellipsis;
}

.conta__menu a,
.conta__menu button {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-2) var(--space-3);
    font: inherit;
    font-size: var(--step--1);
    font-family: var(--font-ui);
    color: var(--text-2);
    background: none;
    border: 0;
    text-align: left;
    cursor: pointer;
}
.conta__menu a:hover,
.conta__menu button:hover { background: var(--surface-2); color: var(--brand); }
.conta__menu .icon { width: 1.1em; height: 1.1em; }

@media (max-width: 860px) {
    .site-header__conta span, .conta__botao span { display: none; }
    .conta__botao { max-width: none; }

    /* Quem empurrava o botão de conta para a direita era a busca do
       cabeçalho, com `margin-left: auto`. No celular ela some — e o botão
       ficava colado na marca, no meio de uma barra vazia. O `auto` precisa
       passar para quem sobrou. */
    .site-header__conta, .site-header .conta { margin-left: auto; }
}

/* ------------------------------------------------------------ minha conta
   Formulários em painéis. Nenhum depende de JavaScript: cada um dá POST e a
   página volta com um aviso — inclusive o de excluir a conta. */

.conta-pagina { max-width: 44rem; margin: 0 auto; }
.conta-pagina__topo { margin-bottom: var(--space-5); }
.conta-pagina__topo p { color: var(--text-2); }

.aviso {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-3);
    margin-bottom: var(--space-5);
    font-size: var(--step--1);
    background: var(--surface-2);
    border-left: 3px solid var(--brand);
}
.aviso--erro { border-left-color: #E5484D; }
.aviso .icon { flex-shrink: 0; margin-top: .15em; }

.painel {
    padding: var(--space-5);
    margin-bottom: var(--space-5);
    background: var(--surface-1);
    border: 1px solid var(--border);
}
.painel__titulo {
    font-family: var(--font-display);
    font-size: var(--step-1);
    margin-bottom: var(--space-3);
}
.painel__lead {
    font-size: var(--step--1);
    color: var(--text-2);
    margin-bottom: var(--space-4);
}
.painel .table-wrap { margin-bottom: 0; }

/* O painel de exclusão é visualmente distinto porque a ação é irreversível:
   ninguém deve chegar nele achando que é mais um formulário de preferência. */
.painel--perigo { border-color: rgba(229, 72, 77, .45); }
.painel--perigo .painel__titulo { color: #FF6B6E; }

.campo { display: block; margin-bottom: var(--space-4); }
.campo > span {
    display: block;
    margin-bottom: var(--space-2);
    font-family: var(--font-ui);
    font-size: var(--step--1);
    font-weight: 600;
    color: var(--text-2);
}
.campo > span em { font-style: normal; font-weight: 400; color: var(--text-3); }
.campo > span code {
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    background: var(--surface-2);
    padding: .1rem .3rem;
}
/* Lista fechada de tipos era um convite a esquecer um: data, número e
   textarea ficavam com o visual cru do navegador — fundo branco no meio
   de um tema escuro. Nega-se o que NÃO é campo de texto. */
.campo input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
.campo textarea,
.campo select {
    width: 100%;
    padding: var(--space-3);
    font: inherit;
    font-size: var(--step--1);
    color: var(--text);
    background: var(--surface-2);
    border: 1px solid var(--border-strong);
    border-radius: 0;
}
.campo input:focus-visible,
.campo select:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.campo__nota {
    font-size: var(--step--2);
    color: var(--text-3);
    margin-bottom: var(--space-4);
}

.opcao {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3) 0;
    border-top: 1px solid var(--border);
    cursor: pointer;
}
.opcao input { margin-top: .28em; width: 1.05rem; height: 1.05rem; accent-color: var(--brand); flex-shrink: 0; }
.opcao strong { display: block; font-size: var(--step--1); font-weight: 600; }
.opcao small { display: block; color: var(--text-3); font-size: var(--step--2); margin-top: .15rem; }
/* `strong` dentro do `small` continua inline: a regra acima é para o strong
   que É o título da opção, não para uma ênfase no meio da frase. */
.opcao small strong { display: inline; font-size: inherit; color: var(--text-2); }
.opcao + .opcao { border-top: 1px solid var(--border); }
.opcao:last-of-type { border-bottom: 1px solid var(--border); margin-bottom: var(--space-4); }

.btn--perigo { background: #E5484D; border-color: #E5484D; color: #fff; }
.btn--perigo:hover { box-shadow: 0 6px 20px rgba(229, 72, 77, .35); }

/* ------------------------------------------------------------- favoritos
   O coração vive sobre a foto do card. `is-active` é o estado real vindo do
   servidor; a animação existe só para confirmar o toque. */

.fav-form { position: absolute; top: var(--space-3); right: var(--space-3); z-index: 3; }
.fav-form--wide { position: static; }

.fav {
    display: grid;
    place-items: center;
    width: 2.2rem;
    height: 2.2rem;
    padding: 0;
    color: #fff;
    background: rgba(11, 20, 32, .55);
    border: 1px solid rgba(255, 255, 255, .22);
    backdrop-filter: blur(6px);
    cursor: pointer;
    transition: color .18s ease, background .18s ease, transform .18s ease;
}
.card > .fav,
.card > a.fav { position: absolute; top: var(--space-3); right: var(--space-3); z-index: 3; }

.fav .icon { width: 1.15rem; height: 1.15rem; }
.fav:hover { color: #FF7A85; border-color: rgba(255, 122, 133, .5); transform: translateY(-1px); }
.fav:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Coração cheio = salvo. A opacidade da forma sobe de .24 para 1: é a mesma
   peça do sprite, sem um segundo ícone só para o estado ligado. */
.fav.is-active { color: #FF5A66; border-color: rgba(255, 90, 102, .55); background: rgba(60, 12, 18, .6); }

.fav-wide { gap: var(--space-2); }
.fav-wide.is-active { color: #FF5A66; }

@keyframes fav-pop {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.28); }
    100% { transform: scale(1); }
}
.fav.just-saved .icon { animation: fav-pop .32s ease; }

@media (prefers-reduced-motion: reduce) {
    .fav.just-saved .icon { animation: none; }
}

/* Lista dos favoritos que saíram do ar. */
.lista-simples { list-style: none; border-top: 1px solid var(--border); }
.lista-simples li {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--border);
    font-size: var(--step--1);
}
.lista-simples li > span { display: flex; align-items: center; gap: var(--space-2); color: var(--text-2); }
.lista-simples small { color: var(--text-3); }

/* Hero sem foto (favoritos): mais baixo. O seletor precisa ter a mesma
   forma de `.hero--page .hero__inner`, senão perde na cascata e o
   espaçamento continua o da página com imagem. */
.hero--slim .hero__inner { padding-block: var(--space-6); }
.hero--slim h1 { margin-bottom: var(--space-2); }
.empty .btn { margin-top: var(--space-4); }

/* Horários vêm como lista de linhas; cada uma na sua. */
.linha-horario { display: block; }
.linha-horario + .linha-horario { margin-top: 2px; }

/* ------------------------------------------------------- a confirmar

   O guia publica ficha com pendência desde 25/08/2026, e isto é o que torna
   isso honesto: o que ainda não foi checado é dito **antes** do conteúdo, não
   escondido num rodapé. Publicar sem este bloco seria publicar como se
   estivesse tudo confirmado.

   Laranja da marca, não vermelho: não é erro nem perigo — é uma informação
   que falta, e o lugar continua valendo a visita. */

.a-confirmar-bloco {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4);
    margin-top: var(--space-4);
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-left: 3px solid var(--brand-2);
    font-size: var(--step--1);
    color: var(--text-2);
}
.a-confirmar-bloco .icon { flex: none; margin-top: .15em; color: var(--brand-2); }
.a-confirmar-bloco strong { color: var(--text); }
.a-confirmar-bloco small {
    display: block;
    margin-top: var(--space-2);
    font-size: var(--step--2);
    color: var(--text-3);
}

/* O campo vazio some da tela e some do problema. Dizer "a confirmar" no lugar
   é o que impede alguém de concluir que o lugar abre a qualquer hora. */
.a-confirmar { color: var(--text-3); font-style: italic; }

/* A dúvida da ficha, repetida na parada do roteiro. Discreta de propósito: o
   aviso forte já está no topo da página, e repetir o tom de alerta treze
   vezes numa linha do tempo faz o leitor parar de ler todos. Aqui o papel é
   só marcar QUAL parada é, para quem vai ligar antes de sair. */
.timeline__aviso {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-top: var(--space-3);
    font-size: var(--step--2);
    color: var(--text-3);
}
.timeline__aviso .icon { flex: none; margin-top: .15em; color: var(--brand-2); }

/* ------------------------------------------------- quando o evento acontece

   A tarja de data é o cartão de evento. Um cartão que não diz quando é não
   serve; um que diz "dezembro" com cara de data serve para pior que nada —
   alguém compra passagem.

   Por isso os dois estados são visualmente diferentes, e não a mesma tarja
   com texto diferente: data apurada usa o laranja da marca, com o peso de
   quem afirma; período típico usa a superfície neutra e a borda tracejada,
   que é o vocabulário do "ainda não confirmado" já usado no resto do guia.
   No canto esquerdo, como o selo do roteiro — a direita é do coração. */

.card--event .card__quando {
    position: absolute; top: 0; left: 0; right: 0;
    /* `block`, e não `flex`: a tarja tem duas frases ("costuma ser em
       dezembro" e "data a confirmar") e precisa quebrar linha como texto.
       Em flex, cada pedaço vira item e a quebra abria um vão no meio. */
    display: block; line-height: 1.35;
    padding: .3rem .7rem;
    background: var(--brand-2); color: var(--text-on-brand);
    font-family: var(--font-ui); font-size: .76rem; font-weight: 700;
}
.card--event .card__quando .icon {
    width: .9em; height: .9em; margin-right: .35em; vertical-align: -.12em;
}

.card--event .card__quando--sem-data {
    background: var(--surface-1); color: var(--text-2);
    border: 1px dashed var(--border-strong); border-left: 0; border-top: 0;
    font-weight: 500;
}
.card--event .card__quando--sem-data .icon { color: var(--brand-2); }
.card--event .card__quando--sem-data strong { color: var(--text); font-weight: 700; }

/* ------------------------------------------------------------ troca de tema

   Três botões, não um alternador de dois estados: "seguir o sistema" é uma
   escolha legítima e a mais comum — quem já configurou o aparelho para
   escurecer à noite não quer que o site ignore isso. Um botão de duas
   posições obriga a pessoa a escolher um lado e perder o automático. */

.tema-troca {
    display: flex; align-items: center; gap: var(--space-3);
    padding: var(--space-4) 0 0;
    border-top: 1px solid var(--border);
    font-size: var(--step--2); color: var(--text-3);
    font-family: var(--font-ui);
}
.tema-troca__opcoes { display: flex; }
.tema-troca__opcoes button {
    padding: .35rem .7rem; cursor: pointer;
    background: transparent; color: var(--text-3);
    border: 1px solid var(--border-strong); border-right-width: 0;
    font: inherit;
}
.tema-troca__opcoes button:last-child { border-right-width: 1px; }
.tema-troca__opcoes button:hover { color: var(--text); }
.tema-troca__opcoes button[aria-pressed="true"] {
    background: var(--brand-2); color: var(--text-on-brand);
    border-color: var(--brand-2);
}

/* ------------------------------------------------------------------
   Entrar, e o perfil que a conta mostra aos outros.

   A página tinha um cartão de 30rem no meio de uma tela de 80rem, com
   metade do espaço vazio abaixo da dobra. Aqui ela vira duas colunas: à
   esquerda o motivo de existir uma conta, à direita o ato de entrar.

   Abaixo de 62rem as colunas empilham — o motivo primeiro, porque é ele
   que faz alguém decidir clicar.
   ------------------------------------------------------------------ */

.auth {
    /* A altura do cabeçalho sai da conta para a página ocupar a tela sem
       criar rolagem. `min-height`, não `height`: com o aviso de rascunho no
       topo ou um recado de erro, ela cresce em vez de cortar. */
    min-height: calc(100vh - var(--header-h) - 5rem);
    display: flex;
    align-items: center;
    padding: var(--space-6) 0;
}

.auth__grid {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
    gap: clamp(var(--space-5), 5vw, var(--space-7));
    align-items: center;
    width: 100%;
}

/* --------------------------------------------------------------- motivo */

/* `city_mark()` devolve o mesmo sinal do cabeçalho, em dois formatos: com
   logo próprio (um `<img>` dentro do quadrado) ou com o sol do sprite. Os
   dois precisam funcionar aqui, porque cidade sem logo é o padrão. */
.auth__marca {
    display: grid;
    place-items: center;
    width: 4.5rem;
    height: 4.5rem;
    margin-bottom: var(--space-4);
    background: var(--brand-2);
    color: var(--text-on-brand);
}
.auth__marca .icon { width: 2.2rem; height: 2.2rem; }
/* Segue a proporção da arte, como o selo do cabeçalho: forçar o quadrado
   deixava faixas de campo vazio em cima e embaixo de uma marca larga.
   A altura é COMPRIMENTO e não `100%` — a porcentagem entra em ciclo com
   a largura automática do selo e o navegador cai no tamanho do arquivo. */
/* `fit-content`, e não `auto`: em contêiner de bloco — a coluna do login —
   `auto` vira a largura inteira disponível, e o selo esticava por 570px
   com a marca perdida no meio. `fit-content` encolhe até a arte nos dois
   casos, seja o pai flex ou bloco. */
.auth__marca--logo { background: var(--campo-marca); padding: 4px; width: fit-content; }
.auth__marca--logo img { height: calc(4.5rem - 8px); width: auto; object-fit: contain; display: block; }

.auth__pitch h1 { margin-bottom: var(--space-3); }
.auth__pitch .auth__lead {
    color: var(--text-2);
    font-size: var(--step-0);
    max-width: 46ch;
    margin-bottom: var(--space-5);
}

.auth__ganhos { list-style: none; display: flex; flex-direction: column; gap: var(--space-4); }
.auth__ganhos li { display: flex; align-items: flex-start; gap: var(--space-3); }
.auth__ganhos .icon {
    flex: none;
    width: 1.15rem; height: 1.15rem;
    margin-top: .12em;
    color: var(--brand-2);
}
.auth__ganhos strong { display: block; font-size: var(--step--1); font-weight: 650; }
.auth__ganhos small { display: block; color: var(--text-3); font-size: var(--step--2); margin-top: .15rem; }

/* ----------------------------------------------------------------- ação */

.auth__painel {
    padding: var(--space-6);
    background: var(--surface-1);
    border: 1px solid var(--border);
}

.auth__painel-titulo {
    font-family: var(--font-display);
    font-size: var(--step-1);
    font-weight: 700;
    margin-bottom: var(--space-2);
}
.auth__painel-lead { color: var(--text-3); font-size: var(--step--1); margin-bottom: var(--space-5); }

.auth__nota {
    font-size: var(--step--2);
    color: var(--text-3);
    margin-top: var(--space-4);
}

.auth__garantias {
    list-style: none;
    border-top: 1px solid var(--border);
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    display: flex; flex-direction: column; gap: var(--space-3);
}
.auth__garantias li {
    display: flex; align-items: flex-start; gap: var(--space-3);
    font-size: var(--step--2); color: var(--text-3);
}
.auth__garantias .icon { flex: none; width: 1em; height: 1em; margin-top: .2em; color: var(--text-3); }

.auth__erro {
    display: flex; align-items: flex-start; gap: var(--space-2);
    padding: var(--space-3);
    margin-bottom: var(--space-4);
    font-size: var(--step--1);
    color: var(--text);
    background: var(--surface-2);
    border-left: 3px solid var(--brand-2);
}
.auth__erro .icon { flex: none; margin-top: .15em; }

.auth__voltar {
    display: inline-flex; align-items: center; gap: var(--space-2);
    margin-top: var(--space-5);
    font-size: var(--step--2);
    color: var(--text-3);
}
.auth__voltar:hover { color: var(--brand-2); }
.auth__voltar .icon { width: 1em; height: 1em; }

/* ------------------------------------------------------- botão do Google

   Segue as diretrizes de marca do Google para "Sign in with Google": fundo
   e borda das cores prescritas, o G de quatro cores sem alteração nenhuma, e
   um dos textos aprovados.

   A fonte prescrita é Roboto, que não hospedamos — usar a do projeto é a
   adaptação usual, e a diretriz que importa é não descaracterizar a marca
   nem sugerir que o botão é do Google além do que ele é.

   Duas versões porque o guia tem dois temas: a escura é a do tema padrão. */

.btn-google {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    width: 100%;
    min-height: 44px;
    padding: 10px 16px;
    border-radius: 4px;             /* o botão é do Google; o canto vivo do guia não se aplica */
    font-family: var(--font-ui);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: .01em;
    cursor: pointer;
    transition: box-shadow .18s var(--ease), background .18s var(--ease);

    background: #131314;
    border: 1px solid #8E918F;
    color: #E3E3E3;
}
.btn-google:hover { background: #1B1B1C; box-shadow: 0 1px 3px rgba(0, 0, 0, .4); }
.btn-google:focus-visible { outline: 2px solid var(--brand-2); outline-offset: 2px; }

/* O G nunca muda de cor, de proporção nem de fundo — nem no tema claro. */
.btn-google__g { flex: none; width: 20px; height: 20px; display: block; }

@media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) .btn-google {
        background: #FFFFFF;
        border-color: #747775;
        color: #1F1F1F;
    }
    :root:not([data-theme="dark"]) .btn-google:hover { background: #F7F8F8; }
}
:root[data-theme="light"] .btn-google {
    background: #FFFFFF;
    border-color: #747775;
    color: #1F1F1F;
}
:root[data-theme="light"] .btn-google:hover { background: #F7F8F8; }

/* ---------------------------------------------------------- empilhado */

@media (max-width: 62rem) {
    .auth { min-height: 0; padding: var(--space-5) 0 var(--space-6); }
    .auth__grid { grid-template-columns: 1fr; gap: var(--space-5); align-items: start; }
    .auth__marca { width: 3.25rem; height: 3.25rem; }
    .auth__pitch .auth__lead { max-width: none; margin-bottom: var(--space-4); }

    /* No celular a lista de ganhos vira o rodapé do argumento, depois do
       botão: quem chegou aqui por um "Entre para salvar" já sabe o motivo, e
       fazer rolar até a ação seria cobrar duas vezes pela mesma decisão. */
    .auth__ganhos { display: none; }
}

@media (max-width: 40rem) {
    .auth__painel { padding: var(--space-4); }
}

/* ==================================================================
   PERFIL PÚBLICO

   O painel é visualmente distinto do resto da página da conta porque a
   regra dele é distinta: aqui nada vale na hora. A borda no laranja da
   marca é o sinal de que aquele bloco tem uma fila atrás.
   ================================================================== */

.avatar {
    width: 2.5rem; height: 2.5rem;
    border-radius: var(--radius-circle);
    object-fit: cover;
    display: block;
    flex: none;
    background: var(--surface-2);
}
.avatar--grande { width: 6rem; height: 6rem; }
.avatar--vazio {
    display: grid; place-items: center;
    color: var(--text-3);
    border: 1px dashed var(--border-strong);
}
.avatar--vazio .icon { width: 45%; height: 45%; }

.perfil-publico { border-left: 3px solid var(--brand-2); }

.perfil-publico__estado {
    display: flex; align-items: flex-start; gap: var(--space-3);
    padding: var(--space-3);
    margin-bottom: var(--space-4);
    font-size: var(--step--1);
    background: var(--surface-2);
}
.perfil-publico__estado .icon { flex: none; width: 1.1em; height: 1.1em; margin-top: .15em; }
.perfil-publico__estado--analise .icon { color: var(--brand-2); }
.perfil-publico__estado--recusado { border-left: 3px solid #E5484D; }
.perfil-publico__estado--recusado .icon { color: #E5484D; }

.perfil-publico__grade {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--space-5);
    align-items: start;
    padding-bottom: var(--space-5);
    margin-bottom: var(--space-5);
    border-bottom: 1px solid var(--border);
}

.perfil-foto { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); }
.perfil-foto__origem { font-size: var(--step--2); color: var(--text-3); text-align: center; max-width: 11rem; }

/* A foto na fila aparece ao lado da que está no ar, menor: quem enviou
   precisa ver que as duas existem e qual delas o guia está mostrando. */
.perfil-foto__pendente { display: flex; align-items: center; gap: var(--space-2); }
.perfil-foto__pendente figcaption { font-size: var(--step--2); color: var(--brand-2); font-weight: 600; }

.perfil-publico__acoes { display: flex; flex-direction: column; gap: var(--space-4); }
.perfil-publico__acoes .btn { align-self: flex-start; }
.perfil-publico__acoes .campo { margin-bottom: var(--space-2); }
.perfil-publico__acoes .campo__nota { margin-bottom: var(--space-3); }

.perfil-foto__envio input[type="file"] {
    width: 100%;
    padding: var(--space-3);
    font-family: var(--font-ui);
    font-size: var(--step--1);
    color: var(--text-2);
    background: var(--surface-2);
    border: 1px dashed var(--border-strong);
}
.perfil-foto__envio input[type="file"]::file-selector-button {
    margin-right: var(--space-3);
    padding: var(--space-2) var(--space-3);
    font-family: var(--font-ui);
    font-size: var(--step--2);
    font-weight: 600;
    color: var(--text-on-brand);
    background: var(--brand-2);
    border: 0;
    cursor: pointer;
}

.perfil-publico__nome .campo { max-width: 26rem; }

@media (max-width: 48rem) {
    .perfil-publico__grade { grid-template-columns: 1fr; justify-items: start; }
    .perfil-foto { flex-direction: row; align-items: center; }
    .perfil-foto__origem { text-align: left; max-width: none; }
}

/* Avatar pequeno, ao lado de uma avaliação. */
.avatar--peq { width: 2.25rem; height: 2.25rem; }
.avatar--inicial {
    display: grid; place-items: center;
    font-family: var(--font-ui);
    font-size: var(--step--1);
    font-weight: 700;
    color: var(--text-on-brand);
    background: var(--brand-2);
}

/* ------------------------------------------------------------------
   Minhas viagens.

   Roteiro do guia é sugestão nossa e tem visual editorial; viagem é
   plano da pessoa e tem visual de agenda: linha do tempo, horário à
   esquerda, densidade maior.
   ------------------------------------------------------------------ */

.grid-viagens {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
    gap: var(--space-4);
    margin-bottom: var(--space-5);
}

.campo-par { display: grid; grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); gap: var(--space-3); }

.card--viagem .card__body { padding-top: var(--space-4); }
.card--viagem .card__desc { display: flex; align-items: center; gap: var(--space-2); color: var(--text-3); }
.card--viagem .card__desc .icon { width: 1em; height: 1em; }

.viagem { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: var(--space-5); align-items: start; }
.viagem__lado { position: sticky; top: calc(var(--header-h) + var(--space-4)); }

/* ---------------------------------------------------------- dia e linha */

.dia-viagem { margin-bottom: var(--space-5); }
.dia-viagem__titulo {
    font-family: var(--font-display);
    font-size: var(--step-1);
    padding-bottom: var(--space-2);
    margin-bottom: var(--space-3);
    border-bottom: 1px solid var(--border);
}

.linha-viagem { list-style: none; }

.parada-viagem {
    display: grid;
    grid-template-columns: 4rem 1fr;
    gap: var(--space-3);
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--border);
}
.parada-viagem:last-child { border-bottom: 0; }

/* O horário à esquerda, alinhado, é o que faz a lista virar agenda: bate o
   olho na coluna e se lê o dia inteiro. */
.parada-viagem__hora {
    font-family: var(--font-ui);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--brand-2);
    padding-top: 2px;
}

.parada-viagem__corpo h3 { font-size: var(--step-0); margin-bottom: 2px; }
.parada-viagem__corpo h3 a { color: var(--text); }
.parada-viagem__corpo h3 a:hover { color: var(--brand); }

.parada-viagem__meta {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--step--2);
    color: var(--text-3);
}
.parada-viagem__meta .icon { width: 1em; height: 1em; }
.parada-viagem__meta--fora { color: var(--brand-2); }

.parada-viagem__nota { margin-top: var(--space-2); font-size: var(--step--1); color: var(--text-2); }

.parada-viagem__editar { margin-top: var(--space-3); }
.parada-viagem__editar summary {
    font-size: var(--step--2);
    color: var(--text-3);
    cursor: pointer;
    display: inline-block;
    padding: 2px 0;
}
.parada-viagem__editar summary:hover { color: var(--brand); }
.parada-viagem__editar[open] summary { margin-bottom: var(--space-3); }
.parada-viagem__editar .campo { margin-bottom: var(--space-3); }

.parada-viagem__acoes { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }

.campo-link {
    width: 100%;
    padding: var(--space-3);
    font: inherit;
    font-size: var(--step--2);
    color: var(--text-2);
    background: var(--surface-2);
    border: 1px solid var(--border-strong);
    border-radius: 0;
}

@media (max-width: 64rem) {
    .viagem { grid-template-columns: 1fr; }
    .viagem__lado { position: static; }
}

@media (max-width: 40rem) {
    .parada-viagem { grid-template-columns: 3.2rem 1fr; gap: var(--space-2); }
}

/* --------------------------------------------------- oferecer o serviço

   Bloco à parte, com a borda no laranja da marca, porque marcar aqui muda a
   natureza do que está sendo publicado: de "estou me organizando" para
   "eu levo pessoas nesse percurso". Isso passa por revisão e expõe um
   contato — merece parecer diferente do resto do formulário. */

.painel--servico { border-left: 3px solid var(--brand-2); }
.painel--servico .campo-check { margin-bottom: var(--space-4); }

/* Como o serviço aparece para quem lê a viagem pública. */
.servico-oferta {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-4);
    margin-bottom: var(--space-5);
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-left: 3px solid var(--brand-2);
}
.servico-oferta__quem { font-weight: 650; }
.servico-oferta__valor { font-family: var(--font-ui); font-size: var(--step-0); color: var(--brand-2); font-weight: 700; }
.servico-oferta__aviso { font-size: var(--step--2); color: var(--text-3); }

/* ------------------------------------------------- viagens de quem foi

   Card sem foto: uma viagem não tem imagem própria, e usar a foto de uma
   parada sugeriria que o guia escolheu aquele lugar como capa. O que
   identifica é quem montou — por isso o autor vem antes do título. */

.viagem-publica { padding: 0; }
.viagem-publica .card__body { padding: var(--space-4); gap: var(--space-2); }

.viagem-publica__autor {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--step--2);
    color: var(--text-3);
    margin-bottom: var(--space-2);
}

/* `.card__meta` tem `margin-top: auto` em components.css, para virar rodapé
   do card de local. Aqui a meta é legenda do título — quem vai para o rodapé
   é a linha de serviço, quando existe. Sem isto, um card com serviço e outro
   sem ficam com a meta em alturas diferentes lado a lado. */
.viagem-publica .card__meta { margin-top: 0; padding-top: 0; }

.viagem-publica__servico {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-top: auto;
    padding-top: var(--space-3);
    border-top: 1px solid var(--border);
    font-size: var(--step--2);
    color: var(--text-2);
}
.viagem-publica__servico .icon { flex: none; width: 1em; height: 1em; margin-top: .15em; color: var(--brand-2); }
.viagem-publica__servico strong { color: var(--brand-2); }

/* O painel de visibilidade tem fila atrás, como o do perfil público. */
.painel--visibilidade { border-left: 3px solid var(--brand-2); }
.painel--visibilidade .opcao:last-of-type { margin-bottom: var(--space-4); }

/* ------------------------------------------------------- mapa da viagem

   Duas colunas no desktop: o mapa ocupa o que sobra e a lista fica ao lado,
   como legenda navegável. No telefone o mapa vem primeiro e a lista embaixo —
   é a ordem de quem está na rua, olhando para onde ir antes de conferir o que
   vem depois. */

.viagem-mapa { display: grid; gap: var(--space-5); }
.viagem-mapa__tela { min-height: 60vh; }

@media (min-width: 900px) {
    .viagem-mapa { grid-template-columns: 1fr 22rem; align-items: start; }
    .viagem-mapa__tela { min-height: 70vh; position: sticky; top: var(--space-5); }
}

.viagem-mapa__onde {
    padding: var(--space-4);
    background: var(--surface-1);
    border: 1px solid var(--border);
    margin-bottom: var(--space-5);
}
.viagem-mapa__onde .hint { margin-top: var(--space-3); }
.viagem-mapa__onde .hint.is-erro { color: var(--brand-2); }

.viagem-mapa__dias { display: grid; gap: var(--space-5); }
.viagem-mapa__dia h2 { display: flex; align-items: center; gap: var(--space-2); }

/* A bolinha da cor do dia é a legenda inteira: sem ela, marcador colorido no
   mapa é enfeite, não informação. */
.viagem-mapa__cor {
    width: .75rem; height: .75rem; border-radius: var(--radius-full);
    flex: none; background: var(--brand);
}

.viagem-mapa__paradas { list-style: none; padding: 0; margin: var(--space-3) 0 0; display: grid; gap: var(--space-2); }

.viagem-mapa__parada {
    display: grid; grid-template-columns: 1.6rem 1fr auto; gap: var(--space-3);
    width: 100%; align-items: center; text-align: left;
    padding: var(--space-2) var(--space-3);
    background: transparent; border: 1px solid transparent; cursor: pointer;
    color: var(--text-2); font-size: var(--step--1); font-family: inherit;
}
.viagem-mapa__parada:hover { border-color: var(--border-strong); color: var(--text); }

.viagem-mapa__numero {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.6rem; height: 1.6rem; border-radius: var(--radius-full);
    background: var(--surface-2); color: var(--text-2);
    font-size: var(--step--2); font-weight: 700; font-family: var(--font-ui);
}
.viagem-mapa__parada small { display: block; font-size: var(--step--2); }

/* Vazio até alguém pedir "onde estou": distância é a pergunta da rua, e sem
   posição ela não tem resposta. */
.viagem-mapa__distancia {
    font-size: var(--step--2); color: var(--brand-2);
    font-family: var(--font-ui); white-space: nowrap;
}

/* Marcador colorido por dia.
   A cor entra por variável para o módulo do mapa continuar sem saber o que é
   um "dia" — ele desenha marcadores, e quem sabe agrupá-los por data é esta
   tela.

   Pinta o `::before`, e não o botão: o pino é desenhado em pseudo-elementos
   (refinements.css), e o `background` do próprio botão é `none`. Pintá-lo
   deixava a legenda colorida ao lado de marcadores todos laranja. */
.map__marker--dia::before { background: var(--marcador, var(--brand-2)); }
.map__marker--dia.is-active::before {
    border-color: var(--marcador, var(--brand-2));
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--marcador, var(--brand-2)) 40%, transparent);
}

/* ------------------------------------------------------------------
   Avaliações de quem visitou.

   Visualmente separadas do conteúdo editorial de propósito: o guia diz
   o que verificou, a avaliação diz o que uma pessoa achou. Misturar os
   dois na mesma superfície é o começo de confundir opinião com fato.
   ------------------------------------------------------------------ */

.avaliacoes { padding-top: var(--space-5); border-top: 1px solid var(--border); margin-top: var(--space-5); }

.estrelas { display: inline-flex; gap: 1px; }
.estrela { color: var(--text-3); opacity: .4; }
.estrela .icon { width: 1em; height: 1em; }
.estrela.is-cheia { color: var(--brand-2); opacity: 1; }
/* NÃO adiantaria mirar o <path> interno daqui: o conteúdo referenciado por
   <use> vira shadow tree, e seletor de fora não alcança. Quem distingue
   cheio de vazio é a COR, que herda por currentColor. */

/* ------------------------------------------------------------ resumo */

.nota-resumo {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--space-5);
    align-items: center;
    padding: var(--space-4);
    margin-bottom: var(--space-5);
    background: var(--surface-1);
    border: 1px solid var(--border);
}

.nota-resumo__media { text-align: center; }
.nota-resumo__media strong {
    display: block;
    font-family: var(--font-display);
    font-size: var(--step-3);
    line-height: 1;
}

.nota-resumo__barras { list-style: none; display: flex; flex-direction: column; gap: 4px; }
.nota-resumo__barras li {
    display: grid;
    grid-template-columns: 1rem 1fr 2rem;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--step--2);
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
}
.nota-resumo__barras progress {
    appearance: none;
    -webkit-appearance: none;
    width: 100%;
    height: .4rem;
    border: 0;
    background: var(--surface-2);
}
.nota-resumo__barras progress::-webkit-progress-bar { background: var(--surface-2); }
.nota-resumo__barras progress::-webkit-progress-value { background: var(--brand-2); }
.nota-resumo__barras progress::-moz-progress-bar { background: var(--brand-2); }

/* ---------------------------------------------------------- avaliação */

.avaliacoes__lista { display: flex; flex-direction: column; }

.avaliacao { padding: var(--space-4) 0; border-bottom: 1px solid var(--border); }
.avaliacao:last-child { border-bottom: 0; }
/* Avatar e nome em cima, texto embaixo — a leitura é "quem disse" e
   depois "o que disse". A nota fica junto do nome porque as duas coisas
   formam o julgamento; a data recua para a direita, que é onde não
   atrapalha. */
.avaliacao header {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    column-gap: var(--space-3);
    row-gap: 2px;
    margin-bottom: var(--space-3);
}
.avaliacao header .avatar { grid-row: span 2; }
.avaliacao__autor { font-weight: 650; font-size: var(--step--1); align-self: end; }
.avaliacao header .estrelas { grid-column: 2; align-self: start; }
.avaliacao header time { grid-column: 3; grid-row: span 2; font-size: var(--step--2); color: var(--text-3); }
.avaliacao__visita { display: block; font-size: var(--step--2); color: var(--text-3); margin-bottom: var(--space-2); }
.avaliacao p { color: var(--text-2); white-space: pre-line; }

/* A própria avaliação é destacada: quem escreveu precisa reconhecê-la de
   relance, sobretudo quando ainda está em análise. */
.avaliacao--minha {
    padding: var(--space-4);
    margin-bottom: var(--space-4);
    background: var(--surface-1);
    border: 1px solid var(--border-strong);
    border-left: 3px solid var(--brand);
}
.avaliacao--em-analise { border-left-color: var(--brand-2); }
.avaliacao--recusada { border-left-color: #E5484D; }

.avaliacao__estado {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--step--2);
    color: var(--text-3);
    margin-bottom: var(--space-2);
}
.avaliacao__estado .icon { width: 1em; height: 1em; flex: none; }
.avaliacao__apagar { margin-top: var(--space-3); }

/* Mesma forma do card de avaliação, com a borda tracejada dizendo que
   é um lugar a preencher, não conteúdo publicado. */
.avaliacoes__convite {
    padding: var(--space-4);
    margin-bottom: var(--space-5);
    background: var(--surface-1);
    border: 1px dashed var(--border-strong);
    border-bottom: 1px dashed var(--border-strong);
    color: var(--text-2);
}
.avaliacoes__convite .estrelas { opacity: .45; }
.avaliacoes__convite .btn { margin-top: var(--space-3); }

/* `.avaliacao p` é `pre-line` para preservar as quebras que a pessoa
   escreveu. Este parágrafo é nosso e está indentado no template — sem
   desfazer a regra, cada quebra do código vira quebra na tela. */
.avaliacoes__convite p { white-space: normal; }

/* ------------------------------------------------------- formulário */

.avaliacao-form { margin-bottom: var(--space-5); }
.avaliacao-form > summary {
    font-family: var(--font-ui);
    font-weight: 600;
    cursor: pointer;
    padding: var(--space-2) 0;
}
.avaliacao-form[open] > summary { margin-bottom: var(--space-4); }

.nota-escolha { display: flex; flex-wrap: wrap; gap: var(--space-2); border: 0; }
.nota-escolha legend {
    font-size: var(--step--2);
    font-weight: 600;
    color: var(--text-2);
    margin-bottom: var(--space-2);
}
.nota-escolha label { display: inline-flex; }
.nota-escolha input { position: absolute; opacity: 0; width: 0; height: 0; }
.nota-escolha span {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: var(--space-2) var(--space-3);
    font-size: var(--step--1);
    background: var(--surface-2);
    border: 1px solid var(--border-strong);
    cursor: pointer;
}
.nota-escolha .icon { width: 1em; height: 1em; }
.nota-escolha input:checked + span { background: var(--gradient); border-color: transparent; color: #14100A; }
.nota-escolha input:focus-visible + span { outline: 2px solid var(--brand); outline-offset: 2px; }

.avaliacao-form__regras {
    font-size: var(--step--2);
    color: var(--text-3);
    margin-bottom: var(--space-4);
}

/* ---------------------------------------------------------- foto */

.foto-envio { border: 0; padding: 0; margin-bottom: var(--space-4); }
.foto-envio legend {
    font-size: var(--step--2);
    font-weight: 600;
    color: var(--text-2);
    margin-bottom: var(--space-2);
}
.foto-envio input[type="file"] {
    width: 100%;
    padding: var(--space-3);
    font-family: var(--font-ui);
    font-size: var(--step--1);
    color: var(--text-2);
    background: var(--surface-2);
    border: 1px dashed var(--border-strong);
}
.foto-envio input[type="file"]::file-selector-button {
    margin-right: var(--space-3);
    padding: var(--space-2) var(--space-3);
    font-family: var(--font-ui);
    font-size: var(--step--2);
    font-weight: 600;
    color: var(--text-on-brand);
    background: var(--brand-2);
    border: 0;
    cursor: pointer;
}

.foto-envio__nota {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-top: var(--space-2);
    font-size: var(--step--2);
    color: var(--text-3);
}
.foto-envio__nota .icon { flex: none; margin-top: .15em; }

.campo-check {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    margin-top: var(--space-3);
    font-size: var(--step--2);
    color: var(--text-2);
    cursor: pointer;
}
.campo-check input { margin-top: .2em; width: 1.05rem; height: 1.05rem; accent-color: var(--brand-2); flex: none; }

/* A foto vem depois do texto e nunca antes: a avaliação é o que a pessoa
   disse; a imagem ilustra. Invertido, a lista vira galeria. */
.avaliacao__foto { margin-top: var(--space-3); }
.avaliacao__foto img {
    display: block;
    width: 100%;
    max-width: 34rem;
    height: auto;
    border: 1px solid var(--border);
}
.avaliacao__foto figcaption {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-top: var(--space-2);
    font-size: var(--step--2);
    color: var(--text-3);
}
.avaliacao__foto figcaption .icon { width: 1em; height: 1em; flex: none; }
.avaliacao__foto--minha img { max-width: 22rem; }

/* Denunciar fica discreto: existe para quem precisa, não para convidar. */
.avaliacao__denuncia { margin-top: var(--space-3); }
.avaliacao__denuncia summary { font-size: var(--step--2); color: var(--text-3); cursor: pointer; }
.avaliacao__denuncia summary:hover { color: var(--brand-2); }
.avaliacao__denuncia[open] summary { margin-bottom: var(--space-3); }
.avaliacao__denuncia .campo { margin-bottom: var(--space-3); }

@media (max-width: 40rem) {
    .nota-resumo { grid-template-columns: 1fr; gap: var(--space-4); }
}

/* ------------------------------------------------------- sugerir um lugar */

.grid-sugestao { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: var(--space-4); align-items: start; }

.sugestao__aviso {
    display: flex; align-items: flex-start; gap: var(--space-2);
    padding: var(--space-3);
    margin-bottom: var(--space-4);
    font-size: var(--step--2);
    color: var(--text-3);
    background: var(--surface-2);
    border-left: 3px solid var(--border-strong);
}
.sugestao__aviso .icon { flex: none; margin-top: .15em; }

.empty__acoes { display: flex; flex-wrap: wrap; gap: var(--space-3); justify-content: center; margin-top: var(--space-4); }
.empty__acoes .btn { margin-top: 0; }

@media (max-width: 64rem) {
    .grid-sugestao { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------- denunciar

   Discreto de propósito: existe para quem precisa, não para convidar. Um
   botão vermelho ao lado de cada avaliação transformaria a página numa
   disputa. Substitui `.avaliacao__denuncia`, que só servia à avaliação —
   agora o mesmo formulário atende viagem pública e foto. */

.denuncia { margin-top: var(--space-3); }
.denuncia summary { font-size: var(--step--2); color: var(--text-3); cursor: pointer; }
.denuncia summary:hover { color: var(--brand-2); }
.denuncia[open] summary { margin-bottom: var(--space-3); }
.denuncia .campo { margin-bottom: var(--space-3); }
.denuncia__nota { font-size: var(--step--2); color: var(--text-3); margin-bottom: var(--space-3); }

/* Galeria: crédito e denúncia embaixo da foto. */
.gallery__item { display: flex; flex-direction: column; gap: var(--space-2); }
.gallery__item .credit { margin: 0; }

/* ==================================================================
   POSTAGEM

   O formato de tudo que sai do guia por um link: coluna vertical, tela
   cheia, timbrada. Uma viagem compartilhada chega quase sempre colada
   num aplicativo de mensagem e é aberta num celular — e muitas vezes
   vira captura de tela antes de virar clique.

   Daí as três regras desta folha:

     1. **Coluna estreita e fixa** (26rem), centrada. No desktop ela não
        se espalha: a peça tem a mesma forma em qualquer tela, que é o
        que permite fotografá-la sem recorte.
     2. **Timbre em cima e embaixo.** Numa captura de tela não existe
        barra de endereço — se a marca não estiver na imagem, ninguém
        sabe de onde aquilo veio.
     3. **Nada clicável essencial.** Tudo que importa é legível parado.
   ================================================================== */

.post-body { background: var(--bg); }

.post {
    min-height: 100vh;
    min-height: 100dvh;          /* no celular, desconta a barra do navegador */
    display: flex;
    justify-content: center;
    padding: clamp(0px, 3vw, var(--space-6)) var(--space-3);

    /* Arcos concêntricos, a mesma decoração do guia — é o que faz a peça
       parecer do Guia mesmo recortada fora do topo. */
    background:
        repeating-radial-gradient(circle at 82% -6%,
            transparent 0 3.4rem,
            color-mix(in srgb, var(--text) 5%, transparent) 3.4rem 3.5rem),
        var(--bg);
}

.post__folha {
    width: 100%;
    max-width: 26rem;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--border);
    box-shadow: var(--shadow);
}

/* ---------------------------------------------------------- timbre */

.post__timbre,
.post__rodape {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    background: var(--campo-marca);
}
.post__timbre { border-bottom: 2px solid var(--brand-2); }
.post__rodape { border-top: 2px solid var(--brand-2); margin-top: auto; }

.post__marca { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; flex: none; background: var(--brand-2); }
.post__marca .icon { width: 1.4rem; height: 1.4rem; color: var(--text-on-brand); }
/* O campo da marca, e não transparente.

   Transparente servia ao logo anterior, que era claro. O de Natal tem o
   "R" em azul-marinho, e sobre o fundo escuro da peça ele desaparecia —
   sobrava a letra ciano. O campo pertence à marca, não à peça. */
.post__marca--logo { background: var(--campo-marca); padding: 2px; }
.post__marca--logo img { width: 100%; height: 100%; object-fit: contain; display: block; }
.post__marca--peq { width: 1.9rem; height: 1.9rem; }

.post__timbre-texto strong,
.post__rodape strong {
    display: block;
    font-family: var(--font-display);
    font-size: var(--step-0);
    font-weight: 700;
    line-height: 1.15;
}
.post__timbre-texto small,
.post__rodape small { display: block; font-size: var(--step--2); color: var(--text-3); }

/* --------------------------------------------------------- conteúdo */

.post__conteudo { padding: var(--space-5); }

.post__olho {
    display: inline-flex; align-items: center; gap: .45em;
    font-family: var(--font-ui);
    font-size: .7rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
    color: var(--brand-2);
    margin-bottom: var(--space-2);
}
.post__olho .icon { width: 1em; height: 1em; }

.post__titulo {
    font-family: var(--font-display);
    font-size: var(--step-3);
    line-height: 1.08;
    letter-spacing: -.02em;
    margin-bottom: var(--space-4);
}

.post__numeros {
    list-style: none;
    display: flex;
    gap: var(--space-5);
    padding-bottom: var(--space-4);
    border-bottom: 1px solid var(--border);
}
.post__numeros strong {
    display: block;
    font-family: var(--font-display);
    font-size: var(--step-1);
    line-height: 1;
}
.post__numeros span { font-size: var(--step--2); color: var(--text-3); }

.post__autoria {
    display: flex; align-items: flex-start; gap: var(--space-2);
    margin-top: var(--space-3);
    font-size: var(--step--2);
    color: var(--text-3);
}
.post__autoria .icon { flex: none; width: 1em; height: 1em; margin-top: .2em; }
.post__autoria strong { color: var(--text-2); }

/* ---------------------------------------------------------- percurso */

.post__dia { margin-top: var(--space-5); }

.post__dia-titulo {
    display: flex; align-items: baseline; gap: .4em;
    font-family: var(--font-display);
    font-size: var(--step-1);
    margin-bottom: var(--space-3);
}
.post__dia-titulo span {
    font-family: var(--font-ui);
    font-size: .7rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
    color: var(--text-3);
}

.post__paradas { list-style: none; display: flex; flex-direction: column; }

/* A linha vertical liga as paradas: é o que faz um monte de itens parecer
   um percurso. Ela para na última — daí o `:last-child`. */
.post__parada {
    position: relative;
    display: grid;
    grid-template-columns: 3.2rem minmax(0, 1fr);
    gap: var(--space-3);
    padding-bottom: var(--space-4);
}
.post__parada::before {
    content: "";
    position: absolute;
    left: 3.1rem; top: .55rem; bottom: 0;
    width: 1px;
    background: var(--border-strong);
}
.post__parada:last-child { padding-bottom: 0; }
.post__parada:last-child::before { content: none; }

.post__hora {
    position: relative;
    font-family: var(--font-ui);
    font-size: var(--step--2);
    font-weight: 700;
    color: var(--brand-2);
    text-align: right;
    padding-top: .1rem;
    font-variant-numeric: tabular-nums;
}
.post__hora::after {
    content: "";
    position: absolute;
    right: -0.42rem; top: .45rem;
    width: 7px; height: 7px;
    background: var(--brand-2);
}

.post__parada h3 { font-size: var(--step-0); font-weight: 650; line-height: 1.25; }
.post__parada-meta { font-size: var(--step--2); color: var(--text-3); margin-top: .15rem; }
.post__nota {
    font-size: var(--step--2);
    color: var(--text-2);
    margin-top: var(--space-2);
    padding-left: var(--space-3);
    border-left: 2px solid var(--border-strong);
}

.post__anotacoes {
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px solid var(--border);
    font-size: var(--step--1);
    color: var(--text-2);
}

.post__vazio {
    display: flex; align-items: center; gap: var(--space-2);
    margin-top: var(--space-5);
    color: var(--text-3);
}

.post__cta { margin-top: var(--space-5); justify-content: center; }

.post .servico-oferta { margin: var(--space-5) 0 0; }

@media (max-width: 30rem) {
    .post { padding: 0; }
    .post__folha { max-width: none; border: 0; box-shadow: none; }
}

/* ==================================================================
   UTILITÁRIOS — o vocabulário fechado que os templates podem usar.

   Existe para acabar com o `style="..."` espalhado pelas páginas: cada
   template escrevia seu próprio tamanho de título e seu próprio espaçamento,
   e o resultado era a mesma coisa parecendo diferente em cada página.
   Se um valor não está aqui, ele não deve aparecer solto no HTML.
   ================================================================== */

/* ------------------------------------------------------------ títulos */

/* Título de bloco: serifa, cor cheia, sem efeito. O degradê em texto saiu
   na revisão editorial — a família e o peso já dão a hierarquia. */
.title-lg { font-size: var(--step-3); margin: 0 0 var(--space-2); }
.title-md { font-size: var(--step-2); margin: 0 0 var(--space-3); }
.title-sm { font-size: var(--step-1); margin: 0 0 var(--space-2); }

/* ---------------------------------------------------------- espaçamento */

.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: var(--space-6); }
.mb-5 { margin-bottom: var(--space-5); }

.pt-4 { padding-top: var(--space-4); }
.pt-5 { padding-top: var(--space-5); }
.pt-6 { padding-top: var(--space-6); }

/* Bloco de conteúdo dentro da coluna principal de uma página de detalhe:
   é este o ritmo entre "História", "Onde fica", "Aparece nestes roteiros". */
.block + .block { margin-top: var(--space-7); }

/* --------------------------------------------------------------- texto */

.muted { color: var(--text-2); }
.muted-2 { color: var(--text-3); }
.text-sm { font-size: var(--step--1); }
.lead { color: var(--text-2); font-size: var(--step--1); margin: 0; }

/* Aviso curto abaixo de um elemento (ex.: "localização aproximada"). */
.hint {
    font-size: var(--step--1);
    color: var(--text-3);
    margin: var(--space-2) 0 0;
}

/* Rótulo de agrupamento em coluna lateral (ex.: zona da cidade). */
.group-label {
    margin: var(--space-3) 0 var(--space-2);
    font-size: .74rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--text-3);
}

/* ------------------------------------------------------------- arranjo */

.row { display: flex; align-items: center; gap: var(--space-3); }
.row--tight { gap: var(--space-2); }
.row--wrap { flex-wrap: wrap; }
.row--center { justify-content: center; }
.stack-center { text-align: center; }

/* Link de lista com ícone à esquerda — padrão de "Por perto" e "Novidades". */
.link-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    color: inherit;
    text-decoration: none;
}
.link-row .icon { color: var(--text-3); flex: none; }
.link-row:hover { color: color-mix(in srgb, var(--brand-2) 75%, var(--text)); }
.link-row:hover .icon { color: color-mix(in srgb, var(--brand-2) 75%, var(--text)); }

/* --------------------------------------------------------------- peças */

.section--soft { background: var(--bg-soft); }

/* Mapa encaixado num painel: sem moldura dupla. */
.panel--flush { padding: 0; overflow: hidden; }
.panel--flush .map { border: 0; border-radius: 0; }

/* Segunda faixa de filtros — tags e bairros.

   **Não gruda no desktop.** Ali ela quebra em três linhas, e duas faixas
   grudadas comiam 25% da altura da janela enquanto a pessoa rolava a lista.
   A categoria é navegação e merece acompanhar; tag e bairro são refinamento,
   escolhidos uma vez.

   E no celular também não gruda, pelo mesmo motivo somado a outro: duas
   faixas fixas comem 115px de uma tela de 700px, e o deslocamento da segunda
   era um número mágico (`3.35rem`) que precisava adivinhar a altura da
   primeira — errava por 8px, e erraria mais a cada mudança de padding ou de
   fonte. Uma faixa fixa só, e nenhuma conta para manter. */
.filter-bar--second { position: static; border-top: 0; }

.search--page { max-width: 34rem; margin-top: var(--space-4); }

.error-code {
    font-size: var(--step-4);
    font-weight: 700;
    color: var(--brand-2);
    letter-spacing: -.03em;
    margin: 0;
    font-family: var(--font-display);
}

/* ----------------------------------------------------- links de apoio */

/* Rodapé e trilha de navegação não usam o estilo de link de texto corrido
   (sublinhado + cor de marca): ali o link é navegação, não destaque. */
.site-footer a,
.breadcrumbs a {
    color: var(--text-2);
    text-decoration: none;
}
.site-footer a:hover,
.breadcrumbs a:hover { color: color-mix(in srgb, var(--brand-2) 80%, var(--text)); }
.breadcrumbs a { color: var(--text-3); }

/* ------------------------------------------------------ créditos e licenças

   A tabela de fotos é longa por natureza e cresce com o acervo: quem chega
   aqui está procurando UMA linha, não lendo tudo. Daí o corpo em tamanho
   menor e a coluna de "onde aparece" em cor recuada — o crédito é o dado, o
   resto é localização. */

.creditos { font-size: var(--step--1); }
.creditos td { vertical-align: top; }
.creditos__onde { color: var(--text-3); }

.creditos-lista { display: flex; flex-direction: column; gap: var(--space-4); margin-bottom: var(--space-5); }
.creditos-lista li {
    display: grid;
    gap: 2px;
    padding-left: var(--space-4);
    border-left: 2px solid var(--border-strong);
}
.creditos-lista strong { font-size: var(--step-0); }
.creditos-lista__autor { color: var(--text-2); font-size: var(--step--1); }
.creditos-lista__licenca { font-size: var(--step--2); }
.creditos-lista__uso { color: var(--text-3); font-size: var(--step--2); }

/* ------------------------------------------------- fichas de direito de imagem

   Uma ficha por imagem, com autor, fonte, licença, obra original e alteração.
   Lista, e não tabela: são sete campos por item e alguns são links longos —
   numa tabela de sete colunas o telefone não mostraria nenhum deles inteiro.

   Esta página permite que o crédito junto da foto seja curto. NÃO o substitui:
   quando a licença exigir a informação junto da obra, a linha no canto da
   imagem continua sendo a que cumpre a exigência. */

.fichas-direitos { list-style: none; padding: 0; margin: var(--space-5) 0; display: grid; gap: var(--space-4); }

.ficha-direito {
    padding: var(--space-4);
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-left: 3px solid var(--brand-2);
}
.ficha-direito__titulo {
    margin: 0 0 var(--space-3);
    font-size: var(--step-0); font-family: var(--font-ui); font-weight: 700;
    color: var(--text);
}
.ficha-direito__dados { display: grid; gap: var(--space-2); margin: 0; font-size: var(--step--1); }
.ficha-direito__dados > div { display: grid; grid-template-columns: 8.5rem 1fr; gap: var(--space-3); }
.ficha-direito__dados dt { color: var(--text-3); font-family: var(--font-ui); }
.ficha-direito__dados dd { margin: 0; color: var(--text-2); overflow-wrap: anywhere; }

/* O prompt inteiro, e não resumido: é ele que demonstra que a imagem partiu
   de uma descrição do lugar, e não da fotografia de alguém. */
.ficha-direito__prompt {
    display: block; margin-top: var(--space-2);
    font-size: var(--step--2); color: var(--text-3); font-style: italic;
}

@media (max-width: 560px) {
    .ficha-direito__dados > div { grid-template-columns: 1fr; gap: 0; }
    .ficha-direito__dados dt { font-size: var(--step--2); }
}

