/* ==========================================================================
   "Nebula" — PDF 题库平台 design system
   Modern, student-friendly. Dark mode via prefers-color-scheme / [data-theme].
   ========================================================================== */

/* ---- design tokens ------------------------------------------------------ */
:root {
  /* brand */
  --accent: #6366f1;
  --accent-strong: #4f46e5;
  --accent-soft: #eef2ff;
  --accent-glow: rgba(99, 102, 241, 0.25);
  --accent2: #14b8a6;
  --accent2-soft: #ecfdf5;

  /* surface */
  --bg: #f8fafc;
  --bg-soft: #f1f5f9;
  --surface: #ffffff;
  --surface-hover: #f8fafc;
  --surface-elevated: #ffffff;

  /* text */
  --text: #0f172a;
  --text-secondary: #475569;
  --text-muted: #94a3b8;
  --text-inverse: #ffffff;

  /* border */
  --border: #e2e8f0;
  --border-light: #f1f5f9;
  --border-focus: #a5b4fc;

  /* semantic */
  --green: #10b981;
  --green-soft: #ecfdf5;
  --green-border: #a7f3d0;
  --amber: #f59e0b;
  --amber-soft: #fffbeb;
  --amber-border: #fcd34d;
  --red: #ef4444;
  --red-soft: #fef2f2;
  --red-border: #fecaca;
  --blue: #3b82f6;
  --blue-soft: #eff6ff;

  /* radius */
  --radius-sm: 8px;
  --radius: 12px;
  --radius-lg: 16px;
  --radius-xl: 20px;
  --radius-full: 999px;

  /* shadows — layered for depth */
  --shadow-xs: 0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow-sm: 0 1px 3px rgba(15, 23, 42, 0.06), 0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow: 0 4px 6px rgba(15, 23, 42, 0.04), 0 2px 4px rgba(15, 23, 42, 0.04);
  --shadow-md: 0 10px 15px rgba(15, 23, 42, 0.06), 0 4px 6px rgba(15, 23, 42, 0.04);
  --shadow-lg: 0 20px 25px rgba(15, 23, 42, 0.06), 0 8px 10px rgba(15, 23, 42, 0.04);
  --shadow-xl: 0 25px 50px rgba(15, 23, 42, 0.12);

  /* glass */
  --glass-bg: rgba(255, 255, 255, 0.72);
  --glass-border: rgba(226, 232, 240, 0.8);
  --glass-blur: saturate(180%) blur(20px);

  /* spacing */
  --space-xs: 4px;
  --space-sm: 8px;
  --space: 12px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 32px;
  --space-2xl: 48px;

  /* animation */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --duration-fast: 150ms;
  --duration: 250ms;
  --duration-slow: 400ms;
}

/* ---- dark theme --------------------------------------------------------- */
[data-theme="dark"] {
  --bg: #1a2236;
  --bg-soft: #222b42;
  --surface: #263148;
  --surface-hover: #2d3a54;
  --surface-elevated: #2d3a54;

  --text: #f1f5f9;
  --text-secondary: #94a3b8;
  --text-muted: #64748b;
  --text-inverse: #0f172a;

  --border: #334155;
  --border-light: #1e293b;
  --border-focus: #6366f1;

  --accent-soft: #1e1b4b;
  --accent2-soft: #022c22;

  --green-soft: #022c22;
  --green-border: #065f46;
  --amber-soft: #451a03;
  --amber-border: #78350f;
  --red-soft: #450a0a;
  --red-border: #7f1d1d;
  --blue-soft: #172554;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.2);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2);
  --shadow: 0 4px 6px rgba(0, 0, 0, 0.25), 0 2px 4px rgba(0, 0, 0, 0.15);
  --shadow-md: 0 10px 15px rgba(0, 0, 0, 0.3), 0 4px 6px rgba(0, 0, 0, 0.2);
  --shadow-lg: 0 20px 25px rgba(0, 0, 0, 0.35), 0 8px 10px rgba(0, 0, 0, 0.2);
  --shadow-xl: 0 25px 50px rgba(0, 0, 0, 0.5);

  --glass-bg: rgba(30, 41, 59, 0.75);
  --glass-border: rgba(51, 65, 85, 0.8);

  --accent-glow: rgba(99, 102, 241, 0.35);
}

/* ---- reset & base ------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

[hidden] { display: none !important; }

html, body { min-height: 100%; }

body {
  margin: 0;
  color: var(--text);
  background: var(--bg);
  font: 14px/1.6 system-ui, -apple-system, "Segoe UI", "Inter", "Microsoft YaHei", sans-serif;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transition: background var(--duration) var(--ease-out), color var(--duration) var(--ease-out);
}

button, input, textarea, select { font: inherit; }

button { cursor: pointer; }

button:disabled, input:disabled, textarea:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

a { color: var(--accent); text-decoration: none; transition: color var(--duration-fast) var(--ease-out); }
a:hover { color: var(--accent-strong); }

/* ---- scrollbar (Webkit) ------------------------------------------------ */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: var(--radius-full); }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

/* ---- selection ---------------------------------------------------------- */
::selection { background: var(--accent-soft); color: var(--accent-strong); }

/* ---- focus ring --------------------------------------------------------- */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* ==========================================================================
   Topbar — glass-morphism sticky header
   ========================================================================== */

.topbar-spa {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: 10px 20px;
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid var(--glass-border);
  position: sticky;
  top: 0;
  z-index: 50;
  min-height: 60px;
  transition: background var(--duration) var(--ease-out), border-color var(--duration) var(--ease-out);
}

.brand-link {
  text-decoration: none;
  color: inherit;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.brand-link h1 {
  margin: 0;
  font-size: 18px;
  font-weight: 800;
  background: linear-gradient(135deg, var(--accent) 0%, #8b5cf6 50%, var(--accent2) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  letter-spacing: -0.3px;
}

.brand-link p {
  margin: 0;
  color: var(--text-muted);
  font-size: 11px;
  display: none;
}

@media (min-width: 640px) {
  .brand-link p { display: block; }
}

/* ---- primary nav (pill tabs) -------------------------------------------- */
.primary-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  flex: 1 1 auto;
  justify-content: center;
}

.nav-link {
  text-decoration: none;
  color: var(--text-secondary);
  border: 1px solid transparent;
  border-radius: var(--radius-full);
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 500;
  transition: all var(--duration-fast) var(--ease-out);
  position: relative;
}

.nav-link:hover {
  color: var(--text);
  background: var(--bg-soft);
}

.nav-link.active {
  color: var(--accent-strong);
  background: var(--accent-soft);
  border-color: var(--border-focus);
  font-weight: 600;
}

/* ---- user chip ---------------------------------------------------------- */
.user-chip {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  flex-shrink: 0;
}

.user-chip .role-badge {
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- theme toggle ------------------------------------------------------- */
.theme-toggle {
  width: 38px;
  height: 38px;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: var(--surface);
  color: var(--text-secondary);
  display: grid;
  place-items: center;
  font-size: 16px;
  transition: all var(--duration-fast) var(--ease-out);
  flex-shrink: 0;
}

.theme-toggle:hover {
  background: var(--bg-soft);
  color: var(--text);
  border-color: var(--border-focus);
}

/* ==========================================================================
   Role badge
   ========================================================================== */

.role-badge {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 14px;
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  background: var(--bg-soft);
  color: var(--text-secondary);
  font-size: 13px;
  white-space: nowrap;
  transition: all var(--duration-fast) var(--ease-out);
}

body[data-role="user"] .role-badge {
  color: var(--green);
  border-color: var(--green-border);
  background: var(--green-soft);
}

body[data-role="super_root"] .role-badge,
body[data-role="subject_root"] .role-badge {
  color: var(--accent-strong);
  border-color: var(--border-focus);
  background: var(--accent-soft);
}

body[data-role="invalid"] .role-badge {
  color: var(--red);
  border-color: var(--red-border);
  background: var(--red-soft);
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  min-height: 38px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 8px 16px;
  background: var(--surface);
  color: var(--text);
  font-weight: 500;
  font-size: 13px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: all var(--duration-fast) var(--ease-out);
  white-space: nowrap;
  text-decoration: none;
}

.btn:hover:not(:disabled) {
  background: var(--bg-soft);
  border-color: var(--border-focus);
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}

.btn:active:not(:disabled) {
  transform: translateY(0);
  box-shadow: none;
}

.btn.primary {
  border-color: var(--accent);
  background: linear-gradient(135deg, var(--accent) 0%, #7c3aed 100%);
  color: #fff;
  font-weight: 600;
  box-shadow: 0 2px 8px var(--accent-glow);
}

.btn.primary:hover:not(:disabled) {
  background: linear-gradient(135deg, var(--accent-strong) 0%, #6d28d9 100%);
  box-shadow: 0 4px 16px var(--accent-glow);
  transform: translateY(-2px);
}

.btn.ghost {
  background: transparent;
  border-color: transparent;
}

.btn.ghost:hover:not(:disabled) {
  background: var(--bg-soft);
}

.btn.danger {
  border-color: var(--red);
  background: var(--red);
  color: #fff;
  font-weight: 600;
}

.btn.danger:hover:not(:disabled) {
  background: #dc2626;
  box-shadow: 0 2px 8px rgba(239, 68, 68, 0.25);
}

/* ==========================================================================
   Buttons — size variants
   ========================================================================== */

.btn-sm {
  min-height: 32px;
  padding: 5px 12px;
  font-size: 12px;
  border-radius: var(--radius-sm);
}

.btn-lg {
  min-height: 46px;
  padding: 10px 24px;
  font-size: 15px;
  border-radius: var(--radius-lg);
}

/* ==========================================================================
   Form controls
   ========================================================================== */

input, textarea, select {
  width: 100%;
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  background: var(--surface);
  padding: 10px 12px;
  outline: none;
  transition: all var(--duration-fast) var(--ease-out);
  font-size: 14px;
}

textarea {
  min-height: 120px;
  resize: vertical;
}

input:focus, textarea:focus, select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}

select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2394a3b8' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 36px;
}

label { display: grid; gap: var(--space-xs); }
label > span { color: var(--text-secondary); font-size: 13px; font-weight: 500; }

.form-grid {
  display: grid;
  gap: var(--space);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.form-grid > .form-row { grid-column: 1 / -1; }

.form-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
}

/* ---- check row ---------------------------------------------------------- */
.check-row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.check-row input { width: auto; }

/* ==========================================================================
   Page shell
   ========================================================================== */

.page {
  padding: var(--space-lg);
  /* New shell (issue #47 step 1): main column is laid out by body grid;
     the page should fill it (no centered max-width creating right-side
     empty space on wide screens). */
  max-width: none;
  margin: 0;
  display: grid;
  gap: var(--space-md);
  animation: pageIn var(--duration-slow) var(--ease-out);
}

@keyframes pageIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes scaleIn {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}

/* ==========================================================================
   Cards
   ========================================================================== */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  box-shadow: var(--shadow-sm);
  transition: all var(--duration) var(--ease-out);
}

.card:hover {
  box-shadow: var(--shadow);
}

.card h2 {
  margin: 0 0 var(--space) 0;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.2px;
}

.card .muted {
  color: var(--text-muted);
  font-size: 13px;
}

.card hr {
  border: none;
  border-top: 1px solid var(--border-light);
  margin: var(--space-md) 0;
}

/* ---- card variants ------------------------------------------------------ */
.card-glass {
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
}

.card-accent {
  border-left: 3px solid var(--accent);
}

/* ==========================================================================
   Tiles (subject-home dashboard)
   ========================================================================== */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-md);
}

