/* ==========================================================================
   Symmy — Raynet & Outlook Sync · design system
   --------------------------------------------------------------------------
   Brand (symmy.visualbook.pro):
     Systémová modrá   #3452f8   primary — actions, links, focus, active nav
     Propojovací zelená #3bd895  accent  — success, "live" states, logo
     Stabilní zelená   #022b26   dark    — app chrome, headings, deep text
     Bílá              #ffffff

   Typefaces: the manual specifies PP Formula Extended Bold (display) and
   Saans Regular (text). Both are commercial and are not redistributed with
   this repo, so the stacks below fall back to the closest freely available
   equivalents — Archivo Expanded and Inter — and finally to Arial, which the
   manual itself names as the universal fallback. To adopt the licensed
   fonts, drop the webfonts in static/fonts/, add @font-face rules, and put
   their family names at the front of --font-display / --font-text. Nothing
   else in this file needs to change.
   ========================================================================== */

/* ── Tokens ─────────────────────────────────────────────────────────────── */
:root {
  /* Brand */
  --brand-blue: #3452f8;
  --brand-blue-600: #2a44d8;
  --brand-blue-700: #2138b4;
  --brand-green: #3bd895;
  --brand-green-600: #2ec07f;
  --brand-dark: #022b26;

  /* Neutrals — tinted towards the brand dark rather than pure grey, which is
     what keeps large flat areas from reading as a default browser page. */
  --ink-900: #022b26;
  --ink-700: #1f3d38;
  --ink-500: #55706a;
  --ink-400: #5f7873;   /* 4.75:1 on white — help text, table heads, captions */
  --ink-300: #a7b8b4;
  --ink-200: #d3dedb;
  --ink-100: #e8efed;
  --ink-050: #f4f8f7;
  --surface: #ffffff;
  --canvas: #f4f6f9;

  /* Semantic */
  --ok: #127a4f;        /* 4.86:1 inside --ok-bg */
  --ok-bg: #e7f8ef;
  --ok-border: #b6e7ce;
  --warn: #9a6700;
  --warn-bg: #fff6e0;
  --warn-border: #f2d999;
  --danger: #c8342b;
  --danger-bg: #fdeceb;
  --danger-border: #f6c4c0;
  --info: #2138b4;
  --info-bg: #ecefff;
  --info-border: #c5cdfb;

  /* Typography */
  --font-display: "Archivo Expanded", "Archivo", Arial, sans-serif;
  --font-text: "Inter", Arial, Helvetica, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;

  /* Fluid type scale — clamp() so small screens are not simply "the desktop
     size, smaller"; each step keeps a readable floor. */
  --t-xs: 0.75rem;
  --t-sm: 0.8125rem;
  --t-base: 0.9375rem;
  --t-md: 1rem;
  --t-lg: clamp(1.0625rem, 0.4vw + 0.97rem, 1.1875rem);
  --t-xl: clamp(1.25rem, 0.8vw + 1.06rem, 1.5rem);
  --t-2xl: clamp(1.5rem, 1.6vw + 1.13rem, 2.125rem);
  --t-3xl: clamp(1.875rem, 2.6vw + 1.26rem, 2.75rem);

  /* Space — 4px base */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.25rem;
  --s-6: 1.5rem;
  --s-8: 2rem;
  --s-10: 2.5rem;
  --s-12: 3rem;
  --s-16: 4rem;

  /* Shape */
  --r-sm: 8px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-xl: 20px;
  --r-pill: 999px;

  /* Elevation — layered and blue-tinted; a single hard shadow is the tell of
     an untouched default. */
  --sh-1: 0 1px 2px rgba(2, 43, 38, 0.05), 0 1px 3px rgba(2, 43, 38, 0.04);
  --sh-2: 0 2px 4px rgba(2, 43, 38, 0.04), 0 6px 16px rgba(52, 82, 248, 0.06);
  --sh-3: 0 4px 8px rgba(2, 43, 38, 0.05), 0 16px 40px rgba(52, 82, 248, 0.10);
  --sh-focus: 0 0 0 3px rgba(52, 82, 248, 0.28);
  --sh-focus-green: 0 0 0 3px rgba(59, 216, 149, 0.40);

  --dur: 160ms;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --shell: 1180px;
  --shell-narrow: 760px;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font-text);
  font-size: var(--t-base);
  line-height: 1.55;
  color: var(--ink-900);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

[hidden] { display: none !important; }

h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.2; letter-spacing: -0.01em; }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; }
img, svg { max-width: 100%; }
a { color: var(--brand-blue); text-decoration: none; }
a:hover { text-decoration: underline; }

/* One visible focus treatment everywhere, keyboard-only. */
:focus-visible {
  outline: 2px solid var(--brand-blue);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}
