/*
 * Tema do projeto — Quadras Atleta do Vôlei
 *
 * Sobrescreve o Bootstrap 5.3 com as cores e a tipografia do Figma.
 *
 * ┌──────────────────────────────────────────────────────────────────────┐
 * │ O primeiro bloco é AUTORAL DO DESIGN e foi copiado literalmente de   │
 * │ docs/design_system/Design System.html, que traz a instrução          │
 * │ "cole em resources/css/theme.css".                                   │
 * │                                                                       │
 * │ NÃO EDITE aquele bloco à mão. Quando o design mudar, extraia o        │
 * │ trecho entre os marcadores "TEMA DO PROJETO" e "fim do tema" do HTML  │
 * │ novo e substitua o bloco inteiro. Ajustes nossos vão DEPOIS dele.     │
 * └──────────────────────────────────────────────────────────────────────┘
 */

/* ===== TEMA DO PROJETO — cole em resources/css/theme.css ===== */
:root {
    --bs-primary: #33488c;
    --bs-primary-rgb: 51, 72, 140;
    --bs-secondary: #de9418;
    --bs-secondary-rgb: 222, 148, 24;
    --bs-success: #3b8646;
    --bs-success-rgb: 59, 134, 70;
    --bs-danger: #ba1a1a;
    --bs-danger-rgb: 186, 26, 26;
    --bs-body-color: #121212;
    --bs-body-bg: #f7f7f7;
    --bs-border-color: #d1d1d1;
    --bs-border-radius: 0.5rem;
    --bs-link-color: #33488c;
    --bs-link-color-rgb: 51, 72, 140;
    --bs-link-hover-color: #2c3e80;
    font-family: 'Inter', system-ui, sans-serif;
}

body {
    font-family: 'Inter', system-ui, sans-serif;
}

.btn {
    --bs-btn-border-radius: 5px;
    font-weight: 600;
}

.btn-primary {
    --bs-btn-bg: #33488c;
    --bs-btn-border-color: #33488c;
    --bs-btn-hover-bg: #2c3e80;
    --bs-btn-hover-border-color: #2c3e80;
    --bs-btn-active-bg: #212d69;
    --bs-btn-active-border-color: #212d69;
    --bs-btn-disabled-bg: #a0accf;
    --bs-btn-disabled-border-color: #a0accf;
}

.btn-outline-primary {
    --bs-btn-color: #33488c;
    --bs-btn-border-color: #33488c;
    --bs-btn-hover-bg: #33488c;
    --bs-btn-hover-border-color: #33488c;
    --bs-btn-active-bg: #212d69;
    --bs-btn-active-border-color: #212d69;
}

.btn-secondary {
    --bs-btn-bg: #de9418;
    --bs-btn-border-color: #de9418;
    --bs-btn-hover-bg: #dd8414;
    --bs-btn-hover-border-color: #dd8414;
    --bs-btn-active-bg: #da690e;
    --bs-btn-active-border-color: #da690e;
    --bs-btn-color: #121212;
    --bs-btn-hover-color: #121212;
    --bs-btn-active-color: #121212;
    --bs-btn-disabled-color: #121212;
    --bs-btn-disabled-bg: #edd682;
    --bs-btn-disabled-border-color: #edd682;
}

.btn-outline-secondary {
    --bs-btn-color: #a2650a;
    --bs-btn-border-color: #de9418;
    --bs-btn-hover-bg: #de9418;
    --bs-btn-hover-border-color: #de9418;
    --bs-btn-hover-color: #121212;
    --bs-btn-active-bg: #de9418;
    --bs-btn-active-border-color: #de9418;
    --bs-btn-active-color: #121212;
}

.btn-success {
    --bs-btn-bg: #3b8646;
    --bs-btn-border-color: #3b8646;
    --bs-btn-hover-bg: #33753c;
    --bs-btn-hover-border-color: #33753c;
    --bs-btn-active-bg: #24562b;
    --bs-btn-active-border-color: #24562b;
}

.btn-danger {
    --bs-btn-bg: #ba1a1a;
    --bs-btn-border-color: #ba1a1a;
    --bs-btn-hover-bg: #b11919;
    --bs-btn-hover-border-color: #b11919;
    --bs-btn-active-bg: #a31919;
    --bs-btn-active-border-color: #a31919;
}

.btn-link {
    --bs-btn-color: #33488c;
    --bs-btn-hover-color: #2c3e80;
    text-decoration: none;
}

.text-primary {
    color: #33488c !important;
}

.bg-primary {
    background-color: #33488c !important;
}

.text-secondary {
    color: #a2650a !important;
}

.form-control,
.form-select {
    --bs-border-radius: 0.5rem;
    border-color: #d1d1d1;
    min-height: 48px;
}

.form-control::placeholder {
    color: #8a8a8a;
}

.form-control:focus,
.form-select:focus {
    border-color: #424242;
    box-shadow: 0 0 0 0.2rem rgba(51, 72, 140, 0.15);
}

.form-control.is-valid,
.was-validated .form-control:valid {
    border-color: #3b8646;
}

.form-control.is-invalid,
.was-validated .form-control:invalid {
    border-color: #ba1a1a;
}

.valid-feedback {
    color: #3b8646;
}

.invalid-feedback {
    color: #ba1a1a;
}

.form-check-input:checked {
    background-color: #33488c;
    border-color: #33488c;
}

.form-check-input:focus {
    border-color: #7b8bbc;
    box-shadow: 0 0 0 0.2rem rgba(51, 72, 140, 0.15);
}

.form-switch .form-check-input:checked {
    background-color: #3b8646;
    border-color: #3b8646;
}

.input-group-text {
    background: #f7f7f7;
    border-color: #d1d1d1;
    color: #5d5d5d;
}

.badge {
    font-weight: 600;
}
/* ===== fim do tema ===== */

/*
 * ──────────────────────────────────────────────────────────────────────────
 * DAQUI PARA BAIXO: estrutura do painel.
 *
 * O bloco acima define CORES e TIPOGRAFIA; ele não descreve o arranjo da
 * tela. O que segue implementa a estrutura de docs/design_system/dashboard-01.png
 * — sidebar fixa, header e cards — usando as mesmas variáveis, para que uma
 * troca de paleta lá em cima se propague sozinha para cá.
 * ──────────────────────────────────────────────────────────────────────────
 */

:root {
    --app-sidebar-width: 16rem;
    --app-header-height: 4.375rem;

    /* Tom escuro da marca, extraído do SVG do design system. */
    --app-brand-dark: #212d69;

    --app-surface: #ffffff;
    --app-muted: #5d5d5d;
    --app-hover: rgba(51, 72, 140, 0.06);
}

/* ── Estrutura ─────────────────────────────────────────────────────────── */

.app-shell {
    min-height: 100vh;
}