.tile {
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  transition: all var(--duration) var(--ease-spring);
  position: relative;
  overflow: hidden;
}

.tile::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, var(--accent) 0%, #8b5cf6 100%);
  opacity: 0;
  transition: opacity var(--duration) var(--ease-out);
  border-radius: var(--radius-lg);
}

.tile:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: var(--border-focus);
}

.tile:hover::before {
  opacity: 0.03;
}

.tile h3 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  position: relative;
  z-index: 1;
}

.tile-num {
  font-size: 36px;
  font-weight: 800;
  background: linear-gradient(135deg, var(--accent) 0%, #8b5cf6 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  margin: var(--space-sm) 0;
  position: relative;
  z-index: 1;
  line-height: 1.2;
}

.tile p {
  margin: 0;
  color: var(--text-muted);
  font-size: 13px;
  position: relative;
  z-index: 1;
}

/* ==========================================================================
   Paper list & hit cards
   ========================================================================== */

.paper-list, .history-list, .result-list {
  display: grid;
  gap: var(--space-sm);
  margin-top: var(--space);
}

.paper-item, .history-item, .hit {
  width: 100%;
  text-align: left;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 12px 14px;
  transition: all var(--duration-fast) var(--ease-out);
  text-decoration: none;
  color: inherit;
  display: block;
}

.paper-item:hover, .hit:hover {
  border-color: var(--border-focus);
  background: var(--accent-soft);
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}

.paper-item.active {
  border-color: var(--border-focus);
  background: var(--accent-soft);
  box-shadow: var(--shadow-sm);
}

.item-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-sm);
  font-weight: 700;
  font-size: 14px;
}

.item-meta {
  margin-top: var(--space-xs);
  color: var(--text-muted);
  font-size: 12px;
  overflow-wrap: anywhere;
}

/* ---- hit card (search results) ----------------------------------------- */
.hit {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr);
  gap: 12px;
  align-items: center;
}

.hit.clickable { cursor: pointer; }

.hit img {
  width: 72px;
  height: 72px;
  object-fit: cover;
  background: var(--bg-soft);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-sm);
  transition: transform var(--duration-fast) var(--ease-out);
}

.hit:hover img { transform: scale(1.05); }

.hit-main { min-width: 0; }

.hit-main strong {
  display: block;
  overflow-wrap: anywhere;
  font-size: 14px;
}

.hit-sub {
  color: var(--text-muted);
  font-size: 12px;
  margin-top: var(--space-xs);
}

/* ==========================================================================
   Badges
   ========================================================================== */

.badge {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding: 2px 10px;
  border-radius: var(--radius-full);
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
  transition: all var(--duration-fast) var(--ease-out);
}

.badge.matched, .badge.ok, .badge.user {
  background: var(--green-soft);
  color: var(--green);
}

.badge.ambiguous, .badge.warn {
  background: var(--amber-soft);
  color: var(--amber);
}

.badge.no_match {
  background: var(--red-soft);
  color: var(--red);
}

.badge.root {
  background: var(--accent-soft);
  color: var(--accent-strong);
}

/* ==========================================================================
   Status pills & lines
   ========================================================================== */

.status-pill {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-full);
  padding: 3px 12px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
  transition: all var(--duration-fast) var(--ease-out);
}

.status-pill.ok    { color: var(--green); background: var(--green-soft); }
.status-pill.error { color: var(--red);   background: var(--red-soft); }
.status-pill.warn  { color: var(--amber); background: var(--amber-soft); }

.status-line {
  display: flex;
  align-items: center;
  min-height: 44px;
  margin-bottom: var(--space-md);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 10px 14px;
  color: var(--text-secondary);
  font-size: 13px;
  transition: all var(--duration-fast) var(--ease-out);
}

.status-line.ok {
  color: var(--green);
  background: var(--green-soft);
  border-color: var(--green-border);
}

.status-line.warn {
  color: var(--amber);
  background: var(--amber-soft);
  border-color: var(--amber-border);
}

.status-line.error {
  color: var(--red);
  background: var(--red-soft);
  border-color: var(--red-border);
}

/* ---- page alerts -------------------------------------------------------- */
.page-error {
  border: 1px solid var(--red-border);
  background: var(--red-soft);
  color: var(--red);
  padding: 14px 16px;
  border-radius: var(--radius);
  font-size: 13px;
}

.page-warning {
  border: 1px solid var(--amber-border);
  background: var(--amber-soft);
  color: var(--amber);
  padding: 14px 16px;
  border-radius: var(--radius);
  font-size: 13px;
}

/* ==========================================================================
   Empty state
   ========================================================================== */

.empty-state {
  display: grid;
  place-items: center;
  min-height: 200px;
  border: 2px dashed var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-soft);
  color: var(--text-muted);
  text-align: center;
  padding: var(--space-lg);
  font-size: 14px;
}

/* ==========================================================================
   Image viewer — zoom/pan replacement for static images
   ========================================================================== */

.image-panel {
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--bg-soft);
  transition: all var(--duration) var(--ease-out);
  position: relative;
}

.image-panel h3 {
  margin: 0;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  font-size: 14px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
}

.image-panel.empty {
  min-height: 240px;
  display: grid;
  place-items: center;
  color: var(--text-muted);
  font-size: 14px;
}

/* zoomable container */
.zoom-container {
  position: relative;
  overflow: hidden;
  cursor: zoom-in;
  background: var(--bg-soft);
  display: grid;
  place-items: center;
  min-height: 200px;
  max-height: 72vh;
  touch-action: none;
}

.zoom-container img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 72vh;
  object-fit: contain;
  transition: transform var(--duration-fast) var(--ease-out);
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}

.zoom-container.zoomed {
  cursor: grab;
  overflow: auto;
}

.zoom-container.zoomed:active {
  cursor: grabbing;
}

.zoom-container.zoomed img {
  max-height: none;
  width: auto;
  min-width: 100%;
}

/* zoom controls */
.zoom-controls {
  position: absolute;
  bottom: 12px;
  right: 12px;
  display: flex;
  gap: 4px;
  z-index: 10;
  opacity: 0;
  transition: opacity var(--duration-fast) var(--ease-out);
}

.image-panel:hover .zoom-controls,
.zoom-container.zoomed .zoom-controls {
  opacity: 1;
}

.zoom-btn {
  width: 34px;
  height: 34px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-size: 16px;
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out);
  box-shadow: var(--shadow-sm);
}

.zoom-btn:hover {
  background: var(--bg-soft);
  border-color: var(--border-focus);
  transform: scale(1.05);
}

/* ==========================================================================
   Lightbox overlay
   ========================================================================== */

.lightbox-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(15, 23, 42, 0.92);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: grid;
  place-items: center;
  padding: var(--space-lg);
  animation: fadeIn var(--duration) var(--ease-out);
  cursor: zoom-out;
}

.lightbox-overlay img {
  max-width: 95vw;
  max-height: 90vh;
  object-fit: contain;
  border-radius: var(--radius);
  box-shadow: var(--shadow-xl);
  cursor: grab;
  user-select: none;
  -webkit-user-drag: none;
  transition: transform var(--duration-fast) var(--ease-out);
}

.lightbox-overlay img:active {
  cursor: grabbing;
}

.lightbox-close {
  position: fixed;
  top: var(--space-md);
  right: var(--space-md);
  width: 44px;
  height: 44px;
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: var(--radius-full);
  background: rgba(30, 41, 59, 0.8);
  color: #fff;
  font-size: 22px;
  display: grid;
  place-items: center;
  cursor: pointer;
  z-index: 1001;
  transition: all var(--duration-fast) var(--ease-out);
  backdrop-filter: blur(12px);
}

.lightbox-close:hover {
  background: rgba(239, 68, 68, 0.8);
  border-color: rgba(239, 68, 68, 0.5);
  transform: scale(1.08);
}

.lightbox-info {
  position: fixed;
  bottom: var(--space-md);
  left: 50%;
  transform: translateX(-50%);
  color: rgba(255,255,255,0.7);
  font-size: 12px;
  background: rgba(30, 41, 59, 0.7);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: var(--radius-full);
  padding: 6px 16px;
  backdrop-filter: blur(12px);
  z-index: 1001;
}

/* ==========================================================================
   Viewer grid
   ========================================================================== */

.viewer-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-md);
}

.viewer-grid.four {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 1024px) {
  .viewer-grid.four {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* ==========================================================================
   Workspace (legacy split-pane)
   ========================================================================== */

.shell {
  display: grid;
  grid-template-columns: 380px minmax(0, 1fr);
  min-height: calc(100vh - 60px);
}

.sidebar {
  background: var(--surface);
  border-right: 1px solid var(--border);
  overflow: auto;
  max-height: calc(100vh - 60px);
  transition: background var(--duration) var(--ease-out);
}

.tabs {
  position: sticky;
  top: 0;
  z-index: 3;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  padding: 12px;
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid var(--border);
}

.tab {
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: 8px 10px;
  background: transparent;
  color: var(--text-muted);
  font-weight: 500;
  transition: all var(--duration-fast) var(--ease-out);
}

.tab.active {
  color: var(--text);
  background: var(--bg-soft);
  border-color: var(--border);
  font-weight: 600;
}

.tab:hover:not(.active) {
  color: var(--text);
  background: var(--surface-hover);
}

.panel {
  display: none;
  padding: 14px;
}

.panel.active {
  display: grid;
  gap: 14px;
}

.workspace {
  min-width: 0;
  padding: var(--space-md);
  overflow: auto;
  max-height: calc(100vh - 60px);
}

/* ---- tool blocks -------------------------------------------------------- */
.tool-block {
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 14px;
  transition: all var(--duration) var(--ease-out);
}

.block-title, .pane-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space);
  margin-bottom: var(--space);
  flex-wrap: wrap;
}

.block-title h2, .pane-head h2 {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.2px;
}

