/* vpn-spa-v2 — Deep Harbour theme (Ar Mor brand system).
   Source of truth: Charliehub Brand System Draft v2 + Deep Harbour spec.

   ── Architecture ────────────────────────────────────────────────────────
   Two-layer tokens: PRIMITIVES (palette) feed SEMANTIC TOKENS (roles).
   Components reference semantic tokens only — so a `surface-noz` context
   can re-theme them automatically without touching component CSS.

   ── Doctrine ────────────────────────────────────────────────────────────
   • Flat. No gradients, glows, blurred decoration.
   • Mor Gwer = action. Buttons, primary links, focus on brand.
   • Maen Roz = accent ONLY. Focus rings, dividers, active-nav bar, small
     badges. Never a panel background. Never body text on light (use rz-700).
   • Noz = the dark surface. Hero panels, immersive screens.

   Fonts self-hosted under /static/fonts/ (Apache 2.0 / SIL OFL 1.1).
*/

/* ── Web fonts (self-hosted, font-display:swap) ──────────────────────── */
@font-face { font-family:"IBM Plex Sans"; font-style:normal; font-weight:400; font-display:swap; src:url("/static/fonts/ibm-plex-sans-400.woff2") format("woff2"); }
@font-face { font-family:"IBM Plex Sans"; font-style:normal; font-weight:500; font-display:swap; src:url("/static/fonts/ibm-plex-sans-500.woff2") format("woff2"); }
@font-face { font-family:"IBM Plex Sans"; font-style:normal; font-weight:600; font-display:swap; src:url("/static/fonts/ibm-plex-sans-600.woff2") format("woff2"); }
@font-face { font-family:"IBM Plex Mono"; font-style:normal; font-weight:400; font-display:swap; src:url("/static/fonts/ibm-plex-mono-400.woff2") format("woff2"); }
@font-face { font-family:"IBM Plex Mono"; font-style:normal; font-weight:500; font-display:swap; src:url("/static/fonts/ibm-plex-mono-500.woff2") format("woff2"); }
@font-face { font-family:"Inter"; font-style:normal; font-weight:400; font-display:swap; src:url("/static/fonts/inter-400.woff2") format("woff2"); }
@font-face { font-family:"Inter"; font-style:normal; font-weight:500; font-display:swap; src:url("/static/fonts/inter-500.woff2") format("woff2"); }

:root {
  /* ── Primitives — Ar Mor palette ─────────────────────────────────────── */
  --mg-900:#0D3B33; --mg-700:#15564B; --mg-500:#1E7D6E; --mg-300:#54AD9D; --mg-200:#9BD2C8; --mg-50:#E3F1EE;
  --rz-900:#6B3A34; --rz-700:#97564C; --rz-500:#C5837A; --rz-300:#DBAAA2; --rz-200:#ECCEC8; --rz-50:#F8EBE8;
  --nz-900:#11212E; --nz-700:#1A3340; --nz-500:#2A4C5A; --nz-300:#5E7E8C; --nz-200:#9DB2BC; --nz-50:#E6ECEF;
  --ink:#11181C; --slate:#1F3A4A; --storm:#556970; --mist:#8A9094;
  --cloud:#E5E7EB; --sand:#F5F1EB; --pearl:#F8F9FA; --white:#FFFFFF;

  /* ── Connection-state primitives (functional only — never decoration) ─ */
  --state-protected:#1E9E7C;
  --state-connecting:#E08A1E;
  --state-exposed:#D63D2E;

  /* ── Semantic tokens — light surfaces (default) ──────────────────────── */
  --bg-page:        var(--pearl);
  --bg-surface:     var(--white);
  --bg-sunken:      #EFEFEC;
  --border:         var(--cloud);
  --border-hover:   #D4D8DC;

  --text-strong:    var(--ink);
  --text:           var(--slate);
  --text-muted:     var(--storm);
  --text-faint:     var(--mist);

  --action:         var(--mg-500);
  --action-hover:   var(--mg-700);
  --on-action:      var(--white);

  --link:           var(--mg-700);

  --accent:         var(--rz-500);
  --accent-text:    var(--rz-700);
  --focus-border:   var(--rz-500);
  --focus-ring:     rgba(197, 131, 122, 0.28);

  /* ── State chips: pale bg + dark fg (AA-safe) ────────────────────────── */
  --protected-bg:#E4F4EE; --protected-fg:#0E5C46;
  --connecting-bg:#FBEEDA; --connecting-fg:#7A4B12;
  --exposed-bg:#FBE4E1;   --exposed-fg:#8A271C;

  /* Destructive-action friendly aliases — same primitives as exposed,
     never a separate red. */
  --danger:        var(--state-exposed);
  --danger-hover:  #B5331F;
  --danger-bg:     var(--exposed-bg);

  /* ── Geometry ────────────────────────────────────────────────────────── */
  --radius-input:   8px;
  --radius-card:    12px;
  --radius-pill:    999px;
  --shadow-card:    0 1px 2px rgba(17, 24, 28, 0.04), 0 4px 12px rgba(17, 24, 28, 0.06);

  /* ── Type ────────────────────────────────────────────────────────────── */
  --font-sans:      "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-display:   "IBM Plex Sans", "Inter", -apple-system, sans-serif;
  --font-mono:      "IBM Plex Mono", "SF Mono", Menlo, "Cascadia Mono", monospace;
}

