/*
 * Design tokens as CSS custom properties.
 * Mirrors docs/design-language/tokens.md and tailwind.config.js.
 *
 * Aligned with the ShootBuddy / One-Liner design system. The only deliberate
 * divergence is --color-header-bg (black for Image Approvals).
 */

:root {
  /* Brand red scale */
  --color-brand-50:  #FFF1F1;
  --color-brand-100: #FFE0E0;
  --color-brand-200: #FFC5C5;
  --color-brand-300: #FF9B9B;
  --color-brand-400: #E04545;
  --color-brand-500: #c00000;
  --color-brand-600: #9a0000;
  --color-brand-700: #800000;
  --color-brand-800: #660000;
  --color-brand-900: #500000;

  --color-primary:       var(--color-brand-500);
  --color-primary-light: #d42a2a;
  --color-primary-dark:  var(--color-brand-600);

  /* Neutrals (Tailwind gray) */
  --color-gray-50:  #F9FAFB;
  --color-gray-100: #F3F4F6;
  --color-gray-200: #E5E7EB;
  --color-gray-300: #D1D5DB;
  --color-gray-400: #9CA3AF;
  --color-gray-500: #6B7280;
  --color-gray-600: #4B5563;
  --color-gray-700: #374151;
  --color-gray-800: #1F2937;
  --color-gray-900: #111827;

  /* Surfaces */
  --color-bg:               #FAFAFA;
  --color-surface:          #FFFFFF;
  --color-surface-elevated: #FFFFFF;
  --color-dark-base:        #111827;
  --color-dark-elevated:    #1F2937;
  --color-header-bg:        #000000; /* divergence from ShootBuddy */

  /* Text */
  --color-text:           var(--color-gray-900);
  --color-text-secondary: var(--color-gray-600);
  --color-text-tertiary:  var(--color-gray-400);
  --color-text-inverse:   #FFFFFF;

  /* Borders */
  --color-border:         var(--color-gray-200);
  --color-border-subtle:  var(--color-gray-100);
  --color-border-focus:   var(--color-brand-500);

  /* Categorical palette — for charts, tags, calendar pills, owner/production
     identity. NEVER for actions, links, focus, or anything decision-bearing
     (those belong to brand red). Each hue ships three steps: 100 = tinted bg,
     500 = solid dot/fill, 700 = readable text on the 100 tint. */
  --color-cat-indigo-100: #E0E7FF;
  --color-cat-indigo-500: #4F46E5;
  --color-cat-indigo-700: #3730A3;
  --color-cat-teal-100:   #CCFBF1;
  --color-cat-teal-500:   #0D9488;
  --color-cat-teal-700:   #115E59;
  --color-cat-amber-100:  #FEF3C7;
  --color-cat-amber-500:  #D97706;
  --color-cat-amber-700:  #92400E;
  --color-cat-violet-100: #EDE9FE;
  --color-cat-violet-500: #7C3AED;
  --color-cat-violet-700: #5B21B6;
  --color-cat-pink-100:   #FCE7F3;
  --color-cat-pink-500:   #DB2777;
  --color-cat-pink-700:   #9D174D;
  --color-cat-slate-100:  #E2E8F0;
  --color-cat-slate-500:  #475569;
  --color-cat-slate-700:  #1E293B;

  /* Semantic */
  --color-success:    #059669;
  --color-success-bg: #ECFDF5;
  --color-warning:    #B45309;
  --color-warning-bg: #FFFBEB;
  --color-error:      #c00000;
  --color-error-bg:   #FEF2F2;
  --color-info:       #2563EB;
  --color-info-bg:    #EFF6FF;

  /* Typography */
  --font-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont,
               'Segoe UI', Roboto, sans-serif;
  --font-mono: 'JetBrains Mono', 'Fira Code', Consolas, monospace;

  /* Spacing (4px grid) */
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  20px;
  --space-6:  24px;
  --space-8:  32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;

  /* Radius */
  --radius-sm:  4px;
  --radius-md:  6px;
  --radius-lg:  8px;
  --radius-xl:  12px;
  --radius-full: 9999px;

  /* Shadow */
  --shadow-xs: 0 1px 2px rgba(0,0,0,0.04);
  --shadow-sm: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04);
  --shadow-md: 0 4px 12px rgba(0,0,0,0.08);
  --shadow-lg: 0 4px 16px rgba(0,0,0,0.1);
  --shadow-xl: 0 20px 25px rgba(0,0,0,0.06), 0 10px 10px rgba(0,0,0,0.03);
  --shadow-focus:       0 0 0 3px rgba(192, 0, 0, 0.15);
  --shadow-focus-error: 0 0 0 3px rgba(220, 38, 38, 0.15);

  /* Motion */
  --ease:           cubic-bezier(0.4, 0, 0.2, 1);
  --duration-fast:  75ms;
  --duration-base:  150ms;
  --duration-slow:  300ms;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 0ms;
    --duration-base: 0ms;
    --duration-slow: 0ms;
  }
}
/*
 * Base layer: body defaults, focus rings.
 * Designed to live inside `@layer base { … }` once Tailwind is wired up.
 *
 * Inter is loaded from Google Fonts in the base Jinja layout:
 *   <link rel="preconnect" href="https://fonts.googleapis.com">
 *   <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
 *   <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
 */

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

html {
  font-family: var(--font-sans);
  color: var(--color-text);
  background-color: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

body {
  margin: 0;
  line-height: 1.5;
  font-size: 0.875rem; /* 14px default body */
}

h1, h2, h3, h4 {
  color: var(--color-text);
  margin: 0;
}

a {
  color: var(--color-primary);
  text-decoration: none;
  transition: color var(--duration-base) var(--ease);
}
/* Exclude `.btn` (including anchor-styled buttons `<a class="btn ...">`) from
 * link hover styling. Otherwise `a:hover` (specificity 0,1,1) overrides a
 * button variant's base text colour (e.g. `.btn-primary` at 0,1,0), so a
 * `.btn-primary` anchor gets dark-red text on its dark-red hover background —
 * invisible — plus an unwanted underline. Buttons own their hover appearance. */
a:not(.btn):hover {
  color: var(--color-primary-dark);
  text-decoration: underline;
}

/* Tabular figures for any number that lives in a stat / table cell. */
.tabular-nums,
.stat__value,
.table td,
.table th {
  font-variant-numeric: tabular-nums;
}

/* Accessible focus ring on every interactive element. */
:where(button, a, input, textarea, select, [role="button"], [tabindex]):focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
  border-radius: var(--radius-md);
}

::selection {
  background: var(--color-brand-50);
  color: var(--color-gray-900);
}