.on-brand :focus-visible { outline-color: #fff; }

/* ── Typography helpers ─────────────────────────────────────────────────── */
.display { font-family: var(--font-display); font-weight: 700; letter-spacing: -0.02em; }
.t-3xl { font-size: var(--t-3xl); }
.t-2xl { font-size: var(--t-2xl); }
.t-xl { font-size: var(--t-xl); }
.t-lg { font-size: var(--t-lg); }
.t-md { font-size: var(--t-md); }
.t-sm { font-size: var(--t-sm); }
.t-xs { font-size: var(--t-xs); }
.mono { font-family: var(--font-mono); font-size: 0.9em; font-variant-ligatures: none; }
.muted { color: var(--ink-500); }
.subtle { color: var(--ink-400); }
.strong { font-weight: 600; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nowrap { white-space: nowrap; }
@media (max-width: 640px) { .hide-sm { display: none; } }

.eyebrow {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-400);
}

/* Screen-reader-only: real labels for inputs that show only a placeholder. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
/* …unless it is focusable, in which case it has to be reachable on screen. */
a.sr-only:focus, a.sr-only:focus-visible, button.sr-only:focus {
  position: fixed; top: var(--s-3); left: var(--s-3);
  width: auto; height: auto; margin: 0; overflow: visible;
  clip: auto; z-index: 100;
}

/* ── Layout ─────────────────────────────────────────────────────────────── */
.shell { width: 100%; max-width: var(--shell); margin: 0 auto; padding: 0 var(--s-5); }
.shell-narrow { max-width: var(--shell-narrow); }
.page { padding: var(--s-8) 0 var(--s-16); }

.stack > * + * { margin-top: var(--s-4); }
.stack-lg > * + * { margin-top: var(--s-6); }
.stack-sm > * + * { margin-top: var(--s-2); }

.row { display: flex; align-items: center; gap: var(--s-3); }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); }
.row-wrap { flex-wrap: wrap; }
.row-top { align-items: flex-start; }
.spacer { flex: 1 1 auto; }

.grid { display: grid; gap: var(--s-5); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* 230px keeps four tiles on a desktop row; below that the fallback is two
   up rather than one, so the table is not pushed a screen down. */
.grid-auto { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
@media (max-width: 640px) {
  .grid-auto { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); }
  .stat { padding: var(--s-4); }
  .stat-value { font-size: var(--t-xl); }
}
.col-span-2 { grid-column: span 2; }

@media (max-width: 860px) {
  .grid-2, .grid-3 { grid-template-columns: minmax(0, 1fr); }
  .col-span-2 { grid-column: auto; }
  .page { padding: var(--s-6) 0 var(--s-12); }
}

/* ── App bar (internal admin) ───────────────────────────────────────────── */
.appbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--brand-dark);
  /* A hairline of brand blue reads as intent; a plain edge reads as unstyled. */
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.07), 0 1px 0 rgba(2, 43, 38, 0.06);
}
.appbar-inner { display: flex; align-items: center; gap: var(--s-5); min-height: 60px; }
.appbar-logo { display: flex; align-items: center; flex-shrink: 0; }
.appbar-logo svg { width: 86px; height: auto; display: block; }
.appbar-wordmark {
  color: rgba(255, 255, 255, 0.5);
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
  padding-left: var(--s-4);
  margin-left: var(--s-1);
  border-left: 1px solid rgba(255, 255, 255, 0.14);
}
.appbar-actions { display: flex; align-items: center; gap: var(--s-3); margin-left: auto; }
.appbar-user {
  display: flex; align-items: center; gap: var(--s-2);
  color: rgba(255, 255, 255, 0.72);
  font-size: var(--t-sm);
}
.avatar {
  display: grid; place-items: center;
  width: 28px; height: 28px;
  border-radius: var(--r-pill);
  background: rgba(59, 216, 149, 0.18);
  color: var(--brand-green);
  font-size: var(--t-xs);
  font-weight: 600;
  text-transform: uppercase;
}

@media (max-width: 640px) {
  .appbar-wordmark { display: none; }
  .appbar-user span:not(.avatar) { display: none; }
  .appbar-inner { gap: var(--s-3); }
}

