@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/fonts/archivo-latin.woff2) format("woff2");
}

:root {
  --ink: #0a0b0d;
  --canvas: #f5f6f8;
  --panel: #ffffff;
  --panel-2: #fafbfc;
  --line: rgba(10, 11, 13, 0.08);
  --line-soft: rgba(10, 11, 13, 0.045);
  --line-strong: rgba(10, 11, 13, 0.15);
  --text: rgba(10, 11, 13, 0.92);
  --muted: rgba(10, 11, 13, 0.5);
  --faint: rgba(10, 11, 13, 0.36);
  --primary: #0969f7;
  --primary-ink: #0b5ed7;
  --primary-on: #ffffff;
  --primary-lift: #5b9dff;
  --primary-glow: rgba(9, 105, 247, 0.28);
  --primary-soft: rgba(9, 105, 247, 0.12);
  --coral: #ff5c38;
  --ok: #1a7d3c;
  --ok-bg: rgba(26, 125, 60, 0.1);
  --danger: #c0341d;
  --danger-bg: rgba(192, 52, 29, 0.08);
  --amber: #b45309;
  --amber-bg: rgba(180, 83, 9, 0.09);
  --radius: 12px;
  --radius-sm: 10px;
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04), 0 1px 3px rgba(15, 23, 42, 0.06);
  --shadow-md: 0 8px 24px rgba(15, 23, 42, 0.12);
  --side-bg: #ffffff;
  --side-text: rgba(10, 11, 13, 0.78);
  --side-strong: #0a0b0d;
  --side-line: rgba(10, 11, 13, 0.08);
  --side-label: rgba(10, 11, 13, 0.42);
  --side-w: 244px;
  --content-w: 1180px;
}

* { box-sizing: border-box; }

html { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--text);
  font-family: "Archivo", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 15px;
  line-height: 1.5;
}

a { color: inherit; text-decoration: none; }

/* Tabler icon font (self-hosted, see tabler-icons.css). Each context sets its own size;
   this only guarantees the glyph never inherits a text baseline it can't sit on. */
i.ti { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }

/* ---------- App shell ---------- */

.app {
  display: grid; grid-template-columns: var(--side-w) minmax(0, 1fr); min-height: 100vh;
  transition: grid-template-columns 0.22s ease;
}

.side {
  position: sticky; top: 0; align-self: start;
  height: 100vh; display: flex; flex-direction: column;
  background: var(--side-bg); color: var(--side-text);
  border-right: 1px solid var(--side-line);
}

/* Everything under the brand — scope, nav, account. One box, because on a phone it is one
   thing: the drawer the burger opens. */
.side-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }

@media (prefers-reduced-motion: reduce) {
  .app { transition: none; }
}

/* Head row: logo left, collapse toggle right. Collapsed the two stack on the same spot —
   the logo fades out and the toggle fades in when the rail is hovered. */
/* space-between rather than a flex-grow on the brand: the brand must never stretch, or a
   stale render where it is a direct child of the column would blow the rail apart. */
.side-head { position: relative; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 18px 14px 16px 20px; }
.side-brand { display: flex; align-items: center; flex: 0 1 auto; min-width: 0; transition: opacity 0.16s; }
.side-logo { height: 26px; width: auto; display: block; }
/* Icon-only mark, swapped in for the wordmark on the collapsed rail. */
.side-icon { display: none; width: 30px; height: 30px; object-fit: contain; }

.side-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; flex-shrink: 0;
  background: transparent; border: 1px solid transparent; border-radius: 9px;
  color: var(--faint); cursor: pointer; padding: 0;
  transition: color 0.14s, background 0.14s, border-color 0.14s, opacity 0.16s;
}
.side-toggle .ti, .side-toggle i { font-size: 20px; }
.side-toggle:hover { color: var(--primary-ink); background: var(--primary-soft); }
.side-toggle:focus-visible { outline: none; color: var(--primary-ink); background: var(--primary-soft); box-shadow: 0 0 0 3px var(--primary-glow); }

/* ---------- Burger (phones only; enabled in the ≤820px block) ----------
   Drawn from three real bars rather than an icon font, because the open/close state is a single
   continuous movement: the outer bars first slide together, and only once they meet do they
   rotate into the cross. Doing it in two beats — rather than sliding and turning at once — is
   what makes it read as one gesture instead of a flip. The delays swap around with .nav-open, so
   the close plays the same two beats in reverse. */
.burger {
  display: none; position: relative;
  width: 42px; height: 42px; flex-shrink: 0;
  align-items: center; justify-content: center;
  padding: 0; border: 1px solid transparent; border-radius: 12px;
  background: transparent; color: var(--side-strong); cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.16s, border-color 0.16s;
}
.burger:hover, .nav-open .burger { background: var(--primary-soft); color: var(--primary-ink); }
.burger:focus-visible { outline: none; background: var(--primary-soft); box-shadow: 0 0 0 3px var(--primary-glow); }

.burger-box { position: relative; width: 20px; height: 14px; }
.burger-bar {
  position: absolute; left: 0; height: 2px; width: 100%;
  border-radius: 2px; background: currentColor;
  /* Beat one: top/width. Beat two: transform. */
  transition:
    top 0.2s cubic-bezier(0.4, 0, 0.2, 1) 0.19s,
    width 0.2s cubic-bezier(0.4, 0, 0.2, 1) 0.19s,
    transform 0.22s cubic-bezier(0.2, 0.9, 0.25, 1.1) 0s,
    opacity 0.1s linear 0.19s;
}
.burger-bar:nth-child(1) { top: 0; }
.burger-bar:nth-child(2) { top: 6px; }
/* Short closed, full open: the stack is deliberately lopsided at rest — it is the one detail that
   makes this burger ours — and squares up as it becomes the cross. */
.burger-bar:nth-child(3) { top: 12px; width: 62%; }

.nav-open .burger-bar {
  transition-delay: 0s, 0s, 0.19s, 0s; /* the beats swap: move first, then turn */
}
.nav-open .burger-bar:nth-child(1) { top: 6px; transform: rotate(45deg); }
.nav-open .burger-bar:nth-child(2) { transform: scaleX(0.15); opacity: 0; }
.nav-open .burger-bar:nth-child(3) { top: 6px; width: 100%; transform: rotate(-45deg); }

@media (prefers-reduced-motion: reduce) {
  .burger-bar, .nav-open .burger-bar { transition: none; }
}

/* ---------- Collapsed rail (class on <html>, set by admin-boot.js) ---------- */

.side-off { --side-w: 72px; }
.side-off .side-head { justify-content: center; padding: 18px 0 16px; }
.side-off .side-brand { justify-content: center; flex: 0 0 auto; }
.side-off .side-logo { display: none; }
.side-off .side-icon { display: block; }
/* Toggle sits on top of the icon and only surfaces when the head row itself is hovered
   (not the whole rail) or the button takes keyboard focus. */
.side-off .side-toggle { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); margin-top: -1px; opacity: 0; pointer-events: none; }
.side-off .side-head:hover .side-brand { opacity: 0; }
.side-off .side-head:hover .side-toggle,
.side-off .side-toggle:focus-visible { opacity: 1; pointer-events: auto; }

.side-off .side-nav { padding: 8px; }
.side-off .side-group { margin-top: 10px; }
.side-off .side-group-label { display: none; }
/* The label is its own <span> so it can be dropped outright — the old font-size: 0 trick
   would also collapse the icon, now that the icons are glyphs rather than SVG. */
.side-off .side-link { justify-content: center; gap: 0; padding: 11px 0; }
.side-off .side-link span { display: none; }

.side-off .side-foot { padding: 10px 8px; }
.side-off .side-user { justify-content: center; padding: 8px 0; gap: 0; }
.side-off .side-user .who, .side-off .side-user .chev { display: none; }
/* The menu would otherwise be as narrow as the rail. */
.side-off .side-menu { right: auto; min-width: 220px; }

/* ---------- Organization scope ----------
   Sits directly under the brand because it frames everything below it: the whole backoffice is
   showing one organization, and this is the line that says which. The administrator's version is a
   picker; the organizer's is the same block with nothing to choose. */

/* The same 12px gutter as .side-nav, so the card and the links below share one edge. */
.side-org { padding: 0 12px 12px; display: flex; flex-direction: column; gap: 6px; }
.side-org-label { padding: 0 2px; }
.side-org-label {
  font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--side-label); font-weight: 700;
}
.side-org-pick { position: relative; display: flex; align-items: center; }
.side-org-pick > i:first-child, .side-org-name > i {
  position: absolute; left: 11px; font-size: 17px; color: var(--primary); opacity: 0.7; pointer-events: none;
}
.side-org-pick .chev { position: absolute; right: 9px; font-size: 15px; color: var(--faint); pointer-events: none; }
.side-org select {
  width: 100%; appearance: none; -webkit-appearance: none;
  padding: 9px 28px 9px 34px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--panel);
  color: var(--side-strong); font: inherit; font-size: 0.83rem; font-weight: 600;
  cursor: pointer; text-overflow: ellipsis;
  transition: border-color 0.14s, box-shadow 0.14s;
}
.side-org select:hover { border-color: var(--primary); }
.side-org select:focus-visible { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-glow); }
/* Without JS the choice needs a button; admin.js marks the form `auto` and takes it away. */
.side-org-go { align-self: flex-start; padding: 5px 10px; border-radius: 8px; border: 1px solid var(--line); background: var(--panel); color: var(--side-text); font: inherit; font-size: 0.75rem; font-weight: 700; cursor: pointer; }
.side-org.auto .side-org-go { display: none; }
/* The organizer's block. Not a control and not a link: a flat card with a monogram, carrying its own
   caption. The nav's pill shape and hover are exactly what it must not borrow. */
.side-org.static { padding-top: 2px; }
.side-org-card {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 11px; border-radius: 12px;
  background: var(--panel); border: 1px solid var(--line);
}
.side-org-mark {
  width: 30px; height: 30px; flex-shrink: 0; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  background: var(--primary); color: #fff;
  font-weight: 800; font-size: 0.8rem;
}
.side-org-txt { min-width: 0; display: flex; flex-direction: column; }
.side-org-cap { font-size: 0.58rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--faint); font-weight: 700; }
.side-org-nm {
  font-size: 0.85rem; font-weight: 700; color: var(--side-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Collapsed to a rail there is no room to name anything, and the picker would be unreadable. */
.side-off .side-org { display: none; }

/* ---- Enhanced client switcher (admin.js). The native .side-org-pick above is the no-JS fallback
   and the posted field; once JS swaps in the listbox below, `enh` takes the fallback away. ---- */
.side-org.enh .side-org-pick { display: none; }

/* The trigger wears the exact pill the native select wore — the look the picker keeps. */
.side-org-trigger {
  width: 100%; display: flex; align-items: center; gap: 8px;
  padding: 9px 11px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--panel);
  color: var(--side-strong); font: inherit; font-size: 0.83rem; font-weight: 600;
  cursor: pointer; text-align: left;
  transition: border-color 0.14s, box-shadow 0.14s, background 0.14s;
}
.side-org-trigger-icon { font-size: 17px; color: var(--primary); opacity: 0.7; }
.side-org-trigger-txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-org-trigger .chev { position: static; font-size: 15px; color: var(--faint); transition: color 0.14s, transform 0.18s ease; }
/* Scoped into a client the trigger takes the same tint the native select gets — before the hover
   and open states below, so they can still override its border. */
.side-org.scoped .side-org-trigger { border-color: var(--primary-glow); background: var(--primary-soft); color: var(--primary-ink); }
.side-org.scoped .side-org-trigger-icon { opacity: 1; }
.side-org-trigger:hover { border-color: var(--primary); }
.side-org-trigger:focus-visible,
.side-org-trigger[aria-expanded="true"] { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-glow); }
.side-org-trigger[aria-expanded="true"] .chev { color: var(--primary); transform: rotate(180deg); }

/* The panel. UA styles for [popover] — border, padding, centring margins — go; the anchoring puts
   it under its trigger, and where the browser cannot anchor it falls back to centred, still usable. */
.side-org-menu {
  min-width: 200px; max-width: min(300px, calc(100vw - 24px));
  max-height: min(340px, 60vh); overflow-y: auto;
  margin: 0; inset: auto; padding: 6px;
  border: 1px solid var(--line); border-radius: 12px;
  background: var(--panel); box-shadow: var(--shadow-md); color: var(--text);
}
.side-org-menu:focus-visible { outline: none; }
@supports (position-area: block-end) {
  .side-org-menu {
    margin-block-start: 8px;
    position-area: block-end span-inline-end;
    position-try-fallbacks: flip-block, flip-inline;
  }
}
/* The modern open: a short lift-and-settle in, its mirror out, driven by @starting-style. */
.side-org-menu {
  opacity: 0; transform: translateY(-6px) scale(0.98); transform-origin: top center;
  transition: opacity 0.15s ease, transform 0.18s cubic-bezier(0.16, 1, 0.3, 1),
              overlay 0.18s allow-discrete, display 0.18s allow-discrete;
}
.side-org-menu:popover-open { opacity: 1; transform: translateY(0) scale(1); }
@starting-style { .side-org-menu:popover-open { opacity: 0; transform: translateY(-6px) scale(0.98); } }
@media (prefers-reduced-motion: reduce) {
  .side-org-menu { transition: overlay 0s allow-discrete, display 0s allow-discrete; transform: none; }
  .side-org-menu:popover-open { transform: none; }
}

.side-org-opt {
  width: 100%; display: flex; align-items: center; gap: 10px;
  padding: 8px 9px; border: 0; border-radius: 9px; background: transparent;
  color: var(--text); font: inherit; text-align: left; cursor: pointer;
  transition: background 0.12s;
}
.side-org-opt + .side-org-opt { margin-top: 1px; }
.side-org-opt:hover { background: var(--panel-2); }
.side-org-opt:focus-visible { outline: none; background: var(--panel-2); box-shadow: inset 0 0 0 2px var(--primary-glow); }
.side-org-opt.is-selected { background: var(--primary-soft); }
/* A hairline sets the "all clients" row apart from the clients themselves — only when there are any. */
.side-org-menu.has-list .side-org-opt.is-all { margin-bottom: 5px; padding-bottom: 9px; border-bottom: 1px solid var(--line-soft); border-radius: 9px 9px 0 0; }

