/* Tema customizado sobre o Bootstrap 5.3 (CDN) — paleta da marca (navy + verdes,
   ver o-flipador-tokens.css, carregado antes deste arquivo) + Inter + superfícies
   elevadas. Suporta claro (padrão) e escuro via [data-bs-theme] no <html>.

   Papéis das cores (brand guidelines v1.1):
   - Ação primária, links, item ativo: navy (branco no escuro) — tokens --action-*.
   - Verde da marca (--accent): só acento, progresso e iconografia. Branco sobre
     ele NÃO passa AA (3,0:1) — nunca usar como fundo de botão com texto. */

:root {
    --accent: var(--brand-green);
    --accent-text: var(--text-positive);
    --action-primary-hover-bg: #164254;
    --action-primary-rgb: 12, 47, 64;
    --action-link-hover: var(--text-secondary);
    --focus-ring: var(--border-focus);
    --focus-ring-rgb: 14, 129, 117;

    /* Remapeia o "primary" do Bootstrap (badges, border-primary, checkbox marcado,
       paginação, link de aba etc.) pra marca em vez do azul padrão dele. */
    --bs-primary: #0C2F40;
    --bs-primary-rgb: 12, 47, 64;
    --bs-primary-text-emphasis: #0C2F40;
    --bs-primary-bg-subtle: #EAF1F3;
    --bs-primary-border-subtle: #C8D6DC;
    --bs-link-color: #0C2F40;
    --bs-link-color-rgb: 12, 47, 64;
    --bs-link-hover-color: #385361;
    --bs-link-hover-color-rgb: 56, 83, 97;

    --bs-font-sans-serif: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
    --bs-border-radius: 0.65rem;
    --bs-border-radius-sm: 0.5rem;
    --bs-border-radius-lg: 0.9rem;

    /* Tokens de superfície — claro por padrão */
    --surface: #ffffff;
    --surface-nav: rgba(255, 255, 255, 0.85);
}

[data-bs-theme="light"] {
    --bs-tertiary-bg: #f4f5f7;
    --bs-border-color: #e4e6eb;
    --surface: #ffffff;
    --surface-nav: rgba(255, 255, 255, 0.85);
}

[data-bs-theme="dark"] {
    /* Superfícies: azul institucional do kit (o-flipador-tokens.css) — página mais
       escura, cards um degrau acima, realces (hover/skeleton) mais um. */
    --bs-body-bg: var(--surface-page);
    --bs-body-bg-rgb: 8, 37, 48;
    --bs-tertiary-bg: var(--surface-card);
    --bs-tertiary-bg-rgb: 12, 47, 64;
    --bs-secondary-bg: var(--surface-subtle);
    --bs-secondary-bg-rgb: 22, 66, 84;
    --bs-border-color: var(--border-default);
    --bs-body-color: var(--text-primary);
    --bs-secondary-color: var(--text-secondary);
    --surface: var(--surface-card);
    --surface-nav: rgba(8, 37, 48, 0.85);

    /* Ação primária invertida (branco com texto navy — tokens --action-* já
       trocam no escuro). O "primary" do Bootstrap vira o teal do kit em vez do
       navy: sobre superfície escura o navy some, e o branco quebraria
       badges/checkbox (texto branco fixo em cima). */
    --accent-text: var(--brand-green-end);
    --action-primary-hover-bg: #EAF1F3;
    --action-primary-rgb: 255, 255, 255;
    --action-link-hover: var(--text-secondary);
    --focus-ring: #11AF9D;
    --focus-ring-rgb: 17, 175, 157;
    --bs-primary: #0E8175;
    --bs-primary-rgb: 14, 129, 117;
    --bs-primary-text-emphasis: #C5D7DE;
    --bs-primary-bg-subtle: #164254;
    --bs-primary-border-subtle: #3A5D6A;
    --bs-link-color: #FFFFFF;
    --bs-link-color-rgb: 255, 255, 255;
    --bs-link-hover-color: #C5D7DE;
    --bs-link-hover-color-rgb: 197, 215, 222;
}

/* ---------------------------------------------------------------------------
   Arquitetura visual da área autenticada (<body class="app">)
   Tudo derivado dos tokens da marca (o-flipador-tokens.css) — sem cores novas
   além dos tons semânticos abaixo. Site público e telas de login não usam a
   classe .app e ficam como estavam.
   Hierarquia (claro): conteúdo (tinta muito leve) < sidebar (tinta da marca)
   < topbar/cards/tabelas/formulários (branco). No escuro, os tokens
   do kit já dão essa hierarquia; só sombras e tons semânticos se adaptam.
   --------------------------------------------------------------------------- */