/* ── Segmented control (language switch) ────────────────────────────────── */
.segmented {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: rgba(255, 255, 255, 0.10);
  border-radius: var(--r-pill);
}
.segmented.on-light { background: var(--ink-100); }
.segmented button {
  border: 0;
  cursor: pointer;
  border-radius: var(--r-pill);
  padding: 5px 11px;
  font-family: inherit;
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.03em;
  background: transparent;
  color: rgba(255, 255, 255, 0.85);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.segmented button:hover { color: rgba(255, 255, 255, 0.9); }
.segmented button[aria-pressed="true"] { background: rgba(255, 255, 255, 0.22); color: #fff; }
.segmented.on-light button { color: var(--ink-500); }
.segmented.on-light button:hover { color: var(--ink-900); }
.segmented.on-light button[aria-pressed="true"] { background: var(--surface); color: var(--brand-blue); box-shadow: var(--sh-1); }

/* ── Buttons ────────────────────────────────────────────────────────────── */
.btn {
  --btn-bg: var(--brand-blue);
  --btn-fg: #fff;
  --btn-bd: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  /* 44px min target: the old 1.5rem-tall buttons were a miss on touch. */
  min-height: 44px;
  padding: 0 var(--s-5);
  border: 1px solid var(--btn-bd);
  border-radius: var(--r-pill);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: inherit;
  font-size: var(--t-base);
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.btn:hover { background: var(--brand-blue-600); text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn svg { width: 17px; height: 17px; flex-shrink: 0; }

/* White on the connecting green is 1.84:1 — unreadable. The brand dark on it
   is 8.31:1, and pairs two brand colours, so the CTA stays green. */
.btn-accent { --btn-bg: var(--brand-green); --btn-fg: var(--brand-dark); }
.btn-accent:hover { background: var(--brand-green-600); }

.btn-ghost { --btn-bg: transparent; --btn-fg: var(--ink-700); --btn-bd: var(--ink-200); }
.btn-ghost:hover { background: var(--ink-050); border-color: var(--ink-300); }

.btn-danger { --btn-bg: transparent; --btn-fg: var(--danger); --btn-bd: var(--danger-border); }
.btn-danger:hover { background: var(--danger-bg); border-color: var(--danger); }

.btn-on-brand { --btn-bg: rgba(255,255,255,0.14); --btn-fg: rgba(255,255,255,0.92); }
.btn-on-brand:hover { background: rgba(255, 255, 255, 0.24); }

.btn-sm { min-height: 36px; padding: 0 var(--s-4); font-size: var(--t-sm); }
.btn-lg { min-height: 52px; padding: 0 var(--s-6); font-size: var(--t-md); }
.btn-block { width: 100%; }

.btn:disabled, .btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}

.btn-link {
  background: none; border: 0; padding: 0;
  color: var(--brand-blue); font: inherit; font-weight: 600;
  cursor: pointer;
}
.btn-link:hover { text-decoration: underline; }

/* ── Cards & widgets ────────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: 1px solid var(--ink-100);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
}
.card-pad { padding: var(--s-6); }
.card-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-4);
  padding: var(--s-4) var(--s-6);
  border-bottom: 1px solid var(--ink-100);
}
.card-head h2, .card-head h3 { font-size: var(--t-base); font-weight: 600; }
.card-body { padding: var(--s-6); }
.card-foot {
  padding: var(--s-4) var(--s-6);
  border-top: 1px solid var(--ink-100);
  background: var(--ink-050);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}
.card-hover { transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease); }
.card-hover:hover { box-shadow: var(--sh-2); border-color: var(--ink-200); }

@media (max-width: 640px) {
  .card-pad, .card-body { padding: var(--s-5); }
  .card-head, .card-foot { padding: var(--s-4) var(--s-5); }
}

/* Stat tile — a number that means something, not a bare <dt>/<dd>. */
.stat {
  position: relative;
  padding: var(--s-5);
  background: var(--surface);
  border: 1px solid var(--ink-100);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  overflow: hidden;
}
.stat::before {
  content: "";
  position: absolute; inset: 0 auto 0 0;
  width: 3px;
  background: var(--stat-accent, var(--ink-200));
}
.stat-ok { --stat-accent: var(--brand-green); }
.stat-warn { --stat-accent: #e3a008; }
.stat-danger { --stat-accent: var(--danger); }
.stat-info { --stat-accent: var(--brand-blue); }
.stat-label { font-size: var(--t-xs); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-400); }
.stat-value { font-family: var(--font-display); font-size: var(--t-2xl); font-weight: 700; line-height: 1.05; margin-top: var(--s-2); letter-spacing: -0.02em; }
.stat-note { font-size: var(--t-xs); color: var(--ink-400); margin-top: var(--s-1); }

/* Definition rows — replaces the flex-justify-between <dl> soup. */
.deflist { display: grid; gap: 0; }
.deflist > div {
  display: grid;
  /* Capped, not a percentage: on a full-width card 38% pushed the value half a
     screen away from the label it belongs to. */
  grid-template-columns: minmax(120px, 15rem) 1fr;
  gap: var(--s-4);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--ink-050);
  font-size: var(--t-base);
}
.deflist > div:first-child { padding-top: 0; }
.deflist > div:last-child { border-bottom: 0; padding-bottom: 0; }
.deflist dt { color: var(--ink-500); }
.deflist dd { margin: 0; color: var(--ink-900); min-width: 0; overflow-wrap: anywhere; }

@media (max-width: 520px) {
  .deflist > div { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .deflist dt { font-size: var(--t-xs); }
}

/* ── Status pills ───────────────────────────────────────────────────────── */
.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 5px 11px 5px 9px;
  border-radius: var(--r-pill);
  font-size: var(--t-xs);
  font-weight: 600;
  border: 1px solid transparent;
  white-space: nowrap;
}
.pill .dot { width: 7px; height: 7px; border-radius: var(--r-pill); flex-shrink: 0; background: currentColor; }
.pill-ok { color: var(--ok); background: var(--ok-bg); border-color: var(--ok-border); }
.pill-warn { color: var(--warn); background: var(--warn-bg); border-color: var(--warn-border); }
.pill-danger { color: var(--danger); background: var(--danger-bg); border-color: var(--danger-border); }
.pill-info { color: var(--info); background: var(--info-bg); border-color: var(--info-border); }
/* Slate, not the teal-tinted neutral: the status dot inherits this colour, and
   a green-ish dot on "unknown" or "not created" reads as healthy. 5.46:1. */
.pill-neutral { color: #5b6673; background: var(--ink-050); border-color: var(--ink-200); }
.pill-lg { font-size: var(--t-sm); padding: 7px 14px 7px 11px; }

/* "Live" only where something really is live, and never for reduced motion. */
.dot-live { position: relative; }
.dot-live::after {
  content: "";
  position: absolute; inset: -4px;
  border-radius: var(--r-pill);
  border: 1px solid currentColor;
  opacity: 0;
  animation: ping 2.4s var(--ease) infinite;
}
@keyframes ping {
  0% { transform: scale(0.7); opacity: 0.7; }
  70%, 100% { transform: scale(1.6); opacity: 0; }
}

/* ── Alerts ─────────────────────────────────────────────────────────────── */
.alert {
  display: flex;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-radius: var(--r-md);
  border: 1px solid var(--info-border);
  background: var(--info-bg);
  color: var(--info);
  font-size: var(--t-base);
}
.alert-success { border-color: var(--ok-border); background: var(--ok-bg); color: var(--ok); }
.alert-error { border-color: var(--danger-border); background: var(--danger-bg); color: var(--danger); }
.alert-warning { border-color: var(--warn-border); background: var(--warn-bg); color: var(--warn); }
.alert svg { width: 18px; height: 18px; flex-shrink: 0; margin-top: 1px; }
.alert-body { min-width: 0; }
.alert-title { font-weight: 600; }
.alert ul { list-style: none; }

/* Banner — an alert that also carries an action. */
.banner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-5); flex-wrap: wrap;
  padding: var(--s-5);
  border-radius: var(--r-lg);
  border: 1px solid var(--warn-border);
  background: linear-gradient(180deg, #fffaf0, var(--warn-bg));
}

/* ── Forms ──────────────────────────────────────────────────────────────── */
.field { min-width: 0; }
.label {
  display: block;
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--ink-700);
  margin-bottom: var(--s-2);
}
.label-req { color: var(--danger); margin-left: 2px; }
.help { font-size: var(--t-xs); color: var(--ink-400); margin-top: var(--s-2); }
.error { font-size: var(--t-xs); color: var(--danger); margin-top: var(--s-2); font-weight: 500; }

.input, .fi {
  display: block;
  width: 100%;
  min-height: 44px;
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--ink-200);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink-900);
  font-family: inherit;
  font-size: var(--t-md);
  line-height: 1.4;
  outline: none;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
