/* ─────────────────────────────────────────────────────────────
   PIXIFY STUDIO · Design Tokens & Shared Components
   ─────────────────────────────────────────────────────────────
   Drop into any HTML page:
     <link rel="preconnect" href="https://fonts.googleapis.com">
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
     {% include "_fonts.html" %}   ← renders the Google Fonts link (and any admin override)
     <link rel="stylesheet" href="/static/pixify-tokens.css">

   Source of truth: design lab tokens committed 2026-04-25.
   Extracted from: pixify-preview/report_pixify_v4.html
   ───────────────────────────────────────────────────────────── */


/* ── 1. Tokens ────────────────────────────────────────────── */
:root {
  /* Surfaces */
  --bg:               #FDFCF9;
  --bg-warm:          #F8F5EE;
  --surface:          #FFFFFF;
  --surface-warm:     #FDFBF6;
  --surface-stone:    #F4F1EB;
  --surface-input:    #F4F1EB;

  /* Borders */
  --border:           #E8E4DB;
  --border-soft:      #EFEBE1;
  --border-warm:      #E5DFD1;

  /* Text */
  --text:             #0A0A0A;
  --text-warm:        #1C1917;
  --text-muted:       #44403C;
  --text-dim:         #78716C;
  --text-quiet:       #A8A29E;

  /* Accent (forest green — primary action) */
  --accent:           #047857;
  --accent-hover:     #065F46;
  --accent-ink:       #FFFFFF;   /* text/icon on a solid accent fill (auto-flips in dark) */
  --accent-light:     #ECFDF5;
  --accent-border:    #A7F3D0;

  /* Danger (warm terracotta — never primary) */
  --red:              #B84A2B;
  --red-bg:           #FCF0EB;
  --red-border:       #F3D5C3;

  /* Warning (orange — unassigned, drafts) */
  --orange:           #C2410C;
  --orange-bg:        #FFF7ED;
  --orange-border:    #FED7AA;

  /* Brand */
  --pixify-red:       #DC0000;

  /* Sand (warm neutral chip / accent) */
  --sand:             #B08968;
  --sand-bg:          #F5EDE2;
  --sand-border:      #E5D5BD;

  /* Amber (ownership / elevated-privilege badges) */
  --amber:            #B45309;
  --amber-bg:         #FEF6E7;
  --amber-border:     #F3D9A6;

  /* Mint — the lighter end of the accent, for gradients only */
  --accent-mint:      #2BB789;
  /* Accent that still reads on a dark photo scrim (badges over imagery) */
  --accent-on-dark:   #6EE7B7;

  /* Categorical — diagrams and status keys on ADMIN surfaces only.
     Kept apart from the semantic colours so meaning never rides on the
     brand accent. Do not use these for state (use accent/red/orange). */
  --cat-blue:         #1D4ED8;
  --cat-blue-bg:      rgba(29, 78, 216, 0.10);
  --cat-purple:       #6D28D9;
  --cat-purple-bg:    rgba(109, 40, 217, 0.10);
  --cat-green:        #059669;
  --cat-green-bg:     rgba(5, 150, 105, 0.12);
  --cat-gold:         #8A5A2B;
  --cat-gold-bg:      rgba(138, 90, 43, 0.10);

  /* Layout — three named page widths replace ~47 one-off values */
  --sidebar-w:        320px;  /* the report's concept list needs the room */
  --content-narrow:   760px;    /* forms, settings, auth */
  --content:          1100px;   /* most pages */
  --content-wide:     1400px;   /* report, data grids */
  --content-max:      1400px;   /* legacy alias → --content-wide */

  /* Spacing scale — eight steps replace ~678 hand-typed gaps */
  --space-xs:         4px;
  --space-sm:         8px;
  --space-md:         12px;
  --space-lg:         16px;
  --space-xl:         24px;
  --space-2xl:        32px;
  --space-3xl:        48px;
  --space-4xl:        64px;

  /* Radii */
  --radius-card:      12px;
  --radius-image:     6px;
  --radius-button:    6px;
  --radius-pill:      4px;
  --radius-modal:     18px;
  --radius-hero:      18px;
  --radius-field:     8px;    /* text inputs, selects */
  --radius-round:     999px;  /* fully round: avatars, chips, switches */

  /* Shadows (warm-tinted, never cool grey) */
  --shadow-soft:      0 1px 2px rgba(28,25,23,0.04);
  --shadow-card:      0 1px 3px rgba(28,25,23,0.05), 0 1px 2px rgba(28,25,23,0.03);
  --shadow-hover:     0 6px 20px rgba(28,25,23,0.06), 0 2px 6px rgba(28,25,23,0.04);
  --shadow-hero:      0 16px 40px -16px rgba(28,25,23,0.14), 0 6px 16px -6px rgba(28,25,23,0.06);
  --shadow-modal:     0 32px 80px -16px rgba(28,25,23,0.4), 0 8px 24px -8px rgba(28,25,23,0.2);
  --shadow-float:     0 1px 2px rgba(28,25,23,0.04), 0 18px 48px -22px rgba(28,25,23,0.20), 0 6px 16px -10px rgba(28,25,23,0.08);
  --shadow-photo:     0 0 0 1px var(--border), 0 0 0 5px var(--surface), 0 6px 18px -8px rgba(28,25,23,0.22);

  /* Focus — one ring for every interactive control */
  --focus-ring:       0 0 0 3px rgba(4, 120, 87, 0.12);

  /* Typography — the DEFAULT faces. design_fonts.py reads the family names off
     these three lines (one source of truth) and an admin can override them at
     runtime from Settings → Typography; the override rides on <html style>
     via templates/_fonts.html, so no page ever re-declares these tokens.
     2026-09-14: Geist (interface) and Geist Mono (labels/data) are settled;
     the heading face is on trial — Playfair Display first, DM Sans second.
     Rejected: Instrument Serif (too extreme), Newsreader / Source Serif 4 /
     Literata (calmer serifs, not picked). */
  --font-body:        'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-display:     'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono:        'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --font-base:        12.5px;

  /* Heading tuning for the display face. These describe --font-display above
     (a grotesk: scale 1, medium); design_fonts.PROFILES overrides all four per
     family when an admin picks a serif, which needs to sit larger and looser. */
  --display-size-scale:     1;
  --display-weight:         500;
  --display-name-weight:    600;
  --display-tracking-scale: 1;

  /* Type ladder — a named scale replaces ~34 ad-hoc sizes */
  --fs-xs:            11px;     /* meta, captions */
  --fs-sm:            12px;     /* secondary UI text */
  --fs-base:          13px;     /* body / default */
  --fs-md:            15px;     /* emphasised body */
  --fs-lg:            18px;     /* small headings */
  --fs-xl:            22px;     /* section headings */
  --fs-2xl:           28px;     /* page headings */
  --fs-3xl:           36px;     /* display (serif) */
  --fs-display:       48px;     /* hero display (serif) */
}


