/* ═══════════════════════════════════════════════════════════════════════════
   CIM-EDGE — Design System v3  ·  Light-first, token-driven, dark-mode ready
   Brand: #1565c0 (blue) · #010409 (ink) · #e6edf3 (paper)
   Type:  Space Grotesk (display) · Inter (UI/body) · JetBrains Mono (data)
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─── Tokens · LIGHT (default) ─────────────────────────────────────────────── */
:root {
  /* brand constants */
  --brand-blue:#1565c0; --brand-blue-600:#1976d2; --brand-blue-700:#0f4c91;
  --brand-ink:#010409;  --brand-paper:#e6edf3;
  /* fixed button blue — identical in light & dark so blue buttons never drift */
  --btn-blue:#1565c0; --btn-blue-hover:#1976d2;

  /* surfaces */
  --bg:#f5f8fc;            /* page */
  --bg-tint:#eef3f9;       /* alternating sections */
  --surface:#ffffff;       /* cards */
  --surface-2:#f6f9fd;     /* elevated alt / inputs */
  --surface-3:#eef3f9;     /* hover wells */
  --surface-inset:#f1f5fa;

  /* lines + text */
  --border:#dde6f1;
  --border-strong:#c6d3e2;
  --text:#0b1726;          /* primary (≈ brand ink, softened) */
  --text-secondary:#475569;
  --text-muted:#8595a8;
  --on-accent:#ffffff;

  /* accent */
  --accent:#1565c0; --accent-hover:#0f4c91; --accent-active:#0c3d75;
  --accent-soft:rgba(21,101,192,.10);
  --accent-soft-2:rgba(21,101,192,.16);
  --accent-ring:rgba(21,101,192,.32);
  --accent-text:#1257a8;   /* accent text that passes contrast on white */

  /* semantic */
  --success:#1a7f4b; --success-bg:rgba(26,127,75,.10); --success-border:rgba(26,127,75,.28);
  --danger:#c4322e;  --danger-bg:rgba(196,50,46,.10);  --danger-border:rgba(196,50,46,.28);
  --warning:#9a6700; --warning-bg:rgba(154,103,0,.12); --warning-border:rgba(154,103,0,.30);
  --info:#1565c0;    --info-bg:rgba(21,101,192,.10);   --info-border:rgba(21,101,192,.28);

  /* effects */
  --shadow-xs:0 1px 2px rgba(13,30,55,.06);
  --shadow-sm:0 1px 3px rgba(13,30,55,.08), 0 1px 2px rgba(13,30,55,.04);
  --shadow-md:0 4px 12px rgba(13,30,55,.08), 0 2px 4px rgba(13,30,55,.05);
  --shadow-lg:0 14px 40px rgba(13,30,55,.12), 0 4px 12px rgba(13,30,55,.06);
  --shadow-glow:0 8px 30px rgba(21,101,192,.22);
  --radius:14px; --radius-sm:10px; --radius-lg:20px; --radius-pill:9999px;

  --font-display:'Space Grotesk','Inter',system-ui,sans-serif;
  --font-sans:'Inter',system-ui,-apple-system,'Segoe UI',sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,'SFMono-Regular',Menlo,monospace;

  --header-h:64px;
  color-scheme:light;

  /* Backward-compat aliases (old design-system token names used across many
     app/admin pages). These reference the new themed tokens, so they adapt to
     light/dark automatically — no need to touch every legacy page. */
  --bg-primary:var(--bg);
  --bg-secondary:var(--surface);
  --bg-surface:var(--surface);
  --bg-elevated:var(--surface-2);
  --text-primary:var(--text);
  --accent-subtle:var(--accent-soft);
  --success-text:var(--success);
  --danger-text:var(--danger);
  --warning-text:var(--warning);
  --info-text:var(--info);
}

/* ─── Tokens · DARK ────────────────────────────────────────────────────────── */
[data-theme="dark"] {
  --bg:#010409;
  --bg-tint:#0a0f17;
  --surface:#0d1117;
  --surface-2:#161b22;
  --surface-3:#1c242e;
  --surface-inset:#11161d;

  --border:#222b36;
  --border-strong:#30363d;
  --text:#e6edf3;
  --text-secondary:#9fb1c4;
  --text-muted:#69788b;
  --on-accent:#ffffff;

  --accent:#4f9bff; --accent-hover:#6fb0ff; --accent-active:#3b86ec;
  --accent-soft:rgba(79,155,255,.14);
  --accent-soft-2:rgba(79,155,255,.22);
  --accent-ring:rgba(79,155,255,.38);
  --accent-text:#7cb4ff;

  --success:#3fb950; --success-bg:rgba(63,185,80,.14); --success-border:rgba(63,185,80,.30);
  --danger:#f85149;  --danger-bg:rgba(248,81,73,.14);  --danger-border:rgba(248,81,73,.30);
  --warning:#e3b341; --warning-bg:rgba(227,179,65,.14);--warning-border:rgba(227,179,65,.30);
  --info:#58a6ff;    --info-bg:rgba(88,166,255,.14);   --info-border:rgba(88,166,255,.30);

  --shadow-xs:0 1px 2px rgba(0,0,0,.4);
  --shadow-sm:0 1px 3px rgba(0,0,0,.5);
  --shadow-md:0 6px 18px rgba(0,0,0,.55);
  --shadow-lg:0 18px 50px rgba(0,0,0,.6);
  --shadow-glow:0 8px 34px rgba(79,155,255,.28);
  color-scheme:dark;
}

/* ─── Reset / base ─────────────────────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}
html{font-size:16px;scroll-behavior:smooth;-webkit-text-size-adjust:100%;scrollbar-gutter:stable}
body{
  margin:0;font-family:var(--font-sans);background:var(--bg);color:var(--text);
  line-height:1.6;min-height:100vh;-webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  transition:background-color .3s ease,color .3s ease;
}
h1,h2,h3,h4,h5{font-family:var(--font-display);font-weight:700;line-height:1.12;letter-spacing:-.02em;color:var(--text);margin:0}
p{margin:0}
a{color:inherit;text-decoration:none}
img,svg,video{display:block;max-width:100%}
::selection{background:var(--accent-soft-2);color:var(--text)}
.font-mono,.tabular{font-family:var(--font-mono);font-variant-numeric:tabular-nums}

/* scrollbars */
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--border-strong);border-radius:9999px;border:2px solid var(--bg)}
::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}

/* focus ring */
:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent-ring);border-radius:6px}
a:focus-visible,button:focus-visible{border-radius:8px}

/* ─── Layout helpers ───────────────────────────────────────────────────────── */
.nav-page-content{padding-top:var(--header-h)}
/* Auth pages: rich, theme-adaptive background + centered card */
:root{--auth-base:#eef3fb;--auth-glow1:rgba(21,101,192,.18);--auth-glow2:rgba(47,138,240,.12)}
[data-theme="dark"]{--auth-base:#010409;--auth-glow1:rgba(21,101,192,.5);--auth-glow2:rgba(11,42,82,.65)}
.auth-bg{position:fixed;inset:0;z-index:-1;overflow:hidden;background:
  radial-gradient(ellipse 70% 60% at 22% 8%,var(--auth-glow1),transparent 55%),
  radial-gradient(ellipse 65% 60% at 92% 95%,var(--auth-glow2),transparent 55%),
  var(--auth-base)}
.auth-bg::after{content:"";position:absolute;inset:0;background-image:linear-gradient(var(--border) 1px,transparent 1px),linear-gradient(90deg,var(--border) 1px,transparent 1px);background-size:60px 60px;opacity:.25;-webkit-mask-image:radial-gradient(ellipse 60% 50% at 50% 30%,#000,transparent 75%);mask-image:radial-gradient(ellipse 60% 50% at 50% 30%,#000,transparent 75%)}
.page-hero{padding:4.5rem 0 3rem;position:relative;overflow:hidden}
.legal-prose{color:var(--text-secondary);line-height:1.8;font-size:.95rem}
.legal-prose h2{font-size:1.3rem;margin:2.25rem 0 .85rem;color:var(--text)}
.legal-prose h3{font-size:1.05rem;margin:1.75rem 0 .6rem;color:var(--text)}
.legal-prose p{margin-bottom:1rem}
.legal-prose ul{margin:0 0 1rem 1.25rem;list-style:disc}
.legal-prose li{margin-bottom:.5rem}
.legal-prose a{color:var(--accent-text);text-decoration:underline;text-underline-offset:2px}
.container{max-width:1200px;margin:0 auto;padding:0 1.5rem}
.container-wide{max-width:1320px;margin:0 auto;padding:0 1.5rem}
.section{padding:5.5rem 0}
.section-tint{background:var(--bg-tint)}
.eyebrow{display:inline-flex;align-items:center;gap:.5rem;font-size:.75rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--accent-text)}
.section-title{font-size:clamp(1.8rem,3.2vw,2.7rem);font-weight:700;letter-spacing:-.03em}
.lead{font-size:1.0625rem;color:var(--text-secondary);line-height:1.7}
.text-primary{color:var(--text)!important}
.text-secondary{color:var(--text-secondary)!important}
.text-muted{color:var(--text-muted)!important}
.text-accent{color:var(--accent-text)!important}

/* ─── Buttons ──────────────────────────────────────────────────────────────── */
/* Base applies to .btn AND each standalone modifier, so legacy markup that
   writes just `btn-primary` (no `.btn`) still gets full button styling. */
.btn,.btn-primary,.btn-secondary,.btn-outline,.btn-ghost,.btn-danger{
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
  padding:.625rem 1.1rem;font-size:.9rem;font-weight:600;font-family:inherit;
  border-radius:var(--radius-sm);border:1px solid transparent;cursor:pointer;
  text-decoration:none;white-space:nowrap;line-height:1;
  transition:background-color .18s ease,border-color .18s ease,color .18s ease,box-shadow .18s ease,transform .12s ease;
}
.btn:active,.btn-primary:active,.btn-secondary:active,.btn-outline:active,.btn-ghost:active,.btn-danger:active{transform:translateY(1px) scale(.99)}
.btn:disabled,.btn-primary:disabled,.btn-secondary:disabled,.btn-outline:disabled,.btn-ghost:disabled,.btn-danger:disabled{opacity:.5;cursor:not-allowed}
.btn svg,.btn-primary svg,.btn-secondary svg,.btn-outline svg,.btn-ghost svg,.btn-danger svg{width:1.05em;height:1.05em;flex-shrink:0}
/* Blue buttons stay company blue + white text in BOTH themes (not the
   lightened dark-mode accent used for links/icons). */
.btn-primary{background:var(--btn-blue);color:#fff!important;box-shadow:var(--shadow-sm)}
.btn-primary:hover{background:var(--btn-blue-hover);color:#fff;box-shadow:var(--shadow-glow)}
.btn-primary svg{color:#fff}
.btn-secondary{background:var(--accent-soft);color:var(--accent-text);border-color:var(--accent);box-shadow:var(--shadow-xs)}
.btn-secondary:hover{background:var(--surface-3);border-color:var(--text-muted)}
.btn-outline{background:var(--accent-soft);color:var(--accent-text);border-color:var(--accent)}
.btn-outline:hover{border-color:var(--accent);color:var(--accent-text);background:var(--accent-soft)}
/* Was transparent, which left ghost buttons looking unfinished beside the
   outline and danger buttons that sit next to them everywhere. */
.btn-ghost{background:var(--accent-soft);color:var(--accent-text);border-color:var(--border-strong)}
.btn-ghost:hover{background:var(--surface-3);color:var(--text)}
.btn-danger{background:var(--danger-bg);color:var(--danger);border-color:var(--danger-border)}
.btn-danger:hover{background:var(--danger);color:#fff;border-color:var(--danger)}
.btn-sm{padding:.4rem .75rem;font-size:.8125rem}
.btn-lg{padding:.85rem 1.6rem;font-size:1rem;border-radius:var(--radius)}
.btn-full{width:100%}

/* ─── Cards ────────────────────────────────────────────────────────────────── */
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:1.4rem;box-shadow:var(--shadow-sm)}
.card-pad-lg{padding:1.75rem}
.card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1rem;gap:.75rem}
.card-title{font-family:var(--font-display);font-size:1rem;font-weight:600;color:var(--text);letter-spacing:-.01em}
.stat-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:1.35rem;box-shadow:var(--shadow-sm);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease}
.stat-card:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:var(--border-strong)}
.stat-value{font-family:var(--font-display);font-size:1.9rem;font-weight:700;letter-spacing:-.02em;color:var(--text)}

/* glassy / feature cards (marketing) */
.glass-card{
  background:color-mix(in srgb,var(--surface) 78%,transparent);
  border:1px solid var(--border);border-radius:var(--radius);padding:1.25rem;
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);box-shadow:var(--shadow-md);
}
.feature-card{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  padding:1.6rem;box-shadow:var(--shadow-sm);
  transition:transform .25s cubic-bezier(.2,.7,.2,1),box-shadow .25s ease,border-color .25s ease;
  position:relative;overflow:hidden;
}
.feature-card::after{content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;background:linear-gradient(135deg,var(--accent-soft-2),transparent 45%);-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:0;transition:opacity .25s ease;pointer-events:none}
.feature-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg);border-color:transparent}
.feature-card:hover::after{opacity:1}

