/* SIBERTEX — Backoffice-only adjustments layered ON TOP of the purchased Power Admin theme.
   The purchased theme files (poweradmin/css/main.css, poweradmin/js/*) are READ-ONLY and untouched.
   This file is loaded ONLY by the backoffice layouts, AFTER main.css. It never affects the public FE.
   It introduces NO new colours — it only re-points Bootstrap's own variables at the theme's existing
   dark tokens (defined in main.css), which the theme leaves at their light defaults because it themes
   via [data-theme=dark] rather than Bootstrap's native [data-bs-theme]. */

/* Bridge Bootstrap 5.3 utility variables to the theme tokens in dark mode, so native Bootstrap
   utilities (.border, .card, .table, bg-*-subtle, text-emphasis) stop rendering white borders /
   black text in dark. All values reference tokens already defined by the theme — no invented colours. */
[data-theme=dark] {
  --bs-body-color: var(--default-color);
  --bs-body-bg: var(--background-color);
  --bs-emphasis-color: var(--heading-color);
  --bs-secondary-color: var(--muted-color);
  --bs-secondary-bg: var(--surface-color);
  --bs-tertiary-bg: var(--table-stripe-bg);
  --bs-border-color: var(--border-color);
  --bs-border-color-translucent: var(--border-color);
  --bs-heading-color: var(--heading-color);
  --bs-link-color: var(--accent-color);
  --bs-link-hover-color: var(--accent-color);
  --bs-card-border-color: var(--border-color);
  --bs-card-cap-bg: var(--surface-color);
}

/* Keep every table row-state text colour on the themed body colour (the theme sets the striped/hover
   backgrounds but not these Bootstrap colour vars, so striped rows fell back to black in dark). */
.table {
  --bs-table-striped-color: var(--default-color);
  --bs-table-hover-color: var(--default-color);
  --bs-table-active-color: var(--default-color);
}

/* Backoffice list tables reuse the theme's ROUND letter avatar (.contact-avatar-initial, used at 80px on
   apps-contacts) at a small table size. Only the size changes; the shape (border-radius:50%), centring and
   bg-*-light/text-* colouring come from the theme — no new component, no new colours. */
.page-users .contact-avatar-initial {
  width: 34px;
  height: 34px;
  font-size: 0.6875rem;
}

/* Inline rich-text editors (notification bodies): keep the Quill widget inside its card — bound the
   height (scroll instead of pushing the card open) and wrap long content so it never overflows. */
.html-editor-host {
  max-width: 100%;
}
.html-editor-host .ql-editor {
  min-height: 140px;
  max-height: 260px;
  overflow-y: auto;
  overflow-wrap: anywhere;
}

/* ── Display type: the same face as the public landing ────────────────────────
   The backoffice page titles now use Share Tech, condensed exactly like the FE headings
   (tight tracking + tight leading), so both sides of the product read as one brand.

   Deliberately scoped to the DISPLAY level only (.page-title / .lp-display-like headings) and NOT to
   card titles, table headers or labels: Share Tech ships a SINGLE weight (400). Applying it everywhere
   would flatten the backoffice hierarchy — an h6 card title would weigh the same as an h1 — and any rule
   asking for bold would make the browser synthesise a smeared fake. Body and UI type stay on Plus Jakarta
   Sans, which is variable and carries the weight hierarchy. */
.page-title {
  font-family: "Share Tech", "Plus Jakarta Sans", system-ui, sans-serif;
  font-weight: 400;
  line-height: 0.98;
  letter-spacing: -0.045em;
}

/* ── Cookie consent — keep the banner + its re-open pin above page content in the backoffice/auth zones.
   Buttons already resolve to the brand accent here; the accent maps are kept for consistency and the
   z-index guarantees the withdrawal pin is always reachable (Art. 7(3)). Colour by token only. */
#cookie-consent { z-index: 1045; }
#cookie-consent .btn-primary {
  --bs-btn-bg: var(--accent-color);
  --bs-btn-border-color: var(--accent-color);
  --bs-btn-hover-bg: var(--accent-color);
  --bs-btn-hover-border-color: var(--accent-color);
  --bs-btn-active-bg: var(--accent-color);
  --bs-btn-active-border-color: var(--accent-color);
  --bs-btn-disabled-bg: var(--accent-color);
  --bs-btn-disabled-border-color: var(--accent-color);
}
#cookie-consent .btn-outline-primary {
  --bs-btn-color: var(--accent-color);
  --bs-btn-border-color: var(--accent-color);
  --bs-btn-hover-bg: var(--accent-color);
  --bs-btn-hover-border-color: var(--accent-color);
  --bs-btn-active-bg: var(--accent-color);
  --bs-btn-active-border-color: var(--accent-color);
}
#cookie-consent .form-check-input:checked {
  background-color: var(--accent-color);
  border-color: var(--accent-color);
}