.block-title span, .pane-head span {
  color: var(--text-muted);
  font-size: 12px;
}

/* ---- paper summary ------------------------------------------------------ */
.paper-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-soft);
  padding: 14px;
  flex-wrap: wrap;
}

/* ---- question buttons --------------------------------------------------- */
.question-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: var(--space-sm);
}

.question-button {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  min-height: 44px;
  font-weight: 600;
  font-size: 13px;
  transition: all var(--duration-fast) var(--ease-out);
}

.question-button:hover {
  background: var(--accent-soft);
  border-color: var(--border-focus);
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}

.question-button.no-answer {
  background: var(--amber-soft);
  border-color: var(--amber-border);
}

/* ---- drop zone (ingest) ------------------------------------------------ */
.drop-zone {
  position: relative;
  min-width: 0;
  display: grid;
  place-items: center;
  min-height: 200px;
  border: 2px dashed var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-soft);
  padding: var(--space-lg);
  outline: none;
  cursor: pointer;
  transition: all var(--duration) var(--ease-out);
}

.drop-zone:hover {
  border-color: var(--border-focus);
  background: var(--accent-soft);
}

.drop-zone.dragging {
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: 0 0 0 4px var(--accent-glow);
}

.drop-zone input { display: none; }

.drop-copy {
  display: grid;
  gap: var(--space-xs);
  text-align: center;
  color: var(--text-muted);
  pointer-events: none;
}

.drop-copy strong {
  color: var(--text);
  font-size: 16px;
  font-weight: 600;
}

.drop-zone.has-image .drop-copy { display: none; }

#imagePreview {
  display: block;
  max-width: 100%;
  max-height: 280px;
  object-fit: contain;
  background: var(--surface);
  border-radius: var(--radius-sm);
}

#imagePreview[hidden] { display: none !important; }

/* ==========================================================================
   Pill tabs (search mode switcher etc.)
   ========================================================================== */

.tabs.three {
  display: inline-flex;
  gap: 4px;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  padding: 4px;
  background: var(--bg-soft);
}

.tabs.three .tab {
  border: none;
  border-radius: var(--radius-full);
  padding: 7px 18px;
  background: transparent;
  color: var(--text-muted);
  font-weight: 500;
  font-size: 13px;
  transition: all var(--duration-fast) var(--ease-out);
}

.tabs.three .tab.active {
  background: var(--surface);
  color: var(--text);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}

.tabs.three .tab:hover:not(.active) {
  color: var(--text);
}

/* ==========================================================================
   Data table
   ========================================================================== */

.table-wrap {
  overflow-x: auto;
  border-radius: var(--radius);
  border: 1px solid var(--border);
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.data-table th, .data-table td {
  border-bottom: 1px solid var(--border-light);
  padding: 10px 14px;
  text-align: left;
  vertical-align: middle;
}

.data-table th {
  background: var(--bg-soft);
  font-weight: 600;
  color: var(--text-secondary);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.data-table tbody tr {
  transition: background var(--duration-fast) var(--ease-out);
}

.data-table tbody tr:hover {
  background: var(--surface-hover);
}

/* ---- bar cell (trends chart) ------------------------------------------- */
.bar-cell {
  position: relative;
  height: 22px;
  background: var(--bg-soft);
  border-radius: var(--radius-sm);
  overflow: hidden;
  min-width: 80px;
}

.bar-cell .bar {
  height: 100%;
  background: linear-gradient(90deg, var(--accent) 0%, #8b5cf6 100%);
  border-radius: var(--radius-sm);
  transition: width var(--duration-slow) var(--ease-out);
}

.bar-cell span {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 11px;
  color: var(--text);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   Point tree
   ========================================================================== */

.tree, .tree ul {
  list-style: none;
  padding-left: 20px;
  margin: 0;
}

.tree > li {
  padding: 5px 0;
  font-size: 14px;
}

.point-tree details > summary {
  cursor: pointer;
  padding: 6px 0;
  font-weight: 500;
  color: var(--text);
  transition: color var(--duration-fast) var(--ease-out);
}

.point-tree details > summary:hover {
  color: var(--accent);
}

.point-tree details > summary code {
  font-weight: 700;
  color: var(--accent-strong);
  background: var(--accent-soft);
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  font-size: 12px;
}

/* ==========================================================================
   KV list
   ========================================================================== */

.kv {
  display: grid;
  gap: var(--space-sm);
  margin: var(--space-sm) 0;
  font-size: 13px;
}

.kv strong {
  color: var(--text-secondary);
}

/* ==========================================================================
   JSON / code output
   ========================================================================== */

.json-output {
  margin: 0;
  max-height: 500px;
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: #0f172a;
  color: #e2e8f0;
  padding: 14px;
  font-size: 12px;
  font-family: "JetBrains Mono", "Fira Code", "Cascadia Code", monospace;
  line-height: 1.7;
}

[data-theme="dark"] .json-output {
  background: #020617;
  color: #cbd5e1;
}

/* ==========================================================================
   Spinner
   ========================================================================== */

.spinner {
  width: 20px;
  height: 20px;
  display: inline-block;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: var(--radius-full);
  animation: spin 0.7s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ---- skeleton loading --------------------------------------------------- */
.skeleton {
  background: linear-gradient(90deg, var(--bg-soft) 25%, var(--border-light) 50%, var(--bg-soft) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm);
}

@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

.skeleton-text {
  height: 14px;
  margin-bottom: var(--space-sm);
}

.skeleton-title {
  height: 22px;
  width: 60%;
  margin-bottom: var(--space);
}

.skeleton-card {
  height: 80px;
  border-radius: var(--radius);
}

.skeleton-img {
  height: 200px;
  border-radius: var(--radius);
}

/* ==========================================================================
   Actions row
   ========================================================================== */

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-top: var(--space);
}

.actions.compact {
  margin-top: 0;
  justify-content: flex-end;
}

/* ---- file row ----------------------------------------------------------- */
.file-row {
  display: grid;
  gap: 6px;
  margin-top: 10px;
}

.file-row span {
  color: var(--text-muted);
  font-size: 12px;
}

/* ---- history ------------------------------------------------------------ */
.history-item {
  display: grid;
  gap: var(--space-sm);
}

.history-actions {
  display: flex;
  justify-content: flex-end;
}

/* ---- root lock ---------------------------------------------------------- */
.root-lock {
  display: none;
  border: 1px solid var(--amber-border);
  border-radius: var(--radius);
  background: var(--amber-soft);
  color: #92400e;
  padding: 14px;
  font-size: 13px;
}

body:not([data-role="super_root"]):not([data-role="subject_root"]) .root-lock {
  display: block;
}

body:not([data-role="super_root"]):not([data-role="subject_root"]) .root-only {
  display: none;
}

/* ---- subject banner ----------------------------------------------------- */
.subject-banner h2 {
  margin-bottom: var(--space-xs);
}

/* ==========================================================================
   Login page — full-viewport image background, floating glass card.
   ========================================================================== */

body.on-login-page {
  background: #0f172a; /* fallback behind image */
}

body.on-login-page .topbar-spa,
body.on-login-page .topbar-lang {
  display: none;
}

/* ---- full-screen background image (covers entire page) ----------------- */
.login-bg-wrap {
  position: fixed;
  inset: -5%;
  z-index: 0;
  transform: scaleX(-1); /* flip — put figure on left, away from form */
}

.login-bg {
  position: absolute;
  inset: 0;
  background: url("/ui/img/hero-bg.png") center center / cover no-repeat;
  animation: heroZoom 20s var(--ease-in-out) infinite alternate;
  filter: brightness(0.95);
}

@keyframes heroZoom {
  0%   { transform: scale(1); }
  100% { transform: scale(1.06); }
}

/* full-page soft overlay — keeps text readable */
.login-bg-overlay {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(135deg, rgba(99,102,241,0.15) 0%, transparent 40%, rgba(20,184,166,0.08) 100%),
    linear-gradient(to top, rgba(15,23,42,0.55) 0%, transparent 35%);
}

body.on-login-page .page {
  padding: 0;
  max-width: none;
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  position: relative;
  overflow: hidden;
}

/* ---- hero panel (left) — brand text over the image --------------------- */
.login-hero {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
}

.login-hero-content {
  text-align: center;
  color: #fff;
  padding: var(--space-xl);
  max-width: 480px;
  animation: heroFadeIn 1.2s var(--ease-out) 0.3s both;
}

@keyframes heroFadeIn {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: translateY(0); }
}

.login-hero-content h1 {
  margin: 0 0 var(--space-md) 0;
  font-size: 36px;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.5px;
  text-shadow: 0 2px 24px rgba(0,0,0,0.5);
}

.login-hero-content p {
  margin: 0;
  font-size: 16px;
  opacity: 0.9;
  line-height: 1.6;
  text-shadow: 0 1px 8px rgba(0,0,0,0.4);
}

.login-hero-content .hero-logo {
  font-size: 52px;
  margin-bottom: var(--space-lg);
  display: inline-block;
  animation: logoFloat 3s var(--ease-in-out) infinite;
  filter: drop-shadow(0 4px 16px rgba(0,0,0,0.3));
}

/* ---- right panel — glass form floating over the image ------------------ */
.login-form-panel {
  display: grid;
  place-items: center;
  padding: var(--space-xl);
  z-index: 1;
  position: relative;
}

body.on-login-page .login-card {
  z-index: 1;
  position: relative;
  max-width: 420px;
  width: 100%;
  animation: heroFadeIn 0.8s var(--ease-out) 0.5s both;
  /* glass — semi-transparent so the image shows through subtly */
  background: rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, 0.35);
  box-shadow: 0 8px 32px rgba(15, 23, 42, 0.12), 0 2px 8px rgba(15, 23, 42, 0.06);
}

[data-theme="dark"] body.on-login-page .login-card {
  background: rgba(30, 41, 59, 0.68);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3), 0 2px 8px rgba(0, 0, 0, 0.2);
}

/* fade out the card's own star BG when over the full-page image */
body.on-login-page .login-card::before { opacity: 0.3; }
body.on-login-page .login-card .login-glow { opacity: 0.5; }

/* ---- shooting stars overlay (both panels) ------------------------------ */
.login-particles {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.login-particles .shooting-star {
  position: fixed;
}

/* ---- login utilities bar ----------------------------------------------- */
.login-utils {
  position: fixed;
  top: var(--space-md);
  right: var(--space-md);
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  z-index: 10;
}

.login-theme-btn {
  width: 36px;
  height: 36px;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: var(--surface);
  color: var(--text-secondary);
  display: grid;
  place-items: center;
  font-size: 15px;
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out);
}

.login-theme-btn:hover {
  background: var(--bg-soft);
  border-color: var(--border-focus);
  color: var(--text);
}

/* ---- responsive — stack on mobile -------------------------------------- */
@media (max-width: 800px) {
  body.on-login-page .page {
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr;
  }

  .login-hero {
    min-height: 180px;
    max-height: 260px;
  }

  .login-hero-content h1 {
    font-size: 22px;
  }

  .login-hero-content p {
    font-size: 13px;
    display: none;
  }

  .login-hero-content .hero-logo {
    font-size: 32px;
    margin-bottom: var(--space-sm);
  }

  .login-form-panel {
    padding: var(--space-md);
    align-items: start;
    padding-top: var(--space-lg);
  }
}

/* ---- keep old card styles (non-login pages) ---------------------------- */
.login-card {
  max-width: 420px;
  width: 100%;
  padding: var(--space-xl) var(--space-lg);
  position: relative;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  isolation: isolate;
}

/* ---- starry sky inside the card ---------------------------------------- */
.login-card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    /* bright white-blue stars */
    radial-gradient(1px 1px at 8% 12%, rgba(203,213,225,0.9) 50%, transparent 50%),
    radial-gradient(0.7px 0.7px at 15% 22%, rgba(226,232,240,0.75) 50%, transparent 50%),
    radial-gradient(1.1px 1.1px at 22% 8%,  rgba(255,255,255,0.85) 50%, transparent 50%),
    radial-gradient(0.6px 0.6px at 28% 32%, rgba(203,213,225,0.7) 50%, transparent 50%),
    radial-gradient(0.9px 0.9px at 35% 15%, rgba(226,232,240,0.8) 50%, transparent 50%),
    radial-gradient(0.5px 0.5px at 42% 28%, rgba(255,255,255,0.7) 50%, transparent 50%),
    radial-gradient(1px 1px at 50% 5%,  rgba(203,213,225,0.85) 50%, transparent 50%),
    radial-gradient(0.8px 0.8px at 58% 18%, rgba(226,232,240,0.75) 50%, transparent 50%),
    radial-gradient(1.1px 1.1px at 65% 35%, rgba(255,255,255,0.8) 50%, transparent 50%),
    radial-gradient(0.6px 0.6px at 72% 12%, rgba(203,213,225,0.7) 50%, transparent 50%),
    radial-gradient(0.9px 0.9px at 78% 25%, rgba(226,232,240,0.8) 50%, transparent 50%),
    radial-gradient(0.5px 0.5px at 85% 8%,  rgba(255,255,255,0.7) 50%, transparent 50%),
    radial-gradient(1px 1px at 92% 30%, rgba(203,213,225,0.85) 50%, transparent 50%),
    radial-gradient(0.7px 0.7px at 95% 18%, rgba(226,232,240,0.75) 50%, transparent 50%),
    radial-gradient(0.6px 0.6px at 18% 38%, rgba(203,213,225,0.7) 50%, transparent 50%),
    radial-gradient(0.9px 0.9px at 55% 38%, rgba(226,232,240,0.7) 50%, transparent 50%),
    radial-gradient(0.7px 0.7px at 82% 38%, rgba(203,213,225,0.65) 50%, transparent 50%),
    radial-gradient(0.5px 0.5px at 3% 5%,   rgba(255,255,255,0.75) 50%, transparent 50%),
    radial-gradient(0.8px 0.8px at 48% 35%, rgba(226,232,240,0.7) 50%, transparent 50%),
    /* colored accent stars */
    radial-gradient(1.2px 1.2px at 40% 10%,  rgba(99,102,241,0.7) 50%, transparent 50%),
    radial-gradient(1.2px 1.2px at 70% 20%,  rgba(139,92,246,0.65) 50%, transparent 50%),
    radial-gradient(1px 1px at 88% 15%, rgba(20,184,166,0.6) 50%, transparent 50%),
    radial-gradient(1.2px 1.2px at 12% 25%,  rgba(99,102,241,0.6) 50%, transparent 50%),
    radial-gradient(0.9px 0.9px at 33% 30%,  rgba(139,92,246,0.5) 50%, transparent 50%),
    radial-gradient(1px 1px at 90% 35%,  rgba(20,184,166,0.55) 50%, transparent 50%);
  animation: starsTwinkle 3s ease-in-out infinite;
}