/* ─── Tables ───────────────────────────────────────────────────────────────── */
.table-wrap{overflow-x:auto;border-radius:var(--radius);border:1px solid var(--border);background:var(--surface);box-shadow:var(--shadow-sm)}
.data-table{width:100%;border-collapse:collapse;font-size:.875rem}
.data-table th{padding:.8rem 1rem;text-align:left;font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-muted);background:var(--surface-2);border-bottom:1px solid var(--border)}
.data-table td{padding:.85rem 1rem;color:var(--text);border-bottom:1px solid var(--border);vertical-align:middle}
.data-table tbody tr:last-child td{border-bottom:none}
.data-table tbody tr{transition:background-color .12s ease}
.data-table tbody tr:hover td{background:var(--surface-3)}

/* ─── Badges / pills ───────────────────────────────────────────────────────── */
.badge{display:inline-flex;align-items:center;gap:.3rem;padding:.25rem .6rem;font-size:.72rem;font-weight:600;border-radius:var(--radius-pill);white-space:nowrap;line-height:1.2}
.badge-success,.badge-active,.badge-in-live{background:var(--success-bg);color:var(--success)}
.badge-danger,.badge-breached,.badge-stopped{background:var(--danger-bg);color:var(--danger)}
.badge-warning,.badge-not-started,.badge-batch-testing{background:var(--warning-bg);color:var(--warning)}
.badge-info,.badge-optim-done,.badge-rc-passed,.badge-student{background:var(--info-bg);color:var(--info)}
.badge-muted,.badge-retired{background:var(--surface-3);color:var(--text-secondary)}
.badge-accent{background:var(--accent-soft);color:var(--accent-text)}
.badge-admin{background:var(--warning-bg);color:var(--warning)}
.pill{display:inline-flex;align-items:center;gap:.45rem;padding:.4rem .85rem;border-radius:var(--radius-pill);border:1px solid var(--border);background:var(--surface);font-size:.8rem;font-weight:500;color:var(--text-secondary);box-shadow:var(--shadow-xs)}

/* ─── Forms ────────────────────────────────────────────────────────────────── */
.form-label{display:block;font-size:.82rem;font-weight:600;color:var(--text-secondary);margin-bottom:.4rem}
.form-input,.form-select,textarea.form-input{
  width:100%;padding:.65rem .9rem;background:var(--surface-2);border:1px solid var(--border-strong);
  border-radius:var(--radius-sm);color:var(--text);font-size:.95rem;font-family:inherit;
  transition:border-color .15s ease,box-shadow .15s ease,background-color .15s ease;outline:none;
}
.form-input:focus,.form-select:focus,textarea.form-input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-ring);background:var(--surface)}
.form-input::placeholder{color:var(--text-muted)}
textarea.form-input{resize:vertical;min-height:110px;line-height:1.6}
.form-hint{font-size:.78rem;color:var(--text-muted);margin-top:.35rem}
/* File input styled to match the design system (the "Choose file" button used to
   be raw Tailwind slate, inconsistent with the site's buttons in both themes). */
.form-file{display:block;width:100%;font-size:.85rem;color:var(--text-secondary)}
.form-file::file-selector-button{
  margin-right:.9rem;padding:.5rem .9rem;font-family:inherit;font-size:.8125rem;font-weight:600;
  border:1px solid var(--accent);border-radius:var(--radius-sm);
  background:var(--accent-soft);color:var(--accent-text);cursor:pointer;
  transition:background-color .18s ease,border-color .18s ease,color .18s ease;
}
.form-file::file-selector-button:hover{background:var(--surface-3);border-color:var(--text-muted)}

/* ─── Progress ─────────────────────────────────────────────────────────────── */
.progress-bar{height:6px;background:var(--surface-3);border-radius:9999px;overflow:hidden}
.progress-fill{height:100%;background:linear-gradient(90deg,var(--accent),var(--brand-blue-600));border-radius:9999px;transition:width .5s cubic-bezier(.2,.7,.2,1)}

/* ─── Avatar ───────────────────────────────────────────────────────────────── */
.avatar{width:2.25rem;height:2.25rem;border-radius:9999px;background:linear-gradient(135deg,var(--accent),var(--brand-blue-700));color:#fff;font-size:.9rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0;box-shadow:var(--shadow-xs)}
.avatar-sm{width:1.75rem;height:1.75rem;font-size:.75rem}
.avatar-lg{width:2.75rem;height:2.75rem;font-size:1.05rem}
/* A member photo sits inside the same circle the initial uses. The initial
   stays underneath, so if the file ever goes missing the fallback is already
   drawn rather than leaving a hole. */
.avatar.has-photo{position:relative;overflow:hidden;background:var(--surface-2)}
.avatar.has-photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:inherit}
.avatar>i{font-style:normal;line-height:1}
.avatar.is-reply{width:1.5rem;height:1.5rem;font-size:.65rem}

/* ─── Alerts ───────────────────────────────────────────────────────────────── */
.alert{display:flex;align-items:flex-start;gap:.65rem;padding:.9rem 1.05rem;border-radius:var(--radius-sm);font-size:.875rem;border:1px solid transparent;line-height:1.5}
.alert svg{width:1.1rem;height:1.1rem;flex-shrink:0;margin-top:.1rem}
.alert-success{background:var(--success-bg);color:var(--success);border-color:var(--success-border)}
.alert-danger{background:var(--danger-bg);color:var(--danger);border-color:var(--danger-border)}
.alert-warning{background:var(--warning-bg);color:var(--warning);border-color:var(--warning-border)}
.alert-info{background:var(--info-bg);color:var(--info);border-color:var(--info-border)}

/* ─── Tabs ─────────────────────────────────────────────────────────────────── */
.tab-bar{display:flex;gap:.25rem;border-bottom:1px solid var(--border)}
.tab-btn{padding:.65rem 1rem;font-size:.9rem;font-weight:600;color:var(--text-secondary);background:transparent;border:none;border-bottom:2px solid transparent;cursor:pointer;transition:color .15s ease,border-color .15s ease;margin-bottom:-1px;font-family:inherit}
.tab-btn:hover{color:var(--text)}
.tab-btn.active{color:var(--accent-text);border-bottom-color:var(--accent)}

/* ─── Empty state / icon wrap / spinner ────────────────────────────────────── */
.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem 1.5rem;text-align:center;color:var(--text-secondary)}
.empty-state svg{margin-bottom:1rem;opacity:.45;width:2.5rem;height:2.5rem}
.icon-wrap{width:2.4rem;height:2.4rem;border-radius:var(--radius-sm);display:inline-flex;align-items:center;justify-content:center;background:var(--accent-soft);color:var(--accent-text);flex-shrink:0}
.spinner{width:1.25rem;height:1.25rem;border:2px solid var(--border-strong);border-top-color:var(--accent);border-radius:50%;animation:spin .6s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}

/* ─── Icon button + public nav (defined here so Tailwind utilities, injected
       later by the CDN, can still override e.g. md:hidden) ────────────────── */
.icon-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:10px;color:var(--text-secondary);background:transparent;border:none;cursor:pointer;transition:background .15s,color .15s}
.icon-btn:hover{background:var(--surface-3);color:var(--text)}
.pubnav{position:fixed;top:0;left:0;right:0;z-index:50;background:color-mix(in srgb,var(--surface) 82%,transparent);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border-bottom:1px solid transparent;transition:border-color .25s ease,box-shadow .25s ease,background-color .25s ease}
.pubnav.scrolled{border-bottom-color:var(--border);box-shadow:var(--shadow-sm)}
.pubnav__link{position:relative;font-size:.9rem;font-weight:500;color:var(--text-secondary);transition:color .15s ease;padding:.25rem 0}
.pubnav__link:hover{color:var(--text)}
.pubnav__link.is-active{color:var(--text)}
.pubnav__link.is-active::after{content:"";position:absolute;left:0;right:0;bottom:-6px;height:2px;border-radius:2px;background:var(--accent)}
[x-cloak]{display:none!important}

/* ═══ APP SHELL (member + admin) ═══════════════════════════════════════════ */
.app-shell{display:flex;min-height:100vh;background:var(--bg)}
.sidebar{position:fixed;left:0;top:0;bottom:0;width:264px;background:var(--surface);border-right:1px solid var(--border);display:flex;flex-direction:column;z-index:30;transition:width .16s ease,transform .18s ease;overflow:hidden}
.sidebar.collapsed{width:72px}
@media(max-width:1023px){.sidebar{transform:translateX(-100%)}.sidebar.mobile-open{transform:translateX(0);box-shadow:var(--shadow-lg)}}
/* Stop scroll chaining: flicking the nav past its end scrolled the page behind it,
   which reads as the whole sidebar "moving up". */
.sidebar nav{overscroll-behavior:none;-webkit-overflow-scrolling:touch}
.nav-section-label{padding:1rem .85rem .35rem;font-size:.66rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted)}
.nav-icon{width:1.15rem;height:1.15rem;flex-shrink:0;color:var(--text-muted);transition:color .15s}
.nav-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav-item{display:flex;align-items:center;gap:.7rem;padding:.6rem .8rem;border-radius:var(--radius-sm);font-size:.875rem;font-weight:500;color:var(--text-secondary);text-decoration:none;transition:background .15s,color .15s;white-space:nowrap;overflow:hidden;margin-bottom:2px;position:relative}
.nav-item:hover{background:var(--surface-3);color:var(--text)}
.nav-item:hover .nav-icon{color:var(--text)}
.nav-item.active{background:var(--accent-soft);color:var(--accent-text);font-weight:600}
.nav-item.active .nav-icon{color:var(--accent)}
.nav-item.active::before{content:"";position:absolute;left:0;top:18%;bottom:18%;width:3px;border-radius:0 3px 3px 0;background:var(--accent)}
.main-content{flex:1;min-width:0;margin-left:264px;min-height:100vh;display:flex;flex-direction:column;background:var(--bg);transition:margin-left .16s ease}
/* Top loading line during htmx navigation (see head.php). */
#cim-nav-progress{position:fixed;top:0;left:0;height:3px;width:0;z-index:9999;pointer-events:none;opacity:0;background:linear-gradient(90deg,var(--btn-blue),#42a5f5);box-shadow:0 0 10px rgba(21,101,192,.5);border-radius:0 3px 3px 0;transition:width .4s ease,opacity .3s ease}
#cim-nav-progress.active{opacity:1}
#cim-nav-progress.done{transition:width .2s ease,opacity .35s ease}
/* JIT safety net. The admin cards (tools / content) are styled with these
   arbitrary Tailwind classes. The Play CDN normally generates them by scanning
   the DOM, but an htmx <body>-swap can race that scan on live, leaving cards
   with no background/border until a hard refresh. Declaring them as real CSS —
   identical to what the JIT emits — makes that layout immune to the race. */