/* Skip-to-content link — visually hidden until keyboard-focused. */
.skip-link {
  position: fixed;
  top: 0.5rem;
  left: 0.5rem;
  z-index: 100;
  padding: 0.5rem 0.875rem;
  background: var(--color-primary);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 600;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  transform: translateY(-150%);
  transition: transform 120ms var(--ease, ease);
}
.skip-link:focus,
.skip-link:focus-visible {
  transform: translateY(0);
  outline: 2px solid #fff;
  outline-offset: 2px;
}
.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.top-0{top:0}.\!m-0{margin:0!important}.m-0{margin:0}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-0{margin-bottom:0}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-12{margin-top:3rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.\!hidden{display:none!important}.hidden{display:none}.\!h-screen{height:100vh!important}.max-h-40{max-height:10rem}.min-h-0{min-height:0}.min-h-screen{min-height:100vh}.w-4{width:1rem}.w-40{width:10rem}.w-9{width:2.25rem}.w-\[5\.5rem\]{width:5.5rem}.w-\[6\.5rem\]{width:6.5rem}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[180px\]{min-width:180px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-\[18ch\]{max-width:18ch}.max-w-\[22rem\]{max-width:22rem}.max-w-\[64ch\]{max-width:64ch}.max-w-md{max-width:28rem}.max-w-none{max-width:none}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.gap-x-6{-moz-column-gap:1.5rem;column-gap:1.5rem}.gap-x-8{-moz-column-gap:2rem;column-gap:2rem}.gap-y-3{row-gap:.75rem}.gap-y-4{row-gap:1rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem*var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(243 244 246/var(--tw-divide-opacity,1))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(229 231 235/var(--tw-divide-opacity,1))}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:6px}.rounded-lg{border-radius:8px}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-b-4{border-bottom-width:4px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1))}.border-primary{--tw-border-opacity:1;border-color:rgb(192 0 0/var(--tw-border-opacity,1))}.border-white\/10{border-color:hsla(0,0%,100%,.1)}.border-white\/25{border-color:hsla(0,0%,100%,.25)}.bg-dark-base{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-3{padding:.75rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-20{padding-top:5rem;padding-bottom:5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-2\.5{padding-bottom:.625rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-4{padding-left:1rem}.pt-1{padding-top:.25rem}.pt-4{padding-top:1rem}.pt-8{padding-top:2rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:JetBrains Mono,Fira Code,Consolas,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-5xl{font-size:3rem;line-height:1}.text-\[11px\]{font-size:11px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.5}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-\[1\.05\]{line-height:1.05}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-\[0\.18em\]{letter-spacing:.18em}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-brand-300{--tw-text-opacity:1;color:rgb(255 155 155/var(--tw-text-opacity,1))}.text-error{--tw-text-opacity:1;color:rgb(192 0 0/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity,1))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.text-primary{--tw-text-opacity:1;color:rgb(192 0 0/var(--tw-text-opacity,1))}.text-success{--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/60{color:hsla(0,0%,100%,.6)}.text-white\/70{color:hsla(0,0%,100%,.7)}.text-white\/80{color:hsla(0,0%,100%,.8)}.text-white\/90{color:hsla(0,0%,100%,.9)}.no-underline{text-decoration-line:none}.shadow-sm{--tw-shadow:0 1px 3px rgba(0,0,0,.06),0 1px 2px rgba(0,0,0,.04);--tw-shadow-colored:0 1px 3px var(--tw-shadow-color),0 1px 2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.first\:pt-0:first-child{padding-top:0}.last\:pb-0:last-child{padding-bottom:0}.hover\:text-primary:hover{--tw-text-opacity:1;color:rgb(192 0 0/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}@media (min-width:640px){.sm\:col-span-2{grid-column:span 2/span 2}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-\[120px_1fr\]{grid-template-columns:120px 1fr}}@media (min-width:768px){.md\:col-span-1{grid-column:span 1/span 1}.md\:col-span-2{grid-column:span 2/span 2}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1024px){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}/*
 * Component recipes. Designed to live inside `@layer components { … }`.
 *
 * Aligned with the ShootBuddy / One-Liner design system. The recipe names
 * (`.btn`, `.btn-primary`, `.card`, `.stat-row`, `.status-badge`,
 * `.meatball`, `.app-header`) match across both projects so people moving
 * between codebases see the same vocabulary.
 *
 * The only deliberate visual divergence is `.app-header` — Image Approvals
 * keeps a black header background. See docs/design-language/README.md.
 */

/* ---------- Layout ---------- */

.page {
  max-width: 80rem; /* 1280px */
  margin-inline: auto;
  padding-inline: var(--space-4);
}
@media (min-width: 768px) { .page { padding-inline: var(--space-6); } }
@media (min-width: 1024px) { .page { padding-inline: var(--space-8); } }

.page--narrow { max-width: 64rem; /* 1024px */ }

/* ---------- App header (black variant) ---------- */

.app-header {
  position: sticky;
  top: 0;
  z-index: 50;
  height: 64px;
  background: var(--color-header-bg);
  color: var(--color-text-inverse);
  border-bottom: 1px solid #000;
}
.app-header__inner {
  max-width: 80rem;
  height: 100%;
  margin-inline: auto;
  padding-inline: var(--space-4);
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.app-header__nav {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}
.app-header__divider {
  width: 1px;
  height: 28px;
  background: var(--color-gray-600); /* visible on black */
  margin: 0 var(--space-2);
}

/* Hamburger trigger — sits as an enclosed square cell at the start of the
   header, with full-height side borders so it reads as its own boundary. */
.hamburger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  background: transparent;
  border: 0;
  border-radius: 0;
  color: #fff;
  cursor: pointer;
  transition: background-color var(--duration-base) var(--ease);
  border-left: 1px solid rgba(255, 255, 255, 0.16);
  border-right: 1px solid rgba(255, 255, 255, 0.16);
}
.hamburger:hover { background: rgba(255,255,255,0.08); }
.hamburger svg { width: 22px; height: 22px; stroke: currentColor; stroke-width: 2.25; }

/* Header nav links — white on black, brand-red active underline. */
.nav-item {
  display: inline-flex;
  align-items: center;
  height: 64px;
  padding: 0 var(--space-4);
  color: var(--color-gray-300);
  font-weight: 500;
  font-size: 0.875rem;
  border-bottom: 2px solid transparent;
  transition: color var(--duration-base) var(--ease),
              border-color var(--duration-base) var(--ease);
}
.nav-item:hover { color: #fff; text-decoration: none; }
.nav-item.is-active { color: #fff; border-bottom-color: var(--color-primary); }

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 10px 16px;
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: background-color var(--duration-base) var(--ease),
              border-color var(--duration-base) var(--ease),
              color var(--duration-base) var(--ease),
              box-shadow var(--duration-base) var(--ease);
}
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}
.btn--sm { height: 32px; padding: 0 16px; font-size: 0.8rem; border-radius: var(--radius-md); box-shadow: none; }
.btn--lg { padding: 12px 20px; font-size: 1rem; }
.btn--block { width: 100%; min-width: 0; }

.btn-primary {
  background: var(--color-primary);
  color: #fff;
}
.btn-primary:hover:not(:disabled) { background: var(--color-primary-dark); }

.btn-secondary {
  background: var(--color-gray-100);
  color: var(--color-gray-700);
  border-color: var(--color-gray-200);
  font-weight: 500;
}
.btn-secondary:hover:not(:disabled) {
  background: var(--color-gray-200);
  border-color: var(--color-gray-300);
}

.btn-danger {
  background: #fff;
  color: var(--color-error);
  border-color: var(--color-gray-200);
}
.btn-danger:hover:not(:disabled) {
  background: var(--color-error-bg);
  border-color: var(--color-brand-200);
}

.btn-ghost {
  background: transparent;
  color: var(--color-gray-700);
  box-shadow: none;
}
.btn-ghost:hover:not(:disabled) { background: var(--color-gray-100); color: var(--color-gray-900); }

/* ---------- Card ---------- */

.card {
  position: relative;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-5);
  box-shadow: var(--shadow-xs);
  transition: box-shadow var(--duration-base) var(--ease),
              border-color var(--duration-base) var(--ease);
}
.card:hover { box-shadow: var(--shadow-md); }

.card__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.card__title {
  font-size: 1.1rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--color-text);
  margin: 0;
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.card__title-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

.card__meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.75rem;
  color: var(--color-text-tertiary);
}

.card__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-top: var(--space-3);
  margin-top: var(--space-4);
  border-top: 1px solid var(--color-border-subtle);
}

.card-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
}
@media (min-width: 768px) {
  .card-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .card-grid { grid-template-columns: repeat(3, 1fr); }
}

/* ---------- Stat row (segmented) ---------- */

.stat-row {
  display: flex;
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin: var(--space-4) 0;
}
.stat {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--space-3) var(--space-2);
  text-align: center;
  border-left: 1px solid var(--color-border-subtle);
  transition: background-color var(--duration-base) var(--ease);
}
.stat:first-child { border-left: 0; }
.stat:hover { background: var(--color-gray-50); }
.stat__value {
  font-size: 1rem;
  font-weight: 700;
  color: var(--color-text);
  line-height: 1.1;
}
.stat__label {
  margin-top: 2px;
  font-size: 0.65rem;
  font-weight: 500;
  color: var(--color-text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* ---------- Status badges (outlined pills) ---------- */

.status-badge {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 10px;
  font-size: 0.65rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  white-space: nowrap;
  border-radius: var(--radius-full);
  border: 1px solid transparent;
  background: var(--color-gray-100);
  color: var(--color-gray-700);
}
.status-badge--success { background: var(--color-success-bg); color: var(--color-success); border-color: #A7F3D0; }
.status-badge--warning { background: var(--color-warning-bg); color: var(--color-warning); border-color: #FDE68A; }
.status-badge--error   { background: var(--color-error-bg);   color: var(--color-error);   border-color: #FECACA; }
.status-badge--info    { background: var(--color-info-bg);    color: var(--color-info);    border-color: #BFDBFE; }

/* ---------- Switch (toggle) ----------
   Binary on/off control. Use for "is this thing active" — feature flags,
   enable/disable, per-row toggles. NOT a substitute for a destructive
   confirm (that's still .modal) and NOT a substitute for a multi-option
   choice (that's a segmented control or select).
   Markup pattern:
     <label class="switch">
       <input type="checkbox" class="switch__input" checked>
       <span class="switch__track"><span class="switch__thumb"></span></span>
       <span class="switch__label">On</span>
     </label>
   For server-driven toggles (no JS), wrap the label inside a <form> that
   submits on change — see admin/workers/index.html. */
.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  user-select: none;
  font-size: 0.8125rem;
  color: var(--color-text-secondary);
}
.switch__input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 0;
  height: 0;
}
.switch__track {
  position: relative;
  display: inline-block;
  width: 36px;
  height: 20px;
  background: var(--color-gray-300);
  border-radius: var(--radius-full);
  transition: background-color var(--duration-base) var(--ease);
  flex-shrink: 0;
}
.switch__thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  background: #fff;
  border-radius: var(--radius-full);
  box-shadow: 0 1px 2px rgba(0,0,0,0.2);
  transition: transform var(--duration-base) var(--ease);
}
.switch__input:checked + .switch__track {
  background: var(--color-primary);
}
.switch__input:checked + .switch__track .switch__thumb {
  transform: translateX(16px);
}
.switch__input:focus-visible + .switch__track {
  box-shadow: 0 0 0 3px rgba(192,0,0,0.15);
}
.switch__input:disabled + .switch__track {
  opacity: 0.5;
  cursor: not-allowed;
}
.switch:has(.switch__input:disabled) {
  cursor: not-allowed;
  color: var(--color-text-tertiary);
}
.switch__label { white-space: nowrap; }
/* Compact variant for table cells. */
.switch--sm .switch__track { width: 28px; height: 16px; }
.switch--sm .switch__thumb { width: 12px; height: 12px; }
.switch--sm .switch__input:checked + .switch__track .switch__thumb {
  transform: translateX(12px);
}

/* ---------- Meatball menu (card overflow) ---------- */

.meatball {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-md);
  color: var(--color-text-tertiary);
  cursor: pointer;
  transition: background-color var(--duration-base) var(--ease),
              color var(--duration-base) var(--ease);
}
.meatball:hover { background: var(--color-gray-100); color: var(--color-gray-700); }
.meatball svg { width: 16px; height: 16px; }

.menu {
  min-width: 170px;
  padding: var(--space-1);
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.menu__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--color-gray-700);
  background: transparent;
  border: 0;
  border-radius: var(--radius-md);
  text-align: left;
  cursor: pointer;
}
.menu__item:hover { background: var(--color-gray-50); color: var(--color-gray-900); }
.menu__item--danger { color: var(--color-error); }
.menu__divider {
  height: 1px;
  background: var(--color-border-subtle);
  margin: var(--space-1) 0;
  border: 0;
}

/* Promoted row action(s) sitting beside the overflow menu. Keeps the button
   and the ⋯ trigger on one line and vertically centred, and stops the pair
   wrapping when the cell narrows. Use sparingly — one promoted action per
   row at most, everything else belongs in the menu. */
.row-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  white-space: nowrap;
}

/* Row overflow (meatball) menu positioning. The trigger + panel live in a
   .row-menu-wrap so the .menu drops below the ⋯ button, right-aligned. The
   panel starts [hidden]; app/static/js/admin.js (or the small per-page toggle)
   removes [hidden] on open. */
.row-menu-wrap { position: relative; display: inline-block; text-align: left; }
.row-menu-wrap .menu {
  position: absolute;
  top: calc(100% + var(--space-1));
  right: 0;
  z-index: 30;
  min-width: 180px;
}
.menu a.menu__item,
.menu button.menu__item { width: 100%; text-decoration: none; }
.menu__item svg { width: 14px; height: 14px; flex: none; opacity: 0.7; }

/* ---------- Checkbox picker (searchable multi-select) ----------
   A usable replacement for a native <select multiple>: a search box over a
   scrollable list of checkbox rows. Used for the user↔productions assignment. */
.check-list__search { margin-top: var(--space-2); }
.check-list__items {
  max-height: 240px;
  overflow-y: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-1);
  margin-top: var(--space-2);
}
.check-list__empty { padding: var(--space-3); font-size: 0.8125rem; color: var(--color-text-tertiary); }
.check-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 0.875rem;
  line-height: 1.3;
}
.check-row:hover { background: var(--color-gray-50); }
.check-row input { flex: none; margin: 0; }

/* Type-ahead user picker (reuses .menu for the results dropdown). */
.user-picker { position: relative; }
.user-picker__results {
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  right: 0;
  z-index: 30;
  max-height: 260px;
  overflow-y: auto;
}
.user-picker__results .menu__item { width: 100%; cursor: pointer; }
.user-picker__results .menu__item--empty { color: var(--color-text-tertiary); cursor: default; }

/* ---------- Progress bar ---------- */

.progress {
  height: 4px;
  background: var(--color-gray-100);
  border-radius: var(--radius-full);
  overflow: hidden;
}
.progress__fill {
  height: 100%;
  background: var(--color-primary);
  transition: width var(--duration-slow) var(--ease);
}
.progress--complete .progress__fill { background: var(--color-success); }

/* ---------- Form fields ---------- */

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: var(--space-5);
}
.field__label {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-text-secondary);
}
.input,
.field__input,
.field__textarea,
.field__select {
  width: 100%;
  padding: 10px 12px;
  font: inherit;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-gray-300);
  border-radius: var(--radius-md);
  transition: border-color var(--duration-base) var(--ease),
              box-shadow var(--duration-base) var(--ease);
}
.field__textarea { min-height: 96px; }
.input:hover,
.field__input:hover { border-color: var(--color-gray-400); }
.input:focus,
.field__input:focus,
.field__textarea:focus,
.field__select:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: var(--shadow-focus);
}
.input::placeholder,
.field__input::placeholder { color: var(--color-text-tertiary); }
.input:disabled { background: var(--color-gray-50); color: var(--color-text-tertiary); cursor: not-allowed; }
.field__help  { font-size: 0.75rem; color: var(--color-text-tertiary); }
.field__error { font-size: 0.75rem; color: var(--color-error); }