.app-sidebar {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    width: var(--app-sidebar-width);
    background: var(--app-surface);
    border-inline-end: 1px solid var(--bs-border-color);
    display: flex;
    flex-direction: column;
    z-index: 1040;

    /* Fora do desktop a sidebar sai da tela e volta pelo botão do header.
       `transform` em vez de `display` para a transição ser suave e o
       conteúdo continuar existindo para leitores de tela. */
    transform: translateX(-100%);
    transition: transform 0.2s ease-in-out;
}

.app-sidebar.is-open {
    transform: translateX(0);
}

.app-main {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.app-header {
    position: sticky;
    top: 0;
    height: var(--app-header-height);
    background: var(--app-surface);
    border-bottom: 1px solid var(--bs-border-color);
    display: flex;
    align-items: center;
    gap: 1rem;
    padding-inline: 1rem;
    z-index: 1030;
}

.app-content {
    flex: 1 1 auto;
    padding: 1.5rem 1rem 3rem;
}

@media (min-width: 992px) {
    .app-sidebar {
        transform: translateX(0);
    }

    .app-main {
        margin-inline-start: var(--app-sidebar-width);
    }

    .app-header,
    .app-content {
        padding-inline: 2rem;
    }
}

/* Tela do calendário: o card ocupa toda a altura disponível, sem área vazia
   embaixo. Escopado por `:has(#calendar)` para valer SÓ nesta tela — as demais
   seguem com altura pelo conteúdo.

   A cadeia de alturas: `.app-main` já tem 100vh e `.app-content` cresce dentro
   dela; aqui transformamos o conteúdo em coluna flex, o cabeçalho fica do seu
   tamanho e o card cresce para preencher o resto. `min-height: 0` nos filhos é
   o que permite ao flex encolher/crescer de verdade dentro do container. O
   FullCalendar recebe height '100%' no JS e preenche o corpo do card. */
.app-content:has(#calendar) {
    display: flex;
    flex-direction: column;
}

.app-content:has(#calendar) > .card {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 32rem; /* piso: em telas muito baixas, não colapsa abaixo do usável */
}

/* A altura precisa chegar ATÉ o #calendar. Cada elo é flex-column com
   `min-height: 0` (senão o conteúdo impõe um mínimo e o flex não encolhe), e o
   #calendar cresce para ocupar o corpo do card. Só então o height '100%' do
   FullCalendar tem um pai com altura real para preencher — sem isso ele mede
   um elemento de altura automática e colapsa nos cabeçalhos. */
.app-content:has(#calendar) > .card > .card-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.app-content:has(#calendar) > .card > .card-body > #calendar {
    flex: 1 1 auto;
    min-height: 0;
}

/* Ações do modal de detalhe da reserva (editar, excluir, fechar): todas em
   cinza claro e pequenas, como no modelo. Sem isto, `text-secondary` sairia
   âmbar e `text-danger` vermelho por causa da paleta do tema. */
.reservation-view-actions .btn {
    color: var(--bs-tertiary-color);
    font-size: 0.95rem;
    line-height: 1;
}

.reservation-view-actions .btn:hover {
    color: var(--bs-secondary-color);
}

/* Escurece o conteúdo enquanto a sidebar está aberta no celular. Sem isto,
   dá para clicar em coisas atrás do menu sem perceber. */
.app-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(18, 18, 18, 0.4);
    z-index: 1035;
}

@media (min-width: 992px) {
    .app-backdrop {
        display: none;
    }
}

/* ── Marca ─────────────────────────────────────────────────────────────── */

.app-brand {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    height: var(--app-header-height);
    padding-inline: 1.25rem;
    border-bottom: 1px solid var(--bs-border-color);
    text-decoration: none;
    color: var(--app-brand-dark);
    flex: 0 0 auto;
}

.app-brand__mark {
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 0.5625rem;
    background: var(--bs-secondary);
    color: var(--app-brand-dark);
    flex: 0 0 auto;
}

/* A marca deixou de ser o monograma "AV" e passou a ser a bola do design
   system. O SVG usa `currentColor`, então a cor vem daqui. */
.app-brand__mark svg {
    width: 1.375rem;
    height: 1.375rem;
}

.app-brand__name {
    font-weight: 700;
    font-size: 0.9375rem;
    line-height: 1.15;
    letter-spacing: -0.01em;
}

.app-brand__name small {
    display: block;
    font-weight: 500;
    font-size: 0.6875rem;
    color: var(--app-muted);
}

/* ── Navegação da sidebar ──────────────────────────────────────────────── */

.app-nav {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 1rem 0.75rem 1.5rem;
}

/* O cabeçalho é um <button>: recolhe o grupo. Os resets abaixo existem porque
   o botão precisa parecer o rótulo de seção que sempre foi. */
.app-nav__heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    width: 100%;
    background: none;
    border: 0;
    text-align: left;
    cursor: pointer;
    padding: 1.25rem 0.75rem 0.5rem;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--app-muted);
}

.app-nav__heading:hover {
    color: var(--bs-body-color);
}

.app-nav__group:first-child .app-nav__heading {
    padding-top: 0.25rem;
}

/* A seta gira em vez de trocar de ícone: um só nó no HTML, e o estado fica
   legível mesmo no meio da transição. Aberto aponta para cima ("clique para
   fechar"), fechado aponta para baixo. */
.app-nav__chevron {
    flex: 0 0 auto;
    font-size: 0.75rem;
    transform: rotate(180deg);
    transition: transform 0.15s ease-in-out;
}

.app-nav__group.is-collapsed .app-nav__chevron {
    transform: rotate(0deg);
}

.app-nav__group.is-collapsed .app-nav__group-items {
    display: none;
}

.app-nav__link {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.625rem 0.75rem;
    border-radius: var(--bs-border-radius);
    color: var(--bs-body-color);
    font-size: 0.875rem;
    font-weight: 500;
    text-decoration: none;
}

.app-nav__link:hover {
    background: var(--app-hover);
    color: var(--bs-primary);
}

.app-nav__link.is-active {
    background: var(--app-hover);
    color: var(--bs-primary);
    font-weight: 600;
}

.app-nav__link svg {
    flex: 0 0 auto;
    opacity: 0.75;
}

.app-nav__link.is-active svg {
    opacity: 1;
}

/* ── Cabeçalho de página ───────────────────────────────────────────────── */

.page-head {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: 1.5rem;
}

.page-head__title {
    font-size: 1.375rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    margin: 0;
}

.page-head__subtitle {
    margin: 0.25rem 0 0;
    color: var(--app-muted);
    font-size: 0.875rem;
}

/* CABEÇALHO COM ABAS NO LUGAR DO TÍTULO (tela de Comandas).
 *
 * `flex-end` alinha o botão de ação pela BASE das abas — com o `flex-start`
 * padrão ele subiria para o topo e ficaria pairando acima da linha das abas.
 *
 * O slot cresce (`flex: 1 1 auto`) para que a linha que fecha as abas atravesse
 * a página em vez de morrer logo depois da palavra "Histórico": é ela que separa
 * o cabeçalho do conteúdo, e uma risca curta pareceria um sublinhado solto. */