@keyframes starsTwinkle {
  0%, 100% { opacity: 0.75; }
  33% { opacity: 1; }
  66% { opacity: 0.82; }
}

/* ---- shooting stars — DOM elements (multiple, continuous) -------------- */
.shooting-star {
  position: absolute;
  z-index: 0;
  pointer-events: none;
  height: 1.5px;
  background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0) 15%, rgba(226,232,240,0.9) 35%, rgba(255,255,255,1) 50%, rgba(226,232,240,0.6) 65%, transparent 100%);
  border-radius: 1px;
  transform: rotate(-28deg);
  box-shadow: 0 0 8px 2px rgba(226,232,240,0.3), 0 0 16px 4px rgba(203,213,225,0.18);
}

.shooting-star:nth-child(1) { top: 15%; left: -10%; width: 90px; animation: shoot1 3.5s linear infinite; }
.shooting-star:nth-child(2) { top: 5%;  left: -10%; width: 70px; animation: shoot2 4.2s linear infinite; animation-delay: 1.8s; }
.shooting-star:nth-child(3) { top: 30%; left: -10%; width: 100px; animation: shoot3 5s linear infinite; animation-delay: 3s; }

.shooting-star::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 45%;
  width: 4px;
  height: 4px;
  background: rgba(255,255,255,0.95);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 10px 3px rgba(226,232,240,0.5);
}

@keyframes shoot1 {
  0%   { transform: rotate(-28deg) translate(0, 0); opacity: 0; }
  3%   { opacity: 1; }
  18%  { transform: rotate(-28deg) translate(550px, 280px); opacity: 0; }
  100% { transform: rotate(-28deg) translate(550px, 280px); opacity: 0; }
}
@keyframes shoot2 {
  0%   { transform: rotate(-28deg) translate(0, 0); opacity: 0; }
  3%   { opacity: 1; }
  16%  { transform: rotate(-28deg) translate(520px, 220px); opacity: 0; }
  100% { transform: rotate(-28deg) translate(520px, 220px); opacity: 0; }
}
@keyframes shoot3 {
  0%   { transform: rotate(-28deg) translate(0, 0); opacity: 0; }
  2%   { opacity: 1; }
  14%  { transform: rotate(-28deg) translate(480px, 260px); opacity: 0; }
  100% { transform: rotate(-28deg) translate(480px, 260px); opacity: 0; }
}

/* remove old single shooting star pseudo-element */
.login-card::after { display: none; }

/* soft radial glow behind the form — AI ambient feel */
.login-card .login-glow {
  content: "";
  position: absolute;
  top: -60%;
  left: -30%;
  width: 160%;
  height: 160%;
  background: radial-gradient(ellipse at 50% 0%, var(--accent-soft) 0%, transparent 70%);
  opacity: 0.5;
  pointer-events: none;
  z-index: 0;
  transition: opacity var(--duration-slow) var(--ease-out);
}

[data-theme="dark"] .login-card .login-glow {
  background: radial-gradient(ellipse at 50% 0%, rgba(99,102,241,0.1) 0%, transparent 70%);
  opacity: 0.7;
}

/* ---- language switch --------------------------------------------------- */
.lang-switch {
  display: flex;
  justify-content: flex-end;
  gap: 4px;
  margin-bottom: var(--space-sm);
  position: relative;
  z-index: 1;
}

.lang-btn {
  width: 36px;
  height: 30px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out);
}

.lang-btn:hover {
  color: var(--text);
  border-color: var(--border-focus);
}

.lang-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* ---- brand lockup ------------------------------------------------------ */
.login-brand {
  text-align: center;
  margin-bottom: var(--space-lg);
  position: relative;
  z-index: 1;
}

.login-logo {
  font-size: 48px;
  margin-bottom: var(--space-sm);
  line-height: 1;
  display: inline-block;
  animation: logoFloat 3s var(--ease-in-out) infinite;
}

@keyframes logoFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

.login-brand h2 {
  margin: 0 0 var(--space-xs) 0;
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.3px;
  background: linear-gradient(135deg, var(--accent) 0%, #8b5cf6 50%, var(--accent2) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

.login-brand .muted {
  font-size: 13px;
  color: var(--text-secondary);
}

/* ---- AI tag ------------------------------------------------------------ */
.login-ai-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: var(--space-sm);
  font-size: 11px;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--border-focus);
  border-radius: var(--radius-full);
  padding: 4px 12px;
  position: relative;
  z-index: 1;
}

.login-ai-tag .ai-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  animation: aiPulse 1.8s ease-in-out infinite;
}

@keyframes aiPulse {
  0%, 100% { opacity: 0.4; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.4); }
}

/* ---- fields ------------------------------------------------------------ */
.login-fields {
  display: grid;
  gap: var(--space-md);
  position: relative;
  z-index: 1;
}

.field {
  display: grid;
  gap: var(--space-xs);
}

.field label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
  display: flex;
  align-items: baseline;
  gap: var(--space-xs);
  flex-wrap: wrap;
}

.field-hint {
  font-weight: 400;
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
}

.field input {
  width: 100%;
  padding: 11px 14px;
  font-size: 14px;
  border-radius: var(--radius);
  transition: all var(--duration-fast) var(--ease-out);
}

.field input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow), 0 0 20px rgba(99,102,241,0.08);
}

.totp-row {
  display: flex;
  gap: var(--space-sm);
  align-items: center;
}

.totp-row input {
  flex: 1;
  min-width: 0;
}

.btn-text {
  background: none;
  border: none;
  color: var(--accent);
  cursor: pointer;
  font-size: 12px;
  font-weight: 500;
  padding: 4px 0;
  white-space: nowrap;
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color var(--duration-fast) var(--ease-out);
}

.btn-text:hover {
  color: var(--accent-strong);
}

/* ---- submit button ----------------------------------------------------- */
.login-submit {
  width: 100%;
  margin-top: var(--space-xs);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 2px;
  position: relative;
  z-index: 1;
  box-shadow: 0 4px 20px var(--accent-glow);
}

.login-submit:hover:not(:disabled) {
  box-shadow: 0 6px 28px rgba(99,102,241,0.4);
  transform: translateY(-2px);
}

/* ---- feedback ---------------------------------------------------------- */
.login-feedback {
  min-height: 22px;
  font-size: 13px;
  text-align: center;
  padding: var(--space-xs) 0;
  color: var(--text-muted);
  transition: color var(--duration-fast) var(--ease-out);
  position: relative;
  z-index: 1;
}

.login-feedback.is-error {
  color: var(--red);
  font-weight: 500;
}

.login-feedback.is-ok {
  color: var(--green);
  font-weight: 500;
}

