/* The signed-in app's own CSS: the nav shell (a left sidebar that becomes a
   bottom tab bar on a phone), the credit strip, and the controls, cards and
   messages the five authenticated pages share.

   Loaded *after* assets/tokens.css, which carries the design tokens, the
   typography and the fonts, and which the public pages load on their own —
   see the header there for why the two are separate files. Everything below
   reads tokens defined there, so the order of the two <link>s matters. */

/* ---- App shell ----
   One <nav> element, two layouts. On a desktop it's the left sidebar the
   design draws: wordmark, the section links with their icons, and a
   footer holding the email, the account's clock and Sair.

   Below --bp-nav that same DOM becomes two fixed bars — the links as a
   bottom tab bar (thumb-reachable, always visible, no tap to reveal), the
   identity block as a slim top bar. `display: contents` on the nav is what
   makes that possible without a second copy of the markup: it drops the
   container out of the box tree so its three children can each be
   positioned on their own, which matters because every id in here
   (#user-info, #clock-time, #logout-btn, #menu-admin-link) is read by
   shared.js and must exist exactly once. */
.app-nav {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--nav-width);
  display: flex;
  flex-direction: column;
  padding: 22px 16px;
  background: var(--card);
  border-right: 1px solid var(--border);
  z-index: 40;
}

.nav-brand {
  font-family: "Source Serif 4", Georgia, serif;
  font-size: 22px;
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
  padding: 0 8px 22px;
  white-space: nowrap;
}
.nav-brand .dot { color: var(--brand); }
.nav-brand .brand-suffix {
  /* Flex on the phone layout collapses the space in the markup, so the
     separation has to be a margin rather than whitespace. */
  margin-left: 6px;
  font-family: "Work Sans", sans-serif;
  font-size: 13px;
  font-weight: 500;
  color: var(--muted);
}

.nav-links { display: flex; flex-direction: column; gap: 2px; }

.nav-links a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--radius-control);
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
}
.nav-links a:hover { background: var(--surface); color: var(--text); }
/* Set by shared.js from location.pathname, not hard-coded per page — one
   place to be wrong instead of five. */
.nav-links a[aria-current="page"] { background: var(--surface); color: var(--accent); }
.nav-links svg { flex-shrink: 0; }

.nav-identity {
  margin-top: auto;
  padding: 14px 8px 0;
  border-top: 1px solid var(--border);
  font-size: 13px;
  color: var(--muted);
}
/* Breaks at the @ and the dots before it breaks mid-word, which
   `break-all` did not — a 232px column turned every address into two
   ragged halves. */
#user-email {
  display: block;
  margin-bottom: 4px;
  font-size: 12px;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

/* One line, baseline-aligned. Separation between the three parts comes
   from the size and weight contrast plus the gap, so no punctuation is
   needed. */