/* ── 2. Reset & body ──────────────────────────────────────── */
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  font-size: var(--font-base);
  line-height: 1.55;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* App-shell variant — for full-bleed admin pages with sidebar */
body.app-shell {
  display: flex;
  height: 100vh;
  overflow: hidden;
}


/* ── 3. Type utilities & display headings ─────────────────── */
.serif        { font-family: var(--font-display); font-weight: 400; letter-spacing: -0.01em; }
.serif-italic { font-family: var(--font-display); font-style: italic; font-weight: 400; }
.mono         { font-family: var(--font-mono); }

h1.display {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: calc(48px * var(--display-size-scale));
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--text);
  margin-bottom: 10px;
}
h1.display .italic { font-style: italic; color: var(--text-muted); }

h2.display {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: calc(36px * var(--display-size-scale));
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--text);
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.eyebrow .eyebrow-dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
}


/* ── 4. Buttons ───────────────────────────────────────────── */
.btn {
  padding: 6px 12px;
  border-radius: var(--radius-button);
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  transition: all 0.12s;
  white-space: nowrap;
  font-family: inherit;
  text-decoration: none;      /* <a class="btn"> must read as a button */
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  line-height: 1;
  letter-spacing: -0.005em;
}
.btn:hover {
  border-color: var(--border-warm);
  background: var(--surface-warm);
  box-shadow: var(--shadow-soft);
}
.btn:active { transform: scale(0.98); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }

.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
}
.btn-primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

.btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--text-muted);
}
.btn-ghost:hover {
  background: var(--surface-stone);
  border-color: var(--border-soft);
  color: var(--text);
}

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

.btn-sm { padding: 5px 10px; font-size: 11.5px; height: 26px; }
.btn-lg { padding: 8px 16px; font-size: 13px;   height: 34px; }
.btn-block { width: 100%; justify-content: center; }   /* the one button a card is about */


/* ── 5. Confirm badge (status-toggle) ─────────────────────── */
.confirm-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: var(--radius-button);
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.12s;
  height: 30px;
  line-height: 1;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  font-family: inherit;
}
.confirm-badge:hover { border-color: var(--accent); color: var(--accent); }
.confirm-badge.confirmed {
  background: var(--accent-light);
  color: var(--accent);
  border-color: var(--accent-border);
}


/* ── 6. Pills & tags ──────────────────────────────────────── */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  font-size: 11.5px;
  color: var(--text-muted);
  background: var(--surface-stone);
  border: 1px solid var(--border-soft);
  line-height: 1.5;
  font-weight: 500;
}
.pill-green  { background: var(--accent-light);  color: var(--accent);  border-color: var(--accent-border); }
.pill-red    { background: var(--red-bg);        color: var(--red);     border-color: var(--red-border); }
.pill-orange { background: var(--orange-bg);     color: var(--orange);  border-color: var(--orange-border); }
.pill-sand   { background: var(--sand-bg);       color: var(--sand);    border-color: var(--sand-border); }
.pill-amber  { background: var(--amber-bg);      color: var(--amber);   border-color: var(--amber-border); }  /* ownership */
.pill-dot    { width: 6px; height: 6px; border-radius: 50%; background: currentColor; display: inline-block; }


/* ── 7. Sidebar shell ─────────────────────────────────────── */
.sidebar {
  width: var(--sidebar-w);
  background: var(--bg-warm);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
}
.sidebar-brand {
  padding: 18px 20px 14px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.brand-logo {
  width: 26px;
  height: 32px;
  border-radius: 5px;
  flex-shrink: 0;
  display: block;
  box-shadow: 0 1px 2px rgba(220, 0, 0, 0.25);
  margin-top: 1px;
}
.brand-wordmark {
  display: flex;
  flex-direction: column;
  gap: 0;
  line-height: 1;
}
.brand-title {
  font-family: var(--font-body);
  font-size: 18px;
  letter-spacing: -0.5px;
  color: var(--text);
  line-height: 1.1;
}
.brand-title .pixify { font-weight: 500; }
.brand-title .studio { font-weight: 400; }
.brand-sub {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-dim);
  letter-spacing: -0.01em;
  margin-top: 4px;
  font-weight: 400;
}

.sidebar-section-label {
  padding: 14px 20px 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 500;
}
.sidebar-nav { flex: 1; overflow-y: auto; padding: 0 10px 8px; }