.side-org-opt-mark {
  width: 28px; height: 28px; flex-shrink: 0; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  background: var(--primary); color: #fff; font-weight: 800; font-size: 0.78rem;
}
.side-org-opt.is-all .side-org-opt-mark { background: var(--primary-soft); color: var(--primary-ink); font-size: 1rem; }
.side-org-opt-txt { min-width: 0; flex: 1; display: flex; flex-direction: column; line-height: 1.25; }
.side-org-opt-nm { font-size: 0.85rem; font-weight: 650; color: var(--side-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-org-opt.is-selected .side-org-opt-nm { color: var(--primary-ink); }
.side-org-opt-sub { font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.09em; color: var(--faint); font-weight: 700; }
.side-org-opt-check { margin-left: auto; font-size: 16px; color: var(--primary); opacity: 0; }
.side-org-opt.is-selected .side-org-opt-check { opacity: 1; }

/* overflow-x must be explicit: with overflow-y auto, a `visible` x-axis computes to auto,
   and mid-expand the still-clipped nowrap labels flash a horizontal scrollbar. */
.side-nav { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 8px 12px; }
.side-group { margin-top: 16px; }
.side-group:first-child { margin-top: 4px; }
.side-group-label {
  font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--side-label); padding: 0 12px 6px; font-weight: 700;
}

.side-link {
  position: relative;
  display: flex; align-items: center; gap: 11px;
  padding: 10px 12px; margin-bottom: 2px; border-radius: 11px;
  color: var(--side-text); font-weight: 600; font-size: 0.9rem;
  transition: background 0.14s, color 0.14s;
}
/* Icons carry the colour: muted-blue at rest, full brand when hovered or active.
   Keeping them grey is what made the whole rail read as washed out. */
.side-link i { font-size: 20px; color: var(--primary); opacity: 0.55; transition: opacity 0.14s; }
.side-link:hover { background: var(--primary-soft); color: var(--side-strong); }
.side-link:hover i { opacity: 0.9; }
.side-link.active { background: var(--primary-soft); color: var(--primary-ink); font-weight: 700; }
.side-link.active i { opacity: 1; }

.side-foot { padding: 12px; border-top: 1px solid var(--side-line); }

/* Account switcher: the row is the trigger, the menu floats above it. */
.side-account { position: relative; }
.side-user {
  display: flex; align-items: center; gap: 11px;
  padding: 8px; border-radius: 11px; cursor: pointer;
  list-style: none; /* kills the native <details> triangle */
  transition: background 0.14s;
}
.side-user::-webkit-details-marker { display: none; }
.side-user:hover { background: var(--panel-2); }
.side-account[open] > .side-user { background: var(--primary-soft); }
.side-user .av {
  width: 32px; height: 32px; border-radius: 9px; flex-shrink: 0;
  background: var(--primary); color: var(--primary-on);
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 0.78rem;
}
.side-user .who { min-width: 0; overflow: hidden; flex: 1; }
.side-user .who .nm { display: block; color: var(--side-strong); font-size: 0.78rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.side-user .who .rl { display: block; margin-top: 1px; font-size: 0.6rem; color: var(--faint); text-transform: uppercase; letter-spacing: 0.06em; }
.side-user .chev { font-size: 16px; color: var(--faint); transition: transform 0.16s; }
.side-account[open] > .side-user .chev { transform: rotate(180deg); }

/* Explicit: some browsers keep the ::details-content box around when closed, and an
   absolutely-positioned child would still paint over the rail. */
.side-account:not([open]) .side-menu { display: none; }
.side-menu {
  position: absolute; bottom: calc(100% + 8px); left: 0; right: 0; z-index: 20;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
  padding: 6px; overflow: hidden;
  animation: menu-in 0.14s ease-out;
}
@keyframes menu-in { from { opacity: 0; transform: translateY(4px); } }
.side-menu-head { padding: 8px 10px 10px; border-bottom: 1px solid var(--line); margin-bottom: 6px; min-width: 0; }
.side-menu-head .nm { display: block; color: var(--side-strong); font-size: 0.8rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.side-menu-head .rl { display: block; margin-top: 1px; font-size: 0.6rem; color: var(--faint); text-transform: uppercase; letter-spacing: 0.06em; }
.side-menu-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: none; border: 0; border-radius: 8px;
  color: var(--text); font-family: inherit; font-weight: 600; font-size: 0.85rem;
  padding: 9px 10px; cursor: pointer; text-align: left;
  transition: background 0.14s, color 0.14s;
}
.side-menu-item:hover { background: var(--danger-bg); color: var(--danger); }
.side-menu-item i { font-size: 17px; }

/* ---------- Confirm modal (native <dialog>) ---------- */

/* The dialog is the full-viewport layer, not a content-sized box. A content-sized dialog
   plus the pop-in transform overflows the document for a few frames and flashes scrollbars. */
.modal {
  position: fixed; inset: 0;
  width: 100%; max-width: 100%; height: 100%; max-height: 100%;
  margin: 0; padding: 0; border: 0; background: transparent;
  overflow: hidden; /* clips the pop-in transform, so it can never grow the scroll area */
  color: var(--text);
  /* A dialog is painted in the top layer but still inherits down the DOM, and the per-row ones are
     written inside `td.tight` — which is nowrap. Without this the text refuses to wrap and the card
     quietly slices it off. Reset here, next to the colour, for the same reason: a modal should not
     read anything off wherever its markup happens to live. */
  white-space: normal;
}
/* display only when open — the UA rule that hides a closed dialog is weaker than ours. */
.modal[open] { display: grid; place-items: center; }
.modal::backdrop {
  background: radial-gradient(130% 130% at 50% 0%, rgba(20, 23, 36, 0.42), rgba(7, 8, 13, 0.64));
  backdrop-filter: blur(7px) saturate(125%);
  -webkit-backdrop-filter: blur(7px) saturate(125%);
  animation: modalfade 0.22s ease both;
}
.modal[open] .modal-card { animation: modalpop 0.2s cubic-bezier(0.2, 0.9, 0.3, 1.2) both; }
@keyframes modalfade { from { opacity: 0; } to { opacity: 1; } }
@keyframes modalpop {
  from { opacity: 0; transform: translateY(10px) scale(0.96); }
  to { opacity: 1; transform: none; }
}

.modal-card {
  width: min(430px, calc(100vw - 32px));
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 26px;
  box-shadow: 0 30px 70px -20px rgba(10, 11, 13, 0.35);
  text-align: center;
}
.modal-icon {
  width: 48px; height: 48px; margin: 0 auto 16px; border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  background: var(--danger-bg); color: var(--danger);
}
.modal-icon i { font-size: 24px; }
.modal-title { margin: 0 0 8px; font-size: 1.25rem; font-weight: 700; letter-spacing: -0.015em; color: var(--ink); }
.modal-body { margin: 0; color: var(--muted); font-size: 0.92rem; line-height: 1.55; }
.modal-actions { display: flex; gap: 10px; margin-top: 24px; }
.modal-actions .btn { flex: 1; justify-content: center; }

@media (prefers-reduced-motion: reduce) {
  .modal[open] .modal-card, .modal::backdrop { animation: none; }
  .sheet-close:hover, .sheet-close:active { transform: none; }
}

/* Sheet variant — same dialog shell, but a left-aligned form with a head/body/foot
   instead of the centred icon + question of a confirmation. */
/* The form can outgrow a short viewport (four fields plus the checklist), so the card caps its
   height and the body — not the page behind it — takes the scroll. */
.modal.sheet .modal-card {
  width: min(470px, calc(100vw - 32px)); padding: 0; text-align: left; overflow: hidden;
  display: flex; flex-direction: column; max-height: calc(100dvh - 40px);
}
.modal.sheet .modal-card > form { display: flex; flex-direction: column; min-height: 0; }
.modal.sheet .sheet-body { overflow-y: auto; min-height: 0; }
.sheet-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 20px 22px 16px; border-bottom: 1px solid var(--line-soft);
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
}
.sheet-head .modal-title { margin: 0; font-size: 1.2rem; letter-spacing: -0.02em; }
.sheet-desc { margin: 6px 0 0; color: var(--muted); font-size: 0.85rem; line-height: 1.5; }
.sheet-body { padding: 18px 24px 6px; }
.sheet-body .form { margin-top: 0; }
.sheet-foot { display: flex; justify-content: flex-end; gap: 10px; padding: 18px 24px; margin-top: 10px; border-top: 1px solid var(--line); }
.sheet-close {
  width: 34px; height: 34px; flex-shrink: 0; border: 0; border-radius: 50%; padding: 0;
  background: var(--line-soft); color: var(--muted); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 0.16s, color 0.16s, transform 0.16s;
}
.sheet-close i { font-size: 18px; }
.sheet-close:hover { background: var(--danger-bg); color: var(--danger); transform: rotate(90deg); }
.sheet-close:active { transform: rotate(90deg) scale(0.92); }
.sheet-close:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-glow); }

/* Inline explainer inside a sheet — why the flow works the way it does. */
.note {
  display: flex; gap: 9px; align-items: flex-start;
  background: var(--primary-soft); border-radius: var(--radius-sm);
  padding: 11px 13px; margin-top: 4px;
  color: var(--primary-ink); font-size: 0.8rem; line-height: 1.5;
}
.note i { font-size: 18px; }

/* ---------- Fields, inline errors, password checklist ---------- */

/* A labelled control with its own error slot, so a message never shifts the fields below it
   around more than the one line it occupies. */
.form .field { display: flex; flex-direction: column; gap: 7px; }
.form .field + .field { margin-top: 15px; }
.form .field > label { margin-top: 0; }

/* Unscoped on purpose: the same class marks a bad field in the admin forms and on the auth pages. */
input.invalid, select.invalid, textarea.invalid {
  border-color: var(--danger); background: var(--danger-bg);
}
input.invalid:focus, select.invalid:focus, textarea.invalid:focus {
  border-color: var(--danger); box-shadow: 0 0 0 3px rgba(192, 52, 29, 0.22);
}

/* Hidden until it carries a message: the slot exists in the markup either way, so the server's
   errors and the ones admin.js writes land in the same place and look identical. */
.field-error { display: none; align-items: center; gap: 6px; margin: 0; color: var(--danger); font-size: 0.78rem; font-weight: 600; }
.field-error.on { display: flex; }
.field-error i { font-size: 15px; }

/* Says what a choice means before it is made — sits where the error would, and never at the same time. */
.field-hint { margin: 0; color: var(--muted); font-size: 0.78rem; line-height: 1.45; }

/* The label and an action that belongs to the field it labels, on one line. */
.field-head { display: flex; align-items: center; gap: 10px; }
.field-head label { margin-top: 0; margin-right: auto; }

/* ---------- Password: strength meter, rule chips, reveal/copy/generate ---------- */

.pwd-meter { margin: 10px 0 2px; display: grid; gap: 8px; }

/* Four segments filled left to right, so the amount of colour *is* the score. */
.pwd-bar { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.pwd-bar span { height: 4px; border-radius: 999px; background: var(--line-strong); transition: background 0.18s; }

/* The level word reserves its line whether or not it has text, so the chips below do not jump
   the moment the first character is typed. */
.pwd-level { margin: 0; font-size: 0.76rem; font-weight: 700; line-height: 1.25; min-height: 1.25em; }

/* An empty field shows the empty track and the unmet chips — the whole shape of what is being
   asked, before the first keystroke. Hiding half of it and leaving the rest is the worst of both:
   a gap that means nothing. No level class is also the no-JS state, and it reads the same. */
.pwd-meter.lvl-1 .pwd-bar span.on { background: var(--danger); }
.pwd-meter.lvl-1 .pwd-level { color: var(--danger); }
.pwd-meter.lvl-2 .pwd-bar span.on { background: var(--amber); }
.pwd-meter.lvl-2 .pwd-level { color: var(--amber); }
.pwd-meter.lvl-3 .pwd-bar span.on, .pwd-meter.lvl-4 .pwd-bar span.on { background: var(--ok); }
.pwd-meter.lvl-3 .pwd-level, .pwd-meter.lvl-4 .pwd-level { color: var(--ok); }

/* A rule you cannot read is not a rule: an unmet chip stays legible and simply is not green yet. */
.pwd-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.pwd-chip {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px 10px 3px 7px;
  border: 1px solid var(--line-strong); border-radius: 999px; background: var(--panel-2);
  color: var(--muted); font-size: 0.72rem; font-weight: 600;
  transition: color 0.14s, background 0.14s, border-color 0.14s;
}
.pwd-chip i { font-size: 14px; opacity: 0.5; transition: opacity 0.14s; }
.pwd-chip.ok { color: var(--ok); background: var(--ok-bg); border-color: transparent; }
.pwd-chip.ok i { opacity: 1; }

/* The buttons sit on top of the field, so the field needs room for them; the copy button only
   exists where the generator does, hence the attribute picking out the wider padding. */
.pwd-wrap { position: relative; display: block; }
/* The width is not inherited from anywhere: on the auth pages the field only filled its column
   because it was a flex item of it, and the wrapper is now the flex item instead. */
.pwd-wrap input.pwd-input { width: 100%; padding-right: 44px; }
.pwd-wrap input.pwd-input[data-pwd-copy] { padding-right: 78px; }

.pwd-icon-btn {
  position: absolute; right: 7px; top: 50%; transform: translateY(-50%);
  width: 30px; height: 30px; padding: 0; border: 0; border-radius: 8px;
  background: transparent; color: var(--faint); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 0.14s, color 0.14s;
}
.pwd-icon-btn i { font-size: 18px; }
.pwd-icon-btn:hover { background: var(--line-soft); color: var(--text); }
.pwd-icon-btn.done { color: var(--ok); }
/* The toggle is always rightmost; copy steps aside for it. */
.pwd-copy { right: 41px; }

/* The auth pages run a bigger field (17px of padding against the admin forms' 10px), and a button
   sized for the small one looks lost in it. Scaled to match, not to a second arbitrary number. */
.fp .pwd-wrap input.pwd-input { padding-right: 54px; }
.fp .pwd-icon-btn { width: 38px; height: 38px; right: 10px; border-radius: 10px; }
.fp .pwd-icon-btn i { font-size: 22px; }

.pwd-gen {
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 4px;
  border: 0; border-radius: 6px; background: transparent; color: var(--primary);
  font: inherit; font-size: 0.75rem; font-weight: 700; cursor: pointer;
  transition: color 0.14s;
}
.pwd-gen i { font-size: 15px; }
.pwd-gen:hover { color: var(--primary-ink); }
.pwd-gen:hover span { text-decoration: underline; }
/* One turn per click, on an icon that already looks like a spinner — the click is the only
   feedback that a new password appeared, since the field itself just changes from dots to dots.
   Reuses the button spinner's keyframe: there is one definition of "turn once". */
.pwd-gen.spin i { animation: btnspin 0.6s cubic-bezier(0.3, 0, 0.2, 1); }
@media (prefers-reduced-motion: reduce) { .pwd-gen.spin i { animation: none; } }

/* Says what happened to the clipboard, which is otherwise invisible. */
.pwd-flash { font-size: 0.72rem; font-weight: 700; }
.pwd-flash.ok { color: var(--ok); }
.pwd-flash.warn { color: var(--amber); }

/* Row markers: "tu" on your own row, "protegida" on the account nobody may touch. Neither is a
   rank — the lock only explains why that row's actions are greyed out. */
.chip {
  display: inline-flex; align-items: center; gap: 3px; vertical-align: middle; margin-left: 6px;
  padding: 1px 7px; border-radius: 999px;
  background: var(--primary-soft); color: var(--primary-ink);
  font-size: 0.65rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
}
.chip i { font-size: 13px; }
.chip.lock { background: var(--line-soft); color: var(--muted); }

/* ---------- Main + page header ---------- */

.main { min-width: 0; display: flex; flex-direction: column; }

/* One block, no sticky bar: trail, then title + strapline with the primary action opposite. */
.head-block { margin-bottom: 24px; }
.head-block .crumb { margin-bottom: 14px; }
.head-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; }
.head-txt { min-width: 0; }
.head-block h1 { font-size: 1.6rem; font-weight: 800; letter-spacing: -0.03em; margin: 0; }
.head-block h1 .sub { color: var(--faint); font-weight: 600; margin-left: 8px; }
.head-block .lead { margin: 6px 0 0; }
.head-block .actions { flex-shrink: 0; display: flex; align-items: center; gap: 10px; }

