/*
 * App shell: top bar (logo, nav, user tag) + main slot + messages slot.
 * Mirrors the chrome drawn in every wireframe screen (docs/wireframes/telas-mvp.html,
 * `.wf-top`) at real desktop scale — the wireframe itself is miniature (11px
 * monospace) to read like a screenshot; this is the actual, readable chrome.
 * Laptop/desktop only (CLAUDE.md §3, Sept 23 2026) — no container queries or
 * stacked layout here yet; the builder grid and the sticky margin bar land in
 * a later screen and get their own container-query pass then.
 */

/* visible focus everywhere — never remove it, only restyle it (WCAG 2.4.7) */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.app-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-5);
  padding: var(--space-3) var(--space-5);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.topbar .logo {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: 0.08em;
  color: var(--ink);
  text-decoration: none;
}

.topbar-nav {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex: 1;
}

.topbar-nav a {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-3);
  text-decoration: none;
}

.topbar-nav a:hover {
  color: var(--ink);
}

.topbar-nav a[aria-current="page"] {
  color: var(--ink);
  box-shadow: inset 0 -2px 0 var(--accent);
}

/* name[ · territory]. Body font, not mono: ~15% narrower. It is the one piece of the bar that may
   shrink — it cuts with an ellipsis before it would push the bar wider than the window. */
.user-tag {
  font-size: 12px;
  color: var(--ink-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  max-width: 100%;
  text-decoration: none;
}

/* the tag is a link to "Meus dados": a quiet hover so it reads as clickable */
a.user-tag:hover {
  color: var(--ink);
  border-color: var(--line-2);
  text-decoration: underline;
}

/*
 * The person's side of the bar: role in use, name tag, role switch, logout. At 1024 px the admin's
 * five nav links plus these four controls do not fit on one line (measured overflow: 1067 px), so
 * the group may drop to its own line, right-aligned (`margin-left: auto`), instead of pushing the
 * bar wider; if even alone it is too wide it wraps inside itself. Nothing is hidden: the switch
 * and "Sair" are always reachable.
 */
.topbar-account {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-left: auto;
  min-width: 0;
  max-width: 100%;
}

/* the role IN USE, in words (§9 TP6). Sober by default; `.app-shell--admin` below changes it */
.role-badge {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  white-space: nowrap;
}

.logout-form,
.role-switch-form {
  margin: 0;
}

.logout-form button,
.role-switch-form button,
.role-switch-link {
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  font-size: 12px;
  color: var(--ink-2);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
}

.logout-form button:hover,
.role-switch-form button:hover,
.role-switch-link:hover {
  color: var(--ink);
  border-color: var(--line-2);
}

/*
 * The `admin` role in use (§9 TP6): the whole bar changes, so the person knows without reading. Amber
 * (`--warn`), not red — nothing is wrong, the role just carries more power — and the badge keeps
 * saying "Papel: administrador" in text, so colour is never the only signal (SC 1.4.1).
 */
.app-shell--admin .topbar {
  background: color-mix(in srgb, var(--warn) 9%, var(--surface));
  border-bottom: 3px solid var(--warn);
}

.app-shell--admin .role-badge {
  color: var(--ink);
  background: color-mix(in srgb, var(--warn) 18%, var(--surface));
  border-color: var(--warn);
}

.app-shell--admin .user-tag {
  color: var(--ink-2);
}

/*
 * Idle warning for the `admin` role (§9 PI6, admin-idle.js). Not a modal: a strip under the bar that
 * stays visible while the page scrolls and never traps focus. With no `data-state` it is clipped, not
 * removed, so its status text stays a live region the screen reader can announce into. It only appears
 * when the script sets a state; the script never makes a request — "Continuar" is the person's click.
 */
.admin-idle {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  padding: var(--space-3) var(--space-5);
  background: color-mix(in srgb, var(--warn) 14%, var(--surface));
  border-bottom: 1px solid var(--warn);
  font-size: 14px;
  color: var(--ink);
}

.admin-idle:not([data-state]) {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.admin-idle[data-state="expired"] {
  background: color-mix(in srgb, var(--bad) 8%, var(--surface));
  border-bottom-color: var(--bad);
}

.admin-idle[data-state="renewed"] {
  background: color-mix(in srgb, var(--good) 8%, var(--surface));
  border-bottom-color: var(--good);
}

.admin-idle-message {
  font-weight: 600;
}

.admin-idle-timer {
  font-family: var(--font-mono);
  font-weight: 600;
}

.admin-idle .btn {
  padding: var(--space-1) var(--space-3);
}

.app-main {
  flex: 1;
  padding: var(--space-5);
}

.messages {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: 0 var(--space-5);
  padding-top: var(--space-4);
}

.message {
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  font-size: 14px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--ink-2);
}

.message--error {
  border-color: var(--bad);
  color: var(--bad);
}

.message--success {
  border-color: var(--good);
  color: var(--good);
}

/* a notice, not a failure (e.g. "O papel de administrador expirou por inatividade"): accent, ink text */
.message--info {
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
  border-color: var(--accent);
  border-left-width: 4px;
  color: var(--ink);
}

/*
 * An information notice inside a page — something the person should read before acting, which is
 * not an error and does not block anything (an expired quote that the next edit will re-price; what
 * saving a product's cost does to open quotes). Accent colour, not red; the first words are always
 * a plain statement of the situation, so colour is never the only signal. Use
 * `<p class="info-notice" role="note">`; never `role="alert"` (nothing went wrong).
 */
.info-notice {
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
  border: 1px solid var(--accent);
  border-left-width: 4px;
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  font-size: 14px;
  color: var(--ink);
  margin-bottom: var(--space-4);
}

/* centered, chrome-less stage for pre-auth screens (login) */
.stage {
  min-height: 100vh;
  display: grid;
  place-items: center;
  background: var(--bg);
  padding: var(--space-6) var(--space-4);
}

/* visually hidden but announced — aria-live regions that carry no visible
   layout of their own (e.g. the builder's recalculated-totals announcer). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* skip link — first focusable element, visible on focus only */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--btn-ink);
  padding: var(--space-2) var(--space-3);
  z-index: 10;
  border-radius: 0 0 var(--radius-sm) 0;
}