.bg-\[var\(--bg-surface\)\]{background-color:var(--bg-surface)}
.bg-\[var\(--bg-elevated\)\]{background-color:var(--bg-elevated)}
.bg-\[var\(--bg-primary\)\]{background-color:var(--bg-primary)}
.bg-\[var\(--accent\)\]{background-color:var(--accent)}
.border-\[var\(--border\)\]{border-color:var(--border)}
.border-\[var\(--accent\)\]{border-color:var(--accent)}
.text-\[var\(--accent\)\]{color:var(--accent)}
.ring-\[var\(--accent\)\]{--tw-ring-color:var(--accent)}
.text-\[10px\]{font-size:10px}
.text-\[11px\]{font-size:11px}
/* gentle page-enter fade (opacity only — no movement, so the layout never shifts) */
.main-content > main{animation:cim-page-in .16s ease both}
@keyframes cim-page-in{from{opacity:.6}to{opacity:1}}
.main-content.collapsed{margin-left:72px}
@media(max-width:1023px){.main-content{margin-left:0!important}}
.app-header{position:sticky;top:0;z-index:10;display:flex;align-items:center;height:var(--header-h);padding:0 1.25rem;gap:.75rem;background:color-mix(in srgb,var(--surface) 88%,transparent);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border-bottom:1px solid var(--border)}