/* Breadcrumb. */
.crumb { display: flex; align-items: center; gap: 7px; min-width: 0; margin: 0; padding: 0; list-style: none; font-size: 0.84rem; color: var(--muted); }
.crumb li { display: flex; align-items: center; min-width: 0; }
.crumb .crumb-home i { font-size: 17px; color: var(--primary); margin-right: 2px; }
.crumb a { font-weight: 500; border-radius: 6px; padding: 2px 4px; margin: 0 -2px; transition: color 0.14s, background 0.14s; }
.crumb a:hover { color: var(--primary-ink); background: var(--primary-soft); }
.crumb .sep { color: var(--faint); }
.crumb .here { color: var(--ink); font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.page { padding: 26px 34px 90px; max-width: calc(var(--content-w) + 68px); margin-inline: auto; width: 100%; }

.lead { color: var(--muted); margin: 5px 0 22px; font-size: 0.9rem; max-width: 76ch; }

h1 { font-size: 2rem; font-weight: 800; letter-spacing: -0.03em; margin: 0 0 4px; }
h2 { font-size: 1.02rem; font-weight: 700; letter-spacing: -0.01em; margin: 0 0 4px; }
h3 { font-size: 0.95rem; font-weight: 700; margin: 0 0 4px; }
h4 { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin: 16px 0 8px; }
.muted { color: var(--muted); }

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  background: var(--primary); color: var(--primary-on); text-decoration: none;
  font-family: inherit; font-weight: 700; font-size: 0.85rem; line-height: 1.2;
  padding: 10px 18px; border-radius: 10px; border: 1px solid transparent; cursor: pointer;
  transition: filter 0.14s, background 0.14s, border-color 0.14s, transform 0.05s;
  white-space: nowrap;
}
.btn:hover { filter: brightness(0.96); }
.btn:active { transform: scale(0.98); }
.btn svg { width: 16px; height: 16px; }
.btn i { font-size: 18px; margin-left: -2px; }
.btn.danger { background: var(--danger); color: #fff; border-color: var(--danger); }
.btn.danger:hover { filter: brightness(1.08); box-shadow: 0 10px 22px -8px rgba(192, 52, 29, 0.55); }
.btn.ghost { background: var(--panel); color: var(--text); border-color: var(--line-strong); }
.btn.ghost:hover { background: var(--panel-2); filter: none; border-color: var(--faint); }
/* An action that exists but is not available yet — still readable, visibly not clickable. */
.btn.is-off { opacity: 0.45; cursor: not-allowed; pointer-events: auto; }
.btn.is-off:hover { background: var(--panel); border-color: var(--line-strong); filter: none; }
.btn.dark { background: var(--ink); color: #fff; }
.btn.sm { padding: 7px 13px; font-size: 0.8rem; border-radius: 9px; }

.link { color: var(--primary-ink); font-weight: 600; }
.link:hover { text-decoration: underline; }

/* Row-action buttons — the last cell of a table reads as a control, not a bare link,
   and the two intents are told apart: `.open` (a platform event you own and manage)
   carries a soft-primary weight; `.view` (a read-only peek at the HMS catalogue) is a
   quiet outline. */
.act { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 8px;
  font-size: 0.8rem; font-weight: 650; line-height: 1; border: 1px solid transparent; white-space: nowrap;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease; }
.act svg { width: 15px; height: 15px; }
.act .ar { transition: transform 0.18s ease; }
.act:hover .ar { transform: translateX(3px); }
.act.open { background: var(--primary-soft); color: var(--primary-ink); }
.act.open:hover { background: var(--primary); color: var(--primary-on); }
.act.view { border-color: var(--line-strong); color: var(--muted); }
.act.view:hover { border-color: var(--primary); color: var(--primary-ink); background: var(--primary-soft); }
/* The icon sits in a fixed-size slot so swapping it for the spinner never shifts the label. */
.act-ic-slot { display: inline-flex; width: 15px; height: 15px; align-items: center; justify-content: center; }
.act.is-loading { pointer-events: none; }
.act-spinner { width: 14px; height: 14px; border: 2px solid currentColor; border-top-color: transparent;
  border-radius: 50%; animation: btnspin 0.7s linear infinite; }

.x { background: transparent; border: 1px solid var(--line); color: var(--muted); cursor: pointer; font-size: 0.85rem; width: 30px; height: 30px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center; padding: 0; transition: color 0.14s, border-color 0.14s, background 0.14s; }
.x:hover { color: var(--danger); border-color: var(--danger); background: var(--danger-bg); }

/* ---------- Cards ---------- */

.cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; margin-top: 22px; }
@media (max-width: 900px) { .cards { grid-template-columns: 1fr; } }
.card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 22px; box-shadow: var(--shadow-sm); }
.card.nested { background: var(--panel-2); border-style: dashed; margin: 14px 0; }
.card > h2, .card.nested > h3 { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.card.nested > h3 form { margin: 0; }

/* ---------- KPI stat tiles ---------- */

.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; margin: 4px 0 26px; }
.kpi { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 18px 20px; box-shadow: var(--shadow-sm); position: relative; overflow: hidden; }
.kpi .k-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); font-weight: 600; display: flex; align-items: center; gap: 7px; }
.kpi .k-label svg { width: 15px; height: 15px; color: var(--primary-ink); }
.kpi .k-value { font-size: 1.9rem; font-weight: 800; letter-spacing: -0.03em; margin-top: 8px; font-variant-numeric: tabular-nums; }
.kpi .k-value .cur { font-size: 0.95rem; color: var(--faint); font-weight: 600; margin-left: 4px; }
.kpi.accent { background: var(--ink); border-color: var(--ink); color: #fff; }
.kpi.accent .k-label { color: rgba(255, 255, 255, 0.6); }
.kpi.accent .k-label svg { color: var(--primary-lift); }
.kpi.accent .k-value .cur { color: rgba(255, 255, 255, 0.45); }

/* ---------- Bento dashboard ---------- */

.bento { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin: 4px 0 0; }
.bento .b-wide { grid-column: span 2; }
.bento .b-full { grid-column: 1 / -1; }
@media (max-width: 900px) { .bento { grid-template-columns: 1fr; } .bento .b-wide { grid-column: auto; } }

.hero-card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 20px 22px; box-shadow: var(--shadow-sm); display: flex; flex-direction: column; }
.hero-card .h-top { display: flex; align-items: center; justify-content: space-between; }
.hero-card .h-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted); font-weight: 700; }
.hero-card .h-trend { font-size: 0.72rem; font-weight: 700; color: var(--ok); }
.hero-card .h-value { font-size: 2rem; font-weight: 800; letter-spacing: -0.03em; margin: 6px 0 0; font-variant-numeric: tabular-nums; }
.hero-card .h-value .cur { font-size: 0.9rem; color: var(--faint); font-weight: 600; margin-left: 4px; }
.hero-card .bars { margin-top: auto; padding-top: 16px; width: 100%; height: 78px; display: block; }
.hero-card .bars text { fill: var(--faint); font-size: 3.4px; font-weight: 600; }

.stat-stack { display: grid; grid-template-rows: repeat(3, 1fr); gap: 14px; }
/* The same tiles laid out across the page instead of down a column, for pages with no hero card
   beside them. Auto-fit so four tiles wrap to two rows on a narrow window rather than squashing. */
.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px; }

/* A plain vertical run of sections. The dashboard has .dash for its two-column arrangement; a page
   that is just one block after another needs only the gap. */
.stack { display: grid; gap: 16px; margin: 4px 0 0; }
/* Grid items default to min-width:auto, so a wide table inside one stretches the whole page
   sideways instead of scrolling inside its own .scroll box. This is what keeps it contained. */
.stack > *, .stat-row > * { min-width: 0; }
.mini-stat { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; box-shadow: var(--shadow-sm); display: flex; align-items: center; gap: 12px; }
.mini-stat .chip { width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; background: var(--primary-soft); color: var(--primary); }
.mini-stat .chip svg { width: 17px; height: 17px; }
.mini-stat .chip.green { background: var(--ok-bg); color: var(--ok); }
/* Block, or the label and the number sit on one line and read as "EVENTOS0". */
.mini-stat .m-label, .mini-stat .m-value { display: block; }
.mini-stat .m-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); font-weight: 700; }
.mini-stat .m-value { font-size: 1.5rem; font-weight: 800; letter-spacing: -0.03em; line-height: 1.05; margin-top: 2px; font-variant-numeric: tabular-nums; }

/* ---------- Tables ---------- */

.scroll { overflow-x: auto; border-radius: var(--radius); }
table.grid { width: 100%; border-collapse: collapse; font-size: 0.9rem; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
table.grid.bare { background: transparent; border: 0; }
table.grid th, table.grid td { text-align: left; padding: 13px 16px; border-bottom: 1px solid var(--line-soft); white-space: nowrap; }
table.grid thead th { background: var(--panel-2); color: var(--faint); font-weight: 700; text-transform: uppercase; font-size: 0.68rem; letter-spacing: 0.06em; border-bottom: 1px solid var(--line); }
table.grid tbody tr { transition: background 0.12s; }
table.grid tbody tr:hover { background: var(--panel-2); }
table.grid tbody tr:last-child td { border-bottom: 0; }
table.grid td.tight { width: 1%; }

/* Table + footnote as one card. The table drops its own frame and inherits the card's. */
.tbl { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow: hidden; }
.tbl > .scroll { border-radius: 0; }
.tbl table.grid { border: 0; border-radius: 0; box-shadow: none; }
.tbl table.grid tbody tr:last-child td { border-bottom: 0; }
table.grid tr[data-row-href] { cursor: pointer; }
table.grid td.num, table.grid th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.grid td.strong { font-weight: 700; }
table.grid.mini { font-size: 0.86rem; }
table.grid.mini th, table.grid.mini td { padding: 9px 12px; }

/* ---------- Properties header (event detail) ---------- */

.props { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; padding: 0 2px 2px; }
.props-meta { display: flex; flex-wrap: wrap; gap: 8px 18px; color: var(--muted); font-size: 0.86rem; }
.props-item { display: inline-flex; align-items: baseline; gap: 7px; }
.props-k { font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; color: var(--faint); }
.props-v { font-weight: 700; color: var(--ink); }
.props-links { display: inline-flex; flex-wrap: wrap; gap: 8px; margin-left: auto; }
.props-link { font-size: 0.82rem; font-weight: 600; color: var(--primary-ink); text-decoration: none; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--line); }
.props-link:hover { border-color: var(--primary); background: var(--primary-soft); }

/* ---------- Accordion: an edition opens to reveal its provas, in place ---------- */

.acc { display: flex; flex-direction: column; gap: 10px; }
.acc-item { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow: hidden; }
.acc-item[open] { border-color: var(--primary-glow); }

.acc-sum {
  display: flex; align-items: center; gap: 14px;
  padding: 15px 18px; cursor: pointer; list-style: none;
  transition: background 0.14s ease;
}
.acc-sum::-webkit-details-marker { display: none; }
.acc-sum:hover { background: var(--panel-2); }
.acc-item[open] .acc-sum { border-bottom: 1px solid var(--line); }