/* Placeholders are text too: ink-300 was 2.07:1. The filled value uses
   ink-900 at 15:1, so the two remain easy to tell apart. */
.input::placeholder, .fi::placeholder { color: var(--ink-400); }
.input:hover, .fi:hover { border-color: var(--ink-300); }
.input:focus, .fi:focus { border-color: var(--brand-blue); box-shadow: var(--sh-focus); }
.input-error, .fi-err { border-color: var(--danger); }
.input-error:focus, .fi-err:focus { box-shadow: 0 0 0 3px rgba(200, 52, 43, 0.22); }

select.input, select.fi, .fi-select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2.5rem;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2355706a' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.85rem center;
}
textarea.input, textarea.fi, .fi-ta {
  min-height: 6rem;
  resize: vertical;
  line-height: 1.6;
}
.fi-flex { width: auto; flex: 1 1 0; min-width: 0; }

/* Checkbox / radio as real chips — a bare checkbox row is the "20 years old"
   look the redesign is meant to remove. */
.choice-set { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.choice {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  min-height: 44px;
  border: 1px solid var(--ink-200);
  border-radius: var(--r-md);
  background: var(--surface);
  cursor: pointer;
  font-size: var(--t-base);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.choice:hover { border-color: var(--ink-300); background: var(--ink-050); }
.choice input { accent-color: var(--brand-blue); width: 18px; height: 18px; margin: 0; cursor: pointer; }
.choice:has(input:checked) {
  border-color: var(--brand-blue);
  background: var(--info-bg);
  box-shadow: inset 0 0 0 1px var(--brand-blue);
}

.input-icon { position: relative; }
.input-icon svg {
  position: absolute; left: 0.9rem; top: 50%;
  transform: translateY(-50%);
  width: 18px; height: 18px;
  color: var(--ink-300);
  pointer-events: none;
}
.input-icon .input, .input-icon .fi { padding-left: 2.7rem; }

.email-row { display: flex; align-items: center; gap: var(--s-2); }
.email-remove {
  display: grid; place-items: center;
  width: 36px; height: 36px; flex-shrink: 0;
  border: 0; border-radius: var(--r-pill);
  background: transparent;
  color: var(--ink-300);
  font-size: 1.25rem; line-height: 1;
  cursor: pointer;
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.email-remove:hover { color: var(--danger); background: var(--danger-bg); }

.form-actions {
  display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap;
  padding-top: var(--s-2);
}
@media (max-width: 520px) {
  .form-actions { flex-direction: column-reverse; align-items: stretch; }
  .form-actions .btn { width: 100%; }
}

/* ── Data table → cards on narrow screens ───────────────────────────────── */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table { width: 100%; border-collapse: collapse; font-size: var(--t-base); }
.table thead th {
  text-align: left;
  padding: var(--s-3) var(--s-5);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-400);
  background: var(--ink-050);
  border-bottom: 1px solid var(--ink-100);
  white-space: nowrap;
}
.table tbody td { padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--ink-050); vertical-align: middle; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr { transition: background var(--dur) var(--ease); }
.table tbody tr:hover { background: var(--ink-050); }
.table .cell-right { text-align: right; }

.row-title { font-weight: 600; color: var(--ink-900); }
.row-title:hover { color: var(--brand-blue); text-decoration: none; }
.row-sub { font-size: var(--t-xs); color: var(--ink-400); margin-top: 2px; }

/* Below 900px the table becomes a stack of cards: each cell keeps its label
   through data-label, so nothing depends on the header row any more. */
@media (max-width: 900px) {
  .table thead { display: none; }
  .table, .table tbody, .table tr, .table td { display: block; width: 100%; }
  .table tbody tr {
    border: 1px solid var(--ink-100);
    border-radius: var(--r-lg);
    background: var(--surface);
    box-shadow: var(--sh-1);
    padding: var(--s-4);
    margin-bottom: var(--s-3);
  }
  .table tbody tr:hover { background: var(--surface); box-shadow: var(--sh-2); }
  .table tbody td { border: 0; padding: var(--s-1) 0; }
  .table tbody td[data-label] {
    display: grid;
    grid-template-columns: 40% 1fr;
    gap: var(--s-3);
    align-items: baseline;
  }
  .table tbody td[data-label]::before {
    content: attr(data-label);
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--ink-400);
  }
  .table td.cell-primary { padding-bottom: var(--s-3); }
  .table td.cell-right { text-align: left; padding-top: var(--s-3); }
  .table-card-hide { display: none !important; }
}

/* ── Toolbar (search / filter above a table) ────────────────────────────── */
.toolbar {
  display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap;
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--ink-100);
}
.toolbar .input-icon { flex: 1 1 220px; min-width: 0; }
.toolbar .input { min-height: 40px; }