.nav-item {
  padding: 7px 10px;
  border-radius: 7px;
  cursor: pointer;
  margin-bottom: 1px;
  display: flex;
  align-items: center;
  gap: 10px;
  transition: background 0.12s, border-color 0.12s;
  color: var(--text-muted);
  border: 1px solid transparent;
}
.nav-item:hover { background: rgba(28, 25, 23, 0.035); }
.nav-item.active {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border);
  box-shadow: var(--shadow-soft);
}
.nav-item .nav-icon {
  width: 28px; height: 28px;
  border-radius: 6px;
  overflow: hidden;
  flex-shrink: 0;
  background: var(--surface-stone);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px;
  color: var(--text-dim);
  border: 1px solid var(--border-soft);
}
.nav-item .nav-icon img { width: 100%; height: 100%; object-fit: cover; }
.nav-item .nav-icon.green  { background: var(--accent); color: #fff; border-color: var(--accent); }
.nav-item .nav-icon.sand   { background: var(--sand);   color: #fff; border-color: var(--sand); }
.nav-item .nav-icon.orange { background: var(--orange); color: #fff; border-color: var(--orange); }
.nav-item .nav-label { font-size: 13px; flex: 1; min-width: 0; }
.nav-item .nav-label .name {
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: -0.01em;
}
.nav-item .nav-label .count {
  font-size: 10.5px;
  color: var(--text-dim);
  font-weight: 400;
  margin-top: 1px;
  font-family: var(--font-mono);
}
.nav-check {
  width: 13px; height: 13px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  font-size: 8px;
  flex-shrink: 0;
  color: transparent;
}
.nav-check.done {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-light);
}

/* Sidebar footer (progress, etc.) */
.sidebar-footer { padding: 14px 20px; border-top: 1px solid var(--border); }
.progress-label {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: var(--text-dim);
  margin-bottom: 7px;
  font-weight: 500;
}
.progress-label .count-num {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text);
}
.progress-track {
  height: 3px;
  background: var(--surface-stone);
  border-radius: 2px;
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  background: var(--accent);
  border-radius: 2px;
  transition: width 0.3s;
}


/* ── 8. Main content shell + sticky top bar ───────────────── */
.main {
  flex: 1;
  overflow-y: auto;
  padding: 0 48px 140px;
}
.main-inner {
  max-width: var(--content-max);
  margin: 0 auto;
}

.top-bar {
  position: sticky;
  top: 0;
  background: rgba(253, 252, 249, 0.88); /* matches --bg with alpha */
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  padding: 14px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  z-index: 100;
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s;
  min-height: 56px;
}
.top-bar.scrolled { border-bottom-color: var(--border); }
.top-bar-left {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
  flex: 1;
}

.breadcrumb {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--text-dim);
  font-weight: 500;
  min-width: 0;
}
.breadcrumb a { color: var(--text-dim); text-decoration: none; transition: color 0.12s; }
.breadcrumb a:hover { color: var(--text); }
.breadcrumb .sep { color: var(--text-quiet); }
.breadcrumb .current { color: var(--text); }

/* Sticky title appears when hero scrolls past */
.top-bar-title {
  font-family: var(--font-display);
  font-size: 18px;
  line-height: 1.2;
  color: var(--text);
  letter-spacing: -0.015em;
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 0.2s, transform 0.2s;
  pointer-events: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 540px;
  display: none;
}
.top-bar.scrolled .top-bar-title.active {
  opacity: 1;
  transform: translateY(0);
  display: block;
}
.top-bar.scrolled .breadcrumb.hide-on-scroll { display: none; }

.top-actions { display: flex; gap: 8px; flex-shrink: 0; }


/* ── 9. Hero (overview-style) ─────────────────────────────── */
.hero {
  position: relative;
  margin: 6px 0 36px;
  border-radius: var(--radius-hero);
  overflow: hidden;
  background: var(--surface-stone);
  box-shadow: var(--shadow-hero);
}
.hero .hero-image {
  aspect-ratio: 16 / 6;
  width: 100%;
  background-size: cover;
  background-position: center;
  position: relative;
}
.hero .hero-image::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(253, 252, 249, 0)    0%,
    rgba(253, 252, 249, 0)    50%,
    rgba(253, 252, 249, 0.85) 92%,
    rgba(253, 252, 249, 1)    100%);
  pointer-events: none;
}
.hero .hero-content {
  position: absolute;
  inset: auto 0 0 0;
  padding: 36px 40px 36px;
  z-index: 2;
}
.hero-desc {
  font-size: 14.5px;
  color: var(--text-muted);
  line-height: 1.55;
  max-width: 680px;
}


/* ── 10. Stats strip ──────────────────────────────────────── */
.stats-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  margin-bottom: 40px;
  overflow: hidden;
}
.stat {
  padding: 14px 18px;
  border-right: 1px solid var(--border-soft);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.stat:last-child { border-right: none; }
.stat-value {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 400;
  line-height: 1;
  color: var(--text);
  letter-spacing: -0.02em;
}
.stat-value.accent { color: var(--accent); }
.stat-value.orange { color: var(--orange); }
.stat-label {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 500;
  margin-top: 4px;
}

/* Separate stat cards — the shoot overview's KPI row. Lived in main.css as
   .overview-stats/.stat-card; the admin pages use the same row, so it is
   shared. The values above (.stat-value / .stat-label) style the inside. */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-lg);
  margin-bottom: var(--space-2xl);
}
.stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 20px;
}


/* ── 11. Section label ────────────────────────────────────── */
.section-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 18px;
}
.section-label h3 {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  color: var(--text);
  letter-spacing: -0.015em;
}
.section-label h3 .italic { font-style: italic; color: var(--text-muted); }
.section-label .right-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-dim);
  font-weight: 500;
  letter-spacing: -0.01em;
}


/* ── 12. Inline meta line (· separated) ───────────────────── */
.meta-line {
  font-size: 13px;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0;
}
.meta-line .meta-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.meta-line .meta-item + .meta-item::before {
  content: '·';
  color: var(--text-quiet);
  margin: 0 10px;
}
.meta-line .meta-num {
  font-family: var(--font-mono);
  color: var(--text);
  font-size: 12.5px;
}
.meta-line .meta-status-confirmed { color: var(--accent); font-weight: 500; }
.meta-line .meta-status-pending   { color: var(--text-dim); }


/* ── 13. Editorial description (article body) ────────────── */
.body-prose {
  font-size: 16px;
  color: var(--text-warm);
  line-height: 1.65;
  max-width: 780px;
}


/* ── 14. Thin rule (section divider) ──────────────────────── */
.thin-rule {
  border: 0;
  height: 1px;
  background: var(--border);
  margin: 0 0 28px;
}


