/*
 * PongSwap — folha de estilo da web publica (W1).
 *
 * Um ficheiro, servido tal e qual de `public/`. Sem Vite, sem npm, sem Tailwind
 * por CDN. A imagem de producao nao tem Node e nao vai passar a ter por causa de
 * uma folha de estilo: um passo de build que so serve para gerar CSS e uma
 * dependencia nova em todos os deploys e mais uma coisa que pode falhar as duas
 * da manha.
 *
 * A cache-busting e o `?v=` com o filemtime — ver App\Support\Web\Asset.
 *
 * DECISOES QUE VALEM POR SI
 *
 * 1. Modo escuro por `prefers-color-scheme`, sem interruptor. Metade destas
 *    visitas vem de um telemovel a partir de uma ligacao colada num grupo, muitas
 *    a noite, e um site que rebenta com luz branca a essa hora fecha-se logo. Um
 *    interruptor exigia JavaScript, um cookie e uma decisao a mais para quem
 *    chega — o sistema operativo ja tem a resposta.
 *
 * 2. Tipografia do sistema. Uma fonte de fora sao 40-80 kB antes de qualquer
 *    texto aparecer, em rede movel, na primeira visita de alguem que ainda nao
 *    decidiu se fica. A fonte do sistema aparece instantaneamente e e a que a
 *    pessoa ja esta habituada a ler. O wordmark e a excepcao — e desenhado em
 *    SVG (`web.partials.wordmark`) e nao depende de fonte nenhuma.
 *
 * 3. Grelha por `auto-fill` e nao por breakpoints. Nao ha aqui "versao movel" e
 *    "versao desktop" — ha uma grelha que poe tantos cartoes quantos couberem. A
 *    medida minima da coluna e 9.5rem para dar DUAS colunas a 375 px: com uma
 *    so, vinte anuncios eram nove mil pixeis de rolagem e ninguem chegava ao fim.
 *
 * 4. A cor da marca manda, mas o contraste manda mais. `--brand-orange`
 *    (#EB5B2A, medido no logotipo) com texto branco da 3,46:1 e falha o minimo
 *    de 4,5:1 para texto normal. Por isso ha DOIS laranjas: o da marca, para
 *    superficies sem texto pequeno por cima (wordmark, foco, barras, acentos), e
 *    `--accent` (#C74716) — o mais claro que passa com folga, 4,84:1 com branco —
 *    para tudo o que leva rotulo: botoes, pastilha activa, accoes.
 */

/* ---------------------------------------------------------------- variaveis */

:root {
    color-scheme: light dark;

    /*
     * A marca, medida no ficheiro do logotipo (ver docs/ui/marca.md). Estes dois
     * valores NAO mudam com o modo claro/escuro: sao a marca, nao sao tema.
     */
    --brand-navy: #0b1e3f;
    --brand-orange: #eb5b2a;

    /* Superficies: cinzento muito claro por baixo, cartoes brancos por cima. */
    --bg: #f4f6f8;
    --surface: #ffffff;
    --surface-2: #edf1f6;
    --border: #dce3eb;
    --border-strong: #c3cedb;

    --text: #0b1e3f;          /* 15,24:1 sobre --bg */
    --muted: #55677e;         /* 5,34:1 sobre --bg, 5,79:1 sobre --surface */

    --accent: #c74716;        /* branco por cima: 4,84:1 */
    --accent-hover: #b03f13;
    --accent-text: #ffffff;

    --link: #0b1e3f;
    --link-hover: #c74716;

    --sold: #8a2b1b;
    --sold-bg: #fbe7e2;
    --reserved: #7a4a06;
    --reserved-bg: #fbf0dc;
    --ok: #10554a;
    --ok-bg: #dff1ec;
    --danger: #8a2b1b;
    --danger-bg: #fbe7e2;

    /* Estado de conservacao — a leitura rapida de uma grelha faz-se por aqui. */
    --cond-new: #1b5e32;
    --cond-new-bg: #e3f3e8;
    --cond-like-new: #14477e;
    --cond-like-new-bg: #e4eefa;
    --cond-good: #10554a;
    --cond-good-bg: #dff1ec;
    --cond-used: #7a4a06;
    --cond-used-bg: #fbf0dc;
    --cond-parts: #8a2b1b;
    --cond-parts-bg: #fbe7e2;

    --radius: 0.875rem;
    --radius-sm: 0.625rem;
    --radius-pill: 999px;
    --shadow: 0 1px 2px rgb(11 30 63 / 6%), 0 1px 3px rgb(11 30 63 / 4%);
    --shadow-lift: 0 2px 6px rgb(11 30 63 / 8%), 0 8px 20px rgb(11 30 63 / 6%);
    --wrap: 72rem;

    /* Alvo de toque minimo. Um dedo tem 9 mm; 44 px e o minimo defensavel. */
    --tap: 2.75rem;
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #0a1424;
        --surface: #111e33;
        --surface-2: #17263e;
        --border: #26385a;
        --border-strong: #35486d;

        --text: #e9eff7;      /* 15,95:1 sobre --bg */
        --muted: #9fb2ca;     /* 8,52:1 sobre --bg, 7,71:1 sobre --surface */

        --accent: #c74716;    /* branco por cima continua a dar 4,84:1 */
        --accent-hover: #d95322;
        --accent-text: #ffffff;

        --link: #e9eff7;
        --link-hover: #ff8a5c;

        --sold: #f0a08f;
        --sold-bg: #33170f;
        --reserved: #e7c377;
        --reserved-bg: #2e2410;
        --ok: #79d3c0;
        --ok-bg: #0e2b27;
        --danger: #f0a08f;
        --danger-bg: #33170f;

        --cond-new: #7fd8a0;
        --cond-new-bg: #12301e;
        --cond-like-new: #8fbef5;
        --cond-like-new-bg: #10233f;
        --cond-good: #79d3c0;
        --cond-good-bg: #0e2b27;
        --cond-used: #e7c377;
        --cond-used-bg: #2e2410;
        --cond-parts: #f0a08f;
        --cond-parts-bg: #33170f;

        --shadow: none;
        --shadow-lift: none;
    }
}

/* -------------------------------------------------------------------- base */

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

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 1rem/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    /* Evita que a barra do browser tape o rodape em iOS. */
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
}

h1, h2, h3 { line-height: 1.2; margin: 0 0 0.75rem; font-weight: 700; color: var(--text); }
h1 { font-size: clamp(1.55rem, 1.15rem + 1.7vw, 2.25rem); letter-spacing: -0.02em; }
h2 { font-size: clamp(1.2rem, 1.05rem + 0.7vw, 1.5rem); letter-spacing: -0.01em; }
h3 { font-size: 1.0625rem; }

p { margin: 0 0 1rem; }
p:last-child { margin-bottom: 0; }

a { color: var(--link); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { color: var(--link-hover); text-decoration-thickness: 2px; }

img { max-width: 100%; height: auto; display: block; }

hr { border: 0; border-top: 1px solid var(--border); margin: 2.5rem 0; }

/*
 * Foco visivel em tudo, e na cor da marca. Quem navega por teclado tem de saber
 * onde esta — e o laranja destaca-se tanto do fundo claro como do escuro, o que
 * o azul da ligacao nao fazia sobre um painel escuro.
 */
:focus-visible {
    outline: 3px solid var(--brand-orange);
    outline-offset: 2px;
    border-radius: 4px;
}

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    padding: 0.75rem 1rem;
    background: var(--surface);
    z-index: 10;
}
.skip-link:focus { left: 0; }

/* Escondido dos olhos, presente para quem le com leitor de ecra. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.wrap {
    width: 100%;
    max-width: var(--wrap);
    margin: 0 auto;
    padding: 0 1rem;
}

.muted { color: var(--muted); }
.small { font-size: 0.875rem; }
.stack > * + * { margin-top: 1rem; }
.center { text-align: center; }

/* ------------------------------------------------------------------ header */

.site-header {
    border-bottom: 1px solid var(--border);
    background: var(--surface);
    position: relative;
}

/*
 * A linha laranja por baixo do cabecalho e o unico sitio onde a cor da marca
 * aparece em TODAS as paginas. Custa 3 px e faz o site parecer o site.
 */
.site-header::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 3px;
    background: var(--brand-orange);
}

/*
 * `flex-wrap` e a valvula de seguranca, nao o plano: com a sessao iniciada o
 * cabecalho leva "a minha conta" e "sair" e pode nao caber em 343 px uteis.
 * Melhor quebrar para uma segunda linha do que empurrar a pagina toda para o
 * lado — uma barra horizontal num telemovel e um defeito que se ve em todas as
 * paginas ao mesmo tempo.
 */
.site-header__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.75rem;
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
    min-height: 3.5rem;
}
@media (min-width: 40rem) {
    .site-header__inner { gap: 0.25rem 1rem; }
}

/*
 * O wordmark e SVG e nao texto: a tipografia do logotipo e geometrica, de traco
 * grosso e muito espacada, e nao existe no sistema de ninguem. O marinho vem de
 * `currentColor` para o wordmark servir tal e qual nos dois modos.
 */
.brand {
    display: inline-flex;
    align-items: center;
    margin-right: auto;
    min-width: 0;
    color: var(--text);
    text-decoration: none;
    padding: 0.25rem 0;
}
/*
 * 1rem a 375 px nao e um valor bonito, e um valor medido: o wordmark tem
 * proporcao 8:1, a esta altura ocupa 127 px e sobram os 204 que a navegacao
 * precisa para caber na mesma linha em ingles. Um passo acima e o cabecalho
 * parte-se em duas linhas em todas as paginas do site.
 */
.brand svg { display: block; height: 1rem; width: auto; max-width: 100%; }
@media (min-width: 30rem) {
    .brand svg { height: 1.375rem; }
}
@media (min-width: 48rem) {
    .brand svg { height: 1.625rem; }
}
.brand:hover { text-decoration: none; color: var(--text); }

.site-nav {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.875rem;
}
@media (min-width: 30rem) {
    .site-nav { font-size: 0.9375rem; }
}
.site-nav form { margin: 0; }

/*
 * `:where()` nao conta para a especificidade. Sem ele, `.site-nav a` (0,1,1)
 * ganhava a `.button` (0,1,0) e o botao "criar conta" dentro do cabecalho saia
 * com texto escuro sobre fundo escuro — invisivel, e sem nada de estranho no
 * codigo que o denunciasse.
 */
.site-nav :where(a) {
    color: var(--text);
    text-decoration: none;
    /* Alvo de toque: o texto tem 22 px de altura, a area tem de ter 44. */
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
    padding: 0 0.5rem;
    border-radius: var(--radius-sm);
    font-weight: 600;
}
.site-nav :where(a):hover { color: var(--link-hover); text-decoration: none; background: var(--surface-2); }
/*
 * Folga lateral apertada em ecra estreito, e a normal a partir de 30rem. E o
 * ultimo ajuste que faz "PongSwap · Entrar · Criar conta" caber numa linha a
 * 375 px em ingles, que e a lingua com as palavras mais longas das duas.
 */
.site-nav :where(a) { padding: 0 0.375rem; }
.site-nav .button { padding-left: 0.7rem; padding-right: 0.7rem; }
@media (min-width: 30rem) {
    .site-nav :where(a) { padding: 0 0.5rem; }
    .site-nav .button { padding-left: 1.25rem; padding-right: 1.25rem; }
}

/*
 * Num telemovel o cabecalho tem de caber numa linha. "Ver material" ja esta na
 * pagina e na barra de procura; repeti-lo la em cima custava uma segunda linha
 * de cabecalho — 60 px roubados a primeira foto em todas as paginas.
 */
.site-nav .nav-secondary { display: none; }
@media (min-width: 48rem) {
    .site-nav .nav-secondary { display: inline-flex; }
}

/*
 * O selector de idioma. Ver `web.partials.lang-switch` para o porque da forma.
 *
 * O que interessa aqui e a LARGURA: o botao mede 3,25rem esteja o site em duas
 * linguas ou em cinco, porque o que cresce e a lista que se abre por cima da
 * pagina e nao a barra. As tres ligacoes lado a lado gastavam 7rem de cabecalho
 * a 375 px e por isso tinham de fugir para o rodape; isto cabe, e o selector
 * volta a estar onde a maioria o procura.
 */
.lang-menu {
    position: relative;
    margin-left: 0.125rem;
}

.lang-menu__button {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    min-height: var(--tap);
    padding: 0 0.4rem;
    border-radius: var(--radius-sm);
    cursor: pointer;
    /* O triangulo do `<details>` sai; o galo do menu e o nosso `__chevron`. */
    list-style: none;
}
.lang-menu__button::-webkit-details-marker { display: none; }
.lang-menu__button:hover { background: var(--surface-2); }
.lang-menu__chevron {
    width: 0.75rem;
    height: 0.75rem;
    color: var(--muted);
    transition: transform 120ms ease;
}
.lang-menu[open] .lang-menu__chevron { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
    .lang-menu__chevron { transition: none; }
}