/* ── Empty state ────────────────────────────────────────────────────────── */
.empty { padding: var(--s-16) var(--s-6); text-align: center; }
.empty-icon {
  display: grid; place-items: center;
  width: 56px; height: 56px; margin: 0 auto var(--s-4);
  border-radius: var(--r-pill);
  background: var(--ink-050);
  color: var(--ink-300);
}
.empty-icon svg { width: 26px; height: 26px; }
.empty h2 { font-size: var(--t-lg); margin-bottom: var(--s-2); }

/* ── Log viewer ─────────────────────────────────────────────────────────── */
.logview {
  margin: 0;
  padding: var(--s-5);
  max-height: 26rem;
  overflow: auto;
  background: var(--brand-dark);
  color: #cfe3de;
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  line-height: 1.65;
  white-space: pre;
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  -webkit-overflow-scrolling: touch;
}

/* ── Breadcrumb ─────────────────────────────────────────────────────────── */
.crumbs { display: flex; align-items: center; gap: var(--s-2); font-size: var(--t-xs); color: var(--ink-400); }
.crumbs a { color: var(--ink-500); }
.crumbs a:hover { color: var(--brand-blue); text-decoration: none; }
.crumbs .sep { color: var(--ink-300); }

/* ── Page header ────────────────────────────────────────────────────────── */
.page-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--s-5); flex-wrap: wrap;
  margin-bottom: var(--s-6);
}
.page-head h1 { font-size: var(--t-xl); }
.page-head .page-sub { color: var(--ink-500); font-size: var(--t-sm); margin-top: 2px; }
.page-head-actions { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }

@media (max-width: 640px) {
  .page-head-actions { width: 100%; }
  .page-head-actions .btn { flex: 1 1 auto; }
}

/* ── Reduced motion ─────────────────────────────────────────────────────── */
/* Nothing in the previous design honoured this; every animation below opts
   out, including the SVG SMIL on the login page (freeze, not remove). */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── Print ──────────────────────────────────────────────────────────────── */
@media print {
  .appbar, .page-head-actions, .toolbar { display: none !important; }
  body { background: #fff; }
  .card { box-shadow: none; break-inside: avoid; }
}

/* ==========================================================================
   Public / brand surfaces — login, password reset, registration, portal
   The admin keeps a calm dark chrome so data reads first; these pages are
   where the brand blue belongs, full-bleed.
   ========================================================================== */

.brandpage {
  min-height: 100vh;
  min-height: 100dvh;   /* iOS: 100vh sits under the browser chrome */
  background: var(--brand-blue);
  color: #fff;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
}
/* A single soft radial keeps the flat blue from looking like an error page,
   without becoming a gradient-for-its-own-sake. */
.brandpage::before {
  content: "";
  position: absolute;
  inset: -30% -10% auto -10%;
  height: 70%;
  background: radial-gradient(60% 60% at 50% 0%, rgba(59, 216, 149, 0.18), transparent 70%);
  pointer-events: none;
}
.brandpage > * { position: relative; }

.brandpage-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-5) var(--s-6);
}
.brandpage-main {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--s-6) var(--s-6) var(--s-10);
}
/* Admin chrome had no footer at all; this one carries the running release. */
.page-foot {
  border-top: 1px solid var(--ink-100);
  padding: var(--s-4) 0;
  margin-top: var(--s-8);
}
.foot-note { font-size: var(--t-xs); color: var(--ink-400); }

.brandpage-foot {
  padding: var(--s-6);
  text-align: center;
  font-size: var(--t-sm);
  color: rgba(255, 255, 255, 0.85);
}

.brand-logo svg { width: 132px; height: auto; display: block; }
.brand-logo-sm svg { width: 96px; }

.brand-card { width: 100%; max-width: 400px; }
.brand-card h1 {
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  font-weight: 700;
  color: #fff;
  letter-spacing: -0.02em;
}
.brand-lede { color: rgba(255, 255, 255, 0.88); font-size: var(--t-md); line-height: 1.6; }

/* Inputs on the brand background: white fields, green focus — the blue focus
   ring would vanish against the blue. */