/* ── Noz dark surface — apply on hero panels / immersive screens ─────────
   Add class `surface-noz` OR `data-surface="noz"` to a container, and every
   component inside auto-rethemes via the semantic tokens. */
.surface-noz, [data-surface="noz"] {
  --bg-page:        var(--nz-900);
  --bg-surface:     var(--nz-700);
  --bg-sunken:      #0C1922;
  --border:         var(--nz-500);
  --border-hover:   #36586A;

  --text-strong:    var(--pearl);
  --text:           var(--nz-200);
  --text-muted:     var(--nz-300);
  --text-faint:     var(--nz-500);

  --action:         var(--mg-500);
  --action-hover:   var(--mg-300);
  --on-action:      var(--white);

  --link:           var(--mg-300);
  --accent:         var(--rz-300);
}

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

html, body {
  margin: 0;
  padding: 0;
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg-page);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3 { font-family: var(--font-display); color: var(--text-strong); font-weight: 600; letter-spacing: -0.015em; }
h1 { font-size: 22px; margin: 0 0 16px; }
h2 { font-size: 18px; margin: 24px 0 12px; }
h3 { font-size: 15px; margin: 16px 0 8px; }

code, pre { font-family: var(--font-mono); font-size: 13px; }
code { background: var(--mg-50); color: var(--mg-700); padding: 1px 6px; border-radius: 3px; }

/* ── Header / nav (Noz dark canvas) ────────────────────────────────────── */
.site-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 24px;
  background: var(--nz-900);
  color: var(--pearl);
  border-bottom: 1px solid var(--nz-700);
}
.site-header .brand { display: flex; align-items: center; gap: 10px; font-weight: 600; font-family: var(--font-display); font-size: 16px; color: var(--pearl); }
/* The Charliehub mark — transparent box; SVG colours via currentColor. */
.site-header .brand .mark { width: 28px; height: 28px; display: inline-flex; color: var(--mg-300); flex: none; }
.site-header .brand .mark svg { width: 100%; height: 100%; display: block; }

.site-header nav > a {
  position: relative;
  color: var(--pearl);
  margin-left: 20px;
  opacity: 0.78;
  font-size: 14px;
  padding-bottom: 6px;
}
.site-header nav > a:hover { opacity: 1; text-decoration: none; }
.site-header nav > a.active { opacity: 1; }
/* Maen Roz accent — the "small indicator bar" per Deep Harbour. */
.site-header nav > a.active::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: var(--rz-300);
  border-radius: 1px;
}

/* ── Page wrapper ──────────────────────────────────────────────────────── */
.page { max-width: 920px; margin: 24px auto; padding: 0 20px; }
.card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 24px;
}
.card + .card { margin-top: 16px; }

/* ── Forms ─────────────────────────────────────────────────────────────── */
label { display: block; font-size: 13px; font-weight: 600; color: var(--text); margin: 14px 0 6px; letter-spacing: .02em; }

input[type=text], input[type=email], input[type=password], select {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--text-strong);
  background: var(--bg-surface);
  transition: border-color .15s, box-shadow .15s;
  outline: none;
}
input:hover, select:hover { border-color: var(--border-hover); }
input:focus, select:focus { border-color: var(--focus-border); box-shadow: 0 0 0 3px var(--focus-ring); }
input[aria-invalid="true"], select[aria-invalid="true"] {
  border-color: var(--state-exposed);
  box-shadow: 0 0 0 3px rgba(214, 61, 46, 0.24);
}

/* ── Buttons ───────────────────────────────────────────────────────────── */
button, .btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 10px 18px; border: 1px solid transparent;
  border-radius: var(--radius-input);
  background: var(--action); color: var(--on-action);
  font-family: var(--font-sans); font-size: 14px; font-weight: 600;
  cursor: pointer;
  transition: background .18s, color .18s, border-color .18s;
}
button:hover, .btn:hover { background: var(--action-hover); color: var(--on-action); text-decoration: none; }
button:focus-visible, .btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}