/* ── 15. Card grid (catalogue / listings) ─────────────────── */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
  margin-bottom: 44px;
}
.card {
  position: relative;
  cursor: pointer;
  border-radius: var(--radius-card);
  background: var(--surface);
  border: 1px solid var(--border);
  overflow: hidden;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.15s;
}
.card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-hover);
  border-color: var(--border-warm);
}
.card-img-wrap {
  aspect-ratio: 16 / 10;
  background: var(--surface-stone);
  position: relative;
  overflow: hidden;
}
.card-img-wrap img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.3s ease;
}
.card:hover .card-img-wrap img { transform: scale(1.02); }
.card-status {
  position: absolute;
  top: 12px; right: 12px;
  background: rgba(255, 255, 255, 0.92);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  padding: 3px 9px;
  border-radius: 20px;
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  gap: 5px;
  border: 1px solid rgba(167, 243, 208, 0.4);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.card-body { padding: 16px 18px 18px; }
.card-eyebrow {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 500;
  margin-bottom: 6px;
}
.card-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 22px;
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: var(--text);
  margin-bottom: 6px;
}
.card-desc {
  font-size: 12.5px;
  color: var(--text-muted);
  line-height: 1.5;
  margin-bottom: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.card-tags { display: flex; flex-wrap: wrap; gap: 4px; }


/* ── 16. Image grid ───────────────────────────────────────── */
.image-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 12px;
  margin-bottom: 32px;
}
.image-card {
  position: relative;
  border-radius: var(--radius-image);
  overflow: hidden;
  aspect-ratio: 1;
  cursor: pointer;
  background: var(--surface-stone);
  border: 1px solid var(--border-soft);
  transition: transform 0.15s, border-color 0.15s;
}
.image-card img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.3s ease;
}
.image-card:hover img { transform: scale(1.04); }
.image-card.selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent);
}
.image-card .check-overlay {
  position: absolute;
  top: 7px; left: 7px;
  width: 20px; height: 20px;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(0, 0, 0, 0.06);
  display: flex; align-items: center; justify-content: center;
  font-size: 10px;
  color: transparent;
  backdrop-filter: blur(4px);
  transition: all 0.12s;
  opacity: 0;
}
.image-card:hover .check-overlay,
.image-card.selected .check-overlay { opacity: 1; }
.image-card.selected .check-overlay {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.grid-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 14px;
}
.grid-toolbar .left-group {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.grid-toolbar .count-serif {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  color: var(--text);
  line-height: 1;
}
.grid-toolbar .count-label {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 500;
}


/* ── 17. Inline keyword rows (no card) ────────────────────── */
.kw-inline { margin-bottom: 32px; }
.kw-row {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border-soft);
}
.kw-row:last-child { border-bottom: none; }
.kw-cat-label {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 15px;
  color: var(--text-dim);
  min-width: 100px;
  padding-top: 3px;
  flex-shrink: 0;
}
.kw-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  align-items: center;
  flex: 1;
}
.kw-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px 3px 10px;
  border-radius: var(--radius-pill);
  font-size: 12.5px;
  color: var(--text-muted);
  background: var(--surface-warm);
  border: 1px solid var(--border-soft);
  line-height: 1.4;
  font-weight: 500;
}
.kw-pill .pill-x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px; height: 14px;
  border-radius: 50%;
  font-size: 9px;
  color: var(--text-quiet);
  cursor: pointer;
  transition: all 0.15s;
  line-height: 1;
}
.kw-pill .pill-x:hover { background: var(--red-bg); color: var(--red); }
.kw-add-input {
  background: transparent;
  border: 1px dashed var(--border);
  color: var(--text);
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  font-size: 12.5px;
  width: 120px;
  line-height: 1.4;
  outline: none;
  font-family: inherit;
  font-weight: 500;
}
.kw-add-input:focus {
  border-color: var(--accent);
  border-style: solid;
  background: var(--accent-light);
  width: 150px;
}
.kw-add-input::placeholder { color: var(--text-quiet); }


/* ── 18. Page nav (prev/next at bottom of page) ────────────── */
.page-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 40px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
  gap: 16px;
}
.page-nav .page-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}


/* ── 19. Lightbox ─────────────────────────────────────────── */
.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(28, 25, 23, 0.92);
  z-index: 1200;
  display: none;
  align-items: center;
  justify-content: center;
}
.lightbox.show { display: flex; }
.lightbox img {
  max-width: 88vw;
  max-height: 88vh;
  border-radius: 10px;
  object-fit: contain;
  cursor: default;
}
.lb-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: #fff;
  font-size: 18px;
  width: 44px;
  height: 56px;
  border-radius: 10px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s;
  z-index: 1;
  backdrop-filter: blur(8px);
}
.lb-nav:hover { background: rgba(255, 255, 255, 0.16); }
.lb-prev { left: 24px; }
.lb-next { right: 24px; }
.lb-counter {
  position: absolute;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(255, 255, 255, 0.1);
  color: rgba(255, 255, 255, 0.9);
  font-size: 11px;
  padding: 7px 14px;
  border-radius: 20px;
  pointer-events: none;
  font-family: var(--font-mono);
  letter-spacing: 0.02em;
  backdrop-filter: blur(8px);
}
.lb-close {
  position: absolute;
  top: 20px; right: 20px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: #fff;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  cursor: pointer;
  font-size: 14px;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s;
  backdrop-filter: blur(8px);
}
.lb-close:hover { background: rgba(255, 255, 255, 0.18); }


/* ── 20. Toast ────────────────────────────────────────────── */
.toast {
  position: fixed;
  bottom: 24px;
  right: 24px;
  background: var(--surface);
  border: 1px solid var(--accent-border);
  color: var(--accent);
  padding: 10px 16px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  z-index: 2000;
  opacity: 0;
  transition: opacity 0.3s;
  box-shadow: var(--shadow-hover);
}
.toast.show { opacity: 1; }
.toast.error { border-color: var(--red-border); color: var(--red); }


/* ── 21. Spinner ──────────────────────────────────────────── */
.spinner {
  display: inline-block;
  width: 12px; height: 12px;
  border: 1.5px solid rgba(255, 255, 255, 0.3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}
.btn:not(.btn-primary) .spinner {
  border-color: rgba(0, 0, 0, 0.15);
  border-top-color: var(--text);
}
@keyframes spin { to { transform: rotate(360deg); } }


/* ── 22. Scrollbar ────────────────────────────────────────── */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 10px;
  border: 2px solid var(--bg);
}
::-webkit-scrollbar-thumb:hover { background: var(--text-quiet); }


/* ── 23. Single-image keywording modal ────────────────────── */
.kw-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(28, 25, 23, 0.62);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 2000;
  padding: 32px;
  animation: kwFade 0.2s ease;
}
.kw-modal-backdrop.show { display: flex; }
@keyframes kwFade { from { opacity: 0; } to { opacity: 1; } }