/*
 * A bandeira e um rectangulo 3:2 com canto arredondado e um contorno tenue: sem
 * ele, a faixa branca da bandeira portuguesa nem sequer se ve contra o fundo
 * claro do cabecalho.
 */
.flag {
    width: 1.375rem;
    height: 0.9167rem;
    flex: none;
    border-radius: 2px;
    /* Cinzento neutro e nao o marinho da marca: o mesmo contorno tem de separar
       a faixa branca da bandeira portuguesa do fundo claro E do fundo escuro. */
    box-shadow: 0 0 0 1px rgb(128 138 155 / 45%);
}

.lang-menu__list {
    position: absolute;
    top: calc(100% + 0.375rem);
    right: 0;
    z-index: 30;
    min-width: 11rem;
    margin: 0;
    padding: 0.25rem;
    list-style: none;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lift);
}
.lang-menu__list li { margin: 0; }

/*
 * `.site-nav :where(a)` nao tem especificidade nenhuma do lado do `:where()`,
 * por isso empata com `.lang-menu__item` — e ganha quem vier depois no ficheiro.
 * Estas regras vem depois de proposito.
 */
.lang-menu__item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 2.5rem;
    padding: 0 0.625rem;
    border-radius: var(--radius-sm);
    color: var(--text);
    font-weight: 600;
    font-size: 0.9375rem;
    text-decoration: none;
    white-space: nowrap;
}
.lang-menu__item:hover { background: var(--surface-2); text-decoration: none; }
/*
 * O idioma activo. A cor sozinha nao chega — o galo diz o mesmo a quem nao a
 * distingue, e o `aria-current` diz o mesmo a quem nao ve nenhum dos dois.
 */
.lang-menu__item[aria-current="true"] {
    background: var(--surface-2);
    font-weight: 700;
}
.lang-menu__item[aria-current="true"]::after {
    content: "\2713";
    margin-left: auto;
    padding-left: 0.5rem;
    color: var(--accent);
}

/* -------------------------------------------------------------------- main */

main {
    flex: 1 0 auto;
    padding: 1.75rem 0 3.5rem;
}

.page-head { margin-bottom: 1.5rem; }
.page-head p { color: var(--muted); max-width: 42rem; }

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

/*
 * O heroi e marinho de ponta a ponta. E a unica superficie escura do site em
 * modo claro, e existe para responder em tres segundos as duas perguntas de
 * quem abre uma ligacao colada num grupo de Facebook: o que e isto, e porque e
 * que e diferente de vender numa publicacao qualquer.
 */
/*
 * A ALTURA DO HEROI E UM ORCAMENTO, e nao uma escolha de gosto.
 *
 * A regra da pagina inicial e que o primeiro cartao de anuncio tem de se ver sem
 * rolar num ecra de 375 x 812 — os anuncios sao a prova de que ha vida do outro
 * lado, e um vendedor com uma borracha de 40 euros para vender nao a confia a um
 * sitio que parece ter sido posto no ar ontem. Tudo o que este bloco gastar sai
 * dessa fotografia. Por isso a folga e menor em ecra estreito, e volta a ser
 * generosa a partir de 40rem, onde ha altura de sobra.
 */
.hero {
    background: var(--brand-navy);
    color: #ffffff;
    margin: -1.75rem 0 1.5rem;
    padding: 1.4rem 0 1.5rem;
    border-bottom: 3px solid var(--brand-orange);
}
@media (min-width: 40rem) {
    .hero { margin-bottom: 2rem; padding: 2.25rem 0; }
}
.hero h1 { color: #ffffff; max-width: 22ch; margin-top: 0.2rem; }
.hero p { max-width: 46rem; color: #d5dfee; font-size: 1.0625rem; }
.hero p.lead { color: #ffffff; }
.hero .eyebrow {
    display: block;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: #ffa273;
    margin-bottom: 0.7rem;
}
.hero .button--quiet {
    background: transparent;
    color: #ffffff;
    border-color: rgb(255 255 255 / 50%);
}
.hero .button--quiet:hover { background: rgb(255 255 255 / 12%); color: #ffffff; border-color: #ffffff; }
.hero__actions { display: flex; gap: 0.6rem; flex-wrap: wrap; margin-top: 1.25rem; }

/*
 * A nota por baixo dos botoes ("nao precisa de conta ate publicar") tem de ser
 * menor do que o corpo do heroi, e `.small` sozinha nao chega: `.hero p` vale
 * 0,1,1 e ganha-lhe o tamanho. Fica escrito aqui em vez de se aumentar a
 * especificidade de `.small`, que e uma utilitaria usada em meia duzia de sitios
 * e que ninguem quer ver a ganhar a componentes.
 */
.hero p.small { font-size: 0.9375rem; color: #b9c8de; margin-top: 0.9rem; }

/* --------------------------------------------- pagina inicial: quem vende */

/*
 * Um cabecalho de seccao com folga por cima, sem que a PRIMEIRA seccao da pagina
 * some essa folga a margem do heroi. O `* + ` resolve-o sem `:first-child`, que
 * aqui nao serve: o bloco de mensagens (`partials/flash`) e o primeiro filho de
 * `.wrap` nos dias em que existe e deixa de existir nos outros — um selector que
 * muda de alvo conforme houve ou nao um registo com sucesso e um selector que
 * ninguem consegue depurar.
 */
.section-head { margin: 0 0 0.9rem; }
* + .section-head { margin-top: 2.25rem; }

/*
 * O primeiro cabecalho da pagina inicial nao leva folga por cima: a margem do
 * heroi ja la esta, e somar as duas empurrava a primeira fotografia para fora da
 * dobra num ecra de 375. A regra da pagina e essa — acima da dobra ha um titulo
 * curto, uma linha e um botao, e a partir dai e PRODUTO.
 */
.section-head--first { margin-top: 0; }

/*
 * As categorias como mosaico, no fim da pagina inicial.
 *
 * Sao duas — o lancamento e so borrachas e madeiras — e duas pastilhas de 14 px a
 * flutuar nao dizem a ninguem o que este site vende. Dois pictogramas grandes
 * dizem-no sem uma palavra, e o pictograma e o MESMO de `partials/category-icon`:
 * traco desenhado, zero pedidos de rede, e nenhuma fotografia de banco de imagens
 * a mentir sobre o que o produto e.
 */
.tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 0.875rem;
    /* Duas categorias nao podem esticar-se a largura toda de um ecra de 1280: um
       alvo de 600 px de largura para um icone de 40 e um erro de escala. */
    max-width: 32rem;
}
.tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 1.25rem 0.75rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    color: var(--text);
    text-decoration: none;
}
.tile:hover {
    border-color: var(--accent);
    box-shadow: var(--shadow-lift);
    text-decoration: none;
    color: var(--text);
}
.tile .chip__icon { color: var(--accent); }
.tile__label { font-weight: 700; }

/*
 * As tres razoes para anunciar. A mesma linguagem grafica dos cartoes da montra
 * — superficie branca sobre o cinzento da pagina — com a barra laranja da marca
 * no topo, como no painel de caracteristicas do anuncio.
 */
.pitch {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.875rem;
}
@media (min-width: 44rem) {
    .pitch { grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
}
.pitch__item {
    background: var(--surface);
    border: 1px solid var(--border);
    border-top: 3px solid var(--brand-orange);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 1.1rem 1.15rem;
}
.pitch__item h3 { font-size: 1rem; margin: 0 0 0.35rem; }
.pitch__item p { margin: 0; color: var(--muted); font-size: 0.9375rem; }

/*
 * O tamanho do catalogo, e a frase honesta de projecto a comecar.
 *
 * O numero vai a cor do texto e NAO a laranja. `--accent` sobre `--surface` da
 * 4,84:1 em modo claro e cerca de 2,3:1 em modo escuro, porque em escuro a
 * superficie tambem e escura — daria um numero de 40 px ilegivel a noite, na
 * unica afirmacao concreta da pagina. O laranja da marca fica na barra do topo,
 * que e objecto grafico e nao texto (docs/ui/marca.md).
 */
.stat {
    background: var(--surface);
    border: 1px solid var(--border);
    border-top: 3px solid var(--brand-orange);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 1.4rem 1.25rem;
    margin-top: 1.5rem;
}
.stat__number {
    margin: 0;
    font-size: 2.5rem;
    line-height: 1.05;
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--text);
}
.stat__label {
    margin: 0.15rem 0 0.75rem;
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--muted);
}
.stat__body { margin: 0 0 0.75rem; color: var(--muted); font-size: 0.9375rem; max-width: 46rem; }
.stat__body:last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------- botoes */

/*
 * ESPECIFICIDADE, E PORQUE E QUE ESTA ESCRITA ASSIM
 *
 * `button.button` tem especificidade 0,1,1 e ganhava a `.button--quiet`
 * (0,1,0): um `<button class="button button--quiet">` — o "terminar sessao" do
 * cabecalho — saia preenchido a cheio, e a accao mais destacada da pagina de
 * quem tem sessao iniciada era sair dela. A correccao e dar a variante a MESMA
 * lista de selectores da base: `.button--quiet, button.button--quiet`. Vem
 * depois no ficheiro e passa a ganhar nos dois casos.
 *
 * O que NAO serve e por a base dentro de `:where()` para a zerar. Ja tentado, e
 * quebra o outro lado: `.site-nav :where(a)` (0,1,0) passava a ganhar a cor e o
 * "criar conta" do cabecalho saia com texto marinho sobre laranja — 3,41:1, por
 * baixo do minimo. As duas regras tem de ficar no mesmo patamar.
 */
.button,
button.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--tap);
    padding: 0.6rem 1.25rem;
    border: 1px solid var(--accent);
    border-radius: var(--radius-sm);
    background: var(--accent);
    color: var(--accent-text);
    font: inherit;
    font-weight: 700;
    font-size: 0.9375rem;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    text-align: center;
}
.button:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    color: var(--accent-text);
    text-decoration: none;
}

/*
 * `button.button--quiet` alem de `.button--quiet`, e pela mesma razao que o
 * `:where()` la em cima existe.
 *
 * A regra de base e `.button, button.button`, e esse segundo selector vale
 * (0,1,1). Uma variante escrita so como `.button--quiet` vale (0,1,0) e PERDE —
 * portanto todo o `<button class="button button--quiet">` do site saia pintado de
 * botao principal, enquanto um `<a class="button button--quiet">` com as MESMAS
 * classes saia certo. Duas coisas iguais a aparecer diferentes conforme a
 * etiqueta HTML, sem nada de estranho no codigo que o denunciasse.
 *
 * Deu na vista quando o stream W2 encheu os ecras de botoes secundarios —
 * "apagar foto", "mover", "reservar" — todos a gritar com a mesma forca do
 * "publicar" que estava ao lado.
 *
 * A auditoria de UI encontrou o mesmo defeito por outro caminho: para quem
 * tinha sessao iniciada, a accao mais destacada do site era "Sair".
 */
.button--quiet,
button.button--quiet {
    background: transparent;
    color: var(--text);
    border-color: var(--border-strong);
    font-weight: 500;
}
.button--quiet:hover,
button.button--quiet:hover { background: var(--surface-2); border-color: var(--muted); color: var(--text); }
.button--quiet:disabled { opacity: 0.4; cursor: default; }

.button--block { display: flex; width: 100%; }

.button--large { font-size: 1.0625rem; padding: 0.85rem 1.6rem; }

/* -------------------------------------------------------------- mensagens */

.notice {
    padding: 0.85rem 1rem;
    border: 1px solid var(--border);
    border-left-width: 4px;
    border-radius: var(--radius-sm);
    margin-bottom: 1.5rem;
    font-size: 0.9375rem;
}
.notice--ok { background: var(--ok-bg); border-color: var(--ok-bg); border-left-color: var(--ok); }
.notice--warn { background: var(--reserved-bg); border-color: var(--reserved-bg); border-left-color: var(--reserved); }
.notice--error { background: var(--danger-bg); border-color: var(--danger-bg); border-left-color: var(--danger); }
.notice--sold { background: var(--sold-bg); border-color: var(--sold-bg); border-left-color: var(--sold); }
.notice strong { display: block; margin-bottom: 0.15rem; }

/* --------------------------------------------------------------- cartoes */