/* Secondary: transparent, action border + text, hover gets mg-50 wash. */
.btn-secondary {
  background: transparent;
  color: var(--action);
  border: 1px solid var(--action);
}
.btn-secondary:hover {
  background: var(--mg-50);
  color: var(--action-hover);
  border-color: var(--action-hover);
}

/* Tertiary / ghost: text-only link. */
.btn-tertiary, .btn-ghost {
  background: transparent;
  color: var(--link);
  border: 1px solid transparent;
}
.btn-tertiary:hover, .btn-ghost:hover {
  background: transparent;
  color: var(--action-hover);
  text-decoration: underline;
}

/* Danger reuses the exposed state-chip pair for clear "removes data" semantics. */
.btn-danger {
  background: transparent;
  color: var(--exposed-fg);
  border: 1px solid var(--exposed-bg);
}
.btn-danger:hover {
  background: var(--exposed-bg);
  color: var(--exposed-fg);
  border-color: var(--exposed-fg);
}

/* ── Tables ────────────────────────────────────────────────────────────── */
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--border); }
th { color: var(--text-faint); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; }
tr:last-child td { border-bottom: none; }

/* ── Auth pages (centered card on light bg) ────────────────────────────── */
.auth-shell { min-height: 100vh; display: flex; align-items: center; justify-content: center; background: var(--bg-page); padding: 20px; }
.auth-card {
  width: 100%; max-width: 380px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 32px;
}
.auth-card .brand { display: flex; align-items: center; gap: 12px; margin-bottom: 24px; }
.auth-card .brand .mark { width: 36px; height: 36px; display: inline-flex; color: var(--action); flex: none; }
.auth-card .brand .mark svg { width: 100%; height: 100%; display: block; }
.auth-card .brand .name { font-family: var(--font-display); font-size: 17px; font-weight: 600; color: var(--text-strong); }
.auth-card h1 { font-size: 20px; margin: 0 0 4px; }
.auth-card .subtitle { color: var(--text-muted); font-size: 14px; margin: 0 0 20px; }

/* Inline form-result banners — derived from state chip pairs. */
.auth-card .error {
  background: var(--exposed-bg);
  color: var(--exposed-fg);
  border: 1px solid transparent;
  padding: 10px 14px;
  border-radius: var(--radius-input);
  font-size: 13px;
  margin-bottom: 16px;
}
.auth-card .info {
  background: var(--protected-bg);
  color: var(--protected-fg);
  border: 1px solid transparent;
  padding: 10px 14px;
  border-radius: var(--radius-input);
  font-size: 13px;
  margin-bottom: 16px;
}
.auth-card button { width: 100%; justify-content: center; padding: 12px; margin-top: 16px; }
.auth-card .links { margin-top: 18px; display: flex; justify-content: space-between; font-size: 13px; }
.auth-card .lang-toggle { text-align: right; margin-top: 12px; font-size: 12px; color: var(--text-faint); font-family: var(--font-mono); }

/* ── Status chips ──────────────────────────────────────────────────────── */
.pill { display: inline-block; padding: 2px 10px; border-radius: var(--radius-pill); font-size: 12px; font-weight: 500; line-height: 1.6; }
.pill-success { background: var(--protected-bg); color: var(--protected-fg); }
.pill-warn    { background: var(--connecting-bg); color: var(--connecting-fg); }
.pill-danger  { background: var(--exposed-bg); color: var(--exposed-fg); }
.pill-muted   { background: var(--bg-sunken); color: var(--text-muted); }

/* ── Misc ──────────────────────────────────────────────────────────────── */
.muted { color: var(--text-muted); }
.kbd   { font-family: var(--font-mono); font-size: 12px; padding: 2px 6px; background: var(--bg-sunken); border: 1px solid var(--border); border-radius: 4px; }
.row   { display: flex; gap: 12px; align-items: center; }
.row > .flex { flex: 1; }
.empty-state    { text-align: center; padding: 40px 20px; color: var(--text-muted); }
.empty-state h2 { color: var(--text-muted); margin-bottom: 6px; }

.fullscreen { min-height: 100vh; }

/* ── QR modal ──────────────────────────────────────────────────────────── */
.qr-modal {
  border: none;
  border-radius: var(--radius-card);
  padding: 0;
  width: min(360px, 92vw);
  background: var(--bg-surface);
  color: var(--text);
}
.qr-modal::backdrop {
  background: rgba(17, 33, 46, 0.62);   /* Noz 900 at 62% */
}
.qr-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  margin: 0;
  border-bottom: 1px solid var(--border);
}
.qr-modal-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  color: var(--text-strong);
}
.qr-modal-close {
  background: transparent;
  border: 0;
  cursor: pointer;
  font-size: 26px;
  line-height: 1;
  color: var(--text-faint);
  padding: 0 8px;
  border-radius: var(--radius-input);
}
.qr-modal-close:hover { color: var(--text-strong); background: var(--bg-sunken); }
.qr-modal-body { padding: 20px; text-align: center; }
.qr-modal-body img {
  width: 100%;
  max-width: 225px;
  height: auto;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
  padding: 6px;
  box-sizing: border-box;
}
.qr-modal-hint { font-size: 13px; margin: 14px 0 0; color: var(--text-muted); }