.kw-modal {
  width: 100%;
  max-width: 1320px;
  height: 100%;
  max-height: 840px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-modal);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: var(--shadow-modal);
  animation: kwSlide 0.25s cubic-bezier(.4, 0, .2, 1);
}
@keyframes kwSlide {
  from { opacity: 0; transform: translateY(8px) scale(0.985); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.kw-modal-header {
  padding: 11px 14px 11px 18px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 14px;
  flex-shrink: 0;
  background: var(--surface);
}
.kw-modal-header .header-nav { display: flex; gap: 4px; align-items: center; }
.kw-nav-btn {
  width: 28px; height: 28px;
  border-radius: var(--radius-button);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px;
  transition: all 0.12s;
}
.kw-nav-btn:hover {
  background: var(--surface-warm);
  color: var(--text);
  border-color: var(--text-quiet);
}
.kw-nav-btn:disabled { opacity: 0.3; cursor: not-allowed; pointer-events: none; }

.kw-modal-header .header-info {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.kw-modal-header .file-name {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--text);
  font-weight: 500;
  letter-spacing: -0.01em;
}
.kw-modal-header .file-meta {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-dim);
  letter-spacing: 0.04em;
}
.kw-modal-header .header-actions { display: flex; gap: 8px; align-items: center; }
.kw-saved-indicator {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.kw-saved-indicator .dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
}
.kw-modal-close {
  width: 30px; height: 30px;
  border-radius: var(--radius-button);
  border: none;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px;
  transition: all 0.12s;
}
.kw-modal-close:hover { background: var(--surface-stone); color: var(--text); }

.kw-modal-body { flex: 1; display: flex; min-height: 0; }
.kw-image-side {
  flex: 1.55;
  min-width: 0;
  background: #1C1917;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.kw-image-side img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
}
.kw-image-meta {
  position: absolute;
  bottom: 16px;
  left: 18px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: rgba(255, 255, 255, 0.78);
  background: rgba(0, 0, 0, 0.45);
  padding: 6px 12px;
  border-radius: 6px;
  backdrop-filter: blur(8px);
  display: flex;
  gap: 14px;
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.kw-image-meta span { display: inline-flex; align-items: center; gap: 5px; }
.kw-image-meta .meta-dot {
  width: 4px; height: 4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.4);
}

.kw-form-side {
  width: 460px;
  flex-shrink: 0;
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  background: var(--bg);
  min-height: 0;
}
.kw-form-body {
  flex: 1;
  overflow-y: auto;
  padding: 18px 24px 24px;
}

.kw-context {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: var(--surface-warm);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  margin-bottom: 20px;
}
.kw-context .ctx-thumb {
  width: 30px; height: 30px;
  border-radius: 5px;
  overflow: hidden;
  flex-shrink: 0;
  border: 1px solid var(--border-soft);
}
.kw-context .ctx-thumb img { width: 100%; height: 100%; object-fit: cover; }
.kw-context .ctx-info {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
  gap: 1px; line-height: 1.2;
}
.kw-context .ctx-label {
  font-family: var(--font-mono);
  font-size: 9.5px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.kw-context .ctx-name {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--text);
  font-style: italic;
}
.kw-context .ctx-link {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  text-decoration: none;
  padding: 4px 8px;
  border-radius: 5px;
  border: 1px solid var(--border-soft);
  transition: all 0.12s;
  flex-shrink: 0;
}
.kw-context .ctx-link:hover { color: var(--text); border-color: var(--text-quiet); }

.kw-form-section {
  margin-bottom: 22px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border-soft);
}
.kw-form-section:last-child { border-bottom: none; padding-bottom: 0; margin-bottom: 0; }
.kw-section-label {
  font-family: var(--font-mono);
  font-size: 9.5px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 500;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.ai-chip {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--accent);
  background: var(--accent-light);
  border: 1px solid var(--accent-border);
  padding: 1px 7px 1px 6px;
  border-radius: 8px;
  letter-spacing: 0.04em;
  font-weight: 500;
  text-transform: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  line-height: 1.3;
}
.ai-chip .sparkle { font-size: 9px; }

.kw-title-input {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--surface);
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 500;
  color: var(--text);
  outline: none;
  letter-spacing: -0.01em;
  line-height: 1.25;
  transition: border-color 0.12s;
}
.kw-title-input:focus { border-color: var(--accent); }
.kw-title-input::placeholder { color: var(--text-quiet); font-style: italic; }

.kw-desc-input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--surface);
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text);
  outline: none;
  line-height: 1.55;
  resize: vertical;
  min-height: 84px;
  transition: border-color 0.12s;
}
.kw-desc-input:focus { border-color: var(--accent); }
.kw-desc-input::placeholder { color: var(--text-quiet); }

/* Tighter keyword rows inside modal */
.kw-modal .kw-row {
  padding: 7px 0;
  align-items: flex-start;
  gap: 12px;
}
.kw-modal .kw-cat-label { font-size: 13px; min-width: 78px; padding-top: 2px; }
.kw-modal .kw-pill { font-size: 11.5px; padding: 2px 8px 2px 9px; }
.kw-modal .kw-add-input { width: 100px; font-size: 11.5px; padding: 2px 9px; }

.kw-modal-footer {
  padding: 12px 18px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-shrink: 0;
  background: var(--surface);
}
.kw-quality-bar { display: flex; align-items: center; gap: 10px; }
.kw-quality-track {
  width: 64px;
  height: 4px;
  background: var(--surface-stone);
  border-radius: 2px;
  overflow: hidden;
}
.kw-quality-fill {
  height: 100%;
  background: var(--accent);
  border-radius: 2px;
}
.kw-quality-label {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  display: flex;
  align-items: baseline;
  gap: 5px;
}
.kw-quality-label .num { color: var(--text); font-weight: 500; }
.kw-modal-footer .footer-actions { display: flex; gap: 8px; }


/* ── 24. Floating selection bar ───────────────────────────── */
#selection-float {
  position: fixed;
  bottom: 20px;
  left: calc(var(--sidebar-w) + 24px);
  right: 24px;
  padding: 9px 12px;
  border-radius: 10px;
  display: none;
  align-items: center;
  gap: 10px;
  z-index: 1000;
  box-shadow: var(--shadow-hover);
  background: var(--surface);
  border: 1px solid var(--border);
  max-width: calc(100vw - var(--sidebar-w) - 48px);
}
#selection-float.sel-mode {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}


/* ── 25. Preview banner (for non-production previews) ─────── */
.preview-banner {
  position: fixed;
  top: 14px;
  right: 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  padding: 5px 12px;
  border-radius: 20px;
  font-size: 10.5px;
  color: var(--text-dim);
  z-index: 500;
  font-family: var(--font-mono);
  letter-spacing: -0.01em;
  box-shadow: var(--shadow-soft);
}
.preview-banner .dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
  margin-right: 6px;
  vertical-align: middle;
}


