/* ═══════════════════════════════════════════════════════════════
   Postura Staff Portal — shared foundations
   Tokens, reset and components used by both the desktop and the
   mobile stylesheets. Layout lives in desktop.css / mobile.css.
   ═══════════════════════════════════════════════════════════════ */

:root {
  color-scheme: only light;
  /* ── Monochrome + mint ───────────────────────────────────────
     White base, black type, mint as the one highlight.

     Mint sits at ~1.3:1 against white, so it is a FILL colour only —
     surfaces, plates, pills. Anything that has to be read (text, icon
     strokes, focus rings) uses --ink or --focus instead. Postura's deep
     green #0E5C43 is kept only for semantic "ok", not as the accent.
     ──────────────────────────────────────────────────────────── */
  --brand-ink: #000000;
  --brand-ink-rgb: 0 0 0;
  --brand-mint: #c2efc7;
  --brand-mint-deep: #a9e6b0;
  --brand-wash-1: #d1f3d5;
  --brand-wash-2: #ddf6e0;
  --brand-wash-3: #eaf9eb;
  --brand-wash-4: #f4fcf5;

  /* The highlight. Admin-editable; --on-accent is computed in JS from its
     luminance, so a dark custom accent flips the label to white by itself. */
  --accent-user: #c2efc7;
  --accent: var(--accent-user);
  --accent-dark: var(--brand-mint-deep);
  --on-accent: #000000;
  --focus: #000000;

  --bg: #ffffff;
  --surface: #ffffff;
  --surface-2: #f7faf7;
  --line: rgb(0 0 0 / 0.14);
  --line-strong: rgb(0 0 0 / 0.26);

  --ink: #000000;
  --ink-2: #3d3d3d;
  --ink-3: #5e5e5e;

  --danger: #a3271a;
  --warn: #7a5200;
  --ok: #0e5c43;

  --radius-sm: 12px;
  --radius: 18px;
  --radius-lg: 26px;
  --pill: 999px;

  --shadow-1: 0 2px 6px rgb(0 0 0 / 0.06), 0 1px 2px rgb(0 0 0 / 0.04);
  --shadow-2: 0 14px 32px rgb(0 0 0 / 0.10), 0 2px 6px rgb(0 0 0 / 0.06);

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;

  --font: "Poppins", "Avenir Next", system-ui, -apple-system, "Segoe UI",
          Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-serif: "Newsreader", Georgia, "Times New Roman", serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

*, *::before, *::after { box-sizing: border-box; }

/* Several components set `display` in a class rule, which outranks the UA's
   `[hidden] { display: none }`. That left the mobile presence sheet visible
   over the bottom of every screen, swallowing taps on the footer and on the
   bottom of forms. One rule closes the whole class of bug. */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* min-height, not height: a fixed 100% makes the viewport the box and clips
   anything taller — it was cutting the bottom off the mobile footer instead of
   letting the page grow and scroll. */
html, body { min-height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

body.is-locked { overflow: hidden; }

h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -0.011em; }
p { margin: 0; }
a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 4px;
}

.muted { color: var(--ink-3); font-size: 13px; }

/* ── Splash / fatal ──────────────────────────────────────────── */
.boot-splash {
  min-height: 100dvh;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--space-4);
  color: var(--ink-3);
}
.boot-splash__mark {
  width: 2.75rem;
  animation: pulse 1.6s ease-in-out infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }

.fatal {
  margin: var(--space-6) auto;
  max-width: 520px;
  padding: var(--space-4);
  border: 1px solid var(--line);
  border-left: 3px solid var(--danger);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink-2);
}

/* ── Buttons ─────────────────────────────────────────────────── */
.btn {
  position: relative;
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 2.5rem;
  padding: 0 var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.14s ease, border-color 0.14s ease, opacity 0.14s ease;
}
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn--primary { background: var(--accent); color: var(--on-accent); }
.btn--primary:hover:not(:disabled) { filter: brightness(1.07); }