/* ── FAQ / Help page ────────────────────────────────────────────────────── */
.faq-page { max-width: 760px; margin: 0 auto; padding: 0 4px; }

.faq-hero { padding: 24px 0 16px; }
.faq-title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 3.6vw, 2.6rem);
  font-weight: 600;
  letter-spacing: -.02em;
  color: var(--text-strong);
  margin: 0 0 10px;
}
.faq-lead {
  font-size: 17px;
  color: var(--text-muted);
  max-width: 580px;
  margin: 0;
  line-height: 1.55;
}

.faq-section { padding: 28px 0; border-top: 1px solid var(--border); }
.faq-section:first-of-type { border-top: none; padding-top: 12px; }
.faq-section h2 {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 600;
  color: var(--text-strong);
  letter-spacing: -.01em;
  margin: 0 0 14px;
}

/* Accordion — native <details>/<summary>. No JS. */
.faq-item {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  margin-bottom: 10px;
  overflow: hidden;
  transition: border-color .15s;
}
.faq-item:hover { border-color: var(--border-hover); }
.faq-item[open] {
  border-color: var(--mg-200);
}

.faq-item > summary {
  list-style: none;
  cursor: pointer;
  padding: 14px 18px 14px 20px;
  display: flex; align-items: center; gap: 12px;
  font-family: var(--font-display);
  font-size: 15.5px;
  font-weight: 500;
  color: var(--text-strong);
  user-select: none;
}
.faq-item > summary::-webkit-details-marker { display: none; }   /* Safari */
.faq-item > summary::marker { display: none; }                   /* Firefox */
.faq-item > summary::before {
  content: "";
  width: 8px; height: 8px;
  border-right: 2px solid var(--mg-500);
  border-bottom: 2px solid var(--mg-500);
  transform: rotate(-45deg);                  /* chevron pointing right when closed */
  transition: transform .18s ease;
  flex: none;
  margin-left: 2px;
}
.faq-item[open] > summary::before {
  transform: rotate(45deg);                   /* chevron pointing down when open */
}
.faq-item > summary:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}

.faq-answer { padding: 4px 22px 18px 40px; color: var(--text); }
.faq-answer p { margin: 0 0 10px; line-height: 1.6; max-width: 60ch; }
.faq-answer p:last-child { margin-bottom: 0; }
.faq-answer ol, .faq-answer ul { margin: 6px 0 10px; padding-left: 22px; line-height: 1.6; }
.faq-answer li { margin-bottom: 4px; max-width: 56ch; }
.faq-answer strong { color: var(--text-strong); font-weight: 600; }
.faq-answer .mono { font-family: var(--font-mono); font-size: .92em; color: var(--text-strong); }

/* Per-platform install panels — stack vertically, clear visual breaks. */
.faq-platforms { margin-top: 14px; display: grid; gap: 12px; }
.faq-platform {
  background: var(--bg-sunken);
  border-radius: var(--radius-input);
  padding: 14px 18px 16px;
}
.faq-platform h3 {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  color: var(--text-strong);
  margin: 0 0 8px;
  letter-spacing: .01em;
}
.faq-platform ol { margin: 0; padding-left: 20px; }
.faq-platform li { margin-bottom: 4px; line-height: 1.55; }

/* Glossary — simple definition list. */
.faq-glossary { display: grid; gap: 10px; margin-top: 6px; }
.faq-glossary dt {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--text-strong);
  font-size: 14px;
}
.faq-glossary dd {
  margin: 2px 0 0;
  color: var(--text);
  font-size: 14px;
  line-height: 1.55;
  max-width: 60ch;
}

/* ── Language toggle (CT2151-style FR/EN pill) ──────────────────────────
   Light context by default; dark variant overrides for the .site-header
   navigation. Uses semantic tokens elsewhere so it auto-themes in any
   surface-noz context. */
.lang-toggle {
  display: inline-flex;
  align-items: center;
  background: var(--bg-sunken);
  border-radius: var(--radius-input);
  padding: 2px;
  gap: 1px;
  margin-top: 12px;
}
.lang-btn {
  background: transparent;
  border: 0;
  color: var(--text-muted);
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  padding: 4px 9px;
  border-radius: 4px;
  cursor: pointer;
  transition: color .15s, background .15s;
  line-height: 1;
}
.lang-btn:hover:not(.active) { color: var(--text-strong); background: transparent; }
.lang-btn.active {
  background: var(--bg-surface);
  color: var(--text-strong);
}
.lang-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}