.brandpage .input, .brandpage .fi {
  border-color: transparent;
  min-height: 48px;
  font-size: var(--t-md);
}
.brandpage .input:focus, .brandpage .fi:focus {
  border-color: transparent;
  box-shadow: var(--sh-focus-green);
}
.brandpage .label { color: rgba(255, 255, 255, 0.9); }
.brandpage a { color: rgba(255, 255, 255, 0.9); }
.brandpage a:hover { color: #fff; }
.brandpage .error, .brandpage .form-error { color: #ffc9c4; }

.brand-status-icon {
  display: grid; place-items: center;
  width: 64px; height: 64px;
  margin: 0 auto var(--s-5);
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
}
.brand-status-icon svg { width: 30px; height: 30px; }
.brand-status-icon.is-ok { background: rgba(59, 216, 149, 0.2); color: var(--brand-green); }

/* The support block appears on both the blue brand pages and the light
   registration/portal pages. It defaults to the light-background colours;
   white links were unreadable on white until this was split. */
.support {
  display: flex; align-items: center; justify-content: center;
  gap: var(--s-3); flex-wrap: wrap;
  font-size: var(--t-sm);
}
.support a { color: var(--ink-500); }
.support .sep { color: var(--ink-300); }
.support-lead { font-size: var(--t-sm); color: var(--ink-500); }

.on-brand .support a, .brandpage .support a { color: rgba(255, 255, 255, 0.92); }
.on-brand .support a:hover, .brandpage .support a:hover { color: #fff; }
.on-brand .support .sep, .brandpage .support .sep { color: rgba(255, 255, 255, 0.45); }
.on-brand .support-lead, .brandpage .support-lead { color: rgba(255, 255, 255, 0.85); }

/* ── Login: split layout ────────────────────────────────────────────────── */
.login-split { display: grid; grid-template-columns: 1fr 460px; min-height: 100vh; min-height: 100dvh; }
/* Diagram and caption are one centred column. The caption used to be pinned to
   the bottom corner, which read as two unrelated things on one white field. */
.login-visual {
  position: relative;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-8);
  padding: var(--s-10);
  overflow: hidden;
}
.login-visual-caption { max-width: 30rem; text-align: center; }
.login-visual-caption h2 {
  font-family: var(--font-display);
  font-size: var(--t-xl);
  color: var(--ink-900);
  letter-spacing: -0.02em;
}
.login-visual-caption p { color: var(--ink-500); font-size: var(--t-base); margin-top: var(--s-3); }
.login-panel { display: flex; flex-direction: column; }

@media (max-width: 1024px) {
  .login-split { grid-template-columns: 1fr; }
  .login-visual { display: none; }
}

/* ── Registration wizard ────────────────────────────────────────────────── */
/* The steps used to be pills inside a card of their own, stacked above a card
   holding the form — the same container twice, plus a row of dots repeating
   what the pills already said. A rail alongside the form carries the same
   information in space that was empty, drops a panel, and leaves room to say
   what each step actually asks for. */
.wizard {
  display: grid;
  grid-template-columns: 17rem minmax(0, 1fr);
  gap: var(--s-8);
  align-items: start;
}
/* Sticky: on the longer steps the form scrolls past the rail, and losing your
   place in a five-step form is the whole problem a stepper exists to solve. */
.wizard-rail { position: sticky; top: var(--s-5); }

.stepper { list-style: none; margin: 0; padding: 0; }
.stepper-item { position: relative; }
/* Connector, drawn behind the markers and stopping at the last one. */
.stepper-item:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 15px;
  top: 34px;
  /* Past the item's own edge so the segments meet the next marker, which paints
     its own background over the end of the line. */
  bottom: -6px;
  width: 2px;
  border-radius: 2px;
  background: var(--ink-100);
}
.stepper-item.is-done:not(:last-child)::before { background: var(--brand-green); }

.stepper-btn {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  width: 100%;
  padding: var(--s-2) var(--s-2) var(--s-4) 0;
  border: 0;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
  color: var(--ink-400);
  transition: color var(--dur) var(--ease);
}
.stepper-btn:hover:not(:disabled) { color: var(--ink-700); }
.stepper-btn:disabled { cursor: not-allowed; opacity: 0.55; }

.stepper-marker {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 32px; height: 32px;
  border-radius: var(--r-pill);
  border: 2px solid var(--ink-200);
  background: var(--surface);
  color: var(--ink-400);
  font-size: var(--t-sm);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  transition: all var(--dur) var(--ease);
}
.stepper-marker .tick { display: none; width: 15px; height: 15px; }

.stepper-item.is-active .stepper-marker {
  border-color: var(--brand-blue);
  background: var(--brand-blue);
  color: #fff;
  box-shadow: 0 0 0 4px rgba(52, 82, 248, 0.14);
}
.stepper-item.is-done .stepper-marker {
  border-color: var(--brand-green);
  background: var(--brand-green);
  color: var(--brand-dark);
}
.stepper-item.is-done .stepper-marker .num { display: none; }
.stepper-item.is-done .stepper-marker .tick { display: block; }

.stepper-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding-top: 4px; }
.stepper-title { font-size: var(--t-base); font-weight: 600; }
.stepper-item.is-active .stepper-title { color: var(--brand-blue-700); }
.stepper-item.is-done .stepper-title { color: var(--ink-700); }
.stepper-hint { font-size: var(--t-xs); color: var(--ink-400); }

/* Compact indicator for the narrow layout, where a vertical rail would push
   the form off the first screen. */
.wizard-compact { display: none; }
.wizard-track {
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--ink-100);
  overflow: hidden;
}
.wizard-fill {
  height: 100%;
  width: 20%;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--brand-blue), var(--brand-green));
  transition: width 260ms var(--ease);
}
.wizard-compact-label {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3);
  margin-top: var(--s-3);
  font-size: var(--t-sm);
}
.wizard-compact-step { font-weight: 600; }
.wizard-compact-count { color: var(--ink-400); font-variant-numeric: tabular-nums; }

@media (max-width: 900px) {
  .wizard { grid-template-columns: minmax(0, 1fr); gap: var(--s-5); }
  .wizard-rail { position: static; }
  .stepper { display: none; }
  .wizard-compact { display: block; }
}

.step-panel { display: none; }
.step-panel.is-active { display: block; animation: step-in 220ms var(--ease); }
@keyframes step-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