.page-head--tabs {
    align-items: flex-end;
}

.page-head__tabs-slot {
    flex: 1 1 auto;
    min-width: 0;
}

/* TECLA DE ATALHO IMPRESSA AO LADO DO RÓTULO ("Abrir Comanda F2").
 *
 * Quem opera o balcão o dia inteiro não vai descobrir o atalho por acaso: a
 * tecla precisa estar VISÍVEL no próprio controle que ela aciona. O `title` que
 * já existe atende quem passa o mouse, mas o operador de teclado não passa o
 * mouse — é justamente ele o público do atalho.
 *
 * `<kbd>` e não `<span>`: é o elemento que significa "entrada de teclado", e o
 * leitor de tela o anuncia como tal em vez de ler "F2" como se fosse parte do
 * nome do botão.
 *
 * PINTA-SE COM `currentColor`. A mesma marca aparece sobre o azul do botão
 * primário e sobre o cinza da aba; fixar cor exigiria uma variante por contexto
 * e uma terceira no dia em que aparecer um botão de outra cor. Herdando a cor do
 * texto, a borda e o rótulo nunca discordam. O `opacity` é o que a rebaixa a
 * legenda — ela informa, não compete com o nome da ação.
 *
 * Bootstrap estiliza `kbd` com fundo escuro e texto branco: sobre o botão azul
 * isso viraria um retângulo preto. Daí o `background: transparent` explícito. */
.shortcut-hint {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0 0.3rem;
    border: 1px solid currentColor;
    border-radius: 0.25rem;
    background: transparent;
    color: inherit;
    font-family: inherit;
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1.4;
    vertical-align: middle;
    opacity: 0.65;
}

/* No campo de busca a tecla mora no fecho do input-group, encostada no campo.
 * Sem borda própria: a do `input-group-text` já a delimita, e duas molduras
 * concêntricas pareceriam um defeito de renderização. */
.input-group-text .shortcut-hint {
    margin-left: 0;
    border-color: transparent;
    opacity: 0.75;
}

/* Ação principal da página como ÍCONE, não como botão com rótulo.
 *
 * Usada quando a ação é óbvia pelo contexto e o rótulo só ocuparia espaço
 * ("Novo lançamento" na tela de Lançamentos). O `aria-label` no elemento é
 * obrigatório: sem texto visível, é ele quem nomeia o botão para o leitor de
 * tela.
 *
 * O alvo de clique tem 2.5rem — o mínimo confortável no toque. O ícone dentro
 * pode ser menor, mas a área não. */
.page-head__add {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--bs-danger);
    font-size: 1.75rem;
    line-height: 1;
    transition: background-color 0.15s ease-in-out;
}

.page-head__add:hover,
.page-head__add:focus-visible {
    background-color: rgba(var(--bs-danger-rgb), 0.1);
    color: var(--bs-danger);
}

/* O caret padrão do Bootstrap sobraria ao lado do ícone e desalinharia o
 * círculo. O menu já se anuncia por `aria-expanded`. */
.page-head__add.dropdown-toggle::after {
    display: none;
}

/* ── Parcelas do agendamento recorrente ────────────────────────────────── */

/* A quebra do pacote período a período, no passo de cobrança da reserva.
 *
 * Grade de quatro colunas — período, quantidade, valor, vencimento — para os
 * números alinharem na vertical: é assim que se confere uma lista de valores de
 * relance. No celular a coluna do meio some, porque a quantidade é a informação
 * mais dispensável das quatro. */
/* A ÚLTIMA COLUNA TEM LARGURA FIXA, e não `auto`, por dois motivos:
 *
 *  1. Ela guarda um campo de data numa tela (Despesas) e a mesma data em TEXTO
 *     na outra (Resumo). Com `auto`, cada grade se dimensionava pelo próprio
 *     conteúdo e as duas telas mostravam a mesma tabela com colunas de larguras
 *     diferentes.
 *  2. Dentro de uma grade só, o input e o texto tinham larguras intrínsecas
 *     distintas, e a coluna dançava conforme a linha.
 */
.reservation-parcels {
    display: grid;
    grid-template-columns: auto auto 1fr 9.5rem;
    gap: 0.375rem 0.75rem;
    align-items: center;
    font-size: 0.875rem;
}

.reservation-parcels:empty {
    display: none;
}

.reservation-parcels__value {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* A RÉGUA ATRAVESSA A LINHA INTEIRA, em vez de ser uma borda por célula.
 *
 * Com borda em cada célula, o `column-gap` partia o traço em quatro pedaços de
 * tamanhos diferentes — que é o que fazia a tabela parecer desalinhada mesmo
 * com as colunas certas. Um elemento só, ocupando da primeira à última coluna,
 * dá um traço contínuo. */
.reservation-parcels__rule {
    grid-column: 1 / -1;
    border-top: 1px solid var(--bs-border-color);
}

.reservation-parcels__total {
    font-weight: 600;
}

/* O campo ocupa a coluna inteira: é o que faz a data digitada cair exatamente
 * sob a data em texto do resumo. */
.reservation-parcels input[type='date'] {
    width: 100%;
}

@media (max-width: 575.98px) {
    .reservation-parcels {
        grid-template-columns: auto 1fr 9.5rem;
    }

    .reservation-parcels__count {
        display: none;
    }
}

/* ── Linha de Lançamentos ──────────────────────────────────────────────── */

/* AS COLUNAS DA DIREITA TÊM LARGURA FIXA.
 *
 * Antes cada uma se dimensionava pelo próprio conteúdo: o nome do banco variava
 * ("Itaú" contra "Banco do Brasil"), a conta sumia inteira quando o lançamento
 * não tinha nenhuma, e a transferência mostra DUAS contas no lugar de uma. O
 * resultado é que valor e polegar dançavam de linha em linha, e a lista não
 * podia ser lida na vertical — que é justamente como se confere dinheiro.
 *
 * A largura fixa resolve na raiz: a coluna existe em TODA linha, mesmo vazia. */
.cashflow-row__bank {
    flex: 0 0 11rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
    color: var(--bs-secondary-color);
}

/* O nome do banco não pode empurrar a coluna: encolhe com reticências. */
.cashflow-row__bank-name {
    font-size: 0.875rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cashflow-row__amount {
    flex: 0 0 8.5rem;
    text-align: right;
    white-space: nowrap;
    font-weight: 600;
    /* Dígitos de mesma largura: sem isto "R$ 1.500,00" e "R$ 100,00" desalinham
     * as casas mesmo dentro de uma coluna de largura fixa. */
    font-variant-numeric: tabular-nums;
}

.cashflow-row__thumb {
    flex: 0 0 1.5rem;
    text-align: center;
}

@media (max-width: 767.98px) {
    /* No celular a coluna do banco sai inteira — é a informação mais
     * dispensável das três, e o valor precisa do espaço. */
    .cashflow-row__bank {
        display: none;
    }

    .cashflow-row__amount {
        flex: 0 0 auto;
    }
}

/* ── Ações que abrem ao passar o mouse ─────────────────────────────────── */

/* O menu de ver/editar/apagar que aparece sobre a reserva no calendário e sobre
 * a linha das listagens. UMA classe para os dois, porque é a mesma coisa: um
 * menu ancorado no item apontado.
 *
 * `position: fixed` porque ele é posicionado a partir do retângulo do item na
 * TELA. Dentro da grade do calendário ou de uma tabela rolável, o `overflow` o
 * cortaria; com `absolute` seria preciso somar a rolagem da página a cada
 * abertura.
 *
 * O z-index passa por cima da grade do FullCalendar, mas fica ABAIXO dos modais
 * do Bootstrap (1055): o menu some quando um modal abre, e não pode flutuar
 * sobre ele nesse intervalo. */
.hover-actions {
    position: fixed;
    z-index: 1050;
    min-width: 10rem;
    padding: 0.25rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.5rem;
    background: var(--bs-body-bg);
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.12);
}

/* SEM MOUSE o menu não flutua: vira uma barra na própria linha. Em tela de
 * toque não existe passar o mouse, e esconder as ações atrás de um gesto que
 * não existe as tornaria inalcançáveis. */
.hover-actions--static {
    position: static;
    display: flex;
    justify-content: flex-end;
    gap: 0.25rem;
    min-width: 0;
    padding: 0;
    border: 0;
    background: transparent;
    box-shadow: none;
}

.hover-actions__item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.375rem 0.625rem;
    border: 0;
    border-radius: 0.375rem;
    background: transparent;
    color: var(--bs-body-color);
    font-size: 0.875rem;
    text-align: left;
    text-decoration: none;
    white-space: nowrap;
}