.grid {
    display: grid;
    /*
     * 9.5rem = 152 px. Duas colunas mais o intervalo dao 318 px e cabem nos 343
     * uteis de um ecra de 375. Com 10.5rem faltavam sete pixeis, a segunda coluna
     * nao entrava e a montra voltava a ser uma fila de vinte cartoes.
     */
    grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
    gap: 0.875rem;
}
@media (min-width: 30rem) {
    .grid { grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); gap: 1.25rem; }
}

.card {
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    overflow: hidden;
    text-decoration: none;
    color: inherit;
}
.card:hover {
    border-color: var(--border-strong);
    box-shadow: var(--shadow-lift);
    text-decoration: none;
    color: inherit;
}

.card__media {
    aspect-ratio: 4 / 3;
    background: var(--surface-2);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    position: relative;
}
/*
 * Muita foto de material e um objecto claro sobre fundo branco. Sem esta linha
 * por dentro, a foto e o cartao fundem-se e o anuncio parece vazio — que e
 * exactamente a impressao que nao se quer dar num sitio de usados.
 */
.card__media::after {
    content: "";
    position: absolute;
    inset: 0;
    border-bottom: 1px solid var(--border);
    pointer-events: none;
}
.card__media img { width: 100%; height: 100%; object-fit: cover; }
.card__media--empty { color: var(--muted); font-size: 0.75rem; padding: 0.75rem; text-align: center; }

.card__body { padding: 0.7rem 0.75rem 0.85rem; display: flex; flex-direction: column; gap: 0.3rem; flex: 1; }
.card__brand {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    font-weight: 700;
    color: var(--muted);
}
.card__title {
    font-weight: 600;
    line-height: 1.3;
    font-size: 0.9375rem;
    color: var(--text);
}
/*
 * Preco a esquerda, estado de conservacao a direita, na mesma linha e no fundo
 * do cartao. E a comparacao que a pessoa faz ao percorrer a grelha: quanto custa
 * e em que estado esta. Tudo o resto no cartao serve para chegar a esta linha.
 */
.card__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.4rem;
    margin-top: auto;
    padding-top: 0.35rem;
    flex-wrap: wrap;
}
.card__price {
    font-weight: 800;
    font-size: 1.0625rem;
    letter-spacing: -0.02em;
    color: var(--text);
}
/* Numa coluna de 164 px, meio ponto a menos e o preco e o estado na mesma linha. */
.card__foot .cond { font-size: 0.6875rem; padding: 0.1rem 0.4rem; }
@media (min-width: 30rem) {
    .card__price { font-size: 1.125rem; }
    .card__foot .cond { font-size: 0.75rem; padding: 0.15rem 0.5rem; }
}
.card__meta { font-size: 0.75rem; color: var(--muted); }

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

.badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.15rem 0.5rem;
    border-radius: var(--radius-pill);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    background: var(--surface-2);
    color: var(--muted);
    border: 1px solid var(--border);
    white-space: nowrap;
}
.badge--sold { background: var(--sold-bg); color: var(--sold); border-color: transparent; }
.badge--reserved { background: var(--reserved-bg); color: var(--reserved); border-color: transparent; }
.badge--ok { background: var(--ok-bg); color: var(--ok); border-color: transparent; }

/*
 * O estado de conservacao com cor propria. A fraude tipica em usados de tenis de
 * mesa e o estado da borracha mal descrito: por o estado a cor, sempre no mesmo
 * sitio do cartao, torna "para pecas" tao visivel como "novo" — e premeia quem e
 * honesto, em vez de esconder a declaracao numa linha de texto cinzento.
 */
.cond {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem 0.5rem;
    border-radius: var(--radius-pill);
    font-size: 0.75rem;
    font-weight: 700;
    white-space: nowrap;
    background: var(--surface-2);
    color: var(--muted);
}
.cond--new { background: var(--cond-new-bg); color: var(--cond-new); }
.cond--like_new { background: var(--cond-like-new-bg); color: var(--cond-like-new); }
.cond--good { background: var(--cond-good-bg); color: var(--cond-good); }
.cond--used { background: var(--cond-used-bg); color: var(--cond-used); }
.cond--for_parts { background: var(--cond-parts-bg); color: var(--cond-parts); }
.cond--lg { font-size: 0.875rem; padding: 0.3rem 0.75rem; }

/* -------------------------------------------------------------- pastilhas */

/*
 * Pastilhas em vez de `<select>` para navegar por categoria. Um `<select>` num
 * telemovel sao dois toques e uma roda que tapa o ecra; uma pastilha e um toque,
 * e ve-se o que existe sem abrir nada. Cada uma e uma ligacao com endereco
 * proprio — continua a funcionar sem JavaScript e cola-se num grupo.
 */
.chips {
    display: flex;
    gap: 0.5rem;
    overflow-x: auto;
    padding: 0.25rem 0.15rem 0.6rem;
    margin: 0 -0.15rem;
    scrollbar-width: thin;
    -webkit-overflow-scrolling: touch;
}
.chips--wrap { flex-wrap: wrap; overflow: visible; }

.chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    flex: 0 0 auto;
    min-height: 2.5rem;
    padding: 0.4rem 0.9rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-pill);
    background: var(--surface);
    color: var(--text);
    font-size: 0.875rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}
.chip:hover { border-color: var(--muted); background: var(--surface-2); color: var(--text); text-decoration: none; }
.chip__icon { flex: 0 0 auto; color: var(--muted); }
.chip:hover .chip__icon { color: var(--text); }
.chip[aria-current="true"] .chip__icon { color: currentColor; }
.chip[aria-current="true"] {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-text);
}
.chip[aria-current="true"]:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--accent-text); }

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

.layout {
    display: grid;
    gap: 1.5rem;
    grid-template-columns: 1fr;
}
@media (min-width: 56rem) {
    .layout { grid-template-columns: 16.5rem 1fr; align-items: start; gap: 2rem; }
}

.filters {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0;
}
.filters h2 { font-size: 1rem; margin: 0; }

/*
 * No telemovel os filtros vivem fechados dentro de um `<details>`: abertos,
 * empurravam a primeira foto para 700 px abaixo da dobra, e a primeira foto e a
 * unica coisa que decide se a pessoa fica. Em ecra largo ha coluna para eles e o
 * `<details>` abre-se sempre — o triangulo desaparece e volta a ser um painel.
 */
.filters__summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    min-height: var(--tap);
    padding: 0.6rem 1rem;
    font-weight: 700;
    cursor: pointer;
    list-style: none;
    border-radius: var(--radius);
}
.filters__summary::-webkit-details-marker { display: none; }
.filters__summary::after {
    content: "▾";
    color: var(--muted);
    font-size: 0.875rem;
}
.filters[open] .filters__summary { border-bottom: 1px solid var(--border); border-radius: var(--radius) var(--radius) 0 0; }
.filters[open] .filters__summary::after { content: "▴"; }
.filters__body { padding: 1rem; }
/* "Limpar" tinha 34x17 px de area util. Um dedo nao acerta em 17 px. */
.filters__body p a { display: inline-block; padding: 0.4rem 0.6rem; }
.filters__count {
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--accent-text);
    background: var(--accent);
    border-radius: var(--radius-pill);
    padding: 0.1rem 0.5rem;
    margin-left: auto;
}

@media (min-width: 56rem) {
    .filters__summary { cursor: default; }
    .filters__summary::after { display: none; }
}

.field { margin-bottom: 0.9rem; }
.field label,
.field legend {
    display: block;
    font-size: 0.8125rem;
    font-weight: 700;
    margin-bottom: 0.3rem;
    color: var(--muted);
}
/*
 * A lista de `type` cresce com os formularios que existem, e por isso o `file`
 * NAO esta ca: um `<input type="file">` esticado a 100% com moldura propria fica
 * pior do que o controlo que o browser desenha sozinho, e cada browser desenha o
 * seu. O `tel` entrou com a confirmacao de telemovel (W2) — sem ele, o campo do
 * numero saia com a largura por omissao do browser ao lado de campos a toda a
 * largura, e a diferenca lia-se como um erro de desenho.
 */
.field input[type="text"],
.field input[type="search"],
.field input[type="email"],
.field input[type="password"],
.field input[type="number"],
.field input[type="tel"],
.field input[type="url"],
.field select,
.field textarea {
    width: 100%;
    min-height: var(--tap);
    padding: 0.55rem 0.65rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    /*
     * 16px, e nao 15. Abaixo de 16px o Safari do iOS AUMENTA a pagina sozinho
     * quando o campo recebe foco, e a pessoa perde o contexto a meio de escrever
     * — depois volta atras com dois dedos e ja nao sabe onde ia. Metade destes
     * anuncios vai ser criada num telemovel encostado a mesa de um clube.
     */
    font-size: 1rem;
}
.field .hint { font-size: 0.8125rem; color: var(--muted); margin: 0.3rem 0 0; font-weight: 400; }
.field--inline { display: flex; gap: 0.6rem; }
.field--inline > * { flex: 1; min-width: 0; }
/*
 * Indicativo + numero na mesma linha. O select NAO leva flex:1 — cresce ate ao
 * texto da opcao escolhida ("🇵🇹 Portugal (+351)") e para; o numero fica com o
 * resto. O max-width trava as opcoes compridas ("🇩🇪 Alemanha (+49)" em ecras
 * de 375px) para o campo do numero nunca ficar mais estreito do que os nove
 * digitos que vai receber — o browser corta o texto do select fechado, e cortar
 * o fim do nome de um pais ja escolhido nao esconde informacao nenhuma.
 */
/*
 * A fila de partilha, por baixo da galeria. Pastilhas com a COR DE CADA REDE:
 * e pela cor que o dedo reconhece o WhatsApp antes de ler a palavra. Os verdes
 * e azuis sao os oficiais das marcas — nao vem da paleta do site de proposito,
 * e ficam SO aqui: um botao de partilha pintado da nossa cor era um botao
 * qualquer.
 */