.skip-link:focus {
  left: 0;
}

/* A refusal said in place (a rejected quantity, a blocked discount, a client form error). */
.rejection-banner,
.blocked-banner {
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  font-size: 14px;
  border: 1px solid var(--bad);
  color: var(--bad);
  background: color-mix(in srgb, var(--bad) 6%, var(--surface));
  margin-bottom: var(--space-3);
}

/*
 * Banner for an htmx action the server refused without a place of its own on screen (hub-banner.js).
 * Sits under the top bar and the idle strip, above the page; same look as `.rejection-banner`
 * (builder.css), plus the dismiss button. Empty (no box) it takes no room.
 */
.hub-banner {
  padding: 0 var(--space-5);
}

.hub-banner:not(:empty) {
  padding-top: var(--space-4);
}

.hub-banner__box {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: 0;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--bad);
  border-left-width: 4px;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--bad) 6%, var(--surface));
  color: var(--bad);
  font-size: 14px;
}

.hub-banner__text {
  font-weight: 600;
}

.hub-banner__close {
  padding: var(--space-1) var(--space-3);
}

/*
 * A warning that is not an error: something the person should read before acting, in amber (a
 * proposal gone stale, a quote with no client yet). Same shape as `.info-notice`; the first words
 * always state the situation, so colour is never the only signal. Never `role="alert"`.
 */
.warn-notice {
  background: color-mix(in srgb, var(--warn) 9%, var(--surface));
  border: 1px solid var(--warn);
  border-left-width: 4px;
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  font-size: 14px;
  color: var(--ink);
  margin-bottom: var(--space-4);
}

/* ── lists: the search row above a table, the count under it, and the pagination row ────────── */

.search-bar {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.search-bar__grow {
  flex: 1 1 280px;
  max-width: 480px;
}

.list-count {
  margin-bottom: var(--space-3);
}

.pager {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--space-3);
  padding: var(--space-3) 0;
}

.pager__text {
  margin: 0 auto 0 0;
  font-size: 13px;
  color: var(--ink-3);
}