.hover-actions--static .hover-actions__item {
    width: auto;
    border: 1px solid var(--bs-border-color);
}

.hover-actions__item:hover,
.hover-actions__item:focus-visible {
    background: var(--bs-secondary-bg);
    color: var(--bs-body-color);
}

.hover-actions__item--danger,
.hover-actions__item--danger:hover,
.hover-actions__item--danger:focus-visible {
    color: var(--bs-danger);
}

/* ── Navegação de período ──────────────────────────────────────────────── */

/* O recorte de tempo de Lançamentos: ‹ Julho de 2026 ›.
 *
 * Centralizado e sozinho na linha, acima da barra de filtros — é o que todos
 * os filtros pressupõem, e dividir a linha com eles o fazia parecer só mais um
 * botão. Ver o comentário na view. */
.period-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.period-nav__arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    color: var(--app-muted);
    text-decoration: none;
    transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out;
}

.period-nav__arrow:hover,
.period-nav__arrow:focus-visible {
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
}

.period-nav__label {
    border: 0;
    background: transparent;
    padding: 0.25rem 0.5rem;
    border-radius: var(--bs-border-radius);
    font-weight: 600;
    color: var(--bs-body-color);
}

.period-nav__label:hover,
.period-nav__label:focus-visible {
    background-color: var(--bs-tertiary-bg);
}

/* O caret sobraria: o rótulo já é claramente clicável pela posição e pelo
 * hover, e o menu se anuncia por `aria-expanded`. */
.period-nav__label.dropdown-toggle::after {
    display: none;
}

.period-nav__menu {
    min-width: 12rem;
    padding: 0.5rem;
    text-align: center;
}

/* Os dois passos do menu ocupam o MESMO lugar — só um aparece por vez. A troca
 * é feita por classe no JavaScript; sem ele, o passo 1 fica visível e os
 * atalhos, que são links, continuam funcionando. */
.period-nav__step.is-hidden {
    display: none;
}

/* ── Cards ─────────────────────────────────────────────────────────────── */

.card {
    --bs-card-bg: var(--app-surface);
    --bs-card-border-color: var(--bs-border-color);
    --bs-card-border-radius: 0.75rem;
    --bs-card-inner-border-radius: 0.75rem;
    --bs-card-spacer-x: 1.25rem;
    --bs-card-spacer-y: 1.25rem;
}

.card-header {
    background: transparent;
    border-bottom-color: var(--bs-border-color);
    font-weight: 600;
    padding-block: 1rem;
}

/* Card de indicador: ícone em quadrado suave, número grande, rótulo abaixo. */
.stat-card__icon {
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 0.625rem;
    background: rgba(var(--bs-primary-rgb), 0.1);
    color: var(--bs-primary);
    margin-bottom: 1.5rem;
}

.stat-card__value {
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.02em;
}

.stat-card__label {
    color: var(--app-muted);
    font-size: 0.875rem;
    margin-top: 0.375rem;
}

/* ── Tabelas ───────────────────────────────────────────────────────────── */

.table {
    --bs-table-border-color: var(--bs-border-color);
    margin-bottom: 0;
}

.table > thead th {
    background: transparent;
    color: var(--app-muted);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    padding-block: 0.875rem;
}

.table > tbody td {
    padding-block: 0.875rem;
    vertical-align: middle;
}

/* ── Header: ações à direita ───────────────────────────────────────────── */

.app-header__action {
    display: grid;
    place-items: center;
    width: 2.375rem;
    height: 2.375rem;
    border: 0;
    border-radius: var(--bs-border-radius);
    background: transparent;
    color: var(--app-muted);
}

.app-header__action:hover {
    background: var(--app-hover);
    color: var(--bs-primary);
}

.app-avatar {
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    background: var(--bs-primary);
    color: #fff;
    font-size: 0.8125rem;
    font-weight: 600;
}

/* ── Telas de autenticação ─────────────────────────────────────────────── */

/*
 * Estrutura de docs/design_system/login-01.png: foto ocupando a tela inteira e
 * um painel branco ancorado à direita.
 *
 * A foto é DECORATIVA, então entra como `background-image` no CSS e não como
 * <img> no HTML: assim nenhum leitor de tela a anuncia e o Vite versiona o
 * arquivo, evitando cache velho depois de uma troca de imagem.
 */