:root {
    --app-bg: color-mix(in srgb, var(--surface-subtle) 60%, #F6F7F7);
    --app-sidebar-bg: var(--surface-subtle);
    --app-line: color-mix(in srgb, var(--border-default) 60%, #fff);
    --app-shadow-xs: 0 1px 2px rgba(12, 47, 64, 0.06);
    --app-shadow-sm: 0 1px 2px rgba(12, 47, 64, 0.05), 0 1px 3px rgba(12, 47, 64, 0.03);
    --app-row-hover: color-mix(in srgb, var(--text-primary) 4%, var(--surface));
    --app-thead-bg: color-mix(in srgb, var(--text-primary) 4%, var(--surface));

    /* Tons semânticos (base = tinta do fundo/borda; fg = texto/ícone) */
    --tone-info-base: var(--brand-navy);
    --tone-info-fg: var(--brand-navy);
    --tone-success-base: var(--brand-green);
    --tone-success-fg: var(--text-positive);
    --tone-warning-base: #E0A100;
    --tone-warning-fg: var(--feedback-warning);
    --tone-danger-base: #C93B4A;
    --tone-danger-fg: var(--feedback-danger);
    --tone-neutral-base: var(--brand-navy);
    --tone-neutral-fg: var(--text-secondary);
}
[data-bs-theme="dark"] {
    --app-bg: var(--surface-page);
    --app-sidebar-bg: var(--surface-nav);
    --app-line: var(--border-default);
    --app-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.25);
    --app-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.25);
    --app-row-hover: color-mix(in srgb, #fff 5%, var(--surface));
    --app-thead-bg: color-mix(in srgb, #fff 4%, var(--surface));
    --tone-info-base: #6FA8C0;
    --tone-info-fg: #9CC6D8;
    --tone-success-fg: var(--brand-green-end);
    --tone-warning-fg: #F2B84B;
    --tone-danger-fg: #F08A94;
    --tone-neutral-base: #fff;
}
/* Claro: só na área autenticada, o cinza neutro do Bootstrap vira o azul-acinzentado
   da marca (bordas, texto secundário, textos de sucesso/erro com contraste AA). */
[data-bs-theme="light"] body.app {
    --bs-body-color: var(--text-primary);
    --bs-body-color-rgb: 12, 47, 64;
    --bs-heading-color: var(--text-primary);
    --bs-secondary-color: var(--text-secondary);
    --bs-border-color: var(--app-line);
    --bs-tertiary-bg: color-mix(in srgb, var(--surface-subtle) 55%, #fff);
    --bs-success: #0B6B46;
    --bs-success-rgb: 11, 107, 70;
    --bs-danger: #A02C38;
    --bs-danger-rgb: 160, 44, 56;
}
body.app {
    background-color: var(--app-bg);
}

body {
    font-feature-settings: "cv11", "ss01";
    letter-spacing: -0.01em;
}

/* <fieldset> tem min-width: min-content por padrão no navegador, o que quebra
   o grid flex do Bootstrap (.row/.col-*) quando usado dentro dele (crispy Fieldset). */
fieldset {
    min-width: 0;
}
fieldset legend {
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: 1rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--bs-border-color);
}

h1, h2, h3, h4, h5, .navbar-brand {
    letter-spacing: -0.02em;
    font-weight: 600;
}

/* Links: navy (branco no escuro) — o sublinhado padrão do Bootstrap fica, já que
   o guia pede outro sinal além da cor. */
a {
    color: var(--action-link);
}
a:hover {
    color: var(--action-link-hover);
}

/* Sidebar */
.app-shell {
    display: flex;
    min-height: 100vh;
    align-items: flex-start;
}
.app-sidebar {
    width: 240px;
    flex: 0 0 240px;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    padding: 1.25rem 1rem;
    background-color: var(--app-sidebar-bg);
    border-right: 1px solid var(--app-line);
}
.app-main {
    flex: 1 1 auto;
    min-width: 0;
}
.app-content {
    flex: 1 1 auto;
    min-width: 0;
}
.sidebar-brand {
    display: block;
    text-decoration: none;
    padding: 0 0.25rem;
}
/* Logo: as duas versões ficam no HTML; o tema (data-bs-theme) decide qual aparece.
   Light sobre fundo claro, Dark sobre fundo escuro (brand guidelines v1.1, p. 13). */
.brand-logo-dark {
    display: none;
}
[data-bs-theme="dark"] .brand-logo-light {
    display: none;
}
[data-bs-theme="dark"] .brand-logo-dark {
    display: inline-block;
}
.sidebar-nav {
    margin-top: 1.5rem;
    gap: 0.15rem;
}
.sidebar-nav .nav-link {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    color: var(--bs-secondary-color);
    font-weight: 500;
    padding: 0.55rem 0.75rem;
    border-radius: var(--bs-border-radius-sm);
}
.sidebar-nav .nav-link:hover {
    color: var(--bs-body-color);
    background-color: color-mix(in srgb, var(--text-primary) 6%, transparent);
}
/* Item ativo: "chip" de superfície (branco no claro) sobre a sidebar tingida. */
.sidebar-nav .nav-link.active {
    color: var(--action-link);
    font-weight: 600;
    background-color: var(--surface);
    box-shadow: inset 0 0 0 1px var(--app-line), var(--app-shadow-xs);
}
/* Barra superior — sempre visível (não só no mobile); no mobile também carrega
   o botão que abre a sidebar como offcanvas. */
.app-topbar {
    width: 100%;
    padding: 0.75rem 1rem;
    background-color: var(--surface-nav);
    backdrop-filter: blur(8px);
    border-bottom: 1px solid var(--app-line);
    box-shadow: var(--app-shadow-xs);
    position: sticky;
    top: 0;
    z-index: 1020;
}
.offcanvas {
    background-color: var(--app-sidebar-bg);
}
.offcanvas .sidebar-nav {
    margin-top: 0.5rem;
}

/* Avatar do usuário (iniciais) e o botão que o envolve na barra superior */
.avatar-btn {
    border: none;
    background: transparent;
    padding: 0;
}
.avatar-btn::after {
    display: none;
}
.avatar-circle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background-color: var(--action-primary-bg);
    color: var(--action-primary-text);
    font-weight: 600;
    font-size: 0.8rem;
    object-fit: cover;
}

/* Skeleton de carregamento pra fotos (imóvel/avatar) — a URL da imagem
   redireciona pro Spaces antes de carregar de fato, então sem isso a foto
   fica "sumida" por um instante depois do resto da página já ter renderizado.
   Precisa de DOIS elementos (não dá pra fazer só no <img>): opacity afeta o
   elemento inteiro, fundo e conteúdo juntos — se o shimmer e o fade-in
   fossem a mesma coisa, zerar a opacidade da imagem escondia o shimmer
   também. Aplicar a classe no elemento que ENVOLVE a <img>, com o tamanho
   já definido (width/height ou aspect-ratio) pra reservar o espaço; a <img>
   dentro dele fica com opacity 0 até carregar (evita pintar de cima pra
   baixo) e assume 100% de largura/altura do wrapper. */
.img-skeleton {
    position: relative;
    overflow: hidden;
    background: linear-gradient(90deg, var(--bs-secondary-bg) 25%, var(--bs-tertiary-bg) 50%, var(--bs-secondary-bg) 75%);
    background-size: 200% 100%;
    animation: img-skeleton-shimmer 1.4s ease-in-out infinite;
}
.img-skeleton.is-loaded {
    animation: none;
    background: none;
}
.img-skeleton > img {
    opacity: 0;
    transition: opacity 0.25s ease-out;
}
.img-skeleton.is-loaded > img {
    opacity: 1;
}
@keyframes img-skeleton-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* Asterisco de campo obrigatório (gerado pelo crispy-forms) — sem isso herda
   a cor normal do texto, ficando pouco visível como indicador. */
.asteriskField {
    color: var(--bs-danger);
}

/* Cards */
.card {
    background-color: var(--surface);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    box-shadow: var(--app-shadow-sm);
}
.card.stat-card {
    transition: transform 0.15s ease, border-color 0.15s ease;
}
.card.stat-card:hover {
    transform: translateY(-1px);
    border-color: color-mix(in srgb, var(--text-primary) 35%, var(--bs-border-color));
}
@media (prefers-reduced-motion: reduce) {
    .card.stat-card { transition: none; }
    .card.stat-card:hover { transform: none; }
}
.card .card-body {
    padding: 1.25rem;
}

/* Botões — retinta os componentes já compilados via suas próprias variáveis CSS */
.btn {
    font-weight: 500;
    border-radius: var(--bs-border-radius);
}
.btn-primary {
    --bs-btn-color: var(--action-primary-text);
    --bs-btn-bg: var(--action-primary-bg);
    --bs-btn-border-color: var(--action-primary-bg);
    --bs-btn-hover-color: var(--action-primary-text);
    --bs-btn-hover-bg: var(--action-primary-hover-bg);
    --bs-btn-hover-border-color: var(--action-primary-hover-bg);
    --bs-btn-active-color: var(--action-primary-text);
    --bs-btn-active-bg: var(--action-primary-hover-bg);
    --bs-btn-active-border-color: var(--action-primary-hover-bg);
    --bs-btn-disabled-color: var(--action-primary-text);
    --bs-btn-disabled-bg: var(--action-primary-bg);
    --bs-btn-disabled-border-color: var(--action-primary-bg);
    --bs-btn-focus-shadow-rgb: var(--focus-ring-rgb);
}
.btn-outline-primary {
    --bs-btn-color: var(--action-link);
    --bs-btn-border-color: var(--action-primary-bg);
    --bs-btn-hover-color: var(--action-primary-text);
    --bs-btn-hover-bg: var(--action-primary-bg);
    --bs-btn-hover-border-color: var(--action-primary-bg);
    --bs-btn-active-color: var(--action-primary-text);
    --bs-btn-active-bg: var(--action-primary-bg);
    --bs-btn-active-border-color: var(--action-primary-bg);
    --bs-btn-disabled-color: var(--action-link);
    --bs-btn-disabled-border-color: var(--action-primary-bg);
    --bs-btn-focus-shadow-rgb: var(--focus-ring-rgb);
}
.btn-outline-light {
    --bs-btn-color: var(--bs-body-color);
    --bs-btn-border-color: var(--bs-border-color);
    --bs-btn-hover-color: var(--bs-body-color);
    --bs-btn-hover-bg: var(--bs-tertiary-bg);
    --bs-btn-hover-border-color: var(--bs-border-color);
}

/* Formulários */
.form-control:focus,
.form-select:focus {
    border-color: var(--focus-ring);
    box-shadow: 0 0 0 0.2rem rgba(var(--focus-ring-rgb), 0.25);
}
.form-check-input:focus {
    border-color: var(--focus-ring);
    box-shadow: 0 0 0 0.2rem rgba(var(--focus-ring-rgb), 0.25);
}
.form-control,
.form-select {
    border-radius: var(--bs-border-radius-sm);
}
/* Área autenticada: campos brancos sobre cards brancos precisam de uma borda um
   degrau acima da dos cards (--app-line) pra continuarem visíveis. */
body.app .form-control,
body.app .form-select,
body.app .form-check-input:not(:checked) {
    /* ~3,5:1 contra o branco do card (WCAG 1.4.11 — limite visual do campo). */
    border-color: color-mix(in srgb, var(--text-primary) 55%, var(--surface));
}
body.app .form-control:focus,
body.app .form-select:focus,
body.app .form-check-input:focus {
    border-color: var(--focus-ring);
}

/* Campos travados (ex.: preenchidos automaticamente pelo CEP) — precisa ficar
   óbvio que não dá pra editar direto, sem depender só do estilo padrão sutil
   do Bootstrap para :read-only. */
.form-control:read-only {
    background-color: var(--bs-tertiary-bg);
    cursor: not-allowed;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236c757d'%3E%3Cpath d='M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2Zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2Z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.75rem center;
    background-size: 1rem;
    padding-right: 2.5rem;
}
.form-control:read-only:focus {
    box-shadow: none;
    border-color: var(--bs-border-color);
}

/* Tabelas — sem table-dark, herdam o tema ambiente com um pouco mais de respiro */
.table {
    --bs-table-bg: transparent;
}
.table > :not(caption) > * > * {
    padding: 0.65rem 0.75rem;
}
/* .table-responsive (Bootstrap) só define overflow-x: auto; como overflow-y fica no valor
   inicial (visible), a especificação CSS recalcula esse eixo pra "auto" também — todo
   .table-responsive do app vira, sem querer, um segundo contêiner de scroll VERTICAL (vazio, sem
   conteúdo pra rolar dentro dele, mas ainda assim capaz de "prender" o gesto). No Chrome/macOS,
   um scroll de trackpad com qualquer componente diagonal sobre uma tabela larga é capturado por
   esse eixo vertical interno em vez de subir pra página — a sensação de "dois scrolls
   concorrentes" mesmo sem nenhuma barra de rolagem vertical visível. Fixar overflow-y: hidden
   aqui (raiz compartilhada de toda tabela com scroll horizontal no app, não só da composição do
   orçamento) remove esse contêiner: a página volta a ser a única dona do scroll vertical, e o
   scroll horizontal da tabela continua funcionando normalmente. */
.table-responsive {
    overflow-y: hidden;
}
.table thead th {
    color: var(--bs-secondary-color);
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
    border-bottom-width: 1px;
    background-color: var(--app-thead-bg);
}
/* Cabeçalho tingido acompanha o raio do card quando a tabela é a primeira coisa dele. */
.card > .table-responsive:first-child > .table > thead:first-child > tr:first-child > th:first-child,
.card > .table:first-child > thead:first-child > tr:first-child > th:first-child {
    border-top-left-radius: calc(var(--bs-border-radius-lg) - 1px);
}
.card > .table-responsive:first-child > .table > thead:first-child > tr:first-child > th:last-child,
.card > .table:first-child > thead:first-child > tr:first-child > th:last-child {
    border-top-right-radius: calc(var(--bs-border-radius-lg) - 1px);
}
.table-hover {
    --bs-table-hover-bg: var(--app-row-hover);
    --bs-table-hover-color: var(--bs-body-color);
}

/* Badges de status */
.badge {
    font-weight: 500;
    letter-spacing: 0.01em;
    padding: 0.4em 0.7em;
    border-radius: 999px;
}

/* Superfícies semânticas — reutilizáveis em qualquer bloco (.surface-info,
   .surface-success, .surface-warning, .surface-danger, .surface-neutral) e
   aplicadas também aos .alert do Bootstrap. Fundo = tom a ~9% sobre a superfície
   do tema, borda = tom a ~30%; funciona no claro e no escuro. Use .tone-fg em
   títulos/ícones dentro delas. Não dependem só de cor: sempre com texto/ícone. */
.surface-info, .alert-info, .alert-primary { --tone-base: var(--tone-info-base); --tone-fg: var(--tone-info-fg); }
.surface-success, .alert-success { --tone-base: var(--tone-success-base); --tone-fg: var(--tone-success-fg); }
.surface-warning, .alert-warning { --tone-base: var(--tone-warning-base); --tone-fg: var(--tone-warning-fg); }
.surface-danger, .alert-danger { --tone-base: var(--tone-danger-base); --tone-fg: var(--tone-danger-fg); }
.surface-neutral, .alert-secondary, .alert-light { --tone-base: var(--tone-neutral-base); --tone-fg: var(--tone-neutral-fg); }
.surface-warning, .alert-warning { --tone-mix: 14%; }
.surface-neutral, .alert-secondary, .alert-light { --tone-mix: 4%; }
.surface-info, .surface-success, .surface-warning, .surface-danger, .surface-neutral,
.alert {
    background-color: color-mix(in srgb, var(--tone-base, var(--tone-neutral-base)) var(--tone-mix, 8%), var(--surface));
    border: 1px solid color-mix(in srgb, var(--tone-base, var(--tone-neutral-base)) 30%, var(--bs-border-color));
    color: var(--bs-body-color);
}
.surface-info, .surface-success, .surface-warning, .surface-danger, .surface-neutral {
    border-radius: var(--bs-border-radius-lg);
}
.alert {
    --bs-alert-color: var(--bs-body-color);
    --bs-alert-link-color: var(--tone-fg, var(--bs-body-color));
    border-radius: var(--bs-border-radius);
}
.tone-fg { color: var(--tone-fg); }
.text-warning { color: var(--tone-warning-fg) !important; }

/* Seções com divisor sutil no lugar de <hr> */
.section-divider {
    border-top: 1px solid var(--bs-border-color);
    margin: 2rem 0;
}

.text-muted-2 {
    color: var(--bs-secondary-color) !important;
}

/* Stepper horizontal do wizard de cadastro de imóvel (inspirado no
   componente Stepper do MUI, implementado em CSS puro — sem dependência). */
.wizard-stepper {
    display: flex;
    align-items: flex-start;
}

.wizard-step {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 1;
    min-width: 0;
    text-align: center;
}

.wizard-step-indicator {
    display: flex;
    align-items: center;
    width: 100%;
}

.wizard-step-circle {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    border: 2px solid var(--bs-border-color);
    color: var(--bs-secondary-color);
    font-weight: 600;
    font-size: 0.875rem;
    background: var(--bs-body-bg);
}

.wizard-step-connector {
    flex: 1;
    height: 2px;
    background: var(--bs-border-color);
}

.wizard-step-connector.is-invisible {
    background: transparent;
}

.wizard-step-connector.is-active {
    background: var(--accent);
}

.wizard-step.is-current .wizard-step-circle {
    border-color: var(--action-primary-bg);
    color: var(--action-primary-text);
    background: var(--action-primary-bg);
}

.wizard-step.is-completed .wizard-step-circle {
    border-color: var(--accent);
    color: var(--accent-text);
    background: var(--bs-body-bg);
}

.wizard-step-label {
    margin-top: 0.5rem;
    font-size: 0.8125rem;
    color: var(--bs-secondary-color);
}

.wizard-step.is-current .wizard-step-label {
    color: var(--bs-body-color);
    font-weight: 600;
}

.wizard-step-optional {
    display: block;
    font-size: 0.75rem;
    color: var(--bs-secondary-color);
}

/* Tabelas de especificação lado a lado: largura de rótulo fixa para os
   valores alinharem entre as tabelas, independente do texto do rótulo. */
.spec-table th {
    width: 45%;
}

/* Feedback de "observação salva" no checklist (ver
   properties/_checklist_step.html) — some sozinho depois de alguns
   segundos, sem precisar de JS pra isso. */
@keyframes checklist-note-saved-fade {
    0%, 70% {
        opacity: 1;
    }
    100% {
        opacity: 0;
        visibility: hidden;
    }
}

.checklist-note-feedback {
    animation: checklist-note-saved-fade 2.5s ease forwards;
}

/* display:flex só quando NÃO escondido — de propósito, sem usar a classe
   utilitária "d-flex" do Bootstrap aqui: ela usa !important, que ganha da
   regra nativa do atributo [hidden] (display:none, sem !important) e
   deixava o elemento visível mesmo com hidden setado via JS/template. */
.checklist-note-display:not([hidden]),
.checklist-note-form:not([hidden]) {
    display: flex;
}

/* Seta do painel colapsável de cada fase do checklist (ver
   property_detail.html) — o Bootstrap alterna a classe "collapsed" no
   próprio botão sozinho, só precisamos girar o ícone em cima dela. */
.checklist-phase-chevron {
    transition: transform 0.2s ease;
}

.checklist-phase-toggle.collapsed .checklist-phase-chevron {
    transform: rotate(-90deg);
}

/* Abas (nav-tabs): sem o azul padrão do Bootstrap, o item inativo usa o texto
   secundário da marca e o ativo (emphasis) se destaca por cor + borda. */
.nav-tabs .nav-link {
    --bs-nav-link-color: var(--text-secondary);
    --bs-nav-link-hover-color: var(--text-primary);
}

/* Barra de progresso: verde da marca (progresso é um dos papéis do verde). */
.progress {
    --bs-progress-bar-bg: var(--accent);
    --bs-progress-bg: color-mix(in srgb, var(--text-primary) 8%, var(--surface));
}

/* Ícone do rótulo de KPI (.stat-card): pequeno "chip" tingido de navy, discreto.
   O ícone é o primeiro <i> dentro do rótulo (.text-muted-2), sem mexer no HTML. */
.stat-card .text-muted-2:has(> .bi:first-child) {
    display: flex;
    align-items: center;
}
.stat-card .text-muted-2 > .bi:first-child {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    margin-right: 0.4rem;
    border-radius: 0.5rem;
    font-size: 0.95rem;
    color: var(--action-link);
    background-color: color-mix(in srgb, var(--text-primary) 8%, var(--surface));
}

/* O Bootstrap compila o azul padrão (#0d6efd) direto nestes componentes, sem
   passar por --bs-primary — então o remapeamento lá em cima não alcança. Cada um
   precisa ser apontado pra marca na mão. */
.form-check-input:checked,
.form-check-input[type="checkbox"]:indeterminate {
    background-color: var(--bs-primary);
    border-color: var(--bs-primary);
}
.dropdown-menu {
    --bs-dropdown-link-active-bg: var(--bs-primary);
    --bs-dropdown-link-active-color: #fff;
}
.pagination {
    --bs-pagination-active-bg: var(--bs-primary);
    --bs-pagination-active-border-color: var(--bs-primary);
    --bs-pagination-active-color: #fff;
    --bs-pagination-focus-box-shadow: 0 0 0 0.2rem rgba(var(--focus-ring-rgb), 0.25);
}
.list-group {
    /* Transparente: o item herda o fundo do card em volta. O padrão do Bootstrap
       (--bs-body-bg) só passava despercebido no claro, onde página e card são
       ambos brancos; no escuro virava uma faixa mais escura dentro do card. */
    --bs-list-group-bg: transparent;
    --bs-list-group-active-bg: var(--bs-primary);
    --bs-list-group-active-border-color: var(--bs-primary);
}
.nav-pills {
    --bs-nav-pills-link-active-bg: var(--bs-primary);
}

/* Cores fixas de status (ver STATUS_COLORS em property_extras.py). Adquirido
   mantém o azul padrão (distinto do teal/navy da marca e do verde de "pronto
   para venda"); vendido usa o estilo da ação primária — navy no claro, branco
   no escuro — pra fechar a sequência com o tom mais forte da marca. */
.text-bg-status-acquired {
    background-color: #0d6efd;
    color: #fff;
}
.text-bg-status-sold {
    background-color: var(--action-primary-bg);
    color: var(--action-primary-text);
}

/* Altura dos controles: 44px (brand guidelines v1.1, p. 10). Só o tamanho padrão —
   -sm (ações compactas em tabelas, dropdowns) e -lg ficam como estão. Feito por
   padding vertical (9px + linha de 24px + borda de 1px, dos dois lados = 44px) e
   não por min-height, pra não esticar botões com p-0 (ex.: .btn-link usado como
   texto clicável). */
.btn:not(.btn-sm):not(.btn-lg) {
    --bs-btn-padding-y: 0.5625rem;
}
.form-control:not(.form-control-sm):not(.form-control-lg),
.form-select:not(.form-select-sm):not(.form-select-lg),
.input-group:not(.input-group-sm):not(.input-group-lg) > .input-group-text {
    padding-top: 0.5625rem;
    padding-bottom: 0.5625rem;
}
/* O botão "Escolher arquivo" do input file compensa o padding do campo com margem
   negativa — precisa acompanhar o novo padding pra continuar preenchendo a altura. */
.form-control:not(.form-control-sm):not(.form-control-lg)::file-selector-button {
    padding-top: 0.5625rem;
    padding-bottom: 0.5625rem;
    margin-top: -0.5625rem;
    margin-bottom: -0.5625rem;
}

/* ---------------------------------------------------------------------------
   Acessibilidade (WCAG 2.1 AA) — telas públicas e de autenticação
   --------------------------------------------------------------------------- */

/* "Pular para o conteúdo": fora da tela até receber foco pelo teclado. */
.skip-link {
    position: absolute;
    left: 0.75rem;
    top: -4rem;
    z-index: 2000;
    padding: 0.75rem 1rem;
    min-height: 44px;
    border-radius: var(--bs-border-radius);
    background: var(--action-primary-bg);
    color: var(--action-primary-text);
    font-weight: 600;
    text-decoration: none;
}
.skip-link:focus {
    top: 0.75rem;
    color: var(--action-primary-text);
}
main[tabindex="-1"]:focus,
.modal[tabindex="-1"]:focus,
.offcanvas[tabindex="-1"]:focus {
    outline: none; /* foco programático do "pular para o conteúdo" — não é controle */
}

/* Foco visível em tudo que é interativo (links, botões, campos, accordions). */
body.site :is(a, button, input, select, textarea, summary, [tabindex]):focus-visible,
body.auth-page :is(a, button, input, select, textarea, summary, [tabindex]):focus-visible,
body.app :is(a, button, input, select, textarea, summary, [tabindex], [role="button"]):focus-visible {
    outline: 3px solid var(--focus-ring);
    outline-offset: 2px;
}

/* Página 404 compartilhada pelo site público e pelo app. O layout é
   independente das navegações principais pra continuar seguro mesmo quando
   a URL que falhou pertence a uma área interna. */
body.error-page {
    display: flex;
    min-height: 100vh;
    flex-direction: column;
    background:
        radial-gradient(720px 360px at 50% 20%, rgba(17, 175, 157, 0.16), transparent 68%),
        var(--bs-body-bg);
}
body.error-page :is(a, button, [tabindex]):focus-visible {
    outline: 3px solid var(--focus-ring);
    outline-offset: 3px;
}
.error-header {
    padding: 1.25rem 0;
}
.error-brand {
    display: inline-flex;
    min-height: 44px;
    align-items: center;
}
.error-main {
    display: flex;
    flex: 1;
    align-items: center;
    padding: 2rem 0 5rem;
}
.error-panel {
    max-width: 720px;
    margin: 0 auto;
    text-align: center;
}
.error-code {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(0.5rem, 2vw, 1rem);
    color: var(--text-primary);
    font-size: clamp(5rem, 18vw, 9rem);
    font-weight: 700;
    letter-spacing: -0.08em;
    line-height: 0.8;
}
.error-code-symbol {
    display: inline-flex;
    width: clamp(4rem, 14vw, 7rem);
    height: clamp(4rem, 14vw, 7rem);
    align-items: center;
    justify-content: center;
}
.error-code-symbol img {
    width: 100%;
    height: 100%;
}
.error-eyebrow {
    margin: 2rem 0 0.75rem;
    color: var(--accent-text);
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.error-panel h1 {
    margin-bottom: 1rem;
    font-size: clamp(2rem, 6vw, 3rem);
    font-weight: 700;
    letter-spacing: -0.035em;
}
.error-copy {
    max-width: 600px;
    margin: 0 auto;
    color: var(--bs-secondary-color);
    font-size: 1.1rem;
    line-height: 1.65;
}
.error-actions {
    display: flex;
    justify-content: center;
    gap: 0.75rem;
    margin-top: 2rem;
}
.error-actions .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
}
.error-help {
    margin-top: 2rem;
    color: var(--bs-secondary-color);
    font-size: 0.9rem;
}

@media (max-width: 575.98px) {
    .error-header { padding: 1rem 0; }
    .error-main { align-items: flex-start; padding: 3rem 0; }
    .error-actions { flex-direction: column; }
    .error-actions .btn { width: 100%; }
}

/* Área de toque de 44×44 sem mexer no tamanho do texto. `link-block`: link
   sozinho na linha, ganha altura real. `tap-target`: link no meio de uma
   frase, a área extra é um pseudo-elemento centrado (não empurra o texto). */
.link-block {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    min-width: 44px;
}
.tap-target {
    position: relative;
}
.tap-target::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: max(calc(100% + 0.5rem), 44px);
    height: 44px;
    transform: translate(-50%, -50%);
}

