/* ==========================================================================
   IeP Painel, camada apple-design.
   Carregado DEPOIS de app.css. Fonte: docs/mockups/inicio-apple (aprovado).

   Duas metades:
     A. MOVIMENTO E MATERIAL  aplica-se a toda a app, sem tocar em markup
     B. SISTEMA VISUAL        peso, profundidade e hierarquia (o passe aprovado)

   Secções = skill apple-design:
     §1 resposta · §7 espacial · §12 materiais · §14 acessibilidade
     §15 tipografia · §16 simplicidade e hierarquia

   Para remover tudo: apagar as 2 linhas em base.html.
   ========================================================================== */

/* ---- tokens novos. Não colidem com os de base.html: são nomes que lá não
        existem, por isso o bloco <style> do base.html continua a mandar em
        tudo o que ele define. -------------------------------------------- */
:root {
  --hair: rgba(16, 20, 24, .09);          /* hairline, não uma border de 1px */
  --lift:    0 .5px 1px rgba(16, 20, 24, .05), 0 2px 6px rgba(16, 20, 24, .045);
  --lift-lg: 0 1px 2px rgba(16, 20, 24, .06), 0 10px 30px rgba(16, 20, 24, .09);
  --glass: color-mix(in srgb, var(--card) 72%, transparent);
  --r-lg: 16px;
  --ic-purple: #6d28d9;

  /* ---- série categórica dos gráficos -------------------------------------
     Uma paleta, definida uma vez, em vez de um literal diferente por template.
     Base Okabe-Ito, que é segura para as três formas comuns de daltonismo,
     com a luminosidade ajustada para assentar sobre um cartão branco.
     Cores COM SIGNIFICADO (entra/sai) não vivem aqui: essas são --good/--bad,
     senão o verde deixa de querer dizer verde. Lidas por charts.js. */
  --chart-1: #0072b2;  --chart-2: #e69f00;  --chart-3: #009e73;  --chart-4: #d55e00;
  --chart-5: #cc79a7;  --chart-6: #3a9fd6;  --chart-7: #8c6d1f;  --chart-8: #6b7280;
}
:root[data-theme="dark"] {
  --hair: rgba(232, 235, 239, .11);
  --lift:    0 .5px 1px rgba(0, 0, 0, .5), 0 2px 6px rgba(0, 0, 0, .35);
  --lift-lg: 0 1px 2px rgba(0, 0, 0, .5), 0 10px 30px rgba(0, 0, 0, .5);
  --ic-purple: #a78bfa;

  /* as mesmas famílias, clareadas para o cartão escuro (#1c222b) */
  --chart-1: #56b4e9;  --chart-2: #f0b23e;  --chart-3: #33c99b;  --chart-4: #f07b45;
  --chart-5: #e39abf;  --chart-6: #7fcdef;  --chart-7: #c9a227;  --chart-8: #98a2b0;
}


/* ==========================================================================
   A · MOVIMENTO E MATERIAL
   ========================================================================== */

/* ---- §1 resposta: o toque é o feedback, e é imediato --------------------
   O Painel é usado no telemóvel, onde :hover não existe. Antes desta camada
   não havia feedback nenhum ao toque em lado nenhum da app. */