.auth-shell {
    min-height: 100vh;
    display: flex;

    /* `center`, e não `stretch`: o painel tem a altura do conteúdo dele e fica
       centralizado na vertical. Esticado, um formulário curto como o login
       virava uma faixa branca de ponta a ponta com os campos perdidos no meio. */
    align-items: center;
    justify-content: flex-end;
    padding: 2rem 1.5rem;

    background-color: var(--app-brand-dark);
    background-image: url('../images/login-background.jpg');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

/*
 * Abaixo de 768px a versão menor economiza ~60 KB, e a diferença de nitidez é
 * imperceptível numa tela desse tamanho.
 */
@media (max-width: 767.98px) {
    .auth-shell {
        background-image: url('../images/login-background-sm.jpg');
    }
}

/*
 * Véu escuro sobre a foto.
 *
 * Não é enfeite: sem ele, a foto original tem áreas claras (as luzes do
 * ginásio) onde a borda do card branco desaparece. O véu garante contraste
 * independentemente do recorte que couber na tela.
 */
.auth-shell::before {
    content: '';
    position: fixed;
    inset: 0;
    background: linear-gradient(90deg, rgba(18, 18, 18, 0.55), rgba(18, 18, 18, 0.25));
    pointer-events: none;
}

.auth-card {
    position: relative;
    width: 100%;
    max-width: 27rem;

    background: var(--app-surface);
    border-radius: 0.75rem;
    box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.25);
    padding: 2.5rem 2rem;

    /* Sem altura fixa nem rolagem interna: o painel acompanha o conteúdo.
       Quando um formulário longo (o cadastro de arena) passa da tela, quem
       rola é a PÁGINA — rolagem dentro de um painel que já parece uma página
       confunde, e a barra interna some do campo de visão. */
}

/* O cadastro de arena tem campos demais para a largura
   padrão — em 27rem os campos de CPF/CNPJ e telefone ficariam empilhados
   quando cabem lado a lado. */
.auth-card--wide {
    max-width: 38rem;
}

/* No celular o painel ocupa a largura toda, mas continua com a altura do
   conteúdo — a foto aparece acima e abaixo dele. */
@media (max-width: 575.98px) {
    .auth-shell {
        padding: 1rem;
        justify-content: center;
    }

    .auth-card {
        max-width: none;
        padding: 2rem 1.25rem;
    }
}

/* Marca no topo do painel: bola sobre o azul da identidade. */
.auth-brand {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    margin-bottom: 2rem;
    color: var(--app-brand-dark);
    text-decoration: none;
}

.auth-brand__ball {
    display: grid;
    place-items: center;
    width: 3rem;
    height: 3rem;
    border-radius: 0.75rem;
    background: var(--app-brand-dark);
    color: #fff;
    flex: 0 0 auto;
}

.auth-brand__ball svg {
    width: 1.75rem;
    height: 1.75rem;
}

.auth-brand__name {
    font-weight: 700;
    font-size: 1.0625rem;
    line-height: 1.2;
    letter-spacing: -0.01em;
}

.auth-brand__name small {
    display: block;
    font-weight: 500;
    font-size: 0.8125rem;
    color: var(--app-muted);
}

/* `margin-top: auto` foi removido junto com o painel de altura cheia: ele só
   empurrava o rodapé para baixo quando havia espaço sobrando, e agora não há. */
.auth-footer {
    margin-top: 2rem;
    text-align: center;
    font-size: 0.75rem;
    color: var(--app-muted);
}

/* Color picker das quadras: grade de quadradinhos coloridos, um por cor da
   paleta. O radio real fica escondido (mas focável); o quadradinho é o label.
   A cor vem da custom property `--swatch` setada inline no label. */
.court-color-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.court-color-picker__swatch {
    position: relative;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 0.5rem;
    background: var(--swatch);
    cursor: pointer;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.12);
    transition: transform 0.08s ease, box-shadow 0.08s ease;
}

.court-color-picker__swatch:hover {
    transform: scale(1.06);
}

.court-color-picker__input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

/* Check branco centralizado, visível só na cor selecionada. */
.court-color-picker__check {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 1.1rem;
    opacity: 0;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}

.court-color-picker__input:checked ~ .court-color-picker__check {
    opacity: 1;
}

/* Anel de foco/seleção acessível ao redor do quadradinho escolhido. */
.court-color-picker__input:checked ~ .court-color-picker__check,
.court-color-picker__swatch:has(.court-color-picker__input:checked) {
    box-shadow:
        inset 0 0 0 1px rgba(0, 0, 0, 0.12),
        0 0 0 3px var(--app-surface, #fff),
        0 0 0 5px var(--swatch);
}

.court-color-picker__swatch:has(.court-color-picker__input:focus-visible) {
    outline: 2px solid var(--swatch);
    outline-offset: 2px;
}

/* Cor já usada por outra quadra: riscada e sem interação. */
.court-color-picker__swatch.is-taken {
    cursor: not-allowed;
    opacity: 0.4;
}

.court-color-picker__swatch.is-taken::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
        to top left,
        transparent calc(50% - 1px),
        rgba(255, 255, 255, 0.9) calc(50% - 1px),
        rgba(255, 255, 255, 0.9) calc(50% + 1px),
        transparent calc(50% + 1px)
    );
    border-radius: inherit;
}

.court-color-picker__swatch.is-taken:hover {
    transform: none;
}

/* Filtro de quadra (setas ‹ nome ›) no topo das reservas. Sem bordas nem caixa:
   só as setas e o nome. Largura fixa da label para o controle não pular de
   tamanho ao trocar de quadra. */
.court-filter {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.court-filter__label {
    min-width: 12rem;
    text-align: center;
    font-weight: 600;
}

/* Setas: botão sem borda nem fundo, só o chevron. */
.court-filter__arrow {
    border: 0;
    background: transparent;
    padding: 0.25rem;
    line-height: 1;
    color: var(--app-muted);
    cursor: pointer;
    border-radius: 0.375rem;
}

.court-filter__arrow:hover {
    color: var(--bs-primary);
}

/* Wizard do formulário de reserva: trilha de passos à esquerda, painel do passo
   atual à direita. Abaixo de 768px vira uma coluna só, com a trilha em cima. */
.reservation-wizard {
    display: grid;
    grid-template-columns: 14rem 1fr;
    min-height: 22rem;
}

.reservation-wizard__steps {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 1.25rem 1rem;
    border-right: 1px solid var(--bs-border-color);
    background: var(--bs-tertiary-bg);
}

.reservation-wizard__panels {
    padding: 1.25rem 1.5rem;
}

/* Cada passo é um botão: dá para voltar clicando nele. */
.reservation-wizard__step {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    border: 0;
    background: transparent;
    padding: 0.5rem 0.25rem;
    text-align: left;
    cursor: pointer;
    position: relative;
}

/* Linha ligando um passo ao seguinte, como na referência. Não sai do último
   (nem de um passo escondido, que fica com display:none). */
.reservation-wizard__step:not(:last-child)::after {
    content: "";
    position: absolute;
    left: 1.0625rem;
    top: 2.5rem;
    bottom: -0.25rem;
    width: 1px;
    background: var(--bs-border-color);
}

.reservation-wizard__bullet {
    flex: 0 0 auto;
    width: 2.125rem;
    height: 2.125rem;
    border-radius: 0.625rem;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.875rem;
    background: var(--bs-secondary-bg);
    color: var(--app-muted);
    z-index: 1;
}

.reservation-wizard__text {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
    min-width: 0;
}

.reservation-wizard__title {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--app-muted);
}