/* ---------- Inline alerts / notice boxes ----------
   Rule: put the text directly on the alert container — never wrap in <p>. */

.alert {
  display: block;
  padding: 10px 12px;
  font-size: 0.875rem;
  border: 1px solid;
  border-radius: var(--radius-lg);
}
.alert--warning { background: var(--color-warning-bg); border-color: #FDE68A; color: #92400E; }
.alert--info    { background: var(--color-info-bg);    border-color: #BFDBFE; color: #1D4ED8; }
.alert--success { background: var(--color-success-bg); border-color: #A7F3D0; color: #047857; }
.alert--error   { background: var(--color-error-bg);   border-color: #FECACA; color: var(--color-error); }
/* Dismissible variant — flash messages with a close button (wired by admin.js
   via data-dismiss-alert). Base .alert stays block so plain alerts are unaffected. */
.alert--dismissible { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-2); }
.alert__close {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; margin: -1px -2px 0 0; padding: 0;
  color: inherit; background: transparent; border: 0; border-radius: var(--radius-sm);
  opacity: 0.6; cursor: pointer;
}
.alert__close:hover { opacity: 1; }

/* ---------- Tables ---------- */

.table {
  width: 100%;
  border-collapse: collapse;
}
.table th {
  text-align: left;
  padding: var(--space-3) var(--space-4);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--color-gray-500);
  background: var(--color-gray-50);
  border-bottom: 1px solid var(--color-border);
}
.table td {
  padding: var(--space-4);
  font-size: 0.875rem;
  color: var(--color-gray-700);
  border-bottom: 1px solid var(--color-border-subtle);
}
.table tr:hover td { background: var(--color-gray-50); }

/* Wide tables.
   `.table` is `width: 100%`, so on its own it shrinks to fit its container
   rather than overflowing it — put it in an `overflow-x: auto` wrapper and
   nothing scrolls, the right-hand columns just get crushed and clip. Pair
   `.table-scroll` (the wrapper) with `.table--wide` (a min-width on the
   table) so the overflow is real and the scrollbar actually engages. */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  /* Firefox */
  scrollbar-width: thin;
  scrollbar-color: var(--color-gray-300) var(--color-gray-50);
}
/* Force a PERSISTENT scrollbar. macOS defaults to overlay scrollbars that stay
   invisible until you already scroll — which is useless as an affordance,
   because the whole point is telling the user there is more table to the
   right. Declaring ::-webkit-scrollbar with a height opts this element out of
   overlay behaviour in Chrome / Safari, so the bar is always drawn. */
.table-scroll::-webkit-scrollbar {
  height: 10px;
  -webkit-appearance: none;
}
.table-scroll::-webkit-scrollbar-track {
  background: var(--color-gray-50);
  border-top: 1px solid var(--color-border-subtle);
}
.table-scroll::-webkit-scrollbar-thumb {
  background: var(--color-gray-300);
  border-radius: 999px;
  border: 2px solid var(--color-gray-50);
}
.table-scroll::-webkit-scrollbar-thumb:hover { background: var(--color-gray-400); }
/* Floor, not a target: wide enough that the columns stay legible, low enough
   that a normal laptop viewport fits the table without scrolling. Only raise
   this if columns actually start colliding — every rem added here is a rem of
   horizontal scrolling for anyone on a smaller screen. */
.table--wide { min-width: 60rem; }
/* Same idea for a table living in a side panel or a half-width card, where
   60rem would mean permanent scrolling on a column that is only ~28rem
   wide. Pick the variant from the container, not the column count. */
.table--wide-sm { min-width: 32rem; }
.table .cell-names {
  display: block;
  max-width: 18rem;
  white-space: normal;
  line-height: 1.35;
}
.table .cell-muted { color: var(--color-gray-400); }

/* ---------- Modal ---------- */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(17, 24, 39, 0.5);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  z-index: 50;
}
.modal-overlay[hidden] { display: none; }
.modal {
  background: var(--color-surface);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  max-width: 500px;
  width: 100%;
  max-height: 90vh;
  /* `overflow: hidden` keeps the rounded corners clipping their children. On
     its own it also CLIPPED any modal taller than 90vh with no way to reach
     the rest — the footer buttons included. Becoming a flex column lets the
     body take the leftover height and scroll inside it, so the header and the
     Cancel/Confirm footer stay pinned and reachable at any viewport height. */
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.modal__header { padding: var(--space-5) var(--space-6); border-bottom: 1px solid var(--color-border); font-weight: 600; }
/* Danger variant — for destructive confirmation modals (permanent delete). */
.modal__header--danger {
  background: var(--color-error-bg);
  border-bottom-color: rgba(192, 0, 0, 0.18);
  color: var(--color-error);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.modal__header--danger svg { width: 18px; height: 18px; flex: none; }
/* A modal whose body and footer are wrapped in a <form> — the pattern every
   editable modal uses, so the footer's submit button posts the body's fields.
   Without this the form is the flex child and `.modal__body` is not, so the
   body has nothing to shrink against and `overflow-y` never engages: the
   modal stays clipped exactly as it was before the flex column was added.
   Pass the column through the form so the body is a flex child either way. */
.modal > form {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

/* The scrolling region. `min-height: 0` is required: a flex child defaults to
   min-height auto, which refuses to shrink below its content and re-creates
   the clipping this fixes. */
.modal__body {
  padding: var(--space-6);
  overflow-y: auto;
  min-height: 0;
}
.modal__footer { padding: var(--space-4) var(--space-6); border-top: 1px solid var(--color-border); background: var(--color-gray-50); display: flex; justify-content: flex-end; gap: var(--space-2); }

/* ---------- Spinner ---------- */

.spinner {
  display: inline-block;
  width: 20px;
  height: 20px;
  border: 2px solid var(--color-gray-200);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  vertical-align: middle;
}
.spinner--sm { width: 14px; height: 14px; border-width: 2px; }
.spinner--lg { width: 32px; height: 32px; border-width: 3px; }
.spinner--inverse { border-color: rgba(255,255,255,0.25); border-top-color: #fff; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 0s; }
}

.loading-overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  gap: 0.75rem;
  background: rgba(255, 255, 255, 0.75);
  backdrop-filter: blur(2px);
  z-index: 5;
}
.loading-overlay__label {
  margin-top: 44px;
  font-size: 0.8125rem;
  color: var(--color-text-secondary);
}

/* ---------- Tabs ---------- */

.tabs {
  display: flex;
  gap: 0.25rem;
  border-bottom: 1px solid var(--color-border);
  overflow-x: auto;
  white-space: nowrap;
  -ms-overflow-style: none;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.75rem 1rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-text-secondary);
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  cursor: pointer;
  transition: color var(--duration-base) var(--ease), border-color var(--duration-base) var(--ease);
}
.tab:hover { color: var(--color-text); }
.tab.is-active { color: var(--color-primary); border-bottom-color: var(--color-primary); font-weight: 600; }
.tab__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  font-size: 0.7rem;
  font-weight: 600;
  background: var(--color-gray-100);
  color: var(--color-text-secondary);
  border-radius: var(--radius-full);
}
.tab.is-active .tab__count { background: var(--color-primary); color: #fff; }

/* ---------- Tooltip ---------- */

.tooltip {
  position: relative;
  display: inline-block;
}
.tooltip__bubble {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  min-width: max-content;
  max-width: 240px;
  padding: 0.5rem 0.75rem;
  background: var(--color-gray-900);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.4;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration-base) var(--ease);
  white-space: normal;
  z-index: 10;
}
.tooltip__bubble::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 4px solid transparent;
  border-top-color: var(--color-gray-900);
}
.tooltip:hover .tooltip__bubble,
.tooltip:focus-within .tooltip__bubble { opacity: 1; }