.btn, a.stat-tile, a.side-link, .range-pills a, .kpi-info, .iep-row,
header.fixed button, .data-table tbody tr.row-link,
table[data-sortable] thead th, .iep-seg a {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.btn {
  transition: background .12s ease, border-color .12s ease, color .12s ease,
              transform .32s cubic-bezier(.22, 1, .36, 1);
}
.btn:active { transform: scale(.96); transition-duration: 0s; }
.btn-sm:active { transform: scale(.94); }

a.stat-tile {
  transition: border-color .12s ease, box-shadow .12s ease,
              transform .32s cubic-bezier(.22, 1, .36, 1);
}
a.stat-tile:active { transform: scale(.985); transition-duration: 0s; }

header.fixed button {
  transition: color .12s ease, transform .32s cubic-bezier(.22, 1, .36, 1);
}
header.fixed button:active { transform: scale(.9); transition-duration: 0s; }

/* superfícies não comprimem: acendem */
a.side-link, .range-pills a, .data-table tbody tr.row-link, .iep-row,
table[data-sortable] thead th, .kpi-info, .iep-seg a {
  transition: background-color .26s ease, color .26s ease, border-color .26s ease;
}
a.side-link:active, .range-pills a:active, .iep-seg a:active,
.data-table tbody tr.row-link:active,
table[data-sortable] thead th:active,
a.iep-row:active {
  background-color: color-mix(in srgb, var(--text) 8%, transparent);
  transition-duration: 0s;
}
.range-pills a.is-active:active { background-color: var(--accent-strong); }

/* ---- §12 barra de topo (telemóvel): separa-se só onde há conteúdo por baixo */
@media (max-width: 767px) {
  header.fixed {
    background: color-mix(in srgb, var(--card) 76%, transparent);
    backdrop-filter: saturate(180%) blur(20px);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    border-bottom-color: transparent;
    transition: border-color .22s ease, background-color .22s ease;
  }
  header.fixed::after {
    content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 14px;
    pointer-events: none; opacity: 0; transition: opacity .22s ease;
    background: linear-gradient(to bottom,
                color-mix(in srgb, var(--surface) 72%, transparent), transparent);
  }
  header.fixed.ad-scrolled::after { opacity: 1; }
  header.fixed.ad-scrolled {
    background: color-mix(in srgb, var(--card) 70%, transparent);
    backdrop-filter: saturate(190%) blur(24px);
    -webkit-backdrop-filter: saturate(190%) blur(24px);
  }
}
.fixed.inset-0.z-40 { backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }

/* ---- §7 o kpi-info deixa de ser um corte seco -------------------------- */
.kpi-info-pop {
  display: block !important;
  opacity: 0; visibility: hidden; scale: .97;
  transform-origin: top left;
  transition: opacity .15s ease,
              scale .28s cubic-bezier(.22, 1, .36, 1),
              visibility 0s linear .28s;
}
.kpi-info:hover > .kpi-info-pop,
.kpi-info:focus > .kpi-info-pop,
.kpi-info:focus-visible > .kpi-info-pop,
.kpi-info:focus-within > .kpi-info-pop {
  opacity: 1; visibility: visible; scale: 1; transition-delay: 0s;
}
@media (min-width: 640px) { .kpi-info-end > .kpi-info-pop { transform-origin: top right; } }


/* ==========================================================================
   B · SISTEMA VISUAL (o passe aprovado)
   ========================================================================== */

body { font-optical-sizing: auto; }

/* ---- §15 o título da página. Era 24px, o mesmo peso visual que o título de
        um cartão, por isso a página não tinha primeiro plano. -------------- */
.t-h1 {
  font-size: 34px; line-height: 1.06; letter-spacing: -.03em; font-weight: 680;
}
@media (max-width: 767px) { .t-h1 { font-size: 27px; } }

.t-stat, .stat-tile-value { letter-spacing: -.024em; }

/* ---- §12/§16 os cartões deixam de ser desenhados e passam a assentar.
        A border fica, mas como hairline: manter 1px preserva a métrica de
        todas as grelhas existentes, e o que muda é só a dureza da linha. -- */
.iep-card, .stat-tile, .filter-bar {
  border-color: var(--hair);
  border-radius: var(--r-lg);
  box-shadow: var(--lift);
}
a.stat-tile:hover { border-color: var(--accent); box-shadow: var(--lift-lg); }

/* ---- §16 a etiqueta da secção vive FORA do cartão.
        Emitida pela macro ui.card() e usada por TODA a app: nao existe mais
        nenhum cabecalho dentro de um cartao. Titulos que nao sao cabecalhos de
        seccao (modais, toggles) usam .iep-ttl-inline em app.css. --- */
.iep-sect {
  font-size: 11px; font-weight: 650; letter-spacing: .085em; text-transform: uppercase;
  color: var(--text-muted); margin: 0 4px 9px;
  display: flex; align-items: center; gap: 10px;
}
.iep-sect .note {
  margin-left: auto; text-transform: none; letter-spacing: 0;
  font-weight: 450; font-size: 12px; color: var(--text-muted);
}
.iep-sect a.note { color: var(--accent); }
.iep-sect .note .btn { margin-left: 6px; }
/* o título fica com o espaço que sobra e nunca encolhe abaixo do legível */
.iep-sect .ttl { flex: 1 1 auto; min-width: 0; }
.iep-sect .note {
  flex: 0 1 auto;
  display: inline-flex; align-items: center; gap: 10px; justify-content: flex-end;
  flex-wrap: wrap;
}
.iep-sect .note-sub { min-width: 0; }
/* subtitle longo: prosa dentro do cartão, antes do conteúdo */
.iep-lead {
  font-size: 13px; line-height: 1.5; color: var(--text-muted);
  margin-bottom: 12px; max-width: 68ch;
}
.iep-card:not(.iep-card-pad) > .iep-lead { padding: 14px 16px 0; margin-bottom: 6px; }
.iep-blk { margin-bottom: 26px; }

/* ui.card() envolve etiqueta + cartão nisto. TEM de ser um só elemento: os
   templates chamam a macro directamente dentro de grelhas, e devolver dois
   irmãos transformaria cada cartão em dois itens de grelha. */
.iep-group { min-width: 0; }
.iep-group + .iep-group { margin-top: 22px; }

/* ---- linhas agrupadas: o padrão que substitui quatro mosaicos iguais ---- */
.iep-row {
  display: flex; align-items: center; gap: 13px; width: 100%;
  padding: 13px 18px; min-height: 62px; position: relative;
  color: var(--text);
}
.iep-row + .iep-row::before {
  content: ""; position: absolute; left: 63px; right: 0; top: 0;
  height: 1px; background: var(--hair);
}
a.iep-row:hover { background: var(--subtle); text-decoration: none; }
.iep-ic {
  width: 32px; height: 32px; border-radius: 9px; flex: none;
  display: grid; place-items: center; color: #fff;
}
.iep-ic svg { width: 17px; height: 17px; }
.iep-rmain { flex: 1; min-width: 0; }
/* título e subtítulo são <span> dentro de um item flex: sem isto ficam ambos
   na mesma linha de texto e a linha desmancha-se. Uma linha cada, com
   reticências: a altura da linha fica constante e o detalhe está no destino. */
.iep-rt, .iep-rs {
  display: block; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.iep-rt { font-size: 14.5px; font-weight: 500; }
.iep-rs { font-size: 12.5px; color: var(--text-muted); margin-top: 2px; }
.iep-rend { text-align: right; flex: none; }
.iep-rv {
  font-size: 19px; font-weight: 640; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.iep-rv.is-good { color: var(--good); }
.iep-rv.is-warn { color: var(--warn); }
.iep-rv.is-zero { color: var(--text-faint); }
.iep-chev { color: var(--text-faint); flex: none; width: 15px; height: 15px; margin-left: 2px; }

/* ---- o herói do capital ------------------------------------------------- */
.iep-hero { padding: 22px 24px 20px; }
.iep-hero .lbl {
  font-size: 11px; font-weight: 650; letter-spacing: .085em;
  text-transform: uppercase; color: var(--text-muted);
}
.iep-hero .big {
  font-size: 44px; line-height: 1.02; letter-spacing: -.032em; font-weight: 680;
  font-variant-numeric: tabular-nums; margin-top: 10px;
}
/* sem saldo definido um "—" a 34px lê-se como um cartão partido, não como um
   estado. O vazio diz o que é e o rodapé diz o que fazer. */
.iep-hero .big.empty {
  font-size: 24px; font-weight: 560; letter-spacing: -.02em; color: var(--text-faint);
}
.iep-hero .foot {
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--hair);
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  font-size: 13px; color: var(--text-muted);
}
.iep-hero .foot b {
  font-weight: 620; color: var(--text); font-variant-numeric: tabular-nums;
}

/* ---- lista de vencimentos ---------------------------------------------- */
.iep-due { display: flex; align-items: center; gap: 12px; padding: 12px 18px; position: relative; }
.iep-due + .iep-due::before {
  content: ""; position: absolute; left: 18px; right: 0; top: 0; height: 1px; background: var(--hair);
}
.iep-due .dm { flex: 1; min-width: 0; }
.iep-due .dt {
  font-size: 13.5px; font-weight: 480;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.iep-due .dd { font-size: 12px; color: var(--text-muted); margin-top: 1px; }
.iep-due .de { text-align: right; flex: none; }
.iep-due .dday {
  font-size: 11.5px; color: var(--text-muted); margin-top: 3px;
  font-variant-numeric: tabular-nums;
}

/* ---- segmentado (as range pills do gráfico) ---------------------------- */
.iep-seg { display: inline-flex; background: var(--subtle); border-radius: 9px; padding: 2px; gap: 2px; }
.iep-seg a {
  padding: 4px 11px; border-radius: 7px; font-size: 12px; font-weight: 500;
  color: var(--text-2); text-decoration: none;
}
.iep-seg a:hover { color: var(--text); }
.iep-seg a.on {
  background: var(--card); box-shadow: 0 1px 3px rgba(0, 0, 0, .12);
  color: var(--text); font-weight: 600;
}

/* ---- §16 tabelas: o cabeçalho deixa de ser um bloco cinzento ------------
   Um bloco cinzento por cima de cada tabela é chrome a competir com os dados.
   Fica uma linha discreta sobre um hairline, e as linhas ganham altura. --- */
   O padding HORIZONTAL fica nos 12px do original de propósito. Subi-o para 16px
   e o Screener, que tem nove colunas, passou a transbordar: a coluna do preço
   partia-se em quatro linhas e o Sinal ficava cortado fora do cartão. Ar a mais
   numa tabela densa não é calma, é dados que deixam de caber. Sobe só o
   vertical, que é o que dá o ritmo das linhas sem alargar nada. */
.data-table thead th {
  background: transparent;
  border-bottom: 1px solid var(--hair);
  padding: 11px 12px 9px;
  font-size: 10.5px; letter-spacing: .075em; color: var(--text-faint);
}
.data-table tbody td {
  padding: 12px 12px; border-top: 1px solid var(--hair); font-size: 13.5px;
}
.data-table .money { font-weight: 620; }
/* O `white-space: nowrap` que aqui esteve foi REMOVIDO: era um penso para o
   número se partir ao meio ("225 / 000 €") e custava caro — media-se 749px de
   tabela dentro de um contentor de 566px na Previsão fiscal, ou seja, scroll
   horizontal numa tabela que cabia. A cura de raiz está no sítio certo: os
   separadores do _eur passaram a U+00A0 em templates_env.py, por isso o número
   já não parte e as células voltam a poder quebrar onde faz sentido. */

/* um "—" sozinho a 28px bold lê-se como uma barra preta, não como um estado */
.t-stat.is-empty, .stat-tile-value.is-empty, .chart .cv.is-empty {
  font-size: 20px; font-weight: 560; letter-spacing: -.01em; color: var(--text-faint);
}

/* ---- pills tingidas ----------------------------------------------------- */
.badge {
  border-radius: 999px; padding: 2.5px 9px;
  font-size: 11px; font-weight: 640; letter-spacing: .02em;
}
.badge-neutral { background: var(--subtle); color: var(--text-muted); border-color: transparent; }

/* ---- §12 a barra lateral como material ---------------------------------
   Era opaca com uma linha à direita. Passa a vidro, com o conteúdo a deslizar
   por baixo. O item activo deixa de ser "fundo tingido + barra à esquerda" e
   passa a ser uma pill preenchida.
   `aside.fixed` (0,1,1) ganha às utilitárias do Tailwind (0,1,0); os selectores
   do side-link levam o elemento à frente para ganharem ao <style> do base.html,
   que carrega depois desta folha. ---------------------------------------- */
@media (min-width: 768px) {
  aside.fixed {
    background: var(--glass);
    backdrop-filter: saturate(180%) blur(24px);
    -webkit-backdrop-filter: saturate(180%) blur(24px);
    border-right-color: var(--hair);
  }
}
a.side-link {
  margin: 0 8px; padding-left: 12px; padding-right: 12px;
  border-radius: 10px; border-left: 0 !important;
}
a.side-link.active {
  background: var(--accent) !important;
  color: #fff !important;
  border-left: 0 !important;
  font-weight: 550;
}
:root[data-theme="dark"] a.side-link.active { color: #0b0e12 !important; }


/* ==========================================================================
   §14  ACESSIBILIDADE
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
  .btn:active, a.stat-tile:active, header.fixed button:active { transform: none !important; }
  .kpi-info-pop {
    scale: 1 !important;
    transition: opacity .14s ease, visibility 0s linear .14s !important;
  }
  .kpi-info:hover > .kpi-info-pop, .kpi-info:focus > .kpi-info-pop,
  .kpi-info:focus-visible > .kpi-info-pop, .kpi-info:focus-within > .kpi-info-pop {
    transition-delay: 0s !important;
  }
  aside.fixed { transition: none !important; }
}

@media (prefers-reduced-transparency: reduce) {
  header.fixed, header.fixed.ad-scrolled, aside.fixed {
    background: var(--card);
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  header.fixed { border-bottom-color: var(--border); }
  header.fixed::after { display: none; }
  .fixed.inset-0.z-40 { backdrop-filter: none; -webkit-backdrop-filter: none; }
}

@media (prefers-contrast: more) {
  :root {
    --hair: rgba(16, 20, 24, .34);
    --border: #9aa2ad; --border-strong: #5b6470;
    --text-muted: #39414b; --text-faint: #5b6470;
  }
  :root[data-theme="dark"] {
    --hair: rgba(232, 235, 239, .38);
    --border: #6b7683; --border-strong: #98a2b0;
    --text-muted: #c3cad3; --text-faint: #98a2b0;
  }
  .iep-card, .stat-tile, .filter-bar, .kpi-info-pop { border-color: var(--border-strong); }
  .badge { border-color: currentColor; }
  header.fixed, header.fixed.ad-scrolled, aside.fixed {
    background: var(--card); backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  header.fixed::after { display: none; }
}


/* ==========================================================================
   MINIATURA DE FOTOGRAFIA — galeria do imóvel (portfolio/detail)
   --------------------------------------------------------------------------
   Um <button> que envolve a imagem, por isso precisa de perder o aspeto de
   botão. A moldura é um inset shadow e não uma border: assim a imagem não
   muda de tamanho ao passar o rato, que faria a grelha toda estremecer.
   ========================================================================== */
.foto-mini {
  display: block; width: 100%; padding: 0; border: 0; cursor: pointer;
  border-radius: 10px; overflow: hidden; background: var(--subtle);
  box-shadow: inset 0 0 0 1px var(--hair);
  transition: box-shadow .2s ease, transform .32s cubic-bezier(.22, 1, .36, 1);
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.foto-mini:hover { box-shadow: inset 0 0 0 1px var(--accent); }
.foto-mini:active { transform: scale(.985); transition-duration: 0s; }
.foto-mini:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.foto-mini img { display: block; }