.reservation-wizard__hint {
    font-size: 0.75rem;
    color: var(--app-muted);
    opacity: 0.75;
}

/* Passo atual: destaque cheio. Passos já visitados: marcados, mas discretos. */
.reservation-wizard__step.is-active .reservation-wizard__bullet {
    background: var(--bs-primary);
    color: #fff;
}

.reservation-wizard__step.is-active .reservation-wizard__title {
    color: var(--bs-body-color);
}

.reservation-wizard__step.is-done .reservation-wizard__bullet {
    background: color-mix(in srgb, var(--bs-primary) 15%, transparent);
    color: var(--bs-primary);
}

.reservation-wizard__panel {
    display: none;
}

.reservation-wizard__panel.is-active {
    display: block;
}

/* Lista de datas da repetição: rola DENTRO do modal quando é longa. A barra só
   aparece se houver transbordo (overflow-y: auto), nunca "vazia". */
.reservation-dates-scroll {
    max-height: 45vh;
    overflow-y: auto;
}

/*
 * O RESUMO do último passo: rótulo à esquerda, valor à direita.
 *
 * Grade de duas colunas e não um <dl> em bloco: os valores precisam alinhar
 * entre si para a leitura ser vertical ("Total" salta aos olhos ao lado dos
 * outros números), e é isso que uma coluna própria dá.
 */
.reservation-summary {
    display: grid;
    grid-template-columns: minmax(7rem, auto) 1fr;
    gap: 0.35rem 1rem;
    margin: 0;
}

.reservation-summary dt {
    font-weight: 400;
    color: var(--bs-secondary-color);
}

.reservation-summary dd {
    margin: 0;
}

.reservation-summary__total {
    font-weight: 600;
}

@media (max-width: 767.98px) {
    .reservation-wizard {
        grid-template-columns: 1fr;
        min-height: 0;
    }

    .reservation-wizard__steps {
        flex-direction: row;
        overflow-x: auto;
        border-right: 0;
        border-bottom: 1px solid var(--bs-border-color);
        padding: 0.75rem;
    }

    /* Na horizontal a linha vertical não faz sentido, e os rótulos roubariam a
       largura toda: fica só a bolinha numerada. */
    .reservation-wizard__step:not(:last-child)::after {
        display: none;
    }

    .reservation-wizard__text {
        display: none;
    }

    .reservation-wizard__step.is-active .reservation-wizard__text {
        display: flex;
    }
}

/* "Nota" do passo de valores: quadra · quantidade · total, depois desconto e
   total. Três colunas alinhadas, com os números à direita — é o que faz a
   coluna de valores ler como uma conta, e não como texto solto. */
.reservation-invoice {
    border: 1px solid var(--bs-border-color);
    border-radius: 0.5rem;
    overflow: hidden;
}

.reservation-invoice__row {
    display: grid;
    grid-template-columns: 1fr auto 7rem;
    gap: 0.75rem;
    align-items: center;
    padding: 0.625rem 0.875rem;
    border-bottom: 1px solid var(--bs-border-color);
}

.reservation-invoice__row > :last-child {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.reservation-invoice__row--head {
    background: var(--bs-tertiary-bg);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--app-muted);
}

.reservation-invoice__row--discount {
    color: var(--app-muted);
}

/*
 * O botão que alterna a unidade do desconto (% ⇄ R$).
 *
 * LARGURA FIXA porque os dois símbolos têm larguras diferentes: sem ela, a
 * troca empurraria o campo de texto alguns pixels para o lado a cada clique — o
 * tipo de tremor que faz uma interface parecer quebrada.
 */
.reservation-discount__unit {
    min-width: 3rem;
    font-weight: 600;
}

.reservation-invoice__row--total {
    border-bottom: 0;
    font-weight: 700;
    font-size: 1.0625rem;
}

/* Rótulo da reserva no calendário: "16:00 - José - Vôlei de Praia".

   A hora e o nome (`__head`) NÃO encolhem; só a modalidade cede espaço e ganha
   reticências quando não cabe. `min-width: 0` é obrigatório nos dois níveis —
   sem ele um filho flex nunca encolhe abaixo do próprio conteúdo, e o
   text-overflow jamais dispara. */
.reservation-event {
    display: flex;
    align-items: baseline;
    min-width: 0;
    overflow: hidden;
}

.reservation-event__head {
    flex: 0 0 auto;
    white-space: nowrap;
}

.reservation-event__modality {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Escolha da quadra por badges, no modal de reserva. A cor de cada badge é a
   cor da própria quadra, via `--court-color` inline: contorno quando não
   escolhida, preenchida quando escolhida. */
.court-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
}

.court-picker__badge {
    border: 1px solid var(--court-color);
    background: transparent;
    color: var(--court-color);
    border-radius: 999px;
    padding: 0.25rem 0.75rem;
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.5;
    cursor: pointer;
    transition: background-color 0.08s ease, color 0.08s ease;
}

.court-picker__badge:hover {
    background: color-mix(in srgb, var(--court-color) 12%, transparent);
}

.court-picker__badge.is-active {
    background: var(--court-color);
    color: #fff;
}

.court-picker__badge:focus-visible {
    outline: 2px solid var(--court-color);
    outline-offset: 2px;
}

/* Box de cor na listagem de quadras. */
.court-color-dot {
    display: inline-block;
    width: 1rem;
    height: 1rem;
    border-radius: 0.25rem;
    vertical-align: -2px;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
}

/* ── Barra de filtros ──────────────────────────────────────────────────────
 *
 * Uma pílula CONTORNADA com os filtros lado a lado, no lugar de vários selects
 * empilhados dentro de um card. Cada botão abre um menu e diz o que está
 * escolhido — "2 contas" em vez de um campo que só revela a seleção ao ser
 * aberto.
 *
 * Contorno cinza e fundo de superfície, como o resto do painel: a barra é um
 * controle, não um bloco de destaque, e uma faixa sólida colorida competiria
 * com os números do relatório pela atenção de quem lê.
 *
 * ⚠️ NADA DE `overflow: hidden` AQUI. O menu do dropdown é posicionado em
 * absoluto e sai dos limites da barra — recortá-lo faz o menu abrir invisível,
 * e o sintoma é exatamente "o dropdown não abre". Os cantos são arredondados
 * item a item (primeiro e último), que resolve o mesmo problema visual sem
 * cortar nada.
 */
.filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    background: var(--app-surface);
    border: 1px solid var(--bs-border-color);
    border-radius: 999px;
}

.filter-bar__item {
    display: flex;
}

/* Arredondamento nas pontas, no lugar do `overflow: hidden`. */
.filter-bar > :first-child,
.filter-bar > :first-child .filter-bar__button {
    border-top-left-radius: 999px;
    border-bottom-left-radius: 999px;
}