.share { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-top: 1rem; }
.share__btn {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    min-height: var(--tap);
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 999px;
    font: inherit;
    font-size: 0.9375rem;
    font-weight: 700;
    color: #fff;
    cursor: pointer;
    text-decoration: none;
}
.share__btn:hover { filter: brightness(1.08); text-decoration: none; }
.share__btn svg { width: 1.25rem; height: 1.25rem; flex: 0 0 auto; }
.share__btn--whatsapp { background: #25d366; }
.share__btn--facebook { background: #1877f2; }
.share__btn--native { background: var(--accent); }
/* Copiar e utilitario, nao e uma rede: fica quieto ao lado das coloridas. */
.share__btn--copy { background: transparent; color: var(--text); border: 1px solid var(--border-strong); }

.field--phone { display: flex; gap: 0.6rem; }
.field--phone select { flex: 0 1 auto; width: auto; max-width: 52%; }
.field--phone input[type="tel"] { flex: 1 1 auto; min-width: 0; }
.field--check { display: flex; align-items: center; gap: 0.6rem; min-height: var(--tap); }
.field--check input[type="checkbox"] { width: 1.5rem; height: 1.5rem; accent-color: var(--accent); flex: 0 0 auto; }
.field--check label { margin: 0; font-weight: 400; color: var(--text); font-size: 0.9375rem; }

.field-error {
    display: block;
    margin-top: 0.3rem;
    font-size: 0.8125rem;
    color: var(--danger);
}

.searchbar { display: flex; gap: 0.5rem; margin-bottom: 1.25rem; }
/*
 * O campo esta dentro de `.searchbar__field`, que e o que ancora a lista de
 * sugestoes em `position: absolute`. O `flex` mudou-se para o embrulho e o input
 * passa a encher-lhe a largura — sem esta linha, o campo encolhia para a largura
 * do texto que la estivesse.
 */
.searchbar input { min-width: 0; }
.searchbar__field input { width: 100%; }
.searchbar .button { flex: 0 0 auto; }


.results-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

/*
 * As estrelas da avaliacao: radios puros, sem JavaScript. A fila esta em
 * row-reverse (o HTML poe o 5 primeiro) para o selector ~ pintar "esta e as
 * anteriores" so com CSS — hover e checked.
 */
.rating__stars { display: inline-flex; flex-direction: row-reverse; gap: 0.15rem; }
.rating__stars input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.rating__stars label { font-size: 2.2rem; line-height: 1; color: var(--border-strong); cursor: pointer; padding: 0 0.1rem; }
.rating__stars label:hover,
.rating__stars label:hover ~ label,
.rating__stars input:checked ~ label { color: #f5a623; }
.rating__stars input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

.review-item { display: flex; align-items: center; gap: 0.9rem; margin-bottom: 1.25rem; }

/* ---------------------------------------------------------- estados vazios */

/*
 * Um ecra sem resultados e metade de um produto novo. Duas linhas de texto
 * cinzento sao um beco sem saida: quem la chega fecha o separador. Um estado
 * vazio tem de dizer o que aconteceu e dar o caminho de volta num toque.
 */
.empty {
    background: var(--surface);
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius);
    padding: 2rem 1.25rem;
    text-align: center;
}
/* h2 ou h3 conforme o nivel que o resto da pagina ja gastou — a hierarquia de
   cabecalhos manda no elemento, e o estado vazio nao pode obrigar a saltar um
   nivel so para apanhar um estilo. */
.empty h2,
.empty h3 { font-size: 1.125rem; margin-bottom: 0.35rem; }
.empty p { color: var(--muted); max-width: 34rem; margin-inline: auto; }
.empty .chips { justify-content: center; margin-top: 1rem; }
.empty__actions { margin-top: 1.25rem; display: flex; gap: 0.6rem; justify-content: center; flex-wrap: wrap; }

/* -------------------------------------------------------------- detalhe */

/*
 * A ordem no DOM e a ordem certa no telemovel: foto, preco e caracteristicas,
 * descricao. E a ordem das perguntas de quem chega — ver a coisa, saber quanto
 * custa, saber em que estado esta — e no telemovel a ordem do DOM E a ordem da
 * pagina. Empurrar o preco para baixo da descricao obrigava a rolar meio ecra
 * para responder a segunda pergunta.
 *
 * Em ecra largo a grelha volta a por a descricao debaixo da galeria, onde ha
 * espaco para ela, sem mexer no HTML.
 */
.detail {
    display: grid;
    gap: 1.5rem;
    grid-template-columns: 1fr;
    align-items: start;
}
@media (min-width: 56rem) {
    /*
     * `1fr` na segunda linha, e nao `auto`: a coluna dos factos atravessa as duas
     * linhas e e quase sempre a mais alta. Com duas linhas automaticas, o excesso
     * dela repartia-se pelas duas e abria um buraco de 160 px entre a foto e a
     * descricao. Numa linha flexivel o excesso cai todo na de baixo, e o
     * `align-self: start` mantem a descricao colada a foto: o vazio, se sobrar,
     * fica no fim da pagina, onde ninguem repara nele.
     */
    .detail { grid-template-columns: minmax(0, 3fr) minmax(19rem, 2fr); grid-template-rows: auto 1fr; gap: 2rem; }
    .detail__gallery { grid-column: 1; grid-row: 1; }
    .detail__facts { grid-column: 2; grid-row: 1 / span 2; }
    .detail__about { grid-column: 1; grid-row: 2; align-self: start; }
}

.listing-head { margin-bottom: 1.25rem; }
.listing-head h1 { margin-bottom: 0.4rem; }
.listing-head__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.75rem;
    color: var(--muted);
    font-size: 0.875rem;
    margin: 0;
}

.gallery__main {
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}
/*
 * A moldura acompanha a fotografia, e nao o contrario.
 *
 * Estava `aspect-ratio: 4 / 3` fixo, deitado. Uma borracha fotografada de cima com
 * um telemovel vem em pe (3:4), e dentro de uma moldura deitada aparecia minuscula
 * entre duas barras — a ocupar um terco do espaco que lhe estava reservado. A
 * proporcao verdadeira vem agora do `style` inline de cada imagem, com os pixeis
 * que ja estavam gravados em `listing_media`.
 *
 * `max-height: 78vh` e o unico limite que fica: sem ele, uma fotografia muito alta
 * empurrava o preco e o botao de contactar para fora do ecra, e a pagina abria numa
 * imagem sem nada mais a vista. `object-fit: contain` garante que ai a imagem
 * encolhe inteira em vez de ser cortada — cortar a fotografia de um anuncio e
 * esconder o que a pessoa quer ver.
 */
.gallery__main img {
    display: block;
    margin: 0 auto;
    /*
     * DOIS TECTOS, E A IMAGEM ENCOLHE NOS DOIS.
     *
     * `width: 100%` com `max-height` nao chega: a largura fica cravada nos 100 % e
     * so a altura e cortada, portanto o `object-fit` mete a fotografia numa caixa
     * larga de mais e desenha barras dos lados — que e exactamente o defeito que
     * isto veio corrigir, so que mais pequeno.
     *
     * Com `width: auto` e os dois maximos, o browser escolhe a menor das duas
     * reducoes e a caixa encolhe com a imagem. Nao ha barras nenhumas porque nao ha
     * espaco a sobrar: a moldura passa a ter o tamanho da fotografia.
     *
     * O tecto de altura fica: sem ele, uma fotografia em pe empurrava o preco e o
     * botao de contactar para fora do ecra, e a pagina abria numa imagem sem nada
     * mais a vista.
     */
    width: 100%;
    height: auto;
    max-height: 78vh;
    /*
     * `cover` e nao `contain`, e so faz diferenca nos extremos: entre 4:5 e 16:9 a
     * moldura E a proporcao da fotografia, portanto nao ha nada a cortar. Fora
     * desse intervalo, `cover` corta o minimo em vez de desenhar barras.
     */
    object-fit: cover;
    background: var(--surface-2);
}

.gallery__strip {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.6rem;
    overflow-x: auto;
    padding-bottom: 0.25rem;
    scrollbar-width: thin;
}
.gallery__strip a { display: block; border-radius: var(--radius-sm); flex: 0 0 auto; }
.gallery__strip img {
    width: 4.5rem;
    height: 4.5rem;
    object-fit: cover;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    display: block;
}

/*
 * A miniatura activa tem de se ver de relance: sem isto, trocar a fotografia
 * grande nao da sinal nenhum de qual delas se esta a ver, e a pessoa clica duas
 * vezes na mesma sem perceber porque e que nada mudou.
 */
.gallery__thumb img { transition: border-color 0.12s ease, opacity 0.12s ease; }
.gallery__thumb:hover img { border-color: var(--muted); }
.gallery__thumb.is-active img {
    border-color: var(--brand-orange);
    box-shadow: 0 0 0 2px var(--brand-orange);
}
.gallery__thumb:not(.is-active) img { opacity: 0.75; }
.gallery__thumb:not(.is-active):hover img { opacity: 1; }
.gallery__empty {
    padding: 3rem 1rem;
    text-align: center;
    color: var(--muted);
    background: var(--surface-2);
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius);
}

.panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1.15rem;
    box-shadow: var(--shadow);
}
.panel + .panel { margin-top: 1rem; }
.panel h2 { font-size: 1.0625rem; }

/*
 * O painel das caracteristicas leva a barra da marca no topo. Nao e decoracao: e
 * o painel que responde a pergunta que faz alguem comprar ou nao comprar, e ate
 * aqui era indistinguivel do painel ao lado.
 */
.panel--specs { border-top: 3px solid var(--brand-orange); }

/*
 * "Avisamos quando aparecer", na montra sem resultados (ou quase).
 *
 * Leva a mesma barra laranja do painel de caracteristicas, e pela mesma razao:
 * num ecra que acabou de dizer "nao ha nada", este e o unico bloco que oferece
 * alguma coisa, e tem de se distinguir do estado vazio que esta imediatamente
 * por cima dele.
 */
.panel--alert { border-top: 3px solid var(--brand-orange); margin-top: 1.25rem; }
.panel--alert p { max-width: 42rem; }
.panel--alert form { margin: 1rem 0 0.75rem; }

/*
 * A procura que se vai guardar, escrita por palavras. E o que a pessoa esta a
 * confirmar antes de carregar no botao — se ela nao se reconhecer nesta linha, o
 * alerta que fica gravado nao e o que ela queria. `SearchSummary` escreve-a, e a
 * mesma frase passa a ser o NOME do alerta.
 */
.alert-cta__search {
    margin: 0.75rem 0 0;
    padding: 0.6rem 0.85rem;
    background: var(--surface-2);
    border-radius: var(--radius-sm);
    font-weight: 600;
}

.price {
    font-size: 2rem;
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1.1;
    margin: 0 0 0.25rem;
    color: var(--text);
}
.price-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-bottom: 0.35rem;
}
.price-row .price { margin: 0; }

/*
 * Rotulo pequeno por cima, valor a negrito por baixo, duas colunas. A tabela
 * `dt`/`dd` alinhada em linha lia-se como uma factura; assim le-se como uma
 * ficha tecnica, que e o que estes campos sao. Espessura, dureza e horas de jogo
 * sao a prova de que um anuncio e honesto — tem de PARECER a prova.
 */
.specs {
    margin: 0;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.85rem 1rem;
}
.specs > div { min-width: 0; }
.specs dt {
    color: var(--muted);
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    margin-bottom: 0.1rem;
}
.specs dd {
    margin: 0;
    font-weight: 700;
    font-size: 0.9375rem;
    color: var(--text);
    overflow-wrap: anywhere;
}

.seller { display: flex; align-items: center; gap: 0.75rem; }
.seller__avatar {
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 50%;
    background: var(--surface-2);
    border: 1px solid var(--border);
    object-fit: cover;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 800;
    color: var(--muted);
}
.seller__name { font-weight: 700; }
.seller--lg .seller__avatar { width: 3.75rem; height: 3.75rem; font-size: 1.35rem; }

/*
 * Estrelas desenhadas com texto, nao com imagem: sao 0 bytes de rede e escalam
 * com o tipo de letra de quem aumentou o corpo do texto no telemovel. O numero
 * fica sempre ao lado — as estrelas dizem "bom" de relance, o numero e o que se
 * verifica — e o `aria-label` diz a frase inteira a quem nao as ve.
 */
.stars {
    display: inline-flex;
    align-items: center;
    gap: 0.1rem;
    color: var(--brand-orange);
    font-size: 0.9375rem;
    line-height: 1;
}
.stars--lg { font-size: 1.25rem; }
.stars .star--off { color: var(--border-strong); }
.rating-line {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    font-size: 0.9375rem;
}
.rating-line .rating-count { color: var(--muted); }

.reviews { list-style: none; margin: 1rem 0 0; padding: 0; }
.reviews li { padding: 0.85rem 0; border-top: 1px solid var(--border); font-size: 0.9375rem; }
.reviews li:first-child { border-top: 0; padding-top: 0; }
.reviews .review__head { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.25rem; }
.reviews .review__who { font-weight: 600; }
.reviews .review__comment { margin: 0; color: var(--text); }

/* ----------------------------------------------------------- formularios */

.form-page { max-width: 27rem; margin: 0 auto; }
.form-page .panel { padding: 1.5rem; }
.form-page h1 { font-size: 1.5rem; }
.form-page .alt { margin-top: 1.25rem; text-align: center; font-size: 0.9375rem; color: var(--muted); }
/* Uma ligacao solta dentro de um formulario tambem e um alvo de toque. */
.form-page .alt a { display: inline-block; padding: 0.5rem 0.25rem; }

/* O mesmo para o "voltar" no topo do anuncio: 17 px de altura nao chegam. */
.back-link { display: inline-block; padding: 0.4rem 0.5rem; margin-left: -0.5rem; font-size: 0.9375rem; font-weight: 600; }

/* --------------------------------------------------------------- listas */

.rows { list-style: none; margin: 0; padding: 0; }
.rows li {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    padding: 0.6rem 0;
    border-bottom: 1px solid var(--border);
}
.rows li:last-child { border-bottom: 0; }
.rows .row__title { font-weight: 600; }
.rows .row__title a { display: inline-block; padding: 0.35rem 0; }
.rows .row__meta { color: var(--text); font-size: 0.9375rem; margin-left: auto; font-weight: 700; }

/* ------------------------------------------------------------------ prosa */

.prose { max-width: 44rem; }
.prose h2 { margin-top: 2rem; }
.prose h3 { margin-top: 1.5rem; }
.prose ul, .prose ol { padding-left: 1.25rem; }
.prose li { margin-bottom: 0.4rem; }

/* ----------------------------------------------------------------- rodape */

/*
 * Tres razoes para ficar, no fim de cada pagina. Nao sao selos de confianca
 * inventados: cada uma descreve uma coisa que o produto FAZ hoje. Um selo de
 * "pagamento seguro" sem pagamento por tras destruia exactamente a confianca que
 * este rodape existe para construir.
 */
.value-props {
    display: grid;
    gap: 1.25rem;
    grid-template-columns: 1fr;
    padding: 2rem 0;
    border-top: 1px solid var(--border);
}
@media (min-width: 44rem) {
    .value-props { grid-template-columns: repeat(3, 1fr); gap: 2rem; }
}
.value-prop { display: flex; gap: 0.75rem; align-items: flex-start; }
.value-prop svg { flex: 0 0 auto; width: 1.5rem; height: 1.5rem; color: var(--brand-orange); }
.value-prop h2 { font-size: 0.9375rem; margin: 0 0 0.15rem; }
.value-prop p { font-size: 0.875rem; color: var(--muted); margin: 0; }