/* ── O PAINEL É O MESMO DA HOME (founder, 2026-09-14: «o certo é o que está na home … mas o painel tem de
   ser igual»). Na home o cartão tem dimensão própria — 430px ancorado ao canto inferior esquerdo, cantos
   largos, botões em pastilha. Aqui desenhava-se como cartão Bootstrap cru dentro da grelha (col-xl-4), e era
   por isso que saía outro painel. O GATILHO continua a diferir por zona — faixa lateral no backoffice,
   pastilha flutuante no público — e isso está certo: cada shell tem a sua gramática. O painel não.

   ⚠ O DESENHO COPIA-SE; AS CORES NÃO. A home é de tema claro fixo (`data-theme="light"` no <html>) e pode
   escrever cinzentos literais. O backoffice tem claro E escuro, pelo que cada cor passa por token — copiar
   os literais da home daria um cartão branco de linhas pretas por cima do tema escuro. Geometria e
   tipografia iguais, cor pelo tema: é assim que fica igual sem partir.

   A home NÃO é tocada: nada disto sai deste ficheiro, e `public.css` não foi aberto. */
#cookie-consent {
  left: 1.25rem !important;
  right: auto !important;
  bottom: calc(1.25rem + env(safe-area-inset-bottom, 0px)) !important;
  width: min(430px, calc(100vw - 2.5rem));
}

/* A grelha deixa de governar a largura — o cartão já a tem. Sem isto o painel volta a esticar-se com a
   coluna e o raio de 18px desenha-se numa faixa larga, que não é o que a home mostra. */
#cookie-consent .container-fluid { padding: 0; }
#cookie-consent .row { margin: 0; }
#cookie-consent [class*="col-"] { flex: 0 0 100%; width: 100%; max-width: 100%; padding: 0; }

#cookie-consent .card {
  border-radius: 18px;
  border: 1px solid var(--border-color);
  background: var(--card-bg);
  /* Profundidade, não marca: a mesma sombra da home, e uma sombra preta translúcida lê-se nos dois temas. */
  box-shadow: 0 8px 20px rgba(0, 0, 0, .07), 0 24px 60px rgba(0, 0, 0, .12);
  overflow: hidden;
}
#cookie-consent .card-body { padding: 1.5rem 1.6rem 1.25rem; }

/* A MESMA LETRA QUE A HOME DESENHA — e chega-se lá por outro caminho, de propósito.
   A home declara `font-family: "Share Tech", var(--lp-serif, serif)`, mas a Share Tech NÃO é carregada no
   shell público: a cadeia cai em `--lp-serif`, que `home.css` define como Plus Jakarta Sans. O título da home
   é, portanto, Plus Jakarta Sans 400 · 1,35 rem — é isso que se reproduz aqui.
   Copiar a declaração dela para cá daria outra coisa: no backoffice a Share Tech ESTÁ carregada, logo o
   painel sairia com uma letra que a home nunca mostra. Declara-se o resultado, não a fórmula.
   (A home fica como está — «a home está bem, não mexer».) */
#cookie-consent .h5 {
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  font-weight: 400;
  letter-spacing: .01em;
  font-size: 1.35rem;
}

#cookie-consent .btn { border-radius: 999px; padding-inline: 1.1rem; }

/* "Rejeitar tudo" e "Guardar" ficam de contorno; só "Aceitar tudo" é cheio — o mesmo peso visual da home.
   A tinta é herdada e a linha é token, por isso o par funciona em claro e em escuro sem segunda regra. */