/* ── Portal (customer-facing) ───────────────────────────────────────────── */
.portal-hero {
  background: var(--brand-blue);
  color: #fff;
  /* Deep enough that the card below can lift into it and still leave a band of
     blue: with a shallower hero the overlap reads as a layout accident. */
  padding: var(--s-6) 0 var(--s-12);
  position: relative;
  overflow: hidden;
}
.portal-hero::before {
  content: "";
  position: absolute;
  inset: auto -10% -60% 40%;
  height: 120%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(59, 216, 149, 0.22), transparent 70%);
  pointer-events: none;
}
.portal-hero > * { position: relative; }
.portal-hero h1 {
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  color: #fff;
  margin-top: var(--s-6);
}
.portal-hero .portal-sub { color: rgba(255, 255, 255, 0.88); margin-top: var(--s-2); }
/* The content was pulled up into the hero with a negative margin. The hero is
   positioned, so it painted over the card's background while the card's own
   children still showed through — the wizard tabs appeared to float on the
   blue. A positive gap has no stacking order to get wrong, so the decoration
   goes rather than getting a z-index patch. */
.portal-body { margin-top: var(--s-6); padding-bottom: var(--s-16); }

/* ==========================================================================
   Login illustration — two lanes, one direction each
   The first attempt pulsed concentric circles behind rounded-square nodes; the
   two shapes fought each other and a frozen frame looked like a blob. Two
   labelled lanes state "both directions" even with every animation stopped,
   which is what a still screenshot — or a reduced-motion visitor — sees.
   ========================================================================== */
.flow { width: 100%; max-width: 40rem; height: auto; }
.flow-node { fill: #fff; stroke: var(--ink-100); stroke-width: 1.5; }
.flow-lane { stroke: var(--ink-100); stroke-width: 1.5; }
.flow-label { font-family: var(--font-text); font-size: 14px; font-weight: 600; fill: var(--ink-900); }
.flow-sub { font-family: var(--font-text); font-size: 11.5px; fill: var(--ink-400); }
.flow-lane-label { font-family: var(--font-text); font-size: 10.5px; font-weight: 600; letter-spacing: 0.06em; }

.flow-packet { animation: flow-right 4.5s linear infinite; }
.flow-packet-back { animation-name: flow-left; }
@keyframes flow-right {
  0%   { transform: translateX(0);     opacity: 0; }
  15%  { opacity: 1; }
  85%  { opacity: 1; }
  100% { transform: translateX(150px); opacity: 0; }
}
@keyframes flow-left {
  0%   { transform: translateX(0);      opacity: 0; }
  15%  { opacity: 1; }
  85%  { opacity: 1; }
  100% { transform: translateX(-150px); opacity: 0; }
}

/* Parked at the lane's start rather than hidden: the arrows already carry the
   meaning, and a stray dot mid-lane would look like a rendering fault. */
@media (prefers-reduced-motion: reduce) {
  .flow-packet { animation: none; opacity: 1; }
}

/* ==========================================================================
   Touch targets
   The compact variants are sized for a mouse. On a touch screen they fall
   under the ~44px a finger needs, and these are the controls that matter most
   on a phone: start/stop an instance, remove an address, switch language.
   ========================================================================== */
@media (hover: none), (max-width: 640px) {
  .btn-sm { min-height: 44px; padding: 0 var(--s-4); }
  .segmented button { padding: 9px 14px; }
  .email-remove { width: 44px; height: 44px; }
  .stepper-btn { padding-top: var(--s-3); padding-bottom: var(--s-5); }
  /* The card rows on the customer list are the tap target for the whole row. */
  .table tbody tr { padding: var(--s-5); }
  .table td.cell-right .btn { width: 100%; }
}

/* Long, unbreakable values — tenant ids, API keys, webhook URLs — are the
   usual source of a page that scrolls sideways on a phone. */
.mono, .deflist dd, .row-sub { overflow-wrap: anywhere; }

/* Nothing may push the page sideways; wide content scrolls inside its own box
   (.table-wrap, .logview) rather than dragging the whole layout with it. */
html, body { overflow-x: hidden; }

/* Per-mailbox sync activity. One block per mailbox, one row per direction.
   `-cold` marks a mailbox that has never synced in either direction — the shape
   of the complaint the panel exists to answer, so it should be findable without
   reading every row. */
.act-mailbox {
  padding: var(--s-3) 0;
  border-top: 1px solid var(--ink-100);
}
.act-mailbox:first-child { border-top: 0; padding-top: 0; }
.act-mailbox-cold { background: var(--warn-bg); border-radius: var(--r-sm); padding: var(--s-3); }
.act-email { font-weight: 600; margin-bottom: var(--s-2); }
.act-dir { display: flex; align-items: baseline; gap: var(--s-2); flex-wrap: wrap; padding: 2px 0; }