/* ---------- Empty state ---------- */

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-12) var(--space-6);
  text-align: center;
  color: var(--color-text-secondary);
}
.empty__icon {
  width: 56px;
  height: 56px;
  display: grid;
  place-items: center;
  background: var(--color-gray-100);
  color: var(--color-gray-400);
  border-radius: var(--radius-full);
}
.empty__title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-text);
  margin: 0;
}
.empty__body { font-size: 0.875rem; max-width: 40ch; margin: 0; }

/* ---------- Circular progress (allowance widget) ---------- */

.progress-circle {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 96px;
  height: 96px;
}
.progress-circle svg { transform: rotate(-90deg); }
.progress-circle__track  { stroke: var(--color-gray-100); }
.progress-circle__fill   { stroke: var(--color-primary); transition: stroke-dashoffset var(--duration-slow) var(--ease); stroke-linecap: round; }
.progress-circle--success .progress-circle__fill { stroke: var(--color-success); }
.progress-circle--warning .progress-circle__fill { stroke: var(--color-warning); }
.progress-circle__label {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.progress-circle__value { font-size: 1.25rem; font-weight: 700; color: var(--color-text); font-variant-numeric: tabular-nums; }
.progress-circle__caption { font-size: 0.65rem; font-weight: 600; letter-spacing: 0.5px; text-transform: uppercase; color: var(--color-text-tertiary); }

/* ---------- Dropzone (file upload) ---------- */

.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: var(--space-12) var(--space-6);
  background: var(--color-surface);
  border: 2px dashed var(--color-gray-300);
  border-radius: var(--radius-lg);
  color: var(--color-text-secondary);
  text-align: center;
  transition: border-color var(--duration-base) var(--ease), background var(--duration-base) var(--ease);
}
.dropzone:hover,
.dropzone.is-active { border-color: var(--color-primary); background: var(--color-brand-50); color: var(--color-text); }
.dropzone__title { font-size: 1rem; font-weight: 600; color: var(--color-text); margin: 0; }
.dropzone__body  { font-size: 0.8125rem; margin: 0; }

/* ---------- List view (toolbar, view toggle, pagination) ----------
   The standard pattern for any CRUD list: search/filter row at top,
   the data in either table or card form, and a pagination footer.
   The same toolbar serves both views so switching never disorients. */

.list {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  overflow: hidden;
}

.list-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--color-border-subtle);
  background: var(--color-surface);
}
/* On screens with room (≥768px) the toolbar should never wrap — the
   `+ New X` button must stay on the same row as the search field. Below
   that breakpoint we fall back to wrap so the buttons don't get cropped. */
@media (min-width: 768px) {
  .list-toolbar { flex-wrap: nowrap; }
}
.list-toolbar__search {
  position: relative;
  flex: 1 1 240px;
  min-width: 0;
  max-width: 360px;
}
.list-toolbar__search .input { padding-left: 2.25rem; }
.list-toolbar__search svg {
  position: absolute; left: 0.75rem; top: 50%;
  transform: translateY(-50%);
  width: 16px; height: 16px;
  color: var(--color-text-tertiary);
}
.list-toolbar__spacer { flex: 1 1 0; }

/* Primary "+ New X" action inside a list toolbar. `margin-left: auto`
   makes it sit at the right edge whether the toolbar fits on one row
   (the spacer already absorbs slack on the left of it) or wraps to a
   second row (the auto margin pushes the lone button to the right edge
   instead of leaving it left-aligned). */
.list-toolbar > a.btn-primary,
.list-toolbar > button.btn-primary {
  margin-left: auto;
  flex-shrink: 0;
  white-space: nowrap;
}

/* Row-link — turn an identity cell (name, title, email) into an inline link
   that leads to the row's edit / detail page without competing visually
   with the Action column buttons on the right. */
.row-link {
  color: inherit;
  text-decoration: none;
  display: inline-block;
}
.row-link:hover { color: var(--color-primary); }
.row-link:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Sortable column header — used inside <th>. The chevron switches between
   asc / desc / unsorted; styling lives in the page template so the icon
   stays trivially overridable per column. */
.th-sort {
  display: inline-flex; align-items: center; gap: 0.375rem;
  color: inherit; text-decoration: none;
}
.th-sort--right { flex-direction: row-reverse; }
.th-sort:hover { color: var(--color-primary); }
/* aria-sort lives on the columnheader (<th>); style the inner link from it. */
.th-sort[aria-sort="asc"], .th-sort[aria-sort="desc"],
[aria-sort="asc"] .th-sort, [aria-sort="desc"] .th-sort {
  color: var(--color-text); font-weight: 600;
}

/* Filter popover wrapper — anchors a .filter-panel under its trigger
   button inside a .list-toolbar. The panel itself uses the existing
   .filter-panel recipe; this wrapper only handles positioning. */
.filter-popover-wrap { position: relative; display: inline-block; }
.filter-popover-wrap .filter-panel {
  position: absolute; top: calc(100% + 0.5rem); left: 0; z-index: 30;
}
.filter-popover-wrap[hidden] { display: none; }
.filter-toggle[aria-expanded="true"] {
  background: var(--color-gray-100); color: var(--color-text);
}
.filter-toggle__badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 0.3rem;
  font-size: 0.65rem; font-weight: 700;
  background: var(--color-primary); color: #fff;
  border-radius: var(--radius-full);
  margin-left: 0.25rem;
}

/* Row overflow menu — anchors a .menu panel under a .meatball trigger in a
   table row or card footer. The panel uses the existing .menu recipe; this
   wrapper only handles positioning. Open/close is wired by admin.js via the
   data-menu-wrap / data-menu-toggle / data-menu-panel hooks. */
.row-menu-wrap { position: relative; display: inline-block; }
.row-menu-wrap .menu {
  position: absolute; top: calc(100% + 0.25rem); right: 0; z-index: 30;
  min-width: 180px;
}
.menu a.menu__item { text-decoration: none; }
.menu a.menu__item:hover { color: var(--color-gray-900); }
.menu__item svg { width: 14px; height: 14px; flex: none; opacity: 0.7; }