/* Bordas de campos e botão "outline" com 3:1 contra o fundo claro (WCAG 1.4.11);
   o cinza suave do tema (#e4e6eb, ~1,2:1) continua valendo pra cards e divisores. */
body.site .form-control,
body.site .form-select,
body.auth-page .form-control,
body.auth-page .form-select,
body.auth-page .form-check-input {
    border-color: #6E858F;
}
body.site .btn-outline-light,
body.auth-page .btn-outline-light {
    --bs-btn-border-color: #6E858F;
    --bs-btn-hover-border-color: #6E858F;
}


/* Refinamento de consistência (área autenticada) ------------------------------
   Toda superfície elevada (cards de KPI, de conteúdo, tabelas, fases do checklist)
   usa o mesmo par borda --bs-border-color + sombra --app-shadow-sm; nada define
   sombra própria. */

/* Fase atual do checklist: o Bootstrap pinta o card inteiro com border-primary
   (navy, parece campo focado). Aqui vira borda suave + faixa lateral verde
   (progresso); o badge "Fase atual" e a barra continuam como estão. */
.card.border-primary {
    --bs-border-opacity: 1;
    border-color: var(--bs-border-color) !important;
}
.card.border-primary:has(.checklist-phase-toggle) {
    border-color: color-mix(in srgb, var(--accent) 35%, var(--bs-border-color)) !important;
    box-shadow: inset 4px 0 0 var(--accent), var(--app-shadow-sm);
}
.card.border-primary:has(.checklist-phase-toggle) > .card-body {
    background: color-mix(in srgb, var(--accent) 2.5%, var(--surface));
    border-radius: inherit;
}