.site-footer {
    border-top: 1px solid var(--border);
    background: var(--surface);
    padding: 1rem 0 1.5rem;
    font-size: 0.875rem;
    color: var(--muted);
}
.site-footer__inner {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
    align-items: center;
}
.site-footer a {
    color: var(--muted);
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
    padding: 0 0.25rem;
}
.site-footer a:hover { color: var(--link-hover); }
.site-footer .spacer { margin-left: auto; }
.site-footer__brand { display: inline-flex; align-items: center; gap: 0.5rem; }
.site-footer__brand svg { height: 0.9rem; width: auto; }

/* Quem prefere menos movimento nao leva nenhum. */
@media (prefers-reduced-motion: reduce) {
    * { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}

/* --------------------------------------------------- intervalo de preco */

/*
 * DOIS SLIDERS EMPILHADOS, e nao dois sobrepostos.
 *
 * A sobreposicao com posicionamento absoluto e a receita habitual e da um
 * controlo bonito: um so carril com dois punhos. Tambem e a receita que parte com
 * o teclado, com o leitor de ecra e em qualquer browser que desenhe o punho a
 * medida diferente. Aqui, cada `range` e um `range` a serio, com o seu rotulo, o
 * seu foco e as suas setas. Custa 40 px de altura e nao custa mais nada.
 *
 * Nasce `hidden` no HTML: sem JavaScript nao ha quem o faca funcionar, e um
 * controlo visivel que nao faz nada e pior do que nenhum.
 */
/*
 * INTERVALO DE PRECO: um percurso, dois punhos.
 *
 * Os dois `input[type=range]` estao sobrepostos em cima da mesma barra. O truque
 * inteiro esta em `pointer-events`: o input nao apanha o rato em lado nenhum, so
 * o punho apanha. Sem isso, o input de cima cobria a barra toda e o de baixo
 * ficava inalcancavel a partir do primeiro pixel.
 *
 * A barra visivel e a `.range__track`, um `<div>`, e nao a barra nativa do input
 * — que fica transparente. Desenhar a nossa e o que permite pintar o troco
 * escolhido entre os punhos, e o que faz os dois inputs parecerem um controlo so.
 *
 * O teclado continua a funcionar como sempre: sao dois campos, com foco proprio e
 * setas proprias. Nada aqui lhes toca.
 */
.range {
    position: relative;
    margin-bottom: 1rem;
    padding: 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
}
.range[hidden] { display: none; }

/* A altura reservada aos dois punhos sobrepostos: um alvo de toque, nao dois. */
.range__track {
    position: relative;
    height: var(--tap);
    margin: 0.25rem 0 0;
}

/* A barra propriamente dita, centrada na altura do alvo de toque. */
.range__track::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 4px;
    transform: translateY(-50%);
    border-radius: 2px;
    background: var(--border-strong);
}

/* O troco escolhido. `left` e `width` sao escritos pelo price-range.js. */
.range__fill {
    position: absolute;
    top: 50%;
    height: 4px;
    transform: translateY(-50%);
    border-radius: 2px;
    background: var(--accent);
}

.range__input {
    position: absolute;
    /* Sobe exactamente a altura do percurso que acabou de ser desenhado, para
       ficar por cima dele. `.range` tem 0.75rem de padding de cada lado. */
    left: 0.75rem;
    right: 0.75rem;
    width: auto;
    height: var(--tap);
    margin-top: calc(var(--tap) * -1);
    background: transparent;
    -webkit-appearance: none;
    appearance: none;
    /* Ver o comentario do bloco: so o punho apanha o rato. */
    pointer-events: none;
}

/* A barra nativa desaparece — a nossa esta por baixo e e a que se ve. */
.range__input::-webkit-slider-runnable-track { background: transparent; border: none; }
.range__input::-moz-range-track { background: transparent; border: none; }

.range__input::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    pointer-events: auto;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 50%;
    border: 2px solid var(--surface);
    background: var(--accent);
    box-shadow: 0 1px 3px rgb(0 0 0 / 0.3);
    cursor: grab;
}

.range__input::-moz-range-thumb {
    pointer-events: auto;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 50%;
    border: 2px solid var(--surface);
    background: var(--accent);
    box-shadow: 0 1px 3px rgb(0 0 0 / 0.3);
    cursor: grab;
}

/*
 * O foco vai ao PUNHO e nao a caixa toda: o input ocupa a largura inteira do
 * percurso, e um contorno a toda a volta nao dizia a ninguem qual dos dois
 * punhos e que estava com o foco.
 */
.range__input:focus { outline: none; }
.range__input:focus-visible::-webkit-slider-thumb { outline: 3px solid var(--brand-orange); outline-offset: 2px; }
.range__input:focus-visible::-moz-range-thumb { outline: 3px solid var(--brand-orange); outline-offset: 2px; }

/*
 * Campo de dinheiro: o simbolo dentro da caixa, e nao no rotulo.
 *
 * No rotulo — "Preco desde (€)" — a moeda le-se uma vez e desaparece; dentro da
 * caixa fica ao lado do numero enquanto se escreve, que e quando a duvida existe.
 * Esta duvida custou caro: os campos estiveram em centimos, e escrever 25 pedia
 * anuncios a partir de vinte e cinco cimos sem nada na pagina que o explicasse.
 */
.money-input {
    position: relative;
    display: block;
}

.money-input__symbol {
    position: absolute;
    left: 0.65rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--muted);
    pointer-events: none;
}

/*
 * `input[type="number"]` e nao `input`: o campo apanha o `padding` geral dos
 * campos do formulario, declarado mais abaixo no ficheiro, e com a mesma
 * especificidade ganha o que vem depois. Sem isto o numero comeca onde o simbolo
 * esta e os dois escrevem-se um por cima do outro.
 */
.money-input input[type="number"] { padding-left: 1.7rem; }

.range__value {
    margin: 0.25rem 0 0;
    font-weight: 700;
    font-size: 0.9375rem;
    text-align: center;
}

/* ------------------------------------------- o que outros pedem pelo modelo */

/*
 * DISCRETO DE PROPOSITO. Isto nao e um conselho nosso sobre quanto pedir: sao
 * factos sobre o que existe, e a diferenca tem de se ver no desenho. Um painel
 * com destaque, ou um numero grande ao lado do campo, leria-se como "preco
 * recomendado" por mais que o texto dissesse o contrario.
 *
 * A barra a esquerda separa-o do erro de validacao, que vive no mesmo sitio e
 * nao pode ser confundido com ele.
 */
.market {
    margin: 0.5rem 0 0;
    padding-left: 0.6rem;
    border-left: 2px solid var(--border-strong);
    font-size: 0.8125rem;
    color: var(--muted);
}
.market__line { display: block; }

/* O preco praticado e facto, o pedido e aspiracao. A diferenca de peso e a unica
   coisa que este bloco afirma. */
.market__line--sold { color: var(--text); font-weight: 600; }

/* --------------------------------------------- fluxo: o que ja esta escolhido */

/*
 * "Borrachas › Butterfly Tenergy 05 › Bom estado", por baixo da barra de passos.
 *
 * A barra diz ONDE SE ESTA; esta linha diz O QUE SE TEM. Ao quarto passo, quem
 * voltou ao formulario no dia seguinte ja nao sabe se escolheu a Tenergy 05 ou a
 * 05 Hard, e a unica maneira de confirmar era recuar e perder o sitio.
 *
 * UMA LINHA, E UMA LINHA SO. A dobra deste fluxo ja esta disputada, e isto nao e
 * um painel: 0,6rem de altura util e um separador a seguir. `overflow-x: auto` e
 * a valvula de ultimo recurso — antes de cortar o nome de um modelo, a linha
 * desliza, como a fila de categorias da montra.
 */
.flow-context {
    display: flex;
    align-items: center;
    gap: 0.15rem;
    margin: 0.35rem 0 0;
    padding-bottom: 0.15rem;
    overflow-x: auto;
    scrollbar-width: none;
    font-size: 0.8125rem;
}
.flow-context::-webkit-scrollbar { display: none; }

.flow-context__item {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex: 0 0 auto;
    padding: 0.3rem 0.4rem;
    border-radius: var(--radius-sm);
    color: var(--muted);
    text-decoration: none;
    /* O nome do modelo NUNCA leva reticencias: e a unica coisa que a pessoa esta
       mesmo a confirmar, e "Butterfly Tenergy…" nao confirma nada. */
    white-space: nowrap;
}
.flow-context a.flow-context__item:hover { color: var(--link-hover); background: var(--surface-2); text-decoration: none; }

/* O separador e desenhado em CSS e nao escrito no HTML: um "›" no meio do texto
   e lido em voz alta por um leitor de ecra a cada elemento. */
.flow-context__item + .flow-context__item::before {
    content: "›";
    margin-right: 0.3rem;
    color: var(--border-strong);
}

/* O passo actual e texto e nao ligacao — e ganha o peso, porque e o unico
   elemento da linha que nao e uma escolha ja feita. */
.flow-context__item.is-current { color: var(--text); font-weight: 700; }

/* O que sai primeiro num ecra estreito e o que menos identifica. O estado e o
   preco desaparecem, e a categoria fica so com o pictograma — o nome do modelo
   fica sempre, e fica inteiro. */
.flow-context__item--category .flow-context__label,
.flow-context__item--details,
.flow-context__item--price { display: none; }

@media (min-width: 30rem) {
    .flow-context__item--category .flow-context__label { display: inline; }
    .flow-context__item--details { display: inline-flex; }
}
@media (min-width: 40rem) {
    .flow-context__item--price { display: inline-flex; }
}

/* --------------------------------------------------- anunciar material (W2) */
/*
 * Os ecras de "Anunciar material" reaproveitam `.panel`, `.field` e `.button` da
 * web publica. O que ha aqui de novo sao as tres coisas que este fluxo tem e as
 * paginas de leitura nao tinham: uma barra de passos, uma grelha de escolha, e a
 * grelha de fotos com o seu progresso.
 */

/* Escolha de categoria: radios que se carregam como cartoes, mas que continuam a
   ser radios — o `:has()` pinta o que esta escolhido sem uma linha de script, e
   onde ele nao existe fica um radio normal, que funciona na mesma. */
.choices {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: 0.6rem;
    border: 0;
    padding: 0;
    margin: 0 0 1rem;
}
.choice {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    background: var(--surface);
    cursor: pointer;
}
.choice:has(input:checked) {
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent);
}
.choice:has(input:focus-visible) { outline: 2px solid var(--link); outline-offset: 2px; }
.choice__label { font-weight: 600; }

.field-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0 1rem;
}
.field-row > .field { flex: 1 1 8rem; }

/* Um formulario de um botao so, para caber numa linha ao lado de texto. Sem isto
   cada `<form>` quebra a linha e a lista de accoes fica com uma altura absurda. */
.inline-form { display: inline; }
.inline-form + .inline-form { margin-left: 0.25rem; }

.row--managed { align-items: center; }

/*
 * A capa de cada anuncio em "os meus anuncios".
 *
 * Uma pessoa com seis anuncios reconhece-os pela fotografia e nao pelo titulo —
 * "Butterfly Tenergy 05" e "Butterfly Tenergy 05 FX" sao a mesma linha de texto
 * ate ao fim. 56 px chegam para reconhecer e nao roubam a linha ao titulo nem
 * aos botoes.
 *
 * `flex: 0 0 auto` porque a linha e um flex com `flex-wrap`: sem isto a
 * miniatura encolhia para uma tira quando os botoes pedem espaco.
 */
.row__thumb {
    flex: 0 0 auto;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--surface-2);
    border: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
}
.row__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

/*
 * Sem fotos NAO e um rectangulo vazio: e a razao numero um de um anuncio nao
 * poder ser publicado, e esta lista e onde a pessoa descobre o que lhe falta. O
 * contorno a tracejado e a mesma linguagem do estado vazio da montra.
 */
.row__thumb--empty {
    border-style: dashed;
    border-color: var(--border-strong);
    color: var(--muted);
    font-size: 0.625rem;
    line-height: 1.2;
    padding: 0.2rem;
}

.row__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    width: 100%;
}