/* Dark variant in the Noz nav — alpha-white pattern mirroring CT2151. */
.site-header .lang-toggle {
  background: rgba(255, 255, 255, 0.08);
  margin-top: 0;
  margin-left: 16px;
}
.site-header .lang-btn { color: rgba(255, 255, 255, 0.55); }
.site-header .lang-btn:hover:not(.active) { color: rgba(255, 255, 255, 0.85); background: transparent; }
.site-header .lang-btn.active {
  background: rgba(255, 255, 255, 0.18);
  color: var(--pearl);
}

/* Auth cards — drop the legacy .lang-toggle margin override; pill is its
   own block element with its own spacing. */
.auth-card .lang-toggle { margin-top: 18px; }

/* Login l-footer — center the pill */
.l-footer .lang-toggle { margin-top: 0; }
.l-footer { display: flex; justify-content: center; }

/* ── Help icon button (round ghost) ─────────────────────────────────────
   Compact secondary entry to the FAQ. Sits next to the primary action
   in card headers; visually subordinate to the primary "+ New peer". */
.help-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--action);
  transition: background .15s, border-color .15s, color .15s;
  text-decoration: none;
  flex: none;
}
.help-btn:hover {
  background: var(--mg-50);
  border-color: var(--action);
  color: var(--action-hover);
  text-decoration: none;
}
.help-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}
.help-btn svg { display: block; }

/* Inline help link below the empty-state CTA. */
.empty-help-link {
  font-size: 14px;
  color: var(--link);
  text-decoration: none;
}
.empty-help-link:hover { text-decoration: underline; color: var(--action-hover); }

/* Inline max_peers editor on /settings/users. Tight number input + Set btn.
   Sits in a narrow table column; doesn't blow up row height. */
.max-peers-form {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
}
.max-peers-form input[type="number"] {
  width: 64px;
  padding: 6px 8px;
  font-size: 13px;
  border-radius: var(--radius-input);
  border: 1px solid var(--border);
  background: var(--bg-surface);
}
.max-peers-form input[type="number"]:focus {
  border-color: var(--focus-border);
  box-shadow: 0 0 0 3px var(--focus-ring);
  outline: none;
}
.max-peers-form .btn {
  padding: 6px 10px;
  font-size: 12px;
  font-weight: 600;
}

/* ── Users admin table — overflow-menu pattern ──────────────────────────
   Replaces three stacked action buttons per row with a single ⋮ kebab
   that opens a dropdown menu. Anchored to the kebab via position:absolute
   inside a position:relative actions cell. */

.users-table { table-layout: auto; }
.users-table tbody tr { transition: background-color .12s; }
.users-table tbody tr:hover { background: var(--bg-sunken); }
.users-table td, .users-table th { vertical-align: middle; }
.users-table th {
  color: var(--text-faint);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* Email cell — keep on one line, ellipsis if long, full address on hover. */
.users-table td.users-email {
  max-width: 260px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.users-table td.users-email strong { vertical-align: middle; }

/* "vous" badge — compact muted pill, matches the table chrome */
.users-table .you-badge {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 8px;
  background: var(--bg-sunken);
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 500;
  border-radius: var(--radius-pill);
  vertical-align: middle;
}

/* Actions cell — anchor for the menu */
.users-table td.users-actions {
  position: relative;
  text-align: right;
  width: 56px;
}

/* Kebab icon button — small, square, ghost. Active when its menu is open. */
.kebab-btn {
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-input);
  color: var(--text-muted);
  cursor: pointer;
  padding: 0;
  transition: background .15s, color .15s, border-color .15s;
}
.kebab-btn:hover { background: var(--bg-sunken); color: var(--text-strong); }
.kebab-btn[aria-expanded="true"] {
  background: var(--bg-sunken);
  color: var(--text-strong);
  border-color: var(--border);
}
.kebab-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}
.kebab-btn svg { display: block; }

/* Dropdown menu — anchored below the kebab, right-edge-aligned. */
.row-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 8px;
  z-index: 20;
  min-width: 210px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(17, 24, 28, 0.10);
  padding: 4px;
  display: none;
}
.row-menu[data-open="true"] { display: block; }
/* If the menu would overflow the viewport bottom, JS flips it above. */
.row-menu[data-flip="up"] { top: auto; bottom: calc(100% + 4px); }