/* Miniaturas/ícones-placeholder repetidos em tabelas: mais claros e sem contraste
   forte, pra não competirem com os dados da linha. */
body.app .table .bg-secondary-subtle {
    background-color: color-mix(in srgb, var(--text-primary) 5%, var(--surface)) !important;
    color: color-mix(in srgb, var(--text-primary) 45%, var(--surface));
}
/* Chip de ícone dos KPIs um pouco menor e mais claro. */
.stat-card .text-muted-2 > .bi:first-child {
    width: 1.6rem;
    height: 1.6rem;
    font-size: 0.85rem;
    background-color: color-mix(in srgb, var(--text-primary) 6%, var(--surface));
}


/* Acessibilidade da área autenticada ------------------------------------------
   Área de toque: botões só com ícone (editar/excluir em tabelas, aprovar/recusar)
   e controles pequenos da topbar ficam com pelo menos 36×36px (a dica de 44px do
   guia é atendida nos botões de tamanho normal; aqui a tabela é densa). */
.btn-icon {
    min-width: 2.25rem;
    min-height: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.app-topbar .btn-sm {
    min-height: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
}
.app-topbar .avatar-btn {
    min-width: 2.25rem;
    min-height: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.sidebar-nav .nav-link { min-height: 2.5rem; }
/* Dica sobre foto ampliável: o cursor já indica, o foco aparece pelo outline. */
.photo-thumb:focus-visible { outline-offset: -3px; }
@media (prefers-reduced-motion: reduce) {
    .checklist-phase-chevron, .img-skeleton > img { transition: none; }
    .img-skeleton { animation: none; }
}


/* Navegação local do imóvel (properties/_property_nav.html) ------------------
   Grupos + sub-abas numa barra fixa logo abaixo da topbar (que tem ~3,8rem).
   Blocos (grupos / sub-abas) quebram de linha inteiros, nunca um item sozinho.
   No mobile só aparece o <select>. */
:root { --app-topbar-h: 3.8125rem; }
.property-nav {
    position: sticky;
    top: var(--app-topbar-h);
    /* Abaixo dos dropdowns do Bootstrap (1000) e da topbar (1020): o menu "Ações" do cabeçalho abre por cima desta barra. */
    z-index: 990;
    margin: 0 -0.75rem 1rem;
    padding: 0.5rem 0.75rem;
    background-color: var(--app-bg);
    border-bottom: 1px solid var(--app-line);
}
.tab-content > .tab-pane { scroll-margin-top: calc(var(--app-topbar-h) + 4.5rem); }
.property-nav-select { font-weight: 600; }
.property-nav-desktop {
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1.25rem;
}
.property-groups {
    display: flex;
    flex: 0 0 auto;
    gap: 0.25rem;
    padding: 0.2rem;
    border-radius: var(--bs-border-radius);
    background-color: color-mix(in srgb, var(--text-primary) 6%, transparent);
}
.property-group {
    min-height: 2.25rem;
    padding: 0.25rem 0.85rem;
    border: 0;
    border-radius: var(--bs-border-radius-sm);
    background: transparent;
    color: var(--bs-secondary-color);
    font-weight: 500;
    white-space: nowrap;
}
.property-group:hover { color: var(--bs-body-color); }
.property-group.is-current {
    background-color: var(--action-primary-bg);
    color: var(--action-primary-text);
    font-weight: 600;
}
.property-subnav {
    flex: 1 1 auto;
    flex-wrap: nowrap;
    gap: 0.25rem;
    min-width: 0;
}
.property-subnav[hidden] { display: none !important; }
.property-subnav .nav-link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 2.25rem;
    padding: 0.25rem 0.75rem;
    border: 1px solid transparent;
    border-bottom-width: 2px;
    border-radius: var(--bs-border-radius-sm);
    color: var(--bs-secondary-color);
    font-weight: 500;
    white-space: nowrap;
}
.property-subnav .nav-link:hover { color: var(--bs-body-color); background-color: color-mix(in srgb, var(--text-primary) 6%, transparent); }
.property-subnav .nav-link.active,
.property-subnav .nav-link.pre-active {
    color: var(--action-link);
    font-weight: 600;
    background-color: var(--surface);
    border-color: var(--app-line);
    border-bottom: 2px solid var(--action-link); /* sinal além da cor: barra sob a seção atual */
    box-shadow: var(--app-shadow-xs);
}
/* Antes do JS assumir (hash na URL): a aba "Visão geral" ainda é .active de
   verdade, mas visualmente quem manda é a .pre-active. */
.property-nav.has-pre-active .nav-link.active:not(.pre-active) {
    color: var(--bs-secondary-color);
    font-weight: 500;
    background-color: transparent;
    border-color: transparent;
    box-shadow: none;
}
@media (max-width: 991.98px) {
    .property-subnav { flex-wrap: wrap; }
}

/* Estado vazio reutilizável (templates/partials/_empty_state.html) ------------ */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    max-width: 100%;
    padding: 2.5rem 1.5rem;
    text-align: center;
    background-color: var(--surface);
    border: 1px dashed color-mix(in srgb, var(--text-primary) 25%, var(--bs-border-color));
    border-radius: var(--bs-border-radius-lg);
}
.empty-state-compact {
    padding: 1.5rem 1rem;
    background: transparent;
    border: 0;
}
.empty-state-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    margin-bottom: 1rem;
    border-radius: 0.85rem;
    font-size: 1.4rem;
    color: var(--action-link);
    background-color: color-mix(in srgb, var(--text-primary) 7%, var(--surface));
}
.empty-state-title {
    margin: 0 0 0.35rem;
    font-size: 1.05rem;
    font-weight: 600;
}
.empty-state-text {
    max-width: 34rem;
    margin: 0 0 1.25rem;
    color: var(--bs-secondary-color);
}
.empty-state-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem;
}
@media (max-width: 575.98px) {
    .empty-state { padding: 2rem 1rem; }
    .empty-state-actions { flex-direction: column; align-self: stretch; }
}