#cookie-consent .btn-outline-secondary {
  --bs-btn-color: inherit;
  --bs-btn-border-color: var(--border-color);
  --bs-btn-hover-bg: color-mix(in srgb, var(--default-color), transparent 95%);
  --bs-btn-hover-color: inherit;
  --bs-btn-hover-border-color: color-mix(in srgb, var(--default-color), transparent 80%);
}
#cookie-consent .border-top,
#cookie-consent .border-bottom { border-color: var(--border-color) !important; }
/* CÓDIGO MORTO REMOVIDO (2026-09-06) — 35 linhas estilizavam `#cookie-reopen`, a pastilha flutuante do
   consentimento, que NUNCA renderiza no backoffice: `_LayoutPowerAdmin` declara `CookieReopenInSidebar = true`
   e o parcial salta-a. O controlo real do BO é o `[data-cookie-reopen]` da faixa lateral. Além de morto, o
   bloco trazia três `#fff` fora dos tokens. O glifo é o mesmo nos dois lados (`bi-shield-check`); o que muda
   é o contexto — pastilha redonda no público, item de faixa no BO, cada um na gramática do seu shell. */

/* SV-013 (REVERTIDO 2026-07-24, decisão do PM: SoT = brand/PowerAdmin-pro). The earlier "fix" flattened the
   pack's dual sidebar into one stacked list of every area — a grave drift from the pack, which shows ONE
   area at a time: the icon strip switches the panel, tooltips + the panel header carry the labels. The
   flatten override was removed; the pack's own CSS/JS behaviour applies again. Discoverability concerns go
   through the pack's model (tooltips, labelled panel headers), never by rewriting the shell. */

/* Stacked table on phones (SoT tables-responsive "Stacked Table Pattern").
   The pack lays each cell out as a flex row of label + value with no shrink allowance, so a single long
   unbreakable value — a company name, a reference — widens the whole table and the page scrolls sideways.
   Let the label keep its size and the value wrap. Found by walking the contract list on a 390px screen. */
@media (max-width: 767.98px) {
  .table-stacked tbody td { min-width: 0; gap: .75rem; overflow-wrap: anywhere; }
  .table-stacked tbody td::before { flex: 0 0 auto; }
  .table-stacked tbody td > * { min-width: 0; }
}

/* ---------------------------------------------------------------------------
   Backoffice menu on a phone.

   The pack turns the sidebar into a drawer below 768px but keeps its desktop
   width: a 70px icon rail plus a 202px panel. On a 390px screen that is 272px
   of menu over a 118px sliver of page — the content behind is crushed and
   unreadable, and the panel's own text column is too narrow to breathe. The
   drawer also inherited desktop row heights: 43 of 44 entries were under the
   44px a finger needs.

   Below 768px the drawer commits to the screen (the sliver was never usable)
   and every entry becomes a real tap target. Widths only — the pack's open and
   close transforms are percentage-based, so they keep working untouched.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {
  .sidebar { width: 100%; z-index: 1050; }
  .sidebar .sidebar-panel { width: auto; flex: 1 1 auto; min-width: 0; }
  .sidebar .panel-link { min-height: 44px; }
  .sidebar .strip-item { min-height: 44px; min-width: 44px; }

  /* The consent banner is fixed to the bottom and would sit on top of the open
     drawer, hiding its last entries. Keep it reachable, just not in front. */
  .sidebar-open #cookie-consent { z-index: 1040; }
}

/* ── Auth shell on wide displays ─────────────────────────────────────────────
   The sign-in screen keeps the pack's own full-bleed two-column split at every
   width. Capping the shell and centring it was tried and is worse: it turns the
   page into a narrow box floating in a dark field. Left as the pack draws it. */

/* The form column centres its children but lets them size themselves, so the
   card, any notice above it and the footer links each ended up a different
   width. Give the column one measure and they line up. */
.auth-main > * {
    width: 100%;
    max-width: 420px;
}

/* The journey notice above the sign-in card keeps the column's own measure and
   carries no colour or box — it is context, not an alert. The separator line
   that follows it ("já tenho conta") needs a rule on each side so the two paths
   read as alternatives rather than as one continuous form. */
.auth-claim-sep {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
}

.auth-claim-sep::before,
.auth-claim-sep::after {
    content: "";
    flex: 1;
    border-top: 1px solid var(--border-color);
}

/* ── Slot floor plan (PM 2026-07-25) — schematic warehouse plan on /Warehouse/Slots ──────────────────────
   Custom component sanctioned by GAP-2 (grid of slot cards per zone). Positions are SCHEMATIC (by code) and
   the view says so; the real plan arrives with the #159 position inventory. Theme tokens only — state colours
   ride the same semantic tokens the badges use, so plan and list can never disagree on colour language. */
.slot-plan {
  border: 1px solid var(--border-color);
  border-radius: 14px;
  overflow: hidden;
  background: var(--card-bg);
}

.slot-plan-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .8rem 1.1rem;
  border-bottom: 1px solid var(--border-color);
  font-weight: 600;
}