.tz-clock { display: flex; align-items: baseline; gap: 7px; white-space: nowrap; }
.tz-clock .clock-time { font-size: 15px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.tz-clock .clock-date,
.tz-clock .clock-zone { font-size: 12px; color: var(--faint); font-variant-numeric: tabular-nums; }

.nav-logout {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  padding: 6px 4px;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
}
.nav-logout:hover { color: var(--danger); }

/* Every authenticated page's own <main> is centred in what's left beside
   the sidebar. Done with padding on <body> rather than by wrapping <main>
   in another element: the five pages already have their own <main> rules
   and none of them had to change for this. */
body.app-shell { padding-left: var(--nav-width); }

/* Pre-authentication: area-cliente.html and admin.html are both a login
   screen *and* the dashboard behind it, one document either way — so the
   nav (which links to Perfis/Créditos/Conta/Admin) has no business showing
   before there's a session to navigate. .pre-auth is the default in the
   markup itself and comes off exactly when a session is confirmed or
   optimistically assumed from a cached identity (see each page's boot()),
   never the other way — a signed-out response always puts it back.
   Unqualified by breakpoint on purpose: it overrides the sidebar on a
   desktop and the two fixed bars the phone layout turns it into equally,
   since both are the same element (see "App shell" above). */
body.pre-auth .app-nav { display: none; }
body.pre-auth.app-shell { padding: 0 !important; }

/* ---- Phone: sidebar becomes a top bar + a bottom tab bar ---- */
@media (max-width: 899px) {
  .app-nav { display: contents; }

  /* The wordmark paints the whole top strip — the identity block below
     then sits on top of it at the right, which is why they can be two
     separate fixed elements and still read as one bar. */
  .nav-brand {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 56px;
    display: flex;
    align-items: center;
    padding: 0 16px;
    font-size: 19px;
    background: var(--card);
    border-bottom: 1px solid var(--border);
    z-index: 40;
  }

  .nav-identity {
    position: fixed;
    top: 0;
    right: 0;
    height: 56px;
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 0;
    padding: 0 16px;
    border-top: none;
    z-index: 41;
  }
  /* The longest item, and the only one repeated elsewhere (/conta shows
     it) — dropping it is what keeps the clock and Sair on one line. */
  #user-email { display: none; }
  /* The time is the point, and the offset is what stops the clock being
     read as the device's own; the date is what gives way. */
  .tz-clock .clock-date { display: none; }
  .nav-logout { margin-top: 0; }
  .nav-logout span { display: none; }

  .nav-links {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    flex-direction: row;
    gap: 0;
    height: var(--nav-height);
    /* Below the bar, the home indicator on an iPhone sits exactly where
       the middle tab is. */
    padding-bottom: env(safe-area-inset-bottom);
    background: var(--card);
    border-top: 1px solid var(--border);
    z-index: 40;
  }
  .nav-links a {
    flex: 1;
    flex-direction: column;
    justify-content: center;
    gap: 3px;
    padding: 0;
    border-radius: 0;
    font-size: 11px;
    font-weight: 600;
  }
  .nav-links a:hover { background: none; }
  .nav-links a[aria-current="page"] { background: none; color: var(--accent); }
  /* The tab bar's own top edge already separates it from the page, so the
     selected tab is marked by a rule directly above it rather than by a
     filled pill, which at this size just looks like a stuck button. */
  .nav-links a[aria-current="page"]::before {
    content: "";
    position: absolute;
    top: -1px;
    left: 22%;
    right: 22%;
    height: 2px;
    background: var(--accent);
    border-radius: 0 0 2px 2px;
  }
  .nav-links a { position: relative; }

  body.app-shell {
    padding-left: 0;
    padding-top: 56px;
    /* Clears the tab bar so the last control on a long form is reachable
       rather than sitting underneath it. */
    padding-bottom: calc(var(--nav-height) + env(safe-area-inset-bottom));
  }

  /* The top bar is fixed, and scrollIntoView() knows nothing about it — it
     stops as soon as the target is inside the *viewport*, which on this
     layout means underneath the bar. area-cliente.js scrolls the history
     date strip into view on load, and that is exactly where it landed.
     scroll-padding on the scrollport is what scrollIntoView (and an #anchor
     jump) actually honours; the two bars each reserve their own edge. */
  :root {
    scroll-padding-top: 68px;
    scroll-padding-bottom: calc(var(--nav-height) + 12px);
  }
}

/* ---- Credit warning strip ----
   Sits directly under the top bar on a phone and at the top of the
   content column on a desktop. Two states: `blocked` when the balance is
   empty and calls are actually stopping, `low` when it is about to be.
   Colour carries the difference, the words carry the meaning — the strip
   is never shown without text. */
.credit-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  padding: 11px 32px;
  font-size: 14px;
  border-bottom: 1px solid var(--border);
}
/* The divider is tinted from the strip's own colour rather than left as
   the page border, which read as a grey line drawn across an amber band.
   color-mix keeps that true in dark mode without a second rule. */