/* Listas de cards (versão mobile/intermediária de tabelas densas) ---------------
   Abaixo de `lg` (992px — com a sidebar de 240px, o conteúdo fica estreito já em
   tablets) as tabelas viram <ul class="data-list"> de cards com os MESMOS dados;
   de `lg` pra cima vale a tabela. Cada card: cabeçalho (título + destaque),
   campos em <dl> e ações com alvo de toque de 44px. */
.data-list {
    display: grid;
    gap: 0.75rem;
    margin: 0;
    padding: 0;
    list-style: none;
}
.data-card {
    position: relative;
    padding: 1rem;
    background-color: var(--surface);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    box-shadow: var(--app-shadow-sm);
}
.data-card-head {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
}
.data-card-main { flex: 1 1 auto; min-width: 0; }
.data-card-title {
    display: block;
    font-weight: 600;
    overflow-wrap: anywhere;
}
.data-card-sub {
    margin-top: 0.15rem;
    color: var(--bs-secondary-color);
    font-size: 0.875rem;
}
.data-card-amount {
    flex: 0 0 auto;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.data-card-badges { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.6rem; }
.data-card-fields {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem 1rem;
    margin: 0.85rem 0 0;
}
.data-card-fields > div { min-width: 0; }
.data-card-fields dt {
    color: var(--bs-secondary-color);
    font-size: 0.75rem;
    font-weight: 500;
}
.data-card-fields dd { margin: 0; overflow-wrap: anywhere; }
.data-card-fields .is-wide { grid-column: 1 / -1; }
.data-card-highlight { font-weight: 600; }
.data-card-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.85rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--bs-border-color);
}
.data-card-actions form { margin: 0; }
.data-card-actions .btn { min-height: 2.75rem; display: inline-flex; align-items: center; gap: 0.35rem; }
/* Excluir: discreto (texto vermelho, sem preenchimento) — o destaque fica na ação principal. */
.data-card-actions .btn-delete { color: var(--bs-danger); font-weight: 500; text-decoration: none; }
.data-card-actions .btn-delete:hover { text-decoration: underline; }
.data-card-thumb { flex: 0 0 auto; }
/* Barras de ações das abas (Nova transação, filtros de custo extra…): alvo de toque de
   44px nas larguras em que a lista vira cards. */
@media (max-width: 991.98px) {
    .tab-content .tab-pane .btn-sm {
        min-height: 2.75rem;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
}

/* Listas de pessoas (membros, convites, solicitações da organização) --------------
   Linhas flexíveis que quebram sozinhas: nome/e-mail à esquerda, ações à direita, e
   embaixo em telas estreitas — sem tabela, sem rolagem horizontal. */
.person-list { margin: 0; padding: 0; list-style: none; }
.person-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1rem;
    padding: 0.65rem 0;
    border-top: 1px solid var(--bs-border-color);
}
.person-row:first-child { border-top: 0; padding-top: 0; }
.person-row:last-child { padding-bottom: 0; }
.person-main { flex: 1 1 14rem; min-width: 0; display: flex; flex-direction: column; }
.person-name { font-weight: 500; overflow-wrap: anywhere; }
.person-sub { color: var(--bs-secondary-color); font-size: 0.875rem; overflow-wrap: anywhere; }
.person-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-left: auto; }
.person-actions form { margin: 0; }
.person-actions .btn { min-height: 2.75rem; display: inline-flex; align-items: center; gap: 0.35rem; }

/* Listagem de imóveis: filtros e linha clicável ------------------------------ */
.property-filters {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: 0.75rem 1rem;
    align-items: end;
    margin-bottom: 1rem;
}
.property-filter-search { grid-column: span 2; }
.property-filter .form-label { margin-bottom: 0.25rem; font-size: 0.8125rem; color: var(--bs-secondary-color); }
.property-filter-submit .btn { width: 100%; }
@media (max-width: 575.98px) {
    /* Celular: busca em linha inteira, Status + Responsável lado a lado, depois Ordenar e o botão. */
    .property-filters { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .property-filter-search, .property-filter:nth-child(4), .property-filter-submit { grid-column: 1 / -1; }
}
.data-card-highlight .fst-italic { font-weight: 400; font-size: 0.9rem; }
/* Linha inteira como área de acesso (o link do endereço se estica por cima da linha,
   sem cobrir outros links/botões, que ficam acima com position: relative). */
.row-link { position: relative; cursor: pointer; }
.row-link:focus-within { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.row-link a:not(.stretched-link), .row-link button { position: relative; z-index: 2; }

/* Tons dos KPIs do painel: só o chip do ícone (e o número, quando é resultado
   positivo/negativo) muda de tom; o número continua sendo o protagonista. */
.stat-card { --kpi-base: var(--text-primary); --kpi-fg: var(--action-link); }
.stat-card.kpi-teal { --kpi-base: var(--brand-mint); --kpi-fg: var(--border-focus); }
.stat-card.kpi-success { --kpi-base: var(--brand-green); --kpi-fg: var(--tone-success-fg); }
.stat-card.kpi-danger { --kpi-base: var(--tone-danger-base); --kpi-fg: var(--tone-danger-fg); }
[data-bs-theme="dark"] .stat-card.kpi-teal { --kpi-fg: var(--brand-mint); }
.stat-card .text-muted-2 > .bi:first-child {
    color: var(--kpi-fg);
    background-color: color-mix(in srgb, var(--kpi-base) 13%, var(--surface));
}

/* Detalhe do imóvel: visão geral, checklist, aquisição e especificação -----------
   O card precisa caber "R$ 12.500.000,00" (o maior valor esperado) sem quebrar
   entre dígitos e sem estourar a largura. Duas peças resolvem isso juntas:
   - minmax(14.5rem, …) — coluna nunca fica mais estreita do que cabe esse texto
     no tamanho de fonte máximo (medido ~221px com padding; 14.5rem = 232px);
     com poucas colunas cabendo, o auto-fit já reduz pra 2 colunas antes do
     mobile sozinho, sem precisar de um breakpoint dedicado.
   - min-width: 0 no item — sem isso, o texto (que nunca quebra, ver
     .metric-value) empurraria a coluna pra mais larga que o minmax quando não
     coubesse, e isso podia vazar num scroll horizontal da página inteira; com
     min-width: 0 a coluna respeita o minmax e, no pior caso (valor helper
     maior que o planejado), só o próprio texto estoura visualmente dentro do
     card — nunca a página. */
.metric-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14.5rem, 1fr));
    gap: 0.75rem;
}
.metric {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.9rem 1rem;
    background-color: var(--surface);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    box-shadow: var(--app-shadow-sm);
    min-width: 0;
}
.metric-label { color: var(--bs-secondary-color); font-size: 0.8125rem; }
/* overflow-wrap: normal (padrão) de propósito — "anywhere" quebrava valores
   monetários no meio dos dígitos (ex.: "R$ 246.830,0" numa linha e "0" na
   seguinte) quando a coluna ficava mais estreita que o texto. Não quebrar é
   seguro porque a largura mínima da coluna (.metric-grid, acima) já garante
   espaço pro maior valor esperado. */
.metric-value { font-size: clamp(1.1rem, 4.8vw, 1.35rem); font-weight: 600; line-height: 1.2; font-variant-numeric: tabular-nums; }
.metric-empty { font-size: 0.95rem; font-weight: 400; }
.spec-highlights { margin-bottom: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(7.25rem, 1fr)); }
.spec-highlights .metric { box-shadow: none; background-color: color-mix(in srgb, var(--text-primary) 3%, var(--surface)); }

.info-card-title {
    margin: 0 0 0.75rem;
    color: var(--bs-secondary-color);
    font-size: 0.9375rem;
    font-weight: 600;
}
.info-card-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    margin-bottom: 0.75rem;
}
.info-card-head .info-card-title { margin: 0; }
.info-card-actions { display: flex; align-items: center; gap: 0.5rem; }
.info-card-actions form { margin: 0; }
.info-group-title {
    margin: 1.1rem 0 0.5rem;
    color: var(--bs-secondary-color);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
/* Lista de informações compacta: rótulo e valor lado a lado, perto um do outro. */
.info-list { margin: 0; }
.info-list > div {
    display: grid;
    grid-template-columns: minmax(7rem, 11rem) minmax(0, 1fr);
    gap: 0.25rem 1rem;
    padding: 0.4rem 0;
    border-top: 1px solid var(--bs-border-color);
}
.info-list > div:first-child { border-top: 0; padding-top: 0; }
.info-list dt { color: var(--bs-secondary-color); font-weight: 500; }
.info-list dd { margin: 0; overflow-wrap: anywhere; }
@media (max-width: 575.98px) {
    .info-list > div { grid-template-columns: 1fr; gap: 0; }
    .info-list dt { font-size: 0.8125rem; }
}
.notes-text { white-space: normal; }
.property-map { height: 320px; border-radius: var(--bs-border-radius); }
.pane-narrow { width: 100%; max-width: 1050px; }  /* detalhes simples: alinhado à esquerda, sem centralizar nem esticar */
.pane-hint { max-width: 46rem; margin: 0 0 0.75rem; color: var(--bs-secondary-color); font-size: 0.875rem; }
.chip-list { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0; padding: 0; list-style: none; }
.chip-list li {
    padding: 0.2rem 0.65rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 999px;
    background-color: color-mix(in srgb, var(--text-primary) 3%, var(--surface));
    font-size: 0.875rem;
}
.spec-missing {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0.75rem;
    margin: 1.1rem 0 0;
    font-size: 0.875rem;
}

/* Checklist */
.checklist-intro { width: 100%; max-width: 72ch; margin: 0 0 1rem; color: var(--bs-secondary-color); font-size: 0.9rem; }
.checklist-step { padding: 0.55rem 0.5rem; border-radius: var(--bs-border-radius-sm); }
.checklist-step.is-done { background-color: color-mix(in srgb, var(--accent) 6%, transparent); }
.checklist-step-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.35rem 1rem; }
.checklist-step-label { min-width: 0; }
.checklist-step-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.75rem; }
.checklist-step-actions form { margin: 0; }
/* Ações secundárias (desfazer, observação): discretas, sem borda, só destacam no hover/foco. */
.checklist-quiet {
    padding: 0.15rem 0.4rem;
    color: var(--bs-secondary-color);
    font-size: 0.8125rem;
    text-decoration: none;
    min-height: 2rem;
}
.checklist-quiet:hover, .checklist-quiet:focus-visible { color: var(--action-link); text-decoration: underline; }
.checklist-note-toggle { min-width: 2rem; }
/* Fase totalmente concluída (a barra recebe .bg-success, inclusive após ações htmx): card compacto e verde suave. */
.checklist-phase:not(.border-primary):has(.progress-bar.bg-success) {
    background-color: color-mix(in srgb, var(--accent) 4%, var(--surface));
    border-color: color-mix(in srgb, var(--accent) 25%, var(--bs-border-color));
    box-shadow: none;
}
.checklist-phase:not(.border-primary):has(.progress-bar.bg-success) > .card-body { padding: 0.6rem 1rem; }
.checklist-phase:has(.progress-bar.bg-success) [id^="checklist-count-"] { color: var(--tone-success-fg) !important; }

