:root{
  --brand: #0b5fa5;
  --brand-dark: #084a82;
  --brand-light: #2f8fd6;
  --ink: #1b2430;
  --ink-soft: #5a6675;
  --bg: #f4f6f9;
  --card: #ffffff;
  --line: #e2e6ec;
  --good: #147a3d;
  --warn: #b9560f;
  --radius: 12px;
  --shadow: 0 1px 2px rgba(20,30,50,.06), 0 4px 16px rgba(20,30,50,.06);
  --maxw: 1280px;
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
[hidden]{ display:none !important; }
body{
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}
img{max-width:100%;display:block}
button{font:inherit}
input,select,textarea{font:inherit}

.visually-hidden{
  position:absolute; width:1px; height:1px; overflow:hidden;
  clip:rect(0 0 0 0); white-space:nowrap;
}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex; align-items:center; gap:.4em; justify-content:center;
  border-radius: 999px; border:1px solid transparent; cursor:pointer;
  padding:.6em 1.1em; font-size:.92rem; font-weight:600; line-height:1.1;
  transition: background .15s, border-color .15s, transform .05s;
  white-space:nowrap; text-decoration:none;
}
.btn:active{transform: scale(.97)}
.btn-primary{ background: var(--brand); color:#fff; }
.btn-primary:hover{ background: var(--brand-dark); }
.btn-outline{ background:#fff; color: var(--ink); border-color: var(--line); }
.btn-outline:hover{ border-color:#c3cad4; }
.btn-ghost{ background:transparent; color: var(--ink); }
.btn-ghost:hover{ background:#0000000a; }
.btn-icon{ background:transparent; border:none; font-size:1.1rem; padding:.3em .5em; border-radius:8px; cursor:pointer; }
.btn-icon:hover{ background:#0000000f; }
.btn-sm{ padding:.4em .8em; font-size:.82rem; }
.btn:disabled{ opacity:.45; cursor:not-allowed; }

.badge{
  background:#fff; color: var(--brand); border-radius:999px;
  font-size:.75rem; font-weight:800; padding:.05em .5em; min-width:1.4em; text-align:center;
}
.btn-primary .badge{ background:rgba(255,255,255,.25); color:#fff; }

/* ---------- topbar ---------- */
.topbar{
  position: sticky; top:0; z-index:20;
  background: var(--brand); color:#fff;
  box-shadow: var(--shadow);
}
.topbar-inner{
  max-width: var(--maxw); margin:0 auto;
  display:flex; align-items:center; justify-content:space-between;
  padding: .7rem 1rem; gap: 1rem;
}
.brand{ display:flex; align-items:center; gap:.6rem; min-width:0; }
.brand-logo{ height:36px; width:auto; border-radius:6px; background:#fff; }
.brand-text{ display:flex; flex-direction:column; line-height:1.15; min-width:0; }
.brand-text strong{ font-size:1.05rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.brand-text span{ font-size:.74rem; opacity:.85; }
.topbar-actions{ display:flex; align-items:center; gap:.5rem; flex-shrink:0; }
/* Botão "Atualizar" + número da versão instalada, um por baixo do outro — para se saber
   sempre, de relance, qual a versão da aplicação que está publicada no servidor. */
.atualizar-wrap{ display:flex; flex-direction:column; align-items:center; gap:.15rem; }
.app-version-tag{ font-size:.64rem; opacity:.75; white-space:nowrap; letter-spacing:.02em; }
.user-tag{ font-size:.78rem; opacity:.9; white-space:nowrap; margin-right:.2rem; }
@media (max-width: 640px){ .user-tag{ display:none; } }
.topbar .btn-ghost{ color:#fff; }
.topbar .btn-ghost:hover{ background:rgba(255,255,255,.15); }
.topbar .btn-primary{ background:#fff; color: var(--brand); }
.topbar .btn-primary:hover{ background:#eef4fb; }
.topbar .btn-primary .badge{ background: var(--brand); color:#fff; }

/* ---------- V187: cliente em contexto (barra escura) ----------
   Ocupa o espaço que sobra ao centro da barra e encolhe antes do logótipo e das ações: num
   telemóvel a pesquisa é mais importante do que o nome da empresa escrito ao lado do logo.
   A lista de resultados é position:absolute por cima de tudo o resto — a barra tem overflow
   visível de propósito para ela poder sair para fora (ver .topbar). */
.cliente-contexto{ flex:1 1 auto; min-width:0; max-width:520px; display:flex; align-items:center; }
.cc-procura{ position:relative; display:flex; align-items:center; width:100%; }
.cc-icone{ position:absolute; left:.7rem; font-size:.85rem; opacity:.7; pointer-events:none; }
.cc-procura input{
  width:100%; border-radius:999px; border:1px solid rgba(255,255,255,.35);
  background:rgba(255,255,255,.12); color:#fff;
  padding:.5rem .8rem .5rem 2.1rem; font-size:.88rem; outline:none;
}
.cc-procura input::placeholder{ color:rgba(255,255,255,.75); }
.cc-procura input:focus{ background:rgba(255,255,255,.2); border-color:#fff; }
.cc-lista{
  position:absolute; top:calc(100% + .35rem); left:0; right:0; z-index:60;
  background:var(--card); color:var(--ink); border:1px solid var(--line);
  border-radius:var(--radius); box-shadow:var(--shadow); overflow:hidden; max-height:60vh; overflow-y:auto;
}
.cc-item{
  display:block; width:100%; text-align:left; background:none; border:0; cursor:pointer;
  padding:.55rem .8rem; border-bottom:1px solid var(--line); line-height:1.25;
}
.cc-item:last-child{ border-bottom:0; }
.cc-item:hover, .cc-item.cc-ativo{ background:#eef4fb; }
.cc-item strong{ display:block; font-size:.9rem; }
.cc-item small{ display:block; font-size:.75rem; color:var(--ink-soft); }
.cc-item .cc-incompleta{ color:var(--warn); font-weight:600; }
.cc-vazio{ padding:.7rem .8rem; font-size:.85rem; color:var(--ink-soft); }
/* cliente escolhido */
.cc-escolhido{
  display:flex; align-items:center; gap:.3rem; width:100%;
  background:rgba(255,255,255,.14); border:1px solid rgba(255,255,255,.35);
  border-radius:999px; padding:.25rem .3rem .25rem .85rem;
}
.cc-identidade{ display:flex; flex-direction:column; line-height:1.15; min-width:0; flex:1 1 auto; }
.cc-empresa{ font-size:.88rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cc-ctr{ font-size:.72rem; opacity:.85; white-space:nowrap; }
.cc-ctr.cc-incompleta{ color:#ffd9a8; font-weight:600; opacity:1; }
.topbar .cc-escolhido .btn-icone{ padding:.35rem .5rem; }
@media (max-width: 860px){
  .cliente-contexto{ order:3; flex-basis:100%; max-width:none; margin-top:.4rem; }
  .topbar-inner{ flex-wrap:wrap; }
}

/* ---------- barra dos módulos (Escritório / Informática / Impressão) ----------
   barra secundária, num azul mais claro do que a barra escura de cima, sempre visível
   enquanto a sessão dura — permite saltar entre módulos sem nunca perder o que já estava
   feito (ex: a proposta em curso no módulo Impressão fica sempre na memória, mesmo a navegar
   para outro módulo e voltar — ver moduloAtivo/mostrarModulo() em js/app.js). */
.module-bar{
  /* fica em fluxo normal, logo abaixo da barra escura (que essa sim fica fixa no topo ao
     fazer scroll) — assim não há sobreposição das duas barras "sticky" na mesma posição. */
  background: var(--brand-light); box-shadow: var(--shadow);
}
.module-bar-inner{
  max-width: var(--maxw); margin:0 auto; padding:.4rem 1rem;
  display:flex; align-items:center; gap:.4rem; flex-wrap:wrap;
}
.module-btn{
  display:inline-flex; align-items:center; gap:.4rem; border:none; border-radius:8px;
  background:transparent; color:#fff; font-size:.86rem; font-weight:600; cursor:pointer;
  padding:.5em .9em; font-family:inherit; opacity:.85;
}
.module-btn:hover{ background:rgba(255,255,255,.18); opacity:1; }
.module-btn.active{ background:#fff; color: var(--brand-light); opacity:1; }

/* ---------- ecrã inicial (tiles dos módulos) e módulos ainda por implementar ---------- */
.module-home{ max-width: var(--maxw); margin:0 auto; padding:1.6rem 1rem; }
.module-home h1{ font-size:1.25rem; margin:0 0 1rem; }
.module-home-grid{
  display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:1rem;
}
.module-tile{
  display:flex; flex-direction:column; align-items:flex-start; gap:.45rem;
  background:#fff; border:1px solid var(--line); border-radius: var(--radius);
  padding:1.3rem 1.4rem; box-shadow: var(--shadow);
  cursor:pointer; text-align:left; font-family:inherit; color:inherit;
  transition:box-shadow .15s ease, transform .15s ease;
}
.module-tile:hover{ box-shadow:0 4px 14px rgba(0,0,0,.1); transform:translateY(-1px); }
.module-tile-icon{ font-size:2rem; line-height:1; }
.module-tile h3{ margin:0; font-size:1.05rem; }
.module-tile p{ margin:0; font-size:.82rem; color: var(--ink-soft); }

.module-placeholder{ max-width: var(--maxw); margin:0 auto; padding:2.4rem 1rem; text-align:center; }
.module-placeholder-icon{ font-size:2.6rem; }
.module-placeholder h2{ margin:.6rem 0 .4rem; }
.module-placeholder p{ color: var(--ink-soft); max-width:480px; margin:0 auto; }

/* ---------- layout ---------- */
.main{ max-width: var(--maxw); margin:0 auto; padding: 1rem; }

.search-panel{
  background: var(--card); border:1px solid var(--line); border-radius: var(--radius);
  padding: 1rem; margin-bottom:1rem; box-shadow: var(--shadow);
}
.search-grid{
  display:grid; gap:.75rem;
  grid-template-columns: repeat(auto-fit, minmax(190px,1fr));
}
.field{ display:flex; flex-direction:column; gap:.3rem; min-width:0; }
.field > span{ font-size:.78rem; font-weight:700; color: var(--ink-soft); }
.field input, .field select, .field textarea{
  padding:.6em .7em; border:1px solid var(--line); border-radius:8px; background:#fff; color: var(--ink);
  width:100%;
}
.field input:focus, .field select:focus, .field textarea:focus{
  outline:2px solid var(--brand); outline-offset:1px;
}
.field-grow{ grid-column: 1 / -1; }
.field-actions{ justify-content:flex-end; }
.field-row{ display:flex; gap:.6rem; }
.field-row .field{ flex:1; }

.doc-filtros{ flex-wrap:wrap; align-items:flex-end; padding-bottom:.8rem; margin-bottom:.2rem; border-bottom:1px solid var(--line); }
.doc-filtros .field{ min-width:150px; flex:1 1 150px; }
#documentosTable th.sortable{ cursor:pointer; user-select:none; white-space:nowrap; }
#documentosTable th.sortable:hover{ color:var(--brand); }
#documentosTable .sort-ind{ font-size:.7em; margin-left:.25em; opacity:.55; }

.search-meta{
  margin:.7rem 0 0; font-size:.85rem; color: var(--ink-soft);
  display:flex; gap:.5rem; align-items:center;
}
.search-meta .dot{ opacity:.5; }
#resultsCount{ font-weight:700; color: var(--ink); }

/* ---------- grid of products ---------- */
.grid{
  display:grid; gap:.9rem;
  grid-template-columns: repeat(auto-fill, minmax(220px,1fr));
}
.card{
  background: var(--card); border:1px solid var(--line); border-radius: var(--radius);
  overflow:hidden; display:flex; flex-direction:column; box-shadow: var(--shadow);
}
.card-img{
  aspect-ratio: 1/1; background:#fff; display:flex; align-items:center; justify-content:center;
  border-bottom:1px solid var(--line); cursor:pointer; padding:.6rem;
}
.card-img img{ width:100%; height:100%; object-fit:contain; }
.card-body{ padding:.7rem .8rem .3rem; display:flex; flex-direction:column; gap:.35rem; flex:1; }
.card-ref{ font-size:.72rem; font-weight:800; letter-spacing:.02em; color: var(--brand); text-transform:uppercase; }

/* Indicador de stock (stock sincronizado no back office — ver lib/produtos_custos.php):
   vermelho sem stock, amarelo abaixo de 10 un., verde a partir de 10. Aparece junto de cada tipo
   de preço (Original/Compatível/Lowcost) que tenha stock sincronizado, não junto da referência.
   Um pequeno círculo colorido chega — a quantidade exata aparece no "title" (tooltip). */
.stock-dot{
  display:inline-block; width:9px; height:9px; border-radius:50%; margin-left:.4em;
  vertical-align:middle; box-shadow: 0 0 0 1px rgba(0,0,0,.06);
}
.stock-dot--red{ background:#c0392b; }
.stock-dot--yellow{ background:#d99a1d; }
.stock-dot--green{ background: var(--good); }
.card-desc{
  font-size:.86rem; line-height:1.3; color: var(--ink); cursor:pointer;
  display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden; min-height:2.6em;
}
.card-tags{ display:flex; gap:.3rem; flex-wrap:wrap; }
.card-tag{
  font-size:.68rem; background:#eef2f7; color: var(--ink-soft); border-radius:6px; padding:.15em .5em; font-weight:700;
}
/* Módulo Escritório — indicadores "A"/"L" de stock por fornecedor (Allto/Líder Papel) numa
   linha própria por baixo das etiquetas de família/tipo, um por cada fornecedor: verde = tem
   stock, cinza = não tem (ou o fornecedor nem sequer tem este produto) — ver alBadgeHtml() em
   js/app.js. */
.al-badges{ display:flex; gap:.35rem; }
.al-badge{
  display:inline-flex; align-items:center; justify-content:center; width:1.35rem; height:1.35rem;
  border-radius:50%; font-size:.68rem; font-weight:800; box-shadow: 0 0 0 1px rgba(0,0,0,.06);
}
.al-badge--on{ background: var(--good); color:#fff; }
.al-badge--off{ background:#eef2f7; color:#b7bfc9; }
.card-prices{ display:flex; flex-direction:column; gap:.15rem; margin-top:.2rem; }
.price-row{ display:flex; justify-content:space-between; font-size:.82rem; padding:.15rem 0; border-top:1px dashed var(--line); }
.price-row:first-child{ border-top:none; }
.price-label{ color: var(--ink-soft); }
.price-value{ font-weight:700; }
.price-value.empty{ color:#b7bfc9; font-weight:500; }
.price-row.highlight .price-value{ color: var(--good); }

.card-actions{
  padding:.7rem .8rem; display:flex; align-items:center; gap:.5rem; border-top:1px solid var(--line); margin-top:.4rem;
}
.qty-input{
  width:3.4em; padding:.4em .3em; text-align:center; border:1px solid var(--line); border-radius:8px;
}
.card-actions .btn{ flex:1; }
.card-actions .btn.added{ background: var(--good); border-color: var(--good); color:#fff; }

.load-more-wrap{ display:flex; justify-content:center; margin:1.3rem 0; }
.empty-state{ text-align:center; color: var(--ink-soft); padding:2.5rem 1rem; font-size:.95rem; }

.app-footer{
  text-align:center; color: var(--ink-soft); font-size:.78rem; padding:1.5rem 1rem 2.5rem;
}

/* ---------- drawer (proposta) ---------- */
.drawer-overlay, .modal-overlay{
  position:fixed; inset:0; background:rgba(15,20,30,.45); z-index:40;
}
.drawer{
  /* mais larga do que a janela base (pedido: "maior amplitude... para se conseguir ver
     melhor os campos sem ter que descer tanto"), com um mínimo confortável para não ficar
     demasiado estreito em ecrãs pequenos — em telemóvel usa a largura toda (ver media query
     mais abaixo). Combinado com o grid de .doc-settings abaixo (vários campos por linha),
     evita o espaço em branco lateral que havia com uma única coluna de campos. */
  position:fixed; top:0; right:0; bottom:0; width:clamp(480px, 58vw, 1080px);
  background:#fff; z-index:41; display:flex; flex-direction:column;
  box-shadow:-8px 0 30px rgba(0,0,0,.2);
}
.drawer-header{
  display:flex; align-items:center; justify-content:space-between;
  padding:1rem 1.1rem; border-bottom:1px solid var(--line);
}
.drawer-header h2{ margin:0; font-size:1.1rem; }
.drawer-body{ flex:1; overflow-y:auto; padding:1rem 1.1rem; }
.drawer-footer{
  display:flex; flex-direction:column; gap:.6rem; padding:1rem 1.1rem; border-top:1px solid var(--line);
}
.drawer-footer #docStatus{ margin:0; }
.drawer-footer-actions{ display:flex; gap:.6rem; flex-wrap:wrap; }
.drawer-footer-actions .btn{ flex:1; min-width:130px; }
.drawer-footer-actions .btn:disabled{ opacity:.5; cursor:not-allowed; }

/* grid com vários campos por linha (mesmo padrão de .search-grid) — em vez de uma única
   coluna onde cada campo ocupava a largura toda da drawer, mesmo sendo estreito, deixando
   muito espaço em branco (pedido: "não precisa ocupar a linha de um lado ao outro"). Os
   campos "normais" (.field) e os que já vinham em .field-row (ex: Email/Telefone,
   Data/Validade) entram todos no mesmo grid — .field-row passa a "invisível" no layout
   (display:contents) para os seus campos ficarem lado a lado com os restantes, em vez de
   ficarem espremidos os dois juntos numa só coluna do grid. Only #moradaTextoField (que já
   tem a sua própria estrutura interna com sub-linha CP/Localidade) e as Notas/condições
   (textarea, .field-grow) continuam a ocupar a linha toda. */
.doc-settings{
  display:grid; grid-template-columns: repeat(auto-fit, minmax(200px,1fr));
  gap:.6rem .9rem; margin-bottom:1rem; align-items:start;
}
.doc-settings .field-row{ display:contents; }
.doc-settings #moradaTextoField{ grid-column: 1 / -1; }
/* V187.5 — o cartão do cliente ocupa a linha toda. Encaixado numa célula de 200px da grelha
   ficava com o nome e o aviso partidos em quatro linhas e o botão apertado contra o texto
   (visível numa captura de ecrã de quem o usou). É o cabeçalho do documento, não um campo. */
.doc-settings .doc-cliente{ grid-column: 1 / -1; margin-bottom:0; }
#moradaTextoField{ display:flex; flex-direction:column; gap:.6rem; }
.col-toggles{
  background: var(--bg); border:1px solid var(--line); border-radius:10px; padding:.7rem .8rem; margin-bottom:1rem;
}
.col-toggles-title{ font-size:.78rem; font-weight:700; color: var(--ink-soft); margin:0 0 .5rem; }
.col-toggles-grid{ display:grid; grid-template-columns: 1fr 1fr; gap:.4rem .8rem; font-size:.85rem; }
.col-toggles-grid label, .show-images-toggle{ display:flex; align-items:center; gap:.4rem; cursor:pointer; }
.show-images-toggle{ margin-top:.5rem; font-size:.85rem; border-top:1px dashed var(--line); padding-top:.5rem; }

.proposal-item{
  border:1px solid var(--line); border-radius:10px; padding:.7rem .8rem; margin-bottom:.6rem; display:flex; gap:.7rem;
}
/* V188.6 — coluna da esquerda: miniatura em cima, setas de mover por baixo. */
/* A largura da coluna da esquerda num sítio só: a miniatura e os botões por baixo têm de ter
   exatamente a mesma, e escrevê-la duas vezes garantia que mais cedo ou mais tarde uma mudava
   sem a outra. */
.proposal-item-esq{
  --largura-miniatura: 52px;
  display:flex; flex-direction:column; align-items:center; gap:.35rem; flex-shrink:0;
}
.proposal-item img{
  width:var(--largura-miniatura, 52px); height:52px; object-fit:contain;
  border:1px solid var(--line); border-radius:6px; background:#fff; flex-shrink:0;
}
/* V188.9 — a pega e as setas alinhadas à largura da imagem (52px), em duas linhas: a pega
   ocupa a linha toda, as setas dividem a de baixo ao meio. Encolhidas a 12px como estavam,
   eram alvos pequenos de mais para um dedo num tablet — e é no terreno que estes ecrãs mais
   se usam. flex-wrap com a pega a 100% é o que faz as setas passarem para a linha seguinte. */
.proposal-item-esq .proposal-item-move{
  flex-direction:row; flex-wrap:wrap; align-items:center; justify-content:space-between;
  width:var(--largura-miniatura); gap:.15rem;
}
.proposal-item-esq .proposal-item-drag{
  width:100%; text-align:center; font-size:1rem; line-height:1;
  padding:.2rem 0; border:1px solid var(--line); border-radius:5px; background:#fff;
}
.proposal-item-esq .btn-move{
  flex:1 1 0; min-width:0; padding:.25rem 0; font-size:.75rem; text-align:center;
}
.proposal-item-body{ flex:1; min-width:0; }
.proposal-item-top{ display:flex; justify-content:space-between; gap:.5rem; align-items:flex-start; }
.proposal-item-top-actions{ display:flex; align-items:center; gap:.3rem; flex-shrink:0; }
.proposal-item-ref{ font-size:.72rem; font-weight:800; color: var(--brand); }
.proposal-item-desc{ font-size:.82rem; margin:.1rem 0 .4rem; line-height:1.25; }
.proposal-item-remove{ background:none; border:none; color:#b23a3a; cursor:pointer; font-size:.9rem; flex-shrink:0; }
.proposal-item-row{ display:flex; align-items:center; gap:.6rem; flex-wrap:wrap; font-size:.78rem; }
.proposal-item-qty{ display:flex; align-items:center; gap:.3rem; }
.proposal-item-qty input{ width:3em; padding:.25em; text-align:center; border:1px solid var(--line); border-radius:6px; }
.proposal-item-qty select.proposal-item-tipo{ width:auto; padding:.25em .4em; border:1px solid var(--line); border-radius:6px; background:#fff; }
/* Proposta / Lista de Preços: uma linha por tipo de preço (Original/Compatível/Lowcost/
   Cx.10un), com o checkbox para incluir esse tipo na linha, o PVP logo a seguir ao nome e,
   quando aplicável, o seu próprio campo "DESC %" (maior, mais visível) com o preço já com
   desconto logo a seguir — para poder dar descontos diferentes a cada tipo na mesma linha. */
.proposal-item-tipos{ display:flex; flex-direction:column; gap:.4rem; margin-top:.4rem; padding-top:.4rem; border-top:1px dashed var(--line); }
.proposal-item-tipo-row{ display:flex; align-items:center; gap:.6rem; flex-wrap:wrap; font-size:.78rem; }
.proposal-item-tipo-check{ display:flex; align-items:center; gap:.3rem; color: var(--ink-soft); cursor:pointer; flex:1 1 auto; min-width:100px; }
.proposal-item-tipo-check input{ transform: scale(.9); }
.proposal-item-tipo-preco{ font-weight:600; color: var(--ink); }
.proposal-item-tipo-preco-final{ font-weight:800; color: var(--brand); }
/* campo de desconto maior/mais visível (pedido explícito) — usado tanto nas linhas por tipo
   (Proposta/Lista de Preços) como no desconto único da Encomenda. */
.proposal-item-desconto-wrap{ font-weight:700; }
.proposal-item-qty input.proposal-item-desconto-lg{
  width:4.4em; padding:.4em .3em; font-size:.95rem; font-weight:700; border-width:2px; border-color: var(--brand);
}
/* nota opcional por produto — pequena e discreta, fica em cinza-claro por baixo da linha no
   PDF (ver "Nota:" em lib/pdf_documento.php e o print-fallback em criarDocumento()). */
.proposal-item-nota-wrap{ margin-top:.4rem; }
.proposal-item-nota{
  width:100%; padding:.35em .5em; font-size:.76rem; color: var(--ink-soft);
  border:1px dashed var(--line); border-radius:6px; background:transparent;
}
.proposal-item-nota:focus{ color: var(--ink); border-style:solid; }

.proposal-item-vert-actions{ display:flex; flex-direction:column; align-items:center; gap:.25rem; }
.proposal-item-add-variante{
  background:none; border:1px solid var(--line); border-radius:5px; color: var(--brand);
  cursor:pointer; font-size:.72rem; line-height:1; padding:.1rem .25rem; flex-shrink:0;
}
.proposal-item-add-variante:hover{ background: var(--bg); }

.proposal-item-move{ display:flex; flex-direction:column; align-items:center; gap:.1rem; }
/* pega para arrastar a linha (arrastar-e-largar) — complementa as setas ▲▼, que continuam
   totalmente funcionais (ver attachDragHandlers() em js/app.js). */
.proposal-item-drag{
  cursor:grab; color: var(--ink-soft); font-size:.85rem; line-height:1; padding:.1rem 0; user-select:none;
}
.proposal-item-drag:active{ cursor:grabbing; }
.proposal-item.dragging, .proposal-separador.dragging{ opacity:.45; }
.proposal-item.drag-over, .proposal-separador.drag-over{
  outline:2px dashed var(--brand); outline-offset:2px;
}
.btn-move{
  background:#fff; border:1px solid var(--line); border-radius:5px; cursor:pointer;
  font-size:.68rem; line-height:1; padding:.15rem .3rem; color: var(--ink-soft);
}
.btn-move:hover:not(:disabled){ background: var(--bg); color: var(--ink); }
.btn-move:disabled{ opacity:.35; cursor:not-allowed; }

#btnAddSeparador{ width:100%; margin-top:-.1rem; margin-bottom:.8rem; }
.proposal-separador{
  border:1px dashed #b9c2cf; border-radius:10px; padding:.5rem .6rem; margin-bottom:.6rem; background: var(--bg);
}
.proposal-separador-row{ display:flex; align-items:center; gap:.5rem; }
.proposal-separador-nota{
  flex:1; min-width:0; padding:.45em .6em; border:1px solid var(--line); border-radius:8px; font-size:.85rem; font-weight:600;
}

/* ---------- modal ---------- */
.modal{
  position:fixed; top:50%; left:50%; transform:translate(-50%,-50%);
  background:#fff; border-radius: var(--radius); z-index:41; width:min(520px,92vw);
  max-height:88vh; display:flex; flex-direction:column; box-shadow:0 20px 60px rgba(0,0,0,.3);
}
.modal-lg{ width:min(640px,92vw); }
.modal-xl{ width:min(1100px,95vw); max-height:92vh; }
.modal > form{ display:flex; flex-direction:column; min-height:0; }
.modal-header{
  display:flex; align-items:center; justify-content:space-between; padding:1rem 1.2rem; border-bottom:1px solid var(--line);
}
.modal-header h2{ margin:0; font-size:1.05rem; }
.modal-body{ padding:1rem 1.2rem; overflow-y:auto; display:flex; flex-direction:column; gap:.8rem; min-height:0; }
.modal-footer{ padding:1rem 1.2rem; border-top:1px solid var(--line); display:flex; justify-content:flex-end; }

.admin-msg{ padding:.6rem .8rem; border-radius:8px; font-size:.85rem; }
.admin-msg.ok{ background:#e9f7ef; color:#1e6b3d; }
.admin-msg.erro{ background:#fdecea; color:#8a1f11; }
.admin-hint{ color: var(--ink-soft); font-size:.82rem; margin:0; }
.checkbox-row{ display:flex; align-items:center; gap:.5rem; font-size:.88rem; font-weight:600; }
.checkbox-row input{ transform:scale(1.15); }

/* ---------- tabelas simples (ex: "Os meus documentos") ---------- */
.table-wrap{ overflow-x:auto; }
.admin-table{ width:100%; border-collapse:collapse; font-size:.86rem; }
.admin-table th, .admin-table td{ text-align:left; padding:.55rem .6rem; border-bottom:1px solid var(--line); white-space:nowrap; }
.admin-table th{ color: var(--ink-soft); font-weight:700; font-size:.78rem; text-transform:uppercase; letter-spacing:.02em; }
.admin-table td.wrap{ white-space:normal; }
.admin-table tbody tr:hover{ background: var(--bg); }
.doc-actions{ display:flex; gap:.4rem; flex-wrap:wrap; }

.perfil-logo-preview{ display:flex; align-items:center; gap:.7rem; margin-top:-.3rem; }
.perfil-logo-preview img{ max-height:52px; max-width:140px; border:1px solid var(--line); border-radius:8px; background:#fff; padding:.2rem; }

.perfil-moradas{ margin-top:.4rem; padding-top:.9rem; border-top:1px solid var(--line); }
.perfil-moradas .admin-card-head{ display:flex; align-items:center; justify-content:space-between; gap:1rem; margin-bottom:.6rem; }
.perfil-moradas h3{ margin:0; font-size:.95rem; }
.morada-row{
  display:flex; align-items:center; justify-content:space-between; gap:.8rem;
  padding:.6rem 0; border-bottom:1px solid var(--line); font-size:.86rem;
}
.morada-row:last-child{ border-bottom:none; }
.morada-row-info strong{ display:block; }
.morada-row-info span{ color: var(--ink-soft); font-size:.82rem; }
.morada-row-padrao{
  display:inline-block; margin-left:.4rem; padding:.1em .5em; border-radius:999px;
  font-size:.7rem; font-weight:700; background:#e9f7ef; color:#1e6b3d;
}

.detail-grid{ display:flex; gap:1rem; flex-wrap:wrap; }
.detail-img{ width:160px; height:160px; object-fit:contain; border:1px solid var(--line); border-radius:10px; background:#fff; flex-shrink:0; }
.detail-info{ flex:1; min-width:200px; }
.detail-info .card-tags{ margin-bottom:.5rem; }
.detail-prices{ width:100%; border-collapse:collapse; margin-top:.8rem; }
.detail-prices td{ padding:.4rem .3rem; border-top:1px solid var(--line); font-size:.88rem; }
.detail-prices td:last-child{ text-align:right; font-weight:700; }
.detail-text{ white-space:pre-line; font-size:.83rem; line-height:1.5; color: var(--ink-soft); max-height:220px; overflow-y:auto; border-top:1px solid var(--line); padding-top:.6rem; }

/* ---------- toast ---------- */
.toast{
  position:fixed; left:50%; bottom:1.3rem; transform:translateX(-50%);
  background: var(--ink); color:#fff; padding:.7em 1.2em; border-radius:999px; font-size:.85rem;
  z-index:60; box-shadow:0 8px 24px rgba(0,0,0,.25);
}

/* ---------- responsive ---------- */
@media (max-width: 640px){
  .topbar-actions .btn span:not(.badge){ display:none; }
  .topbar-actions .btn{ padding:.6em .8em; }
  .brand-text span{ display:none; }
  .brand-text strong{ font-size:.95rem; max-width:38vw; }
  .grid{ grid-template-columns: repeat(auto-fill, minmax(155px,1fr)); gap:.6rem; }
  .card-desc{ -webkit-line-clamp:2; min-height:2.2em; }
  .drawer{ width:100%; }
}

/* ================================================================
   IMPRESSÃO / PDF
   ================================================================ */
.print-area{ display:none; }

@media print{
  @page{ size: A4; margin: 14mm 12mm; }
  html,body{ background:#fff !important; }
  .app-chrome, .drawer-overlay, .drawer, .modal-overlay, .modal, .toast{ display:none !important; }

  .print-area{
    display:block !important;
    color:#111; font-family: Arial, Helvetica, sans-serif; font-size:11px;
  }
  .print-header{
    display:flex; justify-content:space-between; align-items:flex-start;
    border-bottom:2px solid #111; padding-bottom:10px; margin-bottom:12px;
  }
  .print-header img{ max-height:56px; max-width:180px; object-fit:contain; }
  .print-company strong{ font-size:15px; display:block; }
  .print-doc-title{ text-align:right; }
  .print-doc-title h1{ margin:0; font-size:17px; }
  .print-doc-title p{ margin:2px 0 0; font-size:10px; color:#444; }

  /* cabeçalho de duas colunas: esquerda = comercial associado (autor do documento),
     direita = informação do cliente — ver criarDocumento() em js/app.js */
  .print-meta{
    display:flex; justify-content:space-between; gap:10px 24px; margin-bottom:12px; font-size:10.5px;
  }
  .print-meta-col{ flex:1 1 45%; min-width:150px; }
  .print-meta-cliente{ text-align:right; }
  .print-meta div{ margin-bottom:3px; }
  .print-meta strong{ display:block; font-size:9px; text-transform:uppercase; color:#666; letter-spacing:.03em; margin-bottom:2px; }
  .print-meta-empresa span{ display:block; font-size:9.5px; color:#555; }

  table.print-table{ width:100%; border-collapse:collapse; margin-bottom:10px; }
  table.print-table th, table.print-table td{
    border:1px solid #ccc; padding:5px 6px; text-align:left; font-size:10.5px; vertical-align:middle;
  }
  table.print-table th{ background:#eef2f7; font-size:9.5px; text-transform:uppercase; letter-spacing:.02em; }
  table.print-table td.num, table.print-table th.num{ text-align:right; white-space:nowrap; }
  table.print-table img{ width:34px; height:34px; object-fit:contain; }
  table.print-table tr{ break-inside: avoid; }
  table.print-table tr.print-row-separador td{
    background:#eef2f7; font-weight:700; color:#334; border-top:2px solid #ccc; padding-top:8px; padding-bottom:8px;
  }
  /* nota opcional por produto (ver .proposal-item-nota no ecrã) — pequena e em cinza, sem
     grade própria, logo abaixo da linha do produto a que pertence. */
  table.print-table tr.print-row-nota td{
    border-top:none; padding-top:0; padding-bottom:6px; font-size:9px; color:#777; font-style:italic;
  }
  table.print-table tr.print-row-nota em{ font-style:normal; font-weight:700; }
  /* Proposta/Lista de Preços, quando há desconto: PVP e "Desc. X%" pequenos/cinza (menos
     salientes), com o preço já com desconto por baixo, maior e a negrito — o mais saliente, por
     ser o valor que interessa ao cliente (ver criarDocumento() em js/app.js). */
  .print-preco-orig{ display:block; font-size:8.5px; font-weight:normal; color:#82898f; line-height:1.3; }
  .print-preco-final{ display:block; font-size:12px; font-weight:bold; color:#111; margin-top:2px; }
  /* Lista de Preços: nota indicando que os preços são por unidade (não tem coluna de Qtd). */
  .print-preco-unidade-nota{ font-size:9.5px; color:#666; margin:-2px 0 8px; }

  .print-total{ text-align:right; font-size:13px; font-weight:bold; margin-top:6px; }
  .print-totais{ text-align:right; font-size:12px; margin-top:8px; line-height:1.7; }
  .print-totais div{ margin:0; }
  .print-totais strong{ font-size:13px; }
  .print-notes{ margin-top:16px; font-size:10px; color:#333; white-space:pre-line; border-top:1px solid #ccc; padding-top:8px; }
  .print-legal{ margin-top:10px; font-size:8.5px; color:#666; border-top:1px solid #ddd; padding-top:6px; line-height:1.4; }
  .print-legal p{ margin:0 0 3px; }
  .print-legal p:last-child{ margin-bottom:0; }
  .print-footer{ margin-top:12px; font-size:9px; color:#777; text-align:center; }
}

/* V63 — módulo de Propostas de Equipamentos: equipamento já guardado na proposta. Fica em
   leitura, com uma marca visual discreta, para não se mexer nele sem querer enquanto se monta o
   seguinte. O botão "Editar" reabre-o. */
.linha-fechada{ border-left:3px solid #1b6b3a; background:#fbfdfb; }
.linha-fechada h2{ color:#1b6b3a; }

/* V64 — barra fixa mostrada sobre o módulo de Impressão quando se está a escolher consumíveis
   para um equipamento da proposta. Fica no fundo do ecrã para não tapar a grelha de produtos. */
.peq-barra-consumiveis{
  position:fixed; left:0; right:0; bottom:0; z-index:900;
  display:flex; align-items:center; gap:.8rem; flex-wrap:wrap;
  padding:.7rem 1rem; background:#12314d; color:#fff;
  box-shadow:0 -2px 10px rgba(0,0,0,.2);
}
.peq-barra-consumiveis span{ flex:1 1 260px; }
/* Linhas do quadro "o que o cliente vai ver": desmarcadas ficam esbatidas, e as puramente
   internas (valor do pack, serviço mensal) ficam sempre em cinzento. */
.tbl tr.linha-oculta td{ opacity:.45; }
.tbl tr.linha-interna td{ color:#6b7684; font-size:.9em; }
/* V68 — tabela de consumíveis dentro da proposta de equipamento, no mesmo formato da Lista de
   Preços: quando há desconto, o PVP e a percentagem ficam pequenos por cima do preço final. */
.tbl .preco-antes{ color:#6b7684; font-size:.82em; }
.tbl .preco-vazio{ color:#aab2bd; }

/* V79 — promoções. Estrela no canto da imagem do produto, com a percentagem, e a linha de preço
   com o PVP riscado, o desconto e o valor final em destaque. */
.card-img{ position:relative; }
.promo-star{
  position:absolute; top:6px; right:6px; z-index:2;
  display:inline-flex; align-items:center; gap:.2rem;
  background:#c8102e; color:#fff; font-weight:700; font-size:.78rem;
  padding:.18rem .42rem .18rem .34rem; border-radius:999px;
  box-shadow:0 1px 4px rgba(0,0,0,.25); line-height:1;
}
.promo-star-pct{ font-size:.74rem; }
.price-row.promo .price-value{ white-space:nowrap; }
.promo-antes{ color:#8b95a1; font-size:.86em; }
.promo-pct{ color:#c8102e; font-weight:700; font-size:.86em; }
.promo-final{ color:#12314d; }
/* V84 — etiqueta da campanha e condição de quantidade, visíveis no cartão e não só no título da
   estrela: é o que transforma a promoção num argumento de venda. */
.promo-etiqueta{
  position:absolute; left:6px; bottom:6px; z-index:2; max-width:calc(100% - 12px);
  background:#12314d; color:#fff; font-weight:600; font-size:.72rem;
  padding:.16rem .4rem; border-radius:4px; line-height:1.2;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.promo-qtd{
  position:absolute; right:6px; top:28px; z-index:2;
  background:#fff; color:#c8102e; border:1px solid #c8102e; font-weight:600; font-size:.68rem;
  padding:.1rem .32rem; border-radius:999px; line-height:1.2;
}
.promo-qtd-nota{ color:#6b7684; }
/* V85 — imagem e descrição clicáveis nos módulos Escritório e Informática, como no Impressão. */
.card-img{ cursor:pointer; }
.card-desc{ cursor:pointer; }
.card-tag.promo-tag{ background:#c8102e; color:#fff; border-color:#c8102e; }

/* =====================================================================================
   V94 — GEOLOCALIZAÇÃO, ROTAS E MAPEAMENTO COMERCIAL
   Aviso de localização nos documentos (.geo-aviso*) e módulo Mapa & Rotas (.geo-layout ...).
   Também carregado pelo back office (admin/index.php inclui esta folha).
   ===================================================================================== */

/* ---- aviso no painel de documentos / propostas ---- */
.geo-aviso{
  margin:.2rem 0 .8rem; padding:.7rem .8rem; border-radius:10px;
  border:1px solid var(--line); border-left:4px solid var(--brand); background:#f5f9fd;
  font-size:.86rem;
}
.geo-aviso[hidden]{ display:none; }
.geo-aviso-texto{ margin:0 0 .35rem; line-height:1.4; }
.geo-aviso-texto:last-child{ margin-bottom:0; }
.geo-aviso-nota{ color: var(--ink-soft); font-size:.8rem; }
.geo-aviso-acoes{ display:flex; flex-wrap:wrap; gap:.4rem; margin-top:.5rem; }
.geo-aviso-escolha{ width:100%; padding:.5em .6em; border:1px solid var(--line); border-radius:8px; background:#fff; }
.geo-aviso-novo{ border-left-color: var(--warn); background:#fff7f0; }
.geo-aviso-pergunta{ border-left-color: var(--warn); background:#fff7f0; }
.geo-aviso-ok{ border-left-color: var(--good); background:#f1f9f4; }
.geo-aviso-divergente{ border-left-color: var(--warn); background:#fff7f0; }
.geo-aviso-erro{ border-left-color:#c0392b; background:#fdecea; color:#8a1f11; }
.geo-aviso-neutro{ border-left-color:#c3cad4; background:#f7f8fa; color: var(--ink-soft); }
.geo-aviso-divergencia{ color: var(--warn); }

/* ---- módulo Mapa & Rotas ---- */
.geo-layout{
  max-width: var(--maxw); margin:0 auto; padding:1rem;
  display:grid; gap:1rem; grid-template-columns: minmax(300px, 390px) 1fr; align-items:start;
}
.geo-painel{ margin:0; min-width:0; }
.geo-titulo{ grid-column:1 / -1; margin:0; font-size:1.2rem; }
.geo-tabs{ display:flex; gap:.4rem; flex-wrap:wrap; margin-bottom:.6rem; }
.geo-painel .module-msg{ margin:.2rem 0 .6rem; font-size:.84rem; color: var(--ink-soft); min-height:0; }
.geo-painel .module-msg:empty{ display:none; }
.geo-painel .module-msg.erro{ color:#8a1f11; background:#fdecea; padding:.5rem .7rem; border-radius:8px; }
.geo-filtros{ display:grid; gap:.6rem; margin-bottom:.7rem; }
.geo-check{ display:flex; align-items:center; gap:.45rem; font-size:.85rem; cursor:pointer; }
.geo-check input{ width:auto; margin:0; }
.geo-acoes{ display:flex; flex-wrap:wrap; gap:.4rem; }
.geo-resumo{ font-size:.8rem; color: var(--ink-soft); margin:.2rem 0 .5rem; }
.geo-nota{ font-size:.78rem; color: var(--ink-soft); margin:.4rem 0; line-height:1.4; }
.geo-lista{ list-style:none; margin:0; padding:0; max-height:52vh; overflow:auto; border-top:1px solid var(--line); }
.geo-lista-rota{ max-height:none; margin-bottom:.7rem; }
.geo-item{ display:flex; align-items:center; gap:.55rem; padding:.5rem .1rem; border-bottom:1px solid var(--line); }
.geo-item-texto{ flex:1; min-width:0; display:flex; flex-direction:column; }
.geo-item-texto strong{ font-size:.86rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.geo-item-texto small{ font-size:.75rem; color: var(--ink-soft); }
.geo-item-acoes{ display:flex; gap:.3rem; flex-wrap:wrap; justify-content:flex-end; }
.geo-ponto{ display:inline-block; width:12px; height:12px; border-radius:50%; flex:0 0 12px; border:2px solid #fff; box-shadow:0 0 0 1px #c3cad4; vertical-align:middle; }
.geo-mapa-wrap{
  position:sticky; top:1rem; background: var(--card); border:1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow); overflow:hidden;
}
.geo-mapa{ height: calc(100vh - 170px); min-height:420px; width:100%; }
.geo-legenda{ display:flex; flex-wrap:wrap; gap:.3rem .9rem; padding:.5rem .8rem; border-top:1px solid var(--line); font-size:.78rem; }
.geo-legenda[hidden]{ display:none; }
.geo-legenda-item{ display:inline-flex; align-items:center; gap:.35rem; }
.leaflet-marker-icon.geo-num{ background:none; border:none; }
.geo-num span{
  display:flex; align-items:center; justify-content:center; width:26px; height:26px; border-radius:50%;
  background: var(--brand); color:#fff; font-weight:800; font-size:.8rem; border:2px solid #fff;
  box-shadow:0 1px 4px rgba(0,0,0,.35);
}
.geo-num-partida span{ background: var(--ink); }
.geo-num-lista{
  flex:0 0 24px; width:24px; height:24px; border-radius:50%; background: var(--brand); color:#fff;
  display:flex; align-items:center; justify-content:center; font-size:.75rem; font-weight:800;
}
.geo-rota-total{ display:flex; flex-direction:column; gap:.15rem; padding:.6rem .7rem; margin:.6rem 0; border-radius:10px; background:#f5f9fd; }
.geo-rota-total strong{ font-size:1.05rem; }
.geo-rota-total small{ color: var(--ink-soft); font-size:.78rem; }
.geo-rota-total .geo-etiqueta-aviso{ align-self:flex-start; }
.geo-texto-aviso{ color: var(--warn); font-size:.8rem; margin:.2rem 0; }
.geo-etiqueta-aviso{ display:inline-block; background: var(--warn); color:#fff; border-radius:999px; padding:.05em .55em; font-size:.72rem; font-weight:700; vertical-align:middle; }
.geo-links{ display:flex; flex-direction:column; gap:.4rem; margin:.5rem 0; }
.geo-links .btn{ white-space:normal; text-align:center; }
.geo-popup{ font-size:.84rem; line-height:1.45; min-width:190px; }
.geo-popup-acoes{ display:flex; flex-wrap:wrap; gap:.3rem; margin-top:.5rem; }
.geo-popup .btn{ padding:.3em .6em; font-size:.76rem; }
.geo-tabela{ width:100%; border-collapse:collapse; font-size:.8rem; margin-top:.4rem; }
.geo-tabela th, .geo-tabela td{ text-align:left; padding:.35rem .3rem; border-bottom:1px solid var(--line); }
.geo-tabela th{ color: var(--ink-soft); font-weight:700; font-size:.74rem; }

@media (max-width: 900px){
  .geo-layout{ grid-template-columns: 1fr; padding:.6rem; }
  .geo-titulo{ order:-2; }
  .geo-mapa-wrap{ position:static; order:-1; }
  .geo-mapa{ height:55vh; min-height:300px; }
  .geo-lista{ max-height:none; }
}
@media (prefers-reduced-motion: reduce){
  .leaflet-zoom-anim .leaflet-zoom-animated{ transition:none !important; }
}

/* =====================================================================================
   V95 — campos de NIF (js/nif.js) e janela "Localizar cliente" (js/geolocalizacao.js)
   ===================================================================================== */
input.nif-invalido{ border-color:#c0392b !important; outline-color:#c0392b; }
.nif-erro{ display:block; color:#8a1f11; font-size:.76rem; margin-top:.25rem; }
.nif-erro[hidden]{ display:none; }

.geo-procurar-barra{ display:flex; gap:.5rem; align-items:flex-end; }
.geo-procurar-barra .field{ flex:1; }
.geo-procurar-lista{ max-height:50vh; }
.geo-procurar-lista[hidden]{ display:none; }
.geo-procurar-lista li{ border-bottom:1px solid var(--line); }
.geo-procurar-item{
  display:flex; align-items:center; gap:.6rem; width:100%; padding:.6rem .3rem;
  background:none; border:none; text-align:left; cursor:pointer; font:inherit; color:inherit;
}
.geo-procurar-item:hover{ background:#f5f9fd; }
.geo-procurar-item:focus-visible{ outline:2px solid var(--brand); outline-offset:-2px; }
.geo-estado{ flex:0 0 auto; font-size:.74rem; color: var(--ink-soft); background:#f1f3f6; border-radius:999px; padding:.15em .6em; white-space:nowrap; }
.geo-estado-ok{ color: var(--good); background:#e9f7ef; }
#geoProcurarCliente{ display:flex; flex-direction:column; gap:.5rem; align-items:flex-start; }
#geoProcurarCliente[hidden]{ display:none; }
#geoProcurarCliente .geo-aviso{ align-self:stretch; margin:0; }
@media (max-width: 640px){
  .geo-procurar-barra{ flex-direction:column; align-items:stretch; }
}

/* =====================================================================================
   V96 — Novo contacto (js/contactos.js)
   ===================================================================================== */
#contactoModal .modal-body{ gap:.6rem; }
#contactoModal .field[hidden], #contactoModal .field-row[hidden], #contactoModal .geo-nota[hidden]{ display:none; }
#contactoModal .geo-aviso{ margin:0; }
.contacto-rodape{ gap:.5rem; }
.contacto-rodape [hidden]{ display:none; }
.contacto-dup-lista{ max-height:34vh; margin:.4rem 0; background:#fff; border-radius:8px; }
.contacto-dup{ display:flex; align-items:center; gap:.5rem; padding:.45rem .5rem; border-bottom:1px solid var(--line); }
.contacto-dup .geo-item-texto small{ white-space:normal; }
.geo-procurar-vazio{ padding:.6rem .3rem; border-bottom:none !important; }
@media (max-width: 640px){
  #contactoModal .field-row{ flex-direction:column; gap:.6rem; }
}

/* V96 — barra de cima no telemóvel. Com os botões 📍 Localizar cliente e 👤 Novo contacto a
   barra deixou de caber num ecrã de telemóvel (o nome da empresa desaparecia e a página ganhava
   deslocação lateral). Até 640px os botões ficam mais compactos; até 440px o nome da empresa
   passa para uma linha própria e os botões ocupam a linha de baixo, pela mesma ordem. */
@media (max-width: 640px){
  .topbar-inner{ padding:.5rem .6rem; gap:.4rem; }
  .topbar-actions{ gap:.1rem; }
  .topbar-actions .btn{ padding:.5em .45em; }
  .atualizar-wrap .app-version-tag{ font-size:.58rem; }
}
@media (max-width: 440px){
  .topbar-inner{ flex-wrap:wrap; }
  .brand{ flex:1 1 auto; }
  .topbar-actions{ flex:1 1 100%; flex-wrap:wrap; justify-content:space-between; }
}

/* V99 — barra de cima em ecrãs de computador. Com os botões 📍 Localizar cliente e 👤 Novo
   contacto, a barra deixou de caber em portáteis (1366 px e menos, ou ecrãs maiores com o
   Windows a 125%/150%): o nome da empresa era esmagado e "Proposta", "Atualizar" e "Sair"
   ficavam fora do ecrã. Regras, só acima de 640 px (o telemóvel tem as suas, acima):
     - os botões nunca saem do ecrã: se não couberem, passam para uma segunda linha;
     - o nome da empresa nunca é esmagado;
     - os botões secundários (Admin, Palavra-passe, Definições, O meu perfil, Atualizar,
       Sair) ficam só com o ícone — o nome aparece ao passar o rato (title). A barra tem a
       largura do conteúdo (1280 px, --maxw), por isso isto vale mesmo em ecrãs grandes;
     - abaixo de 1100 px, o mesmo para Documentos.
   Localizar cliente, Novo contacto e Proposta mantêm sempre o texto no computador. */
@media (min-width: 641px){
  .brand{ flex-shrink:0; max-width:34%; }
  .topbar-actions{ flex-shrink:1; min-width:0; flex-wrap:wrap; justify-content:flex-end; row-gap:.35rem; }
}
@media (min-width: 641px){
  #btnAdmin span, #btnMeuPerfil span, #btnChangePassword span, #btnSettings span, #btnAtualizar span, #btnLogout span{ display:none; }
  .topbar-actions{ gap:.3rem; }
  .topbar-actions .btn{ padding:.5em .7em; }
  .user-tag{ max-width:12rem; overflow:hidden; text-overflow:ellipsis; }
}
@media (min-width: 641px) and (max-width: 1100px){
  #btnDocumentos span{ display:none; }
  .user-tag{ display:none; }
  .brand-text span{ display:none; }
}

/* =====================================================================================
   AGENDA (V100)
   =====================================================================================
   Usa as variáveis do topo do ficheiro, para acompanhar qualquer mudança de cor da marca
   sem ter de ser revisto. Pensado primeiro para o telemóvel — é onde o comercial o usa,
   no carro e à porta do cliente — e só depois alargado para o computador. */

.agenda-topo{
  display:flex; flex-wrap:wrap; gap:.5rem; align-items:center;
  padding:.75rem; background:var(--card); border:1px solid var(--line);
  border-radius:var(--radius); box-shadow:var(--shadow); margin-bottom:.75rem;
}
.agenda-nav{ display:flex; gap:.35rem; align-items:center; }
.agenda-titulo{ margin-left:.5rem; font-size:1.05rem; }
.agenda-vistas, .agenda-acoes{ display:flex; gap:.35rem; flex-wrap:wrap; }
.agenda-acoes{ margin-left:auto; }

.agenda-lista{ display:flex; flex-direction:column; gap:.5rem; }

/* Cartão de compromisso. A borda esquerda leva a cor do tipo, definida no back office. */
.agenda-cartao{
  display:grid; gap:.15rem; width:100%; text-align:left; cursor:pointer;
  padding:.6rem .75rem; background:var(--card); border:1px solid var(--line);
  border-left:4px solid var(--ink-soft); border-radius:var(--radius); box-shadow:var(--shadow);
  font:inherit; color:inherit;
}
.agenda-cartao:hover{ border-color:var(--brand-light); }
.agenda-hora{ font-weight:600; color:var(--brand); font-size:.9rem; }
.agenda-tit{ font-weight:600; }
.agenda-cli{ color:var(--ink-soft); font-size:.9rem; }
.agenda-meta{ color:var(--ink-soft); font-size:.8rem; }
/* Convite por responder: destacado sem depender só da cor, para quem não a distingue. */
.agenda-pendente{ border-left-style:dashed; background:#fffdf5; }
.agenda-sinal{ margin-left:.35rem; font-size:.85em; }

.etiqueta{
  display:inline-block; padding:.1rem .45rem; border-radius:999px;
  font-size:.75rem; font-weight:600; background:var(--bg); color:var(--ink-soft);
}
.estado-agendado{ background:#e8f1fb; color:var(--brand-dark); }
.estado-em-curso{ background:#e6f4ea; color:var(--good); }
.estado-atraso{ background:#fdeaea; color:#a01b1b; }
.estado-concluido{ background:#eef1f4; color:var(--ink-soft); }
.estado-cancelado{ background:#eef1f4; color:var(--ink-soft); text-decoration:line-through; }
.estado-pendente, .estado-aviso{ background:#fff3e0; color:var(--warn); }

/* Semana: colunas que passam a rolar na horizontal no telemóvel, em vez de espremer sete
   dias num ecrã de 360 px — onde nenhum deles seria legível. */
.agenda-semana{ display:grid; grid-template-columns:repeat(7,minmax(9rem,1fr)); gap:.5rem; overflow-x:auto; }
.agenda-col{ min-width:0; }
.agenda-col-cab{
  position:sticky; top:0; padding:.35rem; text-align:center; font-weight:600;
  background:var(--bg); border-radius:8px; cursor:pointer; margin-bottom:.35rem;
}
.agenda-hoje .agenda-col-cab, .agenda-cel.agenda-hoje{ outline:2px solid var(--brand-light); }
.agenda-vazio-col{ text-align:center; }

.agenda-mes{ display:grid; grid-template-columns:repeat(7,1fr); gap:2px; }
.agenda-mes-cab{ display:contents; }
.agenda-mes-cab span{ text-align:center; font-weight:600; padding:.35rem 0; color:var(--ink-soft); }
.agenda-cel{
  min-height:4.5rem; padding:.25rem; background:var(--card);
  border:1px solid var(--line); border-radius:8px; cursor:pointer;
}
.agenda-cel-dia{ font-size:.8rem; color:var(--ink-soft); }
.agenda-fora{ opacity:.45; }
.agenda-ponto{ display:inline-block; width:.5rem; height:.5rem; border-radius:50%; margin:.1rem; }
.agenda-mais{ font-size:.7rem; color:var(--ink-soft); }

.agenda-grupo{ margin-bottom:1rem; }
.agenda-grupo h4{ margin:.5rem 0; color:var(--ink-soft); }

.agenda-painel{
  margin-top:.75rem; padding:1rem; background:var(--card);
  border:1px solid var(--line); border-radius:var(--radius); box-shadow:var(--shadow);
}
.agenda-painel-cab{ display:flex; justify-content:space-between; align-items:flex-start; gap:.5rem; }
.agenda-painel-cab h3{ margin:0 0 .5rem; }
.agenda-painel label{ display:block; margin:.5rem 0; font-weight:600; }
.agenda-painel input, .agenda-painel select, .agenda-painel textarea{
  display:block; width:100%; margin-top:.2rem; padding:.5rem;
  border:1px solid var(--line); border-radius:8px; font:inherit;
}
.agenda-check{ font-weight:400 !important; }
.agenda-check input{ display:inline !important; width:auto !important; margin-right:.4rem; }
.agenda-painel-botoes{ margin-top:.75rem; display:flex; gap:.35rem; flex-wrap:wrap; }
.agenda-colegas{ border:1px solid var(--line); border-radius:8px; padding:.5rem; }
.agenda-notas{ white-space:pre-wrap; }
.agenda-checkin{ padding:.5rem; background:var(--bg); border-radius:8px; }
.agenda-relatorio{ margin-top:.75rem; padding:.75rem; background:var(--bg); border-radius:8px; }
.agenda-relatorio h4{ margin:0 0 .5rem; }
.agenda-paragem{ padding:.6rem 0; border-bottom:1px solid var(--line); }
.agenda-disp{ padding:.5rem 0; border-bottom:1px solid var(--line); }

.agenda-avisos{ margin-bottom:.75rem; }
.agenda-aviso{
  padding:.5rem .75rem; margin-bottom:.35rem; border-radius:8px;
  background:#e8f1fb; border-left:4px solid var(--brand);
}
.agenda-atraso{
  padding:.6rem .75rem; margin-bottom:.75rem; border-radius:8px;
  background:#fdeaea; border-left:4px solid #a01b1b;
}
.agenda-vazio{ padding:1.5rem; text-align:center; }

@media (max-width: 640px){
  /* No telemóvel a barra de cima é usada com o polegar: os botões passam a ocupar a largura
     toda em vez de ficarem espremidos num canto. */
  .agenda-acoes{ margin-left:0; width:100%; }
  .agenda-acoes .btn{ flex:1 1 auto; }
  .agenda-vistas{ width:100%; }
  .agenda-vistas .btn{ flex:1 1 auto; }
  .agenda-titulo{ width:100%; margin:.25rem 0 0; }
  .agenda-cel{ min-height:3.25rem; }
}

/* Agenda — vista da agenda de um colega (V100.2) */
.agenda-dequem{ font-size:.85rem; color:var(--ink-soft); display:flex; align-items:center; gap:.35rem; }
.agenda-dequem select{ padding:.3rem; border:1px solid var(--line); border-radius:8px; font:inherit; }
/* Bloco sem detalhe: riscado a diagonal e sem cursor de clique, para se perceber à primeira
   que não há nada para abrir ali — e não que o clique está avariado. */
.agenda-reservado{
  cursor:default; border-left-color:var(--ink-soft);
  background:repeating-linear-gradient(45deg, var(--bg), var(--bg) 6px, #f2f4f7 6px, #f2f4f7 12px);
  color:var(--ink-soft);
}
.agenda-reservado .agenda-tit{ font-weight:600; }

/* =====================================================================================
   AGENDA — GRELHA DE HORAS (V100.3)
   ===================================================================================== */
.agenda-dia{ display:flex; gap:.5rem; }
.agenda-gutter{ flex:0 0 3.2rem; }
.agenda-gutter-corpo{ position:relative; }
.agenda-gutter-cab{ background:transparent; }
/* A hora é escrita ligeiramente acima da linha a que corresponde, como nos calendários
   de secretária — encostada à linha, parece pertencer à faixa de baixo. */
.agenda-gutter-h{
  position:absolute; right:.35rem; transform:translateY(-50%);
  font-size:.72rem; color:var(--ink-soft); white-space:nowrap;
}
/* A régua alinha-se com o topo da grelha. A grelha tem 1px de bordo, por isso a régua desce
   1px — sem isto, as horas ficam meio píxel acima das linhas a que correspondem. */
.agenda-gutter-corpo{ padding-top:1px; }
/* Compromissos de dia inteiro: a tira empurra a grelha para baixo e a régua acompanha,
   com a mesma altura e a mesma margem. */
.agenda-dia-com-tira .agenda-gutter-corpo{ margin-top:calc(2.6rem + .4rem); }
.agenda-coluna-dia{ flex:1 1 auto; min-width:0; }

.agenda-grelha{
  position:relative; background:var(--card); border:1px solid var(--line);
  border-radius:var(--radius); overflow:hidden;
}
.agenda-linha{ position:absolute; left:0; right:0; height:1px; background:var(--line); }
.agenda-almoco{
  position:absolute; left:0; right:0; background:#fff8e6;
  border-top:1px dashed #e3c16f; border-bottom:1px dashed #e3c16f;
}
.agenda-almoco span{
  position:absolute; right:.4rem; top:.15rem; font-size:.7rem; color:#8a6d1f;
}
.agenda-fora-horas{ position:absolute; left:0; right:0; background:#f7f8fa; }
/* Faixas de meia hora: invisíveis até se lhes passar por cima, para não poluir a grelha. */
.agenda-alvo{ position:absolute; left:0; right:0; cursor:pointer; }
.agenda-alvo:hover{ background:rgba(30,136,229,.08); }

.agenda-bloco{
  position:absolute; overflow:hidden; text-align:left; cursor:pointer;
  padding:.15rem .3rem; margin:0 1px; font:inherit; color:inherit;
  background:var(--card); border:1px solid var(--line); border-left:3px solid var(--ink-soft);
  border-radius:6px; box-shadow:var(--shadow); display:flex; flex-direction:column; gap:1px;
}
.agenda-bloco:hover{ z-index:3; box-shadow:0 2px 8px rgba(0,0,0,.18); }
.agenda-bloco-hora{ font-size:.68rem; font-weight:600; color:var(--brand); }
.agenda-bloco-tit{ font-size:.78rem; font-weight:600; line-height:1.15; }
.agenda-bloco-cli{ font-size:.7rem; color:var(--ink-soft); }
.agenda-bloco-feito{ opacity:.62; }
.agenda-bloco-feito .agenda-bloco-tit{ text-decoration:line-through; }
.agenda-bloco-atraso{ border-color:#a01b1b; background:#fdeaea; }

/* V113.4 — compromissos curtos (meia hora e menos).
   Com 54px por hora, meia hora são 27px: não há altura para a hora e o título em linhas
   separadas, e o título ficava cortado a meio. Passam a partilhar a linha, e o nome do cliente
   sai — num bloco desta altura, o que interessa é saber O QUE é, não de quem. */
.agenda-bloco-curto{
  flex-direction:row; align-items:baseline; gap:.3rem; padding:.1rem .3rem;
}
.agenda-bloco-curto .agenda-bloco-hora{ flex:0 0 auto; }
/* min-width:0 é o que permite ao título encolher dentro do flex e cortar com reticências em
   vez de empurrar para fora do bloco. */
.agenda-bloco-curto .agenda-bloco-tit{
  flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.agenda-bloco-curto .agenda-bloco-cli{ display:none; }

.agenda-dia-inteiro{
  display:flex; flex-wrap:wrap; gap:.35rem; margin-bottom:.4rem;
  min-height:2.6rem; align-items:stretch;
}
.agenda-dia-inteiro .agenda-cartao{ width:auto; flex:1 1 12rem; }

.agenda-semana-grelha{ display:flex; gap:.5rem; }
.agenda-semana-grelha .agenda-semana{
  flex:1 1 auto; display:grid; grid-template-columns:repeat(7,minmax(7rem,1fr));
  gap:.35rem; overflow-x:auto;
}

@media (max-width: 640px){
  /* Blocos mais estreitos deixam de ter espaço para o cliente; fica o essencial. */
  .agenda-bloco-cli{ display:none; }
  .agenda-gutter{ flex-basis:2.6rem; }
}

/* =====================================================================================
   BARRA DE CIMA — MENUS (V101)
   ===================================================================================== */
.topnav{ display:flex; align-items:center; gap:.2rem; flex-wrap:wrap; }
/* Sem regra de cor para os botões da barra: ".topbar .btn-ghost{ color:#fff }" (mais acima)
   já trata disso, e os botões da barra são todos transparentes.
   Uma regra ".topnav .btn{ color:#fff }" parecia inofensiva e foi o que, copiada para o back
   office, fez os botões brancos ficarem com texto branco. Regra a mais é armadilha à espera. */
.menu{ position:relative; }
.menu-seta{ font-size:.7em; margin-left:.2rem; opacity:.7; }
.menu-lista{
  position:absolute; top:calc(100% + .3rem); left:0; z-index:60; min-width:13rem;
  background:var(--card); border:1px solid var(--line); border-radius:var(--radius);
  box-shadow:0 6px 20px rgba(0,0,0,.16); padding:.25rem; display:flex; flex-direction:column;
  /* A barra de cima tem fundo da marca e texto branco. A lista tem fundo branco, por isso a
     cor do texto tem de ser reposta aqui — herdada, dava branco sobre branco. */
  color:var(--ink);
}
.menu-lista-dir{ left:auto; right:0; }
.menu-item{
  display:block; width:100%; text-align:left; padding:.5rem .6rem; border:0; border-radius:8px;
  background:transparent; font:inherit; cursor:pointer; text-decoration:none; white-space:nowrap;
  /* Cor explícita e não "inherit": é o que causava o texto ilegível. */
  color:var(--ink);
}
.menu-item:visited, .menu-item:link{ color:var(--ink); }
.menu-item:hover{ background:var(--bg); }
/* Sair separado do resto por uma linha: é de outra natureza, e o intervalo evita o toque
   acidental logo a seguir a "Definições". */
.menu-item-sair, .menu-item-sair:link, .menu-item-sair:visited{
  margin-top:.25rem; border-top:1px solid var(--line); padding-top:.55rem; color:#a01b1b;
}
/* Selecionado e menu aberto: verde claro com letras pretas (12,78:1). O fundo claro anterior
   mantinha o texto branco herdado da barra — branco sobre quase branco, 1,08:1.
   Verde CLARO e não escuro: numa barra de fundo escuro, um verde escuro ficaria abafado e não
   se perceberia qual está selecionado, que é justamente para o que serve. */
.menu-aberto > .menu-abre,
.topnav-ativo,
.menu.topnav-ativo > .menu-abre{
  background:#a5d6a7;
  color:#000;
  box-shadow:inset 0 -2px 0 #1b5e20;
}
/* O texto dentro do botão (o rótulo e a seta) também tem de mudar: sem isto, um <span>
   com cor própria continuava branco. */
.menu-aberto > .menu-abre span,
.topnav-ativo span,
.menu.topnav-ativo > .menu-abre span{ color:#000; opacity:1; }
.btn-icone span{ display:none; }
.btn-carrinho{ display:inline-flex; align-items:center; gap:.3rem; }
/* A versão vive por baixo do nome da marca. É informação de diagnóstico, em corpo pequeno:
   não deve competir com nada. */
.brand-text{ display:flex; flex-direction:column; line-height:1.1; }
.brand-text .app-version-tag{ font-size:.68rem; color:var(--ink-soft); }

@media (max-width: 640px){
  /* No telemóvel o menu abre encostado à direita para não sair do ecrã, e ocupa largura
     suficiente para o polegar acertar. */
  .menu-lista{ left:auto; right:0; min-width:12rem; }
  .topnav{ width:100%; justify-content:space-between; }
  .topnav .btn span{ display:none; }
  .topnav .menu-abre span.menu-seta{ display:inline; }
  .menu-item{ padding:.65rem .6rem; }
}

/* Rotas guardadas (V103) */
.geo-guardar-rota{ display:flex; flex-wrap:wrap; gap:.6rem; align-items:flex-end; margin-top:.5rem; }
.geo-guardar-rota label{ display:flex; flex-direction:column; gap:.2rem; font-size:.82rem; color:var(--ink-soft); }
.geo-guardar-rota input{ padding:.4rem; border:1px solid var(--line); border-radius:8px; font:inherit; color:var(--ink); }
/* Marca de que se está a alterar uma rota já guardada, e não a criar outra — é a diferença
   entre gravar por cima e criar uma segunda sem dar por isso. */
.geo-rota-editar{ font-size:.78rem; color:var(--warn); align-self:center; }
.geo-rota-guardada{
  padding:.6rem .7rem; margin-bottom:.5rem; background:var(--card);
  border:1px solid var(--line); border-radius:var(--radius);
}
.geo-rota-guardada .geo-acoes{ margin-top:.4rem; }

/* IVA na apresentação dos preços (V103.1 / V103.3) */
.preco-iva{
  font-size:.68em; font-weight:600; color:var(--ink-soft); margin-left:.2rem;
  vertical-align:baseline; white-space:nowrap;
}

/* Interruptor do IVA na barra de cima. Os DOIS rótulos ficam sempre visíveis e o ativo é que
   é destacado — ao contrário de um interruptor comum, onde só se vê o estado e é preciso
   saber de cor o que ele significa. Com preços no ecrã, a dúvida custa dinheiro. */
.iva-switch{
  display:inline-flex; align-items:stretch; padding:2px; gap:2px; cursor:pointer;
  background:rgba(0,0,0,.18); border:1px solid rgba(255,255,255,.35);
  border-radius:999px; font:inherit; line-height:1;
}
.iva-opt{
  padding:.32rem .55rem; border-radius:999px; font-size:.72rem; font-weight:700;
  letter-spacing:.02em; color:rgba(255,255,255,.72); white-space:nowrap;
  transition:background .12s ease, color .12s ease;
}
/* Verde claro com letras pretas, o mesmo do resto da barra: um só idioma para "isto é o que
   está ativo". */
.iva-opt-ativa{ background:#a5d6a7; color:#000; box-shadow:0 1px 2px rgba(0,0,0,.25); }
.iva-switch:hover .iva-opt:not(.iva-opt-ativa){ color:#fff; }
.iva-switch:focus-visible{ outline:2px solid #fff; outline-offset:2px; }

@media (max-width: 640px){
  .iva-opt{ padding:.3rem .45rem; font-size:.68rem; }
}

/* Aviso de IVA na ficha do produto (V103.4) */
.detail-iva{
  margin:.5rem 0 0; padding:.45rem .6rem; border-radius:8px;
  font-size:.82rem; color:var(--ink); background:var(--bg);
  border-left:3px solid var(--ink-soft);
}
/* Com IVA ligado o aviso muda de cor, para a diferença se notar sem se ter de ler: é o
   estado menos habitual, e é nele que um engano custa mais. */
.detail-iva-com{ background:#e8f5e9; border-left-color:#1b5e20; }

/* Produto com taxa de IVA própria, diferente da geral (V104) */
.detail-iva-propria{
  display:inline-block; margin-left:.35rem; padding:.1rem .4rem; border-radius:999px;
  font-size:.72rem; font-weight:700; background:#fff3e0; color:#8a5a00;
}

/* Linhas de IVA por taxa no resumo do documento (V104.1) */
.doc-iva-linha{ font-size:.86rem; color:var(--ink-soft); }

/* CRM — fichas e cronologia (V105) */
.crm-topo{ margin-bottom:.75rem; }
.crm-procura{ display:flex; flex-direction:column; gap:.25rem; font-weight:600; max-width:32rem; }
.crm-procura input{ padding:.55rem; border:1px solid var(--line); border-radius:8px; font:inherit; color:var(--ink); }
.crm-resultados h4{ margin:.75rem 0 .35rem; color:var(--ink-soft); }
.crm-resultado{
  display:flex; flex-direction:column; gap:.1rem; width:100%; text-align:left; cursor:pointer;
  padding:.55rem .7rem; margin-bottom:.35rem; background:var(--card);
  border:1px solid var(--line); border-radius:var(--radius); font:inherit; color:var(--ink);
}
.crm-resultado:hover{ border-color:var(--brand-light); }
.crm-ficha{
  margin-top:1rem; padding:1rem; background:var(--card);
  border:1px solid var(--line); border-radius:var(--radius); box-shadow:var(--shadow);
}

/* ---------- V199.5: a ficha do CRM abre em gaveta lateral ----------
   Abria por baixo da lista, e a página saltava para o fim: perdia-se de vista onde se estava, e
   voltar à lista era rolar para cima à procura. A gaveta deixa a lista intacta por trás.
   Mesma linguagem da gaveta da ficha do cliente (V187.9), mas z-index abaixo dela: as duas
   podem estar abertas ao mesmo tempo, e a de edição tem de ficar por cima. */
.crm-overlay{ position:fixed; inset:0; background:rgba(0,0,0,.35); z-index:50; }
.crm-gaveta{
  position:fixed; top:0; right:0; bottom:0; z-index:51;
  width:78vw; max-width:1200px; min-width:320px;
  margin:0; border-radius:0; border:0; overflow-y:auto;
  background:var(--card); box-shadow:-8px 0 30px rgba(0,0,0,.25);
  padding:1.1rem 1.2rem 2rem;
}
/* O cabeçalho acompanha o rolar: numa ficha com cronologia longa, o nome da empresa e o botão
   de fechar não podem ficar lá em cima, fora de vista. */
.crm-gaveta .crm-ficha-cab{
  position:sticky; top:0; z-index:1; background:var(--card);
  padding-bottom:.6rem; margin-bottom:.4rem; border-bottom:1px solid var(--line);
}
@media (max-width: 860px){
  .crm-gaveta{ width:100vw; max-width:none; padding:1rem .9rem 2rem; }
}
.crm-ficha-cab{ display:flex; align-items:flex-start; gap:.5rem; flex-wrap:wrap; }
.crm-ficha-cab h3{ margin:0; flex:1 1 auto; }
.crm-pessoas{ margin-top:.75rem; }
.crm-pessoa{ padding:.4rem 0; border-bottom:1px solid var(--line); }
/* Quem já saiu fica esbatido mas visível: apagá-lo do ecrã tornaria incompreensível o
   histórico das visitas antigas, onde ele aparece. */
.crm-pessoa-antiga{ opacity:.6; }
.crm-link{
  background:none; border:0; padding:0; font:inherit; color:var(--brand);
  cursor:pointer; text-decoration:underline;
}
.crm-comentar{ margin-top:1rem; padding-top:.75rem; border-top:1px solid var(--line); }
.crm-comentar textarea{
  width:100%; padding:.55rem; border:1px solid var(--line); border-radius:8px;
  font:inherit; color:var(--ink);
}
.crm-comentar-linha{ display:flex; flex-wrap:wrap; gap:.5rem; align-items:center; margin-top:.5rem; }
.crm-comentar-linha label{ font-size:.82rem; color:var(--ink-soft); }
.crm-comentar-linha input{ padding:.35rem; border:1px solid var(--line); border-radius:8px; font:inherit; }

.crm-cronologia{ margin-top:1rem; }
.crm-cronologia h4{ margin:0 0 .5rem; }
/* Linha vertical a ligar os registos: dá a leitura de "uma coisa a seguir à outra" sem ser
   preciso comparar datas de cabeça. */
.crm-evento{
  position:relative; padding:.5rem 0 .5rem 1.4rem; border-left:2px solid var(--line); margin-left:.4rem;
}
.crm-evento-topo{ display:flex; gap:.4rem; align-items:baseline; flex-wrap:wrap; }
.crm-evento-icone{
  position:absolute; left:-0.72rem; top:.5rem; width:1.4rem; height:1.4rem;
  display:grid; place-items:center; border-radius:50%;
  background:var(--card); border:1px solid var(--line); font-size:.78rem;
}
.crm-evento-data{ margin-left:auto; font-size:.78rem; color:var(--ink-soft); white-space:nowrap; }
.crm-evento-texto{ margin-top:.2rem; white-space:pre-wrap; }
.crm-evento-meta{ margin-top:.15rem; font-size:.76rem; color:var(--ink-soft); }
.crm-evento-acoes{ margin-top:.2rem; font-size:.78rem; }
.crm-evento-nota{ border-left-color:var(--brand-light); }

/* Agenda — formulário do compromisso (V105.2) */
.agenda-nota-tipo{ margin:.15rem 0 .5rem; font-size:.8rem; }
.agenda-procura-lista{ margin:.25rem 0 .5rem; max-height:14rem; overflow-y:auto; }
.agenda-procura-item{
  display:flex; flex-direction:column; gap:.1rem; width:100%; text-align:left; cursor:pointer;
  padding:.45rem .6rem; margin-bottom:.25rem; background:var(--card);
  border:1px solid var(--line); border-radius:8px; font:inherit; color:var(--ink);
}
.agenda-procura-item:hover{ border-color:var(--brand-light); }
.agenda-colegas-acoes{ margin-bottom:.4rem; }

/* CRM — ações da ficha (V105.3) */
.crm-ficha-acoes{ display:flex; gap:.35rem; flex-wrap:wrap; }

/* CRM — separadores da ficha (V105.4) */
/* V189.7 — separadores com moldura. Eram texto solto com um risco por baixo do ativo: numa
   fila de oito, sem contorno, não se percebia onde acabava um e começava o outro, e o ativo
   distinguia-se por três pixels de cor. Agora cada um é uma caixa e o ativo fica preenchido. */
.crm-abas{ display:flex; gap:.35rem; flex-wrap:wrap; margin:.75rem 0 .75rem; }
.crm-aba{
  padding:.45rem .85rem; border:1px solid var(--line); background:var(--card);
  font:inherit; font-weight:600; color:var(--ink-soft); cursor:pointer; border-radius:8px;
}
.crm-aba:hover{ background:var(--bg); border-color:#9fbcd8; color:var(--ink); }
.crm-aba-ativa,
.crm-aba-ativa:hover{
  background:var(--brand); border-color:var(--brand); color:#fff;
}
.crm-aba-corpo{ padding-top:.5rem; }
.crm-form{ display:grid; grid-template-columns:repeat(auto-fit,minmax(14rem,1fr)); gap:.6rem; }
.crm-campo{ display:flex; flex-direction:column; gap:.2rem; font-size:.85rem; font-weight:600; color:var(--ink-soft); }
.crm-campo input, .crm-campo textarea{
  padding:.5rem; border:1px solid var(--line); border-radius:8px; font:inherit;
  font-weight:400; color:var(--ink);
}
.crm-campo-largo{ grid-column:1 / -1; }
.crm-form-acoes{ display:flex; gap:.5rem; align-items:center; margin-top:.75rem; }
.crm-filtro{ margin-bottom:.5rem; font-size:.85rem; color:var(--ink-soft); }
.crm-filtro select{ padding:.35rem; border:1px solid var(--line); border-radius:8px; font:inherit; }
.crm-tabela{ width:100%; border-collapse:collapse; font-size:.88rem; }
.crm-tabela th, .crm-tabela td{ padding:.4rem .5rem; border-bottom:1px solid var(--line); text-align:left; }
.crm-tabela th{ color:var(--ink-soft); font-size:.8rem; }
.crm-compromisso{ padding:.5rem 0; border-bottom:1px solid var(--line); }
.crm-cartoes{ display:grid; grid-template-columns:repeat(auto-fit,minmax(9rem,1fr)); gap:.6rem; }
.crm-cartao{
  display:flex; flex-direction:column; gap:.1rem; padding:.7rem; text-align:center;
  background:var(--bg); border-radius:var(--radius);
}
.crm-cartao-valor{ font-size:1.5rem; font-weight:700; color:var(--brand); line-height:1.1; }
.crm-cartao-rotulo{ font-size:.8rem; font-weight:600; }

/* CRM — separadores em ecrã estreito (V105.5) */
.crm-abas-botao{ display:none; }
.crm-abas-fundo{ display:none; }
.crm-ligados{ display:flex; flex-wrap:wrap; gap:.3rem; margin:.2rem 0 .3rem; width:100%; }
.crm-chip{
  display:inline-flex; align-items:center; gap:.3rem; padding:.25rem .6rem;
  background:var(--bg); border:1px solid var(--line); border-radius:999px;
  font:inherit; font-size:.82rem; color:var(--brand); cursor:pointer;
}
.crm-chip:hover{ border-color:var(--brand-light); }
.crm-chip-antigo{ opacity:.6; }
.crm-chip-marca{ font-size:.68rem; color:var(--ink-soft); font-weight:600; }
.crm-nota-email{ margin-top:.75rem; padding:.5rem .6rem; background:var(--bg); border-radius:8px; }

/* CRM — troca de emails (V109). A seta da primeira coluna diz o sentido sem ocupar largura:
   numa tabela com assunto e endereços, uma coluna "Sentido" com a palavra escrita empurrava o
   assunto para fora do ecrã em tablet. */
.crm-tabela-emails td{ vertical-align:top; }
.crm-email-sentido{ width:1.4rem; color:var(--ink-soft); font-weight:700; }
/* Já não está na caixa: marca-se com fundo, NÃO com opacidade.
   A primeira versão usava opacity:.82 sobre a linha toda. O cálculo de contraste deu 3,96:1
   no texto esbatido (--ink-soft misturado com branco dá #77818d) — abaixo do mínimo de 4,5:1,
   e precisamente no texto que diz "já não está na caixa", que é o que se quis preservar.
   Com fundo em vez de opacidade: 5,40:1 no esbatido e 14,46:1 no texto normal. */
.crm-email-ausente td{ background:var(--bg); }
.crm-email-corpo{
  margin-top:.75rem; padding:.75rem; background:var(--card);
  border:1px solid var(--line); border-radius:var(--radius);
}
.crm-email-cabecalho{
  display:flex; gap:.75rem; align-items:baseline; justify-content:space-between;
  margin-bottom:.4rem;
}
.crm-email-texto{
  margin:.6rem 0 0; padding:.6rem; max-height:26rem; overflow:auto;
  background:var(--bg); border-radius:8px;
  font:inherit; font-size:.88rem; white-space:pre-wrap; word-break:break-word;
}

@media (max-width: 820px){
  /* A fila de separadores passa a gaveta: sete numa linha obrigavam a rolar na horizontal,
     e os do meio ficavam sem ser vistos. O botão diz sempre em que separador se está. */
  .crm-abas-botao{
    display:inline-flex; align-items:center; gap:.4rem; margin:.5rem 0;
    padding:.5rem .8rem; background:var(--card); border:1px solid var(--line);
    border-radius:999px; font:inherit; font-weight:600; color:var(--ink); cursor:pointer;
  }
  .crm-abas{
    position:fixed; top:0; left:0; bottom:0; z-index:70; width:14rem;
    flex-direction:column; gap:0; margin:0; padding:1rem .5rem;
    background:var(--card); border:0; border-right:1px solid var(--line);
    box-shadow:4px 0 20px rgba(0,0,0,.18);
    transform:translateX(-100%); transition:transform .18s ease;
  }
  .crm-abas-aberta{ transform:translateX(0); }
  .crm-aba{
    width:100%; text-align:left; border-bottom:0; border-left:3px solid transparent;
    border-radius:0 8px 8px 0; padding:.7rem .8rem;
  }
  .crm-aba-ativa{ border-left-color:var(--brand); background:var(--bg); }
  .crm-abas-fundo{
    display:block; position:fixed; inset:0; z-index:69; background:rgba(0,0,0,.35);
  }
}

/* CRM — classificação da empresa (V106) */
.crm-classificacao{
  margin-top:1rem; padding:.75rem; background:var(--bg); border-radius:var(--radius);
  border-left:3px solid var(--warn);
}
.crm-classificacao h4{ margin:0 0 .3rem; }
.crm-classificacao select{ padding:.45rem; border:1px solid var(--line); border-radius:8px; font:inherit; }
.crm-classificacao.muted{ border-left-color:var(--line); font-size:.85rem; }

/* Separador Fornecedor (V192): a relação de compra. A barra lateral distingue-o à vista dos
   separadores que toda a gente vê — quem está aqui está numa parte reservada da ficha. */
.crm-fornecedor{ border-left:3px solid var(--warn); padding-left:.75rem; }
.crm-fornecedor h4{ margin:1.25rem 0 .3rem; }
.crm-fornecedor h5{ margin:1rem 0 .3rem; font-size:.9rem; color:var(--ink-soft); }
.crm-fornecedor textarea{
  width:100%; padding:.45rem; border:1px solid var(--line); border-radius:8px; font:inherit;
}
/* V200 — moradas de entrega na ficha. O estado da localização tem cor própria: uma morada sem
   ponto e uma morada cujo ponto não se conseguiu obter são coisas diferentes, e sem isto
   pareciam a mesma. */
.crm-entrega{ flex:1 1 14rem; min-width:0; }
.crm-entrega-form{ margin-top:.75rem; padding:.75rem; background:var(--bg); border-radius:var(--radius); }
.crm-campo-check{ display:flex; align-items:center; gap:.4rem; margin:.5rem 0; }
.geo-ok{ font-size:.82rem; color:var(--good); }
.geo-falha{ font-size:.82rem; color:var(--warn); }
.geo-espera{ font-size:.82rem; color:var(--ink-soft); }

.crm-lista-simples{ list-style:none; margin:.25rem 0; padding:0; }
.crm-lista-simples li{
  display:flex; flex-wrap:wrap; gap:.5rem; align-items:center;
  padding:.4rem 0; border-bottom:1px solid var(--line);
}

/* Menu reduzido a um único item (V106.2): sem seta, porque não abre nada.
   E sem o ícone do menu — o rótulo passa a ser o do item, que traz o ícone dele. Sem isto
   apareciam os dois lado a lado (🧮 📑 Propostas de equipamentos). */
.menu-unico > .menu-abre .menu-seta,
.menu-unico > .menu-abre .menu-icone{ display:none; }

/* Procura nos três catálogos (V106.7) */
.module-procura{ flex:1 1 18rem; min-width:12rem; display:flex; gap:.35rem; align-items:center; }
.module-procura input{
  flex:1 1 auto; min-width:0; padding:.45rem .7rem; border:1px solid var(--line);
  border-radius:999px; font:inherit; color:var(--ink); background:var(--card);
}
.module-procura .btn{ flex:0 0 auto; }
.procura-lista{ display:flex; flex-direction:column; gap:.35rem; }
.procura-item{
  display:grid; grid-template-columns:3rem 7rem 1fr auto auto; gap:.6rem; align-items:center;
  width:100%; text-align:left; cursor:pointer; padding:.55rem .7rem;
  background:var(--card); border:1px solid var(--line); border-radius:var(--radius);
  font:inherit; color:var(--ink);
}
.procura-item:hover{ border-color:var(--brand-light); }
/* A etiqueta do módulo é a informação que falta a quem procura sem saber onde está o produto:
   fica à esquerda, sempre no mesmo sítio, para se ler a coluna de uma vez. */
.procura-modulo{
  font-size:.72rem; font-weight:700; text-align:center; padding:.15rem .4rem;
  background:var(--bg); border-radius:999px; color:var(--ink-soft);
}
.procura-preco{ font-weight:600; white-space:nowrap; }
/* V174 — no telemóvel cada elemento diz ONDE fica. Antes só se mudava o número de colunas, e o
   posicionamento automático da grelha punha a descrição na coluna da imagem, com 2,5rem de
   largura: o nome do produto saía em oito linhas de duas palavras. Uma grelha sem posições
   explícitas arruma sozinha, e arruma como lhe apetece. */
@media (max-width: 640px){
  .procura-item{
    grid-template-columns:2.5rem 1fr;
    align-items:start; row-gap:.35rem;
  }
  .procura-img{ width:2.5rem; height:2.5rem; grid-column:1; grid-row:1; }
  .procura-modulo{ grid-column:2; grid-row:1; justify-self:start; }
  /* A descrição, os preços e os botões ocupam a largura toda, um por linha. */
  .procura-desc{ grid-column:1 / -1; grid-row:2; font-weight:600; }
  .procura-preco{ grid-column:1 / -1; grid-row:3; white-space:normal; }
  .procura-acoes{ grid-column:1 / -1; grid-row:4; justify-self:end; }
  .module-procura{ flex-basis:100%; order:10; margin-top:.35rem; }
}

/* Imagem nos resultados da procura transversal (V106.9) */
.procura-img{
  width:3rem; height:3rem; object-fit:contain; background:#fff;
  border:1px solid var(--line); border-radius:8px; flex:0 0 auto;
}
.procura-img-vazia{
  display:grid; place-items:center; font-size:1.3rem; color:var(--ink-soft);
  background:var(--bg);
}

/* Ordenação e ações nos resultados (V107) */
.field-ordem select{ padding:.4rem; border:1px solid var(--line); border-radius:8px; font:inherit; color:var(--ink); }
.procura-ordem{
  flex:0 0 auto; padding:.4rem; border:1px solid var(--line); border-radius:999px;
  font:inherit; font-size:.85rem; color:var(--ink); background:var(--card);
}
.procura-acoes{ display:flex; gap:.3rem; white-space:nowrap; }
.procura-item{ cursor:default; }

/* =====================================================================================
   RELÓGIO DE PONTO — ECRÃ DO COLABORADOR (V110)
   =====================================================================================
   Contrastes calculados, não estimados. O --warn do tema (#b9560f) dá 4,41:1 sobre o cinzento
   das linhas, abaixo do mínimo de 4,5:1 para texto normal — por isso a diferença negativa usa
   um tom próprio, #a84e0d, que dá 5,58:1 sobre branco, 5,16:1 sobre o cinzento e 5,11:1 sobre
   o fundo das linhas incompletas. O verde usa #116b35 pela mesma razão (6,61:1 e 6,10:1). */
.ponto-topo h2{ margin:0 0 .2rem; }
.ponto-topo{ margin-bottom:1rem; }

.ponto-cartao{
  background:var(--card); border:1px solid var(--line); border-radius:var(--radius);
  padding:1rem; box-shadow:var(--shadow); margin-bottom:1rem;
}
.ponto-cartao-topo{
  display:flex; justify-content:space-between; align-items:baseline;
  flex-wrap:wrap; gap:.5rem; margin-bottom:.75rem;
}
.ponto-data{ font-weight:600; }
.ponto-total{ font-size:1.3rem; font-weight:700; color:var(--brand); }

/* Os botões de picar são o gesto principal do ecrã e são usados com uma mão, em pé, muitas
   vezes com luvas ou à pressa. Daí a altura mínima de 3rem: um alvo pequeno falha-se, e uma
   picagem falhada é um buraco na folha que alguém vai ter de corrigir à mão. */
.ponto-botoes{ display:flex; flex-wrap:wrap; gap:.6rem; margin-bottom:.75rem; }
.ponto-botao{ min-height:3rem; min-width:9rem; font-size:1rem; }

.ponto-sugestao{
  padding:.6rem .7rem; margin-bottom:.75rem; border-radius:8px;
  background:#eaf2fa; color:#084a82; font-size:.9rem;   /* 8,04:1 */
}
.ponto-aviso{
  padding:.5rem .6rem; margin:.5rem 0 0; border-radius:8px;
  background:#fdf3ec; color:#8a3d06; font-size:.88rem;  /* 6,98:1 */
}
.ponto-msg .ok{ color:#116b35; }
.ponto-msg .erro{ color:#a84e0d; }

.ponto-lista{ margin:.5rem 0 0; padding-left:1.1rem; font-size:.9rem; }
.ponto-lista li{ margin:.15rem 0; }

.ponto-folha-topo{
  display:flex; justify-content:space-between; align-items:center;
  flex-wrap:wrap; gap:.5rem; margin:1.2rem 0 .5rem;
}
.ponto-folha-topo h3{ margin:0; }
.ponto-nav{ display:flex; align-items:center; gap:.5rem; }

.ponto-tabela{ width:100%; border-collapse:collapse; font-size:.88rem; }
.ponto-tabela th, .ponto-tabela td{
  padding:.35rem .5rem; border-bottom:1px solid var(--line); text-align:left;
}
.ponto-tabela th{ color:var(--ink-soft); font-size:.8rem; }
.ponto-tabela tfoot th{ color:var(--ink); font-weight:700; border-top:2px solid var(--line); }
/* Dia que não é de trabalho: fundo, nunca opacidade. A opacidade mistura o texto com o branco
   e derruba o contraste — foi o erro corrigido na V109.1 no separador de emails. */
.ponto-tabela tr.ponto-nao-util td{ background:#f0f2f5; }
.ponto-tabela tr.ponto-incompleto td{ background:#fdf3ec; }
.ponto-dif{ font-weight:600; }
.ponto-mais{ color:#116b35; }
.ponto-menos{ color:#a84e0d; }
.ponto-sub{ margin:1.2rem 0 .4rem; font-size:1rem; }

@media (max-width: 640px){
  /* Em telemóvel o botão ocupa a linha toda: é onde se pica no terreno, e meio ecrã de alvo
     vale mais do que uma fila bonita. */
  .ponto-botao{ flex:1 1 100%; }
  .ponto-tabela{ font-size:.82rem; }
  .ponto-tabela th, .ponto-tabela td{ padding:.3rem .25rem; }
}

/* =====================================================================================
   CANAL DE RH — ECRÃ DO COLABORADOR (V112)
   =====================================================================================
   Reutiliza os tons já calculados na V110: #116b35 para o positivo (6,61:1 sobre branco) e
   #a84e0d para o negativo (5,58:1). Não se introduzem cores novas onde as que existem servem. */
.rh-topo{ display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:.5rem; }
.rh-topo h2{ margin:0; }
.rh-nav{ display:flex; align-items:center; gap:.5rem; }

.rh-cartoes{ display:grid; grid-template-columns:repeat(auto-fit,minmax(8rem,1fr)); gap:.6rem; margin:.8rem 0; }
.rh-cartao{
  display:flex; flex-direction:column; gap:.1rem; padding:.7rem; text-align:center;
  background:var(--bg); border-radius:var(--radius);
}
.rh-cartao-valor{ font-size:1.6rem; font-weight:700; color:var(--brand); line-height:1.1; }
.rh-cartao-rotulo{ font-size:.82rem; font-weight:600; }

.rh-accoes{ display:flex; gap:.6rem; flex-wrap:wrap; margin:.6rem 0; }
.rh-msg .ok{ color:#116b35; }
.rh-msg .erro{ color:#a84e0d; }

.rh-cartao-form{
  background:var(--card); border:1px solid var(--line); border-radius:var(--radius);
  padding:1rem; margin:.6rem 0;
}
.rh-cartao-form h4{ margin:0 0 .5rem; }
.rh-grelha{ display:grid; grid-template-columns:repeat(auto-fit,minmax(11rem,1fr)); gap:.6rem; }

.rh-tabela{ width:100%; border-collapse:collapse; font-size:.88rem; }
.rh-tabela th, .rh-tabela td{ padding:.4rem .5rem; border-bottom:1px solid var(--line); text-align:left; vertical-align:top; }
.rh-tabela th{ color:var(--ink-soft); font-size:.8rem; }
/* Pedido cancelado ou recusado: fundo, nunca opacidade — foi o erro corrigido na V109.1. */
.rh-tabela tr.rh-cancelado td{ background:var(--bg); }

.rh-conversa{ list-style:none; margin:.5rem 0; padding:0; }
.rh-conversa li{
  padding:.6rem .7rem; margin-bottom:.5rem; border-radius:var(--radius);
  background:var(--bg); border-left:3px solid var(--line);
}
.rh-conversa li.rh-minha{ border-left-color:var(--brand); }
.rh-conversa li.rh-deles{ border-left-color:#116b35; background:#f0f5f1; }
.rh-texto{ white-space:pre-wrap; margin:.25rem 0; }
.rh-nova-mensagem{ max-width:40rem; }

/* V113.3 — ligação ao Google Calendar na Agenda.
   O botão muda de cor quando a conta está ligada, mas a cor não é a única marca: o texto muda
   também ("Ligar ao Google" / "Google: ligado" / "Google: com erro"). Quem não distingue cores
   tem de conseguir ler o estado. */
.agenda-google-ligado{ border-color:#116b35; color:#116b35; }   /* 6,61:1 sobre branco */
.agenda-painel-cartao{
  background:var(--card); border:1px solid var(--line); border-radius:var(--radius);
  padding:1rem; box-shadow:var(--shadow);
}
.agenda-painel-cartao h3{ margin:0 0 .6rem; }
.agenda-painel-cartao p{ margin:.4rem 0; }

/* =====================================================================================
   FUNIS E NEGÓCIOS (V115)
   =====================================================================================
   Reutiliza os tons já calculados: #116b35 para ganho (6,61:1), #a84e0d para perdido (5,58:1),
   #084a82 sobre #eaf2fa para o automático (8,04:1). Não se introduzem cores novas onde as que
   existem servem — e todas passam o mínimo de 4,5:1. */
.funis-topo{ display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:.5rem; }
.funis-topo h2{ margin:0; }
.funis-controlos{ display:flex; gap:.5rem; flex-wrap:wrap; align-items:center; }

.funis-resumo{
  display:flex; gap:1.2rem; flex-wrap:wrap; padding:.6rem .8rem; margin:.6rem 0;
  background:var(--bg); border-radius:var(--radius); font-size:.9rem;
}
.funis-ganho{ color:#116b35; }
.funis-perdido{ color:#a84e0d; }
.funis-msg .ok{ color:#116b35; }
.funis-msg .erro{ color:#a84e0d; }

/* O quadro rola na horizontal: um funil com oito fases não cabe em ecrã nenhum, e encolher
   as colunas até caberem tornava os cartões ilegíveis. */
.funis-quadro{ display:flex; gap:.7rem; overflow-x:auto; padding-bottom:.5rem; align-items:flex-start; }
.funis-coluna{
  flex:0 0 15rem; background:var(--bg); border-radius:var(--radius); padding:.5rem;
  border-top:3px solid var(--line);
}
.funis-coluna-cab{ display:flex; flex-direction:column; gap:.1rem; margin-bottom:.5rem; font-size:.85rem; }
.funis-alvo{ outline:2px dashed var(--brand); outline-offset:-2px; }
.funis-cartoes{ display:flex; flex-direction:column; gap:.4rem; min-height:2rem; }
.funis-vazia{ text-align:center; margin:.5rem 0; }

.funis-cartao{
  display:flex; flex-direction:column; gap:.15rem; width:100%; text-align:left;
  background:var(--card); border:1px solid var(--line); border-radius:8px;
  padding:.5rem .6rem; cursor:pointer; font:inherit; color:inherit; box-shadow:var(--shadow);
}
.funis-cartao:hover{ box-shadow:0 2px 8px rgba(0,0,0,.14); }
.funis-a-arrastar{ opacity:.5; }
.funis-cartao-titulo{ font-weight:600; font-size:.9rem; line-height:1.2; }
.funis-cartao-empresa{ font-size:.82rem; color:var(--brand); }
.funis-cartao-rodape{ display:flex; gap:.5rem; flex-wrap:wrap; font-size:.78rem; margin-top:.2rem; }
.funis-docs{ color:#084a82; }
/* Entidade em quarentena: o cartão avisa, porque emitir um documento contra um contribuinte
   duplicado é o erro que a quarentena existe para evitar. */
.funis-quarentena{
  display:inline-block; width:1.1rem; height:1.1rem; line-height:1.1rem; text-align:center;
  background:#fdf3ec; color:#8a3d06; border-radius:50%; font-weight:700; font-size:.75rem;
}

/* V193 — cartões da triagem cujo remetente ainda não tem ficha. A marca distingue-os no
   quadro: são os que esperam uma decisão, não um seguimento. */
.funis-sem-ficha{
  display:inline-block; padding:.05rem .35rem; border-radius:6px; font-size:.72rem;
  background:#eef2f7; color:#5a6675; border:1px solid var(--line);
}
.funis-ficha-sem-ficha{ display:flex; flex-wrap:wrap; gap:.5rem; align-items:center; }

/* V134 — painel de resumo. Cartões de número grande: o que se quer é ver o número de longe,
   não ler uma tabela. */
.resumo-cartoes{ display:flex; gap:.6rem; flex-wrap:wrap; margin:.5rem 0; }
.resumo-cartao{
  display:flex; flex-direction:column; min-width:8.5rem;
  border:1px solid #e6eaef; border-radius:6px; padding:.5rem .7rem; background:#fff;
}
.resumo-valor{ font-size:1.5rem; font-weight:700; line-height:1.1; }
.resumo-rotulo{ font-size:.82rem; color:#5a6675; }
.resumo-nota{ font-size:.75rem; color:#5a6675; }
/* A lista do que está parado leva barra à esquerda: é a metade do ecrã que dá trabalho. */
.resumo-pendentes{ list-style:none; padding:0; margin:.3rem 0; }
.resumo-pendentes li{ border-left:3px solid #a84e0d; padding:.25rem .6rem; margin-bottom:.3rem; }

/* V126 — bloco da localização na ficha do cliente. Mesmo desenho do bloco da classificação,
   que lhe fica ao lado: são os dois "coisas da ficha que não são campos de texto". */
.crm-localizacao{
  border:1px solid #e6eaef; border-radius:4px; padding:.6rem .8rem; margin:.6rem 0;
}
.crm-localizacao h4{ margin:0 0 .3rem; }

/* V138 — linha de negócio na ficha do cliente: clicável, e a dizê-lo. Uma linha que responde
   ao clique sem nada que o anuncie só é descoberta por acaso. */
.crm-linha-negocio{ cursor:pointer; }
.crm-linha-negocio:hover{ background:#eaf2fa; }

/* V125 — vista em lista dos negócios. */
.funis-vistas{ display:flex; gap:.35rem; flex-wrap:wrap; align-items:center; margin:.4rem 0; }
.funis-filtros{ display:flex; gap:.6rem; flex-wrap:wrap; align-items:flex-end; margin:.5rem 0; }
.funis-filtros label{ display:flex; flex-direction:column; font-size:.82rem; color:#5a6675; }
.funis-filtro-check{ flex-direction:row !important; align-items:center; gap:.3rem; }
.funis-filtros-acoes{ margin-bottom:.6rem; }
.funis-lista-resumo{ margin:.3rem 0 .5rem; }
table.funis-lista{ width:100%; border-collapse:collapse; font-size:.86rem; }
table.funis-lista th, table.funis-lista td{
  text-align:left; padding:.4rem .5rem; border-bottom:1px solid #e6eaef; vertical-align:top;
}
table.funis-lista tbody tr{ cursor:pointer; }
table.funis-lista tbody tr:hover{ background:#eaf2fa; }
/* Etiqueta da fase com a cor à esquerda: a cor identifica a fase sem ser o único sinal —
   quem não distingue as cores lê o nome, que está lá ao lado. */
.funis-fase-etiqueta{ border-left:3px solid #5a6675; padding-left:.35rem; }

/* V124 — painel de resposta a um email, dentro do corpo da mensagem aberta. Borda à esquerda
   para se ver onde começa a resposta e onde acaba a mensagem original. */
.crm-email-resposta{
  border-left:3px solid #084a82; background:#eaf2fa; border-radius:4px;
  padding:.6rem .8rem; margin-top:.8rem;
}
.crm-email-resposta textarea{ width:100%; font-family:inherit; }
.crm-email-resposta input[readonly]{ background:#f2f4f7; color:#5a6675; }

/* V142 — tabela da quarentena. Os botões de cada linha em coluna estreita partiam-se a meio;
   agora não quebram e a linha respira. O motivo pode ser longo e fica com espaço. */
.xd-quarentena td, .xd-quarentena th{ padding:.45rem .5rem; vertical-align:middle; }
/* V152 — as ações passaram da última coluna para a PRIMEIRA. O alinhamento à direita e o
   nowrap acompanharam-nas; sem isso, os três ícones quebravam para três linhas e a linha da
   tabela ficava com o triplo da altura. A largura fixa evita que a coluna dance entre linhas. */
.xd-quarentena td.xd-accoes{ white-space:nowrap; width:1%; }
.xd-quarentena td.xd-accoes .btn{ margin-right:.15rem; padding:.2rem .4rem; }
.xd-quarentena td.wrap{ max-width:22rem; }
.xd-proveniencia{ font-size:.82rem; line-height:1.35; white-space:nowrap; }
.xd-quarentena tbody tr:nth-child(even){ background:#fafbfc; }

/* V122 — linha do formulário de correção, dentro da tabela de quarentena. Fundo próprio para
   se ver onde começa e acaba, sem opacidade (baixa o contraste — armadilha do handover). */
.xd-editor td{ background:#f7f9fb; }

/* V119 — progresso da importação por lotes. Barra e não percentagem só em texto: com 2 434
   entidades, o que se quer saber ao fim de vinte segundos é se está a andar. */
.xd-progresso{ background:#eaf2fa; border-radius:4px; height:.6rem; overflow:hidden; margin:.5rem 0 .2rem; }
.xd-progresso-barra{ background:#084a82; height:100%; transition:width .2s; }

/* V118 — botões dos documentos na ficha do cliente. Em linha e a não quebrar a meio de um
   botão: a coluna é estreita e sem isto o "Duplicar e atualizar" partia-se em duas linhas. */
.crm-doc-acoes{ display:flex; gap:.3rem; flex-wrap:wrap; }
.crm-doc-acoes .btn{ white-space:nowrap; }

/* V118 — tabela de fases arrastável. A pega é um alvo próprio e não a linha inteira: com a
   linha toda arrastável, selecionar texto dentro de um campo começava um arrasto. */
.funis-pega{ cursor:grab; user-select:none; color:#5a6675; font-size:1.1rem; text-align:center; }
.funis-pega:active{ cursor:grabbing; }
/* Fases finais com fundo próprio, não opacidade: baixar a opacidade baixa o contraste, que é
   a armadilha registada no handover. */
.funis-fase-final td{ background:#f2f4f7; }
.admin-aviso{ color:#8a3d06; font-size:.85rem; }
/* V144 — a confirmação ao lado do botão, em verde, para se distinguir do aviso de "por
   gravar" que ocupa o mesmo sítio. */
.admin-aviso-ok{ color:#116b35; }
/* V145 — campo alterado e ainda por gravar. O contorno é o que permite ver, numa tabela de
   cinquenta linhas, quais é que foram mexidas. */
.campo-por-gravar{ outline:2px solid #a84e0d; outline-offset:1px; background:#fff8f2; }

/* V116 — negócio sinalizado por um automatismo. Fundo e não opacidade: baixar a opacidade
   baixa o contraste, que é a armadilha registada no handover. O par #8a3d06 sobre #fdf3ec
   é um dos tons já confirmados acima do mínimo. */
.funis-sinal{
  background:#fdf3ec; color:#8a3d06; border-radius:4px; padding:0 .3rem; font-size:.78rem;
}
.funis-sinal-faixa{
  background:#fdf3ec; color:#8a3d06; border-left:3px solid #8a3d06; border-radius:4px;
  padding:.4rem .6rem; margin:.5rem 0; font-size:.88rem;
}

/* V147 — o painel do negócio, lateral e agarrado ao ecrã.
   Estava por baixo do quadro, e numa fase com cinquenta cartões ficava a mil píxeis de
   distância: abria-se e não se via nada. Lateral, lê-se o negócio COM o funil à vista, que é
   o que permite arrastar o cartão a seguir sem fechar nada. */
.funis-painel{
  position:fixed; top:0; right:0; bottom:0;
  /* V148 — TRÊS QUARTOS do ecrã, e não 26rem.
     Enquanto se preenche o negócio, a empresa e a pessoa, o quadro não serve para nada — e
     um painel estreito obriga a rolar por campos que caberiam lado a lado. Fica uma faixa do
     funil à vista, o suficiente para se saber onde se está; o mínimo em rem impede que num
     ecrã pequeno os 75% dêem uma coluna fina demais para os formulários. */
  width:75%; min-width:34rem; max-width:100%;
  background:#fff; border-left:1px solid #d7dde5; box-shadow:-4px 0 16px rgba(0,0,0,.12);
  padding:1rem 1.4rem; overflow-y:auto; z-index:1200;
}
/* Os campos passam a poder ficar lado a lado: com três quartos de ecrã há espaço, e obrigar
   a rolar por uma coluna estreita era metade do incómodo. */
.funis-painel .funis-grelha{ grid-template-columns:repeat(auto-fit,minmax(14rem,1fr)); }

/* O quadro deixa de encolher: com o painel a ocupar três quartos, empurrá-lo dava colunas de
   dois centímetros, ilegíveis, em vez de uma faixa limpa. Fica por baixo, à vista. */
body.com-painel-negocio .funis-quadro,
body.com-painel-negocio .funis-lista-zona,
body.com-painel-negocio .funis-resumo,
body.com-painel-negocio .funis-vistas{ padding-right:0; }

/* O véu passa a existir TAMBÉM no computador. Com o painel a tapar três quartos do ecrã, o
   que sobra do quadro não é para trabalhar — é para se saber onde se está. Clicar lá fecha,
   que é o gesto que toda a gente tenta primeiro. */
.funis-veu{
  display:block; position:fixed; inset:0; background:rgba(0,0,0,.25); z-index:1100;
}

@media (max-width: 900px) {
  .funis-painel{ width:100%; min-width:0; border-left:0; padding:1rem; }
  .funis-veu{ background:rgba(0,0,0,.35); }
  /* O corpo deixa de correr por baixo do painel: no telemóvel, fazer scroll dentro do painel
     e ver a página a mexer-se atrás é o que faz perder o sítio onde se estava. */
  body.com-painel-negocio{ overflow:hidden; }
}
.funis-cartao-form{
  background:var(--card); border:1px solid var(--line); border-radius:var(--radius);
  padding:1rem; box-shadow:var(--shadow);
}
.funis-grelha{ display:grid; grid-template-columns:repeat(auto-fit,minmax(11rem,1fr)); gap:.6rem; }
.funis-accoes{ display:flex; gap:.5rem; flex-wrap:wrap; margin:.7rem 0; }
.funis-lista{ margin:.4rem 0; padding-left:1.1rem; font-size:.88rem; }
.funis-lista li{ margin:.15rem 0; }
.funis-ficha-empresa{ font-size:1rem; }
.funis-auto{ background:#eaf2fa; color:#084a82; padding:0 .3rem; border-radius:4px; font-size:.8rem; }
.funis-procura{ display:flex; flex-direction:column; gap:.2rem; margin:.3rem 0; }
.funis-sugestao{
  text-align:left; background:var(--bg); border:1px solid var(--line); border-radius:6px;
  padding:.35rem .5rem; cursor:pointer; font:inherit; color:inherit;
}
.funis-sugestao:hover{ background:var(--card); }

/* Negócios na ficha do cliente. Fundo, nunca opacidade — ver a nota da V109.1. */
.crm-linha-fechada td{ background:#f0f2f5; }
.crm-fase{ border-left:3px solid var(--line); padding-left:.4rem; }

@media (max-width: 640px){
  /* Em telemóvel arrastar não funciona bem, e metade da equipa anda no terreno: o movimento
     faz-se pelo seletor de fase dentro da ficha do negócio, que está sempre disponível. */
  .funis-coluna{ flex:0 0 12rem; }
}

/* V153 — marca do valor herdado ao lado do campo da margem. Discreta de propósito: informa que
   o nível não tem margem própria, sem competir com os valores que estão de facto escritos. */
.familias-item-herdado{ color:#6b7280; font-size:.78rem; margin-left:.35rem; white-space:nowrap; }

/* ---- Correspondência (V163) — ver js/correspondencia.js ---- */
/* V199.4 — a barra cabe numa linha só. Antes todos os campos tinham 11rem de mínimo, incluindo
   as duas datas, que não precisam de mais do que o que uma data ocupa: eram elas que empurravam
   o resto para a linha de baixo. A procura é a única que cresce com o espaço que sobrar. */
.corr-filtros{ display:flex; flex-wrap:wrap; gap:.6rem; align-items:flex-end; margin:.75rem 0; }
.corr-filtros .field{ min-width:0; }
.corr-f-procura{ flex:1 1 14rem; min-width:10rem; }
.corr-f-caixa, .corr-f-pasta{ flex:0 1 11rem; }
.corr-f-ficha{ flex:0 0 8.5rem; }
.corr-f-data{ flex:0 0 8.5rem; }
.corr-f-data input{ width:100%; }
.corr-f-botao{ flex:0 0 auto; }

/* O "?" ao lado do nome do campo. A explicação aparece por baixo da barra, num sítio só, em vez
   de um balão por campo — num ecrã com seis filtros, seis balões são seis coisas a tapar. */
.ajuda-sinal{
  display:inline-flex; align-items:center; justify-content:center;
  width:1.05rem; height:1.05rem; margin-left:.25rem; padding:0;
  border:1px solid var(--line); border-radius:50%; background:var(--card);
  color:var(--ink-soft); font-size:.7rem; line-height:1; cursor:help; font-family:inherit;
}
.ajuda-sinal:hover, .ajuda-sinal:focus{ background:var(--bg); color:var(--ink); }
.ajuda-sinal[aria-expanded="true"]{ background:var(--ink); color:#fff; border-color:var(--ink); }
.ajuda-texto{
  margin:-.25rem 0 .75rem; padding:.5rem .65rem; background:var(--bg);
  border-left:3px solid var(--line); border-radius:6px;
}
.corr-check{ flex-direction:row; align-items:center; gap:.4rem; }

/* Duas colunas no computador, uma no telemóvel: a leitura passa para baixo da lista em vez de
   espremer as duas, que é o que torna ambas inúteis num ecrã estreito. */
.corr-layout{ display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.2fr); gap:1rem; align-items:start; }
@media (max-width: 900px){ .corr-layout{ grid-template-columns:1fr; } }

.corr-lista{ max-height:70vh; overflow-y:auto; border:1px solid var(--linha,#e3e8ee); border-radius:.5rem; }
.corr-item{ padding:.6rem .8rem; border-bottom:1px solid var(--linha,#eef2f6); cursor:pointer; }
.corr-item:last-child{ border-bottom:0; }
.corr-item:hover{ background:#f6f9fc; }
.corr-item.selecionado{ background:#eaf2fb; }
.corr-item header{ display:flex; justify-content:space-between; gap:.5rem; font-size:.85rem; color:#5a6a7a; }
.corr-de{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.corr-data{ white-space:nowrap; }
.corr-assunto{ font-weight:600; margin:.15rem 0 .3rem; }
.corr-item footer{ display:flex; flex-wrap:wrap; gap:.4rem; align-items:center; font-size:.78rem; }
.corr-empresa{ background:#e6f0e6; color:#2c5c2c; padding:.1rem .4rem; border-radius:.3rem; }
.corr-sem-ficha{ background:#fdf0dc; color:#8a5a12; padding:.1rem .4rem; border-radius:.3rem; }
.corr-caixa-nome{ color:#6b7280; }
.corr-aviso{ color:#8a3d06; }

.corr-leitura{ border:1px solid var(--linha,#e3e8ee); border-radius:.5rem; padding:1rem; min-height:12rem; }
.corr-cabecalho{ color:#5a6a7a; font-size:.86rem; margin:.15rem 0; }
/* pre-wrap e não pre: o corpo vem em texto com linhas longas, e sem isto a coluna ganhava uma
   barra horizontal própria. */
.corr-corpo{ white-space:pre-wrap; word-break:break-word; font-family:inherit; margin-top:.8rem; }
.corr-paginacao{ display:flex; gap:.6rem; align-items:center; margin-top:.8rem; }

/* =====================================================================================
   VISTA DA RUA (V165) — ver js/rua.js
   =====================================================================================
   A casca minimalista. Só ganha efeito quando o <body> tem .modo-rua, por isso nada disto
   toca na aplicação de secretária — e sair do modo é tirar uma classe, não recarregar nada. */

.rua-titulo{ margin:.2rem 0 1rem; font-size:1.25rem; }

.rua-grelha{ display:grid; grid-template-columns:repeat(2, 1fr); gap:.7rem; }
/* Num ecrã muito estreito (telemóveis pequenos, 320-360px) duas colunas deixam os nomes a
   partir a meio das palavras. Uma coluna é menos bonito e mais legível, e legível ganha. */
@media (max-width: 380px){ .rua-grelha{ grid-template-columns:1fr; } }

.rua-mosaico{
  display:flex; flex-direction:column; align-items:flex-start; gap:.15rem;
  /* 5.5rem de altura mínima: um alvo que se acerta com o polegar, em pé, com o telemóvel numa
     mão só. É a medida que torna isto utilizável na rua e não um site encolhido. */
  min-height:5.5rem; padding:.8rem;
  background:#fff; border:1px solid var(--line,#e3e8ee); border-radius:.8rem;
  text-align:left; cursor:pointer;
}
.rua-mosaico:active{ background:#eef4fb; }
.rua-icone{ font-size:1.5rem; line-height:1; }
.rua-nome{ font-weight:600; }
.rua-nota{ font-size:.78rem; color:#6b7280; line-height:1.25; }

.rua-sair{
  grid-column:1 / -1; margin-top:.4rem; padding:.7rem;
  background:transparent; border:1px dashed var(--line,#cbd5e1); border-radius:.6rem;
  color:#4b5563; cursor:pointer;
}

/* Barra fixa em baixo, e não em cima: é onde o polegar chega sem trocar a mão de posição. */
.rua-barra{
  position:fixed; left:0; right:0; bottom:0; z-index:40;
  display:flex; justify-content:space-around; align-items:stretch;
  background:#fff; border-top:1px solid var(--line,#e3e8ee);
  /* env(safe-area-inset-bottom): nos iPhone com barra de gestos, sem isto os botões ficam por
     baixo dela e não se consegue carregar no último. */
  padding-bottom:env(safe-area-inset-bottom, 0);
}
.rua-barra-item{
  flex:1 1 0; display:flex; flex-direction:column; align-items:center; gap:.1rem;
  padding:.5rem .2rem; background:none; border:0; cursor:pointer; color:#374151;
}
.rua-barra-item span{ font-size:1.15rem; line-height:1; }
.rua-barra-item small{ font-size:.66rem; }
.rua-barra-item:active{ background:#eef4fb; }

/* ---- O que a rua esconde ---- */
.modo-rua .topnav{ display:none; }
/* A barra fixa tapa o fim da página; sem esta folga, o último botão de qualquer ecrã fica
   inalcançável — e é sempre o botão de gravar. */
.modo-rua .app-chrome, .modo-rua body{ padding-bottom:4.5rem; }
.modo-rua .main{ padding-bottom:4.5rem; }
/* O quadro dos funis não é usável num telemóvel e não deve lá aparecer: na rua usa-se a vista
   em lista. Ver a nota no documento de partida — mostrar outro ecrã, não encolher este. */
.modo-rua .funis-quadro{ display:none; }
.rua-vazio{ grid-column:1 / -1; padding:1rem; background:#fff7e6; border:1px solid #f0d9a8;
  border-radius:.6rem; color:#7a5a12; line-height:1.4; }

/* V171 — a barra azul dos catálogos só aparece dentro da loja, em qualquer ecrã. Estava sempre
   visível: no Início repetia os mosaicos logo por baixo, e nos outros módulos era navegação para
   um sítio que quem lá está já não quer. Quem marca o body é mostrarModulo(), em js/app.js —
   uma regra só, para o computador e para o telemóvel. */
.module-bar{ display:none; }
body.na-loja .module-bar{ display:block; }

/* V167 — a versão debaixo do logótipo, dentro da caixa branca dele. Sobre o azul escuro estava
   a cinzento claro e não se lia à luz do dia. */
.brand-logo-wrap{
  display:inline-flex; flex-direction:column; align-items:center; gap:1px;
  background:#fff; border-radius:8px; padding:3px 7px 2px;
}
.brand-logo-wrap .app-version-tag{ color:#111; opacity:1; font-weight:600; }
.brand--so-logo .brand-text{ display:none; }

/* Procura dentro da loja da rua. */
.rua-loja-procura{ display:flex; gap:.5rem; margin-bottom:1rem; }
.rua-loja-procura input{ flex:1 1 auto; min-width:0; padding:.7rem .8rem;
  border:1px solid var(--line,#cbd5e1); border-radius:.6rem; font-size:1rem; }

/* V172 — o voltar da rua. Só existe em .modo-rua: na versão de secretária há a barra de cima e
   os menus.
   V174 — deixou de flutuar sobre o conteúdo. Estava fixo acima da barra de baixo e tapava
   exatamente o que a pessoa estava a ler — numa lista de resultados, escondia o produto
   seguinte. Passa a ser uma faixa colada ao topo do conteúdo: acompanha o ecrã, nunca cobre
   nada, e está onde se procura um voltar. */
.rua-voltar{ display:none; }
.modo-rua .rua-voltar{
  display:inline-flex; align-items:center; gap:.3rem;
  position:sticky; top:0; z-index:39; margin:0 0 .6rem;
  padding:.5rem .9rem; border-radius:0 0 1rem 0;
  background:#fff; border:1px solid var(--line,#cbd5e1); border-top:0; border-left:0;
  box-shadow:0 2px 6px rgba(0,0,0,.08); font-weight:600; color:#1f2937; cursor:pointer;
}
.modo-rua .rua-voltar[hidden]{ display:none; }
.modo-rua .rua-voltar:active{ background:#eef4fb; }

/* V173 — os tipos de preço nos resultados da procura. Nos consumíveis há até quatro (Original,
   Compatível, Lowcost, Cx.10), cada um com o seu stock: mostrar um só obrigava a abrir o produto
   para saber se havia compatível, que é precisamente o que se quer saber numa procura. */
.procura-tipos{ display:flex; flex-wrap:wrap; gap:.15rem .9rem; justify-content:flex-end; }
.procura-tipo{ display:flex; flex-direction:column; align-items:flex-end; line-height:1.2; }
.procura-tipo small{ font-size:.68rem; color:#6b7280; white-space:nowrap; }
.procura-tipo strong{ font-size:.92rem; white-space:nowrap; }
.procura-sem-preco{ color:#6b7280; }
/* Num telemóvel os quatro tipos não cabem numa linha ao lado da descrição: passam para baixo,
   alinhados à esquerda, em vez de espremerem a descrição até ela ser ilegível. */
@media (max-width: 640px){
  .procura-tipos{ justify-content:flex-start; }
  .procura-tipo{ align-items:flex-start; }
}

/* =====================================================================================
   V174 — a barra de cima na vista da rua
   =====================================================================================
   No telemóvel a barra de cima estava a ocupar um terço do ecrã antes de se ver o que quer que
   fosse: logótipo grande, carrinho, S/IVA, nome de quem está ligado, e por baixo a barra dos
   catálogos com a procura. Na rua trabalha-se num ecrã de mão, e cada linha que a barra ganha é
   uma linha de conteúdo que se perde.
   Fica o que é preciso em movimento: o logótipo (com a versão, que é como se confirma o que
   está instalado), o carrinho e o S/IVA. O nome de quem está ligado sai — quem está com o
   telemóvel na mão sabe quem é, e o menu da conta continua a abrir-se pelo mesmo sítio na
   versão completa. */
.modo-rua .brand-logo{ height:26px; }
.modo-rua .brand-logo-wrap{ padding:2px 5px 1px; }
.modo-rua .brand-logo-wrap .app-version-tag{ font-size:.56rem; }
.modo-rua #userTag{ display:none; }
.modo-rua .topbar-inner{ padding:.35rem .5rem; gap:.3rem; }
.modo-rua .topbar-actions{ gap:.2rem; }

/* V176 — na rua, o Ponto é só picar. A folha do mês é uma tabela de trinta linhas: quem está na
   rua quer registar a entrada ou a saída e seguir caminho, e a folha consulta-se à secretária.
   O JavaScript também não a vai buscar (ver folhaVisivel(), em js/ponto.js) — esconder por CSS
   tirava-a da vista mas gastava a ligação à mesma. */
.modo-rua .ponto-folha-topo,
.modo-rua #pontoFolha{ display:none; }

/* =====================================================================================
   ECRÃ INICIAL (V177) — atalhos numa linha, painel do dia por baixo
   ===================================================================================== */
.inicio-atalhos{
  display:flex; flex-wrap:wrap; gap:.6rem; margin:0 0 1.4rem;
}
.inicio-atalho{
  display:inline-flex; align-items:center; gap:.45rem;
  padding:.6rem 1rem; border-radius:.6rem;
  background:#fff; border:1px solid var(--line,#e3e8ee);
  font-weight:600; color:#1f2937; cursor:pointer; white-space:nowrap;
}
.inicio-atalho:hover{ background:#eef4fb; border-color:#c7d8ec; }
.inicio-atalho-icone{ font-size:1.1rem; line-height:1; }
/* Numa só linha enquanto couber; abaixo disso quebra em vez de encolher os nomes até não se
   lerem — um atalho que não se lê não é atalho nenhum. */
@media (max-width: 720px){
  .inicio-atalho{ padding:.55rem .75rem; font-size:.9rem; }
}

.inicio-painel{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(17rem, 1fr)); gap:1rem;
  align-items:start;
}
.painel-bloco{
  background:#fff; border:1px solid var(--line,#e3e8ee); border-radius:.7rem; padding:.9rem 1rem;
}
.painel-bloco h3{ margin:0 0 .5rem; font-size:.98rem; }
.painel-bloco ul{ list-style:none; margin:0; padding:0; }
.painel-bloco li{ padding:.4rem 0; border-bottom:1px solid var(--line,#f0f4f8); }
.painel-bloco li:last-child{ border-bottom:0; }
.painel-bloco li strong{ display:block; font-weight:600; font-size:.92rem; }
.painel-bloco li small{ display:block; color:#6b7280; font-size:.78rem; margin-top:.1rem; }

/* V179 — a barra de cima ficou só com o Início. Os módulos passaram para os botões do ecrã
   inicial (V177), e tê-los nos dois sítios era a mesma navegação duas vezes, com a agravante de
   a de cima não caber num portátil pequeno.
   Os menus ficam no HTML, escondidos: o JavaScript que decide quem os vê continua a correr, e
   repô-los é tirar esta regra. Apagá-los do HTML obrigaria a mexer em quatro sítios do app.js
   que os procuram por id — e a fazê-lo sem poder experimentar. */
#topnav .menu{ display:none !important; }

/* V180 — faixa do modo demonstração. Permanente, no topo, e impossível de ignorar: o risco deste
   modo não é estragar dados (não estraga), é alguém esquecer-se de que está nele e tirar
   conclusões sobre o negócio a partir de dados de brincadeira. */
.demo-faixa{
  position:sticky; top:0; z-index:60;
  background:#8a3d06; color:#fff; text-align:center;
  padding:.45rem .8rem; font-weight:600; font-size:.85rem; letter-spacing:.01em;
}

/* ---------- V187: quem é o cliente, no painel do pedido ----------
   Cartão de leitura no topo do carrinho. Substitui os campos que aqui se escreviam à mão. */
.doc-cliente{
  display:flex; align-items:center; gap:.6rem;
  background:#eef4fb; border:1px solid #cfe0f2; border-radius:var(--radius);
  padding:.6rem .8rem; margin-bottom:.6rem;
}
.doc-cliente-txt{ display:flex; flex-direction:column; min-width:0; flex:1 1 auto; line-height:1.25; }
.doc-cliente-txt strong{ font-size:.95rem; }
.doc-cliente-txt span{ font-size:.78rem; color:var(--ink-soft); }
.doc-cliente.doc-cliente-falta{ background:#fdf3e8; border-color:#f0d3b0; }
.doc-cliente.doc-cliente-falta .doc-cliente-txt span{ color:var(--warn); font-weight:600; }

/* ---------- V187: criar cliente a partir da barra ---------- */
.cc-item.cc-criar{ background:#f4f9f4; }
.cc-item.cc-criar:hover{ background:#e6f4e6; }
.cc-item.cc-criar strong{ color:var(--ok); }

/* o popup do lead novo */
.lead-segmento{ display:flex; gap:.5rem; margin-bottom:.8rem; }
.lead-seg{
  flex:1 1 0; display:flex; flex-direction:column; align-items:center; gap:.1rem;
  padding:.7rem .5rem; cursor:pointer; background:var(--card);
  border:2px solid var(--line); border-radius:var(--radius); color:var(--ink);
}
.lead-seg strong{ font-size:1rem; }
.lead-seg small{ font-size:.75rem; color:var(--ink-soft); }
.lead-seg:hover{ border-color:#9fbcd8; }
.lead-seg-ativo{ border-color:var(--brand); background:#eef4fb; }
.lead-seg-ativo small{ color:var(--brand); }
.lead-erro{
  margin:.6rem 0 0; padding:.55rem .7rem; border-radius:var(--radius);
  background:#fdecec; border:1px solid #f3c2c2; color:#a33; font-size:.85rem;
}
.lead-duplicados{ margin-top:.7rem; border-top:1px solid var(--line); padding-top:.6rem; }
.lead-dup-titulo{ margin:0 0 .4rem; font-size:.85rem; color:var(--ink-soft); }
.lead-dup{
  display:block; width:100%; text-align:left; cursor:pointer; margin-bottom:.35rem;
  background:var(--card); border:1px solid var(--line); border-radius:var(--radius);
  padding:.5rem .7rem; line-height:1.25;
}
.lead-dup:hover{ background:#eef4fb; border-color:#9fbcd8; }
.lead-dup strong{ display:block; font-size:.9rem; }
.lead-dup small{ display:block; font-size:.75rem; color:var(--ink-soft); }
.lead-dup-criar{ margin-top:.3rem; }

/* V187 — indicativo + número, na mesma linha.
   V187.7: o seletor tinha min-width de 7.5rem e o campo do número ficava com min-width 0 — num
   telemóvel, com o Telefone a partilhar a linha com o Email, sobrava-lhe largura zero e NÃO
   HAVIA ONDE ESCREVER O NÚMERO. O campo existia, media nada. Agora o seletor encolhe até 5.5rem
   e o número tem um mínimo próprio; abaixo dos 720px os dois campos deixam de partilhar linha. */
.tel-linha{ display:flex; gap:.4rem; }
.tel-linha select{ flex:0 1 auto; width:auto; min-width:5.5rem; max-width:8rem; }
.tel-linha input{ flex:1 1 7rem; min-width:6rem; }
@media (max-width: 720px){
  #leadModal .field-row{ flex-direction:column; gap:.6rem; }
}

/* ---------- V187.4: passo 2 do carrinho (dados do cliente) ----------
   Cobre o painel dos produtos sem o substituir: recuar não perde nada. */
.drawer-passo2{
  position:absolute; inset:0; z-index:5; background:var(--bg);
  display:flex; flex-direction:column; min-height:0;
}
.drawer-passo2-topo{
  display:flex; align-items:center; gap:.6rem;
  padding:.8rem 1rem; border-bottom:1px solid var(--line); background:var(--card);
}
.drawer-passo2-corpo{ flex:1 1 auto; overflow-y:auto; padding:1rem; }
.passo-linhas{ display:flex; flex-direction:column; gap:.5rem; }
.passo-linha{
  display:flex; align-items:baseline; gap:.5rem; padding:.5rem .7rem;
  border:1px solid var(--line); border-radius:var(--radius); background:var(--card);
}
.passo-linha .passo-rotulo{ flex:0 0 9rem; font-size:.8rem; color:var(--ink-soft); }
.passo-linha .passo-valor{ flex:1 1 auto; font-size:.9rem; word-break:break-word; }
.passo-linha.passo-falta{ background:#fdf3e8; border-color:#f0d3b0; }
.passo-linha.passo-falta .passo-valor{ color:var(--warn); font-weight:600; }

/* ---------- V187.6: conteúdo do passo 2 ---------- */
.passo-titulo{ margin:1.1rem 0 .5rem; font-size:.95rem; color:var(--ink); }
.passo-titulo:first-child{ margin-top:0; }
.passo-produtos{ display:flex; flex-direction:column; gap:.3rem; }
.passo-produto{
  display:flex; justify-content:space-between; gap:1rem; align-items:baseline;
  padding:.4rem .7rem; border:1px solid var(--line); border-radius:var(--radius);
  background:var(--card); font-size:.85rem;
}
.passo-produto-nome{ flex:1 1 auto; min-width:0; }
.passo-produto-valor{ flex:0 0 auto; font-variant-numeric:tabular-nums; white-space:nowrap; }
.passo-totais{ margin-top:.6rem; border-top:1px solid var(--line); padding-top:.5rem; }
.passo-total{ display:flex; justify-content:space-between; font-size:.88rem; padding:.15rem 0; }
.passo-total-final{ font-weight:700; font-size:1rem; border-top:1px solid var(--line); margin-top:.3rem; padding-top:.4rem; }
.drawer-passo2-corpo .field{ margin-top:.6rem; }

/* ---------- V187.9: ficha do cliente em gaveta lateral ----------
   3/4 do ecrã, pela direita. z-index acima do painel do pedido (que é 40/41), porque abre-se
   quase sempre de dentro dele e tem de ficar por cima sem o fechar. */
.ficha-overlay{
  position:fixed; inset:0; background:rgba(0,0,0,.4); z-index:60;
}
.ficha-gaveta{
  position:fixed; top:0; right:0; bottom:0; z-index:61;
  width:75vw; max-width:1100px; min-width:320px;
  background:var(--bg); box-shadow:-8px 0 30px rgba(0,0,0,.25);
  display:flex; flex-direction:column; min-height:0;
}
.ficha-topo{
  display:flex; align-items:center; gap:.8rem;
  padding:.9rem 1.1rem; background:var(--card); border-bottom:1px solid var(--line);
}
.ficha-topo-txt{ display:flex; flex-direction:column; min-width:0; flex:1 1 auto; line-height:1.25; }
.ficha-topo-txt strong{ font-size:1rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ficha-topo-txt span{ font-size:.78rem; color:var(--ink-soft); }
.ficha-corpo{ flex:1 1 auto; overflow-y:auto; padding:1rem 1.1rem; }
.ficha-corpo .field{ margin-bottom:.7rem; }
.ficha-rodape{
  display:flex; justify-content:flex-end; gap:.6rem;
  padding:.9rem 1.1rem; background:var(--card); border-top:1px solid var(--line);
}
.ficha-aviso{
  padding:.6rem .8rem; margin-bottom:.8rem; border-radius:var(--radius);
  background:#fdf3e8; border:1px solid #f0d3b0; color:var(--warn); font-size:.85rem; font-weight:600;
}
.ficha-nota{ display:block; margin-top:.25rem; font-size:.75rem; color:var(--ink-soft); }
.ficha-gaveta input[readonly]{ background:#f0f2f5; color:var(--ink-soft); cursor:not-allowed; }
/* Num telemóvel 3/4 não chega para nada: ocupa tudo. */
@media (max-width: 860px){
  .ficha-gaveta{ width:100vw; max-width:none; }
}

/* ---------- V188.7: proposta com vários tipos de preço no passo de confirmação ---------- */
.passo-produto-multi{ flex-direction:column; align-items:stretch; gap:.3rem; }
.passo-preco{
  display:flex; justify-content:space-between; gap:1rem; font-size:.82rem;
  padding:.15rem .4rem; border-left:2px solid var(--line); margin-left:.2rem;
  color:var(--ink-soft);
}
.passo-preco .passo-produto-valor{ color:var(--ink); }
.passo-preco-falta{ color:var(--warn); font-weight:600; border-left-color:var(--warn); }
.passo-separador{
  font-weight:700; font-size:.85rem; margin:.6rem 0 .2rem; color:var(--brand);
}

/* V189 — painel de "documento criado", no lugar do carrinho. */
.passo-feito{
  text-align:center; padding:2rem 1rem;
  background:#eef7ee; border:1px solid #cfe6cf; border-radius:var(--radius);
}
.passo-feito h3{ margin:0 0 .6rem; font-size:1.15rem; color:var(--ok); }
.passo-feito p{ margin:.3rem 0; }

/* ---------- V189.6: barra de fases no cartão do negócio ----------
   O funil todo de relance, com as cores do quadro. Substitui os botões de "Marcar ganho" e
   "Marcar perdido", que faziam o que uma fase já faz. */
.funis-fases-barra{
  display:flex; flex-wrap:wrap; gap:.3rem; margin:.2rem 0 1rem;
}
.funis-fase-passo{
  --cor-fase:#6b7a8c;
  flex:0 1 auto; cursor:pointer; font-size:.8rem; line-height:1.2;
  padding:.4rem .7rem; border-radius:999px;
  border:1.5px solid var(--cor-fase); background:var(--card); color:var(--ink);
  white-space:nowrap;
}
.funis-fase-passo:hover{ background:var(--bg); }
/* A fase onde o cartão está: preenchida, e não só com borda — num quadro com seis fases, uma
   borda um pouco mais grossa não se distingue de relance. */
.funis-fase-passo.funis-fase-atual{
  background:var(--cor-fase); color:#fff; font-weight:700; cursor:default;
}
.funis-fase-passo.funis-fase-atual:hover{ background:var(--cor-fase); }

/* V190.1 — ordenar funis por arrasto, e a marca de principal. */
.funis-adm-funil .funis-pega{ cursor:grab; color:var(--ink-soft); user-select:none; }
.funis-adm-funil.a-arrastar{ opacity:.45; }
.funis-principal{
  display:inline-block; font-size:.7rem; font-weight:700; text-transform:uppercase;
  letter-spacing:.04em; padding:.1rem .45rem; border-radius:999px;
  background:var(--brand); color:#fff; vertical-align:middle;
}


/* V201 — prospecção na rua. O mapa só ocupa espaço quando há alguma coisa para ver. */
.prosp-mapa{ height:60vh; min-height:320px; margin-top:1rem; border-radius:var(--radius); }
.prosp-a-decorrer{ display:flex; flex-direction:column; gap:.4rem; align-items:flex-start; }

/* V202 — legenda das cores do mapa de prospecção. As mesmas quatro cores do js/prospecao.js;
   se uma mudar, a outra tem de mudar com ela. */
.prosp-leg{ display:inline-block; padding:.05rem .4rem; margin:0 .15rem; border-radius:6px; color:#fff; font-size:.75rem; }
.prosp-leg-1{ background:#c0392b; }
.prosp-leg-2{ background:#e67e22; }
.prosp-leg-3{ background:#2c6fbb; }
.prosp-leg-4{ background:#147a3d; }

/* V204 — o botão de marcar ponto. É usado dez vezes por manhã, muitas delas a andar na rua e
   com o telemóvel numa mão só: tem de se acertar sem olhar. */
.btn-grande{ padding:.9rem 1.4rem; font-size:1.05rem; min-width:12rem; }