/* ── 26. Forms (text input / select / textarea / label) ───── */
.label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-muted);
  margin-bottom: var(--space-xs);
}
.input, .select, .textarea {
  width: 100%;
  font-family: inherit;
  font-size: var(--fs-base);
  color: var(--text);
  background: var(--surface-input);
  border: 1px solid var(--border);
  border-radius: var(--radius-button);
  padding: 8px 11px;
  line-height: 1.4;
  transition: border-color 0.12s, box-shadow 0.12s, background 0.12s;
}
.input::placeholder, .textarea::placeholder { color: var(--text-quiet); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--border-warm); }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  background: var(--surface);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-light);
}
.textarea { resize: vertical; min-height: 72px; }
.input:disabled, .select:disabled, .textarea:disabled { opacity: 0.5; cursor: not-allowed; }

/* Field label in the editorial voice — small mono caps, like an eyebrow */
.label.label-mono {
  font-family: var(--font-mono);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: var(--space-sm);
}
/* Roomier input for the one field a dialog is about */
.input.input-lg { padding: 11px 14px; font-size: 14px; }
/* One field = label + control + the gap to the next thing */
.field { margin-bottom: var(--space-xl); }


/* ── 27. Modal (overlay + panel) ───────────────────────────
   Was hand-rolled on three separate pages. One recipe: a blurred warm
   scrim, a surface panel, a serif heading, actions right-aligned. */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  padding: var(--space-xl);
  background: rgba(28, 25, 23, 0.5);
  backdrop-filter: blur(8px) saturate(1.1);
  -webkit-backdrop-filter: blur(8px) saturate(1.1);
  display: none;
  align-items: center;
  justify-content: center;
}
.modal-overlay.open { display: flex; }
.modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-modal);
  padding: 30px;
  width: 540px;
  max-width: 92vw;
  box-shadow: var(--shadow-modal);
}
.modal.modal-lg { width: 640px; max-height: 80vh; display: flex; flex-direction: column; }
.modal h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 26px;
  letter-spacing: -0.015em;
  margin-bottom: 6px;
  color: var(--text);
}
.modal .subtitle {
  color: var(--text-dim);
  font-size: 13.5px;
  margin-bottom: var(--space-xl);
  line-height: 1.5;
}
.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: var(--space-lg);
}


/* ── 28. Page shell — the centered page (Batches, Upload, Account) ──
   One wrapper for every page that is not the sidebar app-shell, so the
   list, the upload step and the account pages share one width, one header
   rhythm and one back-affordance. Wide data pages add .page-wide. */
.page {
  max-width: var(--content);
  margin: 0 auto;
  padding: 56px 32px 80px;
}
.page.page-wide   { max-width: var(--content-wide); }
.page.page-narrow { max-width: var(--content-narrow); }

.page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-xl);
  margin-bottom: 34px;
}
.page-header h1 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 42px;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text);
}
/* Title block: optional back-link above, h1 with an optional status pill beside it */
.page-title { display: flex; flex-direction: column; gap: var(--space-md); min-width: 0; }
.page-title .title-row { display: flex; align-items: center; gap: var(--space-lg); min-width: 0; }
.page-title h1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.header-actions { display: flex; gap: 10px; align-items: center; flex-shrink: 0; }
/* When the title block carries a .page-lede, the actions line up with the h1, not the lede */
.page-header.with-lede { align-items: flex-start; }
.page-header.with-lede .header-actions { margin-top: 6px; }

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-dim);
  text-decoration: none;
  letter-spacing: 0.02em;
  transition: color 0.12s;
}
.back-link:hover { color: var(--text); }

/* One sentence under the h1 saying what the page is for (admin pages) */
.page-lede {
  font-size: var(--fs-md);
  color: var(--text-dim);
  line-height: 1.5;
  max-width: 680px;
}


/* ── 29. User menu & avatar ──────────────────────────────────
   The profile dropdown (templates/_user_menu.html) and the initials
   avatar it is built from. Lived in auth.css; every v5 page needs it. */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  color: #FFFFFF;             /* initials on a saturated hue: white in both themes */
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.3px;
  user-select: none;
  flex-shrink: 0;
  border: 2px solid var(--surface);
}
.avatar.lg { width: 36px; height: 36px; font-size: 13px; }
.avatar.xl { width: 64px; height: 64px; font-size: 22px; }
.avatar-stack { display: inline-flex; align-items: center; }
.avatar-stack .avatar + .avatar { margin-left: -6px; }
.avatar-stack .overflow {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 24px; height: 24px; border-radius: 999px;
  background: var(--surface-stone); color: var(--text-dim);
  font-size: 10px; padding: 0 6px; margin-left: -6px;
  border: 2px solid var(--surface);
}
/* A viewer who just left fades for a few seconds (presence, static/js/ui/avatar.js) */
.avatar.ghost {
  opacity: 0.35;
  filter: saturate(0.3);
  transition: opacity 0.4s ease;
}

.user-menu { position: relative; display: inline-flex; align-items: center; }
.user-menu-trigger {
  display: flex; align-items: center; gap: 8px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 8px 4px 4px;
  color: var(--text);
  cursor: pointer;
  font-size: 13px;
  font-family: inherit;
}
.user-menu-trigger:hover { border-color: var(--accent); }
.user-menu-trigger .chevron { color: var(--text-dim); font-size: 11px; }
.user-menu-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 220px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 6px;
  box-shadow: var(--shadow-hover);
  z-index: 500;
}
.user-menu-panel[hidden] { display: none; }
.user-menu-panel .header { padding: 10px 12px; border-bottom: 1px solid var(--border); margin-bottom: 4px; }
.user-menu-panel .header .name  { font-weight: 600; font-size: 14px; }
.user-menu-panel .header .email { color: var(--text-dim); font-size: 12px; }
.user-menu-panel a,
.user-menu-panel button {
  display: block; width: 100%; text-align: left;
  padding: 8px 12px;
  background: transparent; color: var(--text);
  border: none; font: inherit; text-decoration: none;
  cursor: pointer; border-radius: 6px; font-size: 13px;
}
.user-menu-panel a:hover,
.user-menu-panel button:hover { background: var(--surface-stone); }
.user-menu-panel .divider { height: 1px; background: var(--border); margin: 4px 0; }


/* ── 30. Data table (admin ledgers) ────────────────────────────
   Session Overview, Audit log, Email queue and Team share one table
   recipe: a card with an optional toolbar on top and a footer for paging,
   mono caps column heads like the batch list, quiet row rules, numbers
   right-aligned in the mono face. */