/* Filter chip — for active filters that the user has applied. */
.filter-chip {
  display: inline-flex; align-items: center; gap: 0.375rem;
  height: 28px;
  padding: 0 0.625rem;
  font-size: 0.75rem;
  font-weight: 500;
  background: var(--color-gray-100);
  color: var(--color-gray-700);
  border-radius: var(--radius-full);
}
.filter-chip button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px;
  background: transparent; border: 0;
  color: var(--color-gray-500); cursor: pointer;
  border-radius: var(--radius-full);
}
.filter-chip button:hover { background: rgba(0,0,0,0.08); color: var(--color-gray-900); }

/* View toggle — segmented control for table ↔ cards.
   Height locked to match .btn--sm (32px) so it lines up with
   neighbouring toolbar buttons (Filter, New day) without tweaks. */
.view-toggle {
  display: inline-flex;
  height: 32px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-surface);
}
.view-toggle__btn {
  display: inline-flex; align-items: center; gap: 0.375rem;
  height: 100%;
  padding: 0 0.75rem;
  font-size: 0.8rem;
  font-weight: 500;
  line-height: 1;
  color: var(--color-text-secondary);
  background: transparent;
  border: 0;
  cursor: pointer;
  transition: background-color var(--duration-base) var(--ease), color var(--duration-base) var(--ease);
}
.view-toggle__btn + .view-toggle__btn { border-left: 1px solid var(--color-border); }
.view-toggle__btn:hover { color: var(--color-text); background: var(--color-gray-50); }
.view-toggle__btn.is-active { background: var(--color-gray-900); color: #fff; }
.view-toggle__btn.is-active:hover { background: var(--color-gray-800); }
.view-toggle__btn svg { width: 14px; height: 14px; }

/* Pagination footer */
.list-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  padding: 0.875rem 1.25rem;
  border-top: 1px solid var(--color-border-subtle);
  background: var(--color-gray-50);
  font-size: 0.8125rem;
  color: var(--color-text-secondary);
}
.list-footer__range { margin-right: auto; }
.list-footer__range strong { color: var(--color-text); font-weight: 600; }

.pagination { display: inline-flex; align-items: center; gap: 0.125rem; }
.page-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 32px; height: 32px;
  padding: 0 0.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--color-text-secondary);
  background: transparent;
  border: 0;
  border-radius: var(--radius-md);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  transition: background-color var(--duration-base) var(--ease), color var(--duration-base) var(--ease);
}
.page-btn:hover:not(:disabled) { background: var(--color-gray-100); color: var(--color-text); }
.page-btn.is-active {
  background: var(--color-gray-900);
  color: #fff;
}
.page-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.page-ellipsis { padding: 0 0.25rem; color: var(--color-text-tertiary); user-select: none; }

/* Page-size selector (small native select inside the footer). */
.page-size {
  display: inline-flex; align-items: center; gap: 0.375rem;
  font-size: 0.8125rem; color: var(--color-text-secondary);
}
.page-size select {
  height: 30px;
  padding: 0 0.5rem;
  font: inherit; font-size: 0.8125rem;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

/* ---------- Filter panel (popover that opens from list toolbar) ---------- */

.filter-panel {
  width: 320px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.filter-panel__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.875rem 1rem;
  border-bottom: 1px solid var(--color-border-subtle);
  font-size: 0.8125rem; font-weight: 600;
  color: var(--color-text);
}
.filter-panel__body {
  max-height: 360px; overflow-y: auto;
  padding: 0.75rem 0;
}
.filter-panel__group {
  padding: 0.5rem 1rem 0.75rem;
  border-bottom: 1px solid var(--color-border-subtle);
}
.filter-panel__group:last-child { border-bottom: 0; }
.filter-panel__label {
  display: block;
  font-size: 0.65rem; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--color-text-tertiary);
  margin-bottom: 0.5rem;
}
.filter-panel__option {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.3125rem 0;
  font-size: 0.875rem; color: var(--color-text);
  cursor: pointer;
}
.filter-panel__option input[type="checkbox"] { accent-color: var(--color-primary); }
.filter-panel__option .count {
  margin-left: auto;
  font-size: 0.7rem; color: var(--color-text-tertiary); font-variant-numeric: tabular-nums;
}
.filter-panel__foot {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
  padding: 0.75rem 1rem;
  border-top: 1px solid var(--color-border-subtle);
  background: var(--color-gray-50);
}

/* ---------- Categorical tags & dots ----------
   Non-action identity colours — productions, owners, day units, chart series.
   Use the `.cat-{hue}` modifier on a `.cat-tag` or `.cat-dot`. */

.cat-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  height: 22px;
  padding: 0 0.625rem;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.2px;
  border-radius: var(--radius-full);
  background: var(--color-gray-100);
  color: var(--color-gray-700);
}
.cat-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: var(--radius-full);
  background: var(--color-gray-400);
  flex-shrink: 0;
}

.cat-tag.cat-indigo { background: var(--color-cat-indigo-100); color: var(--color-cat-indigo-700); }
.cat-tag.cat-teal   { background: var(--color-cat-teal-100);   color: var(--color-cat-teal-700);   }
.cat-tag.cat-amber  { background: var(--color-cat-amber-100);  color: var(--color-cat-amber-700);  }
.cat-tag.cat-violet { background: var(--color-cat-violet-100); color: var(--color-cat-violet-700); }
.cat-tag.cat-pink   { background: var(--color-cat-pink-100);   color: var(--color-cat-pink-700);   }
.cat-tag.cat-slate  { background: var(--color-cat-slate-100);  color: var(--color-cat-slate-700);  }

.cat-dot.cat-indigo { background: var(--color-cat-indigo-500); }
.cat-dot.cat-teal   { background: var(--color-cat-teal-500);   }
.cat-dot.cat-amber  { background: var(--color-cat-amber-500);  }
.cat-dot.cat-violet { background: var(--color-cat-violet-500); }
.cat-dot.cat-pink   { background: var(--color-cat-pink-500);   }
.cat-dot.cat-slate  { background: var(--color-cat-slate-500);  }

/* ---------- Colour-coded row action icon buttons ----------
   Compact, solid-colour icon buttons for dense table-row action toolbars
   (admin production days / access). Colour-coding + icon makes each action
   scannable at a glance where a stack of same-colour buttons overflowed and
   read as undifferentiated. Icon-only, so the label lives in `aria-label` +
   `title` (required on every instance for a11y + hover tooltip).
   NOTE: this intentionally uses the categorical hues on ACTION controls — a
   product-owner-requested exception to the usual "categorical = non-action
   only" rule; destructive stays brand-red. */
.act-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex: 0 0 auto;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  color: #fff;
  cursor: pointer;
  box-shadow: none;
  transition: filter var(--duration-base) var(--ease),
              box-shadow var(--duration-base) var(--ease);
}
.act-icon svg { width: 16px; height: 16px; }
.act-icon:hover:not(:disabled) { filter: brightness(1.08); }
.act-icon:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.act-icon:disabled { opacity: 0.5; cursor: not-allowed; }

.act-icon--indigo { background: var(--color-cat-indigo-500); }
.act-icon--teal   { background: var(--color-cat-teal-500);   }
.act-icon--amber  { background: var(--color-cat-amber-500);  }
.act-icon--violet { background: var(--color-cat-violet-500); }
.act-icon--pink   { background: var(--color-cat-pink-500);   }
.act-icon--slate  { background: var(--color-cat-slate-500);  }
.act-icon--danger { background: var(--color-error); }

/* Tidy inline toolbar wrapper for the action cell. */
.act-toolbar { display: inline-flex; align-items: center; gap: 6px; }

/* ---------- Side nav ----------
   Persistent left sidebar for desktop layouts. Two states:
   .side-nav (expanded ~240px) and .side-nav.is-collapsed (~64px, icons only).
   The collapsed state still shows tooltips on hover for each item. */

.side-nav {
  display: flex;
  flex-direction: column;
  width: 240px;
  height: 100%;
  background: var(--color-surface);
  border-right: 1px solid var(--color-border);
  transition: width var(--duration-base) var(--ease);
}
.side-nav.is-collapsed { width: 64px; }
.side-nav__head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  height: 56px;
  padding: 0 0.75rem;
  border-bottom: 1px solid var(--color-border-subtle);
}
.side-nav__head .label { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-text-tertiary); }
.side-nav.is-collapsed .side-nav__head .label,
.side-nav.is-collapsed .side-nav__group,
.side-nav.is-collapsed .side-nav__item .label { display: none; }