.filter-bar > :last-child,
.filter-bar > :last-child .filter-bar__button {
    border-top-right-radius: 999px;
    border-bottom-right-radius: 999px;
}

.filter-bar__button {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.5rem 0.875rem;
    border: 0;
    border-right: 1px solid var(--bs-border-color);
    background: transparent;
    color: var(--bs-body-color);
    font-size: 0.875rem;
    font-weight: 500;
    white-space: nowrap;
}

.filter-bar__button:hover,
.filter-bar__button:focus-visible {
    background: var(--bs-secondary-bg);
    color: var(--bs-body-color);
}

.filter-bar__button:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: -2px;
}

/* Filtro ATIVO em destaque discreto — a pista de que a lista está recortada
 * precisa estar no botão fechado, não só dentro do menu aberto. */
.filter-bar__button.is-active {
    background: var(--bs-secondary-bg);
    color: var(--bs-primary);
    font-weight: 600;
}

/* O "x" que limpa os filtros: quadrado, sem o padding do texto. Era um par com
 * a lupa de aplicar, que saiu quando o filtro passou a valer sozinho. */
.filter-bar__icon {
    padding-inline: 0.875rem;
    justify-content: center;
}

/* O menu é do Bootstrap; aqui só o teto de altura, para uma arena com dezenas
 * de categorias não abrir um menu maior que a tela. */
.filter-bar__menu {
    max-height: 18rem;
    overflow-y: auto;
    min-width: 15rem;
}

@media (max-width: 767.98px) {
    /* No celular a pílula vira uma coluna: os botões lado a lado não cabem sem
     * virar rolagem horizontal, que é pior do que empilhar. */
    .filter-bar {
        border-radius: 0.75rem;
    }

    .filter-bar > :first-child,
    .filter-bar > :first-child .filter-bar__button,
    .filter-bar > :last-child,
    .filter-bar > :last-child .filter-bar__button {
        border-radius: 0;
    }

    .filter-bar__button {
        border-right: 0;
        border-bottom: 1px solid var(--bs-border-color);
        width: 100%;
        justify-content: flex-start;
    }

    .filter-bar__item {
        width: 100%;
        margin-left: 0;
    }
}

/* ==========================================================================
   Modal de novo pedido (Comandas)
   ========================================================================== */

/* Catálogo à esquerda, carrinho à direita. Larguras em grid e não em colunas do
   Bootstrap porque o carrinho precisa de largura FIXA: em porcentagem ele
   encolhe junto com a tela e a linha "nome / − qtd + / subtotal" quebra. */
.order-picker {
    display: grid;
    grid-template-columns: 1fr 24rem;
    min-height: 26rem;
}

.order-picker__catalog {
    padding: 1rem 1.25rem;
    min-width: 0;
}

/* Badges de categoria: uma faixa que ROLA na horizontal. Quebrar em várias
   linhas empurraria a grade de produtos para fora da área visível do modal
   justamente nas arenas com muitas categorias. */
.order-categories {
    display: flex;
    flex-wrap: nowrap;
    gap: 0.5rem;
    overflow-x: auto;
    padding-bottom: 0.5rem;
    margin-bottom: 0.75rem;
    /* Esconde a barra no Firefox e no WebKit: a faixa é curta e a barra
       ocuparia parte visível da altura útil. O gesto de arrastar continua. */
    scrollbar-width: none;
}

.order-categories::-webkit-scrollbar {
    display: none;
}

/* `flex: 0 0 auto` é o que impede o flex de espremer as badges até caberem
   todas — sem ele não haveria rolagem, só texto cortado. */
.order-categories__item {
    flex: 0 0 auto;
    white-space: nowrap;
}

/* QUATRO POR LINHA, fixo — não `auto-fill`. O número de colunas deixa de
   depender da largura sobrada, o que é justamente o ponto: com `auto-fill`, dar
   mais espaço ao carrinho reduzia as colunas do catálogo de forma imprevisível.
   Fixando em 4, o card encolhe e o carrinho fica com largura de sobra.

   `minmax(0, 1fr)` e não `1fr`: o mínimo automático do grid é o conteúdo, então
   um nome de produto longo empurraria a coluna e estouraria a linha para fora
   da área visível. O zero é o que autoriza o card a encolher. */
.order-products {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.75rem;
    max-height: 26rem;
    overflow-y: auto;
}

/* O card inteiro é um <button>: zera o estilo de botão e mantém o de card. */
.order-product {
    padding: 0;
    text-align: left;
    cursor: pointer;
    overflow: hidden;
    transition: border-color 0.15s ease, transform 0.15s ease;
}

.order-product:hover {
    border-color: var(--bs-primary);
    transform: translateY(-2px);
}

/* Já está no pedido: contorno cheio, para o operador não recontar o que clicou. */
.order-product.is-chosen {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 1px var(--bs-primary) inset;
}

/* `aspect-ratio` no lugar de altura fixa: a imagem acompanha a largura da
   coluna, que muda com o `auto-fill` da grade. */
.order-product__image {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
}

.order-product__image--empty {
    background: var(--bs-tertiary-bg);
    color: var(--app-muted);
    font-size: 1.5rem;
}

/* Nome à esquerda, preço à direita — o rodapé pedido. `min-width: 0` no nome é
   o que permite o `text-overflow` funcionar dentro do flex. */
.order-product__footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.5rem 0.625rem;
    font-size: 0.8125rem;
}

.order-product__name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.order-product__price {
    flex: 0 0 auto;
    font-weight: 600;
}

/* O card de "nenhum produto" ocupa a linha toda da grade. */
.order-products__empty {
    grid-column: 1 / -1;
}

/* ----- Carrinho ----- */

/* `grid-template-rows` com `1fr` no meio: cabeçalho e rodapé ficam fixos e só a
   lista rola. Com tudo no fluxo, o total sairia da tela numa comanda longa —
   e o total é justamente o que o operador confere antes de finalizar. */
.order-cart {
    display: grid;
    grid-template-rows: auto 1fr auto;
    border-left: 1px solid var(--bs-border-color);
    background: var(--bs-tertiary-bg);
    min-height: 0;
}

.order-cart__head {
    display: flex;
    flex-direction: column;
    padding: 1rem 1rem 0.75rem;
    border-bottom: 1px solid var(--bs-border-color);
}

.order-cart__items {
    overflow-y: auto;
    padding: 0.5rem 0;
    min-height: 0;
}

/* Nome flexível, controle e subtotal com largura própria. */
.order-cart__item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 1rem;
    font-size: 0.875rem;
}

.order-cart__name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.order-cart__stepper {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    flex: 0 0 auto;
}