.row-menu form { display: block; margin: 0; }
.row-menu-item, .row-menu-item-button {
  width: 100%;
  height: 36px;
  padding: 0 12px;
  border: 0;
  background: transparent;
  border-radius: 6px;
  color: var(--text);
  text-align: left;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
}
.row-menu-item:hover, .row-menu-item-button:hover,
.row-menu-item:focus-visible, .row-menu-item-button:focus-visible {
  background: var(--bg-sunken);
  outline: none;
}
.row-menu-item-danger { color: var(--danger); }
.row-menu-item-danger:hover, .row-menu-item-danger:focus-visible {
  background: var(--danger-bg);
  color: var(--danger);
}
.row-menu-divider {
  margin: 4px 0;
  border: 0;
  border-top: 1px solid var(--border);
  height: 0;
}

/* Status pill — explicit "Inactive" variant uses muted chip pair */
.pill-status-inactive {
  display: inline-block;
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.6;
  background: var(--bg-sunken);
  color: var(--text-muted);
}

/* Max-peers input — disabled Set until value changes. */
.max-peers-form .btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
  background: var(--bg-sunken);
  color: var(--text-muted);
  border: 1px solid var(--border);
}

/* ── Delete confirmation dialog ─────────────────────────────────────────
   Custom <dialog> replaces native confirm(). Same shape pattern as
   .qr-modal: backdrop + centred card with header/body/actions. */
.confirm-dialog {
  border: none;
  border-radius: var(--radius-card);
  padding: 0;
  width: min(420px, 92vw);
  background: var(--bg-surface);
  color: var(--text);
}
.confirm-dialog::backdrop { background: rgba(17, 33, 46, 0.62); }
.confirm-dialog form { margin: 0; }
.confirm-dialog-body { padding: 22px 24px 14px; }
.confirm-dialog h2 {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--text-strong);
  margin: 0 0 6px;
}
.confirm-dialog .detail {
  font-size: 14px;
  color: var(--text-strong);
  font-family: var(--font-mono);
  word-break: break-all;
  margin: 0 0 12px;
}
.confirm-dialog .warning {
  font-size: 13px;
  color: var(--text-muted);
  margin: 0 0 16px;
}
.confirm-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 0 24px 22px;
}
.confirm-dialog-actions .btn-danger {
  background: var(--danger);
  color: var(--on-action);
  border: 1px solid var(--danger);
}
.confirm-dialog-actions .btn-danger:hover {
  background: var(--danger-hover);
  border-color: var(--danger-hover);
}

/* Visually hidden — accessible-only label. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ── FAQ: trust-path diagram ────────────────────────────────────────────
   Three calm cards stacked vertically (device → Charliehub → internet),
   thin arrow connectors between. Apple-support style, not infra. */
.faq-section-diagram { padding-top: 24px; padding-bottom: 16px; }

.trust-path {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  margin: 4px 0 14px;
}

.trust-node {
  width: 100%;
  max-width: 360px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 18px 22px;
  text-align: center;
}
.trust-node-primary {
  border-color: var(--mg-200);
  background: var(--mg-50);
}

.trust-icon {
  width: 48px; height: 48px;
  margin: 0 auto 8px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--bg-sunken);
  color: var(--text-muted);
}
.trust-node-primary .trust-icon {
  background: var(--mg-500);
  color: var(--white);
}
.trust-icon-mark { padding: 6px; }
.trust-icon-mark svg { width: 100%; height: 100%; }

.trust-label {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  color: var(--text-strong);
  margin-bottom: 2px;
}
.trust-sub {
  font-size: 13px;
  color: var(--text-muted);
}

.trust-flags {
  margin-top: 10px;
  font-size: 22px;
  letter-spacing: 4px;
  line-height: 1;
}

.trust-connector {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: var(--text-faint);
  margin: -2px 0;
}
.trust-connector-svg { display: block; }
.trust-connector-caption {
  /* z-index above adjacent .trust-node cards so the caption text isn't
     painted over by the tinted .trust-node-primary background. Cards have
     no explicit z-index, so any positive value wins by DOM order. */
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--text-muted);
  text-transform: uppercase;
  /* Caption's bg matches the section's pearl background, so where the
     caption overlaps card edges it visually "punches" through — the
     tucked-into-the-arrow effect. Padding-block + smaller negative
     margins keep a breathing band so descenders aren't clipped at the
     card edge. */
  background: var(--bg-page);
  padding: 3px 10px;
  margin-top: -4px;
  margin-bottom: -4px;
  border-radius: 999px;
}

.trust-explainer {
  text-align: center;
  font-size: 15px;
  color: var(--text);
  max-width: 580px;
  margin: 8px auto 4px;
  line-height: 1.55;
}

.trust-check-cta {
  text-align: center;
  margin: 14px 0 4px;
}

/* ── Check-my-connection page ──────────────────────────────────────────── */
.check-exit-page { max-width: 640px; margin: 0 auto; padding: 0 4px; }