.acc-lead { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 3px; }
.acc-title { font-weight: 800; font-size: 1rem; letter-spacing: -0.01em; display: inline-flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.acc-sub { font-size: 0.8rem; color: var(--muted); }

.acc-chev {
  flex-shrink: 0; width: 34px; height: 34px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line-strong); color: var(--muted);
  transition: color 0.14s ease, border-color 0.14s ease, background 0.14s ease;
}
.acc-sum:hover .acc-chev, .acc-item[open] .acc-chev { border-color: var(--primary); color: var(--primary-ink); background: var(--primary-soft); }
.acc-chev svg { width: 18px; height: 18px; transition: transform 0.22s ease; }
.acc-item[open] .acc-chev svg { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .acc-chev svg { transition: none; } }

.acc-body { padding: 0; }
.acc-body .tbl { border: 0; box-shadow: none; border-radius: 0; }
.acc-actions { display: flex; flex-wrap: wrap; gap: 16px; padding: 12px 18px; }
.acc-empty { padding: 16px 18px; text-align: left; color: var(--muted); }

.acc-item[open] .acc-body { animation: acc-in 0.22s ease both; }
@keyframes acc-in { from { opacity: 0; transform: translateY(-4px); } }
@media (prefers-reduced-motion: reduce) { .acc-item[open] .acc-body { animation: none; } }

/* ---------- Pills / badges ---------- */

.pill { display: inline-flex; align-items: center; gap: 6px; padding: 4px 11px; border-radius: 999px; border: 1px solid var(--line-strong); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; color: var(--muted); }
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: 0.7; }
.pill.ok { border-color: transparent; background: var(--ok-bg); color: var(--ok); }
/* Filter pills carry meaning, so their colour is semantic: active green, inactive red, all in the
   app blue. Same criterion throughout — hover is an outline tint, selected is a soft fill. */
.pill.filt { cursor: pointer; transition: border-color 0.14s ease, color 0.14s ease, background 0.14s ease; }
.pill.filt.f-active:hover   { border-color: var(--ok); color: var(--ok); }
.pill.filt.f-inactive:hover { border-color: var(--danger); color: var(--danger); }
.pill.filt.f-all:hover      { border-color: var(--primary); color: var(--primary-ink); }
.pill.filt.f-active.is-on   { border-color: transparent; background: var(--ok-bg); color: var(--ok); }
.pill.filt.f-inactive.is-on { border-color: transparent; background: var(--danger-bg); color: var(--danger); }
.pill.filt.f-all.is-on      { border-color: transparent; background: var(--primary-soft); color: var(--primary-ink); }

/* Badge — a pill that leads with an icon instead of a dot. */
.badge { display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; border-radius: 999px; font-size: 0.74rem; font-weight: 700; background: var(--line-soft); color: var(--muted); white-space: nowrap; }
.badge i { font-size: 15px; }
.badge.ok { background: var(--ok-bg); color: var(--ok); }
.badge.pending { background: var(--amber-bg); color: var(--amber); }
.badge.role { border-radius: 7px; font-weight: 600; text-transform: none; }
.badge.off { background: var(--line-soft); color: var(--faint); }

/* ---------- Table extras ---------- */

/* Identity cell: square avatar + name over a secondary line. */
.u-cell { display: flex; align-items: center; gap: 12px; min-width: 0; }
.u-av {
  width: 34px; height: 34px; border-radius: 9px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--primary-soft); color: var(--primary-ink);
  font-weight: 800; font-size: 0.72rem; letter-spacing: 0.02em;
}
.u-av.soft { background: var(--line-soft); color: var(--faint); }
.u-main { min-width: 0; }
.u-name { display: block; font-weight: 700; color: var(--ink); font-size: 0.88rem; }
.u-sub { display: block; color: var(--muted); font-size: 0.82rem; margin-top: 1px; }

/* Profile cell: the badge says what the account is, the line under it says over what. An
   administrator's "Todas as organizações" is stated rather than left blank — a blank there reads
   as missing data, when it is in fact the whole point of the profile. */
.u-profile { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.u-org { font-size: 0.78rem; font-weight: 600; color: var(--muted); }
.u-org.faint { color: var(--faint); font-weight: 500; }

/* A row whose subject no longer has access — recedes, but stays legible and actionable. */
table.grid tbody tr.off .u-name { color: var(--muted); }
table.grid tbody tr.off td { opacity: 0.72; }
table.grid tbody tr.off td.tight { opacity: 1; }

/* Footnote strip under a table, inside the same card. */
.table-foot {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 16px; border-top: 1px solid var(--line);
  background: var(--panel); color: var(--faint); font-size: 0.8rem;
}
.table-foot i { font-size: 16px; }

/* ---------- Row action menu ---------- */

.rowmenu { position: relative; display: flex; justify-content: flex-end; }
.rowmenu-btn {
  width: 32px; height: 32px; border-radius: 8px; border: 0; padding: 0;
  background: transparent; color: var(--faint); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 0.14s, color 0.14s;
}
.rowmenu-btn i { font-size: 20px; }
.rowmenu-btn:hover, .rowmenu-btn[aria-expanded="true"] { background: var(--line-soft); color: var(--text); }
.rowmenu-btn:focus-visible { outline: none; color: var(--primary-ink); background: var(--primary-soft); box-shadow: 0 0 0 3px var(--primary-glow); }

/* Fixed, not absolute: the row lives inside a card that clips its overflow to keep the
   rounded corners, and an absolutely-positioned menu would be cut off by it. admin.js
   pins the menu to the button's viewport box and closes it on scroll. */
.rowmenu-list {
  position: fixed; z-index: 30; min-width: 200px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
  padding: 6px; display: none;
  animation: menu-in 0.14s ease-out;
}
.rowmenu-list.open { display: block; }
.rowmenu-list form { margin: 0; }
.rowmenu-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: none; border: 0; border-radius: 7px; cursor: pointer; text-align: left;
  padding: 9px 10px; font-family: inherit; font-size: 0.85rem; font-weight: 600; color: var(--text);
  transition: background 0.14s;
}
.rowmenu-item i { font-size: 18px; color: var(--muted); }
.rowmenu-item:hover { background: var(--line-soft); }
.rowmenu-item.danger, .rowmenu-item.danger i { color: var(--danger); }
.rowmenu-item.danger:hover { background: var(--danger-bg); }
.rowmenu-item[disabled] { opacity: 0.45; cursor: not-allowed; }
.rowmenu-item[disabled]:hover { background: none; }
.rowmenu-sep { height: 1px; background: var(--line); margin: 5px 4px; }

/* ---------- Toolbar: search + filter ---------- */

.toolbar { display: flex; gap: 10px; margin-bottom: 14px; }
.search { position: relative; flex: 1; display: flex; align-items: center; }
.search i { position: absolute; left: 12px; font-size: 18px; color: var(--faint); pointer-events: none; }
.search input {
  width: 100%; height: 40px; padding: 0 14px 0 38px;
  background: var(--panel); border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  color: var(--ink); font-family: inherit; font-size: 0.9rem; outline: none;
  transition: border-color 0.14s, box-shadow 0.14s;
}
.search input::placeholder { color: var(--faint); }
.search input:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-glow); }
/* The chevron is a data-URI so the control keeps a single, consistent look across browsers. */
.select {
  height: 40px; padding: 0 34px 0 13px; flex-shrink: 0;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--panel) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%2394a3b8' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right 11px center;
  color: var(--text); font-family: inherit; font-size: 0.9rem; cursor: pointer;
  -webkit-appearance: none; appearance: none; outline: none;
  transition: border-color 0.14s, box-shadow 0.14s;
}
.select:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-glow); }

/* Shown by admin.js when a search or filter leaves no rows standing. */
.no-match { display: none; padding: 40px 20px; text-align: center; color: var(--faint); font-size: 0.9rem; }
.no-match.on { display: block; }

/* ---------- Stat tiles ---------- */

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; margin-bottom: 20px; }
.stat { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 15px 18px; box-shadow: var(--shadow-sm); }
.stat-label { display: flex; align-items: center; gap: 7px; font-size: 0.78rem; color: var(--muted); font-weight: 600; }
.stat-label i { font-size: 17px; color: var(--primary); }
.stat-value { font-size: 1.6rem; font-weight: 800; letter-spacing: -0.03em; color: var(--ink); margin-top: 7px; line-height: 1; font-variant-numeric: tabular-nums; }
.stat-value small { font-size: 0.82rem; font-weight: 600; color: var(--faint); }

/* ---------- Forms ---------- */

.form { display: flex; flex-direction: column; gap: 7px; margin-top: 10px; }
.form h2 { margin-top: 14px; }
.form label, .fieldgrid label { font-size: 0.76rem; color: var(--muted); font-weight: 600; margin-top: 4px; }
.form input, .form select, .form textarea,
.fieldgrid input, .fieldgrid select, .fieldgrid textarea {
  background: var(--panel-2); border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  padding: 10px 13px; color: var(--text); font-size: 0.95rem; font-family: inherit; outline: none; width: 100%;
  transition: border-color 0.14s, box-shadow 0.14s;
}
.form input:focus, .form select:focus, .form textarea:focus,
.fieldgrid input:focus, .fieldgrid select:focus, .fieldgrid textarea:focus {
  border-color: var(--primary-ink); box-shadow: 0 0 0 3px var(--primary-glow); background: var(--panel);
}
.form input[type="color"] { padding: 4px; height: 44px; width: 68px; }
.form .btn { margin-top: 12px; align-self: flex-start; }
.form.inline { flex-flow: row wrap; align-items: end; gap: 10px; border-top: 1px dashed var(--line-strong); padding-top: 16px; margin-top: 16px; }
.form.inline input, .form.inline select { width: auto; flex: 1; min-width: 130px; }
.form.inline .btn { margin-top: 0; }

.fieldgrid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px 16px; margin: 6px 0 12px; }
.fieldgrid .wide { grid-column: 1 / -1; }
.fieldgrid .check { align-self: end; }
.fieldgrid label { display: block; margin-bottom: 4px; }
.fieldgrid input, .fieldgrid select, .fieldgrid textarea { font-size: 0.9rem; }
.fieldgrid .check label { display: inline-flex; align-items: center; gap: 8px; margin: 0; font-size: 0.9rem; color: var(--text); }
.fieldgrid .check input { width: auto; }
@media (max-width: 640px) { .fieldgrid { grid-template-columns: 1fr; } }

/* Repeatable field rows (price windows): proper date/value fields, add and remove — never a textarea. */
.rows { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
.row-fields { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
.row-fields > div { display: flex; flex-direction: column; gap: 5px; flex: 1 1 130px; min-width: 120px; }
.row-fields > div > label { margin: 0; }
.row-fields .x { flex: 0 0 auto; margin-bottom: 1px; }
@media (max-width: 560px) { .row-fields > div { flex-basis: 100%; } }

details.builder { margin-top: 14px; border-top: 1px dashed var(--line-strong); padding-top: 12px; }
details.builder > summary { cursor: pointer; font-weight: 700; font-size: 0.82rem; color: var(--primary-ink); list-style: none; display: inline-flex; align-items: center; gap: 7px; }
details.builder > summary::-webkit-details-marker { display: none; }
details.builder > summary::before { content: "+"; font-size: 1rem; line-height: 1; }
details.builder[open] > summary::before { content: "−"; }

/* ---------- Notices ---------- */

.notice, .alert { margin: 0 0 20px; padding: 12px 16px; border-radius: var(--radius-sm); font-size: 0.88rem; display: flex; align-items: center; gap: 10px; font-weight: 500; }
.notice { border: 1px solid rgba(9, 105, 247, 0.24); background: var(--primary-soft); color: var(--primary-ink); }
.notice::before { content: "✓"; font-weight: 800; }
.alert { border: 1px solid rgba(192, 52, 29, 0.28); background: var(--danger-bg); color: var(--danger); }

.empty { padding: 40px 20px; text-align: center; color: var(--faint); }

/* ---------- Layout helpers ---------- */

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

.row { display: flex; align-items: center; gap: 12px; }
.row.wrap { flex-wrap: wrap; }
.row.gap { gap: 8px; }
.mt { margin-top: 12px; }
.mt-lg { margin-top: 24px; }

/* ---------- Auth — two rounded panels: photo left, form right ---------- */

.auth-shell { position: relative; min-height: 100vh; background: var(--canvas); padding: 18px; }
.auth-grid {
  display: grid; grid-template-columns: 0.98fr 1.02fr; gap: 18px;
  min-height: calc(100vh - 36px);
}

/* Left — video panel (photo is the poster / no-JS fallback) */
.bp {
  position: relative; overflow: hidden; color: #fff; border-radius: 24px;
  padding: 44px clamp(30px, 3vw, 52px);
  display: flex; flex-direction: column; justify-content: flex-end;
  background-color: #0c0f14;
  background-image: url("/img/login-bg.jpg");
  background-size: cover;
  background-position: center 32%;
  background-repeat: no-repeat;
}
.bp-video {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover; object-position: center 32%;
  /* Tame the footage so it reads as background, not as content: pull the saturation
     out of the race kit / bibs, darken, and lift contrast slightly to keep shape. */
  filter: saturate(0.55) brightness(0.78) contrast(1.05);
  /* fade in once the first frame is decoded, so the poster→video swap is not a jump */
  animation: bpfade 0.9s ease both;
}
@keyframes bpfade { from { opacity: 0; } to { opacity: 1; } }

/* Neutral dark wash + bottom gradient, so the title always has a calm, dark bed.
   Kept near-black rather than brand blue — a blue tint over footage reads as "tinted photo". */
.bp-scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(8, 10, 14, 0) 0%, rgba(8, 10, 14, 0.18) 52%, rgba(8, 10, 14, 0.72) 94%),
    linear-gradient(90deg, rgba(8, 10, 14, 0.22) 0%, rgba(8, 10, 14, 0) 55%);
}
.bp-mid { position: relative; z-index: 2; }