/* Mensagens temporárias: saída suave (a altura colapsa) para a página não "pular" quando somem. */
.app-messages .alert { transition: height 0.3s ease, opacity 0.3s ease, margin 0.3s ease, padding 0.3s ease, border-width 0.3s ease; }
.app-messages .alert.is-closing { height: 0 !important; opacity: 0; margin-top: 0 !important; margin-bottom: 0 !important; padding-top: 0 !important; padding-bottom: 0 !important; border-width: 0 !important; overflow: hidden; }
@media (prefers-reduced-motion: reduce) { .app-messages .alert { transition: none; } }
/* Observação do checklist: com observação, ícone preenchido e mais escuro (forma + cor). */
.checklist-note-toggle.has-note { color: var(--action-link); }
/* Observações longas (palavras/links sem espaço) não podem empurrar a página pra fora do viewport. */
.checklist-note-display p { min-width: 0; overflow-wrap: anywhere; }
.notes-text { overflow-wrap: anywhere; }

/* Aba Transações: cabeçalhos ordenáveis, filtros e resumo */
.sort-link { color: inherit; text-decoration: none; white-space: nowrap; }
.sort-link:hover, .sort-link:focus-visible { color: var(--action-link); text-decoration: underline; }
th[aria-sort="ascending"] .sort-link, th[aria-sort="descending"] .sort-link { color: var(--action-link); }
.tx-filters { grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); }
.tx-summary { margin-bottom: 1rem; }
.tx-soma-detalhe { white-space: nowrap; }

/* Orçamentos: desvio planejado × registrado, card clicável e zona de exclusão */
.desvio { font-weight: 600; }
.desvio-acima { color: var(--tone-danger-fg); }
.desvio-abaixo { color: var(--tone-success-fg); }
.desvio-igual { color: var(--bs-secondary-color); }
/* Resumo do orçamento ainda incompleto (ver renovation_extras.desvio_orcamento): nunca verde —
   o valor que falta registrar não é economia confirmada, só ainda não foi lançado. */
.desvio-neutro { color: var(--bs-secondary-color); }
/* Situação de pagamento do item (ver renovation_extras.situacao_pagamento) — ícone + texto,
   nunca só a cor. */
.situacao-pagamento { display: inline-flex; align-items: center; gap: 0.35rem; font-weight: 600; font-size: 0.875rem; }
.situacao-pagamento-sucesso { color: var(--tone-success-fg); }
.situacao-pagamento-atencao { color: var(--tone-warning-fg); }
.situacao-pagamento-perigo { color: var(--tone-danger-fg); }
.situacao-pagamento-neutro { color: var(--bs-secondary-color); }
/* Finalidade do gasto do item (ver renovation_extras.finalidade_item): etiqueta discreta com ícone
   e texto — a diferença entre as finalidades nunca depende só da cor. */
.finalidade { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.8rem; font-weight: 600; line-height: 1.3; }
.finalidade-essencial { color: var(--tone-info-fg); }
.finalidade-melhoria { color: var(--tone-success-fg); }
.finalidade-opcao { padding: 0.5rem 0.75rem 0.5rem 2.25rem; border: 1px solid var(--bs-border-color); border-radius: 0.5rem; margin-bottom: 0.5rem; }
.finalidade-opcao:has(input:checked) { border-color: var(--bs-primary); }
.finalidade-opcao:focus-within { outline: 2px solid var(--bs-primary); outline-offset: 1px; }
.finalidade-opcao .form-check-label { font-weight: 600; }
.finalidade-opcao .form-text { margin-top: 0.1rem; }
/* Resumo por finalidade: no mobile cabe sem rolagem horizontal — o "R$" sai da vista (continua lido
   por leitores de tela) e o cabeçalho da coluna segue dizendo do que se trata. */