.btn--ghost { border-color: var(--line-strong); background: transparent; }
.btn--ghost:hover { background: var(--surface-2); }

.btn--quiet { background: transparent; color: var(--ink-2); }
.btn--quiet:hover { background: var(--surface-2); color: var(--ink); }

.btn--danger { background: transparent; color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, transparent); }
.btn--danger:hover { background: color-mix(in srgb, var(--danger) 10%, transparent); }

.btn--block { width: 100%; }
.btn--sm { min-height: 32px; padding: 0 var(--space-3); font-size: 13px; }

.icon-btn {
  position: relative;
  appearance: none;
  display: grid;
  place-content: center;
  width: 2rem; height: 2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink-2);
  font: inherit;
  cursor: pointer;
}
.icon-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--ink); }
.icon-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.icon-btn--danger:hover { color: var(--danger); border-color: var(--danger); }

/* ── Fields ──────────────────────────────────────────────────── */
.field { display: grid; gap: var(--space-2); margin-bottom: var(--space-4); }

.field label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-2);
}

.field input[type="text"],
.field input[type="password"],
.field input[type="url"],
.field input:not([type]),
.field input[type="email"] {
  width: 100%;
  min-height: 40px;
  padding: 0 var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  transition: border-color 0.14s ease, box-shadow 0.14s ease;
}
.field input:focus {
  outline: none;
  border-color: var(--focus);
  box-shadow: 0 0 0 3px var(--accent);
}
.field input[type="color"] {
  width: 46px; height: 34px;
  padding: 2px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  cursor: pointer;
}

.field-hint { font-size: 12px; color: var(--ink-3); }

.field input.is-invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 18%, transparent);
}

.field select {
  width: 100%;
  min-height: 2.75rem;
  padding: 0 var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
}
.field-error {
  margin-bottom: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  color: var(--danger);
  font-size: 13px;
}

.colour-row { display: flex; align-items: center; gap: var(--space-3); }
.colour-row code { font-family: var(--mono); font-size: 12px; color: var(--ink-3); }

/* ── Switch ──────────────────────────────────────────────────── */
/* Expand the hit area of small controls to the 48px guideline without
   inflating what is drawn. */
.icon-btn::after,
.icon-picker__opt::after,
.switch::after {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: max(100%, 48px);
  height: max(100%, 48px);
}

.switch { position: relative; display: inline-flex; align-items: center; cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch__track {
  position: relative;
  width: 38px; height: 22px;
  border-radius: 999px;
  background: var(--line-strong);
  transition: background 0.16s ease;
}
.switch__track::after {
  content: "";
  position: absolute;
  top: 3px; left: 3px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.16s ease;
}
.switch input:checked + .switch__track { background: var(--accent); }
.switch input:checked + .switch__track::after { transform: translateX(16px); }
.switch input:focus-visible + .switch__track { outline: 2px solid var(--accent); outline-offset: 2px; }

.switch-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.75rem;
  font-size: 0.875rem;
  cursor: pointer;
}
.switch-row input[type="checkbox"] {
  width: 1.5rem; height: 1.5rem;
  flex: none;
  margin: 0;
  accent-color: var(--accent);
}

/* ── Icon picker ─────────────────────────────────────────────── */
.icon-picker { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.icon-picker__opt {
  position: relative;
  appearance: none;
  display: grid;
  place-content: center;
  width: 2.25rem; height: 2.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink-3);
  cursor: pointer;
}
.icon-picker__opt:hover { color: var(--ink); border-color: var(--line-strong); }
.icon-picker__opt.is-active {
  color: var(--on-accent);
  border-color: var(--line-strong);
  background: var(--accent);
}

/* ── Presence ────────────────────────────────────────────────── */
.presence-stack { display: flex; align-items: center; }
.presence-stack .avatar + .avatar { margin-left: -8px; }
.presence-empty { font-size: 12px; color: var(--ink-3); }