@media (prefers-reduced-motion: reduce) {
  .bp-video { display: none; }
}
.bp-title { font-size: clamp(2rem, 2.6vw, 2.8rem); font-weight: 900; letter-spacing: -0.045em; line-height: 1; margin: 0; text-transform: uppercase; }
.bp-title em { font-style: normal; color: #bcd8fd; }
.bp-tag { margin: 14px 0 0; color: rgba(255, 255, 255, 0.76); font-size: 0.98rem; max-width: 34ch; line-height: 1.55; }

/* Right — form panel. Logo + form sit in a centred column; the footer spans the card. */
.fp {
  background: var(--panel); border: 1px solid var(--line); border-radius: 24px;
  padding: 40px clamp(36px, 4vw, 64px);
  display: flex; flex-direction: column; overflow-y: auto;
}
.fp-col { flex: 1; width: 100%; max-width: 430px; margin: 0 auto; display: flex; flex-direction: column; }
.fp-top { display: flex; justify-content: center; }
.fp-logo { height: 42px; width: auto; object-fit: contain; display: block; }
.fp-inner { width: 100%; margin: auto 0; padding: 32px 0; }
.fp h1 { font-size: 2.05rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; margin: 0 0 10px; color: var(--ink); }
.fp > .fp-inner > .muted, .fp .lead-sub { font-size: 1rem; color: var(--muted); margin: 0; line-height: 1.6; max-width: 38ch; }
.fp-foot {
  padding-top: 32px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  font-size: 0.76rem; color: var(--faint);
}
.fp-foot .mfa { display: inline-flex; align-items: center; gap: 7px; color: var(--muted); font-weight: 600; }
.fp-foot .mfa svg { width: 14px; height: 14px; }

.auth-steps { display: flex; align-items: center; gap: 7px; margin: 26px 0 0; }
.auth-steps .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line-strong); transition: background 0.2s; }
.auth-steps .dot.on { background: var(--primary); }
/* margin: 0 is load-bearing — the bare `.bar` progress bar further down carries a
   margin-top, and without this the connector sits below the dots instead of between them. */
.auth-steps .bar { width: 26px; height: 2px; margin: 0; border-radius: 2px; background: var(--line-strong); transition: background 0.2s; }
.auth-steps .bar.on { background: var(--primary); }

.fp form { margin-top: 26px; display: flex; flex-direction: column; gap: 16px; }
.auth-field { display: flex; flex-direction: column; gap: 9px; }
.fp label { font-size: 0.82rem; color: var(--text); font-weight: 700; }
.fp input {
  background: var(--panel-2); border: 1px solid var(--line-strong); border-radius: 14px;
  padding: 17px 18px; color: var(--text); font-size: 1.02rem; font-family: inherit; outline: none;
  line-height: 1.2; /* pinned so .email-chip can reproduce the exact same height */
  transition: border-color 0.14s, box-shadow 0.14s;
}
.fp input:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-glow); background: var(--panel); }
.fp .btn { margin-top: 8px; width: 100%; padding: 17px; font-size: 1rem; border-radius: 14px; }
.fp .alert { margin: 20px 0 0; }

/* animated CTA */
.btn-cta { position: relative; overflow: hidden; }
.btn-cta::after { content: ""; position: absolute; top: 0; left: -70%; width: 45%; height: 100%; background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.4), transparent); transform: skewX(-20deg); transition: left 0.55s ease; }
.btn-cta:hover::after { left: 150%; }
.btn-cta:hover { box-shadow: 0 12px 26px -8px rgba(9, 105, 247, 0.6); }
.btn-cta .ar { transition: transform 0.22s ease; display: inline-block; }
.btn-cta:hover .ar { transform: translateX(5px); }
.btn.is-loading { pointer-events: none; }
.btn-spinner { width: 17px; height: 17px; border: 2.5px solid rgba(255, 255, 255, 0.4); border-top-color: #fff; border-radius: 50%; animation: btnspin 0.7s linear infinite; }
@keyframes btnspin { to { transform: rotate(360deg); } }

/* read-only email row on step 2 */
/* Same border, padding, font-size and line-height as .fp input, so both boxes land
   on the same rendered height without a hard-coded value. */
.email-chip { display: flex; align-items: center; justify-content: space-between; gap: 10px; background: var(--primary-soft); border: 1px solid var(--border-accent, rgba(9,105,247,.22)); border-radius: 14px; padding: 17px 18px; }
.email-chip .who { display: flex; align-items: center; gap: 9px; min-width: 0; color: var(--text); }
.email-chip .who svg { width: 17px; height: 17px; color: var(--primary); flex-shrink: 0; }
.email-chip .who i { font-size: 19px; color: var(--primary); }
.email-chip .addr { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; font-size: 1.02rem; line-height: 1.2; }
.email-chip .chg { color: var(--primary-ink); font-size: 0.8rem; font-weight: 700; flex-shrink: 0; }
.email-chip .chg:hover { text-decoration: underline; }

/* one-box-per-digit OTP field */
.otp { display: flex; gap: 8px; }
.otp-box {
  flex: 1 1 0; min-width: 0; height: 56px; padding: 0; text-align: center;
  font-family: inherit; font-size: 1.35rem; font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--text); background: var(--panel-2);
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  outline: none; caret-color: var(--primary);
  transition: border-color 0.14s, box-shadow 0.14s, background 0.14s, transform 0.12s;
}
.otp-box.has { border-color: var(--primary); background: var(--panel); }
.otp-box:focus {
  border-color: var(--primary); background: var(--panel);
  box-shadow: 0 0 0 3px var(--primary-glow); transform: translateY(-1px);
}
.otp-note:empty { display: none; }
.otp-note { margin: 8px 0 0; font-size: 0.85rem; color: var(--muted); }
.otp.shake { animation: otpShake 0.32s ease; }
@keyframes otpShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(2px); }
}
@media (prefers-reduced-motion: reduce) {
  .otp.shake { animation: none; }
  .otp-box:focus { transform: none; }
}
@media (max-width: 400px) {
  .otp { gap: 6px; }
  .otp-box { height: 48px; font-size: 1.15rem; }
}