@media (max-width: 575.98px) {
    .composition-table.finalidade-table th, .composition-table.finalidade-table td { padding: 0.35rem 0.3rem; font-size: 0.8rem; }
    .composition-table.finalidade-table thead th { font-size: 0.65rem; }
    .finalidade-rs { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
}
.budget-progress { margin-top: 0.85rem; }
/* Aviso de cadastro com orçamento inicial (properties/_aviso_cadastro.html): a ação é secundária
   (botão pequeno no desktop) e ganha alvo de toque de 44×44px no celular/tablet e em telas de toque.
   O texto fica acima da ação, então em telas estreitas tudo se empilha sem espremer o botão. */
.aviso-cadastro > .flex-grow-1 { min-width: 0; overflow-wrap: anywhere; }
.aviso-cadastro .aviso-cadastro-acao {
    display: inline-flex; align-items: center; justify-content: center; gap: 0.35rem;
    /* Cores do tema (tom de sucesso legível nos dois temas): o verde padrão do Bootstrap fica abaixo de 4,5:1 no escuro. */
    --bs-btn-color: var(--tone-success-fg);
    --bs-btn-border-color: var(--tone-success-fg);
    --bs-btn-hover-color: var(--tone-success-fg);
    --bs-btn-hover-bg: color-mix(in srgb, var(--tone-success-fg) 14%, transparent);
    --bs-btn-hover-border-color: var(--tone-success-fg);
    --bs-btn-active-color: var(--tone-success-fg);
    --bs-btn-active-bg: color-mix(in srgb, var(--tone-success-fg) 22%, transparent);
    --bs-btn-active-border-color: var(--tone-success-fg);
}
@media (max-width: 991.98px), (pointer: coarse) {
    .aviso-cadastro .aviso-cadastro-acao { min-height: 2.75rem; min-width: 2.75rem; }
    /* Botão "Fechar aviso": a área interativa vai de 24×24px (padrão do Bootstrap) para 44×44px, mas o
       "x" continua do mesmo tamanho (16px, centralizado) e no mesmo lugar: a margem negativa de 10px
       (= (44 − 24) / 2) devolve o excesso para o padding do aviso, então o aviso não cresce, o botão
       não passa da borda (sobram 6px do padding de 16px) e o texto — que é flex — apenas cede 10px. */
    .aviso-cadastro > .btn-close {
        box-sizing: border-box;
        width: 2.75rem;
        height: 2.75rem;
        padding: 0;
        margin: -0.625rem -0.625rem -0.625rem 0;
        background-size: 1em auto;
        background-position: center;
    }
}
.budget-card { transition: border-color 0.15s ease, box-shadow 0.15s ease; }
.budget-card:hover, .budget-card:focus-within { border-color: color-mix(in srgb, var(--text-primary) 35%, var(--bs-border-color)); box-shadow: 0 2px 8px rgba(12, 47, 64, 0.1); }
/* Menu "Ações" do cabeçalho do orçamento (mesmo dropdown do imóvel): itens com alvo de toque de 44px
   no celular, onde o dropdown padrão (32px) fica apertado. */
@media (max-width: 575.98px) {
    .budget-header-actions .dropdown-item { display: flex; align-items: center; gap: 0.5rem; min-height: 44px; }
}
.budget-card-title { font-weight: 600; color: var(--action-link); text-decoration: none; overflow-wrap: anywhere; }
.budget-card-title:hover { text-decoration: underline; }
.budget-card-cta { margin-top: 0.85rem; color: var(--action-link); font-size: 0.875rem; font-weight: 600; }
.budget-card:hover .budget-card-cta i { transform: translateX(3px); }
.budget-card-cta i { display: inline-block; transition: transform 0.15s ease; }
@media (prefers-reduced-motion: reduce) { .budget-card, .budget-card-cta i { transition: none; } .budget-card:hover .budget-card-cta i { transform: none; } }
/* Cards de custos programados (aba do imóvel) ----------------------------------------
   Uma coluna no celular e em larguras médias; duas colunas só a partir de `xl` (1200px — com a
   sidebar de 240px sobram ~900px de conteúdo, o suficiente para dois cards legíveis). Com um único
   card (.is-single) a lista fica em uma coluna. `align-items: start`: cada card tem a altura do
   próprio conteúdo (sem esticar para igualar o vizinho). Sem rolagem interna: nenhum overflow. */
.scheduled-list {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: 0.75rem;
    margin: 0;
    padding: 0;
    list-style: none;
}
/* Um único card: uma coluna, sem esticar por toda a área útil. */
.scheduled-list.is-single { max-width: 52rem; }
@media (min-width: 1200px) {
    .scheduled-list:not(.is-single) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.scheduled-card {
    position: relative; /* âncora do .stretched-link: o card inteiro vira área de clique */
    container-type: inline-size; /* o resumo financeiro se reorganiza pela largura do PRÓPRIO card (ver @container abaixo) */
    min-width: 0;
    padding: 0.85rem 1rem;
    background-color: var(--surface);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    box-shadow: var(--app-shadow-sm);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.scheduled-card:hover { border-color: color-mix(in srgb, var(--text-primary) 35%, var(--bs-border-color)); }
.scheduled-card:focus-within { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.scheduled-card-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 0.5rem 1rem; }
/* O valor principal desce para uma linha própria quando título + valor não cabem lado a lado (título longo ou valor grande). */
.scheduled-card-main { flex: 1 1 10rem; min-width: 0; }
.scheduled-card-title { margin: 0; font-size: 1rem; font-weight: 600; overflow-wrap: anywhere; }
.scheduled-card .data-card-badges { margin-top: 0.4rem; }
/* Valor principal (mensal ou total): o maior e mais forte número do card. */
.scheduled-card-principal { flex: 0 0 auto; max-width: 100%; margin: 0 0 0 auto; text-align: right; }
.scheduled-card-principal dt { color: var(--bs-secondary-color); font-size: 0.75rem; font-weight: 500; }
.scheduled-card-principal dd { margin: 0; font-size: 1.25rem; font-weight: 700; line-height: 1.2; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.scheduled-card-details {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 0.5rem 1rem;
    margin: 0.65rem 0 0;
}
.scheduled-card-details > div { min-width: 0; }
.scheduled-card-details dt, .scheduled-card-summary dt { color: var(--bs-secondary-color); font-size: 0.75rem; font-weight: 500; }
.scheduled-card-details dd { margin: 0; overflow-wrap: anywhere; }
.scheduled-card-progress { margin-top: 0.65rem; }
.scheduled-card-progress-text { margin: 0 0 0.3rem; font-size: 0.9375rem; }
.scheduled-card-progress .progress { height: 0.5rem; }
/* Resumo financeiro secundário: Registrado, Pago e Pendente sempre juntos, em um bloco discreto. */
.scheduled-card-summary {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.5rem;
    margin: 0.65rem 0 0;
    padding: 0.5rem 0.65rem;
    background-color: var(--app-thead-bg);
    border-radius: var(--bs-border-radius);
}
.scheduled-card-summary > div { min-width: 0; }
.scheduled-card-summary dd { margin: 0; font-size: 0.875rem; font-weight: 500; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
/* Ação explícita: o link (único do card) se estica sobre o card todo; alvo de toque de 44px. */
.scheduled-card-cta { margin-top: 0.4rem; }
.scheduled-card-link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 2.75rem;
    color: var(--action-link);
    font-size: 0.875rem;
    font-weight: 600;
    text-decoration: none;
}
.scheduled-card-link:hover { text-decoration: underline; }
.scheduled-card-link i { transition: transform 0.15s ease; }
.scheduled-card:hover .scheduled-card-link i { transform: translateX(3px); }
.scheduled-card-link:focus-visible { outline: none; } /* o foco aparece no card (:focus-within), com o mesmo anel dos demais controles */
@media (prefers-reduced-motion: reduce) { .scheduled-card, .scheduled-card-link i { transition: none; } .scheduled-card:hover .scheduled-card-link i { transform: none; } }
/* Card estreito (celular): Registrado/Pago/Pendente viram linhas rótulo → valor. Valores grandes
   (R$ 12.345.678,90) nunca quebram no meio nem são truncados, e o grupo continua junto. */
@container (max-width: 25rem) {
    .scheduled-card-summary { grid-template-columns: minmax(0, 1fr); gap: 0.2rem; }
    .scheduled-card-summary > div { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; }
    .scheduled-card-summary dd { text-align: right; }
}
@media (max-width: 575.98px) {
    .scheduled-card { padding: 0.8rem 0.85rem; }
}
.breadcrumb-nav { margin-bottom: 0.75rem; font-size: 0.875rem; }
.breadcrumb-nav .breadcrumb { margin: 0; flex-wrap: wrap; }
.danger-zone { margin-top: 2rem; padding: 1rem 1.25rem; }
.danger-zone h2 { margin: 0 0 0.25rem; font-size: 1rem; font-weight: 600; color: var(--tone-danger-fg); }
.metric-value-sm { font-size: 0.95rem; font-weight: 400; line-height: 1.4; }
.metric-unit { font-size: 0.9rem; font-weight: 400; color: var(--bs-secondary-color); }
.metric .budget-progress { margin-top: 0.25rem; }
/* Resumo do detalhe do orçamento: dois grupos (Planejamento/Execução), cada um com seu próprio
   .metric-grid auto-fit — não precisa mais de override de colunas fixas (.budget-summary, 6
   métricas numa grade só, foi retirado quando o resumo virou sempre as duas seções; o espaço
   entre as seções já vem do mb-4 da primeira, no template). */

/* Composição do orçamento: lista compacta (não são cards) */
.composition-table { font-size: 0.9rem; }
.composition-table tfoot th, .composition-table tfoot td { border-top: 2px solid var(--bs-border-color); }
@media (max-width: 575.98px) {
    .composition-table th, .composition-table td { padding: 0.4rem 0.5rem; font-size: 0.85rem; }
    .composition-table thead th { font-size: 0.7rem; letter-spacing: 0; }
}

/* Cenários de venda ------------------------------------------------------------ */
/* Tratamento pelo sinal: positivo = sucesso, negativo = atenção/perigo (o sinal "-" continua no número). */
.tom-positivo { color: var(--tone-success-fg); }
.tom-negativo { color: var(--tone-danger-fg); }

/* Melhor resultado: selo com texto + ícone, e fundo verde bem suave (nunca só a cor). */
.best-badge {
    background-color: color-mix(in srgb, var(--tone-success-base) 16%, var(--surface));
    color: var(--tone-success-fg);
    border: 1px solid color-mix(in srgb, var(--tone-success-base) 40%, var(--bs-border-color));
    font-weight: 600;
}
.scenario-table .is-best, .scenario-compare .is-best > * { background-color: color-mix(in srgb, var(--tone-success-base) 7%, var(--surface)); }
.data-card.is-best { border-color: color-mix(in srgb, var(--tone-success-base) 45%, var(--bs-border-color)); box-shadow: inset 4px 0 0 var(--tone-success-base), var(--app-shadow-sm); }

/* Simulador de custo adicional: opções em "chips"; a selecionada usa a cor da marca + ícone de check. */
.cost-simulator { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-bottom: 1rem; }
.cost-simulator-label { color: var(--bs-secondary-color); font-size: 0.875rem; }
.chip-option {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    min-height: 2.25rem;
    padding: 0.25rem 0.85rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 999px;
    background-color: var(--surface);
    color: var(--action-link);
    font-size: 0.875rem;
    font-weight: 500;
    text-decoration: none;
}
.chip-option:hover { background-color: color-mix(in srgb, var(--text-primary) 6%, var(--surface)); color: var(--action-link); }
.chip-option.is-selected { background-color: var(--action-primary-bg); border-color: var(--action-primary-bg); color: var(--action-primary-text); font-weight: 600; }
.cost-simulator-custom { display: flex; align-items: center; gap: 0.35rem; margin: 0; }
.cost-simulator-custom .input-group { width: 10rem; flex-wrap: nowrap; }

/* Comparativo compacto: barra proporcional ao lucro (escala visual; o valor está sempre escrito). */
.scenario-bar-row { display: flex; align-items: center; gap: 0.6rem; }
.scenario-bar-track { flex: 1 1 auto; min-width: 4rem; height: 8px; border-radius: 4px; background-color: color-mix(in srgb, var(--text-primary) 7%, var(--surface)); overflow: hidden; }
.scenario-bar { display: block; height: 100%; border-radius: 4px; background-color: var(--tone-success-base); }
.scenario-bar.is-negative { background-color: var(--tone-danger-base); }

/* Ações editar/excluir discretas: sem borda nem cor até o hover/foco. */
.btn-quiet { background: transparent; border-color: transparent; color: var(--bs-secondary-color); }
.btn-quiet:hover, .btn-quiet:focus-visible { background-color: color-mix(in srgb, var(--text-primary) 6%, transparent); color: var(--action-link); border-color: transparent; }
.btn-quiet-danger:hover, .btn-quiet-danger:focus-visible { color: var(--bs-danger); }

.scenario-note { display: flex; gap: 0.6rem; align-items: flex-start; font-size: 0.9rem; }

/* Comparativo dos cenários no celular: sem rolagem horizontal (selo quebra de linha, barra some) */
.scenario-compare .scenario-bar-row strong { position: relative; }
@media (max-width: 575.98px) {
    .scenario-compare th[scope="row"] { white-space: normal !important; }
    .scenario-compare .best-badge { display: inline-block; margin-top: 0.15rem; }
    .scenario-compare .scenario-bar-track { display: none; }
    .scenario-compare .scenario-bar-row { justify-content: flex-end; }
    .scenario-compare thead th:nth-child(2) { text-align: right; }
    .scenario-compare .table > :not(caption) > * > * { padding-left: 0.5rem; padding-right: 0.5rem; }
    .scenario-compare thead th { font-size: 0.68rem; }
    .scenario-compare table { font-size: 0.85rem; }
}

/* Matriz de cenários: com muitos cenários rola na horizontal e a coluna das métricas fica fixa */
.scenario-table th:first-child { position: sticky; left: 0; z-index: 1; min-width: 11rem; background-color: var(--surface); box-shadow: 1px 0 0 var(--border-subtle, rgba(0, 0, 0, .08)); }
.scenario-table tr.table-active th:first-child { background-color: color-mix(in srgb, var(--text-primary) 6%, var(--surface)); }
.scenario-table th:not(:first-child), .scenario-table td { min-width: 9.5rem; }
.scenario-disclaimer { max-width: 60ch; }
/* Estado vazio com sugestões */
.scenario-suggestions { display: grid; gap: 0.35rem; max-width: 22rem; margin: 0 auto 1rem; padding: 0; }
.scenario-suggestions li { display: flex; justify-content: space-between; gap: 1rem; padding: 0.4rem 0.75rem; border-radius: var(--bs-border-radius); background-color: color-mix(in srgb, var(--text-primary) 5%, var(--surface)); }

/* Nome do cenário: secundário e compacto, acima/ao lado do preço */
.scenario-name { display: block; max-width: 11rem; font-size: 0.72rem; font-weight: 500; line-height: 1.2; color: var(--bs-secondary-color); white-space: normal; overflow-wrap: anywhere; }
.scenario-name-inline { font-weight: 600; overflow-wrap: anywhere; }

/* Fornecedores, organização e perfil (item 11) */
.contact-whatsapp { display: inline-flex; align-items: center; gap: 0.25rem; margin-left: 0.5rem; padding: 0.1rem 0.5rem; border: 1px solid color-mix(in srgb, var(--tone-success-base) 40%, transparent); border-radius: 999px; font-size: 0.8125rem; font-weight: 500; text-decoration: none; color: var(--tone-success-fg); white-space: nowrap; }
.contact-whatsapp:hover { background-color: color-mix(in srgb, var(--tone-success-base) 10%, var(--surface)); text-decoration: underline; }
@media (max-width: 991.98px) { .contact-whatsapp { min-height: 2.75rem; align-items: center; padding: 0.35rem 0.75rem; margin: 0.25rem 0 0 0; } }
.contractor-actions-toggle { min-width: 2.25rem; }
.eyebrow { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--bs-secondary-color); }
.team-page { max-width: 880px; }
.page-narrow { max-width: 780px; }
.badge-owner, .badge-pending { background-color: color-mix(in srgb, var(--tone-base) 12%, var(--surface)); color: var(--tone-fg); border: 1px solid color-mix(in srgb, var(--tone-base) 35%, transparent); }
.badge-owner { --tone-base: var(--tone-info-base); --tone-fg: var(--tone-info-fg); }
.badge-pending { --tone-base: var(--tone-warning-base); --tone-fg: var(--tone-warning-fg); }
.copy-status { min-height: 1.25rem; color: var(--tone-success-fg); }
/* Avatar com prévia (perfil) */
.avatar-field { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; }
.avatar-field-circle { width: 72px; height: 72px; font-size: 1.5rem; overflow: hidden; }
.avatar-field-circle img { width: 100%; height: 100%; object-fit: cover; }
.avatar-field-controls { flex: 1 1 16rem; display: flex; flex-direction: column; gap: 0.35rem; min-width: 0; }
/* O input nativo fica sempre oculto (.visually-hidden, fora da tela mas focável); o foco aparece no botão. */
.avatar-field-input:focus-visible + .avatar-field-choose { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.avatar-field .btn-check:focus-visible + .btn { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.avatar-field .btn-check:checked + .btn { border-color: var(--tone-danger-base); color: var(--tone-danger-fg); }

/* Envio de várias fotos (aba Fotos): área de seleção clicável + grade de prévias.
   O <input type=file multiple> fica oculto (.visually-hidden, mas focável) ANTES do <label>; o foco de teclado
   aparece na área inteira. Sem JavaScript o rótulo continua abrindo o seletor nativo. */
.photo-dropzone { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.25rem; min-height: 7.5rem; padding: 1rem; text-align: center; cursor: pointer; border: 2px dashed var(--bs-border-color); border-radius: var(--bs-border-radius-lg); background-color: var(--surface); color: var(--bs-body-color); transition: border-color 0.15s ease, background-color 0.15s ease; }
.photo-dropzone:hover { border-color: var(--tone-info-base); background-color: color-mix(in srgb, var(--tone-info-base) 6%, var(--surface)); }
.photo-dropzone .bi { font-size: 1.75rem; }
.photo-dropzone-titulo { font-weight: 600; }
.photo-dropzone-dica { font-size: 0.875rem; color: var(--bs-secondary-color); }
.photo-input:focus-visible + .photo-dropzone { outline: 2px solid var(--focus-ring); outline-offset: 2px; border-color: var(--tone-info-base); }
.photo-preview-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 0.75rem; margin-top: 0.75rem; }
.photo-preview-grid[hidden] { display: none; }
.photo-preview { position: relative; min-width: 0; display: flex; flex-direction: column; gap: 0.35rem; padding: 0.5rem; border: 1px solid var(--bs-border-color); border-radius: var(--bs-border-radius); background-color: var(--surface); }
.photo-preview.is-rejeitada { border-style: dashed; border-color: color-mix(in srgb, var(--tone-warning-base) 55%, var(--bs-border-color)); }
.photo-preview.is-rejeitada .photo-preview-moldura { opacity: 0.55; }
.photo-preview-moldura { aspect-ratio: 4 / 3; display: flex; align-items: center; justify-content: center; overflow: hidden; border-radius: var(--bs-border-radius-sm); background-color: var(--bs-tertiary-bg); }
.photo-preview-moldura img { width: 100%; height: 100%; object-fit: cover; }
.photo-preview-moldura .bi { font-size: 2rem; color: var(--bs-secondary-color); }
.photo-preview-info { min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.photo-preview-nome { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.875rem; font-weight: 500; }
.photo-preview-estado { font-size: 0.8125rem; color: var(--bs-secondary-color); overflow-wrap: anywhere; }
.photo-preview.is-rejeitada .photo-preview-estado { color: var(--tone-warning-fg); }
.photo-preview-remover { position: absolute; top: 0.25rem; right: 0.25rem; background-color: color-mix(in srgb, var(--surface) 88%, transparent); }

/* Aba Fotos: etapa → álbum → fotos. Cabeçalho do álbum com quebra de linha (sem rolagem horizontal no celular). */
.foto-album-cabecalho { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem 1rem; margin: 1.25rem 0 0.75rem; padding-bottom: 0.4rem; border-bottom: 1px solid var(--bs-border-color); }
.foto-album-cabecalho .foto-album-alternar { margin-right: 0.25rem; }
.foto-album-titulo { flex: 1 1 12rem; min-width: 0; overflow-wrap: anywhere; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.35rem; }
.foto-album-acoes { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem; }
.foto-album-acoes form { display: inline-flex; margin: 0; }
.foto-album-corpo[hidden] { display: none; }
.foto-album-vazio { padding: 0.5rem 0; }
.foto-card-rodape { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.25rem 0.5rem; }
.foto-card-acoes form { margin: 0; }
.foto-legenda { overflow-wrap: anywhere; }

/* Zona de perigo discreta (configurações da organização): superfície neutra, vermelho só em título, ícone, borda e botão */
.danger-zone-quiet { margin-top: 2rem; padding: 1rem 1.25rem; background-color: var(--surface); border: 1px solid color-mix(in srgb, var(--tone-danger-base) 40%, var(--bs-border-color)); border-radius: var(--bs-border-radius); }
.danger-zone-quiet h2 { margin: 0 0 0.25rem; font-size: 1rem; font-weight: 600; color: var(--tone-danger-fg); }

/* Item 12: cabeçalhos, largura de texto e wizard de cadastro */
.page-header-row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end; gap: 0.5rem 1rem; margin-bottom: 1.5rem; }
.page-header-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.page-description { max-width: 65ch; margin: 0.25rem 0 0; color: var(--bs-secondary-color); }
/* Textos explicativos: linhas longas cansam a leitura; o limite só vale para parágrafos, não para tabelas ou formulários. */
.app-content p.text-muted-2, .app-content .form-text, .app-content .empty-state-text { max-width: 72ch; }
.app-content .empty-state-text, .app-content .text-center .form-text { margin-left: auto; margin-right: auto; }
.wizard-page { max-width: 960px; }
.wizard-mobile-count { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--bs-secondary-color); }
.wizard-mobile-name { font-size: 1.125rem; font-weight: 600; }
.wizard-step-optional-inline { font-size: 0.875rem; font-weight: 400; color: var(--bs-secondary-color); }
.wizard-surface { background-color: var(--surface); }

/* Contexto do imóvel no cabeçalho dos modais (o modal não tem breadcrumb) */
.modal-title-group { min-width: 0; }
.modal-context { margin: 0.15rem 0 0; font-size: 0.8125rem; color: var(--bs-secondary-color); overflow-wrap: anywhere; }

/* Ícone de ajuda (templates/partials/_info_tip.html): focável por teclado/toque, com foco visível. */
.info-tip { cursor: help; display: inline-block; border-radius: 50%; }
.info-tip:focus-visible { outline: 2px solid var(--bs-primary); outline-offset: 2px; }

/* Composição pago/pendente dentro de um card do Painel: cada linha quebra o valor para baixo quando o
   card é estreito (valores grandes no mobile), sem crescer o card de forma desproporcional. */
.stat-composition > div { display: flex; flex-wrap: wrap; column-gap: 0.35rem; align-items: baseline; }
.stat-composition dt, .stat-composition dd { margin: 0; overflow-wrap: anywhere; }

/* Valor principal que se ajusta à largura do card (container query) e ao número de caracteres:
   largura do texto ≈ (caracteres + "R$ ") × 0,53em, entre 1rem e 1,75rem. Sem suporte a cqi, vale o tamanho fixo acima (não usa .fs-3: o Bootstrap o marca !important). */
.stat-fit-box { container-type: inline-size; }
.stat-fit { white-space: nowrap; line-height: 1.25; font-size: 1.5rem; }
@supports (font-size: 1cqi) {
    .stat-fit { font-size: clamp(1rem, calc(100cqi / ((var(--chars, 12) + 3) * 0.53)), 1.75rem); }
}

/* Foto cuja miniatura E original falharam (photo_fallback.js): para o brilho do skeleton. */
.img-skeleton.is-failed {
    animation: none;
}

/* Miniatura da galeria: link real para o original protegido (JavaScript abre o carrossel por cima). */
a.photo-thumb {
    cursor: zoom-in;
    border-radius: var(--bs-border-radius-lg) var(--bs-border-radius-lg) 0 0;
}

/* Rodapé de cada foto do carrossel: contexto ("Foto 3 de 24 — legenda") e "Abrir original". */
.foto-visualizacao-rodape {
    text-align: center;
    padding: 0.75rem 1rem 1rem;
    color: #fff;
}
.foto-visualizacao-contexto { color: rgba(255, 255, 255, 0.85); }
.foto-abrir-original {
    min-height: 44px; /* alvo de toque confortável no celular */
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    /* O `.btn-outline-light` do tema é feito para fundo CLARO; o modal do carrossel é escuro: cores explícitas (contraste ≥ 4,5:1). */
    color: #fff;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.7);
}
.foto-abrir-original:hover,
.foto-abrir-original:focus-visible {
    color: #111;
    background: #fff;
    border-color: #fff;
}