/* ═══ MARKETING / EFFECTS ══════════════════════════════════════════════════ */
.gradient-text{background:linear-gradient(105deg,var(--brand-blue-600),var(--accent) 45%,#0a3e7d);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}
[data-theme="dark"] .gradient-text{background:linear-gradient(105deg,#7cb4ff,#4f9bff 50%,#2f8af0);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.glow-cyan,.glow-accent{box-shadow:var(--shadow-glow)}
.text-glow{text-shadow:0 0 30px var(--accent-ring)}
.section-divider{height:1px;background:linear-gradient(90deg,transparent,var(--border) 18%,var(--border) 82%,transparent);border:0;margin:0}
.hero-aurora{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0}
.hero-aurora::before,.hero-aurora::after{content:"";position:absolute;border-radius:50%;filter:blur(70px);opacity:.5}
.hero-aurora::before{width:46rem;height:46rem;top:-16rem;right:-10rem;background:radial-gradient(circle,rgba(21,101,192,.30),transparent 65%)}
.hero-aurora::after{width:38rem;height:38rem;bottom:-14rem;left:-8rem;background:radial-gradient(circle,rgba(47,138,240,.20),transparent 65%)}
[data-theme="dark"] .hero-aurora::before{background:radial-gradient(circle,rgba(79,155,255,.28),transparent 65%)}
[data-theme="dark"] .hero-aurora::after{background:radial-gradient(circle,rgba(21,101,192,.30),transparent 65%)}
.grid-overlay{position:absolute;inset:0;background-image:linear-gradient(var(--border) 1px,transparent 1px),linear-gradient(90deg,var(--border) 1px,transparent 1px);background-size:56px 56px;opacity:.4;-webkit-mask-image:radial-gradient(ellipse 70% 60% at 50% 35%,#000 30%,transparent 75%);mask-image:radial-gradient(ellipse 70% 60% at 50% 35%,#000 30%,transparent 75%);pointer-events:none}

/* scroll reveal */
.reveal{opacity:0;transform:translateY(22px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}
.reveal.revealed{opacity:1;transform:none}
.reveal-delay-1{transition-delay:.08s}
.reveal-delay-2{transition-delay:.16s}
.reveal-delay-3{transition-delay:.24s}
.reveal-delay-4{transition-delay:.32s}

/* segmented control / filter pills */
.seg{display:inline-flex;flex-wrap:wrap;gap:.2rem;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-pill);padding:.25rem}
.seg a,.seg button{padding:.38rem .8rem;border-radius:var(--radius-pill);font-size:.82rem;font-weight:600;color:var(--text-secondary);background:transparent;border:none;cursor:pointer;text-decoration:none;transition:background .15s,color .15s;white-space:nowrap}
.seg a:hover,.seg button:hover{color:var(--text)}
.seg a.active,.seg button.active{background:var(--btn-blue);color:#fff!important}
.seg a.active:hover,.seg button.active:hover{background:var(--btn-blue-hover);color:#fff!important}

/* marquee (logo/trust strips) */
.marquee{display:flex;overflow:hidden;-webkit-mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent)}
.marquee__track{display:flex;gap:3rem;align-items:center;animation:marquee 28s linear infinite;padding-right:3rem}
@keyframes marquee{to{transform:translateX(-50%)}}

/* utility */
.truncate-2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.truncate-3{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.divider-or{display:flex;align-items:center;gap:.75rem;color:var(--text-muted);font-size:.82rem}
.divider-or::before,.divider-or::after{content:"";flex:1;height:1px;background:var(--border)}

/* ═══ COMPATIBILITY LAYER ══════════════════════════════════════════════════
   Existing app/admin markup hardcodes dark-theme Tailwind colors. Scope a
   remap to the app shell so those pages are theme-correct immediately, while
   keeping the (rewritten, light) marketing pages untouched. Specificity
   (.app-shell .x = 0,2,0) safely overrides Tailwind's single-class utilities. */
.app-shell .text-white{color:var(--text)}
.app-shell .text-slate-200,.app-shell .text-slate-300{color:var(--text)}
.app-shell .text-slate-400,.app-shell .text-slate-500{color:var(--text-secondary)}
.app-shell .text-slate-600{color:var(--text-muted)}
.app-shell .text-cyan,.app-shell .text-\[var\(--accent\)\]{color:var(--accent-text)}
.app-shell .bg-navy,.app-shell .bg-navy-secondary{background:var(--surface)}
.app-shell .border-navy-border{border-color:var(--border)}

/* Public-page remap (specificity 0,1,1 beats Tailwind's single-class utilities
   regardless of injection order) — neutralises dark-assumption classes so any
   page still on legacy markup renders correct in the light-first system. */
body .text-white,body .text-slate-100,body .text-slate-200,body .text-slate-300{color:var(--text)}
body .text-slate-400,body .text-slate-500{color:var(--text-secondary)}
body .text-slate-600,body .text-slate-700{color:var(--text-muted)}
body .text-cyan{color:var(--accent-text)}
/* Theme-toggle icon: driven by data-theme (set before first paint) so the
   correct icon shows immediately — no flash of both icons on page load. */
:root[data-theme="light"] .theme-ic-dark{display:none}
:root[data-theme="dark"] .theme-ic-light{display:none}

/* the <body> element itself carries bg-navy/text-slate-* on legacy pages */
body.bg-navy{background:var(--bg);color:var(--text)}
body.text-slate-100,body.text-slate-200,body.text-slate-300{color:var(--text)}
body .bg-navy{background:var(--bg)}
body .bg-navy-secondary{background:var(--surface)}
body .bg-navy-elevated,body .bg-navy-surface{background:var(--surface-2)}
body .border-navy-border,body .border-navy-elevated{border-color:var(--border)}
/* re-assert app-shell surfaces (0,2,0) over the body remap (0,1,1) */
.app-shell .bg-navy,.app-shell .bg-navy-secondary{background:var(--surface)}
/* Fix malformed arbitrary classes that slipped into the dashboard markup
   (e.g. bg-[var(--bg-primary)]-secondary). Tailwind can't generate these, so
   we map the exact tokens to real surfaces via attribute selectors. */
[class~="bg-[var(--bg-primary)]-secondary"]{background:var(--surface)}
[class~="bg-[var(--bg-primary)]-surface"]{background:var(--surface-2)}
[class~="border-[var(--border)]-border"]{border-color:var(--border)}
[class~="border-[var(--border)]-border/50"]{border-color:var(--border)}
.app-shell .bg-cyan\/10,.app-shell .bg-cyan\/20{background:var(--accent-soft)}
/* Buttons written as bg-[var(--accent)] → company blue + white text (both themes) */
.app-shell [class~="bg-[var(--accent)]"]{background:var(--btn-blue)!important;color:#fff!important}
.app-shell [class~="hover:bg-[var(--accent)]"]:hover{background:var(--btn-blue-hover)!important}
.app-shell [class~="bg-cyan"]{background:var(--btn-blue)!important;color:#fff!important}
/* real Tailwind blue buttons (bg-blue-600/700) → company blue */
.app-shell .bg-blue-600,.app-shell .bg-blue-700,.app-shell [class~="hover:bg-blue-700"]:hover{background:var(--btn-blue)!important;color:#fff!important}
.app-shell .bg-blue-900\/40{background:var(--surface-2)}
.app-shell [class*="bg-blue-500/"]{background:var(--accent-soft)}
.app-shell [class*="border-blue-500"]{border-color:var(--border)}
.app-shell .text-blue-400{color:var(--accent-text)}
/* hover:text-white goes invisible in light mode → use the theme text colour */
.app-shell [class~="hover:text-white"]:hover{color:var(--text)!important}

/* Dark Tailwind slate/gray surfaces used by legacy app pages (matrix, journals,
   combo-detail) → semantic surfaces. Adapts in both themes. */
.app-shell .bg-slate-900,.app-shell .bg-slate-800,.app-shell .bg-gray-900,.app-shell .bg-gray-800{background:var(--surface)}
.app-shell .bg-slate-700,.app-shell .bg-slate-600,.app-shell .bg-gray-700,.app-shell .bg-gray-600{background:var(--surface-2)}
.app-shell [class*="bg-slate-800/"],.app-shell [class*="bg-slate-700/"],.app-shell [class*="bg-slate-600/"],.app-shell [class*="bg-gray-800/"],.app-shell [class*="bg-gray-700/"]{background:var(--surface-2)}
.app-shell [class*="hover:bg-slate-"]:hover,.app-shell [class*="hover:bg-gray-"]:hover{background:var(--surface-3)}
.app-shell [class*="border-slate-"],.app-shell [class*="border-gray-"]{border-color:var(--border)}
/* light status text colors → adaptive semantic tokens (contrast-safe both themes) */
.app-shell .text-green-300,.app-shell .text-green-400,.app-shell .text-emerald-300,.app-shell .text-emerald-400{color:var(--success)}
.app-shell .text-yellow-300,.app-shell .text-yellow-400,.app-shell .text-amber-300,.app-shell .text-amber-400{color:var(--warning)}
.app-shell .text-red-300,.app-shell .text-red-400,.app-shell .text-rose-300,.app-shell .text-rose-400{color:var(--danger)}
.app-shell .text-blue-300,.app-shell .text-blue-400,.app-shell .text-sky-300,.app-shell .text-sky-400{color:var(--info)}

/* ─── Motion preferences ───────────────────────────────────────────────────── */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
  .reveal{opacity:1!important;transform:none!important}
}

/* ─── Responsive ───────────────────────────────────────────────────────────── */
@media(max-width:768px){.section{padding:3.5rem 0}.table-wrap{border-radius:0;border-left:none;border-right:none}}
@media(max-width:480px){.card{padding:1.1rem}.container,.container-wide{padding:0 1.1rem}}

/* ── Mobile audit round 2 (2026-07-18) ─────────────────────────────────── */
/* C. Text must never break INSIDE a button/chip/badge — parent rows wrap. */
button, .btn, .badge { white-space: nowrap; }
/* B. Scroll-hint shadows on every horizontal table scroller: fading edges
   tell the thumb there's more content (classic scroll-shadow technique). */
.atk-scroll, .table-scroll, .table-wrap, .overflow-x-auto {
  background:
    linear-gradient(90deg, var(--surface) 30%, transparent) 0 0,
    linear-gradient(270deg, var(--surface) 30%, transparent) 100% 0,
    radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.22), transparent) 0 0,
    radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.22), transparent) 100% 0;
  background-repeat: no-repeat;
  background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
  background-attachment: local, local, scroll, scroll;
}
/* Tab pill groups: on phones scroll horizontally instead of wrapping into
   lopsided rows (leaderboard tabs, feed filter). */
@media(max-width:640px){
  .seg{flex-wrap:nowrap;overflow-x:auto;max-width:100%;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  .seg::-webkit-scrollbar{display:none}
}

/* ── Admin content/list rows (global so pjax-swapped pages never need the
   page <head> style or Tailwind runtime to align action buttons) ──────── */
.content-card{background:var(--bg-surface,#0d1117);border:1px solid var(--border);border-radius:.75rem;overflow:hidden}
.content-head{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:1rem 1.25rem;border-bottom:1px solid var(--border)}
.list-row{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.7rem 1.25rem}
/* Content-management rows: title and its Edit/Delete buttons stay on ONE line;
   the list pans horizontally instead of wrapping the buttons under the text.
   `truncate` used to hide long titles outright — now the row is as wide as its
   content and .list-scroll reveals the rest. */
.list-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
@media(max-width:640px){
  /* Every row gets the SAME width, not max-content. With max-content each row
     was only as wide as its own text, so the Edit/Delete pair landed at a
     different x on every line - that's the "scattered" look. A shared width
     puts the actions in a real, aligned column. */
  .list-scroll .list-row{
    display:grid;grid-template-columns:1fr max-content;align-items:center;
    min-width:34rem;column-gap:1rem;
  }
  .list-scroll .cim-row-title,.list-scroll .cim-row-sub{white-space:nowrap}
  .list-scroll .row-actions{justify-content:flex-end}
}

/* public/tools.php cards. Desktop keeps the two-column look (the media cell
   spans both text rows). On phones the single column falls in DOM order, which
   is exactly what we want: header → image → text → button. */
@media(min-width:768px){
  .tool-row{grid-template-rows:auto auto;align-items:center}
  .tool-head{align-self:end}
  .tool-body{align-self:start}
  .tool-media{align-self:center}
}

.list-row + .list-row{border-top:1px solid var(--border)}
/* Episode prev / complete / next: 3 equal tracks keep the middle action centred
   even when Previous or Next is absent (empty placeholders used to collapse). */
.ep-nav{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:.75rem}
.ep-nav-side{display:flex;align-items:center;min-width:0}
.ep-nav-mid{display:flex;align-items:center;justify-content:center}
@media(max-width:520px){
  .ep-nav{grid-template-columns:1fr;justify-items:center}
  .ep-nav-side{justify-content:center!important}
}
.row-actions{display:flex;gap:.5rem;align-items:center;flex-shrink:0}
/* Delete lives in its own <form> (to POST) while Edit is a bare <button>. A form
   flex-item lays out differently across browsers (fine in Chrome, nudged in
   Firefox) → the two buttons misalign. display:contents removes the form's own
   box so its button becomes a direct flex child of .row-actions — both buttons
   are then treated identically and line up in every browser. Form still submits. */
.row-actions form{display:contents}

/* ─── Mobile refinements (2026-08-06) ──────────────────────────────────────── */

/* Reflection Journal header: title + subtext, with the action BELOW them on
   phones (it used to sit on the same line and squeeze the heading). */
.refl-head{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem}
.refl-head .refl-add{flex-shrink:0}
@media(max-width:640px){
  .refl-head{flex-direction:column;align-items:flex-start;gap:.9rem}
  .refl-head .refl-add{align-self:flex-start}
}

/* Research Centre on phones: the fixed table layout let the wide "Completed —
   Pass" badge bleed over the Results column. Give the columns room, keep each
   cell on its own line, and let .table-wrap scroll instead of overlapping. */
@media(max-width:768px){
  .table-wrap .data-table{table-layout:auto}
  .table-wrap .data-table th,.table-wrap .data-table td{white-space:nowrap}
  .table-wrap .data-table td .badge{display:inline-block;max-width:none}
}

/* admin/content.php rows on phones: keep the meta line and the buttons in a
   tidy column-aligned pair rather than letting them stagger row to row. */
@media(max-width:640px){
  .list-scroll .list-row{align-items:center;gap:1rem;padding-left:1rem;padding-right:1rem}
  .list-scroll .row-actions{margin-left:auto}
  .list-scroll .row-actions .btn,.list-scroll .row-actions button{min-width:64px;justify-content:center}
}

/* Payout tracker charts on phones: the Chart.js canvas kept its intrinsic
   width, pushing the plot off-centre inside the card. (This previously targeted
   a .chart-box class that does not exist in the markup, so it did nothing.) */
.chart-container{position:relative;width:100%;overflow:hidden}
.chart-container canvas{max-width:100%!important}

/* A note popover is absolutely positioned INSIDE the horizontally scrollable
   months table, so anchoring it left made it extend past the last column and
   widen the scroll area - that's the empty gap at the right edge. Anchor it to
   the right instead so it grows inward and never adds width. */
/* NOTE: the months table uses a plain .overflow-x-auto wrapper, not .table-wrap,
   so scoping this to .table-wrap matched nothing and the popover kept widening
   the scroll area. Unscoped now. */
.cim-note-pop{left:auto!important;right:0}
@media(max-width:640px){ .cim-note-pop{width:min(16rem,70vw)} }

/* Grid/flex children default to min-width:auto, so a wide scroll container
   inside one (the Instruments table, the chart cards) stretches the whole
   column instead of scrolling - that's boxes "flowing out" on phones. */
.grid > *{min-width:0}
#perfPage .card,#perfPage .card-pad-lg{min-width:0;overflow-wrap:anywhere}
.chart-container{min-width:0}

/* Research Centre: the combinations table scrolls, but on a phone there was no
   sign of it - the last column just ran off the edge. A local-attachment
   gradient stays pinned to the scroll box (unlike an absolutely positioned
   pseudo-element) so it fades at the right until you reach the end. */
@media(max-width:768px){
  .table-wrap{
    background-image:linear-gradient(to right,transparent,var(--surface) 92%);
    background-repeat:no-repeat;background-attachment:local;
    background-position:right center;background-size:26px 100%;
    border-right:2px solid var(--accent-soft-2);
  }
}

/* Performance Journal header: title + subtext, with "New Month Entry" BELOW
   them on phones instead of squeezed onto the same line. */
.perf-head{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem}
.perf-head .perf-new{flex-shrink:0}
@media(max-width:640px){
  .perf-head{flex-direction:column;align-items:flex-start;gap:.9rem}
  .perf-head .perf-new{align-self:flex-start}
}

/* Programme certificate: keep the sheet centred in the viewport. */
.cert-wrapper{margin-left:auto;margin-right:auto}

/* Community composer: the action row fades/slides the SAME way in both
   directions. Alpine's bare x-transition leaves near-instantly, which made the
   buttons snap shut after opening smoothly. */
.cim-fade-enter{transition:opacity .18s ease, transform .18s ease}
.cim-fade-leave{transition:opacity .18s ease, transform .18s ease}
.cim-fade-start{opacity:0;transform:translateY(-4px)}
.cim-fade-end{opacity:1;transform:translateY(0)}
/* The textarea drove the jump: the rows attribute is not animatable, so the
   box collapsed instantly while the buttons were still fading. Height is CSS
   now, on the SAME .18s curve as the action row, so close mirrors open. */
.cim-composer-input{height:2.75rem;overflow-y:hidden;transition:height .18s ease}
.cim-composer-input.is-open{height:7rem;overflow-y:auto}

/* ═══════════════════════════════════════════════════════════════════════════
   EMAIL LOG  ·  admin/email-log.php
   Built phone first. The message list is a stack of cards on a small screen
   and a real table from 900px up, because a seven column table on a phone is
   unreadable no matter how much you shrink the type.
   ═══════════════════════════════════════════════════════════════════════════ */
.elog{min-width:0}
[x-cloak]{display:none!important}

.elog-head{display:flex;flex-direction:column;gap:.9rem;margin-bottom:1.25rem}
.elog-head-actions{display:flex;gap:.5rem;flex-wrap:wrap}
/* A form here is only a wrapper for the button. Let the button take part in
   the flex row directly so it lines up before any script has run. */
.elog-head-actions form{display:contents}
@media(min-width:768px){
  .elog-head{flex-direction:row;align-items:flex-start;justify-content:space-between}
  .elog-head-actions{flex-shrink:0}
}

/* ─── headline numbers ─────────────────────────────────────────────────────── */
.elog-stats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.6rem;margin-bottom:1.25rem}
@media(min-width:560px){.elog-stats{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(min-width:900px){.elog-stats{grid-template-columns:repeat(5,minmax(0,1fr))}}
@media(min-width:1280px){.elog-stats{grid-template-columns:repeat(9,minmax(0,1fr))}}
.elog-stat{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:.75rem .8rem;box-shadow:var(--shadow-xs);min-width:0;text-decoration:none;display:block;
  transition:border-color .15s ease,transform .15s ease}
a.elog-stat:hover{border-color:var(--accent);transform:translateY(-1px)}
.elog-stat.is-warn{border-color:var(--warning-border);background:var(--warning-bg)}
.elog-stat.is-bad{border-color:var(--danger-border);background:var(--danger-bg)}
.elog-stat-v{font-family:var(--font-display);font-size:1.35rem;font-weight:700;color:var(--text);
  letter-spacing:-.02em;line-height:1.15}
.elog-stat-l{font-size:.68rem;color:var(--text-muted);margin-top:.15rem;line-height:1.25;
  text-transform:uppercase;letter-spacing:.04em}

/* ─── tabs ─────────────────────────────────────────────────────────────────── */
.elog-tabs{display:flex;gap:.35rem;overflow-x:auto;-webkit-overflow-scrolling:touch;
  border-bottom:1px solid var(--border);margin-bottom:1.25rem;padding-bottom:0}
.elog-tabs::-webkit-scrollbar{display:none}
.elog-tab{flex-shrink:0;padding:.65rem .95rem;font-size:.875rem;font-weight:600;color:var(--text-secondary);
  border-bottom:2px solid transparent;text-decoration:none;white-space:nowrap;display:inline-flex;
  align-items:center;gap:.4rem;transition:color .15s ease,border-color .15s ease}
.elog-tab:hover{color:var(--text)}
.elog-tab.is-active{color:var(--accent-text);border-bottom-color:var(--accent)}
.elog-tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:1.15rem;height:1.15rem;
  padding:0 .3rem;border-radius:var(--radius-pill);background:var(--danger-bg);color:var(--danger);
  font-size:.68rem;font-weight:700}

/* ─── saved views + presets ────────────────────────────────────────────────── */
.elog-presets{display:flex;gap:.4rem;flex-wrap:wrap;margin-bottom:.9rem}
.elog-preset{display:inline-flex;align-items:center;gap:.3rem;padding:.35rem .75rem;font-size:.8rem;
  font-weight:500;border-radius:var(--radius-pill);border:1px solid var(--border);background:var(--surface);
  color:var(--text-secondary);text-decoration:none;transition:all .15s ease}
.elog-preset:hover{border-color:var(--accent);color:var(--accent-text)}
.elog-preset.is-on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-text);font-weight:600}
.elog-preset-saved{padding-right:.3rem}
.elog-preset-saved a{color:inherit;text-decoration:none}
.elog-preset-saved button{background:none;border:0;color:var(--text-muted);cursor:pointer;font-size:1rem;
  line-height:1;padding:0 .25rem;border-radius:4px}
.elog-preset-saved button:hover{color:var(--danger);background:var(--danger-bg)}

/* ─── filters ──────────────────────────────────────────────────────────────── */
.elog-filterwrap{margin-bottom:1rem}
.elog-filter-toggle{display:flex;align-items:center;gap:.5rem;width:100%;padding:.7rem .9rem;
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);
  color:var(--text);font-size:.875rem;font-weight:600;cursor:pointer;box-shadow:var(--shadow-xs)}
.elog-filter-toggle svg{width:1rem;height:1rem;color:var(--text-muted)}
.elog-filter-toggle-hint{margin-left:auto;font-weight:500;font-size:.8rem;color:var(--text-muted)}
/* The toggle is useful on a desktop too: the filter panel is tall and gets
   in the way once you have set it. */
/* One rule decides it: hidden only when the wrap says closed. The starting
   position comes from width (collapsed on a phone, open on a desktop) and is
   set once by Alpine, so the button behaves identically at both sizes. */
.elog-filters{display:none;grid-template-columns:1fr;gap:.75rem;background:var(--surface);
  border:1px solid var(--border);border-radius:var(--radius);padding:1rem;margin-top:.6rem;
  box-shadow:var(--shadow-xs)}
.elog-filterwrap.is-open .elog-filters{display:grid}
@media(min-width:640px){.elog-filters{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:900px){
  .elog-filterwrap.is-open .elog-filters{grid-template-columns:repeat(4,minmax(0,1fr))}
  .elog-field-wide{grid-column:span 2}
}
@media(min-width:1280px){.elog-filters{grid-template-columns:repeat(5,minmax(0,1fr))}}
.elog-field{min-width:0}
.elog-field .form-input{width:100%}
.elog-check{display:flex;align-items:center;gap:.5rem;font-size:.85rem;color:var(--text-secondary);
  align-self:end;padding-bottom:.5rem}
.elog-check input{width:1rem;height:1rem;accent-color:var(--accent)}
.elog-filter-actions{display:flex;gap:.5rem;align-items:end;padding-bottom:.15rem}
.elog-savebar{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;margin-bottom:1rem;
  font-size:.85rem;color:var(--text-secondary)}
.elog-savebar .form-input{max-width:16rem;flex:1 1 10rem}

/* ─── chart ────────────────────────────────────────────────────────────────── */
.elog-chartcard{margin-bottom:1rem}
.elog-chart{height:200px;position:relative}
@media(min-width:768px){.elog-chart{height:240px}}

/* ─── result bar ───────────────────────────────────────────────────────────── */
.elog-resultbar{display:flex;align-items:center;justify-content:space-between;gap:.75rem;flex-wrap:wrap;
  margin-bottom:.7rem;font-size:.875rem;color:var(--text-secondary)}

/* ─── the message list: cards on a phone, a table on a desktop ─────────────── */
.elog-list{display:flex;flex-direction:column;gap:.6rem}
.elog-row{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:.85rem;display:grid;grid-template-columns:1fr;gap:.45rem;box-shadow:var(--shadow-xs);min-width:0}
.elog-row.is-bad{border-left:3px solid var(--danger)}
.elog-row.is-warn{border-left:3px solid var(--warning)}
.elog-row-head{display:none}
.elog-row>div{min-width:0;display:flex;flex-wrap:wrap;align-items:center;gap:.4rem;font-size:.875rem}
.elog-row>div[data-l]:not([data-l=""])::before{content:attr(data-l);flex:0 0 5.5rem;font-size:.68rem;
  text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);font-weight:700}
@media(min-width:900px){
  .elog-list{gap:0;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;
    background:var(--surface);box-shadow:var(--shadow-sm)}
  .elog-row{grid-template-columns:5.5rem minmax(0,1.4fr) minmax(0,2.2fr) 8.5rem 6.5rem 9rem 5rem;
    align-items:center;gap:.75rem;border:0;border-bottom:1px solid var(--border);border-radius:0;
    box-shadow:none;padding:.7rem .9rem}
  .elog-row.is-bad{border-left:3px solid var(--danger)}
  .elog-row:last-child{border-bottom:0}
  .elog-row:hover{background:var(--surface-3)}
  .elog-row-head{display:grid;background:var(--surface-2);border-bottom:1px solid var(--border)}
  .elog-row-head>div{font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;
    color:var(--text-muted)}
  .elog-row-head:hover{background:var(--surface-2)}
  .elog-row>div[data-l]::before{display:none}
  .elog-list-4 .elog-row{grid-template-columns:minmax(0,1.3fr) minmax(0,1fr) minmax(0,1fr) minmax(0,1.2fr)}
}
.elog-when{font-weight:600;color:var(--text)}
.elog-when-t{color:var(--text-muted);font-size:.8rem}
.elog-name{font-weight:600;color:var(--text);text-decoration:none;display:block;width:100%}
.elog-name:hover{color:var(--accent-text)}
.elog-addr{font-family:var(--font-mono);font-size:.75rem;color:var(--text-muted);word-break:break-all}
.elog-subject a{color:var(--text);text-decoration:none;font-weight:500;line-height:1.35}
.elog-subject a:hover{color:var(--accent-text);text-decoration:underline}
.elog-err{font-size:.75rem;color:var(--danger);width:100%;line-height:1.35}
.elog-dot{font-size:.68rem;color:var(--text-muted);text-transform:uppercase;letter-spacing:.04em}
.elog-dot.is-click{color:var(--success)}
.elog-rowact{justify-content:flex-start}
@media(min-width:900px){.elog-rowact{justify-content:flex-end}}
.elog-pager{display:flex;align-items:center;justify-content:center;gap:1rem;padding:1.25rem 0;
  font-size:.85rem;color:var(--text-secondary)}
.elog-inline-link{color:var(--accent-text);text-decoration:underline;font-size:.8rem}

/* ─── the message itself ───────────────────────────────────────────────────── */
.elog-detail{background:var(--surface);border:1px solid var(--accent);border-radius:var(--radius);
  margin-bottom:1.25rem;overflow:hidden;box-shadow:var(--shadow-md)}
.elog-detail-bar{display:flex;align-items:flex-start;justify-content:space-between;gap:.75rem;
  padding:.9rem 1rem;background:var(--surface-2);border-bottom:1px solid var(--border)}
.elog-detail-title{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;min-width:0;
  font-size:.95rem;color:var(--text);line-height:1.4}
.elog-detail-grid{display:grid;grid-template-columns:1fr;gap:0}
@media(min-width:1024px){.elog-detail-grid{grid-template-columns:minmax(0,1fr) 20rem}}
.elog-detail-main{padding:1rem;min-width:0}
.elog-detail-side{padding:1rem;border-top:1px solid var(--border);background:var(--surface-2);min-width:0}
@media(min-width:1024px){.elog-detail-side{border-top:0;border-left:1px solid var(--border)}}
.elog-seg{display:inline-flex;background:var(--surface-3);border-radius:var(--radius-pill);
  padding:.2rem;gap:.15rem;margin-bottom:.75rem}
.elog-seg button{border:0;background:none;padding:.35rem .8rem;border-radius:var(--radius-pill);
  font-size:.8rem;font-weight:600;color:var(--text-secondary);cursor:pointer}
.elog-seg button.is-on{background:var(--surface);color:var(--text);box-shadow:var(--shadow-xs)}
.elog-frame{border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;background:#f5f8fc}
.elog-frame iframe{width:100%;height:460px;border:0;display:block;background:#f5f8fc}
.elog-frame-tall iframe{height:560px}
.elog-plain{background:var(--surface-inset);border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:1rem;font-family:var(--font-mono);font-size:.8rem;line-height:1.6;color:var(--text);
  white-space:pre-wrap;word-break:break-word;max-height:460px;overflow:auto;margin:0}
.elog-kv{display:flex;gap:.6rem;padding:.4rem 0;border-bottom:1px solid var(--border);font-size:.82rem;
  align-items:baseline}
.elog-kv:last-of-type{border-bottom:0}
.elog-kv span{flex:0 0 5.5rem;color:var(--text-muted);text-transform:uppercase;font-size:.66rem;
  letter-spacing:.05em;font-weight:700}
.elog-kv b{color:var(--text);font-weight:600;min-width:0;word-break:break-word}
.elog-kv b a{color:var(--accent-text)}
.elog-kv.is-bad b{color:var(--danger)}
.elog-timeline{margin:1rem 0;padding-top:.75rem;border-top:1px solid var(--border)}
.elog-step{display:flex;gap:.7rem;padding-bottom:.85rem;position:relative}
.elog-step:not(:last-child)::before{content:'';position:absolute;left:.28rem;top:.85rem;bottom:0;
  width:1px;background:var(--border)}
.elog-step-dot{flex:0 0 .6rem;height:.6rem;border-radius:50%;background:var(--accent);margin-top:.3rem;
  position:relative;z-index:1}
.elog-step-what{font-size:.82rem;font-weight:600;color:var(--text)}
.elog-step-when{font-size:.75rem;color:var(--text-secondary)}
.elog-step-note{font-size:.72rem;color:var(--text-muted);line-height:1.4}
.elog-detail-actions{display:flex;flex-wrap:wrap;gap:.4rem;padding-top:.75rem;border-top:1px solid var(--border)}

/* ─── panels used by the watch, health and preview tabs ───────────────────── */
.elog-panel{margin-bottom:2rem}
.elog-panel-head{margin-bottom:.9rem}
.elog-panel-head h2{font-family:var(--font-display);font-size:1.1rem;font-weight:700;color:var(--text);
  letter-spacing:-.01em;margin-bottom:.3rem}
.elog-panel-head p{font-size:.85rem;color:var(--text-secondary);line-height:1.55;max-width:60ch}
.elog-ok{background:var(--success-bg);border:1px solid var(--success-border);border-radius:var(--radius-sm);
  padding:.85rem 1rem;font-size:.875rem;color:var(--success);font-weight:500}
.elog-cards{display:grid;grid-template-columns:1fr;gap:.75rem}
@media(min-width:640px){.elog-cards{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1200px){.elog-cards{grid-template-columns:repeat(3,minmax(0,1fr))}}
.elog-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:1rem;box-shadow:var(--shadow-xs);min-width:0}
.elog-card-top{display:flex;align-items:center;justify-content:space-between;gap:.5rem;margin-bottom:.5rem}
.elog-card-title{font-weight:600;font-size:.9rem;color:var(--text)}
.elog-card-big{font-family:var(--font-display);font-size:1.75rem;font-weight:700;color:var(--text);
  letter-spacing:-.02em}
.elog-card-note{font-size:.8rem;color:var(--text-secondary);line-height:1.5;margin-top:.4rem;
  min-width:0;overflow-wrap:anywhere}
/* A backup filename has no spaces in it, and neither did the address it was
   copied to, so the browser had nowhere to break the line and the text simply
   ran out of the card. Belt and braces: the card can shrink, and anything
   inside it can break mid-word if it has to. */
.elog-card{min-width:0}
.elog-card-big{min-width:0;overflow-wrap:anywhere}
.bk-file{display:block;font-family:var(--font-mono);font-size:.74rem;color:var(--text);
  overflow-wrap:anywhere;line-height:1.45}
.bk-meta{display:block;margin-top:.15rem;color:var(--text-muted);overflow-wrap:anywhere}
.elog-code{display:block;font-family:var(--font-mono);font-size:.72rem;background:var(--surface-inset);
  border:1px solid var(--border);border-radius:6px;padding:.45rem .6rem;color:var(--text-secondary);
  word-break:break-all;line-height:1.5}
.elog-foot-note{font-size:.78rem;color:var(--text-muted);margin-top:.75rem;line-height:1.5;max-width:70ch}

/* ─── template previews ────────────────────────────────────────────────────── */
.elog-previews{display:flex;flex-direction:column;gap:.6rem}
.elog-preview{border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);
  overflow:hidden;box-shadow:var(--shadow-xs)}
.elog-preview-head{display:flex;align-items:center;gap:.6rem;width:100%;padding:.8rem .9rem;background:none;
  border:0;cursor:pointer;text-align:left;flex-wrap:wrap}
.elog-preview-head:hover{background:var(--surface-3)}
.elog-preview-subject{flex:1 1 12rem;min-width:0;font-size:.875rem;font-weight:500;color:var(--text)}
.elog-preview-chev{color:var(--text-muted);font-size:1.1rem;font-weight:700;line-height:1;margin-left:auto}
.elog-preview-body{padding:0 .9rem .9rem}
.elog-findings{list-style:none;margin:0 0 .75rem;padding:0;display:flex;flex-direction:column;gap:.35rem}
.elog-findings li{font-size:.8rem;line-height:1.5;padding:.5rem .7rem;border-radius:6px}
.elog-findings li.is-bad{background:var(--danger-bg);color:var(--danger)}
.elog-findings li.is-warn{background:var(--warning-bg);color:var(--warning)}

/* ─── blast composer actions ───────────────────────────────────────────────── */
.ebl-actions{display:flex;flex-direction:column;gap:.5rem}
@media(min-width:560px){.ebl-actions{flex-direction:row;flex-wrap:wrap;align-items:center}}
.ebl-actions .btn{justify-content:center}
.ebl-now{display:flex;gap:.6rem;align-items:flex-start;font-size:.8rem;color:var(--text-secondary);
  line-height:1.5;padding:.6rem .75rem;background:var(--warning-bg);border:1px solid var(--warning-border);
  border-radius:var(--radius-sm)}
.ebl-now input{margin-top:.15rem;width:1rem;height:1rem;flex-shrink:0;accent-color:var(--warning)}

/* ─── member email preferences ─────────────────────────────────────────────── */
.epref-list{display:flex;flex-direction:column;gap:.25rem;margin-bottom:1.25rem}
.epref-item{display:flex;gap:.85rem;align-items:flex-start;padding:.85rem;border-radius:var(--radius-sm);
  cursor:pointer;transition:background-color .15s ease}
.epref-item:hover{background:var(--surface-3)}
.epref-item input{width:1.15rem;height:1.15rem;margin-top:.15rem;flex-shrink:0;accent-color:var(--accent)}
.epref-item span{display:flex;flex-direction:column;gap:.15rem;min-width:0}
.epref-item strong{font-size:.95rem;color:var(--text);font-weight:600}
.epref-item em{font-style:normal;font-size:.82rem;color:var(--text-secondary);line-height:1.5}
.epref-actions{display:flex;flex-direction:column;gap:.5rem}
@media(min-width:480px){.epref-actions{flex-direction:row;align-items:center}}
.epref-note{font-size:.78rem;color:var(--text-muted);line-height:1.6;margin-top:1rem;
  padding-top:1rem;border-top:1px solid var(--border)}

/* ─── per-member email history on the admin student page ───────────────────── */
.smail-list{display:flex;flex-direction:column;gap:.3rem}
.smail-row{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;padding:.5rem .65rem;
  border-radius:var(--radius-sm);text-decoration:none;transition:background-color .15s ease;
  border:1px solid transparent}
.smail-row:hover{background:var(--surface-3);border-color:var(--border)}
.smail-when{font-size:.72rem;color:var(--text-muted);font-weight:600;flex:0 0 3rem}
.smail-subject{flex:1 1 12rem;min-width:0;font-size:.82rem;color:var(--text);line-height:1.4}

/* ─── message list, compact phone card ─────────────────────────────────────── */
/* Seven labelled lines per message came out at nearly 300px, so one screen
   showed less than three emails. Rearranged into four lines, subject first,
   which is what you actually scan for. */
.elog-list-msg .elog-row{
  grid-template-columns:auto 1fr auto;
  grid-template-areas:
    "when    .       status"
    "subject subject subject"
    "to      to      to"
    "type    how     act";
  gap:.4rem .5rem;align-items:center}
.elog-list-msg .ec-when{grid-area:when}
.elog-list-msg .ec-to{grid-area:to}
.elog-list-msg .ec-subject{grid-area:subject}
.elog-list-msg .ec-type{grid-area:type}
.elog-list-msg .ec-how{grid-area:how}
.elog-list-msg .ec-status{grid-area:status;justify-content:flex-end}
.elog-list-msg .ec-act{grid-area:act;justify-content:flex-end}
.elog-list-msg .ec-subject a{font-weight:600;font-size:.9rem}
.elog-list-msg .ec-to{gap:.1rem .5rem}
.elog-list-msg .elog-name{display:inline;width:auto;font-size:.82rem;font-weight:500}
@media(min-width:900px){
  /* Back to real columns. grid-template-areas has to be cleared or it keeps
     forcing the phone shape. */
  .elog-list-msg .elog-row{grid-template-areas:none;
    /* Wider first column and a real gap: the date and the time share this
       column, so at 5.5rem the time ran straight into the name beside it. */
    grid-template-columns:6.75rem minmax(0,1.4fr) minmax(0,2.2fr) 8.5rem 6.5rem 9rem 5rem;gap:1.25rem}
  .elog-list-msg .ec-when,.elog-list-msg .ec-to,.elog-list-msg .ec-subject,
  .elog-list-msg .ec-type,.elog-list-msg .ec-how,.elog-list-msg .ec-status,
  .elog-list-msg .ec-act{grid-area:auto}
  .elog-list-msg .ec-status{justify-content:flex-start}
  .elog-list-msg .ec-subject a{font-weight:500;font-size:.875rem}
  .elog-list-msg .elog-name{display:block;width:100%;font-weight:600}
}

/* Thumb sized controls on the new admin screens. A 28px button is fine with a
   mouse and fiddly with a thumb, so anything tappable gets 36px on a phone. */
@media(max-width:767px){
  .elog .btn,.elog .btn-sm,.epref-actions .btn,.ebl-actions .btn{min-height:36px}
  .elog-preset{min-height:32px}
  .elog-tab{min-height:40px}
}

/* ─── restore steps on the backup page ─────────────────────────────────────── */
.bk-steps{margin:0 0 1rem;padding-left:1.2rem;display:flex;flex-direction:column;gap:.6rem}
.bk-steps li{font-size:.85rem;line-height:1.6;color:var(--text-secondary)}
.bk-steps strong{color:var(--text)}
.bk-steps code{font-family:var(--font-mono);font-size:.75rem;background:var(--surface-inset);
  border:1px solid var(--border);border-radius:5px;padding:.1rem .35rem;color:var(--text);
  word-break:break-all;display:inline-block;max-width:100%}

/* ─── public nav spacing between 768px and 960px ───────────────────────────── */
/* The desktop nav appears at 768px, but at that width the five links plus the
   logo plus the two buttons do not fit. "Inside Scope" wrapped onto a second
   line and sat on top of the logo. Nothing is allowed to wrap now, and the gap
   closes up until there is room for the full spacing. */
.pubnav__links{gap:1rem}
.pubnav__link{white-space:nowrap}
@media(min-width:960px){ .pubnav__links{gap:1.75rem} }

/* ─── community guidelines page ────────────────────────────────────────────── */
.gl-intro{margin-bottom:2rem}
.gl-intro p{font-size:.95rem;line-height:1.75;color:var(--text-secondary)}
.gl-intro p + p{margin-top:.9rem}
.gl-group{margin-bottom:2.25rem}
.gl-group-title{font-family:var(--font-display);font-size:1.15rem;font-weight:700;color:var(--text);
  letter-spacing:-.01em;margin-bottom:1rem;padding-bottom:.6rem;border-bottom:1px solid var(--border)}
.gl-rule{padding:.9rem 0;border-bottom:1px solid var(--border)}
.gl-rule:last-child{border-bottom:0}
.gl-rule h3{font-size:.95rem;font-weight:650;color:var(--text);margin-bottom:.35rem;line-height:1.45}
.gl-rule p{font-size:.88rem;line-height:1.7;color:var(--text-secondary)}
.gl-ladder{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.75rem;counter-reset:none}
.gl-ladder li{display:flex;gap:.85rem;align-items:flex-start;padding:.85rem 1rem;background:var(--surface);
  border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:var(--shadow-xs)}
.gl-ladder-n{flex:0 0 1.6rem;height:1.6rem;border-radius:50%;background:var(--accent-soft);
  color:var(--accent-text);font-weight:700;font-size:.8rem;display:flex;align-items:center;
  justify-content:center}
.gl-ladder li > span:last-child{display:flex;flex-direction:column;gap:.2rem;min-width:0}
.gl-ladder strong{font-size:.9rem;color:var(--text);font-weight:650}
.gl-ladder em{font-style:normal;font-size:.85rem;color:var(--text-secondary);line-height:1.6}
.gl-foot{font-size:.82rem;color:var(--text-muted);line-height:1.7;text-align:center;margin-top:1rem}
.gl-foot a{color:var(--accent-text);text-decoration:underline}

/* ─── house rules card pinned above the community feed ────────────────────── */
.gl-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  margin-bottom:1rem;overflow:hidden;box-shadow:var(--shadow-xs)}
.gl-card-head{display:flex;align-items:center;gap:.6rem;width:100%;padding:.8rem 1rem;background:none;
  border:0;cursor:pointer;text-align:left;color:var(--text);font-size:.875rem;font-weight:600}
.gl-card-head:hover{background:var(--surface-3)}
.gl-card-head svg{width:1.05rem;height:1.05rem;color:var(--accent);flex-shrink:0}
.gl-card-hint{margin-left:auto;font-weight:500;font-size:.78rem;color:var(--text-muted);flex-shrink:0}
.gl-card-body{padding:0 1rem 1rem;font-size:.85rem;line-height:1.7;color:var(--text-secondary)}
.gl-card-body ul{list-style:none;margin:.4rem 0 .8rem;padding:0;display:flex;flex-direction:column;gap:.35rem}
.gl-card-body li{padding-left:1.1rem;position:relative}
.gl-card-body li::before{content:'';position:absolute;left:0;top:.6rem;width:5px;height:5px;
  border-radius:50%;background:var(--accent)}
.gl-card-body a{color:var(--accent-text);text-decoration:underline}

/* ─── moderation queue ─────────────────────────────────────────────────────── */
.mod-item{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  padding:1rem;margin-bottom:.85rem;box-shadow:var(--shadow-xs)}
.mod-item.is-hidden{border-left:3px solid var(--text-muted);background:var(--surface-2)}
.mod-top{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;margin-bottom:.6rem}
.mod-when{font-size:.78rem;color:var(--text-muted)}
.mod-note{font-size:.85rem;color:var(--text-secondary);margin-bottom:.6rem;line-height:1.6}
.mod-note em{font-style:italic;color:var(--text)}
.mod-post{background:var(--surface-inset);border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:.85rem;margin-bottom:.75rem}
.mod-post-by{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;font-size:.82rem;font-weight:600;
  color:var(--text);margin-bottom:.5rem}
.mod-post-by a{color:var(--accent-text);text-decoration:none}
.mod-post-by a:hover{text-decoration:underline}
.mod-post-by .text-muted{font-weight:400;font-size:.76rem}
.mod-post-text{font-size:.875rem;line-height:1.65;color:var(--text);white-space:pre-wrap;word-break:break-word}
.mod-actions{display:flex;flex-direction:column;gap:.5rem}
.mod-actions .form-input{width:100%;font-size:.85rem}
.mod-buttons{display:flex;flex-wrap:wrap;gap:.4rem}
@media(min-width:900px){
  .mod-actions{flex-direction:row;align-items:center}
  .mod-actions .form-input{flex:1 1 14rem}
  .mod-buttons{flex-shrink:0}
}
@media(max-width:767px){ .mod-buttons .btn{min-height:36px;flex:1 1 auto;justify-content:center} }

/* ─── signup agreement ─────────────────────────────────────────────────────── */
.reg-agree{display:flex;gap:.7rem;align-items:flex-start;padding:.85rem;margin-bottom:1.25rem;
  background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);cursor:pointer}
.reg-agree input{width:1.1rem;height:1.1rem;margin-top:.1rem;flex-shrink:0;accent-color:var(--accent)}
/* One flowing sentence, not a stack. As a flex column every link became its
   own line and the closing full stop sat on a line by itself. */
.reg-agree span{display:block;font-size:.85rem;line-height:1.65;
  color:var(--text-secondary);min-width:0}
.reg-agree span em{display:block;margin-top:.35rem}
.reg-agree a{color:var(--accent-text);text-decoration:underline}
.reg-agree em{font-style:normal;font-size:.78rem;color:var(--text-muted)}

/* ─── house rules step inside the welcome wizard ───────────────────────────── */
/* A scroll box rather than a wall of text: it makes the length obvious, and
   the Continue button stays locked until it has actually been scrolled. */
.ob-rules{max-height:19rem;overflow-y:auto;padding:1rem;background:var(--surface-2);
  border:1px solid var(--border);border-radius:var(--radius-sm);font-size:.85rem;line-height:1.65;
  color:var(--text-secondary);-webkit-overflow-scrolling:touch}
.ob-rules h2{font-family:var(--font-display);font-size:.95rem;font-weight:700;color:var(--text);
  margin:1.1rem 0 .5rem;padding-bottom:.35rem;border-bottom:1px solid var(--border)}
.ob-rules h2:first-child{margin-top:0}
.ob-rules h3{font-size:.86rem;font-weight:650;color:var(--text);margin:.7rem 0 .2rem}
.ob-rules p{margin-bottom:.5rem}
.ob-rules strong{color:var(--text)}
.ob-rules-end{margin-top:1rem;padding-top:.75rem;border-top:1px solid var(--border);
  color:var(--text-muted);font-size:.8rem}

/* Waiting on something the person has not done yet. */
.is-locked{opacity:.5;cursor:not-allowed}
.reg-agree.is-locked{opacity:.55}

/* ─── visitors dashboard ───────────────────────────────────────────────────── */
.tf-controls{display:flex;flex-direction:column;gap:.5rem;margin-bottom:1.25rem}
@media(min-width:900px){.tf-controls{flex-direction:row;justify-content:space-between;align-items:center}}
.tf-controls .elog-presets{margin-bottom:0}
.tf-grid{display:grid;grid-template-columns:1fr;gap:0}
@media(min-width:900px){.tf-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:0 2rem}}

/* bar lists */
.tf-bars{display:flex;flex-direction:column;gap:.3rem}
.tf-bar{position:relative;display:flex;align-items:center;gap:.75rem;padding:.55rem .7rem;
  border-radius:var(--radius-sm);background:var(--surface);border:1px solid var(--border);
  overflow:hidden;min-width:0}
.tf-bar-fill{position:absolute;left:0;top:0;bottom:0;background:var(--accent-soft);z-index:0}
.tf-bar-label{position:relative;z-index:1;flex:1 1 auto;min-width:0;font-size:.85rem;color:var(--text);
  display:flex;flex-direction:column;gap:.1rem;word-break:break-all}
.tf-bar-label em{font-style:normal;font-size:.72rem;color:var(--text-muted)}
.tf-bar-count{position:relative;z-index:1;flex-shrink:0;font-weight:700;font-size:.85rem;
  color:var(--accent-text);font-family:var(--font-mono)}

/* human / bot split */
.tf-mix{display:flex;flex-direction:column;gap:.5rem}
.tf-mix-item{position:relative;display:flex;align-items:center;gap:.75rem;padding:.7rem .85rem;
  border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);
  text-decoration:none;overflow:hidden}
.tf-mix-item:hover{border-color:var(--accent)}
.tf-mix-bar{position:absolute;left:0;top:0;bottom:0;opacity:.16;z-index:0}
.tf-mix-label{position:relative;z-index:1;flex:1;font-size:.9rem;font-weight:600;color:var(--text)}
.tf-mix-n{position:relative;z-index:1;font-family:var(--font-mono);font-size:.9rem;font-weight:700;
  color:var(--text);display:flex;gap:.5rem;align-items:baseline}
.tf-mix-n em{font-style:normal;font-size:.78rem;color:var(--text-muted)}

/* busiest times */
.tf-heat-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:.35rem}
.tf-heat{border-collapse:separate;border-spacing:2px;min-width:34rem}
.tf-heat th{font-size:.68rem;color:var(--text-muted);font-weight:600;text-align:center;padding:0 .15rem}
.tf-heat tbody th{text-align:right;padding-right:.5rem;white-space:nowrap}
.tf-heat td{width:1.1rem;height:1.1rem;border-radius:3px}

/* funnel */
.tf-funnel{display:flex;flex-direction:column;gap:.6rem}
.tf-step{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:.75rem .85rem}
.tf-step-bar{height:6px;background:var(--surface-3);border-radius:3px;overflow:hidden;margin-bottom:.5rem}
.tf-step-bar span{display:block;height:100%;background:var(--accent);border-radius:3px}
.tf-step-text{display:flex;flex-wrap:wrap;align-items:baseline;gap:.5rem 1rem;font-size:.875rem}
.tf-step-text strong{color:var(--text);font-weight:600;flex:1 1 12rem}
.tf-step-text > span{font-family:var(--font-mono);font-weight:700;color:var(--text)}
.tf-step-text em{font-style:normal;font-family:var(--font-sans);font-weight:400;font-size:.78rem;
  color:var(--text-muted)}
.tf-step-drop{font-family:var(--font-sans)!important;font-weight:500!important;font-size:.78rem;
  color:var(--text-muted)!important}
.tf-step-drop.is-bad{color:var(--danger)!important;font-weight:600!important}

/* ─── branded error page ───────────────────────────────────────────────────── */
.err-code{font-family:var(--font-display);font-size:clamp(4rem,14vw,7rem);font-weight:700;
  line-height:1;letter-spacing:-.04em;color:var(--accent);opacity:.22;margin-bottom:.5rem}
.err-asked{font-size:.8rem;color:var(--text-muted);margin-bottom:1.5rem;word-break:break-all}
.err-asked code{font-family:var(--font-mono);background:var(--surface-inset);border:1px solid var(--border);
  border-radius:5px;padding:.15rem .4rem;color:var(--text-secondary)}
.err-actions{display:flex;flex-direction:column;gap:.5rem;align-items:stretch}
@media(min-width:520px){.err-actions{flex-direction:row;justify-content:center;flex-wrap:wrap}}
.err-actions .btn{justify-content:center}
.err-note{font-size:.85rem;color:var(--text-secondary);line-height:1.7;margin-top:2rem;
  padding-top:1.5rem;border-top:1px solid var(--border)}
.err-note a{color:var(--accent-text);text-decoration:underline}

/* ─── keep clear of the floating WhatsApp button ───────────────────────────── */
/* The chat button is fixed to the bottom right at z-index 60, so on a phone it
   sits over whatever is beneath it at that moment. Padding does not solve it,
   because a fixed element overlaps content at whatever scroll position they
   happen to meet. What does solve it is keeping the important control out of
   that corner: the two buttons sit side by side on a phone, so Save occupies
   the left half and the float only ever covers the secondary action's edge.
   The pager gets clearance too, since its Next link sat in the same corner. */
@media(max-width:640px){
  .epref-actions{flex-direction:row;gap:.5rem}
  .epref-actions .btn:first-child{flex:1 1 60%}
  .epref-actions .btn:last-child{flex:0 1 40%;padding-left:.5rem;padding-right:.5rem}
  .elog-pager{padding-bottom:5.5rem}
}

/* ─── count badge in the left navigation ───────────────────────────────────── */
/* Sits on the right of a nav item, and stays visible when the sidebar is
   collapsed to icons, because that is exactly when you would otherwise miss it. */
.nav-count{margin-left:auto;flex-shrink:0;min-width:1.15rem;height:1.15rem;padding:0 .3rem;
  display:inline-flex;align-items:center;justify-content:center;border-radius:var(--radius-pill);
  background:var(--btn-blue);color:#fff;font-size:.68rem;font-weight:700;line-height:1}
/* Blue, not red. These count things worth a look, not things on fire, and a row
   of red pips in the sidebar reads as alarm every time you open the site. */

/* ─── error entries on Site Health ─────────────────────────────────────────── */
/* The plain sentence leads; the raw text is one click away for when it is
   actually needed. */
.hl-err-top{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;margin-bottom:.25rem}
.hl-err-what{font-size:.95rem;color:var(--text);font-weight:650}
.hl-err-when{font-size:.72rem;color:var(--text-muted)}
.hl-err-why{font-size:.85rem;line-height:1.6;color:var(--text-secondary);margin-bottom:.4rem}
.hl-err-toggle{background:none;border:0;padding:0;font-size:.78rem;font-weight:600;
  color:var(--accent-text);cursor:pointer;text-decoration:underline}
.hl-err-toggle:hover{color:var(--accent)}

/* ─── email preview frame ──────────────────────────────────────────────────── */
/* An email is built 600px wide. On a phone that is wider than the screen, so
   the frame is scaled down rather than left to scroll sideways. */
.elog-frame.is-dark,.elog-frame.is-dark iframe{background:#0d1117}
@media(max-width:700px){
  .elog-frame{overflow:hidden}
  .elog-frame iframe{width:640px;transform-origin:top left}
}
@media(max-width:640px){ .elog-frame iframe{transform:scale(.72);height:780px;margin-bottom:-190px} }
@media(max-width:520px){ .elog-frame iframe{transform:scale(.60);height:900px;margin-bottom:-330px} }
@media(max-width:400px){ .elog-frame iframe{transform:scale(.50);height:1060px;margin-bottom:-500px} }
/* The header row of a preview wraps rather than squeezing on a narrow screen. */
@media(max-width:640px){
  .elog-preview-subject{flex:1 1 100%;order:3;font-size:.82rem}
  .elog-preview-chev{order:2}
}

/* ─── the plan list on onboarding step 1 ───────────────────────────────────── */
.ob-plan{list-style:none;margin:0 0 1.5rem;padding:0;display:flex;flex-direction:column;gap:.55rem;text-align:left}
.ob-plan li{display:flex;align-items:center;gap:.7rem;font-size:.9rem;color:var(--text-secondary)}
.ob-plan li span{flex:0 0 1.5rem;height:1.5rem;border-radius:50%;background:var(--accent-soft);
  color:var(--accent-text);font-weight:700;font-size:.78rem;display:flex;align-items:center;justify-content:center}

/* ─── two-factor setup ─────────────────────────────────────────────────────── */
.tfa-qr{display:flex;justify-content:center;padding:1rem;background:#fff;border:1px solid var(--border);
  border-radius:var(--radius-sm);margin-top:.75rem}
.tfa-qr img,.tfa-qr canvas{display:block}
.tfa-form{display:flex;flex-direction:column;gap:.5rem;margin-top:.75rem}
@media(min-width:520px){.tfa-form{flex-direction:row;align-items:center}
  .tfa-form .form-input{flex:1 1 auto}}
.tfa-code-input{font-family:var(--font-mono);font-size:1.35rem;letter-spacing:.35em;text-align:center}
.tfa-codes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.4rem;margin-top:.75rem}
@media(min-width:520px){.tfa-codes{grid-template-columns:repeat(4,minmax(0,1fr))}}
.tfa-codes code{font-family:var(--font-mono);font-size:.9rem;text-align:center;padding:.5rem .3rem;
  background:var(--surface-inset);border:1px solid var(--border);border-radius:6px;color:var(--text);
  letter-spacing:.06em}

/* ─── short messages, top of screen ────────────────────────────────────────── */
/* Used when something a member did was refused, and when the connection drops.
   Fixed to the top so it is seen wherever they are on the page. */
.cim-notices{position:fixed;top:calc(var(--header-h) + .6rem);left:50%;transform:translateX(-50%);
  z-index:80;display:flex;flex-direction:column;gap:.5rem;width:min(30rem,calc(100vw - 1.5rem));
  pointer-events:none}
.cim-notice{display:flex;align-items:flex-start;gap:.75rem;padding:.75rem .9rem;border-radius:var(--radius-sm);
  background:var(--surface);border:1px solid var(--border);box-shadow:var(--shadow-lg);
  font-size:.875rem;line-height:1.5;color:var(--text);pointer-events:auto;
  opacity:0;transform:translateY(-8px);transition:opacity .2s ease,transform .2s ease}
.cim-notice.is-in{opacity:1;transform:translateY(0)}
.cim-notice span{flex:1;min-width:0}
.cim-notice button{flex-shrink:0;background:none;border:0;color:var(--text-muted);font-size:1.15rem;
  line-height:1;cursor:pointer;padding:0 .1rem;border-radius:4px}
.cim-notice button:hover{color:var(--text)}
/* The tint is layered over the solid card colour rather than replacing it.
   The warning and success tokens are deliberately see-through, so setting one
   as the only background left the page showing straight through the message. */
.cim-notice.is-warn{border-left:3px solid var(--warning);
  background:linear-gradient(var(--warning-bg),var(--warning-bg)),var(--surface)}
.cim-notice.is-good{border-left:3px solid var(--success);
  background:linear-gradient(var(--success-bg),var(--success-bg)),var(--surface)}
.cim-notice.is-info{border-left:3px solid var(--accent)}
@media(max-width:640px){ .cim-notices{top:calc(var(--header-h) + .4rem)} }

/* ─── backup row actions ───────────────────────────────────────────────────── */
/* An inline form sits on the text baseline while the button beside it is a flex
   box, so Download and Delete sat at slightly different heights until a reload
   changed the font metrics. Making the row a flex line settles it on first
   paint, every time. */
.bk-actions{display:flex;align-items:center;gap:.4rem;flex-wrap:wrap}
.bk-actions form{display:contents}

/* ─── membership plan picker on signup ─────────────────────────────────────── */
/* The chosen plan used a 10% tint of the brand blue, which read as barely
   different from the two beside it. Solid company blue, so the choice is
   unmistakable at a glance and on a phone in daylight. */
.reg-plan{background:var(--surface)}
.reg-plan:hover{border-color:var(--border-strong)}
.reg-plan:has(:checked){background:var(--btn-blue);border-color:var(--btn-blue);box-shadow:var(--shadow-sm)}
.reg-plan:has(:checked),
.reg-plan:has(:checked) *{color:#fff!important}
.reg-plan:has(:checked) span{font-weight:600}
/* Older browsers without :has still get a clear state from the focus ring. */
.reg-plan:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-ring)}

/* ─── merge field helper ───────────────────────────────────────────────────── */
/* Eighteen field names is more than anybody remembers, and guessing one that
   does not exist gets the send refused. So the list sits on every page where
   you write an email, and each one copies itself when clicked. */
.mf-help{border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-2);
  margin-top:.75rem;overflow:hidden}
.mf-help summary{padding:.65rem .85rem;cursor:pointer;font-size:.85rem;font-weight:600;color:var(--text);
  list-style:none;display:flex;align-items:center;gap:.4rem}
.mf-help summary::-webkit-details-marker{display:none}
.mf-help summary::before{content:'+';font-weight:700;color:var(--accent);font-size:1rem;line-height:1}
.mf-help[open] summary::before{content:'-'}
.mf-help summary:hover{background:var(--surface-3)}
.mf-note{padding:0 .85rem;font-size:.78rem;color:var(--text-secondary);line-height:1.5;margin-bottom:.5rem}
.mf-grid{display:grid;grid-template-columns:1fr;gap:.3rem;padding:0 .85rem .85rem}
@media(min-width:560px){.mf-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1000px){.mf-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
.mf-chip{display:flex;flex-direction:column;gap:.1rem;align-items:flex-start;text-align:left;
  padding:.45rem .6rem;border:1px solid var(--border);border-radius:6px;background:var(--surface);
  cursor:pointer;transition:border-color .15s ease,background-color .15s ease;min-height:36px}
.mf-chip:hover{border-color:var(--accent);background:var(--accent-soft)}
.mf-chip code{font-family:var(--font-mono);font-size:.76rem;color:var(--accent-text);font-weight:600}
.mf-chip em{font-style:normal;font-size:.7rem;color:var(--text-muted);line-height:1.3}
.mf-chip.is-copied{border-color:var(--success);background:var(--success-bg)}
.mf-chip.is-copied code{color:var(--success)}

/* ─── template editing ─────────────────────────────────────────────────────── */
.tpl-edit{margin-top:.85rem;padding-top:.85rem;border-top:1px solid var(--border)}
.tpl-edit-bar{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}
.tpl-form{margin-top:.85rem;padding:.9rem;background:var(--surface-2);border:1px solid var(--border);
  border-radius:var(--radius-sm)}
.tpl-form .form-input{width:100%}
.tpl-body{font-family:var(--font-mono);font-size:.82rem;line-height:1.65;resize:vertical}
.tpl-hint{font-size:.78rem;color:var(--text-muted);line-height:1.5;margin:.6rem 0 .8rem}

/* A field chip sitting inside a sentence rather than in the grid above. */
.mf-chip-inline{display:inline-flex;padding:.1rem .35rem;margin:0 .12rem;vertical-align:baseline}
.mf-chip-inline em{display:none}

/* ── Member photo on the profile page ────────────────────────────────────────
   The file input itself is hidden rather than styled: browsers each draw it
   their own way and none of them match the rest of the page. The label beside
   it is the button, and clicking it opens the same picker. */
.avatar-xl{width:4.5rem;height:4.5rem;font-size:1.75rem}
.pf-hero{display:flex;justify-content:center;margin-bottom:1rem}
.pf-hero .avatar{width:5rem;height:5rem;font-size:2rem}
.pf-photo{display:flex;align-items:center;gap:1rem;flex-wrap:wrap}
.pf-photo-form{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap;margin:0}
.pf-file{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.pf-file:focus-visible + label{outline:2px solid var(--accent);outline-offset:2px}
.pf-photo-hint{font-size:.75rem;color:var(--text-muted)}
@media(max-width:520px){
  .pf-photo{gap:.75rem}
  .pf-photo-form{width:100%}
  .pf-photo-hint{flex-basis:100%}
}

/* The signed-in member's own row on the leaderboard. */
.avatar.is-me{box-shadow:0 0 0 2px var(--accent)}

/* While a photo is on its way up. */
.pf-photo.is-busy{opacity:.55;pointer-events:none}
.pf-photo.is-busy .avatar{transition:opacity .15s ease}

/* ── The field list, inside the editor ───────────────────────────────────────
   One row that scrolls sideways rather than a grid that grows downwards, so
   opening it never changes the height of the box you are typing in. */
.fb{margin-top:.5rem}
.fb-toggle{display:inline-flex;align-items:center;gap:.4rem}
.fb-n{display:inline-flex;align-items:center;justify-content:center;min-width:1.2rem;height:1.2rem;
  padding:0 .3rem;border-radius:var(--radius-pill);background:var(--surface-3);
  color:var(--text-muted);font-size:.68rem;font-weight:700}
.fb-toggle[aria-expanded="true"] .fb-n{background:var(--btn-blue);color:#fff}
.fb-strip{display:flex;gap:.35rem;overflow-x:auto;-webkit-overflow-scrolling:touch;
  padding:.5rem .1rem;margin-top:.4rem;scrollbar-width:thin}
.fb-strip::-webkit-scrollbar{height:6px}
.fb-strip::-webkit-scrollbar-thumb{background:var(--border-strong);border-radius:3px}
.fb-chip{flex:0 0 auto;font-family:var(--font-mono);font-size:.75rem;font-weight:600;
  padding:.3rem .55rem;border-radius:var(--radius-sm);cursor:pointer;white-space:nowrap;
  border:1px solid var(--border);background:var(--surface-2);color:var(--accent-text)}
.fb-chip:hover{border-color:var(--accent);background:var(--accent-soft)}
.fb-chip.is-own{border-color:var(--btn-blue);background:var(--accent-soft)}
.fb-chip.is-other{opacity:.55}
.fb-key{display:inline-flex;align-items:center;gap:.3rem;margin-left:.15rem}
.fb-swatch{display:inline-block;width:.7rem;height:.7rem;border-radius:3px;
  border:1px solid var(--border-strong);background:var(--surface-2);opacity:.55}
.fb-chip.is-copied{border-color:var(--success);background:var(--success-bg);color:var(--success)}
.fb-hint{font-size:.72rem;color:var(--text-muted);line-height:1.45;margin-top:.15rem}

/* ── Putting a template of your own on a repeat ──────────────────────────── */
.tpl-sched{border:1px solid var(--border);border-radius:var(--radius-sm);
  background:var(--surface-2);padding:.85rem;margin-top:.75rem}
.tpl-sched legend{font-size:.8rem;font-weight:700;color:var(--text);padding:0 .35rem}
.tpl-sched-row{display:grid;grid-template-columns:1fr;gap:.6rem}
@media(min-width:700px){.tpl-sched-row{grid-template-columns:repeat(4,minmax(0,1fr))}}
.tpl-sched-f{display:flex;flex-direction:column;min-width:0}
.tpl-sched-f .form-label{margin-bottom:.2rem}
/* What a repeating template does, shown on its row. */
.tpl-when{font-size:.75rem;color:var(--accent-text);font-weight:600}

/* ── Previous / Next under a long list ─────────────────────────────────────── */
.pgr{display:flex;align-items:center;justify-content:center;gap:.75rem;margin-top:.75rem}
.pgr-count{font-size:.8rem;color:var(--text-muted);font-variant-numeric:tabular-nums;min-width:7rem;
  text-align:center}
.pgr button[disabled]{opacity:.4;cursor:default}

/* ─── Licence activity ─────────────────────────────────────────────────────
   Reuses the message-log shell (.elog-*) and adds only what a licence check
   needs that an email does not: its own column widths, the day bars, and the
   panel of reasons things were refused. */

/* What is failing right now, above everything else. No email goes out for a
   refused licence on purpose, so this line is the whole alarm. */
.llog-alarm{display:flex;gap:.9rem;align-items:flex-start;margin-bottom:1.25rem;
  background:var(--warning-bg);border:1px solid var(--warning-border);
  border-radius:var(--radius-sm);padding:.9rem 1.05rem}
.llog-alarm-n{font-family:var(--font-display);font-size:1.6rem;font-weight:700;
  color:var(--warning);line-height:1}
.llog-alarm-body{font-size:.875rem;color:var(--text);line-height:1.5;min-width:0}
.llog-alarm-list{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:.45rem}
.llog-alarm-list a{font-size:.78rem;padding:.2rem .55rem;border-radius:var(--radius-pill);
  background:var(--surface);border:1px solid var(--border);color:var(--text-secondary);
  text-decoration:none;white-space:nowrap}
.llog-alarm-list a:hover{border-color:var(--accent);color:var(--accent-text)}

/* Checks per day. Plain boxes rather than a chart library, so it costs nothing
   and cannot arrive blank after a no-reload page swap. */
.llog-chartcard{margin-bottom:1.25rem;padding:1rem 1.1rem}
.llog-chart{display:flex;align-items:flex-end;gap:2px;height:84px;
  border-bottom:1px solid var(--border)}
/* The slot behind each day is nearly invisible on purpose. At the surface-3 it
   used to be, a day with no checks drew a full-height box that read as a bar
   the same size as a busy day - the one thing a chart must never do. It is
   still there so every day stays a hover target. */
.llog-bar{flex:1 1 0;min-width:2px;height:100%;position:relative;border-radius:2px 2px 0 0;
  background:var(--surface-2)}
.llog-bar-fill,.llog-bar-bad{position:absolute;left:0;right:0;bottom:0;border-radius:2px 2px 0 0}
.llog-bar-fill{background:var(--accent);opacity:.55}
.llog-bar-bad{background:var(--danger)}
.llog-bar:hover .llog-bar-fill{opacity:.9}
.llog-chart-l{margin-top:.6rem;font-size:.75rem;color:var(--text-muted)}

/* Why licences were refused, worst first. Each one is a filter, which is what
   turns a list of events into something you can act on. */
.llog-reasons{display:grid;grid-template-columns:1fr;gap:.5rem;margin-bottom:1.25rem}
@media(min-width:760px){.llog-reasons{grid-template-columns:repeat(2,minmax(0,1fr))}}
.llog-reason{display:grid;grid-template-columns:auto auto 1fr;align-items:center;gap:.6rem;
  padding:.6rem .8rem;background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius-sm);text-decoration:none;min-width:0}
.llog-reason:hover{border-color:var(--accent)}
.llog-reason.is-on{border-color:var(--accent);background:var(--accent-soft)}
.llog-reason b{font-family:var(--font-display);font-size:1.05rem;color:var(--text)}
.llog-reason em{font-style:normal;font-size:.74rem;color:var(--text-muted);line-height:1.35;
  min-width:0;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}

/* Six columns rather than the message log's seven, and wider where an
   identifier lives, because a truncated licence key helps nobody. */
@media(min-width:900px){
  .llog-list .elog-row{grid-template-columns:5.5rem 9rem minmax(0,1.7fr) 9.5rem minmax(0,1fr) minmax(0,1fr)}
}
.llog-list .elog-row code{font-family:var(--font-mono);font-size:.78rem}

/* Five controls, one row.
   The shared panel is four equal columns with the search box spanning two, which
   is right for the message log's nine fields but wraps this page's five onto a
   second line for no reason. These are sized to what they hold instead: the
   search box wide because a licence key is 31 characters, the three menus even,
   and the button only as wide as its own word.
   Same specificity as the rule it replaces, and later in the file, so it wins
   without !important. Below 1100px it falls back to the shared panel's own
   two- and one-column layouts. */
@media(min-width:1100px){
  .elog-filterwrap.is-open .llog-filters{
    grid-template-columns:minmax(0,2.4fr) minmax(0,1fr) minmax(0,1fr) minmax(0,1fr) auto;
    align-items:end}
  .llog-filters .elog-field-wide{grid-column:auto}
}