.photo-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: 0.75rem;
    list-style: none;
    padding: 0;
    margin: 1rem 0 0;
}
.photo {
    position: relative;
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    overflow: hidden;
    background: var(--surface-2);
}
.photo img {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
}
.photo__placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1 / 1;
    font-size: 0.8125rem;
    color: var(--muted);
    text-align: center;
    padding: 0.5rem;
}
.photo__badge {
    position: absolute;
    top: 0.4rem;
    left: 0.4rem;
}
.photo__actions {
    display: flex;
    /*
     * `nowrap`, e os tres botoes a repartir a largura da coluna.
     *
     * Com `wrap`, numa coluna de 124 px, o caixote caia para uma segunda linha e
     * cada miniatura ficava 44 px mais alta — numa grelha de seis, sao 264 px de
     * rolagem por causa de um botao. A largura encolhe ate 36 px; a ALTURA fica
     * nos 44 do token `--tap`, que e a medida que conta para um dedo e a que
     * mantem os tres bem acima do minimo de 24 x 24 da WCAG 2.5.8.
     */
    flex-wrap: nowrap;
    gap: 0.25rem;
    padding: 0.4rem;
    justify-content: center;
}
.photo__actions .icon-button { flex: 1 1 0; width: auto; min-width: 2.25rem; }

/* Uma foto que falhou nao pode parecer uma foto: conta para o minimo de tres
   tanto como uma que nao existe, ou seja, nada. */
.photo--failed { border-color: var(--danger); }
.photo--failed .photo__placeholder { color: var(--danger); font-weight: 600; }
.photo__note {
    margin: 0;
    padding: 0 0.5rem 0.5rem;
    font-size: 0.75rem;
    color: var(--muted);
    text-align: center;
}

/*
 * BOTOES SO COM ICONE — as duas setas e o caixote de cada miniatura.
 *
 * Eram tres botoes com texto, e numa fila de seis miniaturas enchiam o ecra de
 * palavras: escondiam exactamente aquilo que a pessoa esta a tentar ver, que sao
 * as fotografias.
 *
 * O ALVO NAO ENCOLHE COM O ICONE. `--tap` e o mesmo token dos botoes normais
 * (2,75rem = 44 px): um icone de 20 px desenhado dentro de um alvo de 44 le-se e
 * acerta-se num telemovel. Um botao de 20 px nao se acerta.
 */
.icon-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--tap);
    height: var(--tap);
    padding: 0;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    cursor: pointer;
    line-height: 0;
}
.icon-button:hover:not(:disabled) { background: var(--surface-2); border-color: var(--muted); }
.icon-button:disabled { opacity: 0.35; cursor: default; }
.icon-button--danger:hover:not(:disabled) { color: var(--danger); border-color: var(--danger); }
.icon-button .icon { display: block; }

/*
 * A ZONA DE LARGAR.
 *
 * O `<input type="file">` continua la dentro, visivel e a funcionar: e ele que
 * serve quem nao tem JavaScript e e ele que da o foco de teclado a zona inteira
 * — o rotulo e um `<label for>`, e o anel de foco desenha-se na zona toda com
 * `:focus-within`. Nao ha aqui uma `<div>` que so responde ao rato.
 */
.dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 0.5rem;
    padding: 1.5rem 1rem;
    border: 2px dashed var(--border-strong);
    border-radius: var(--radius);
    background: var(--surface-2);
    margin-bottom: 1rem;
}
.dropzone:focus-within { border-color: var(--accent); outline: 3px solid var(--brand-orange); outline-offset: 2px; }
.dropzone.is-dragging { border-color: var(--accent); background: var(--surface); border-style: solid; }
.dropzone svg { color: var(--accent); }
.dropzone__title {
    font-weight: 700;
    font-size: 1.0625rem;
    cursor: pointer;
    /* O rotulo e o alvo grande do rato: um `<label for>` ja abre o selector de
       ficheiros sem uma linha de script. */
    padding: 0.25rem 0.5rem;
}
.dropzone__hint { margin: 0; font-size: 0.875rem; color: var(--muted); max-width: 34rem; }
.dropzone input[type="file"] { max-width: 100%; }
/* `.field .hint` nao chega aqui: a zona de largar nao esta dentro de um `.field`,
   e sem isto a linha dos formatos saia do tamanho do corpo, a competir com o
   convite que esta por cima dela. */
.dropzone .hint { margin: 0.25rem 0 0; font-size: 0.8125rem; color: var(--muted); }

/*
 * A pre-visualizacao de cada ficheiro escolhido, ANTES de subir.
 *
 * O erro vive ao lado da miniatura a que pertence e nao num bloco no topo: um
 * aviso a dizer "uma das fotos falhou" obriga a adivinhar qual.
 */
.upload-previews {
    list-style: none;
    padding: 0;
    margin: 0.75rem 0 0;
    display: grid;
    gap: 0.5rem;
}
.upload-preview {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.4rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
}
.upload-preview__media {
    flex: 0 0 auto;
    width: 3rem;
    height: 3rem;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--surface-2);
}
.upload-preview__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.upload-preview__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.25rem; }
.upload-preview__name { font-size: 0.875rem; word-break: break-word; }
.upload-preview progress { width: 100%; }
.upload-preview .field-error:empty { display: none; }
.upload-preview.is-done { border-color: var(--ok); }
.upload-preview.is-failed { border-color: var(--danger); }

.review__cover {
    display: block;
    /* Uma pre-visualizacao, nao a pagina do anuncio: a foto nao pode ocupar o
       ecra todo e empurrar para baixo a lista do que ainda falta. */
    max-width: min(100%, 20rem);
    border-radius: 0.5rem;
    margin: 0.75rem 0;
}

textarea {
    width: 100%;
    font: inherit;
    padding: 0.6rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: 0.4rem;
    background: var(--surface);
    color: var(--text);
    resize: vertical;
}

/* Visivel para um leitor de ecra, invisivel para os olhos. Serve os rotulos que
   existem por obrigacao de acessibilidade mas que o desenho ja diz. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}


/* ------------------------------------------------- moldura do fluxo (W2) */
/*
 * O fluxo de anunciar NAO usa o layout do site, e nada aqui e decoracao: um
 * formulario de seis passos compete com tudo o que estiver a volta dele, e cada
 * ligacao de navegacao e um convite a sair a meio. Ver
 * resources/views/web/sell/layouts/flow.blade.php.
 *
 * A pagina de sucesso e a excepcao e volta ao layout normal — nesse momento
 * queremos exactamente o contrario.
 */

.flow-body {
    /* Uma coluna estreita, centrada. Uma decisao por ecra le-se melhor num
       bloco que cabe de uma vez do que espalhada por 1200px. */
    max-width: 34rem;
    margin: 0 auto;
    padding: 0 1rem 3rem;
}

.flow-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.25rem 0 0.5rem;
}
/*
 * O logotipo e ancora, nao menu: pequeno e sem peso visual. E o mesmo wordmark
 * em SVG do resto do site — duas marcas diferentes no mesmo produto notam-se,
 * ainda por cima a meio do fluxo que pede a conta.
 */
.flow-brand {
    display: inline-flex;
    color: var(--text);
    text-decoration: none;
}
.flow-brand svg { height: 1.1rem; width: auto; display: block; }

.flow-main { padding: 1rem 0 0; }

.flow-footer {
    margin-top: 2.5rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--border);
    font-size: 0.8125rem;
    color: var(--muted);
    text-align: center;
}
.flow-footer p { margin: 0.35rem 0; }

/* "Voltar" e sempre secundario e discreto: a decisao do ecra e a outra. */
.flow-back { margin-top: 1.25rem; text-align: center; font-size: 0.875rem; }
.flow-back a { color: var(--muted); }

.steps { margin: 0 0 1.5rem; }
.steps__count {
    margin: 0 0 0.4rem;
    font-size: 0.8125rem;
    color: var(--muted);
    font-weight: 600;
}
.steps__bar {
    display: block;
    width: 100%;
    height: 0.35rem;
    border: 0;
    border-radius: 999px;
    background: var(--surface-2);
    /* O `progress` tem partes internas proprias em cada motor; sem estas duas
       linhas, Firefox e WebKit desenham cada um a sua barra cinzenta. */
    -webkit-appearance: none;
    appearance: none;
    overflow: hidden;
}
.steps__bar::-webkit-progress-bar { background: var(--surface-2); }
.steps__bar::-webkit-progress-value { background: var(--accent); }
.steps__bar::-moz-progress-bar { background: var(--accent); }

/*
 * A lista de nomes dos passos so a partir de ecra largo. Num telemovel, seis
 * etiquetas em duas linhas roubavam o espaco ao passo actual — e "Passo 3 de 6"
 * mais a barra ja dizem tudo o que ela diria.
 */
.steps__list { display: none; }
@media (min-width: 34rem) {
    .steps__list {
        display: flex;
        flex-wrap: wrap;
        gap: 0.25rem 0.9rem;
        list-style: none;
        padding: 0;
        margin: 0.6rem 0 0;
        font-size: 0.8125rem;
        counter-reset: step;
    }
    .steps__item { color: var(--muted); counter-increment: step; }
    /* O numero vem do contador CSS e nao do HTML: reordenar os passos no PHP
       nao pode obrigar a renumerar nada a mao. */
    .steps__item::before { content: counter(step) ". "; }
    .steps__item a { color: var(--muted); }
    .steps__item.is-done { color: var(--text); }
    .steps__item.is-current { color: var(--text); font-weight: 600; }
}

/* Alvos grandes: o botao principal de cada ecra desenha-se para um polegar. */
.flow-body .button--block {
    padding: 0.85rem 1.15rem;
    font-size: 1rem;
    margin-top: 0.5rem;
}

/* Nada de scroll horizontal, em ecra nenhum. */
.flow-body img, .flow-body table, .flow-body pre { max-width: 100%; }

/* ------------------------------------------------- mensagens na web (W3) */
/*
 * Uma conversa nao e uma pagina de leitura nem um formulario: e as duas coisas
 * ao mesmo tempo, e a mais importante das duas depende de quem esta a olhar. Quem
 * abre uma conversa de ha tres dias precisa primeiro de saber DO QUE ELA E; quem
 * a tem aberta ha dois minutos precisa da caixa de escrita. E por isso que o
 * anuncio vem primeiro no DOM e a caixa vem no fim.
 *
 * Em ecra largo os dois trocam de sitio pela grelha, sem se mexer no HTML: o
 * anuncio passa para a direita e a conversa fica com a coluna larga. Nao ha
 * "versao movel" — ha uma coluna que se parte em duas quando ha espaco.
 */
.convo {
    display: grid;
    gap: 1.25rem;
    grid-template-columns: 1fr;
    align-items: start;
}
@media (min-width: 56rem) {
    .convo { grid-template-columns: minmax(0, 3fr) minmax(17rem, 1fr); gap: 2rem; }
    .convo__thread { grid-column: 1; grid-row: 1; }
    /* Fica a vista enquanto se rola o fio: e a razao de existir do painel. */
    .convo__aside { grid-column: 2; grid-row: 1; position: sticky; top: 1rem; }
}

.convo__head { margin-bottom: 1rem; }
.convo__head h1 { margin-bottom: 0.15rem; font-size: 1.375rem; }
.convo__head p { margin: 0; }

/* O anuncio no painel lateral: foto pequena, titulo e preco numa linha so. */
.convo-listing { display: flex; gap: 0.75rem; align-items: center; margin-bottom: 0.75rem; text-decoration: none; color: inherit; }
.convo-listing:hover .convo-listing__title { text-decoration: underline; }
.convo-listing__media {
    flex: 0 0 auto;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--surface-2);
    border: 1px solid var(--border);
}
.convo-listing__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.convo-listing__body { display: flex; flex-direction: column; min-width: 0; }
.convo-listing__title { font-weight: 600; }
.convo-listing__price { font-weight: 700; font-size: 1.125rem; }
.convo-listing__state { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0 0 0.5rem; }

/*
 * A linha de acontecimentos.
 *
 * Sem altura fixa e sem rolagem propria. Uma caixa com scroll interno parece o
 * cliente de chat que toda a gente conhece e comporta-se pior em todos os
 * telemoveis: rouba o gesto de rolar a pagina, esconde-se atras do teclado
 * virtual e quebra a procura do browser. A pagina rola, como todas as outras.
 */
.timeline { list-style: none; margin: 0 0 1rem; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }

.event { display: flex; }
.event.is-mine { justify-content: flex-end; }

.bubble {
    max-width: min(100%, 34rem);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0.65rem 0.85rem;
}
/*
 * O que e meu tem fundo proprio. E a unica pista de autoria que se le sem parar
 * para ler: num fio de vinte mensagens, procurar o nome em cada uma para saber
 * quem disse o que e trabalho que o desenho devia poupar. O canto quadrado do
 * lado de dentro faz o balao apontar para quem o escreveu.
 */
.event.is-mine .bubble { background: var(--surface-2); border-color: var(--border-strong); border-bottom-right-radius: var(--radius-sm); }
.event:not(.is-mine) .bubble { border-bottom-left-radius: var(--radius-sm); }