/* ---- help text --------------------------------------------------------- */
.login-help {
  text-align: center;
  font-size: 13px;
  color: var(--text-muted);
  margin: var(--space-md) 0 0;
  position: relative;
  z-index: 1;
}

.login-help .btn-text {
  font-size: 13px;
}

/* ---- divider & details in login card ----------------------------------- */
.login-card hr { position: relative; z-index: 1; }
.login-card details { position: relative; z-index: 1; }

/* ---- legacy overrides --------------------------------------------------- */
.login-form .form-row { justify-content: flex-start; }
.login-card .login-form .form-row { justify-content: flex-start; }

/* ==========================================================================
   Token field & legacy auth
   ========================================================================== */

.token-field {
  display: grid;
  gap: var(--space-xs);
  min-width: 280px;
  max-width: 520px;
  flex: 1;
}

.token-field span {
  color: var(--text-muted);
  font-size: 12px;
}

.authbar {
  flex: 1;
  display: flex;
  align-items: end;
  justify-content: flex-end;
  gap: var(--space-sm);
  min-width: 0;
}

.local-auth {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-sm);
  color: var(--text-muted);
  font-size: 12px;
}

.local-auth strong { color: var(--text); }

.local-auth code {
  max-width: 280px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  padding: 5px 8px;
}

/* ==========================================================================
   Utility: link highlight
   ========================================================================== */

body[data-role="anonymous"] .nav-link { display: none; }
body[data-role="anonymous"] .user-chip { display: none; }

/* ---- topbar language switch -------------------------------------------- */
.topbar-lang { margin-right: 2px; }
.topbar-lang .lang-btn { width: 32px; height: 28px; font-size: 11px; }

/* ==========================================================================
   Skip to main content (accessibility)
   ========================================================================== */

.skip-link {
  position: absolute;
  top: -100%;
  left: 12px;
  z-index: 100;
  background: var(--accent);
  color: #fff;
  padding: 8px 16px;
  border-radius: var(--radius);
  font-weight: 600;
  font-size: 13px;
  text-decoration: none;
}

.skip-link:focus {
  top: 12px;
}

/* ==========================================================================
   Responsive — tablet
   ========================================================================== */

@media (max-width: 1080px) {
  .shell {
    grid-template-columns: 1fr;
  }

  .sidebar {
    max-height: none;
    border-right: none;
    border-bottom: 1px solid var(--border);
  }

  .workspace {
    max-height: none;
  }
}

/* ==========================================================================
   Responsive — mobile
   ========================================================================== */

@media (max-width: 820px) {
  .topbar-spa {
    flex-wrap: wrap;
    gap: var(--space-sm);
    padding: 10px 14px;
  }

  .primary-nav {
    order: 3;
    width: 100%;
    justify-content: flex-start;
    overflow-x: auto;
    padding-bottom: var(--space-xs);
  }

  .shell {
    grid-template-columns: 1fr;
  }

  .sidebar, .panel, .workspace {
    width: 100%;
    max-width: 100vw;
    overflow-x: hidden;
  }

  .panel, .workspace {
    padding: 12px;
  }

  .block-title, .pane-head {
    align-items: flex-start;
    flex-direction: column;
    gap: var(--space-xs);
  }

  .block-title span, .pane-head span {
    text-align: left;
  }

  .workspace-grid, .viewer-grid, .viewer-grid.four {
    grid-template-columns: 1fr;
  }

  .page {
    padding: var(--space);
  }

  .tiles {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  }

  .hit {
    grid-template-columns: 56px minmax(0, 1fr);
    gap: var(--space-sm);
    padding: 10px;
  }

  .hit img {
    width: 56px;
    height: 56px;
  }

  .tabs.three {
    flex-wrap: wrap;
  }

  .user-chip .role-badge {
    max-width: 180px;
    font-size: 12px;
  }
}

/* ==========================================================================
   Filter bar — inline filter row (papers, audit)
   ========================================================================== */

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 14px 0;
}

.filter-field {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
}

.filter-field span {
  color: var(--text-muted);
  font-size: 12px;
  white-space: nowrap;
}

.filter-field select,
.filter-field input {
  width: auto;
  min-width: 80px;
  padding: 7px 10px;
  font-size: 13px;
}

.filter-bar > input[type="search"] {
  flex: 1;
  min-width: 160px;
  max-width: 280px;
  padding: 7px 12px;
  font-size: 13px;
}

/* ==========================================================================
   Ingest — full-width two-column layout
   ========================================================================== */

.ingest-shell {
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr);
  gap: 0;
  min-height: calc(100vh - 60px - 48px);
  margin: -18px;
}

.ingest-sidebar {
  background: var(--surface);
  border-right: 1px solid var(--border);
  padding: 20px;
  overflow-y: auto;
}

.ingest-main {
  padding: 20px;
  overflow-y: auto;
  background: var(--bg-soft);
}

.ingest-main {
  background: var(--surface);
  display: flex;
  flex-direction: column;
}

.ingest-main .json-output {
  max-height: none;
  min-height: 300px;
  margin: 0;
  flex: 1;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.ingest-main .empty-state {
  flex: 1;
  margin: 0;
}

.file-pick {
  display: grid;
  gap: 6px;
  padding: 16px;
  border: 2px dashed var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out);
  margin-bottom: var(--space);
  text-align: center;
}

.file-pick:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.file-pick input { display: none; }

.file-pick-icon {
  font-size: 24px;
  color: var(--accent);
  font-weight: 300;
}

.file-pick-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}

.file-pick-hint {
  font-size: 12px;
  color: var(--text-muted);
}

/* ==========================================================================
   Admin panel — tab panel visibility
   ========================================================================== */

.admin-panel { display: none; }
.admin-panel.active { display: block; }

@media (max-width: 800px) {
  .ingest-shell {
    grid-template-columns: 1fr;
    margin: -12px;
  }
  .ingest-sidebar { border-right: none; border-bottom: 1px solid var(--border); }
}

/* ==========================================================================
   Motion — reduced motion preference
   ========================================================================== */

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

/* ==========================================================================
   AI Chat standalone page (#/ai/chat)
   ========================================================================== */
.ai-chat-shell {
  max-width: 880px; margin: 0 auto; padding: 16px;
  display: flex; flex-direction: column; height: calc(100vh - 140px);
  background: var(--surface-elevated); border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.ai-chat-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; border-bottom: 1px solid var(--border-light);
  background: linear-gradient(180deg, var(--accent-soft) 0%, var(--surface) 100%);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.ai-chat-head h2 { margin: 0; font-size: 17px; }
.ai-chat-head-actions { display: flex; align-items: center; gap: 8px; }
.ai-chat-msgs {
  flex: 1; overflow-y: auto; padding: 16px;
  display: flex; flex-direction: column; gap: 12px;
}
.ai-chat-msgs .ai-msg { /* same styles as widget */ }
.ai-chat-input {
  border-top: 1px solid var(--border-light);
  padding: 8px 12px 12px;
  background: var(--surface);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}
.ai-pending-img {
  position: relative; display: inline-block; margin-bottom: 8px;
}
.ai-pending-img img {
  max-height: 120px; max-width: 200px; border-radius: var(--radius-sm);
  border: 1px solid var(--border);
}
.ai-img-x {
  position: absolute; top: -8px; right: -8px;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--text); color: var(--text-inverse);
  border: 2px solid var(--surface); cursor: pointer;
  font-size: 14px; line-height: 1; padding: 0;
}
.ai-msg-img {
  display: block; max-width: 220px; max-height: 160px;
  border-radius: var(--radius-sm); margin-bottom: 6px;
}
.ai-status {
  font-size: 12px; color: var(--text-muted); min-height: 16px;
  margin-bottom: 4px; padding: 0 4px;
}
.ai-tool-btn {
  width: 36px; height: 36px; border-radius: var(--radius-sm);
  background: var(--surface-hover); border: 1px solid var(--border);
  color: var(--text-secondary); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s var(--ease-out), color 0.15s var(--ease-out);
}
.ai-tool-btn:hover { background: var(--accent-soft); color: var(--accent-strong); }
.ai-voice-btn.recording {
  background: #fee2e2; color: #dc2626; border-color: #fca5a5;
  animation: ai-pulse 1.2s ease-in-out infinite;
}
@keyframes ai-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.4); }
  50%      { box-shadow: 0 0 0 8px rgba(220, 38, 38, 0); }
}

/* ==========================================================================
   AI suggestion chips on question detail page
   ========================================================================== */
.ai-suggest-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 10px 12px;
  background: linear-gradient(135deg, var(--accent-soft) 0%,
                                       var(--accent2-soft) 100%);
  border: 1px solid var(--border-light);
  border-radius: var(--radius);
}
.ai-chip {
  padding: 6px 12px; font-size: 13px;
  background: var(--surface); color: var(--accent-strong);
  border: 1px solid var(--border); border-radius: var(--radius-full);
  cursor: pointer; transition: transform 0.15s var(--ease-out),
                                background 0.15s var(--ease-out);
}
.ai-chip:hover {
  transform: translateY(-1px);
  background: var(--accent); color: var(--text-inverse);
  border-color: var(--accent);
}

/* ==========================================================================
   AI Material Library admin page
   ========================================================================== */
.ai-mat-card {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 14px; margin-bottom: 12px;
  background: var(--surface);
}
.ai-mat-card header {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  margin-bottom: 8px; font-size: 12px;
}
.ai-mat-card .badge.pending  { background: #fef3c7; color: #92400e; }
.ai-mat-card .badge.approved { background: #d1fae5; color: #065f46; }
.ai-mat-card .badge.rejected { background: #fee2e2; color: #991b1b; }
.ai-mat-body { display: grid; gap: 10px;
               grid-template-columns: 1fr 1fr; margin-bottom: 10px; }
@media (max-width: 720px) { .ai-mat-body { grid-template-columns: 1fr; } }
.ai-mat-q, .ai-mat-a {
  background: var(--bg-soft); padding: 10px; border-radius: var(--radius-sm);
  border: 1px solid var(--border-light);
}
.ai-mat-q pre, .ai-mat-a pre {
  font: inherit; font-size: 13px; line-height: 1.5; white-space: pre-wrap;
  margin: 4px 0 0; max-height: 240px; overflow: auto;
}

/* ==========================================================================
   Notifications admin — iPhone-inspired
   ========================================================================== */

.notify-page {
  max-width: 600px;
  margin: 0 auto;
  display: grid;
  gap: 20px;
  padding: 8px 0;
}

.notify-card {
  background: var(--surface);
  border-radius: 16px;
  padding: 20px 22px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.04);
}

.notify-title {
  margin: 0 0 2px;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.3px;
}

.notify-hint {
  margin: 0 0 18px;
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.4;
}

.notify-subtitle {
  margin: 0 0 12px;
  font-size: 15px;
  font-weight: 600;
  color: var(--text-secondary);
}

.notify-error {
  color: var(--red);
  font-size: 13px;
  text-align: center;
  padding: 24px;
}

/* ---- form ---------------------------------------------------------------- */

.notify-form {
  display: grid;
  gap: 12px;
}

/* Kind chips — horizontal scrollable segmented control */
.notify-kinds {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-bottom: 4px;
  -webkit-overflow-scrolling: touch;
}

.notify-kind-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  border-radius: 10px;
  background: var(--bg-soft);
  border: 1.5px solid transparent;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  transition: all 0.2s var(--ease-out);
  white-space: nowrap;
  flex-shrink: 0;
  user-select: none;
}

.notify-kind-chip input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.notify-kind-chip:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.notify-kind-chip.active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-strong);
  font-weight: 600;
}