.side-nav__body { flex: 1; overflow-y: auto; padding: 0.5rem 0.5rem; }
.side-nav__group {
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-text-tertiary);
  padding: 0.75rem 0.625rem 0.375rem;
}
.side-nav__item {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.5rem 0.625rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-gray-700);
  text-decoration: none;
  border-radius: var(--radius-md);
  transition: background var(--duration-base) var(--ease), color var(--duration-base) var(--ease);
}
.side-nav__item:hover { background: var(--color-gray-50); color: var(--color-gray-900); text-decoration: none; }
.side-nav__item.is-active { background: var(--color-brand-50); color: var(--color-primary); font-weight: 600; }
.side-nav__item.is-active svg { color: var(--color-primary); }
.side-nav__item svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--color-gray-500); }
.side-nav.is-collapsed .side-nav__item { justify-content: center; padding: 0.5rem; }
.side-nav__item .count {
  margin-left: auto;
  font-size: 0.7rem; font-variant-numeric: tabular-nums;
  background: var(--color-gray-100); color: var(--color-text-secondary);
  padding: 0 0.375rem; height: 18px;
  border-radius: var(--radius-full);
  display: inline-flex; align-items: center;
}
.side-nav__item.is-active .count { background: var(--color-primary); color: #fff; }
.side-nav.is-collapsed .side-nav__item .count { display: none; }

.side-nav__foot {
  padding: 0.5rem;
  border-top: 1px solid var(--color-border-subtle);
}

/* ---------- Breadcrumbs ---------- */

.crumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.25rem;
  font-size: 0.8125rem;
  color: var(--color-text-secondary);
  margin: 0;
  padding: 0;
  list-style: none;
}
.crumbs a {
  color: var(--color-text-secondary);
  padding: 0.125rem 0.375rem;
  border-radius: var(--radius-sm);
  text-decoration: none;
  transition: background var(--duration-base) var(--ease), color var(--duration-base) var(--ease);
}
.crumbs a:hover { background: var(--color-gray-100); color: var(--color-text); text-decoration: none; }
.crumbs__sep { color: var(--color-gray-300); user-select: none; display: inline-flex; align-items: center; }
.crumbs__here { padding: 0.125rem 0.375rem; color: var(--color-text); font-weight: 600; max-width: 32ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.crumbs__home {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  border-radius: var(--radius-sm);
  color: var(--color-text-tertiary);
}
.crumbs__home:hover { background: var(--color-gray-100); color: var(--color-text); }

/* ---------- Avatar ---------- */

.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--color-gray-900);
  color: #fff;
  font-weight: 600;
  letter-spacing: 0.02em;
  border-radius: var(--radius-full);
  text-transform: uppercase;
  flex-shrink: 0;
  overflow: hidden;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar--xs { width: 24px; height: 24px; font-size: 0.625rem; }
.avatar--sm { width: 32px; height: 32px; font-size: 0.75rem; }
.avatar--md { width: 40px; height: 40px; font-size: 0.875rem; }
.avatar--lg { width: 56px; height: 56px; font-size: 1.125rem; }

.avatar-stack { display: inline-flex; }
.avatar-stack > .avatar + .avatar { margin-left: -8px; box-shadow: 0 0 0 2px var(--color-surface); }
.avatar-stack > .avatar--sm + .avatar--sm { margin-left: -10px; }