.slot-plan-zone { display: inline-flex; align-items: center; color: var(--accent-color); letter-spacing: .04em; }

.slot-plan-count {
  font-size: .75rem;
  padding: .2rem .6rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent-color), transparent 88%);
  color: var(--accent-color);
  font-variant-numeric: tabular-nums;
}

/* The floor: a concrete-toned field with a faint grid, like a plan sheet. */
.slot-plan-floor {
  position: relative;
  padding: 1.1rem 1.1rem 2.6rem;
  background:
    linear-gradient(color-mix(in srgb, var(--border-color), transparent 55%) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--border-color), transparent 55%) 1px, transparent 1px),
    color-mix(in srgb, var(--card-bg), var(--border-color) 12%);
  background-size: 24px 24px, 24px 24px, auto;
  overflow-x: auto;   /* narrow screens scroll the plan inside itself — the page never scrolls sideways */
}

.slot-plan-row {
  display: flex;
  gap: .45rem;
  margin-bottom: .45rem;
  width: max-content;
  min-width: 100%;
}

/* One slot cell — a container seen from above. Colour = the SAME semantic tokens as the state badges. */
.slot-cell {
  flex: 1 0 3.1rem;
  min-width: 3.1rem;
  height: 2.4rem;
  display: grid;
  place-items: center;
  border-radius: 6px;
  border: 1px solid;
  font-size: .78rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  cursor: default;
  padding: 0;
  transition: transform .15s ease, box-shadow .15s ease;
}

.slot-cell:hover { transform: translateY(-2px) scale(1.06); box-shadow: 0 6px 14px rgba(0, 0, 0, .18); z-index: 2; }