.link-btn { background: transparent; border: 0; color: var(--muted); cursor: pointer; font-size: 0.84rem; text-decoration: underline; padding: 6px 0; font-family: inherit; }
.link-btn:hover { color: var(--text); }
.center-form { margin-top: 12px; text-align: center; }
.qr { margin: 18px auto 12px; display: flex; justify-content: center; background: #fff; padding: 14px; border-radius: 16px; width: fit-content; border: 1px solid var(--line); box-shadow: var(--shadow-sm); }
.small { font-size: 0.8rem; margin-bottom: 6px; }
.key { font-family: ui-monospace, "Cascadia Code", monospace; letter-spacing: 0.08em; color: var(--text); background: var(--panel-2); border: 1px solid var(--line-strong); border-radius: 9px; padding: 10px 14px; display: inline-block; word-break: break-all; }

@media (max-width: 900px) {
  .auth-shell { padding: 12px; }
  .auth-grid { grid-template-columns: 1fr; grid-template-rows: 180px 1fr; gap: 12px; min-height: calc(100vh - 24px); }
  .bp { padding: 26px 28px; }
  .bp-title { font-size: 1.7rem; }
  .bp-tag, .bp-foot { display: none; }
  .fp { padding: 32px 28px; }
  .fp-inner { max-width: none; padding: 26px 0; }
  .fp h1 { font-size: 1.75rem; }
  .fp-foot { flex-direction: column; align-items: flex-start; gap: 8px; padding-top: 24px; }
}
/* Off the phone the scrim is not part of the layout at all. */
.nav-scrim { display: none; }

@media (max-width: 820px) {
  /* The rail becomes a top bar — brand on the left, burger on the right — and everything that
     was under the brand becomes the drawer the burger opens. There is nothing left to collapse,
     so every .side-off rule is neutralised here rather than fought with later. */
  /* Two rows now, and they must be named: the grid still carries min-height 100vh, and auto rows
     under the default align-content: stretch would split the leftover height between the bar and
     the page — a 300px-tall white band under the logo. */
  .app, .side-off .app { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr); }
  .side-toggle, .side-off .side-toggle { display: none; }

  .side {
    position: sticky; top: 0; z-index: 50;
    height: auto; align-self: start;
    flex-direction: column; align-items: stretch; overflow: visible;
    border-right: 0; border-bottom: 1px solid var(--side-line);
  }
  .side-head, .side-off .side-head { justify-content: space-between; padding: 9px 14px; }
  .side-off .side-brand, .side-off .side-head:hover .side-brand { justify-content: flex-start; opacity: 1; }
  .side-off .side-logo { display: block; }
  .side-off .side-icon { display: none; }

  /* Drawer — only when the script is there to open it. Without JS the nav simply stays on the
     page, stacked under the bar, exactly as it is here minus the folding. */
  .js .burger { display: inline-flex; }
  .js .side-body, .js.side-off .side-body {
    position: absolute; top: 100%; left: 0; right: 0;
    flex: 0 0 auto;
    padding: 4px 6px 10px;
    background: var(--side-bg);
    border-bottom: 1px solid var(--side-line);
    box-shadow: var(--shadow-md);
    max-height: calc(100vh - 62px); overflow-y: auto;
    opacity: 0; visibility: hidden; transform: translateY(-10px);
    transition: transform 0.26s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.18s linear, visibility 0s linear 0.26s;
  }
  .js.nav-open .side-body { opacity: 1; visibility: visible; transform: none; transition: transform 0.26s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.18s linear, visibility 0s; }

  /* The panel arrives, then its contents settle into it. On the way out they leave at once —
     the delays are only on the open — so closing stays as quick as the burger's own snap. */
  .js .side-body > * { opacity: 0; transform: translateY(-7px); transition: opacity 0.2s, transform 0.24s cubic-bezier(0.16, 1, 0.3, 1); }
  .js.nav-open .side-body > * { opacity: 1; transform: none; }
  .js.nav-open .side-body > *:nth-child(1) { transition-delay: 0.05s; }
  .js.nav-open .side-body > *:nth-child(2) { transition-delay: 0.1s; }
  .js.nav-open .side-body > *:nth-child(3) { transition-delay: 0.15s; }

  .nav-scrim {
    display: block; position: fixed; inset: 0; z-index: 40;
    background: rgba(10, 11, 13, 0.4);
    opacity: 0; visibility: hidden;
    transition: opacity 0.22s linear, visibility 0s linear 0.22s;
  }
  .nav-open .nav-scrim { opacity: 1; visibility: visible; transition: opacity 0.22s linear, visibility 0s; }

  /* In the drawer the rail is itself again: full-width links, labels back, account at the foot
     (which the old row bar had to drop for want of room). */
  .side-org, .side-off .side-org { display: flex; padding: 8px 6px 10px; }
  .side-nav, .side-off .side-nav { padding: 4px 6px; }
  .side-group, .side-off .side-group { margin-top: 14px; }
  .side-group:first-child { margin-top: 2px; }
  .side-group-label, .side-off .side-group-label { display: block; }
  .side-link, .side-off .side-link { justify-content: flex-start; font-size: 0.95rem; gap: 11px; padding: 11px 12px; }
  .side-off .side-link span { display: inline; }
  .side-foot, .side-off .side-foot { display: block; padding: 10px 6px 2px; }
  .side-user, .side-off .side-user { justify-content: flex-start; padding: 8px 10px; gap: 10px; }
  .side-off .side-user .who { display: block; }
  .side-off .side-user .chev { display: block; }

  .page { padding: 22px 18px 70px; }
  .head-row { flex-direction: column; align-items: stretch; gap: 14px; }
  .head-block .actions .btn { flex: 1; justify-content: center; }
  .toolbar { flex-wrap: wrap; }
  .search { flex-basis: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .js .side-body, .js.nav-open .side-body,
  .js .side-body > *, .js.nav-open .side-body > *,
  .nav-scrim, .nav-open .nav-scrim { transition: none; }
  .js .side-body > * { transform: none; opacity: 1; }
}

/* ---------- Dashboard ---------- */

.dash {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin-top: 2px;
}
/* Above 1120px the hero chart and the KPI stack share the first row; below, everything stacks. */
.dash-hero { grid-column: span 2; }
.dash-kpis { grid-column: span 2; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
@media (min-width: 1120px) {
  .dash { grid-template-columns: minmax(0, 1.62fr) minmax(0, 1fr); }
  .dash-hero { grid-column: 1; grid-row: 1; }
  .dash-kpis { grid-column: 2; grid-row: 1; grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .dash, .dash-kpis { grid-template-columns: 1fr; }
  .dash-hero, .dash-kpis { grid-column: auto; }
}

/* Staggered reveal. --i is the child's position, put there by initStagger in admin.js: it used to
   be hand-written into each block's style attribute, where style-src 'self' dropped it unread and
   the whole page arrived at once. Without the script every delay is 0 — which is the animation
   this page has actually been playing all along. */
.dash > * { animation: dash-in 0.45s cubic-bezier(0.22, 0.9, 0.3, 1) both; animation-delay: calc(var(--i, 0) * 55ms); }
@keyframes dash-in { from { opacity: 0; transform: translateY(10px); } }
@media (prefers-reduced-motion: reduce) { .dash > *, .bar-fill, .rk-bar { animation: none; } }

/* Hero — the only dark surface on the page, so the money number owns the screen. */
.dash-hero {
  background:
    radial-gradient(120% 130% at 92% -10%, rgba(9, 105, 247, 0.34) 0%, rgba(9, 105, 247, 0) 58%),
    var(--ink);
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  padding: 22px 24px 10px;
  color: #fff;
  box-shadow: 0 24px 48px -28px rgba(10, 11, 13, 0.5);
  display: flex; flex-direction: column;
  overflow: hidden;
}
.dh-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.dh-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.12em; font-weight: 700; color: rgba(255, 255, 255, 0.5); }
.dh-value { font-size: 2.5rem; font-weight: 800; letter-spacing: -0.04em; line-height: 1.1; margin-top: 4px; font-variant-numeric: tabular-nums; }
.dh-value .cur { font-size: 0.95rem; font-weight: 600; color: rgba(255, 255, 255, 0.42); margin-left: 6px; letter-spacing: 0; }
.dh-sub { display: flex; align-items: center; gap: 9px; margin-top: 8px; font-size: 0.82rem; color: rgba(255, 255, 255, 0.55); }

.delta { display: inline-flex; align-items: center; gap: 3px; padding: 3px 8px; border-radius: 999px; font-size: 0.72rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.delta svg { width: 12px; height: 12px; }
.delta.up { background: rgba(26, 125, 60, 0.18); color: #4ade80; }
.delta.down { background: rgba(192, 52, 29, 0.2); color: #fb8a72; }
.delta.sm.up { background: var(--ok-bg); color: var(--ok); }
.delta.sm.down { background: var(--danger-bg); color: var(--danger); }

.dh-legend { display: flex; gap: 14px; flex-shrink: 0; }
.dh-legend .lg { display: inline-flex; align-items: center; gap: 6px; font-size: 0.72rem; font-weight: 600; color: rgba(255, 255, 255, 0.55); white-space: nowrap; }
.dh-legend .lg::before { content: ""; width: 10px; height: 3px; border-radius: 2px; background: var(--primary-lift); }
.dh-legend .lg-bar::before { width: 8px; height: 8px; border-radius: 2px; background: rgba(255, 255, 255, 0.28); }

.dh-chart { width: 100%; height: auto; margin-top: 14px; display: block; }
.dh-chart text { fill: rgba(255, 255, 255, 0.38); font-size: 11px; font-weight: 600; font-family: inherit; }
.dh-chart text.yr { fill: rgba(255, 255, 255, 0.7); }

/* ---- KPI stack ---- */

.dk { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px 18px; box-shadow: var(--shadow-sm); display: flex; flex-direction: column; justify-content: center; }
.dk-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.dk-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.1em; font-weight: 700; color: var(--muted); }
.dk-value { font-size: 1.85rem; font-weight: 800; letter-spacing: -0.035em; line-height: 1.15; margin-top: 6px; font-variant-numeric: tabular-nums; }
.dk-value.sm { font-size: 1.5rem; margin-top: 0; }
.dk-value .cur { font-size: 0.85rem; font-weight: 600; color: var(--faint); margin-left: 4px; letter-spacing: 0; }
.dk-foot { font-size: 0.76rem; color: var(--faint); margin-top: 4px; }
.dk-ring { display: flex; align-items: center; gap: 14px; margin-top: 8px; }
.dk-ring svg { width: 52px; height: 52px; flex-shrink: 0; }
.dk-ring > div { min-width: 0; }

/* ---- Panels ---- */

.panel { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 18px 20px 10px; box-shadow: var(--shadow-sm); }
.p-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 6px; }
.p-head h2 { margin: 0; }
.p-note { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; color: var(--faint); }
.panel .empty { padding: 30px 0; }

/* ---------- Titled table section (bare, no card) ----------
   For pages that list several tables straight on the page (see Eventos): each
   table gets a titled band with an icon chip — the same language as the
   mini-stats — and generous space between sections so they never crowd. */
.sec-stack { gap: 30px; }
.sec-head { display: flex; align-items: center; gap: 13px; margin: 0 0 15px; }
.sec-ic {
  width: 38px; height: 38px; border-radius: 11px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--primary-soft); color: var(--primary);
}
.sec-ic svg { width: 19px; height: 19px; }
.sec-title { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sec-title h2 { margin: 0; font-size: 1.1rem; line-height: 1.12; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.sec-sub { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.07em; font-weight: 700; color: var(--faint); }
.sec-aside { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.race-list, .feed, .rank { list-style: none; margin: 0; padding: 0; }
.race-list > li, .feed > li { border-top: 1px solid var(--line); }
.race-list > li:first-child, .feed > li:first-child { border-top: 0; }

.race { display: flex; align-items: center; gap: 14px; padding: 12px 8px; margin: 0 -8px; border-radius: var(--radius-sm); transition: background 0.14s; }
.race:hover { background: var(--panel-2); }
.race-date {
  width: 46px; flex-shrink: 0; text-align: center; padding: 6px 0;
  border-radius: 10px; background: var(--primary-soft); color: var(--primary-ink);
}
.race-date .dd { display: block; font-size: 1.1rem; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
.race-date .mm { display: block; font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; margin-top: 2px; opacity: 0.75; }
.race-main { flex: 1; min-width: 0; }
.race-name { display: block; font-weight: 700; font-size: 0.9rem; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.race-name .yr, .rk-name .yr { color: var(--faint); font-weight: 600; }
.race-meta { display: flex; align-items: center; gap: 8px; margin-top: 4px; font-size: 0.76rem; }
.race-num { text-align: right; flex-shrink: 0; }
.race-num .n { display: block; font-weight: 800; font-size: 0.95rem; font-variant-numeric: tabular-nums; }
.race-num .l { display: block; font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--faint); font-weight: 600; }

.bar { display: block; height: 4px; border-radius: 3px; background: var(--line); overflow: hidden; margin-top: 8px; }
/* Width comes from --w, set by initWidths in admin.js off the element's data-w. The 0% fallback is
   load-bearing: this used to have no width of its own and took it from a style attribute the CSP
   discards, so every capacity bar rendered full — an event with 7 of 15000 places sold drew as sold
   out. An empty bar under-reports, which is survivable; a full one lies. The real numbers are in
   the label on .bar either way. */
.bar-fill { display: block; width: var(--w, 0%); height: 100%; border-radius: 3px; background: var(--primary); animation: bar-grow 0.7s cubic-bezier(0.2, 0.9, 0.3, 1) both; }
.bar-fill.hot { background: var(--coral); }
@keyframes bar-grow { from { transform: scaleX(0); transform-origin: left; } }

.fd { display: flex; align-items: center; gap: 12px; padding: 11px 8px; margin: 0 -8px; border-radius: var(--radius-sm); transition: background 0.14s; }
.fd:hover { background: var(--panel-2); }
.fd-av {
  width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--primary-soft); color: var(--primary-ink);
  font-weight: 800; font-size: 0.72rem;
}
.fd-main { flex: 1; min-width: 0; }
.fd-name { display: block; font-weight: 700; font-size: 0.88rem; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fd-sub { display: block; font-size: 0.76rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; }
.fd-right { text-align: right; flex-shrink: 0; }
.fd-amt { display: block; font-weight: 700; font-size: 0.86rem; font-variant-numeric: tabular-nums; }
.fd-when { display: flex; align-items: center; justify-content: flex-end; gap: 7px; font-size: 0.7rem; color: var(--faint); margin-top: 3px; }

.rank > li {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 8px; margin: 0 -8px; border-top: 1px solid var(--line);
}
.rank > li:first-child { border-top: 0; }
.rk {
  width: 22px; height: 22px; border-radius: 7px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel-2); border: 1px solid var(--line);
  font-size: 0.7rem; font-weight: 800; color: var(--muted);
}
.rank > li:first-child .rk { background: var(--ink); border-color: var(--ink); color: #fff; }
.rk-main { flex: 1; min-width: 0; }
.rk-name { display: block; font-weight: 700; font-size: 0.86rem; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Width comes from --w on the <li> — the row's revenue as a share of the top row's, set by
   initWidths in admin.js and inherited down to here. */
.rk-bar { display: block; height: 5px; border-radius: 3px; margin-top: 6px; width: var(--w, 0%); min-width: 6px; background: var(--primary); opacity: 0.85; animation: bar-grow 0.7s cubic-bezier(0.2, 0.9, 0.3, 1) both; }
.rank.alt .rk-bar { background: var(--coral); }
.rk-num { text-align: right; flex-shrink: 0; }
.rk-num .n { display: block; font-weight: 800; font-size: 0.86rem; font-variant-numeric: tabular-nums; }
.rk-num .l { display: block; font-size: 0.68rem; color: var(--faint); font-weight: 600; }

.pill.warn { border-color: transparent; background: rgba(255, 92, 56, 0.12); color: #b5411f; }
.pill.off { border-color: transparent; background: rgba(10, 11, 13, 0.06); color: var(--muted); }

/* ---------- Empty dashboard ----------
   A ghost preview of the dashboard to come: three skeleton cards float in over a brand glow and a
   fading dot grid; the revenue line draws itself, the bars grow, the ring fills. Every colour is a
   theme token and every movement is CSS — the CSP forbids inline styles and external assets, and a
   GIF could follow neither the theme nor a reduced-motion request.

   Entrances animate opacity/scale and the idle drift animates `translate` (the individual property,
   not `transform`, which statically holds each card's tilt) so the three never fight. Every entrance
   is a `from`-only keyframe over the element's final resting style: kill the animations — as the
   reduced-motion block does — and the finished scene is what renders. */

.dash-empty { position: relative; overflow: hidden; text-align: center; padding: 54px 24px 58px; }
.dash-empty::before {
  content: ""; position: absolute; top: -90px; left: 50%; translate: -50% 0;
  width: 580px; height: 380px; pointer-events: none;
  background: radial-gradient(closest-side, var(--primary-glow), transparent 72%);
}
.dash-empty::after {
  content: ""; position: absolute; top: 0; left: 50%; translate: -50% 0;
  width: 640px; height: 300px; pointer-events: none; opacity: 0.6;
  background-image: radial-gradient(var(--line) 1.2px, transparent 1.2px);
  background-size: 20px 20px;
  -webkit-mask-image: radial-gradient(closest-side, #000 20%, transparent 75%);
  mask-image: radial-gradient(closest-side, #000 20%, transparent 75%);
}

.empty-scene { position: relative; z-index: 1; width: min(440px, 100%); height: 205px; margin: 0 auto; }
/* g-card, not .ghost: `.btn.ghost` already owns that name, and a bare `.ghost` here
   would land its absolute positioning and float animation on every ghost button. */
.g-card {
  position: absolute; text-align: left;
  background: var(--panel); border: 1px solid var(--line); border-radius: 16px;
  box-shadow: 0 24px 48px -28px rgba(10, 11, 13, 0.28);
  transform: rotate(var(--r, 0deg));
  animation: ghost-in 0.7s cubic-bezier(0.22, 0.9, 0.3, 1) backwards,
             ghost-float 6.5s ease-in-out infinite;
}
/* Negative float delays desync the drift, so the cards never bob in unison. */
.g-hero { --r: -3deg; left: 3%; top: 30px; width: 236px; padding: 14px; z-index: 2; animation-delay: 0.05s, -1.8s; }
.g-kpi  { --r: 2.5deg; right: 3%; top: 2px; width: 150px; padding: 14px; animation-delay: 0.22s, -3.6s; }
.g-donut { --r: -2deg; right: 11%; bottom: 0; width: 172px; padding: 12px 14px; display: flex; align-items: center; gap: 12px; z-index: 3; animation-delay: 0.4s, -5s; }

.g-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.g-dot { width: 10px; height: 10px; border-radius: 4px; background: var(--primary); opacity: 0.8; }
/* Skeleton text: the shimmer says "content loading", which is exactly the promise being made. */
.g-line {
  display: block; height: 8px; border-radius: 999px;
  background: linear-gradient(90deg, var(--line-soft) 25%, var(--line) 50%, var(--line-soft) 75%);
  background-size: 200% 100%;
  animation: g-shimmer 2.4s linear infinite;
}
.g-line.w40 { width: 40%; }
.g-line.w60 { width: 60%; }
.g-col { flex: 1; display: flex; flex-direction: column; gap: 9px; }

.g-chart { display: block; width: 100%; height: 64px; }
.g-area { fill: var(--primary); opacity: 0.07; animation: g-fade 0.9s 1s backwards; }
.g-spark {
  fill: none; stroke: var(--primary); stroke-width: 2.5;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 100 100; /* pathLength=100 in the markup, so these are percentages */
  animation: g-draw 1.5s cubic-bezier(0.4, 0, 0.2, 1) 0.55s backwards;
}

.g-bars { display: flex; align-items: flex-end; gap: 6px; height: 46px; margin-top: 12px; }
.g-bars span { flex: 1; border-radius: 5px 5px 2px 2px; background: var(--primary-soft); transform-origin: bottom; animation: g-grow 0.7s cubic-bezier(0.3, 1.35, 0.4, 1) backwards; }
.g-bars span:nth-child(1) { height: 42%; animation-delay: 0.5s; }
.g-bars span:nth-child(2) { height: 64%; animation-delay: 0.58s; }
.g-bars span:nth-child(3) { height: 46%; animation-delay: 0.66s; }
.g-bars span:nth-child(4) { height: 86%; background: var(--primary); animation-delay: 0.74s; }
.g-bars span:nth-child(5) { height: 60%; animation-delay: 0.82s; }

.g-ring { width: 52px; height: 52px; flex-shrink: 0; }
.g-ring circle { fill: none; stroke-width: 5; }
.g-ring-track { stroke: var(--line-soft); }
.g-ring-fill {
  stroke: var(--primary); stroke-linecap: round; stroke-dasharray: 68 32;
  transform: rotate(-90deg); transform-origin: center;
  animation: g-ring 1.4s cubic-bezier(0.4, 0, 0.2, 1) 0.7s backwards;
}

.empty-copy { position: relative; z-index: 1; margin-top: 28px; }
.empty-copy > * { animation: empty-rise 0.6s cubic-bezier(0.22, 0.9, 0.3, 1) backwards; }
.empty-copy > *:nth-child(1) { animation-delay: 0.25s; }
.empty-copy > *:nth-child(2) { animation-delay: 0.33s; }
.empty-copy > *:nth-child(3) { animation-delay: 0.41s; }
.empty-copy > *:nth-child(4) { animation-delay: 0.5s; }

.empty-kicker {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 13px; border-radius: 999px;
  background: var(--primary-soft); color: var(--primary-ink);
  font-size: 0.68rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.12em;
}
.k-pulse { width: 7px; height: 7px; border-radius: 50%; background: var(--primary); animation: k-pulse 2.2s ease-out infinite; }

.dash-empty h2 { margin: 16px auto 8px; font-size: 1.42rem; letter-spacing: -0.015em; max-width: 30ch; }
.dash-empty p { max-width: 46ch; margin: 0 auto; color: var(--muted); line-height: 1.6; }
.empty-cta { margin-top: 24px; }

@keyframes ghost-in { from { opacity: 0; scale: 0.9; } }
@keyframes ghost-float { 50% { translate: 0 -7px; } }
@keyframes g-shimmer { to { background-position: -200% 0; } }
@keyframes g-draw { from { stroke-dashoffset: 100; } }
@keyframes g-fade { from { opacity: 0; } }
@keyframes g-grow { from { scale: 1 0; } }
@keyframes g-ring { from { stroke-dasharray: 0 100; } }
@keyframes empty-rise { from { opacity: 0; translate: 0 12px; } }
@keyframes k-pulse { from { box-shadow: 0 0 0 0 var(--primary-glow); } to { box-shadow: 0 0 0 9px transparent; } }

/* Less motion: the same scene, finished and still. */
@media (prefers-reduced-motion: reduce) {
  .dash-empty *, .dash-empty::before, .dash-empty::after { animation: none !important; }
}

/* ---------- Platform dashboard (administrator, unscoped) ---------- */

/* The activity feed owns the full width under the hero/KPI row. */
.pf-activity { grid-column: 1 / -1; }

.act-feed { list-style: none; margin: 6px 0 8px; padding: 0; display: flex; flex-direction: column; }
.act-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 2px; border-top: 1px solid var(--line-soft);
  animation: dash-in 0.4s cubic-bezier(0.22, 0.9, 0.3, 1) both;
  animation-delay: calc(var(--i, 0) * 40ms);
}
.act-row:first-child { border-top: 0; }
@media (prefers-reduced-motion: reduce) { .act-row { animation: none; } }

.act-mark {
  width: 34px; height: 34px; flex-shrink: 0; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--primary) 0%, var(--primary-lift) 100%);
  color: #fff; font-weight: 800; font-size: 0.85rem;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28);
}

.act-body { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
.act-line { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.act-who {
  font-weight: 700; color: var(--side-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.act-client {
  flex-shrink: 0; font-size: 0.68rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted);
}
.act-ctx {
  font-size: 0.8rem; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.act-side { flex-shrink: 0; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.act-amount { font-weight: 800; letter-spacing: -0.01em; color: var(--side-strong); font-variant-numeric: tabular-nums; }
.act-amount .cur { font-size: 0.68rem; font-weight: 700; color: var(--faint); margin-left: 4px; }
.act-tail { display: flex; align-items: center; gap: 8px; }
.act-tail .pill { padding: 2px 9px; font-size: 0.62rem; }
.act-tail time { font-size: 0.74rem; color: var(--faint); white-space: nowrap; }

@media (max-width: 560px) { .act-ctx { white-space: normal; } }

/* Empty feed — the state HMS Sports is in until the first registration lands. */
.act-empty {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  padding: 36px 24px 40px; text-align: center;
}
.act-empty-ic {
  width: 46px; height: 46px; border-radius: 13px;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel-2); border: 1px solid var(--line); color: var(--faint); font-size: 22px;
}
.act-empty p { margin: 0; max-width: 380px; color: var(--muted); font-size: 0.9rem; }

/* Empty platform: no clients yet. Reuses the empty-copy voice from the org dashboard. */
.pf-none { padding: 44px 28px; }
.pf-none .empty-copy { max-width: 520px; margin: 0 auto; text-align: center; }

/* ---------- Sidebar scope selector ---------- */

/* Inside a client the selector stops being neutral: a primary tint says "you are here". */
.side-org.scoped select { border-color: var(--primary-glow); background: var(--primary-soft); color: var(--primary-ink); }
.side-org.scoped .side-org-pick > i:first-child { opacity: 1; }

/* ---------- Profile ("A minha conta") ---------- */
.profile { display: flex; flex-direction: column; gap: 18px; max-width: 640px; }
.profile .card > h2 { margin: 0 0 4px; font-size: 1.02rem; }
.profile .card > h2 > span { display: inline-flex; align-items: center; gap: 9px; }
.profile .card > h2 i { color: var(--muted); font-size: 19px; }
.profile .form { margin-top: 14px; }
.profile .form .btn { align-self: flex-start; }
/* Prose under a card heading — a description, not the tiny .p-note label. */
.card-note { margin: 6px 0 0; color: var(--muted); font-size: 0.86rem; line-height: 1.55; }
/* A rejected password post gently pulls the eye to the right card. */
.card.flash { animation: card-flash 1.6s ease; }
@keyframes card-flash {
  0%, 100% { box-shadow: var(--shadow-sm); }
  20% { box-shadow: 0 0 0 3px var(--primary-soft), var(--shadow-md); }
}

/* Passkey list */
.pk-empty { margin: 14px 0 0; color: var(--muted); font-size: 0.9rem; }
.pk-list { list-style: none; margin: 14px 0 0; padding: 0; }
.pk-row { display: flex; align-items: center; gap: 13px; padding: 12px 0; border-top: 1px solid var(--line); }
.pk-row:first-child { border-top: 0; }
.pk-ico { flex-shrink: 0; width: 38px; height: 38px; border-radius: 10px; display: inline-flex; align-items: center; justify-content: center; background: var(--primary-soft); color: var(--primary); }
.pk-ico i { font-size: 20px; }
.pk-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.pk-name { font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: flex; align-items: center; gap: 8px; }
.pk-sub { font-size: 0.78rem; color: var(--muted); }

/* Sessions: the current device sits above the paged list of the others. */
.pk-subhead { margin: 20px 0 0; font-size: 0.8rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--faint); }
.pk-row.current .pk-ico { background: var(--ok-bg); color: var(--ok); }

/* Server-side pager (Anterior / Página X de Y / Próxima). */
.pager { display: flex; align-items: center; justify-content: center; gap: 16px; margin: 16px 0 0; padding-top: 14px; border-top: 1px solid var(--line); }
.pager-link { display: inline-flex; align-items: center; gap: 5px; font-size: 0.82rem; font-weight: 600; color: var(--primary); text-decoration: none; padding: 6px 10px; border-radius: 8px; }
.pager-link:hover { background: var(--primary-soft); }
.pager-link i { font-size: 16px; }
.pager-info { font-size: 0.8rem; color: var(--muted); font-variant-numeric: tabular-nums; }

/* .alert/.notice set display:flex, which (author origin) overrides the browser's [hidden]
   display:none — so a hidden alert would still show as an empty box. Restore the hide. */
.notice[hidden], .alert[hidden] { display: none; }

/* ---------- Login: passkey alternative ---------- */
.auth-alt { margin-top: 24px; }
.auth-or { display: flex; align-items: center; gap: 12px; margin: 4px 0 16px; color: var(--faint); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; }
.auth-or::before, .auth-or::after { content: ""; flex: 1; height: 1px; background: var(--line-strong); }
.btn-passkey i { font-size: 20px; }
/* The shared .btn-spinner is white for the primary CTA; on a light ghost/passkey button that is
   invisible, so give it a dark track there. */
.btn.ghost .btn-spinner { border-color: rgba(10, 11, 13, 0.2); border-top-color: var(--text); }

/* ---------- Dashboard: passkey suggestion banner ---------- */
.pk-suggest { display: flex; align-items: center; gap: 16px; padding: 15px 18px; margin: 0 0 22px; border: 1px solid rgba(9, 105, 247, 0.22); background: var(--primary-soft); border-radius: var(--radius); }
.pk-suggest-ico { flex-shrink: 0; width: 42px; height: 42px; border-radius: 11px; display: inline-flex; align-items: center; justify-content: center; background: #fff; color: var(--primary); }
.pk-suggest-ico i { font-size: 22px; }
.pk-suggest-body { flex: 1; min-width: 0; }
.pk-suggest-txt { display: flex; flex-direction: column; gap: 2px; }
.pk-suggest-txt strong { color: var(--text); font-size: 0.95rem; }
.pk-suggest-txt span { color: var(--muted); font-size: 0.85rem; line-height: 1.45; }
.pk-suggest-body .alert { margin: 10px 0 0; }
/* stretch, not center: the primary button is taller (its icon is 18px), so let "Agora não" match it. */
.pk-suggest-actions { flex-shrink: 0; display: flex; gap: 8px; align-items: stretch; }
@media (max-width: 640px) {
  .pk-suggest { flex-wrap: wrap; }
  .pk-suggest-actions { width: 100%; }
  .pk-suggest-actions .btn { flex: 1; justify-content: center; }
}

/* ---- Gestão de Acessos -------------------------------------------------
   The security desk gets a look of its own: monospace IP chips, a slow pulse
   on anything currently blocking, and a scanline sweep across the stat cards.
   Everything stays inside the existing token palette. */

.access-stats .stat { position: relative; overflow: hidden; }
.access-stats .stat::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 40%, rgba(9, 105, 247, 0.06) 50%, transparent 60%);
  background-size: 250% 100%;
  animation: access-scan 6s linear infinite;
  pointer-events: none;
}
@keyframes access-scan {
  from { background-position: 125% 0; }
  to { background-position: -125% 0; }
}

.access-card { margin-top: 18px; }
.access-card + .access-card { margin-top: 22px; }

.access-sub {
  display: flex; align-items: center; gap: 8px;
  margin: 22px 0 10px; font-size: 0.92rem; letter-spacing: 0.01em;
}
.access-sub i { color: var(--muted); font-size: 18px; }

/* ---------- Blocked (403) — served by IpBlockMiddleware from /blocked.html ----------
   A dead end, so it carries no navigation: whoever lands here has nothing to click. The page
   is plain HTML with no layout behind it, which is why it restates the shell rather than
   leaning on .card. Inline styles are not an option — the CSP is style-src 'self'. */
.blocked {
  min-height: 100vh;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.blocked-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: 40px 36px;
  max-width: 460px; width: 100%;
  text-align: center;
}
.blocked-logo { height: 26px; width: auto; margin-bottom: 28px; }
.blocked-badge {
  width: 62px; height: 62px; margin: 0 auto 20px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--danger-bg);
  color: var(--danger);
}
.blocked-badge i.ti { font-size: 30px; }
.blocked-title { margin: 0 0 12px; font-size: 1.4rem; letter-spacing: -0.01em; }
.blocked-text { margin: 0; color: var(--muted); line-height: 1.6; }
.blocked-text-soft { margin-top: 12px; color: var(--faint); font-size: 0.88rem; }

/* An IP is read digit by digit — the same fixed-width treatment the .ip-chip rows get. */
.access-ip-input {
  font-family: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: 0.03em;
}

/* IPs read best as fixed-width chips — they line up and scan vertically. */
.ip-chip {
  display: inline-flex; align-items: center;
  padding: 3px 9px; border-radius: 7px;
  font-family: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.02em;
  background: var(--panel-2); border: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
}
.ip-chip.auto { border-left: 3px solid var(--coral); }
.ip-chip.manual { border-left: 3px solid var(--primary); }

.badge.danger { background: var(--danger-bg); color: var(--danger); }

/* A block in effect breathes slowly — alive, not alarming. */
.badge.pulse i { animation: access-pulse 2.4s ease-in-out infinite; }
@keyframes access-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}
@media (prefers-reduced-motion: reduce) {
  .badge.pulse i, .access-stats .stat::after { animation: none; }
}

/* Rows that are blocking right now get a live left edge the history rows lack. */
tr.access-live > td:first-child { box-shadow: inset 3px 0 0 var(--danger); }

.access-when { white-space: nowrap; color: var(--muted); font-variant-numeric: tabular-nums; }
.access-reason { color: var(--muted); max-width: 260px; }
.access-user { overflow-wrap: anywhere; }

.access-account { display: flex; flex-direction: column; gap: 2px; }
.access-account-name { font-weight: 600; }
.access-account-mail { font-size: 0.8rem; color: var(--muted); }

/* ---------- Color picker ----------
   Built by initColorFields in admin.js, which hides the native <input type="color"> and puts this
   in front of it. The input keeps the value; everything here is the part you can see.

   Every actual color is set from JS through the CSSOM — style-src is 'self' with no
   'unsafe-inline', so nothing below can carry a color of its own. What lives here is the shape. */

.cp-field { position: relative; display: inline-flex; }
.cp-field .cp-native { display: none; }

/* The label used to sit inline beside a 68px native swatch and just about got away with it. The
   trigger is wider and carries the hex, so the two stack now — like every other field on the form.
   Scoped to labels that actually precede a picker; nothing else on the page moves. */
label:has(+ .cp-field) { display: block; margin-bottom: 5px; }

/* Reads as one of the form's own inputs, because that is what it replaced. */
.cp-trigger {
  display: inline-flex; align-items: center; gap: 9px;
  height: 42px; padding: 0 13px 0 7px;
  background: var(--panel-2); border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  color: var(--text); font-family: inherit; font-size: 0.9rem; cursor: pointer;
  transition: border-color 0.14s, box-shadow 0.14s, background 0.14s;
}
.cp-trigger:hover { background: var(--panel); border-color: var(--faint); }
.cp-trigger:focus-visible { outline: none; border-color: var(--primary-ink); box-shadow: 0 0 0 3px var(--primary-glow); }

/* The inner shadow keeps a white or near-white brand color from vanishing into the button. */
.cp-chip {
  width: 28px; height: 28px; border-radius: 7px; flex-shrink: 0;
  box-shadow: inset 0 0 0 1px rgba(10, 11, 13, 0.14);
}
.cp-code { font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }

/* ---- the panel ---- */

/* [popover] arrives with UA styles — a border, padding and auto margins that centre it. All of
   them go; the anchoring below puts it where it belongs. */
.cp-pop {
  width: 254px; padding: 12px; border: 1px solid var(--line);
  background: var(--panel); border-radius: var(--radius); box-shadow: var(--shadow-md);
  color: var(--text); overflow: visible;
}
.cp-pop:focus-visible { outline: none; }

/* Anchored where the browser can do it, and centred in the top layer where it cannot — which is
   the UA default, so the fallback costs nothing and is still perfectly usable. */
@supports (position-area: block-end) {
  .cp-pop {
    inset: auto; margin: 0; margin-block-start: 8px;
    position-area: block-end span-inline-end;
    position-try-fallbacks: flip-block, flip-inline;
  }
}

.cp-pop {
  opacity: 0; transform: scale(0.97); transform-origin: top left;
  transition: opacity 0.14s ease, transform 0.14s ease,
              overlay 0.14s allow-discrete, display 0.14s allow-discrete;
}
.cp-pop:popover-open { opacity: 1; transform: scale(1); }
@starting-style { .cp-pop:popover-open { opacity: 0; transform: scale(0.97); } }

@media (prefers-reduced-motion: reduce) {
  .cp-pop { transition: overlay 0s allow-discrete, display 0s allow-discrete; transform: none; }
  .cp-pop:popover-open { transform: none; }
}

/* ---- saturation / brightness ----
   Two gradients over the flat hue: white left-to-right, black bottom-to-top. No canvas — this
   stays sharp at any size and paints nothing. */
.cp-sv {
  position: relative; height: 132px; border-radius: var(--radius-sm); cursor: crosshair;
  background:
    linear-gradient(to top, #000, rgba(0, 0, 0, 0)),
    linear-gradient(to right, #fff, rgba(255, 255, 255, 0)),
    var(--cp-hue, #f00);
  box-shadow: inset 0 0 0 1px rgba(10, 11, 13, 0.12);
  touch-action: none; /* the drag is ours; the page must not scroll out from under it */
}
.cp-sv:focus-visible { outline: none; box-shadow: inset 0 0 0 1px rgba(10, 11, 13, 0.12), 0 0 0 3px var(--primary-glow); }

.cp-dot {
  position: absolute; width: 16px; height: 16px; border-radius: 50%;
  transform: translate(-50%, -50%); pointer-events: none;
  box-shadow: inset 0 0 0 2px #fff, 0 0 0 1px rgba(10, 11, 13, 0.35), 0 1px 3px rgba(0, 0, 0, 0.3);
}

/* ---- hue + eyedropper ---- */

.cp-bar { display: flex; align-items: center; gap: 9px; margin-top: 11px; }

.cp-hue {
  flex: 1; height: 14px; margin: 0; padding: 0;
  -webkit-appearance: none; appearance: none; background: transparent; outline: none; cursor: pointer;
}
.cp-hue::-webkit-slider-runnable-track {
  height: 14px; border-radius: 999px;
  background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
  box-shadow: inset 0 0 0 1px rgba(10, 11, 13, 0.12);
}
.cp-hue::-moz-range-track {
  height: 14px; border-radius: 999px;
  background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
  box-shadow: inset 0 0 0 1px rgba(10, 11, 13, 0.12);
}
/* Hollow, so the track colour it is sitting on reads straight through it. */
.cp-hue::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 16px; height: 16px; margin-top: -1px; border-radius: 50%; background: transparent;
  box-shadow: inset 0 0 0 3px #fff, 0 0 0 1px rgba(10, 11, 13, 0.4);
}
.cp-hue::-moz-range-thumb {
  width: 16px; height: 16px; border: none; border-radius: 50%; background: transparent;
  box-shadow: inset 0 0 0 3px #fff, 0 0 0 1px rgba(10, 11, 13, 0.4);
}
.cp-hue:focus-visible::-webkit-slider-thumb { box-shadow: inset 0 0 0 3px #fff, 0 0 0 1px rgba(10, 11, 13, 0.4), 0 0 0 4px var(--primary-glow); }
.cp-hue:focus-visible::-moz-range-thumb { box-shadow: inset 0 0 0 3px #fff, 0 0 0 1px rgba(10, 11, 13, 0.4), 0 0 0 4px var(--primary-glow); }

.cp-eye {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; flex-shrink: 0; padding: 0;
  background: var(--panel-2); border: 1px solid var(--line-strong); border-radius: 9px;
  color: var(--muted); cursor: pointer;
  transition: color 0.14s, background 0.14s, border-color 0.14s;
}
.cp-eye i { font-size: 17px; }
.cp-eye:hover { color: var(--primary-ink); background: var(--primary-soft); border-color: var(--primary); }
.cp-eye:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-glow); }

/* ---- hex ---- */

.cp-pop .cp-hex {
  width: 100%; margin-top: 10px; height: 36px; padding: 0 11px;
  background: var(--panel-2); border: 1px solid var(--line-strong); border-radius: 9px;
  color: var(--text); font-family: inherit; font-size: 0.88rem;
  font-variant-numeric: tabular-nums; letter-spacing: 0.02em; text-transform: lowercase;
  outline: none; transition: border-color 0.14s, box-shadow 0.14s;
}
.cp-pop .cp-hex:focus { border-color: var(--primary-ink); box-shadow: 0 0 0 3px var(--primary-glow); background: var(--panel); }
/* Only while it cannot be read as a color — never on an empty box, and never mid-word. */
.cp-pop .cp-hex.bad { border-color: var(--danger); box-shadow: 0 0 0 3px var(--danger-bg); }

/* ---- swatches ---- */

.cp-swatch-label { margin: 12px 0 6px; font-size: 0.68rem; font-weight: 700; color: var(--faint); text-transform: uppercase; letter-spacing: 0.06em; }
.cp-swatch-row { display: grid; grid-template-columns: repeat(10, 1fr); gap: 4px; }
.cp-swatch {
  aspect-ratio: 1; padding: 0; border: none; border-radius: 5px; cursor: pointer;
  box-shadow: inset 0 0 0 1px rgba(10, 11, 13, 0.14);
  transition: transform 0.12s ease;
}
.cp-swatch:hover { transform: scale(1.18); }
.cp-swatch:focus-visible { outline: none; box-shadow: inset 0 0 0 1px rgba(10, 11, 13, 0.14), 0 0 0 3px var(--primary-glow); }

@media (max-width: 420px) {
  .cp-pop { width: min(254px, calc(100vw - 32px)); }
}

/* Form-builder drag-and-drop: a grip handle per row, a lifted look while dragging. */
.drag-cell { width: 1.6rem; padding-right: 0; }
.drag-grip {
  display: inline-block; cursor: grab; color: var(--faint);
  line-height: 1; letter-spacing: -1px; user-select: none;
}
.drag-grip:active { cursor: grabbing; }
.grid.mini tr[data-field-key] { transition: background 0.12s ease; }
.grid.mini tr[data-field-key].dragging { opacity: 0.55; background: var(--panel); }
.grid.mini tbody[data-reorder] tr[data-field-key]:hover .drag-grip { color: var(--muted); }

/* ---------------------------------------------------------------------------
   Adicionar passo: botão tracejado + seletor de posição por slots na modal
   --------------------------------------------------------------------------- */
.add-step-open {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 1rem;
  border: 1.5px dashed var(--line-strong);
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.add-step-open:hover {
  border-color: var(--primary);
  color: var(--primary-ink);
  background: var(--primary-soft);
}
.add-step-open .ti { font-size: 1.1rem; }

.step-slots {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 0.35rem;
  padding: 0.85rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}
.step-chip {
  display: inline-flex;
  align-items: center;
  padding: 0.5rem 0.85rem;
  border-radius: 999px;
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--text);
  font-weight: 600;
  white-space: nowrap;
}
.step-slot {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 0 0.15rem;
  cursor: pointer;
}
.step-slot input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.step-slot-line {
  display: block;
  width: 4px;
  align-self: stretch;
  min-height: 2.4rem;
  border-radius: 999px;
  background: var(--line-strong);
  transition: background 0.15s, box-shadow 0.15s, transform 0.15s;
}
.step-slot:hover .step-slot-line { background: var(--primary-lift); }
.step-slot input:checked ~ .step-slot-line {
  background: var(--primary);
  box-shadow: 0 0 0 4px var(--primary-glow);
  transform: scaleX(1.35);
}
.step-slot input:focus-visible ~ .step-slot-line {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
}
.step-slot-tip {
  position: absolute;
  bottom: calc(100% + 0.35rem);
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  font-size: 0.75rem;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.15rem 0.45rem;
  box-shadow: var(--shadow-md);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s;
  z-index: 1;
}
.step-slot:hover .step-slot-tip,
.step-slot input:checked ~ .step-slot-tip { opacity: 1; }

/* Adicionar campo: segmentos de modo (predefinido/personalizado) + painéis. */
.field-modes {
  display: inline-flex; gap: 4px; padding: 4px; margin-bottom: 16px;
  border-radius: 999px; background: var(--panel-2); border: 1px solid var(--line);
}
.field-mode { position: relative; }
.field-mode input { position: absolute; opacity: 0; width: 0; height: 0; }
.field-mode span {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: 999px;
  font-size: 0.85rem; font-weight: 600; color: var(--muted); cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.field-mode input:checked + span { background: var(--panel); color: var(--ink); box-shadow: var(--shadow-sm); }
.field-mode input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: 2px; }
.add-field-body:has(input[value="custom"]:checked) .mp-lib { display: none; }
.add-field-body:not(:has(input[value="custom"]:checked)) .mp-custom { display: none; }
/* O botão de submeter não pode colar ao fundo da modal. */
.add-field-body { padding-bottom: 22px; }

/* Formulário do campo personalizado — grelha limpa. */
.af-form { display: flex; flex-direction: column; gap: 14px; }
.af-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.af-field { display: flex; flex-direction: column; gap: 6px; margin: 0; min-width: 0; }
.af-field > span { font-size: 0.78rem; font-weight: 600; color: var(--muted); }
.af-field[hidden] { display: none; }
.af-form input, .af-form select, .af-form textarea {
  width: 100%; padding: 9px 11px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--panel); color: var(--text); font: inherit; font-size: 0.9rem;
}
.af-form textarea { resize: vertical; min-height: 68px; }
.af-form input:focus, .af-form select:focus, .af-form textarea:focus {
  outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft);
}
.af-form .btn { align-self: flex-start; margin-top: 2px; }
@media (max-width: 560px) { .af-grid { grid-template-columns: 1fr; } }

/* Checkbox moderna (substitui a do browser) — usada nas modais de campo. */
.af-check { display: flex; align-items: center; gap: 10px; margin: 0; font-size: 0.9rem; color: var(--text); cursor: pointer; }
.add-field-body input[type="checkbox"] {
  appearance: none; -webkit-appearance: none; margin: 0;
  width: 20px; height: 20px; flex-shrink: 0; border: 1.5px solid var(--line-strong);
  border-radius: 6px; background: var(--panel); cursor: pointer; position: relative;
  transition: background 0.15s, border-color 0.15s;
}
.add-field-body input[type="checkbox"]:hover { border-color: var(--muted); }
.add-field-body input[type="checkbox"]:checked { background: var(--primary); border-color: var(--primary); }
.add-field-body input[type="checkbox"]:checked::after {
  content: ""; position: absolute; left: 6px; top: 2px; width: 5px; height: 10px;
  border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.add-field-body input[type="checkbox"]:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-glow); }

/* Ações no cabeçalho de um card de passo (editar / apagar). */
.card > h2 .card-actions { display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0; }
.card > h2 .card-actions form { margin: 0; }
.card > h2 .card-actions .x { display: inline-flex; align-items: center; justify-content: center; }

/* Reordenar passos: botão + lista arrastável dentro do sheet. */
.reorder-steps-open { justify-self: start; }
.reorder-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.reorder-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  transition: background 0.12s, box-shadow 0.12s, opacity 0.12s;
}
.reorder-row .drag-grip { cursor: grab; color: var(--faint); line-height: 1; letter-spacing: -1px; user-select: none; }
.reorder-row:hover .drag-grip { color: var(--muted); }
.reorder-row .drag-grip:active { cursor: grabbing; }
.reorder-title { font-weight: 600; }
.reorder-row .muted { margin-left: auto; font-size: 0.8rem; }
.reorder-row.dragging { opacity: 0.55; box-shadow: var(--shadow-md); }
.reorder-row.is-locked { background: var(--panel-2); border-style: dashed; cursor: not-allowed; }
.reorder-lock { color: var(--faint); display: inline-flex; }
.reorder-row.is-extras { border-color: var(--primary-soft); background: var(--primary-soft); }
.reorder-row.is-extras .reorder-title { display: inline-flex; align-items: center; gap: 6px; color: var(--primary-ink); }

/* Extras: interruptor de visibilidade + linha esbatida quando escondido. */
.toggle-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: 999px;
  border: 1px solid var(--line-strong); background: var(--panel-2);
  color: var(--muted); font: inherit; font-size: 0.78rem; font-weight: 600; cursor: pointer;
  transition: background 0.14s, color 0.14s, border-color 0.14s;
}
.toggle-pill:hover { border-color: var(--muted); }
.toggle-pill.on { background: var(--ok-bg); color: var(--ok); border-color: transparent; }
tr.is-off { opacity: 0.55; }
tr.is-off .strong { text-decoration: line-through; text-decoration-color: var(--faint); }

/* Toasts: cartões no canto inferior direito, entram e auto-desaparecem. */
.toast-wrap {
  position: fixed; right: 20px; bottom: 20px; z-index: 60;
  display: flex; flex-direction: column; gap: 10px; max-width: min(92vw, 380px);
}
.toast {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px; border-radius: var(--radius-sm);
  background: var(--panel); border: 1px solid var(--line); box-shadow: var(--shadow-md);
  transform: translateY(12px); opacity: 0;
  transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.28s;
}
.toast.in { transform: none; opacity: 1; }
.toast.leaving { transform: translateY(8px); opacity: 0; }
.toast > i { font-size: 1.1rem; line-height: 1.3; flex-shrink: 0; }
.toast.ok > i { color: var(--ok); }
.toast.err > i { color: var(--danger); }
.toast.ok { border-left: 3px solid var(--ok); }
.toast.err { border-left: 3px solid var(--danger); }
.toast span { flex: 1; min-width: 0; font-size: 0.88rem; line-height: 1.4; }
.toast-x {
  flex-shrink: 0; display: inline-flex; padding: 2px; margin: -2px -2px 0 0;
  border: 0; background: none; color: var(--faint); cursor: pointer; border-radius: 6px;
}
.toast-x:hover { color: var(--text); background: var(--line-soft); }
@media (prefers-reduced-motion: reduce) {
  .toast { transition: none; transform: none; opacity: 1; }
}