.table-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
/* A ledger wider than its card scrolls inside the card; the page never scrolls sideways */
.table-scroll { overflow-x: auto; }

.toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 13px 20px;
  border-bottom: 1px solid var(--border-soft);
}
.toolbar-search {
  flex: 1;
  min-width: 160px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.toolbar-search > span { color: var(--text-quiet); font-size: 13px; line-height: 1; }
.toolbar-search input {
  flex: 1; min-width: 0;
  background: transparent; border: none; outline: none;
  color: var(--text); font-family: var(--font-body); font-size: 13.5px;
}
.toolbar-search input::placeholder { color: var(--text-quiet); }
.toolbar .input, .toolbar .select {
  width: auto; height: 30px; padding: 0 10px; font-size: var(--fs-sm);
}
.toolbar .label { margin: 0 0 0 var(--space-xs); }

.data-table { width: 100%; border-collapse: collapse; }
.data-table thead th {
  text-align: left;
  padding: 11px 20px;
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-quiet);
  font-weight: 500;
  background: var(--surface-warm);
  border-bottom: 1px solid var(--border-soft);
  white-space: nowrap;
}
.data-table thead th.sortable { cursor: pointer; user-select: none; }
.data-table thead th.sortable:hover { color: var(--text-muted); }
.data-table thead th.sorted { color: var(--text); }
.data-table thead th .sort-arrow { margin-left: 4px; color: var(--accent); }
.data-table tbody td {
  padding: 13px 20px;
  border-bottom: 1px solid var(--border-soft);
  font-size: var(--fs-base);
  vertical-align: middle;
}
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover td { background: var(--surface-warm); }
.data-table .num  { text-align: right; font-family: var(--font-mono); font-size: 11.5px; font-variant-numeric: tabular-nums; }
.data-table .mono { font-family: var(--font-mono); font-size: 11.5px; }
.data-table .dim  { color: var(--text-dim); }
.data-table .row-title { font-weight: 600; color: var(--text); letter-spacing: -0.01em; text-decoration: none; }
.data-table a.row-title:hover { color: var(--accent); }
.data-table .row-sub { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-dim); margin-top: 2px; }
.data-table .nowrap { white-space: nowrap; }
/* A state row (loading / empty / error) fills the table and never highlights */
.data-table tr.state td { padding: 0; }
.data-table tr.state:hover td { background: transparent; }

/* Empty, loading and error states — one shape, the words belong to the page */
.table-state {
  padding: var(--space-3xl) var(--space-xl);
  display: flex; flex-direction: column; align-items: center;
  gap: var(--space-md);
  text-align: center;
  color: var(--text-dim);
  font-size: var(--fs-base);
  line-height: 1.5;
}
.table-state .title {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 500;
  color: var(--text);
  letter-spacing: -0.01em;
}
.table-state.error .title { color: var(--red); }
.table-state .btn { margin-top: var(--space-xs); }

.table-foot {
  display: flex; justify-content: space-between; align-items: center;
  gap: var(--space-lg);
  padding: 10px 20px;
  border-top: 1px solid var(--border-soft);
  background: var(--surface-warm);
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-dim);
}
.table-foot .paging { display: flex; align-items: center; gap: var(--space-sm); }


/* ── 31. Segmented switch (two or three exclusive options) ─────── */
.segmented {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-button);
  overflow: hidden;
  background: var(--surface);
}
.segmented button {
  border: none;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 500;
  padding: 0 12px;
  height: 28px;
  line-height: 1;
  transition: background 0.12s, color 0.12s;
}
.segmented button + button { border-left: 1px solid var(--border); }
.segmented button:hover { color: var(--text); background: var(--surface-warm); }
.segmented button[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); }


/* ── 32. Notice — one sentence of status, coloured by meaning ───
   Green = healthy, red = stopped or broken, orange = the machine is
   working or something is pending. Neutral for plain information. */
.notice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
  padding: 12px 16px;
  margin-bottom: var(--space-xl);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-warm);
  color: var(--text-muted);
  font-size: var(--fs-base);
  line-height: 1.5;
}
.notice[hidden] { display: none; }
.notice b { color: var(--text); font-weight: 600; }
.notice .btn { margin-left: auto; flex-shrink: 0; }
.notice-green  { background: var(--accent-light); border-color: var(--accent-border); color: var(--accent); }
.notice-red    { background: var(--red-bg);       border-color: var(--red-border);    color: var(--red); }
.notice-orange { background: var(--orange-bg);    border-color: var(--orange-border); color: var(--orange); }
.notice-green b, .notice-red b, .notice-orange b { color: inherit; }


/* ── 33. Settings group — a card of labelled rows (Profile, Team) ──
   One heading, an optional intro line, rows of mono label · value · action,
   and an action strip at the bottom. Tables inside use .data-table. */
.settings-group {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  margin-bottom: var(--space-xl);
  overflow: hidden;
}
.settings-group > h2 {
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
  padding: 16px 22px 14px;
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.settings-group > h2 .meta {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
  white-space: nowrap;
}
.settings-group > .intro {
  font-size: var(--fs-base);
  color: var(--text-dim);
  line-height: 1.5;
  padding: 0 22px 14px;
  margin-top: -4px;
}
.settings-row {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  padding: 14px 22px;
  min-height: 56px;
  border-top: 1px solid var(--border-soft);
  font-size: 14px;
}
.settings-row[hidden] { display: none; }
.settings-row .label { width: 132px; flex-shrink: 0; margin: 0; }
.settings-row .value {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--space-md);
  flex-wrap: wrap;
  color: var(--text-warm);
}
.settings-row .value a { color: var(--accent); text-decoration: none; font-weight: 500; }
.settings-row .value a:hover { text-decoration: underline; text-underline-offset: 3px; }
.settings-row .input, .settings-row .select { max-width: 320px; }
.settings-note {
  padding: 0 22px 14px;
  margin-top: -4px;
  font-size: var(--fs-sm);
  color: var(--text-dim);
}
.settings-note:empty { display: none; }
.settings-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 16px 22px 18px;
  border-top: 1px solid var(--border-soft);
}
.settings-group .data-table thead th { border-top: 1px solid var(--border-soft); }
.settings-group .data-table thead th, .settings-group .data-table tbody td { padding-left: 22px; padding-right: 22px; }
.settings-group .data-table tbody tr:last-child td { border-bottom: none; }