.credit-banner.low {
  background: var(--warm-bg);
  color: var(--warm-text);
  border-bottom-color: color-mix(in srgb, var(--warm-text) 25%, var(--warm-bg));
}
.credit-banner.blocked {
  background: var(--danger-bg);
  color: var(--danger);
  border-bottom-color: color-mix(in srgb, var(--danger) 25%, var(--danger-bg));
}
.credit-banner a { color: inherit; font-weight: 700; }
@media (max-width: 899px) {
  .credit-banner { padding: 10px 16px; font-size: 13.5px; }
}

/* ---- Support-access strip ----
   The one thing standing between an operator and forgetting whose account
   is on screen, so it does not share styling with the credit strip above —
   the two must never be visually confusable, and this one always reads as
   an alert, never as a balance notice. sticky rather than static, so it
   stays visible on a long profile form instead of scrolling out of view
   the moment there is something worth clicking. Copied block — see the
   credit banner's own note; five pages, no build step. */
.support-banner {
  position: sticky;
  top: 0;
  z-index: 55;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 14px;
  padding: 11px 32px;
  font-size: 14px;
  font-weight: 600;
  background: var(--danger-bg);
  color: var(--danger);
  border-bottom: 1px solid color-mix(in srgb, var(--danger) 35%, var(--danger-bg));
}
.support-banner button {
  background: none;
  border: none;
  padding: 0;
  color: inherit;
  font-weight: 700;
  text-decoration: underline;
  cursor: pointer;
  font-size: inherit;
  font-family: inherit;
}
@media (max-width: 899px) {
  .support-banner { padding: 10px 16px; font-size: 13.5px; top: 56px; }
}

/* ---- Controls, shared by all five pages ----
   These were five near-copies of the same rules, one per page's <style>.
   Only the values changed with the redesign; what moved here is the
   half that was already identical. */
button, .btn {
  cursor: pointer;
  border: none;
  border-radius: var(--radius-control);
  padding: 11px 18px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  display: inline-block;
  text-decoration: none;
  text-align: center;
}
.btn-primary { background: var(--accent); color: var(--accent-text); }
.btn-primary:hover { background: var(--accent-hover); }
.btn-secondary { background: var(--surface); color: var(--text); }
.btn-secondary:hover { background: var(--border); }
/* The one "start something new" action per page. */
.btn-brand { background: var(--brand); color: var(--brand-text); }
.btn-brand:hover { background: var(--brand-hover); }
.btn-link { background: none; color: var(--accent); padding: 4px 0; font-weight: 600; }

/* Plain prose links — the ones not dressed as buttons, like "O que
   guardamos" on /conta. Left unstyled they render in the browser's own
   blue (and visited purple), which was merely out of place against the old
   palette and is jarring against a cream one. Scoped to <main> so the nav
   and the credit strip keep the colours they set for themselves. */
main a { color: var(--accent); }

.btn-danger { background: var(--danger-bg); color: var(--danger); }

input[type="text"], input[type="email"], input[type="password"],
input[type="tel"], input[type="number"], input[type="date"],
input[type="time"], input[type="search"], select, textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 14.5px;
  font-family: inherit;
  background: var(--card);
  color: var(--text);
}
input:focus, select:focus, textarea:focus { border-color: var(--accent); }
textarea { min-height: 80px; resize: vertical; }

label { display: block; font-size: 13px; font-weight: 600; margin: 14px 0 6px; }

/* Helper text for a single field: a rule it enforces, or something about
   what to type that changes the answer.

   Default position is between the label and the control. Guidance that
   shapes what you enter has to be read before you enter it, and hint text
   underneath is routinely missed until a submit has already failed (the
   reasoning GOV.UK's Design System gives, on forms with much the same
   audience as this one: people filling in details on behalf of a relative).
   `minlength` has exactly that problem on its own, staying silent until a
   submit is refused and then naming the shortfall rather than the rule.

   It goes *after* the control instead when the field shares a `.row` with
   another one, as "Nome do idoso" does with the phone number. Above the
   input, the hint lands between the two labels and the two inputs, and the
   row's inputs stop lining up with each other across the gap, which is the
   more visible problem of the two. The sibling rule below flips the margin
   for that case, so one class covers both positions and neither needs a
   modifier.

   Tied to its control with aria-describedby either way, so a screen reader
   reads it as part of the field rather than as a loose sentence nearby.

   Distinct from `.meta`, which is a general muted paragraph used for
   section-level explanation rather than for one field. */