.slot-cell--primary   { background: color-mix(in srgb, var(--accent-color), transparent 78%);  border-color: var(--accent-color);  color: var(--accent-color); }
.slot-cell--success   { background: color-mix(in srgb, var(--success-color), transparent 86%); border-color: var(--success-color); color: var(--success-color); }
.slot-cell--info      { background: color-mix(in srgb, var(--info-color), transparent 82%);    border-color: var(--info-color);    color: var(--info-color); }
.slot-cell--danger    { background: color-mix(in srgb, var(--danger-color), transparent 80%);  border-color: var(--danger-color);  color: var(--danger-color); }
.slot-cell--warning   { background: color-mix(in srgb, var(--warning-color), transparent 78%); border-color: var(--warning-color); color: var(--warning-color); }
.slot-cell--dark,
.slot-cell--secondary { background: color-mix(in srgb, var(--default-color, #6c757d), transparent 85%); border-color: var(--border-color); color: inherit; }

/* EST bays read as parking: taller stalls with a painted-line divider look. */
.slot-plan-row--bays .slot-cell {
  height: 3rem;
  border-radius: 4px 4px 10px 10px;
  border-top-width: 3px;
}

/* Aisle between banks: a driving lane with a dashed centre line and its label. */
.slot-plan-aisle {
  position: relative;
  height: 1.7rem;
  margin: .35rem 0 .8rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.slot-plan-aisle::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 50%;
  border-top: 2px dashed color-mix(in srgb, var(--accent-color), transparent 55%);
}

.slot-plan-aisle span {
  position: relative;
  padding: 0 .6rem;
  font-size: .65rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-muted, #6c757d);
  background: color-mix(in srgb, var(--card-bg), var(--border-color) 12%);
}

/* Entrance marker anchored to the plan's bottom edge. */
.slot-plan-entrance {
  position: absolute;
  left: 50%;
  bottom: 0;
  translate: -50% 0;
  padding: .25rem 1rem;
  border: 1px solid var(--accent-color);
  border-bottom: 0;
  border-radius: 10px 10px 0 0;
  background: color-mix(in srgb, var(--accent-color), transparent 90%);
  color: var(--accent-color);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}

@media (prefers-reduced-motion: reduce) { .slot-cell, .slot-cell:hover { transition: none; transform: none; } }

/* ---------------------------------------------------------------------------------------------------------
   GAP-3 · metric-card icon: the "danger" tint the pack does not ship.

   The pack defines exactly four tints for .metric-card-icon — accent, success, warning, info (main.css
   8618-8636). It ships no danger tint, yet a backoffice dashboard has to be able to say "critical": the
   operator's queue distinguishes work that is pending from work that is late, and the admin dashboard's
   billing KPI already asks for `danger` today and silently renders with no tint at all.

   Completed here, in the BO-only layer, never in the pack: same rule shape as the four above, same token
   pair (--danger-color / --danger-color-light), no hex, no new visual language.
   --------------------------------------------------------------------------------------------------------- */
.page-dashboard .metric-card-icon.danger {
  background: var(--danger-color-light);
  color: var(--danger-color);
}


/* 2026-07-30 — o utilizador é as suas iniciais, não a fotografia demo do pack (imagem martelada removida).
   Só tokens do tema; dimensões herdadas de .avatar / .user-dropdown-avatar do pack. */
.avatar-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-color);
  color: var(--contrast-color);
  font-weight: 600;
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  user-select: none;
}

/* 2026-07-30 — bandeiras pt/en no seletor de língua do BO (assets próprios em /assets/brand/flags). */
.lang-flag {
  width: 1.1em;
  height: 1.1em;
  border-radius: var(--radius-full);
  object-fit: cover;
}

/* 2026-07-31 — o avatar da FAIXA da sidebar: o pack dimensionava `.sidebar-strip-avatar img` (36px, círculo,
   borda); o span de iniciais não herdava nada disso e colapsava num filete. Mesmas medidas, só tokens. */
.sidebar-strip-avatar .avatar-initials {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  border: 2px solid var(--border-color);
  transition: border-color var(--transition-fast);
}
.sidebar-strip-avatar:hover .avatar-initials {
  border-color: var(--accent-color);
}

/* ── Ficha da conta (2026-09-02) — legibilidade do cabeçalho dos line-items ───────────────────────────────
 * O pack pinta a faixa do thead com --heading-color e o texto com --contrast-color; no tema escuro ambos
 * resolvem claros e os títulos das colunas desaparecem. --background-color é, por definição, o oposto do
 * heading em AMBOS os modos — texto escuro na faixa clara (dark) e claro na faixa escura (light). */
.page-invoice .invoice-line-items .table thead th {
  color: var(--background-color);
}

/* R4.1 · WCAG 2.4.1 — skip link. Invisível até receber foco; usa os tokens do pack, sem cor nova. */
.sib-skip-link {
    position: absolute;
    left: var(--spacing-md);
    top: -4rem;
    z-index: 2000;
    padding: var(--spacing-sm) var(--spacing-md);
    background: var(--accent-color);
    color: var(--contrast-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    text-decoration: none;
    transition: top var(--transition-fast);
}
.sib-skip-link:focus,
.sib-skip-link:focus-visible {
    top: var(--spacing-md);
    outline: 2px solid var(--contrast-color);
    outline-offset: 2px;
}
/* R4 · foco sempre visível — o pack não o garante em todos os controlos interativos. */
.main :is(a, button, [role="button"], input, select, textarea, summary):focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

/* ── CALENDÁRIO: AS CORES DO PACK, SEM `style=` INLINE ───────────────────────────────────────────────
   O `apps-calendar.html` pinta a barra do evento e o ponto da categoria com `style="background: var(--…)"`.
   Inline é proibição absoluta das regras de desenho — e desnecessária: são quatro tons, e o token é o
   mesmo. As classes existem só para isso; nenhuma cor nova, nenhum hex. */
.cal-tone-danger  { background: var(--danger-color); }
.cal-tone-success { background: var(--success-color); }
.cal-tone-info    { background: var(--info-color); }
.cal-tone-primary { background: var(--accent-color); }

/* A lista de vencimentos dentro de um cartão do painel respira melhor sem o limite de 300px do pack, que
   existe para uma barra lateral estreita. Só altura — nada de cor. */
.page-dashboard .upcoming-events { max-height: none; }
/* A página do calendário É a lista: o pack limita `.upcoming-events` a 300px com scroll interno (apps-calendar.html,
   barra lateral), o que cortava os vencimentos ao quarto e deixava a coluna vazia por baixo (founder, 2026-09-30). */
.page-calendar .upcoming-events { max-height: none; }

/* ── A PESQUISA É A MESMA EM TODO O BACKOFFICE ───────────────────────────────────────────────────────
   O pack limita `.users-search` a `.page-users`, `.page-users-view` e `.page-users-edit` — e foi por isso
   que cada ecrã fora dessas três inventou a sua caixa de pesquisa: catorze caixas, cinco formas.
   Aqui só se ALARGA o âmbito da mesma classe do pack ao backoffice inteiro. Nenhuma regra nova, nenhuma
   cor: as declarações são as do pack, aplicadas onde também fazem falta. */
.main .users-search { position: relative; flex: 1; min-width: 180px; max-width: 280px; }
.main .users-search i {
    position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
    color: var(--light-color); font-size: 0.875rem;
}
.main .users-search input {
    width: 100%; padding: 0.5rem 0.75rem 0.5rem 2.25rem;
    border: 1px solid var(--border-color); border-radius: var(--bs-border-radius);
    background: var(--surface-color); color: var(--default-color); font-size: 0.875rem;
}
.main .users-search input:focus { outline: none; border-color: var(--accent-color); }

/* ── APOIO E CONVERSA: A LINHA É UM LINK, NÃO UM `onclick` ───────────────────────────────────────────
   O `apps-support.html` e o `apps-chat.html` abrem cada linha com `data-bs-toggle="modal"` num `div`. Aqui
   uma linha é um endereço — `/apoio/12` cola-se num email e abre outra vez amanhã — pelo que o elemento é
   um `<a>`. O pack estilou o `div`; estas três declarações só desfazem o que o browser acrescenta a um
   link (cor e sublinhado) e mantêm a caixa do pack. Nenhuma cor nova, nenhum hex. */
a.ticket-item, a.chat-item { color: inherit; text-decoration: none; }
a.ticket-item:hover, a.chat-item:hover { color: inherit; }

/* Texto escrito por uma pessoa mantém os parágrafos que essa pessoa escreveu. O corpo entra como TEXTO
   (nunca HTML), pelo que sem isto um relato de defeito com seis passos chegava numa única linha corrida. */
.bo-preserve-breaks { white-space: pre-wrap; }

/* A inicial substitui o avatar: a app não tem fotografias de utilizador e não vai pedir uma para desenhar
   um círculo. Cores do pack — o mesmo par que `.ticket-user-initial` já usa. */
.ticket-user-initial { background: var(--accent-color); color: var(--contrast-color); flex-shrink: 0; }
.chat-item-avatar .ticket-user-initial,
.chat-header-avatar .ticket-user-initial,
.message-avatar .ticket-user-initial { width: 100%; height: 100%; font-size: 0.875rem; }

/* A caixa de pesquisa unificada ocupa a largura da barra lateral da conversa, que é estreita e só tem ela. */
.chat-search .users-search { max-width: none; }

/* ── Separadores da ficha de perfil, num telemóvel ───────────────────────────
   O pack desenha `.profile-tabs` como `display:flex` com `width:fit-content` e três pastilhas — a 390px a
   quarta empurra a faixa para fora do cartão e a página passa a deslizar de lado. A faixa passa a poder
   deslizar DENTRO de si própria: o cartão nunca cresce, a página nunca anda ao lado, e as pastilhas ficam
   todas alcançáveis. Nada muda acima de um ecrã estreito, onde já cabem. */
.page-profile .profile-tabs {
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;                 /* a faixa é curta: a barra roubava mais altura do que valia */
  flex-wrap: nowrap;
}
.page-profile .profile-tabs::-webkit-scrollbar { display: none; }
.page-profile .profile-tab { white-space: nowrap; }

/* A fotografia no lugar da inicial, na faixa lateral. O pack desenha `.sidebar-strip-avatar` como o círculo e
   `.avatar-initials` como o texto lá dentro; uma imagem precisa de preencher esse mesmo círculo em vez de
   ficar deitada dentro dele. Mesmo diâmetro, recorte ao centro. */
.sidebar-strip-avatar-img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}

/* ── A inicial no lugar da fotografia ────────────────────────────────────────
   O pack desenha o avatar do perfil para um `<img>`: dá-lhe diâmetro, recorte e contorno, e a cor vem da
   própria imagem. Sem fotografia, o mesmo `<span>` ficava com contorno e sem fundo — um anel vazio com uma
   letra pequena ao lado, que foi o que apareceu no ecrã. A inicial precisa de uma superfície e de tamanho
   de letra próprios; a geometria continua a ser a do pack. Tokens nos dois temas. */
.page-profile .profile-hero-avatar:not(img),
.page-profile .profile-edit-avatar:not(img) {
  background: color-mix(in srgb, var(--accent-color), transparent 82%);
  color: var(--accent-color);
  border-color: color-mix(in srgb, var(--accent-color), transparent 60%);
  flex: 0 0 auto;
  overflow: hidden;
}
.page-profile .profile-hero-avatar:not(img) { font-size: 2rem; line-height: 1; }
.page-profile .profile-edit-avatar:not(img) { font-size: 1.5rem; line-height: 1; }

/* O bloco de números do perfil é uma grelha de quatro colunas iguais; sem `min-width: 0` uma célula recusa-se
   a encolher abaixo do seu conteúdo e a linha inteira fica mais larga do que a página — foi o que cortou o
   quarto cartão no ecrã. A grelha continua a ser a do pack; só se lhe permite encolher. */
.page-profile .profile-stats-row,
.page-profile .profile-stat { min-width: 0; }
.page-profile .profile-stat-value,
.page-profile .profile-stat-label { overflow-wrap: anywhere; }

/* A barra de ações do herói leva agora três controlos e um deles é um formulário. Que envolva as linhas em vez
   de as empurrar para fora do cartão. */
.page-profile .profile-hero-actions { flex-wrap: wrap; }

/* ── O estado de carregamento do pacote, num elemento que NÃO é botão ────────
   `.btn-loading` (main.css:4316) desenha o spinner em `::after` e pinta-o com `var(--contrast-color)` —
   branco, que é o que se quer sobre um botão cheio e é INVISÍVEL sobre um link ou um item de menu. O pacote
   também não lhe dá posição, por isso num elemento largo o círculo aterra no início do conteúdo em vez do
   meio. Duas linhas para o mesmo componente funcionar onde o pacote não previu que fosse usado.

   A cor é o acento (token, nos dois temas) e não `currentColor`: o próprio `.btn-loading` põe a cor do
   elemento a `transparent !important` para esconder o rótulo, logo `currentColor` seria... transparente. */
a.btn-loading::after,
.strip-item.btn-loading::after,
.mobile-menu-item.btn-loading::after,
.panel-link.btn-loading::after,
.settings-nav-item.btn-loading::after,
.users-action-btn.btn-loading::after {
  color: var(--accent-color);
  top: 50%;
  left: 50%;
  margin: -0.5em 0 0 -0.5em;
}

/* ── Indicador de navegação em ecrã inteiro ──────────────────────────────────
   O spinner lá dentro é o do pacote (`spinner-border`), com a cor do tema pelo `text-primary` do pacote.
   Isto é só a moldura: cobre o ecrã, centra, e fica por cima de tudo — incluindo da gaveta lateral aberta,
   que em telemóvel está a 1050.

   O VÉU NÃO PARTE O TEMA: a cor vem do token de fundo da própria página (`--background-color`), com
   transparência por `color-mix`. Em tema claro escurece de leve sobre branco; em escuro faz o mesmo sobre
   escuro. Não há um único valor literal aqui — foi um `#fff` num sítio destes que pintou um véu branco por
   cima do tema escuro da última vez.

   `pointer-events: none` de propósito: isto informa, não bloqueia. A página está a ser substituída de
   qualquer maneira, e um véu que intercepta cliques transforma um atraso num ecrã encravado. */
.sbx-nav {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  background: color-mix(in srgb, var(--background-color), transparent 30%);
  /* SEM `backdrop-filter`. Tinha lá um `blur(1px)` e num telemóvel isso é caro: obriga o browser a compor a
     camada a partir do que está por baixo, no preciso instante em que ele já está a preparar a navegação —
     ou seja, atrasa a única pintura que interessa. Um véu translúcido não precisa de desfoque para se ler. */
}

/* O `hidden` do HTML é a fonte de verdade do estado; sem isto o `display:flex` acima vencia-o. */
.sbx-nav[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .sbx-nav .spinner-border { animation-duration: 1.6s; }   /* continua a rodar: é o único sinal de trabalho */
}

/* ═══ BOTÃO DE PREFERÊNCIAS DE COOKIES — nas páginas que usam este layout SEM serem backoffice ═══
 *
 * O membership é página de CLIENTE: quem lá chega é um utilizador registado a provar que é cliente. Não
 * tem barra lateral de operação, logo não tem o atalho de cookies que ela transporta — e ficava sem forma
 * nenhuma de rever o consentimento, que é um direito (RGPD art. 7.º/3), não um enfeite.
 *
 * ⚠ O ESTILO NASCE AQUI, NÃO SE IMPORTA DO FRONTEND. O gémeo público vive em `public.css`, que este layout
 * não carrega — e a norma proíbe misturar CSS de FE no BO. É a MESMA FORMA, escrita com os tokens do pack:
 * mesmo círculo de 44px, mesmo afastamento, mesmo glifo. O que muda é a origem da cor.
 *
 * E ao contrário do público, que é claro-único, este layout tem DOIS TEMAS. A sombra é o que os separa:
 * no claro a peça levanta-se do branco; no escuro uma sombra preta não se vê, e o que a destaca é um anel
 * subtil. A cor de acento é a mesma nos dois, porque é a identidade da marca e não uma resposta ao fundo. */
#cookie-reopen {
  position: fixed;
  left: 1.5rem !important;
  right: auto !important;
  bottom: calc(1.5rem + env(safe-area-inset-bottom, 0px)) !important;
  margin: 0 !important;
  z-index: 900;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  /* As utilitárias `btn-secondary` e `bottom-0 start-0` do markup trazem peso próprio; sem `!important`
     aqui o botão ficava cinzento e colado à borda. O markup é partilhado com o público e não se duplica. */
  background: var(--accent-color) !important;
  color: var(--contrast-color, #fff) !important;
  border: none !important;
  box-shadow: 0 4px 8px rgba(11, 13, 16, .06), 0 12px 28px rgba(11, 13, 16, .14);
}

#cookie-reopen:hover,
#cookie-reopen:focus-visible {
  background: color-mix(in srgb, var(--accent-color), black 12%) !important;
  color: var(--contrast-color, #fff) !important;
}

#cookie-reopen .bi { font-size: 1.15rem; line-height: 1; }

/* Só o glifo. O nome continua a existir para quem usa leitor de ecrã, em `aria-label` e `title`. */
#cookie-reopen .cookie-reopen-label { display: none; }

/* No escuro, uma sombra preta sobre fundo escuro não existe. O que levanta a peça é um anel — e o mesmo
 * laranja continua a ser o laranja, porque a marca não muda com o tema. */
[data-theme=dark] #cookie-reopen {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent-color), transparent 55%),
              0 10px 24px rgba(0, 0, 0, .45);
}