.identity {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}
.identity__meta { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.identity__name { font-size: 0.875rem; font-weight: 600; color: var(--color-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.identity__sub  { font-size: 0.7rem; color: var(--color-text-tertiary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- Toast ----------
   Transient, time-bound feedback. Distinct from inline .alert which lives
   inline with content. Toasts stack in a corner and dismiss automatically. */

.toast-stack {
  position: fixed;
  z-index: 70;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 1rem;
  max-width: 24rem;
}
.toast-stack--br { bottom: 0; right: 0; }
.toast-stack--tr { top: 0; right: 0; }
.toast-stack--bl { bottom: 0; left: 0; }
.toast-stack--tl { top: 0; left: 0; }

.toast {
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  padding: 0.75rem 0.875rem;
  background: var(--color-gray-900);
  color: #fff;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  font-size: 0.8125rem;
  line-height: 1.4;
}
.toast__icon {
  flex-shrink: 0;
  width: 20px; height: 20px;
  display: grid; place-items: center;
  color: #fff;
}
.toast__body { flex: 1; min-width: 0; }
.toast__title { font-weight: 600; margin: 0 0 0.125rem; }
.toast__msg { margin: 0; color: rgba(255,255,255,0.78); }
.toast__close {
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px;
  background: transparent; border: 0;
  color: rgba(255,255,255,0.6); cursor: pointer;
  border-radius: var(--radius-sm);
}
.toast__close:hover { color: #fff; background: rgba(255,255,255,0.1); }

.toast--success .toast__icon { color: #6EE7B7; }
.toast--warning .toast__icon { color: #FCD34D; }
.toast--error   .toast__icon { color: #FCA5A5; }
.toast--info    .toast__icon { color: #93C5FD; }

/* ---------- Prose container ----------
   For long-form page text: T&Cs, release notes, help articles, request-access
   explanations, anything where the user is reading paragraphs. Caps line
   length, gives headings/lists/inline elements a consistent voice without
   the author having to style each tag. */

.prose {
  max-width: 64ch;
  color: var(--color-text);
  font-size: 1rem;
  line-height: 1.65;
}
.prose > * + * { margin-top: 1rem; }
.prose h2 {
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.25;
  margin-top: 2.5rem;
  color: var(--color-text);
}
.prose h3 {
  font-size: 1.125rem;
  font-weight: 700;
  line-height: 1.3;
  margin-top: 1.75rem;
  color: var(--color-text);
}
.prose h2:first-child,
.prose h3:first-child { margin-top: 0; }
.prose p { margin: 0; color: var(--color-gray-700); }
.prose strong { color: var(--color-text); font-weight: 600; }
.prose a {
  color: var(--color-primary);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.prose a:hover { color: var(--color-primary-dark); }
.prose ul, .prose ol { padding-left: 1.25rem; color: var(--color-gray-700); }
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }
.prose li + li { margin-top: 0.375rem; }
.prose li::marker { color: var(--color-text-tertiary); }
.prose code {
  font-family: var(--font-mono);
  font-size: 0.85em;
  padding: 0.125rem 0.375rem;
  background: var(--color-gray-100);
  border-radius: var(--radius-sm);
  color: var(--color-text);
}
.prose blockquote {
  margin: 1.25rem 0;
  padding: 0.25rem 0 0.25rem 1rem;
  border-left: 3px solid var(--color-primary);
  color: var(--color-gray-700);
  font-style: italic;
}
.prose hr {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: 2rem 0;
}
.prose__lead {
  font-size: 1.125rem;
  line-height: 1.55;
  color: var(--color-gray-700);
}

.content-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: 2rem 2.25rem;
}
@media (min-width: 768px) { .content-card { padding: 2.5rem 3rem; } }

/* ---------- Accordion ----------
   Built on native <details>/<summary> for keyboard + screen-reader support
   out of the box. The chevron rotates via [open] selector — no JS required. */

.accordion {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  background: var(--color-surface);
  overflow: hidden;
}
.accordion__item + .accordion__item { border-top: 1px solid var(--color-border-subtle); }
.accordion__item { position: relative; }
.accordion__summary {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem 1.25rem;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--color-text);
  cursor: pointer;
  list-style: none;
  user-select: none;
  transition: background var(--duration-base) var(--ease);
}
.accordion__summary::-webkit-details-marker { display: none; }
.accordion__summary:hover { background: var(--color-gray-50); }
.accordion__summary::after {
  content: "";
  margin-left: auto;
  width: 16px;
  height: 16px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  transition: transform var(--duration-base) var(--ease);
}
.accordion__item[open] > .accordion__summary::after { transform: rotate(180deg); }
.accordion__item[open] > .accordion__summary { background: var(--color-gray-50); color: var(--color-text); }
.accordion__body {
  padding: 0 1.25rem 1.25rem;
  color: var(--color-gray-700);
  font-size: 0.875rem;
  line-height: 1.6;
}
.accordion__body > p { margin: 0; }
.accordion__body > * + * { margin-top: 0.75rem; }

/* Leading icon variant — for FAQ-style accordions where each item has its
   own glyph. Use inside the summary; size matches the chevron. */
.accordion__summary .lead-icon {
  display: inline-grid; place-items: center;
  width: 28px; height: 28px;
  background: var(--color-brand-50);
  color: var(--color-primary);
  border-radius: var(--radius-md);
  flex-shrink: 0;
}

/* ---------- Content card with side aside ----------
   Variant of .content-card with an optional supporting right column —
   table of contents, callouts, metadata, related links. The aside is
   sticky on desktop so it stays in view as the main article scrolls.
   Stacks below the main column under 900 px. */

.content-card--with-aside {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 240px;
  gap: 3rem;
  padding: 2rem 2.25rem;
}
@media (min-width: 768px) {
  .content-card--with-aside { padding: 2.5rem 3rem; }
}
@media (max-width: 900px) {
  .content-card--with-aside { grid-template-columns: 1fr; gap: 2rem; }
}

.content-aside {
  position: sticky;
  /* Clear app header + sticky section nav (64 + 52 + slack). */
  top: calc(64px + 52px + 24px);
  align-self: start;
  font-size: 0.8125rem;
}
@media (max-width: 900px) {
  .content-aside { position: static; }
}

.content-aside__group + .content-aside__group { margin-top: 1.5rem; }
.content-aside__label {
  display: block;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-primary);
  margin-bottom: 0.5rem;
}
.content-aside__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  border-left: 1px solid var(--color-border);
}
.content-aside__list a {
  display: block;
  padding: 0.25rem 0 0.25rem 0.75rem;
  margin-left: -1px;
  color: var(--color-text-secondary);
  text-decoration: none;
  border-left: 1px solid transparent;
  font-size: 0.8125rem;
  transition: color var(--duration-base) var(--ease), border-color var(--duration-base) var(--ease);
}
.content-aside__list a:hover { color: var(--color-text); }
.content-aside__list a.is-active {
  color: var(--color-primary);
  border-left-color: var(--color-primary);
  font-weight: 600;
}

.content-aside__callout {
  padding: 0.875rem 1rem;
  background: var(--color-brand-50);
  border-left: 3px solid var(--color-primary);
  border-radius: var(--radius-md);
  color: var(--color-gray-700);
  font-size: 0.8125rem;
  line-height: 1.5;
}
.content-aside__callout strong { color: var(--color-text); }

.content-aside__meta {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  font-size: 0.75rem;
  color: var(--color-text-tertiary);
}
.content-aside__meta dt { font-weight: 600; color: var(--color-text); margin-bottom: 0.125rem; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.5px; }
.content-aside__meta dd { margin: 0; }

/* ============================================================
   Gallery island — image viewer recipes
   ============================================================ */

/* Layout shell that hosts the React-mounted island below the admin
   sidenav. The toolbar + body split mirrors a standard inbox-style
   reading surface: sticky header, scrollable body, left filter rail.
*/
.gallery-island {
  display: flex;
  flex-direction: column;
  /* The island fills the remaining height of its flex-parent (the admin
     main column). 100% is the parent's flex-basis; min-height: 0 lets
     internal scrollers (grid + filter rail) own their own overflow. */
  height: 100%;
  min-height: 0;
  background: var(--color-surface-muted, #fafafa);
}
.gallery-island__body {
  display: flex;
  flex: 1;
  min-height: 0;
  align-items: stretch;
}
.gallery-island__main {
  flex: 1;
  min-width: 0;
  overflow-y: auto;
  padding: var(--space-5) var(--space-6);
}

.gallery-toolbar {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  padding: var(--space-4) var(--space-6) var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.gallery-toolbar__title {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.gallery-toolbar__title-actions { display: flex; gap: var(--space-2); }
.gallery-toolbar__eyebrow {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--color-primary);
  margin: 0 0 0.125rem;
}
.gallery-toolbar__heading {
  font-size: 1.5rem;
  font-weight: 700;
  margin: 0;
  letter-spacing: -0.01em;
}
.gallery-toolbar__controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}
.gallery-toolbar__count {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: 0.8125rem;
  color: var(--color-text-secondary);
}
.gallery-toolbar__count strong {
  color: var(--color-text);
  font-size: 1rem;
  margin-right: 0.25rem;
}
.gallery-toolbar__count-meta { color: var(--color-text-tertiary); margin-left: 0.25rem; }
.gallery-toolbar__group {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8125rem;
}
.gallery-toolbar__field-label {
  font-weight: 500;
  color: var(--color-text-secondary);
}
.gallery-toolbar__pager { display: inline-flex; gap: 0.25rem; }
.gallery-toolbar__spacer { flex: 1; }

/* Inline select inside the toolbar — narrower than the page-form variant. */
.field__select--inline {
  height: 32px;
  padding: 0 1.75rem 0 0.5rem;
  font-size: 0.8125rem;
}

/* ---------- Filter panel (gallery variant) ---------- */

.filter-panel--gallery {
  flex-shrink: 0;
  width: 260px;
  border-right: 1px solid var(--color-border);
  background: var(--color-surface);
  overflow-y: auto;
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.filter-panel__group {
  margin: 0;
  padding: 0;
  border: 0;
}
.filter-panel__label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--color-text-secondary);
  margin: 0 0 0.5rem;
}
.filter-panel__clear {
  background: none;
  border: 0;
  font: inherit;
  color: var(--color-primary);
  cursor: pointer;
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.7rem;
}
.filter-panel__hint {
  font-size: 0.75rem;
  color: var(--color-text-tertiary);
  margin: 0;
}
.filter-panel__day-list {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  max-height: 220px;
  overflow-y: auto;
}
.filter-panel__check {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8125rem;
  cursor: pointer;
  padding: 0.125rem 0;
}
.filter-panel__day-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.filter-panel__day-count {
  font-variant-numeric: tabular-nums;
  color: var(--color-text-tertiary);
  font-size: 0.75rem;
}
.filter-panel__pills {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.filter-panel__pill {
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.625rem;
  border-radius: 999px;
  font-size: 0.75rem;
  background: var(--color-gray-100);
  color: var(--color-text-secondary);
  cursor: pointer;
  border: 1px solid transparent;
  transition: background var(--duration-base) var(--ease),
              color var(--duration-base) var(--ease);
}
.filter-panel__pill input { position: absolute; opacity: 0; pointer-events: none; }
.filter-panel__pill.is-active {
  background: var(--color-primary);
  color: #fff;
  border-color: var(--color-primary-dark);
}
.filter-panel__tag-input {
  display: flex;
  gap: 0.25rem;
  margin-bottom: 0.5rem;
}
.filter-panel__tag-chips {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

/* ---------- Image grid + cards ---------- */

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--thumb-size, 200px), 1fr));
  gap: var(--space-3);
}
.gallery-grid__skeleton {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--thumb-size, 200px), 1fr));
  gap: var(--space-3);
}

.image-grid-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: box-shadow var(--duration-base) var(--ease),
              border-color var(--duration-base) var(--ease),
              transform var(--duration-base) var(--ease);
}
.image-grid-card:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--color-gray-300);
}
.image-grid-card.is-selected {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 2px rgba(192, 0, 0, 0.15);
}
.image-grid-card.is-removed { opacity: 0.55; }
.image-grid-card.is-removed .image-grid-card__thumb img {
  filter: grayscale(0.8);
}
.image-grid-card--skeleton {
  background: linear-gradient(
    90deg,
    var(--color-gray-100) 0%,
    var(--color-gray-200) 50%,
    var(--color-gray-100) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
  height: var(--thumb-size, 200px);
}
@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.image-grid-card__thumb {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  background: var(--color-gray-100);
  border: 0;
  padding: 0;
  cursor: zoom-in;
  overflow: hidden;
}
.image-grid-card__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--duration-base) var(--ease);
}
.image-grid-card:hover .image-grid-card__thumb img { transform: scale(1.03); }
.image-grid-card__missing {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--color-text-tertiary);
  font-size: 0.75rem;
}
.image-grid-card__check {
  position: absolute;
  top: 0.375rem;
  left: 0.375rem;
  background: rgba(255, 255, 255, 0.92);
  border-radius: 4px;
  padding: 0.125rem;
  z-index: 2;
  cursor: pointer;
  line-height: 0;
}
.image-grid-card__check input { width: 14px; height: 14px; cursor: pointer; }
.image-grid-card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 0.625rem;
  gap: 0.5rem;
  border-top: 1px solid var(--color-border);
  font-size: 0.75rem;
}
.image-grid-card__name {
  flex: 1;
  min-width: 0;
  font-weight: 500;
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.image-grid-card__day { color: var(--color-text-tertiary); font-size: 0.7rem; }

/* Thumbnail overlay — small status dots that ride the bottom-right of the
   thumbnail. Stacked horizontally and clipped against the thumbnail edge so
   they read as part of the image rather than the card chrome. */
.thumbnail-overlay {
  position: absolute;
  right: 0.375rem;
  bottom: 0.375rem;
  display: inline-flex;
  gap: 0.25rem;
  pointer-events: none;
}
.thumbnail-overlay__dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 0.25rem;
  border-radius: 6px;
  font-size: 0.625rem;
  font-weight: 700;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}