.check-exit-hero { padding: 24px 0 12px; text-align: center; }
.check-exit-hero h1 {
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 3.4vw, 2.2rem);
  font-weight: 600;
  letter-spacing: -.02em;
  color: var(--text-strong);
  margin: 0 0 8px;
}
.check-exit-hero .lead {
  font-size: 15px;
  color: var(--text-muted);
  max-width: 480px;
  margin: 0 auto;
  line-height: 1.55;
}

.check-exit-card {
  display: flex;
  align-items: center;
  gap: 22px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 26px 28px;
  margin: 22px 0 16px;
}
.check-exit-card-success { border-color: var(--mg-200); background: var(--protected-bg); }
.check-exit-card-warn    { border-color: var(--rz-200); background: var(--rz-50); }

.check-exit-flag {
  font-size: 56px;
  line-height: 1;
  flex: none;
}
.check-exit-card-warn .check-exit-flag {
  color: var(--rz-700);
}

.check-exit-result h2 {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 600;
  color: var(--text-strong);
  margin: 0 0 6px;
}
.check-exit-result p { margin: 4px 0; font-size: 14px; }
.check-exit-result .ip {
  font-family: var(--font-mono);
  font-size: 13px;
  background: var(--bg-surface);
  color: var(--text-strong);
  padding: 1px 6px;
  border-radius: 4px;
  border: 1px solid var(--border);
}
.check-exit-result .meta {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-faint);
  letter-spacing: .03em;
  margin-top: 6px;
}

.check-exit-howto {
  background: var(--bg-sunken);
  border-radius: var(--radius-card);
  padding: 18px 22px 14px;
  margin: 0 0 18px;
}
.check-exit-howto h3 {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  color: var(--text-strong);
  margin: 0 0 8px;
}
.check-exit-howto ol { margin: 0; padding-left: 20px; }
.check-exit-howto li { margin-bottom: 4px; line-height: 1.55; font-size: 14px; }

.check-exit-caveat {
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.55;
  border-left: 3px solid var(--border);
  padding-left: 12px;
  margin: 16px 0;
}

.check-exit-actions {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-top: 18px;
}
.check-exit-actions .btn-tertiary {
  color: var(--link);
  background: transparent;
  border: none;
  font-weight: 500;
  align-self: center;
}
.check-exit-actions .btn-tertiary:hover {
  text-decoration: underline;
  background: transparent;
  color: var(--action-hover);
}

/* Check-exit transient "checking..." state during JS upgrade. */
.check-exit-card-checking {
  border-color: var(--border);
  background: var(--bg-surface);
}
.check-exit-card-checking .check-exit-flag {
  font-size: 32px;
  color: var(--text-muted);
  opacity: 0.6;
}
.check-exit-card-checking .check-exit-result h2 {
  color: var(--text-muted);
}

/* ── Nav help button (in site-header) ──────────────────────────────────
   Promotes the FAQ link from a plain text link to a button-styled affordance
   with the help-circle icon, so it's recognisable as "help" at a glance. */
.site-header nav a.nav-help-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 20px;
  padding: 5px 11px 5px 9px;
  border-radius: var(--radius-input);
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.04);
  color: var(--pearl);
  font-size: 13px;
  opacity: 0.92;
  text-decoration: none;
}
.site-header nav a.nav-help-btn:hover {
  background: rgba(255, 255, 255, 0.10);
  border-color: rgba(255, 255, 255, 0.30);
  opacity: 1;
  text-decoration: none;
}
.site-header nav a.nav-help-btn.active {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.35);
}
.site-header nav a.nav-help-btn.active::after { display: none; }   /* override the underline rule */
.site-header nav a.nav-help-btn svg { flex: none; display: block; }

/* ── Sign-in button in the anonymous nav ──────────────────────────────
   Primary-action treatment — Mor Gwer fill on the Noz header reads as
   the page's "next step" affordance for visitors who hit /faq before
   signing in. Matches the page-level .btn / .nav-help-btn geometry. */
.site-header nav a.nav-login-btn {
  display: inline-flex;
  align-items: center;
  margin-left: 20px;
  padding: 5px 14px;
  border-radius: var(--radius-input);
  background: var(--mg-500);
  border: 1px solid var(--mg-500);
  color: var(--white);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .01em;
  opacity: 1;
}
.site-header nav a.nav-login-btn:hover {
  background: var(--mg-300);
  border-color: var(--mg-300);
  color: var(--white);
  text-decoration: none;
}
.site-header nav a.nav-login-btn::after { display: none; }   /* no active underline on primary buttons */

/* ── Brand block becomes a link when wrapped in <a> ────────────────────
   When base.html wraps the brand in an anchor (so anonymous visitors can
   click back to / and signed-in users to /peers), keep the visual
   identical to the old non-link form — no underline, no opacity drop. */