/* ── Pad de assinatura presencial ────────────────────────────────────────────────────────────────────────
   ⛔ O ACTO CHAMA-SE TOQUE (2026-09-24). A superfície pedia um ficheiro de imagem para o que o domínio chama
   `LOCAL_TOUCH_SIGNATURE`; passou a haver onde assinar. Estas regras vivem AQUI e não no atributo `style` da
   view porque a norma de desenho proíbe CSS inline e hex — a cor vem por token, como todas as outras.
   `touch-action:none` é o que impede o tablet de interpretar o traço como scroll: sem isto, a pessoa arrasta
   a página em vez de assinar. */
.signature-pad__canvas {
    height: 180px;
    width: 100%;
    touch-action: none;
    background: var(--card-bg);
    cursor: crosshair;
}

/* ── Rubrica da gerência ─────────────────────────────────────────────────────────────────────────────────
   A imagem da rubrica tem de SER VISTA na página que a gere. Dimensões aqui e não em `style` inline, pela
   mesma regra de sempre; a assinatura é escura sobre fundo claro, por isso a moldura usa o fundo do corpo. */
.mgr-signature-preview { max-height: 120px; max-width: 100%; object-fit: contain; }
.mgr-signature-thumb   { height: 28px; max-width: 90px; object-fit: contain; vertical-align: middle; }

/* Favourites in the work panel (2026-09-29): a label above a list of entries the menu already has.
   The label is not a link; the counter sits at the end of its entry. Tokens only. */
.sidebar .panel-nav-heading {
  padding: 16px 14px 6px;
  font-size: 0.75rem;
  color: var(--sidebar-color);
  opacity: 0.7;
}
.sidebar .panel-link.panel-link-counted {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* THE CALENDAR READS THE THEME'S TOKENS. The vendor sheet colours three elements with selectors stronger than the
   pack's own rules (`span.flatpickr-weekday` against `.flatpickr-weekday`), in fixed black: in the dark theme the
   weekday names were black on dark. Same elements, same strength, the pack's tokens. */
.flatpickr-calendar span.flatpickr-weekday {
  color: var(--muted-color);
}
.flatpickr-calendar .flatpickr-weekwrapper span.flatpickr-day,
.flatpickr-calendar .flatpickr-weekwrapper span.flatpickr-day:hover {
  color: var(--muted-color);
}
.flatpickr-calendar .flatpickr-current-month input.cur-year[disabled],
.flatpickr-calendar .flatpickr-current-month input.cur-year[disabled]:hover {
  color: var(--muted-color);
}