.bubble__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 0.6rem;
    margin: 0 0 0.25rem;
    font-size: 0.8125rem;
    color: var(--muted);
}
.bubble__author { font-weight: 600; color: var(--text); }
.bubble__body { margin: 0; overflow-wrap: anywhere; }

/*
 * A area de escrita: campo em cima, accoes por baixo e encostadas a direita.
 *
 * Os dois blocos sao separados de proposito. Hoje as accoes sao um botao; a
 * marcacao esta preparada para receber mais companhia sem o campo de texto ter
 * de mudar de sitio.
 */
.composer { display: flex; flex-direction: column; gap: 0.6rem; }
.composer__field { display: flex; flex-direction: column; }
/*
 * 16px no campo, como em todos os outros: abaixo disso o Safari do iOS aumenta a
 * pagina sozinho ao receber foco e a pessoa perde o sitio a meio de escrever.
 */
.composer textarea { font-size: 1rem; border-color: var(--border-strong); }
.composer__actions { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: flex-end; align-items: center; }

/* ------------------------------------------------------- caixa de entrada */
/*
 * Cada linha e uma so ligacao, do bordo esquerdo ao direito. Um alvo de toque do
 * tamanho da linha inteira nao falha; tres ligacoes pequenas na mesma linha
 * falham todas.
 */
.rows li.convo-row { padding: 0; display: block; }
.convo-row__link {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
    padding: 0.85rem 0.25rem;
    color: inherit;
    text-decoration: none;
    min-height: var(--tap);
}
.convo-row__link:hover { background: var(--surface-2); }
.convo-row__main { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; flex: 1; }
.convo-row__top { display: flex; align-items: center; gap: 0.5rem; }
.convo-row__top .row__title { margin: 0; }
.convo-row .row__meta { margin-left: 0; font-weight: 400; color: var(--muted); font-size: 0.875rem; }
.convo-row__last { color: var(--muted); font-size: 0.9375rem; overflow-wrap: anywhere; }
.convo-row__at { flex: 0 0 auto; color: var(--muted); font-size: 0.8125rem; white-space: nowrap; }
/* Por ler ganha peso e um risco na margem. So a negrito nao se ve de relance. */
.convo-row.is-unread .convo-row__link { border-left: 3px solid var(--accent); padding-left: 0.6rem; }
.convo-row.is-unread .row__title { font-weight: 700; }
.convo-row.is-unread .convo-row__last { color: var(--text); }

/* A mensagem guardada, mostrada na porta da conta. Ve-la e o que torna a
   promessa de que nada se perdeu credivel. */
.quoted {
    margin: 0.5rem 0 0.75rem;
    padding: 0.6rem 0.85rem;
    border-left: 3px solid var(--brand-orange);
    background: var(--surface-2);
    border-radius: var(--radius-sm);
    overflow-wrap: anywhere;
}

/* ------------------------------------------------------------------ *
 * Aviso de cookies
 *
 * Fica colado ao fundo da janela, mas nao tapa nada: `position: sticky`
 * com `bottom: 0` dentro do fluxo normal significa que a barra acompanha
 * o scroll e, ao chegar ao fim da pagina, assenta depois do rodape em vez
 * de ficar por cima dele. Nao ha overlay nem fundo escurecido, porque nao
 * ha aqui nenhuma decisao a tomar antes de ver a pagina.
 *
 * `--surface-2` e nao a cor da marca: isto e uma nota de rodape, e pinta-la
 * de laranja dava-lhe uma importancia que ela nao tem.
 * ------------------------------------------------------------------ */
.cookie-notice {
    position: sticky;
    bottom: 0;
    z-index: 20;
    background: var(--surface-2);
    border-top: 1px solid var(--border);
}

.cookie-notice__inner {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding-top: 0.7rem;
    padding-bottom: 0.7rem;
}

.cookie-notice__icon {
    flex: none;
    width: 1.25rem;
    height: 1.25rem;
    color: var(--muted);
}

.cookie-notice__text {
    flex: 1 1 auto;
    margin: 0;
    font-size: 0.875rem;
    line-height: 1.45;
    color: var(--muted);
}

/* O link herda o tamanho do texto a volta; so o peso o distingue. */
.cookie-notice__text a {
    color: var(--link);
    font-weight: 600;
    white-space: nowrap;
}

.cookie-notice__form {
    flex: none;
    margin: 0;
}

/*
 * Abaixo de 40rem o texto e o botao empilham. O botao fica alinhado a
 * esquerda e nao esticado a toda a largura: um botao de largura total
 * neste contexto le-se como accao principal da pagina, e nao e.
 */
@media (max-width: 40rem) {
    .cookie-notice__inner {
        flex-wrap: wrap;
    }

    .cookie-notice__icon {
        display: none;
    }

    .cookie-notice__text {
        flex: 1 1 100%;
    }
}

/*
 * O `button--quiet` normal escurece para `--surface-2` no hover, que e
 * exactamente o fundo desta barra — ficaria sem resposta nenhuma ao rato.
 * Aqui clareia em vez de escurecer.
 */
.cookie-notice .button--quiet {
    background: var(--surface);
}

.cookie-notice .button--quiet:hover {
    background: var(--bg);
    border-color: var(--muted);
}

/* ------------------------------------------------------------------ *
 * Filtros de caracteristica (facetas)
 *
 * Densos de proposito. Sao muitos — cor, espessura, dureza, tipo, horas,
 * corte — e com o espacamento de um campo normal empurravam o resto do
 * painel para fora do ecra. Aqui o texto e mais pequeno, as linhas mais
 * juntas, e a contagem alinhada a direita da a lista uma coluna por onde
 * o olho desce.
 * ------------------------------------------------------------------ */
.facets {
    margin: 0 0 1rem;
    padding: 0;
    border: 0;
}

.facets > legend {
    padding: 0;
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted);
}

.facet { margin-top: 0.85rem; }

.facet__group {
    margin: 0;
    padding: 0;
    border: 0;
}

.facet__title {
    display: block;
    padding: 0;
    margin-bottom: 0.3rem;
    font-size: 0.8125rem;
    font-weight: 600;
}

/*
 * A linha inteira e o alvo, e nao so o quadrado de 13 px. Num painel com
 * vinte opcoes, acertar no quadrado com o polegar e o que faz a diferenca
 * entre um filtro que se usa e um que se desiste de usar.
 */
.facet__option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3rem 0.25rem;
    margin: 0 -0.25rem;
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
    cursor: pointer;
}

.facet__option:hover { background: var(--surface-2); }

.facet__option input { margin: 0; flex: none; accent-color: var(--accent); }

.facet__option > span:nth-of-type(1) { flex: 1 1 auto; }

/*
 * A contagem e informacao de apoio: `--muted` e tabular para os numeros
 * ficarem alinhados uns por baixo dos outros em vez de dancarem com a
 * largura dos algarismos.
 */
.facet__count {
    flex: none;
    font-size: 0.8125rem;
    font-variant-numeric: tabular-nums;
    color: var(--muted);
}

.facet .field--inline { margin-bottom: 0; }

/* ------------------------------------------------------------------ *
 * Picker: lista de caixas com pesquisa, dentro de um `<details>`
 *
 * Usado pela marca, onde a lista pode ter dezenas de entradas. Fechado
 * ocupa uma linha; aberto tem altura maxima e faz scroll proprio, para
 * uma marca com 60 entradas nao empurrar o resto do painel para fora do
 * ecra.
 * ------------------------------------------------------------------ */
.picker {
    margin-bottom: 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
}

.picker__summary {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 0.75rem;
    font-size: 0.8125rem;
    font-weight: 600;
    cursor: pointer;
    min-height: var(--tap);
}

.picker__summary::-webkit-details-marker { display: none; }

/* A seta e nossa: a nativa muda de forma entre browsers e desalinha. */
.picker__summary::after {
    content: "";
    margin-left: auto;
    width: 0.45rem;
    height: 0.45rem;
    border-right: 2px solid var(--muted);
    border-bottom: 2px solid var(--muted);
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform 0.15s ease;
}

.picker[open] > .picker__summary::after { transform: rotate(-135deg) translate(-2px, -2px); }

/* Quantas marcas estao marcadas, visivel com o painel fechado. */
.picker__badge {
    min-width: 1.25rem;
    padding: 0 0.35rem;
    border-radius: 999px;
    background: var(--accent);
    color: var(--accent-text);
    font-size: 0.75rem;
    line-height: 1.25rem;
    text-align: center;
}

.picker__search {
    display: block;
    width: calc(100% - 1.5rem);
    margin: 0 0.75rem 0.4rem;
}

.picker__search[hidden] { display: none; }

.picker__list {
    max-height: 15rem;
    overflow-y: auto;
    padding: 0 0.5rem 0.5rem;
}

.picker__empty {
    margin: 0;
    padding: 0 0.75rem 0.75rem;
    font-size: 0.8125rem;
    color: var(--muted);
}

/* ------------------------------------------------------------------ *
 * Barra de ordenacao, por cima da lista
 *
 * Ordenar nao e filtrar: nao tira anuncios nenhuns da lista, so muda a
 * ordem. Por isso vive aqui, ao lado da contagem, e nao dentro do painel
 * de filtros.
 * ------------------------------------------------------------------ */
.results-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.sortbar {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-left: auto;
}

.sortbar label {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--muted);
    white-space: nowrap;
}

.sortbar select {
    width: auto;
    padding-top: 0.4rem;
    padding-bottom: 0.4rem;
    font-size: 0.875rem;
}

.sortbar button[hidden] { display: none; }

@media (max-width: 30rem) {
    .sortbar { margin-left: 0; width: 100%; }
    .sortbar select { flex: 1; }
}

/*
 * As entradas do selector de idioma passaram de `<a>` a `<button>` dentro de um
 * formulario — ver o comentario em lang-switch.blade.php. O desenho e o mesmo; o
 * que muda e o que o browser traz por omissao num botao e nao trazia numa
 * ligacao: fundo, moldura, tipo de letra e alinhamento ao centro.
 */
.lang-menu__list form { margin: 0; }