/* ── 34. Live dot — something is happening right now ──────────── */
.live-dot {
  display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-light);
  animation: live-pulse 2s infinite;
  vertical-align: middle;
}
@keyframes live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }


/* ── 35. Folded settings — a dialog's optional sections ─────────
   Studio v1 put "Instructions (optional)" and "Keywords (optional)" behind
   an accordion in its Add-new-folder dialog: out of the way of the one field
   that matters (the name), one click from anyone who wants them. Same shape
   here, shared by the Create batch dialog and the batch page's Custom
   settings dialog — see templates/_custom_settings.html and
   static/js/ui/custom-settings.js. A closed fold still says whether it is
   carrying anything (.fold-summary), because a setting you cannot see is a
   setting you forget you set. */
.fold {
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-button);
  background: var(--surface-warm);
  margin-bottom: 8px;
}
.fold.is-open { border-color: var(--border-warm); background: var(--surface); }
.fold-head {
  width: 100%;
  display: flex; align-items: center; gap: 10px;
  padding: 13px 16px;
  background: none; border: none; cursor: pointer; text-align: left;
  font-family: inherit; font-size: 13.5px; font-weight: 600; color: var(--text);
}
.fold-head:hover { color: var(--accent); }
.fold-head .optional { font-weight: 400; color: var(--text-quiet); }
.fold-summary {
  margin-left: auto;
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.04em;
  color: var(--text-dim); font-weight: 500;
}
.fold-summary:empty { display: none; }
.fold-caret {
  color: var(--text-quiet); font-size: 15px; line-height: 1;
  transition: transform 0.18s ease;
}
.fold.is-open .fold-caret { transform: rotate(90deg); }
.fold-body { padding: 0 16px 14px; }
.fold-body[hidden] { display: none; }
.fold-help {
  color: var(--text-dim); font-size: 12px; line-height: 1.5;
  margin: 0 0 8px;
}
/* The keyword field: the report's own pills and dashed add-input (§17), laid
   out as one bordered field so it reads as an input rather than a list. */
.kw-field {
  display: flex; flex-wrap: wrap; align-items: center; gap: 5px;
  padding: 7px 8px;
  background: var(--surface-input);
  border: 1px solid var(--border);
  border-radius: var(--radius-button);
}
.kw-field:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-light); }
.kw-field .kw-add-input { flex: 1 1 200px; width: auto; border-color: transparent; }
.kw-field .kw-add-input:focus { width: auto; background: transparent; border-color: transparent; }
.kw-field .kw-pill .pill-x { cursor: pointer; border: none; background: none; font-family: inherit; }


/* ── 36. Dark theme ───────────────────────────────────────────
   Opt-in only: applies when [data-theme="dark"] is set on <html>. */
[data-theme="dark"] {
  /* Surfaces */
  --bg:               #14110D;
  --bg-warm:          #1A1611;
  --surface:          #1F1A14;
  --surface-warm:     #241E17;
  --surface-stone:    #2A231B;
  --surface-input:    #221C15;

  /* Borders */
  --border:           #352D23;
  --border-soft:      #2C261D;
  --border-warm:      #41382C;

  /* Text */
  --text:             #F7F3EC;
  --text-warm:        #EFEAE1;
  --text-muted:       #CFC7B9;
  --text-dim:         #A29789;
  --text-quiet:       #756B5E;

  /* Accent — brighter emerald stays legible on dark; ink flips to dark green */
  --accent:           #34D399;
  --accent-hover:     #6EE7B7;
  --accent-ink:       #052E22;
  --accent-light:     rgba(52,211,153,0.14);
  --accent-border:    rgba(52,211,153,0.38);

  /* Danger */
  --red:              #F0876A;
  --red-bg:           rgba(240,135,106,0.13);
  --red-border:       rgba(240,135,106,0.34);

  /* Warning */
  --orange:           #F2A65A;
  --orange-bg:        rgba(242,166,90,0.13);
  --orange-border:    rgba(242,166,90,0.32);

  /* Sand */
  --sand:             #D2A77B;
  --sand-bg:          rgba(210,167,123,0.12);
  --sand-border:      rgba(210,167,123,0.30);

  /* Shadows — deeper on dark */
  --shadow-soft:      0 1px 2px rgba(0,0,0,0.4);
  --shadow-card:      0 1px 3px rgba(0,0,0,0.45), 0 1px 2px rgba(0,0,0,0.3);
  --shadow-hover:     0 6px 20px rgba(0,0,0,0.5), 0 2px 6px rgba(0,0,0,0.35);
  --shadow-hero:      0 16px 40px -16px rgba(0,0,0,0.6), 0 6px 16px -6px rgba(0,0,0,0.4);
  --shadow-modal:     0 32px 80px -16px rgba(0,0,0,0.7), 0 8px 24px -8px rgba(0,0,0,0.5);
}

/* ── 40. Narrow screens ──────────────────────────────────────
   The v5 shell was designed at desktop width and carried no media queries
   at all until 2026-09-17. Two shared components actively break on a phone,
   and both are fixed here rather than page-by-page (tests/test_design_system
   .py::test_shared_components_are_defined_once enforces that):

   * `.page-header` is a flex row with `.header-actions` at flex-shrink:0
     beside an ellipsised h1, so the title collapses — "Billing" rendered as
     "B…" at 390px, and Profile's h1 collapsed to zero width. Wrapping puts
     the actions under the title instead.
   * `.settings-row` stays one flex row, so label + input + button overlap
     once the nav rail and card padding are subtracted. Stacking keeps every
     control tappable.

   Both are no-ops above the breakpoint. This is a targeted fix, not a
   responsive pass: the grids and tables on the admin pages have not been
   reviewed at this width. */
@media (max-width: 560px) {
  .page { padding: 32px 16px 56px; }

  .page-header { flex-wrap: wrap; gap: var(--space-md); }
  .page-header h1 { font-size: 32px; }
  .page-title { flex: 1 1 100%; }
  .header-actions { flex: 1 1 100%; }

  .settings-row { flex-wrap: wrap; align-items: flex-start; }
  .settings-row .label { width: auto; flex: 1 1 100%; }
  .settings-row .value { flex: 1 1 100%; }
  .settings-row > .btn { width: 100%; justify-content: center; }

  .stat-grid { grid-template-columns: minmax(0, 1fr); }
}