.avatar {
  display: grid;
  place-content: center;
  width: 28px; height: 28px;
  border-radius: 50%;
  border: 2px solid var(--bg);
  background: var(--avatar-colour, var(--ink-3));
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  flex: none;
}
.avatar--more { background: var(--line-strong); color: var(--ink-2); }
.avatar--typing { box-shadow: 0 0 0 2px var(--avatar-colour, var(--accent)); }

.typing-slot { display: inline-flex; gap: var(--space-2); }
.typing {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--avatar-colour, var(--accent)) 16%, transparent);
  color: var(--avatar-colour, var(--accent));
  font-size: 11px;
  font-weight: 500;
}
.typing__dots { display: inline-flex; gap: 2px; }
.typing__dots i {
  width: 3px; height: 3px;
  border-radius: 50%;
  background: currentColor;
  animation: blink 1.1s infinite;
}
.typing__dots i:nth-child(2) { animation-delay: 0.18s; }
.typing__dots i:nth-child(3) { animation-delay: 0.36s; }
@keyframes blink { 0%, 60%, 100% { opacity: 0.3; } 30% { opacity: 1; } }

/* ── Live cursors ────────────────────────────────────────────── */
.cursor-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 60;
  overflow: hidden;
}
.cursor {
  position: absolute;
  top: 0; left: 0;
  display: flex;
  align-items: flex-start;
  gap: 2px;
  transition: transform 0.08s linear;
  will-change: transform;
}
.cursor__point {
  width: 0; height: 0;
  border-left: 7px solid var(--cursor-colour);
  border-bottom: 11px solid transparent;
  border-right: 3px solid transparent;
  filter: drop-shadow(0 1px 1px rgb(0 0 0 / 0.25));
}
.cursor__label {
  margin-top: 8px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--cursor-colour);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

/* ── Status chip / dot ───────────────────────────────────────── */
.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--ink-3);
  font-size: 12px;
  font-weight: 500;
}
.status-chip::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--ink-3);
}
.status-chip[data-state="connected"] { color: var(--ok); }
.status-chip[data-state="connected"]::before { background: var(--ok); }
.status-chip[data-state="disconnected"],
.status-chip[data-state="error"] { color: var(--warn); }
.status-chip[data-state="disconnected"]::before,
.status-chip[data-state="error"]::before { background: var(--warn); }

.m-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--ink-3);
  flex: none;
}
.m-dot[data-state="connected"] { background: var(--ok); }
.m-dot[data-state="disconnected"], .m-dot[data-state="error"] { background: var(--warn); }

/* ── Result callout ──────────────────────────────────────────── */
.result {
  display: grid;
  gap: var(--space-2);
  margin-top: var(--space-4);
  padding: var(--space-3);
  border: 1px solid var(--line-strong);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.result__code {
  font-family: var(--mono);
  font-size: 15px;
  word-break: break-all;
  user-select: all;
  color: var(--ink);
}
.result__warn { font-size: 12px; color: var(--warn); }

.meta-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-1) var(--space-4);
  margin: var(--space-5) 0 0;
  font-size: 12px;
}
.meta-list dt { color: var(--ink-3); }
.meta-list dd { margin: 0; color: var(--ink-2); }

/* ── Toasts ──────────────────────────────────────────────────── */
.toast-host {
  position: fixed;
  z-index: 90;
  bottom: max(var(--space-4), env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%);
  display: grid;
  gap: var(--space-2);
  width: min(420px, calc(100vw - 2 * var(--space-4)));
}
.toast {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-2);
  font-size: 14px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.toast.is-in { opacity: 1; transform: none; }