.notify-kind-icon {
  font-size: 16px;
  line-height: 1;
}

/* Row fields — audience + expiry side by side */
.notify-row-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.notify-input,
.notify-select {
  width: 100%;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  color: var(--text);
  font-size: 14px;
  outline: none;
  transition: border-color 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
  box-sizing: border-box;
}

.notify-input:focus,
.notify-select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}

.notify-select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2394a3b8' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 32px;
}

.notify-textarea {
  resize: vertical;
  min-height: 64px;
  font: inherit;
}

/* Form footer — msg + submit */
.notify-form-foot {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-top: 4px;
}

.notify-msg {
  flex: 1;
  font-size: 12px;
  color: var(--text-muted);
}

.notify-msg--ok    { color: var(--green); }
.notify-msg--error { color: var(--red); }

.notify-submit {
  padding: 10px 24px;
  border: none;
  border-radius: 10px;
  background: var(--accent);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s var(--ease-out);
}

.notify-submit:hover {
  background: var(--accent-strong);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px var(--accent-glow);
}

/* ---- history rows -------------------------------------------------------- */

.notify-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border-light);
  transition: background 0.15s var(--ease-out);
}

.notify-row:last-child {
  border-bottom: none;
}

.notify-row-icon {
  font-size: 18px;
  flex-shrink: 0;
  width: 28px;
  text-align: center;
}

.notify-row-body {
  flex: 1;
  min-width: 0;
}