.site-header a.brand,
.site-header a.brand:hover,
.site-header a.brand:visited {
  color: var(--pearl);
  text-decoration: none;
}

/* ── Page-level help button — labeled variant ──────────────────────────
   Reuses .help-btn (round circular ghost) but expands at ≥768px to show
   an inline "Help"/"Aide" text label, dramatically increasing legibility
   without breaking the 36×36 mobile target. */
.help-btn-labeled {
  width: auto;
  height: 36px;
  padding: 0 12px 0 10px;
  gap: 6px;
  border-radius: 18px;
  border: 1px solid var(--mg-200);
  color: var(--action);
  background: var(--mg-50);
}
.help-btn-labeled:hover {
  background: var(--mg-50);
  border-color: var(--action);
  color: var(--action-hover);
}
.help-btn-labeled .help-btn-label {
  display: none;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .01em;
  white-space: nowrap;
}
@media (min-width: 768px) {
  .help-btn-labeled .help-btn-label { display: inline; }
}

/* ── Action button — icon + label variant ──────────────────────────────
   Used on the device-row actions to give a quick visual cue alongside
   the existing text label. */
.btn-icon {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.btn-icon svg { flex: none; display: block; }

/* ── Onboarding card — first-run empty state on /peers ─────────────────
   Three numbered steps with platform install pills under step 1. */
.onboarding {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 32px 28px 24px;
  margin-top: 20px;
}
.onboarding-title {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 3vw, 1.7rem);
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--text-strong);
  margin: 0 0 24px;
  text-align: center;
}
.onboarding-steps {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 22px;
}
.onboarding-step {
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 16px;
  align-items: start;
}
.onboarding-num {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--mg-500);
  color: var(--white);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 16px;
  display: flex; align-items: center; justify-content: center;
  flex: none;
}
.onboarding-body h3 {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--text-strong);
  margin: 6px 0 4px;
}
.onboarding-body p {
  margin: 0 0 10px;
  color: var(--text);
  font-size: 14px;
  line-height: 1.55;
}
.onboarding-footer {
  margin: 24px 0 0;
  text-align: center;
  font-size: 14px;
}

/* Platform install pills (step 1) */
.install-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}
.install-link {
  display: inline-flex;
  align-items: center;
  padding: 7px 14px;
  border-radius: var(--radius-pill);
  background: var(--bg-sunken);
  color: var(--text-strong);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  border: 1px solid var(--border);
  transition: background .15s, border-color .15s, color .15s;
}
.install-link:hover {
  background: var(--mg-50);
  border-color: var(--mg-200);
  color: var(--action);
  text-decoration: none;
}
.install-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}

/* ── Form field helper text — small muted line under each field ────────
   Visible by default, doesn't replace the label. */
.field-help {
  margin: 4px 0 12px;
  font-size: 12.5px;
  color: var(--text-muted);
  line-height: 1.4;
}

/* ── Info tooltip ("?" next to a label) ──────────────────────────────── */
.info-tip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px; height: 16px;
  margin-left: 4px;
  border-radius: 50%;
  color: var(--text-muted);
  vertical-align: middle;
  cursor: help;
}
.info-tip:hover, .info-tip:focus-visible {
  color: var(--action);
  outline: none;
}
.info-tip svg { display: block; }

/* ── Advanced collapsible section (e.g. /account technical fields) ─────
   Native <details>/<summary>, same chevron pattern as the FAQ accordion. */
.advanced-section {
  margin-top: 22px;
  border-top: 1px solid var(--border);
  padding-top: 16px;
}
.advanced-section > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted);
  letter-spacing: .02em;
  text-transform: uppercase;
  user-select: none;
}
.advanced-section > summary::-webkit-details-marker { display: none; }
.advanced-section > summary::marker { display: none; }
.advanced-section > summary::before {
  content: "";
  width: 6px; height: 6px;
  border-right: 2px solid var(--text-muted);
  border-bottom: 2px solid var(--text-muted);
  transform: rotate(-45deg);
  transition: transform .18s ease;
}
.advanced-section[open] > summary::before { transform: rotate(45deg); }

/* ── QR modal — install fallback line ────────────────────────────────── */
.qr-modal-no-wg {
  margin: 8px 0 0;
  font-size: 12.5px;
  text-align: center;
}
.qr-modal-no-wg a {
  color: var(--link);
}

/* ── Site-header nav flex fix (added 2026-05-24) ──────────────────────── */
/* nav was display:block; adding flex so all items sit on one row.         */
.site-header nav {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 0;
}
.site-header nav > * { flex: 0 0 auto; }
.site-header nav .lang-toggle { margin-top: 0; }
.site-header nav .nav-admin-drop { width: auto; margin-left: 20px; }
.nav-admin-btn  { margin-left: 0; }