.toast--success { border-left: 3px solid var(--ok); }
.toast--error { border-left: 3px solid var(--danger); }
.toast--warn { border-left: 3px solid var(--warn); }
.toast--info { border-left: 3px solid var(--accent); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ── Icon buttons ────────────────────────────────────────────── */
.btn--icon { gap: var(--space-2); padding-inline: var(--space-3); }
.btn--icon svg { flex: none; }
.btn__label { white-space: nowrap; }
/* Icon-only: the label stays in the DOM for assistive tech. */
.btn--icon-only { width: 2.75rem; padding-inline: 0; }
.btn--icon-only .btn__label {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ── Postura logo ────────────────────────────────────────────────
   The mark and wordmark are Postura's own PNGs, used as alpha masks and
   tinted with `background-color`, so one file per shape serves every
   context and colour scheme with no recoloured copies to keep in sync.

   The tint follows the type colour: black on white, mint on black. Inside
   the mint badge it is always black, because the plate is mint in both
   schemes and mint-on-mint would vanish.

   `mask-image` needs Safari's prefix; the @supports block falls back to the
   plain PNG anywhere masks are unavailable.
   ───────────────────────────────────────────────────────────── */

.brand-mark,
.brand-wordmark {
  display: block;
  flex: none;
  background-color: var(--ink);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

.brand-mark {
  width: 2rem;
  aspect-ratio: 1;
  -webkit-mask-image: url("/brand/postura-mark.png");
  mask-image: url("/brand/postura-mark.png");
}

.brand-wordmark {
  /* The wordmark artwork is 400×82. */
  height: 1.5rem;
  aspect-ratio: 400 / 82;
  width: auto;
  -webkit-mask-image: url("/brand/postura-wordmark.png");
  mask-image: url("/brand/postura-wordmark.png");
}

/* The mark on its mint plate, as used in headers. Declared after the shared
   rules above would lose to them, so the plate's own override lives here. */
.brand-badge {
  display: grid;
  place-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--radius-sm);
  background: var(--brand-mint);
  flex: none;
}
.brand-badge .brand-mark {
  width: 1.5rem;
  /* Always black: the plate stays mint in both schemes. */
  background-color: #000;
}

@supports not ((-webkit-mask-image: url("#")) or (mask-image: url("#"))) {
  .brand-mark,
  .brand-wordmark {
    background-color: transparent;
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;
  }
  .brand-mark { background-image: url("/brand/postura-mark.png"); }
  .brand-wordmark { background-image: url("/brand/postura-wordmark.png"); }
}

/* ── User accounts panel ─────────────────────────────────────── */
.users-panel { display: grid; gap: var(--space-3); }
.users-panel__intro { font-size: 0.8125rem; color: var(--ink-3); }

.user-card {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  overflow: hidden;
}
.user-card.is-off { opacity: 0.6; }
.user-card__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.user-card__who { display: grid; gap: 1px; min-width: 0; flex: 1 1 8rem; }
.user-card__who strong { font-size: 0.875rem; }
.user-card__who span { font-size: 0.75rem; color: var(--ink-3); font-family: var(--mono); }

.role-pill {
  padding: 1px 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  font-size: 0.6875rem;
  color: var(--ink-3);
  white-space: nowrap;
}
.role-pill--admin {
  border-color: var(--line-strong);
  color: var(--on-accent);
  background: var(--accent);
}

.user-card__body { padding: var(--space-4); }
.user-card__pwrow { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
.user-card__tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
}

.user-add {
  margin-top: var(--space-2);
  padding: var(--space-4);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
}
.user-add h4 { font-size: 0.875rem; margin-bottom: var(--space-4); }
.user-add__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0 var(--space-4);
}

/* Account registration, approval and password controls. */
.account-notice { padding: 1rem; border: 1px solid #80ac88; border-radius: 12px; background: #effbf0; color: #123a22; }
.account-dialog { width: min(92vw, 480px); max-height: 90dvh; overflow: auto; border: 1px solid #cddbd2; border-radius: 18px; padding: 1.5rem; background: #fff; color: #111; }
.account-dialog::backdrop { background: rgb(0 20 10 / 45%); }
.account-password { display: grid; gap: 1rem; margin: 0 0 1rem; }
.registration-review { display: grid; gap: 1rem; margin-bottom: 2rem; }
.registration-review__actions { display: flex; flex-wrap: wrap; gap: .5rem; }
.user-role-controls { display: grid; gap: .5rem; }
[hidden] { display: none !important; }