.field-hint { font-size: 12px; color: var(--muted); line-height: 1.45; margin: 0 0 6px; }
input + .field-hint,
select + .field-hint,
textarea + .field-hint,
.password-row + .field-hint,
.phone-row + .field-hint { margin: 5px 0 0; }

.password-row { display: flex; gap: 8px; }
.password-row input { flex: 1; }
.password-row button { flex: 0 0 auto; white-space: nowrap; }

/* ---- Surfaces and messages, shared by all five pages ---- */
.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 22px;
  margin-bottom: 16px;
  box-shadow: var(--shadow-card);
}
h2 { font-size: 16px; margin: 0 0 16px; }

/* A card's own heading sharing a row with one trailing control — a filter,
   a button — instead of stacking above it. Started on creditos.html (the
   balance row's "Carregar créditos"); admin.html reuses it for the
   accounts table's role filter and account-detail's back/export row, so it
   lives here rather than in either page's own <style>. */
.card-header { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 16px; }
.card-header h2 { margin: 0; }

/* The page-level heading every authenticated page's <main> opens with —
   what the old <header>'s <h1> did before the nav took the wordmark. Sits
   directly on the page background, never inside a .card: "Perfis" isn't a
   property of the list beneath it, it's the page's own name. Plain <h1>
   where there's nothing beside it (perfil.html's "Editar perfil"); wrapped
   in .page-header, sharing a row with one trailing action (area-cliente's
   "Perfis" + "Novo perfil"), where there is. */
main h1 { font-size: 26px; margin: 0 0 20px; }
.page-header { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin: 0 0 20px; }
.page-header h1 { margin: 0; }

/* ---- Icon action buttons ----
   A square, tinted-background button holding one glyph and nothing else —
   "Editar"/"Eliminar" as words next to a call button that was already an
   icon read as two different idioms for the same kind of action. One
   variant per intent rather than per page, since "edit this" and "delete
   this" mean the same thing on a profile card today and on whatever else
   picks this up later. */
.icon-btn {
  width: 38px;
  height: 38px;
  border: none;
  border-radius: var(--radius-control);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
  background: var(--surface);
  color: var(--muted);
}
/* The icon's own width/height attributes size it everywhere else on this
   page (the nav, the "Novo perfil" plus) — only as a flex item does one
   axis go missing, since a flex child's auto min-width defaults to its
   content box rather than the replaced element's intrinsic size. Explicit
   CSS sidesteps that resolution instead of fighting it. */
.icon-btn svg {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
}
.icon-btn:hover:not(:disabled) { filter: brightness(0.96); }
.icon-btn:disabled { opacity: 0.4; cursor: default; }
.icon-btn-ok { background: var(--ok-bg); color: var(--ok-text); }
.icon-btn-accent { color: var(--accent); }
.icon-btn-danger { color: var(--danger); }

.actions { display: flex; gap: 10px; margin-top: 18px; flex-wrap: wrap; }

/* Both carry a live-region role in the markup — role="alert" on .error (a
   refused save interrupts; you are about to act on a form that didn't go
   through), role="status" on .info (a confirmation waits its turn).
   Which means the order the pages write them in is load-bearing:
   un-hide *first*, then set the text. Written the other way round the
   text lands while the element is still out of the accessibility tree,
   and the reveal alone mutates nothing for a screen reader to announce —
   the message is on screen and silent. The two .info boxes whose text is
   static in the markup reassign textContent for the same reason. */
.error, .info {
  padding: 9px 13px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  margin-top: 10px;
}
.error { background: var(--danger-bg); color: var(--danger); }
.info { background: var(--ok-bg); color: var(--ok-text); }