.notify-row-title {
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.notify-row-preview {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.notify-row-aud {
  font-size: 11px;
  font-weight: 500;
  color: var(--accent-strong);
  background: var(--accent-soft);
  padding: 3px 8px;
  border-radius: 6px;
  white-space: nowrap;
  flex-shrink: 0;
}

.notify-row-time {
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

.notify-row-del {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.15s var(--ease-out);
  flex-shrink: 0;
}

.notify-row-del:hover {
  background: var(--red-soft);
  color: var(--red);
}

.notify-empty {
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
  padding: 20px 0;
}

/* ---- responsive ---------------------------------------------------------- */

@media (max-width: 640px) {
  .notify-card {
    padding: 16px;
    border-radius: 12px;
  }

  .notify-row-fields {
    grid-template-columns: 1fr;
  }

  .notify-row-aud {
    display: none;
  }

  .notify-row-time {
    font-size: 10px;
  }
}

/* ==========================================================================
   Sidebar shell (issue #47 step 1) — left primary nav + top utility row
   Replaces the old .topbar-spa horizontal layout; iPhone-simple style.
   ========================================================================== */

body {
  display: grid;
  grid-template-columns: var(--sb-w, 248px) minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  grid-template-areas:
    "sidebar topbar"
    "sidebar main";
  min-height: 100vh;
  min-height: 100dvh;
  transition: grid-template-columns 0.32s cubic-bezier(0.4, 0, 0.2, 1);
}

body.sidebar-collapsed { --sb-w: 56px; }

body.on-login-page {
  grid-template-columns: 1fr;
  grid-template-areas:
    "topbar"
    "main";
}
body.on-login-page .sidebar { display: none; }

/* ---- sidebar ---- */
.sidebar {
  grid-area: sidebar;
  background: var(--surface, #fff);
  border-right: 1px solid var(--border-light, #e5e7eb);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  z-index: 30;
}

.sidebar-brand {
  padding: 18px 16px 12px;
  border-bottom: 1px solid var(--border-light, #e5e7eb);
}
.sidebar-brand-link {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none; color: inherit;
}
.sidebar-brand-icon {
  font-size: 22px; color: var(--accent, #6366f1); flex-shrink: 0;
  width: 28px; text-align: center;
}
.sidebar-brand-text {
  display: flex; flex-direction: column; gap: 1px;
  overflow: hidden; min-width: 0;
  transition: opacity 0.22s ease;
}
.sidebar-brand-title {
  font-size: 14px; font-weight: 700;
  color: var(--text, #111827);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sidebar-brand-tag {
  font-size: 11px; color: var(--text-muted, #6b7280);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

body.sidebar-collapsed .sidebar-brand-text {
  opacity: 0; pointer-events: none;
}

/* ---- sidebar sections ---- */
.sidebar-section {
  padding: 8px 8px;
  border-bottom: 1px solid var(--border-light, #e5e7eb);
}
.sidebar-section:last-of-type { border-bottom: none; }

.sidebar-section-label {
  font-size: 10px;
  font-weight: 600;
  color: var(--text-muted, #6b7280);
  text-transform: uppercase;
  letter-spacing: 0.6px;
  padding: 4px 8px;
  transition: opacity 0.22s ease;
}
body.sidebar-collapsed .sidebar-section-label { opacity: 0; }

/* ---- subject list / nav items / tools items — uniform sizing ---- */
.sidebar-subject-list,
.sidebar-nav,
.sidebar-tools-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin-top: 2px;
}

.sidebar-link,
.sidebar-tools-toggle {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px;
  border-radius: 8px;
  color: var(--text-secondary, #4b5563);
  text-decoration: none;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  border: none; background: none;
  width: 100%;
  text-align: left;
  transition: background 0.15s ease, color 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}
.sidebar-link:hover,
.sidebar-tools-toggle:hover {
  background: var(--surface-hover, #f3f4f6);
  color: var(--text, #111827);
}
.sidebar-link.active {
  background: var(--accent-soft, #eef2ff);
  color: var(--accent-strong, #4f46e5);
  font-weight: 600;
}

.sidebar-link-icon {
  flex-shrink: 0;
  width: 20px;
  text-align: center;
  font-size: 15px;
}
.sidebar-link-label {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: opacity 0.22s ease;
}
body.sidebar-collapsed .sidebar-link-label,
body.sidebar-collapsed .sidebar-tools-label,
body.sidebar-collapsed .sidebar-tools-chevron {
  opacity: 0; pointer-events: none;
}
body.sidebar-collapsed .sidebar-link,
body.sidebar-collapsed .sidebar-tools-toggle {
  justify-content: center;
  padding: 9px 8px;
}

/* ---- tools dropdown ---- */
.sidebar-tools-toggle {
  justify-content: space-between;
}
.sidebar-tools-toggle .sidebar-tools-icon {
  flex-shrink: 0;
  width: 20px;
  text-align: center;
  font-size: 14px;
}
.sidebar-tools-toggle .sidebar-tools-label {
  flex: 1;
}
.sidebar-tools-chevron {
  flex-shrink: 0;
  transition: transform 0.18s ease;
}
.sidebar-tools-toggle[aria-expanded="true"] .sidebar-tools-chevron {
  transform: rotate(180deg);
}

.sidebar-tools-list {
  padding: 4px 0 4px 0;
  margin-left: 0;
  animation: sidebarToolsSlide 0.22s ease;
}
.sidebar-tools-list .sidebar-link {
  padding-left: 36px;
  font-size: 12.5px;
  color: var(--text-muted, #6b7280);
}

@keyframes sidebarToolsSlide {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

body.sidebar-collapsed .sidebar-tools-list { display: none !important; }

/* ---- sidebar footer + collapse button ---- */
.sidebar-footer {
  margin-top: auto;
  padding: 8px;
  border-top: 1px solid var(--border-light, #e5e7eb);
  display: flex;
  justify-content: flex-end;
}
.sidebar-collapse-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border: none; background: none; cursor: pointer;
  border-radius: 8px;
  color: var(--text-muted, #6b7280);
  transition: background 0.15s ease, color 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}
.sidebar-collapse-btn:hover {
  background: var(--surface-hover, #f3f4f6);
  color: var(--text, #111827);
}
.sidebar-collapse-icon { transition: transform 0.32s cubic-bezier(0.4, 0, 0.2, 1); }
body.sidebar-collapsed .sidebar-collapse-icon { transform: rotate(180deg); }
body.sidebar-collapsed .sidebar-footer { justify-content: center; }

/* ==========================================================================
   Topbar — minimal utility row (issue #47 step 1)
   ========================================================================== */

.topbar {
  grid-area: topbar;
  display: flex; align-items: center; gap: 6px;
  padding: 8px 16px;
  background: var(--surface, #fff);
  border-bottom: 1px solid var(--border-light, #e5e7eb);
  min-height: 48px;
  box-sizing: border-box;
  position: sticky; top: 0; z-index: 20;
}

.topbar-burger {
  display: none;     /* visible on mobile only */
  align-items: center; justify-content: center;
  width: 36px; height: 36px;
  border: none; background: none; cursor: pointer;
  border-radius: 8px;
  color: var(--text-muted, #6b7280);
  -webkit-tap-highlight-color: transparent;
}
.topbar-burger:hover { background: var(--surface-hover, #f3f4f6); }

.topbar-spacer { flex: 1; }

.topbar-icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 36px; height: 36px;
  padding: 0 8px;
  border: none; background: none; cursor: pointer;
  border-radius: 8px;
  color: var(--text-muted, #6b7280);
  font-size: 13px; font-weight: 500;
  transition: background 0.15s ease, color 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}
.topbar-icon-btn:hover {
  background: var(--surface-hover, #f3f4f6);
  color: var(--text, #111827);
}

/* topbar-tools-slot is filled by tools.js with its 📖 toggle + input row */
.topbar-tools-slot { display: inline-flex; align-items: center; }

/* lang single-button popover (中/EN with horizontal options) */
.topbar-lang-wrap { position: relative; display: inline-flex; }

.topbar-lang-popover {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  display: flex;
  background: var(--surface-elevated, #fff);
  border: 1px solid var(--border-light, #e5e7eb);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(15,23,42,0.12);
  padding: 4px;
  gap: 2px;
  z-index: 50;
  animation: topbarLangPop 0.16s ease;
}
@keyframes topbarLangPop {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.topbar-lang-option {
  border: none; background: none; cursor: pointer;
  padding: 6px 14px;
  border-radius: 6px;
  font-size: 13px; color: var(--text, #111827);
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.topbar-lang-option:hover { background: var(--surface-hover, #f3f4f6); }
.topbar-lang-option.active {
  background: var(--accent-soft, #eef2ff);
  color: var(--accent-strong, #4f46e5);
  font-weight: 600;
}

/* main content area */
.page {
  grid-area: main;
  padding: 16px 20px;
  overflow-x: hidden;
}

/* ==========================================================================
   Mobile (≤ 720px) — sidebar slides over content; topbar burger visible
   ========================================================================== */

@media (max-width: 720px) {
  body {
    grid-template-columns: 1fr;
    grid-template-areas: "topbar" "main";
  }
  .sidebar {
    position: fixed; top: 0; left: 0;
    width: 248px; height: 100vh; height: 100dvh;
    transform: translateX(-100%);
    transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow: 0 12px 32px rgba(15,23,42,0.18);
  }
  body.sidebar-mobile-open .sidebar {
    transform: translateX(0);
  }
  .topbar-burger { display: inline-flex; }

  .sidebar-scrim {
    position: fixed; inset: 0;
    background: rgba(15,23,42,0.32);
    z-index: 25;
    animation: scrimFadeIn 0.22s ease;
  }
  @keyframes scrimFadeIn {
    from { opacity: 0; } to { opacity: 1; }
  }
  /* mobile: ignore desktop collapsed state, sidebar is full-width slide */
  body.sidebar-collapsed { --sb-w: 248px; }
  body.sidebar-collapsed .sidebar-link-label,
  body.sidebar-collapsed .sidebar-tools-label,
  body.sidebar-collapsed .sidebar-tools-chevron,
  body.sidebar-collapsed .sidebar-section-label,
  body.sidebar-collapsed .sidebar-brand-text {
    opacity: 1;
  }
  body.sidebar-collapsed .sidebar-link,
  body.sidebar-collapsed .sidebar-tools-toggle {
    justify-content: flex-start;
    padding: 9px 12px;
  }
}

/* ==========================================================================
   UI v3 step 1 fixes — page width / sidebar-page height consistency
   (issue #47 follow-up: 左右一致, 不要居中留白)
   ========================================================================== */

/* Make the main column at least as tall as the sidebar so the
   border-right line and the content area visually end at the same Y.
   Topbar is ~48px so we subtract that. */
.page {
  min-height: calc(100vh - 48px);
  min-height: calc(100dvh - 48px);
  align-content: start;
}

/* Sidebar bottom: don't push collapse btn far away from content.
   `margin-top: auto` is fine but the section gap was too generous —
   shrink the gap by tightening section padding. */
.sidebar-section { padding: 6px 8px; }
.sidebar-footer  { padding: 6px 8px; }

/* ---- card defaults: full width inside the column ---- */
.card,
.section.card,
section.card {
  width: 100%;
  max-width: none;
  box-sizing: border-box;
}

/* ---- admin/subjects: clickable subject cards (issue 1+6) ---- */
.subject-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 12px;
  margin-top: 16px;
}
.subject-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border-light);
  border-radius: 12px;
  text-decoration: none;
  color: var(--text);
  transition: all 0.18s ease;
  -webkit-tap-highlight-color: transparent;
  position: relative;
  cursor: pointer;
}
.subject-card:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(99, 102, 241, 0.08);
}
.subject-card-icon {
  width: 42px; height: 42px;
  flex-shrink: 0;
  display: grid; place-items: center;
  background: var(--accent-soft);
  color: var(--accent-strong);
  border-radius: 10px;
  font-size: 22px;
}
.subject-card-body { flex: 1; min-width: 0; }
.subject-card-title { font-size: 15px; font-weight: 600; }
.subject-card-meta  { font-size: 12px; color: var(--text-muted); margin-top: 2px;
                       white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.subject-card-arrow {
  flex-shrink: 0;
  color: var(--text-muted);
  transition: transform 0.18s ease;
}
.subject-card:hover .subject-card-arrow {
  color: var(--accent);
  transform: translateX(2px);
}

/* ---- ingest: rebalance left/right widths + single result frame ---- */
.ingest-shell {
  grid-template-columns: 280px minmax(0, 1fr) !important;
  margin: 0 !important;            /* override negative margin from old shell */
  min-height: calc(100vh - 96px);
}
.ingest-sidebar { padding: 18px; }
.ingest-main {
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 0;                          /* result is one box, not two */
}
.ingest-main .json-output { flex: 1; margin: 0; }
.ingest-main .empty-state { flex: 1; display: grid; place-items: center; }

/* ---- review: full layout, no inner shrink ---- */
.review-card { width: 100%; }

/* ---- ai/chat tip area: don't wrap, ellipsis instead ---- */
.ai-chat-tip,
.ai-chat-foot .muted {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 240px;
  font-size: 12px;
}

/* ---- admin/users: proportional grid for the form-grid sections ---- */
.card .form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
}
.card .form-grid label { display: flex; flex-direction: column; gap: 4px; }
.card .form-grid label > span:first-child {
  font-size: 12px; color: var(--text-muted);
}
.card .form-grid .form-row,
.card .form-grid label.check-row {
  grid-column: 1 / -1;
}

/* ---- admin/audit: border alignment + table fills column ---- */
.audit-table { width: 100%; }
.audit-table .table-wrap { width: 100%; }

/* ---- admin/ai-materials: gentler empty state instead of red 404 ---- */
.ai-mat-empty {
  padding: 28px 20px;
  text-align: center;
  color: var(--text-muted);
  font-size: 14px;
}

/* ---- admin/notifications: top border alignment fix ---- */
.notify-admin-layout > .notify-left,
.notify-admin-layout > .notify-right {
  align-self: stretch;
}
.notify-admin-layout .notify-card { box-sizing: border-box; }

/* ==========================================================================
   UI v3 step 2 — exam login / lesson plan / feedback / admin tweaks
   (issue #47 follow-up batch 2)
   ========================================================================== */

/* ---- Sidebar: collapse btn integrated with brand row, no footer gap ---- */
.sidebar { height: auto; min-height: 100vh; min-height: 100dvh; }
.sidebar-brand {
  display: flex; align-items: center; gap: 8px;
  justify-content: space-between;
}
.sidebar-brand .sidebar-brand-link {
  flex: 1; min-width: 0;
}
.sidebar-collapse-btn {
  width: 28px; height: 28px;
  border: none; background: none; cursor: pointer;
  border-radius: 8px;
  color: var(--text-muted, #6b7280);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  transition: background 0.15s ease;
}
.sidebar-collapse-btn:hover { background: var(--surface-hover, #f3f4f6); }
.sidebar-collapse-icon { transition: transform 0.32s cubic-bezier(0.4,0,0.2,1); }
body.sidebar-collapsed .sidebar-collapse-icon { transform: rotate(180deg); }
body.sidebar-collapsed .sidebar-collapse-btn { margin: 0 auto; }

/* sidebar bottom no longer has empty footer area; sections flow top→down */

/* ---- exam login page: A-level style ---- */
.exam-login {
  min-height: calc(100vh - 96px);
  display: grid;
  place-items: center;
  padding: 24px 16px;
}
.exam-login-card {
  width: 100%;
  max-width: 460px;
  background: var(--surface);
  border: 1px solid var(--border-light);
  border-radius: 16px;
  padding: 32px 28px;
  box-shadow: 0 4px 16px rgba(15,23,42,0.06);
}
.exam-login-head {
  text-align: center;
  border-bottom: 1px solid var(--border-light);
  padding-bottom: 18px;
  margin-bottom: 22px;
}
.exam-login-emblem {
  display: inline-grid; place-items: center;
  width: 52px; height: 52px;
  border-radius: 12px;
  background: linear-gradient(135deg, var(--accent), var(--accent2, #8b5cf6));
  color: #fff;
  font-weight: 700; font-size: 16px;
  margin-bottom: 10px;
  letter-spacing: 1px;
}
.exam-login-head h1 {
  margin: 0; font-size: 18px; font-weight: 600;
  color: var(--text);
}
.exam-login-sub {
  margin: 6px 0 0; font-size: 13px; color: var(--text-muted);
}
.exam-login-form { display: grid; gap: 14px; }
.exam-field {
  display: flex; flex-direction: column; gap: 4px;
}
.exam-field span {
  font-size: 12px; color: var(--text-muted); font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.5px;
}
.exam-field input {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font: inherit;
  background: var(--surface);
  transition: border-color 0.15s ease;
}
.exam-field input:focus {
  outline: none;
  border-color: var(--accent);
}
.exam-login-actions { margin-top: 4px; }
.exam-login-btn {
  width: 100%;
  padding: 12px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 10px;
  font: inherit; font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease;
}
.exam-login-btn:hover { background: var(--accent-strong); }
.exam-login-foot {
  text-align: center; font-size: 11px; margin: 14px 0 0;
}

/* ---- lesson plan tree ---- */
.lesson-page { display: grid; gap: 16px; }
.lesson-head {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.lesson-badge {
  background: var(--accent-soft); color: var(--accent-strong);
  padding: 4px 10px; border-radius: 9999px;
  font-size: 12px; font-weight: 600;
}
.lesson-tree {
  list-style: none; padding: 0; margin: 0;
}
.lesson-tree > li { margin: 0; }
.lesson-tree > li + li { margin-top: 4px; }
.lesson-tree summary {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px;
  border-radius: 10px;
  cursor: pointer;
  list-style: none;
  font-weight: 500;
  transition: background 0.15s ease;
}
.lesson-tree summary::-webkit-details-marker { display: none; }
.lesson-tree summary:hover { background: var(--surface-hover); }
.lesson-tree-icon {
  width: 30px; height: 30px;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-strong);
  border-radius: 8px; font-size: 16px;
  flex-shrink: 0;
}
.lesson-tree-name { flex: 1; }
.lesson-tree-units {
  list-style: none;
  margin: 4px 0 8px 44px;
  padding: 0;
  display: grid; gap: 2px;
}
.lesson-unit {
  display: flex; align-items: baseline; gap: 10px;
  padding: 8px 12px;
  border-radius: 8px;
  text-decoration: none; color: var(--text-secondary);
  font-size: 13px;
  transition: background 0.15s ease, color 0.15s ease;
}
.lesson-unit:hover {
  background: var(--accent-soft);
  color: var(--accent-strong);
}
.lesson-unit code {
  font-size: 11px;
  padding: 2px 6px;
  background: var(--bg-soft);
  border-radius: 4px;
  color: var(--text-muted);
}

/* ---- feedback board ---- */
.feedback-page { display: grid; gap: 16px; }
.feedback-form { display: grid; gap: 12px; }
.feedback-form label {
  display: flex; flex-direction: column; gap: 4px;
}
.feedback-form label > span {
  font-size: 12px; font-weight: 600; color: var(--text-muted);
}
.feedback-form input,
.feedback-form select,
.feedback-form textarea {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font: inherit;
  background: var(--surface);
}
.feedback-form textarea { resize: vertical; min-height: 120px; }
.feedback-list { display: grid; gap: 10px; }
.feedback-item {
  padding: 12px 14px;
  background: var(--bg-soft);
  border-radius: 10px;
  border-left: 3px solid var(--accent);
}
.feedback-item-head {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 4px;
}
.feedback-item-kind {
  font-size: 12px; font-weight: 500; color: var(--text);
}
.feedback-item-title { font-weight: 600; font-size: 14px; }
.feedback-item-body {
  font-size: 13px; color: var(--text-secondary); margin-top: 4px;
  white-space: pre-wrap;
}

/* ---- admin/users compactness ---- */
.admin-users-grid .card {
  padding: 14px 16px;        /* tighter than default */
}
.admin-users-grid .card h2 {
  font-size: 14px;
  margin: 0 0 10px;
}
.admin-users-grid .form-grid label {
  font-size: 12px;
}

/* ---- ai chat fill the page area ---- */
.ai-chat-shell {
  width: 100%;
  min-height: calc(100vh - 96px);
  display: flex;
  flex-direction: column;
  padding: 0;
}
.page > .ai-chat-shell {
  margin: 0 -4px;     /* tiny breathing room left/right */
}

/* ---- admin/notifications: text no-wrap + balanced height ---- */
.notify-row-title,
.notify-row-preview,
.notify-row-aud,
.notify-row-time {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.notify-row-preview { max-width: 360px; }

/* ---- ingest: balance left+right column heights ---- */
.ingest-shell { align-items: stretch !important; }
.ingest-sidebar,
.ingest-main { height: 100%; }

/* ==========================================================================
   UI v3 step 2 batch 2 — exam-stub fullscreen, lesson polish, feedback,
   admin/users form-foot, admin pages full width  (issue #47 follow-up)
   ========================================================================== */

/* exam-stub: full-page centered card */
.exam-stub-page {
  min-height: calc(100vh - 96px);
  display: grid;
  place-items: center;
  padding: 24px 16px;
}
.exam-stub-card {
  width: 100%;
  max-width: 460px;
  background: var(--surface);
  border: 1px solid var(--border-light);
  border-radius: 16px;
  padding: 48px 32px;
  text-align: center;
  box-shadow: 0 4px 16px rgba(15,23,42,0.06);
}
.exam-stub-card h2 { margin: 0 0 12px; font-size: 18px; }
.exam-stub-icon { font-size: 48px; margin-bottom: 12px; }
.exam-stub-msg {
  color: var(--text-muted);
  font-size: 14px;
  margin: 0 0 20px;
}

/* lesson: tighter shell, no color step between sections */
.lesson-shell { padding: 0 !important; overflow: hidden; }
.lesson-shell .lesson-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 20px;
  border-bottom: 1px solid var(--border-light);
}
.lesson-shell .lesson-head h2 { margin: 0; font-size: 16px; }
.lesson-shell .lesson-tree {
  list-style: none; padding: 8px; margin: 0;
}
.lesson-tree summary {
  position: relative;
}
.lesson-tree-count {
  font-size: 11px;
  color: var(--text-muted);
  background: var(--bg-soft);
  padding: 2px 8px;
  border-radius: 9999px;
}
.lesson-tree-chevron {
  flex-shrink: 0;
  color: var(--text-muted);
  transition: transform 0.18s ease;
}
.lesson-tree details[open] > summary > .lesson-tree-chevron {
  transform: rotate(180deg);
}

/* feedback-board: consistent form alignment */
.feedback-page {
  min-height: calc(100vh - 96px);
}
.feedback-page .card { width: 100%; }
.feedback-title { margin: 0 0 4px; font-size: 16px; }
.feedback-hint { margin: 0 0 16px; color: var(--text-muted); font-size: 13px; }
.feedback-subtitle { margin: 0 0 12px; font-size: 14px; }
.feedback-form .form-row {
  display: flex; align-items: center; gap: 12px;
}
.feedback-response {
  padding: 14px 16px;
  background: var(--accent-soft);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  white-space: pre-wrap;
  font-size: 13px;
}

/* admin/users form-foot row: TOTP + Create align horizontally */
.form-foot {
  grid-column: 1 / -1;
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
  padding-top: 8px;
  border-top: 1px solid var(--border-light);
  margin-top: 4px;
}
.form-foot .check-row {
  margin: 0;
  display: flex; align-items: center; gap: 6px;
  font-size: 13px;
}
.form-foot-actions {
  display: flex; align-items: center; gap: 10px;
}

/* admin/* pages: full width inside main column (no centred narrow look) */
#page > section.card,
#page > .feedback-page,
#page > .exam-login,
#page > .exam-stub-page,
#page > .lesson-page,
#page > .ai-chat-shell {
  width: 100%; max-width: none;
}

/* admin/notifications right pane — make textarea use available height */
@media (min-width: 800px) {
  .notify-admin-layout { min-height: calc(100vh - 96px); }
  .notify-admin-layout > .notify-right { display: flex; flex-direction: column; gap: 16px; }
  .notify-admin-layout > .notify-right .notify-card:first-child { flex: 0 0 auto; }
  .notify-admin-layout > .notify-right .notify-card:nth-child(2) { flex: 1; min-height: 0; }
}

/* review page full-size frame */
#page > section.card { min-height: 240px; }
.review-card,
section.card.review { min-height: calc(100vh - 96px); }

/* ==========================================================================
   AI welcome card — first-load onboarding (issue #47 step 2)
   Sparkle ✦ animation + fade-in + tidy bullet list
   ========================================================================== */

.ai-welcome {
  background: linear-gradient(135deg,
              var(--accent-soft, #eef2ff) 0%,
              var(--surface, #fff) 65%);
  border: 1px solid var(--border-light);
  border-radius: 16px;
  padding: 24px 26px;
  margin: 8px 0;
  box-shadow: 0 4px 18px rgba(99, 102, 241, 0.08);
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
  animation: aiWelcomeIn 0.6s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;
}

@keyframes aiWelcomeIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Subtle gradient bg dots */
.ai-welcome::before,
.ai-welcome::after {
  content: "";
  position: absolute;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--accent, #6366f1);
  opacity: 0;
  pointer-events: none;
  filter: blur(0.5px);
}
.ai-welcome::before { top: 18px; right: 38px; animation: aiSpark 2.4s ease-in-out infinite; }
.ai-welcome::after  { top: 56px; right: 22px; width: 6px; height: 6px;
                       animation: aiSpark 2.4s ease-in-out infinite 0.8s; }

.ai-welcome-greet {
  font-size: 13px;
  color: var(--text-muted);
  margin-bottom: 4px;
}

.ai-welcome-title {
  margin: 0 0 12px;
  font-size: 17px;
  font-weight: 600;
  color: var(--text);
  display: flex; align-items: center; gap: 8px;
}

.ai-welcome-spark {
  display: inline-block;
  color: var(--accent, #6366f1);
  animation: aiSparkRotate 3s ease-in-out infinite;
  filter: drop-shadow(0 0 4px rgba(99,102,241,0.4));
}

@keyframes aiSparkRotate {
  0%, 100% { transform: rotate(0) scale(1);   opacity: 1; }
  50%      { transform: rotate(180deg) scale(1.2); opacity: 0.7; }
}

@keyframes aiSpark {
  0%, 100% { opacity: 0;   transform: scale(0.5); }
  50%      { opacity: 0.6; transform: scale(1); }
}

.ai-welcome-lead,
.ai-welcome-cta {
  margin: 0 0 12px;
  color: var(--text-secondary);
}
.ai-welcome-cta {
  margin: 12px 0 0;
  font-size: 13px;
  color: var(--text-muted);
  font-style: italic;
}

.ai-welcome-list,
.ai-welcome-soon-list {
  margin: 0 0 14px;
  padding: 0;
  list-style: none;
}
.ai-welcome-list li,
.ai-welcome-soon-list li {
  padding: 4px 0;
  color: var(--text);
  font-size: 13.5px;
}
.ai-welcome-soon-title {
  margin: 16px 0 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.6px;
}
.ai-welcome-soon-list li {
  color: var(--text-muted);
  font-size: 13px;
  position: relative;
  padding-left: 16px;
}
.ai-welcome-soon-list li::before {
  content: "·";
  position: absolute;
  left: 4px;
  color: var(--accent);
}

/* The welcome lives at the top of .ai-chat-msgs and isn't a regular
   .ai-msg bubble — opt out of bubble styling. */
.ai-msg-welcome.ai-msg { all: unset; }

/* ──────────────────────────────────────────────────────────────────────────
   AI chat — background-image controls (issue #47 step 3)
   Two small icon buttons inline in the chat-head action row (next to the
   quota pill and clear-chat button): cycle (⇄) + upload (image-icon).
   At-cap behavior: upload replaces oldest + brief friendly toast appears
   under the chat-head bar.
   ──────────────────────────────────────────────────────────────────────────*/
.ai-chat-shell { position: relative; overflow: hidden; }

/* Bg image lives BEHIND the conversation messages area only — not the
   head bar / input bar.  Sized cover so it fully fills the msgs area
   regardless of the image's aspect ratio.  Opacity is gentle enough
   to keep chat bubbles readable but visible enough that the picture
   actually shows. */
.ai-chat-msgs { position: relative; }
.ai-chat-msgs.has-bg::before {
  content: "";
  position: absolute; inset: 0;
  background-image: var(--ai-bg-image);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  opacity: 0.55;
  pointer-events: none;
  z-index: 0;
}
.ai-chat-msgs > * { position: relative; z-index: 1; }

.ai-bg-cycle-btn,
.ai-bg-add-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  padding: 0;
  border-radius: 8px;
  color: var(--text-muted, #6b7280);
}
.ai-bg-cycle-btn:hover,
.ai-bg-add-btn:hover {
  color: var(--accent-strong, #4f46e5);
}

.ai-bg-toast {
  position: absolute;
  top: 100%;
  right: 16px;
  margin-top: 6px;
  padding: 6px 12px;
  font-size: 12px;
  color: var(--text, #111827);
  background: var(--surface-elevated, #fff);
  border: 1px solid var(--border-light, #e5e7eb);
  border-radius: 8px;
  box-shadow: 0 4px 14px rgba(0,0,0,0.08);
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px);
  transition: opacity 0.18s ease, transform 0.18s ease;
  z-index: 5;
  white-space: nowrap;
}
.ai-bg-toast.show {
  opacity: 1;
  transform: translateY(0);
}