/* Largura mínima na quantidade: sem ela, a linha inteira dança de 9 para 10. */
.order-cart__quantity {
    min-width: 1.5rem;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.order-cart__subtotal {
    flex: 0 0 auto;
    min-width: 4.5rem;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Lixeira: tira o item inteiro do pedido. Discreta por padrão e vermelha no
   hover — é a única ação destrutiva da linha, e no balcão ela fica ao lado de
   um "−" que o operador usa o tempo todo. Sem o contraste, os dois pareceriam
   a mesma coisa. */
.order-cart__remove {
    flex: 0 0 auto;
    border: 0;
    background: transparent;
    padding: 0 0 0 0.25rem;
    line-height: 1;
    font-size: 0.875rem;
    color: var(--app-muted);
    cursor: pointer;
    transition: color 0.15s ease;
}

.order-cart__remove:hover,
.order-cart__remove:focus-visible {
    color: var(--bs-danger);
}

/* O aviso de carrinho vazio ocupa a mesma faixa da lista, centrado. */
.order-cart__empty {
    grid-row: 2;
    align-self: center;
    padding: 0 1.5rem;
    margin: 0;
}

.order-cart__foot {
    padding: 0.75rem 1rem 1rem;
    border-top: 1px solid var(--bs-border-color);
}

@media (max-width: 991.98px) {
    /* No tablet e no celular o carrinho vai para BAIXO do catálogo: 20rem ao
       lado deixariam a grade de produtos com espaço para um card por linha. */
    .order-picker {
        grid-template-columns: 1fr;
    }

    .order-cart {
        border-left: 0;
        border-top: 1px solid var(--bs-border-color);
    }

    .order-products {
        max-height: 18rem;
    }
}

@media (max-width: 575.98px) {
    /* No celular, quatro colunas dariam cards de ~4rem: imagem ilegível e nome
       cortado na primeira sílaba. Duas é o máximo que ainda mostra o produto. */
    .order-products {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ==========================================================================
   Card de comanda na listagem — clicável por inteiro
   ========================================================================== */

/* O card inteiro abre o detalhe, então ele precisa PARECER clicável antes do
   clique: cursor de mão e uma elevação no hover. Sem isso, o operador olharia
   para um cartão de aparência estática e procuraria um botão que não existe. */
.order-card {
    cursor: pointer;
    transition:
        border-color 0.15s ease,
        box-shadow 0.15s ease;
}

.order-card:hover {
    border-color: var(--bs-primary);
    box-shadow: var(--bs-box-shadow-sm);
}

/* A FAIXA DO NOME NÃO CRESCE, e a sobra do `h-100` vai para a lista de itens.
   `flex: 0 0 auto` desliga o `flex: 1 1 auto` que o .card-body do Bootstrap traz
   — sem isso, o card com poucos itens empurraria o nome para o meio da altura
   herdada da linha e nenhum nome ficaria na mesma altura do vizinho.

   A altura FIXA de duas linhas (`min-height` + `line-clamp`) resolve o outro
   lado do mesmo problema: "Ana" e "Maria Aparecida da Silva Sauro" ocupariam
   uma e três linhas, e a lista de itens começaria em alturas diferentes em cada
   card. Duas linhas cabem a grande maioria dos nomes; o que passar disso é
   cortado com reticências, e o nome completo continua no modal.

   `column`: a faixa empilha o nome e a DATA DE ABERTURA. No `row` padrão do
   flex os dois ficariam lado a lado, com a data espremida à direita do nome.
   O `min-height` sobe junto para caber a segunda linha sem apertar os nomes
   longos contra a borda. */
.order-card__head {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 6.75rem;
}

/* O SELO DA TECLA NA QUINA DO CARD (⇧3).
 *
 * `absolute` e fora do fluxo: dentro da faixa do nome ele entraria na coluna
 * flex centralizada e empurraria o nome para baixo, quebrando o alinhamento de
 * altura que `.order-card__head` existe para garantir.
 *
 * Ancora no `.card`, que o Bootstrap já deixa `position: relative` por causa do
 * `stretched-link` — não é preciso (nem seguro) declarar um novo contexto aqui:
 * fazer da faixa do nome o contexto mudaria também o alvo do `stretched-link`,
 * que passaria a cobrir só o cabeçalho em vez do card inteiro.
 *
 * SEM `z-index`. O `stretched-link::after` do Bootstrap passa por cima com
 * z-index 1, e é isso que se quer: a camada transparente que capta o clique
 * precisa continuar cobrindo a quina, senão haveria um retângulo morto no card
 * justamente onde o operador pode mirar. O selo aparece porque a camada é
 * transparente, e não porque está acima dela. */
.order-card__key {
    position: absolute;
    top: 0.5rem;
    left: 0.5rem;
    margin-left: 0;
    color: var(--app-muted);
    opacity: 1;
}

/* Discreta de propósito: a data situa a comanda, mas quem varre a grade procura
   o NOME. Mesmo peso visual do nome faria as duas informações competirem. */
.order-card__date {
    margin-top: 0.25rem;
}

.order-card__name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    overflow-wrap: anywhere;
}

/* A lista recebe a sobra da altura — o espaço vazio fica DEPOIS do último item,
   que é onde ele não desalinha nada. */
.order-card__items {
    flex: 1 1 auto;
}

/* O gatilho é um <button> por causa do teclado e do leitor de tela, mas não
   deve PARECER um botão — quem vê o card vê o nome do cliente. Daí o reset
   completo de aparência, herdando a tipografia do <h2> que o envolve. */
.order-card__trigger {
    border: 0;
    background: transparent;
    padding: 0;
    color: inherit;
    font: inherit;
    text-align: inherit;
}

/* O foco visível migra para o CARD: o `stretched-link` cobre o card inteiro,
   então um anel desenhado só ao redor do texto marcaria uma área muito menor
   que a realmente clicável.

   `:focus`, E NÃO `:focus-visible`. A regra era `:focus-visible` para o anel não
   aparecer no clique de mouse, mas na tela de Comandas o anel deixou de ser
   decoração de teclado e virou o CURSOR DA GRADE: é ele que diz qual comanda o
   Enter vai abrir e de onde as setas partem (ver card-nav.js). Duas situações
   quebram com `:focus-visible`:

     1. O card-nav.js põe o foco no primeiro card ao abrir a tela. Foco dado por
        script frequentemente NÃO conta como "visible" para o navegador — a
        grade estaria navegável e sem nada na tela indicando onde.
     2. Ao fechar o modal, o Bootstrap devolve o foco ao gatilho que o abriu. Se
        o modal foi aberto com o mouse, o anel não voltaria, e as setas
        continuariam de uma posição invisível.

   O efeito colateral aceito é o anel aparecer ao clicar num card. Aqui isso não
   é ruído: o clique abre o modal por cima, e quando ele fecha o anel é
   exatamente a informação que o operador precisa — "você está nesta". */
.order-card:has(.order-card__trigger:focus) {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 0.25rem rgba(var(--bs-primary-rgb), 0.25);
}

.order-card__trigger:focus {
    outline: 0;
}