button.lang-menu__item {
    width: 100%;
    border: 0;
    border-radius: 0;
    background: none;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

/*
 * Linha da escolha ja feita: "Butterfly   Mudar".
 *
 * Substitui a lista depois de a marca estar escolhida. Manter a lista aberta por
 * cima dos modelos era manter uma pergunta ja respondida a ocupar o ecra por cima
 * da pergunta a seguir — e num telemovel isso e o ecra todo.
 */
.chosen-line {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    margin: 0 0 0.5rem;
}

.chosen-line strong { font-size: 1.0625rem; }

/*
 * A lista dos modelos de uma marca e mais alta do que a das marcas: uma marca
 * grande tem centenas de modelos, e 15rem obrigavam a rolar dentro de uma caixa
 * que ja esta dentro da pagina. Continua a ter tecto — sem ele, uma marca com 356
 * madeiras empurrava tudo o resto para fora do ecra.
 */
.picker__list--tall { max-height: 24rem; }

/* ------------------------------------------------ medir com uma moeda de 1 euro */

/*
 * A regua por moeda: a janela de trabalho, as marcas por cima da fotografia, e o
 * resultado com a margem.
 *
 * NASCE ESCONDIDA. O painel inteiro tem `hidden` no HTML e e o `sell-measure.js`
 * que o mostra, como o slider de precos. Sem o script, o que fica e uma frase a
 * dizer que as medidas se escrevem no passo das caracteristicas — que e verdade,
 * e e onde elas sempre estiveram.
 *
 * `touch-action: none` na janela nao e opcional: sem isso, arrastar um punho num
 * telemovel rola a pagina em vez de mover a marca, e a ferramenta fica impossivel
 * de usar exactamente no aparelho em que estas fotografias sao tiradas.
 */
.measure[hidden] { display: none; }

/*
 * E o `[hidden]` DE DENTRO da ferramenta, e faz falta: `.button` declara
 * `display: inline-flex`, e uma declaracao de `display` ganha sempre ao
 * `display: none` que o browser da a `[hidden]` na folha de omissao. Sem esta
 * linha, o botao de voltar a moeda aparecia no passo da moeda — um botao para ir
 * para onde ja se esta.
 */
.measure [hidden] { display: none; }

.measure__step {
    margin: 0.75rem 0 0.5rem;
    font-weight: 600;
}

.measure__stage {
    position: relative;
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    touch-action: none;
    cursor: grab;
    user-select: none;
}

.measure__stage:active { cursor: grabbing; }

.measure__canvas { position: absolute; top: 0; left: 0; }

.measure__canvas img {
    display: block;
    width: 100%;
    height: 100%;
    -webkit-user-drag: none;
}

.measure__canvas svg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

/*
 * `vector-effect: non-scaling-stroke` e o que mantem os tracos com a mesma
 * espessura seja qual for a ampliacao. Sem ele, a 10x um contorno de 2 px ficava
 * uma mancha de 20 e tapava precisamente a borda da moeda que se esta a tentar
 * acertar.
 */
.measure__ellipse,
.measure__line,
.measure__handle {
    vector-effect: non-scaling-stroke;
}

.measure__ellipse {
    fill: none;
    stroke: var(--brand-orange);
    stroke-width: 2px;
}

.measure__line {
    stroke: var(--brand-orange);
    stroke-width: 2px;
    stroke-linecap: round;
}

/*
 * Os punhos sao claros com contorno escuro e nao o contrario: por cima de uma
 * borracha preta sobre uma mesa escura — que e metade destas fotografias — um
 * punho escuro desaparece, e o que a pessoa esta a tentar fazer e precisamente
 * ver onde ele esta.
 */
.measure__handle {
    /*
     * BRANCO FIXO, e nao `var(--surface)`.
     *
     * Estes punhos vivem por cima de uma FOTOGRAFIA e nao por cima da pagina, e
     * uma fotografia nao muda de cor com o modo escuro. Com o token da superficie,
     * de noite os punhos ficavam quase pretos por cima de uma borracha preta sobre
     * uma mesa escura — que e metade destas fotografias — e a pessoa perdia de
     * vista exactamente aquilo que esta a tentar mover.
     */
    fill: #ffffff;
    fill-opacity: 0.92;
    stroke: var(--brand-orange);
    stroke-width: 2.5px;
    cursor: move;
}

.measure__handle:focus {
    outline: none;
    stroke: var(--accent);
    stroke-width: 4px;
}

.measure__controls {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0.75rem 0;
}

.measure__confirm { margin-top: 1rem; }

.measure-result {
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
}

.measure-result__label {
    margin: 0;
    color: var(--muted);
    font-size: 0.875rem;
}

/*
 * O valor grande e o intervalo LOGO POR BAIXO, ao tamanho do texto normal.
 *
 * A margem nao vai para letra pequena e nao vai para o rodape do painel: um
 * numero grande sozinho le-se como uma medicao, e esta nao e uma. O intervalo e
 * parte da resposta e nao uma nota de rodape sobre ela.
 */
.measure-result__value {
    margin: 0.15rem 0 0;
    font-size: 1.5rem;
    font-weight: 700;
}

.measure-result__range {
    margin: 0.15rem 0 0.75rem;
    font-weight: 600;
}

/* ------------------------------------------------------------------ *
 * A montra do heroi: anuncios a serio, a deslizar devagar.
 *
 * O heroi tinha metade da largura vazia num ecra de computador, e o
 * argumento mais forte desta pagina nao e uma frase — sao os anuncios
 * que existem.
 *
 * CSS E MAIS NADA. A lista esta escrita duas vezes no HTML e o carril
 * desliza de 0 a -50 %: a emenda cai exactamente onde a copia comeca,
 * portanto o ciclo nao tem costura nenhuma e nao ha um salto a cada
 * volta. Feito em JavaScript, isto seria uma peca que nao existe
 * enquanto o script nao chega — no elemento que mais pesa na primeira
 * pintura da pagina.
 *
 * SO A PARTIR DE 40 REM. Abaixo disso nao ha coluna nenhuma para uma
 * segunda coisa: num telemovel, o que interessa e o titulo, a linha de
 * apoio e os botoes, e os anuncios estao logo a seguir em grelha.
 * ------------------------------------------------------------------ */
.showcase { display: none; }

@media (min-width: 62rem) {
    /*
     * O `.wrap` do heroi passa a duas colunas. A da direita e fixa em
     * 20rem: uma coluna que encolhe com a janela acaba por mostrar
     * cartoes de miniatura, e uma miniatura de uma borracha vermelha e
     * um circulo vermelho.
     */
    /*
     * A MONTRA ESTA FORA DO FLUXO, e essa e a decisao inteira.
     *
     * Tentei-a primeiro como coluna de uma grelha e depois como item flexivel
     * esticado. As duas falharam pela mesma razao: um elemento no fluxo participa
     * no calculo da altura, e o carril tem o DOBRO do conteudo — o heroi passava
     * de 200 px para 685 e depois para 1400, e os anuncios que isto existe para
     * mostrar caiam abaixo da dobra. O oposto do objectivo.
     *
     * Absoluta, a montra nao tem voto nenhum: a altura do heroi continua a ser a
     * do texto, exactamente como era antes de ela existir, e ela ocupa o espaco
     * que ja estava vazio a direita.
     */
    .hero--showcase .wrap { position: relative; }

    /* O espaco reservado a direita, para o texto nao passar por baixo dela. */
    .hero--showcase .hero__text { max-width: calc(100% - 23rem); }

    .showcase {
        display: block;
        /*
         * A MONTRA NUNCA DEFINE A ALTURA DO HEROI.
         *
         * `flex: none` na largura, e a altura vem do `align-items: stretch` do
         * pai — ou seja, e exactamente a altura do TEXTO ao lado. O heroi fica com
         * a altura que sempre teve, e o que muda e so o que ha no espaco que
         * estava vazio.
         *
         * O `min-height: 0` e o que faz o `overflow: hidden` funcionar dentro de
         * um item flexivel esticado: sem ele, o conteudo empurra e a caixa cresce.
         */
        position: absolute;
        top: 0;
        bottom: 0;
        /* 1rem e o padding do `.wrap`: alinha com a margem do resto da pagina. */
        right: 1rem;
        width: 20rem;
        overflow: hidden;

        /*
         * Esbatido nas duas pontas, em vez de um corte seco. O corte
         * parece um erro de layout; o esbatido diz "continua".
         */
        -webkit-mask-image: linear-gradient(to bottom, transparent, #000 12%, #000 88%, transparent);
        mask-image: linear-gradient(to bottom, transparent, #000 12%, #000 88%, transparent);
    }

    .showcase__track {
        display: flex;
        flex-direction: column;
        gap: 0.75rem;
        animation: showcase-drift 48s linear infinite;
    }

    /*
     * 48 segundos para dar a volta a oito cartoes: seis segundos por
     * cartao. Devagar que chegue para se ler um preco de relance e para
     * nao competir com o botao ao lado, que e o que a pagina quer que a
     * pessoa carregue.
     */
    @keyframes showcase-drift {
        from { transform: translateY(0); }
        to { transform: translateY(-50%); }
    }

    /* Parar ao passar o rato: se alguem se interessou, nao se foge com a coisa. */
    .showcase:hover .showcase__track { animation-play-state: paused; }

    /*
     * CARTOES BRANCOS SOBRE O MARINHO, e nao um branco a 7 % que so se ve de
     * perto. Sao a mesma coisa que a grelha logo abaixo mostra — um cartao de
     * anuncio — e valem como prova precisamente por se reconhecerem como tal.
     * Sobre o marinho da marca, o contraste tambem faz o trabalho que a caixa
     * quase transparente nao fazia: a fotografia recorta-se, o preco le-se.
     */
    .showcase__card {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        padding: 0.5rem;
        border-radius: var(--radius-sm);
        background: var(--surface);
        color: var(--text);
        text-decoration: none;
        flex: none;
    }

    /*
     * O hover levanta em vez de escurecer: sobre branco, escurecer le-se como
     * desactivado. Uma sombra curta diz "isto e uma ligacao".
     */
    .showcase__card:hover {
        box-shadow: 0 2px 10px rgb(0 0 0 / 25%);
    }

    .showcase__card img {
        width: 3.5rem;
        height: 3.5rem;
        object-fit: cover;
        border-radius: var(--radius-sm);
        flex: none;
        background: var(--surface-2);
    }

    .showcase__meta { min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }

    .showcase__name {
        font-size: 0.875rem;
        line-height: 1.3;
        /* Duas linhas e depois corta: os titulos variam de "Tenergy 05" a
           "Stiga Legacy Carbon - Chinese Penhold", e uma coluna com cartoes de
           alturas diferentes le-se pior do que uma com titulos cortados. */
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }

    .showcase__price { font-size: 0.9375rem; font-weight: 700; color: var(--text); }
}

/*
 * QUEM PEDIU MENOS MOVIMENTO NAO TEM MOVIMENTO NENHUM.
 *
 * A lista fica quieta e continua a ler-se por inteiro — nao se perde
 * informacao nenhuma, so o deslizar. Enjoo nao e um pormenor de gosto, e
 * um heroi que se mexe e das piores coisas para quem o tem.
 */
@media (prefers-reduced-motion: reduce) {
    .showcase__track { animation: none; }
}

/* ------------------------------------------------------------------ *
 * Combobox: um `<select>` transformado numa caixa onde se escreve.
 *
 * A partir do terceiro caracter mostra so as correspondencias. Antes
 * disso nao mostra lista nenhuma — com duas letras, "bu" corresponde a
 * meia lista, e uma lista de meia lista nao e ajuda.
 *
 * O `<select>` continua no HTML, escondido, a levar o valor. Estes
 * estilos so existem quando o JavaScript correu; sem ele o que se ve e
 * um `<select>` normal com os estilos de campo de sempre.
 * ------------------------------------------------------------------ */
.combobox { position: relative; }

.combobox__input { width: 100%; }

.combobox__list {
    position: absolute;
    z-index: 30;
    top: calc(100% + 2px);
    left: 0;
    right: 0;
    margin: 0;
    padding: 0.25rem;
    list-style: none;
    max-height: 16rem;
    overflow-y: auto;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    box-shadow: 0 6px 20px rgb(0 0 0 / 12%);
}

.combobox__list[hidden] { display: none; }

.combobox__option {
    padding: 0.5rem 0.6rem;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: 0.9375rem;
}

/*
 * `aria-selected` e nao `:hover` sozinho: quem percorre com as setas tem
 * de ver onde esta, e o rato nunca lhe tocou. Os dois pintam igual, de
 * proposito — e o mesmo estado visto de duas maneiras.
 */
.combobox__option:hover,
.combobox__option[aria-selected="true"] {
    background: var(--accent);
    color: var(--accent-text);
}

.combobox__empty {
    padding: 0.5rem 0.6rem;
    font-size: 0.875rem;
    color: var(--muted);
}

/* ------------------------------------------------------------------ *
 * Sugestoes da caixa de procura da montra.
 *
 * Ao contrario do combobox, estas vem do SERVIDOR: o que interessa aqui
 * nao e o catalogo (4 586 modelos nao cabem na pagina) mas o que TEM
 * anuncios. Por isso cada linha traz a contagem — e o que impede a lista
 * de sugerir caminhos para paginas vazias.
 * ------------------------------------------------------------------ */
/*
 * O embrulho do campo — e o que ancora a lista de sugestoes em `position:
 * absolute`, e o que o campo perdeu ao deixar de ser filho directo do flex.
 *
 * `display: flex` NAO E DECORATIVO: como filho directo de `.searchbar`, o input
 * esticava sozinho ate a altura do botao ao lado (`align-items: stretch`, que e o
 * que um flex faz por omissao). Dentro de um embrulho que nao e flex, ele voltava
 * a altura do texto — mais fino do que o botao, e visivelmente errado. Com o
 * embrulho tambem em flex, a altura volta a ser distribuida ate ao input.
 */
.searchbar__field {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
}

.suggestions {
    position: absolute;
    z-index: 30;
    top: calc(100% + 2px);
    left: 0;
    right: 0;
    margin: 0;
    padding: 0.25rem;
    list-style: none;
    max-height: 20rem;
    overflow-y: auto;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    box-shadow: 0 6px 20px rgb(0 0 0 / 12%);
    text-align: left;
}

.suggestions[hidden] { display: none; }

.suggestions a {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.6rem;
    border-radius: var(--radius-sm);
    color: var(--text);
    text-decoration: none;
}

/*
 * O mesmo estado pintado de duas maneiras: o rato e as setas. Quem
 * percorre com o teclado tem de ver onde esta, e o rato nunca lhe tocou.
 */
.suggestions a:hover,
.suggestions [aria-selected="true"] a {
    background: var(--accent);
    color: var(--accent-text);
}

.suggestion__name { flex: 1 1 auto; min-width: 0; font-size: 0.9375rem; }

/* A marca a cheio, o modelo a seguir: le-se a hierarquia de relance. */
.suggestion__name strong { font-weight: 700; }

.suggestion__count {
    flex: none;
    font-size: 0.8125rem;
    font-variant-numeric: tabular-nums;
    color: var(--muted);
}

.suggestions a:hover .suggestion__count,
.suggestions [aria-selected="true"] a .suggestion__count { color: var(--accent-text); }

.suggestions__empty {
    padding: 0.5rem 0.6rem;
    font-size: 0.875rem;
    color: var(--muted);
}