.thumbnail-overlay__dot--selected { background: var(--color-primary); }
.thumbnail-overlay__dot--removed { background: var(--color-gray-700); }
.thumbnail-overlay__dot--caption { background: var(--cat-teal, #0d9488); }
.thumbnail-overlay__dot--tag { background: var(--cat-indigo, #4f46e5); }
.thumbnail-overlay__dot--kill { background: #7c2d12; }

/* ---------- Bulk toolbar ---------- */

.bulk-toolbar {
  position: fixed;
  bottom: var(--space-5);
  left: 50%;
  transform: translateX(-50%);
  background: var(--color-gray-900);
  color: #fff;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 0.5rem 0.75rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  z-index: 40;
  animation: bulk-rise var(--duration-base) var(--ease);
}
@keyframes bulk-rise {
  from { transform: translate(-50%, 20px); opacity: 0; }
  to   { transform: translate(-50%, 0);     opacity: 1; }
}
.bulk-toolbar__count {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8125rem;
  padding-right: 0.5rem;
  border-right: 1px solid rgba(255, 255, 255, 0.16);
}
.bulk-toolbar__count strong { font-size: 0.95rem; }
.bulk-toolbar__count .btn-ghost {
  color: var(--color-gray-300);
}
.bulk-toolbar__count .btn-ghost:hover {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}
.bulk-toolbar__actions { display: flex; gap: 0.25rem; }
.bulk-toolbar__actions .btn { background: rgba(255, 255, 255, 0.08); color: #fff; border-color: transparent; }
.bulk-toolbar__actions .btn:hover:not(:disabled) { background: rgba(255, 255, 255, 0.16); }
.bulk-toolbar__actions .btn-ghost { background: transparent; }

/* ---------- Lightbox ---------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(15, 23, 42, 0.94);
  color: #f1f5f9;
  display: flex;
  flex-direction: column;
}
.lightbox__top {
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 0 var(--space-4);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.lightbox__top-left {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}
.lightbox__icon-btn {
  width: 32px; height: 32px;
  background: rgba(255, 255, 255, 0.05);
  color: #fff;
  border: 0;
  border-radius: 6px;
  font-size: 1.25rem;
  cursor: pointer;
}
.lightbox__icon-btn:hover { background: rgba(255, 255, 255, 0.12); }
.lightbox__name {
  font-weight: 600;
  font-size: 0.95rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lightbox__name-meta { color: rgba(255, 255, 255, 0.6); margin-left: 0.5rem; font-weight: 400; }
.lightbox__top-actions { display: inline-flex; gap: 0.25rem; }
.lightbox__top-actions .btn,
.lightbox__top-actions .btn-ghost {
  background: rgba(255, 255, 255, 0.05);
  color: #fff;
  border-color: transparent;
}
.lightbox__top-actions .btn:hover:not(:disabled) { background: rgba(255, 255, 255, 0.12); }

.lightbox__body {
  flex: 1;
  display: flex;
  min-height: 0;
}
.lightbox__stage {
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: var(--space-4);
}
.lightbox__img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  user-select: none;
  cursor: zoom-in;
}
.lightbox__img.is-zoomed {
  cursor: zoom-out;
  max-width: none;
  max-height: none;
  transform: scale(1.8);
}
.lightbox__placeholder {
  color: rgba(255, 255, 255, 0.6);
  font-size: 0.95rem;
}
.lightbox__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
  border: 0;
  font-size: 1.75rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox__nav:hover { background: rgba(255, 255, 255, 0.18); }
.lightbox__nav--prev { left: var(--space-4); }
.lightbox__nav--next { right: var(--space-4); }

.lightbox__drawer {
  width: 360px;
  background: #0f172a;
  border-left: 1px solid rgba(255, 255, 255, 0.08);
  overflow-y: auto;
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.lightbox__section { display: flex; flex-direction: column; gap: 0.5rem; }
.lightbox__section-title {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.7);
  margin: 0;
}
.lightbox__section .field__input {
  background: rgba(255, 255, 255, 0.06);
  color: #f1f5f9;
  border-color: rgba(255, 255, 255, 0.1);
}
.lightbox__section .field__input::placeholder { color: rgba(255, 255, 255, 0.45); }
.lightbox__section-actions { display: flex; gap: 0.25rem; }
.lightbox__tag-input { display: flex; gap: 0.25rem; }
.lightbox__tag-chips {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.lightbox__hint { color: rgba(255, 255, 255, 0.5); font-size: 0.8125rem; }
.lightbox__meta {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.25rem 0.75rem;
  font-size: 0.8125rem;
  margin: 0;
}
.lightbox__meta dt { color: rgba(255, 255, 255, 0.55); font-weight: 500; }
.lightbox__meta dd { margin: 0; color: #f1f5f9; }
.lightbox__viewers {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  font-size: 0.8125rem;
}
.lightbox__viewer-meta { color: rgba(255, 255, 255, 0.55); margin-left: 0.25rem; }
.lightbox__viewer--killed strong { color: #fca5a5; }
.lightbox__outstanding summary {
  cursor: pointer;
  font-size: 0.8125rem;
  color: rgba(255, 255, 255, 0.7);
  margin-top: 0.5rem;
}
.lightbox__outstanding ul {
  list-style: none;
  padding: 0.5rem 0 0;
  margin: 0;
  font-size: 0.8125rem;
  color: rgba(255, 255, 255, 0.85);
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

/* ---------- Keyboard shortcut chips ---------- */

.kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5rem;
  height: 1.5rem;
  padding: 0 0.375rem;
  background: var(--color-gray-100);
  border: 1px solid var(--color-border);
  border-bottom-width: 2px;
  border-radius: 4px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.75rem;
  color: var(--color-text);
}
.kbd-help-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}
.kbd-help-table th {
  text-align: left;
  padding: 0.5rem 0;
  font-weight: 500;
  width: 1%;
  white-space: nowrap;
}
.kbd-help-table td {
  padding: 0.5rem 0 0.5rem 1rem;
  color: var(--color-text-secondary);
}
.kbd-help-sep { display: inline-block; margin: 0 0.25rem; color: var(--color-text-tertiary); }

/* Small inline-dismiss button paired with the existing .cat-tag chip. The
   chip body itself is defined upstream (cat-indigo / cat-teal / etc.) —
   we only add the close-button affordance for the gallery filter chips. */
.cat-tag__remove {
  background: transparent;
  border: 0;
  color: inherit;
  cursor: pointer;
  font-size: 0.85rem;
  line-height: 1;
  padding: 0 0 0 0.125rem;
  margin-left: 0.125rem;
  opacity: 0.7;
}
.cat-tag__remove:hover { opacity: 1; }

/* Toast entrance animation — the recipe body itself is defined upstream
   (.toast / .toast-stack at the design-language top) which uses dark
   gray-900 with white text. We reuse it from the React island so the
   visual contract is single-sourced. */
@keyframes toast-in {
  from { transform: translateY(-8px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}
.toast-stack--gallery .toast { animation: toast-in var(--duration-base) var(--ease); }

/* Small generic spinner used by the toolbar count + lightbox stage. */
.spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spinner-rot 0.8s linear infinite;
}
@keyframes spinner-rot {
  to { transform: rotate(360deg); }
}

/* ---------- Modal — large variant (gallery upload) ---------- */
.modal--lg { max-width: 720px; width: calc(100vw - 4rem); }

.upload-modal__body { display: flex; flex-direction: column; gap: var(--space-3); }
.upload-modal__controls {
  display: grid;
  grid-template-columns: minmax(180px, 1fr) minmax(220px, 2fr);
  gap: var(--space-3);
}
.upload-modal__field { display: flex; flex-direction: column; gap: 0.25rem; }
.upload-modal__loading {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  color: var(--color-text-secondary);
}
.upload-modal__dashboard {
  /* Uppy injects its own dashboard chrome here. We just reserve a sensible
     minimum height so the loading state and empty state don't collapse. */
  min-height: 320px;
  border-radius: var(--radius-md);
  overflow: hidden;
}
.upload-modal__hint {
  font-size: 0.75rem;
  color: var(--color-text-tertiary);
  flex: 1;
  margin-right: var(--space-3);
}

/* Per-file upload outcome, inside the summary .alert. A batch can be 200
   files, so the list scrolls rather than pushing the modal footer off
   screen; each row is filename + reason so nothing fails silently. */
.upload-modal__summary-note {
  font-size: 0.75rem;
  margin-top: var(--space-1);
}
.upload-modal__summary-heading {
  font-size: 0.75rem;
  font-weight: 600;
  margin-top: var(--space-2);
}
.upload-modal__summary-list {
  margin: var(--space-1) 0 0;
  padding: 0;
  list-style: none;
  max-height: 10rem;
  overflow-y: auto;
  font-size: 0.75rem;
}
.upload-modal__summary-list li {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 0.25rem 0;
  border-bottom: 1px solid var(--color-border-subtle);
}
.upload-modal__summary-list li:last-child { border-bottom: 0; }
.upload-modal__summary-name {
  font-family: var(--font-mono, ui-monospace, monospace);
  word-break: break-all;
}
.upload-modal__summary-reason {
  color: var(--color-text-secondary);
  text-align: right;
  flex: none;
  max-width: 60%;
}

.upload-modal__empty {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-muted, #fafafa);
}
.upload-modal__empty-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }

/* Modal header variant with an inline icon-only close affordance. The
   default `.modal__header` only carries the title; this variant flexes it
   left and pins the `×` button to the right edge with the standard
   icon-button treatment so any modal can opt in by adding the modifier. */
.modal__header--with-close {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
.modal__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-md);
  color: var(--color-text-tertiary);
  cursor: pointer;
  transition: background-color var(--duration-base) var(--ease),
              color var(--duration-base) var(--ease);
}
.modal__close:hover { background: var(--color-gray-100); color: var(--color-text); }
.modal__close:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Gallery toolbar meatball + menu positioning + counts chip. */
.gallery-toolbar__menu-wrap { position: relative; }
.gallery-toolbar__meatball {
  width: 32px;
  height: 32px;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
}
.gallery-toolbar__menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 30;
  min-width: 280px;
}
.gallery-toolbar__menu-header {
  padding: 0.375rem 0.75rem 0.25rem;
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--color-text-tertiary);
}
.gallery-toolbar__menu .menu__item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
}
.gallery-toolbar__menu .menu__item:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.menu__count {
  font-variant-numeric: tabular-nums;
  font-size: 0.7rem;
  font-weight: 600;
  background: var(--color-gray-100);
  color: var(--color-text-secondary);
  padding: 0.125rem 0.375rem;
  border-radius: 999px;
}
