/* ===== Tokens =====
   Everything a theme can change lives here. Overriding these in the custom CSS
   box restyles the whole UI without touching a single class name. The template
   in themes/template.css lists them all with what they affect. */
:root {
  /* Tells the browser how to paint the bits we do not control: checkboxes,
     dropdown popups, scrollbars. A light theme has to flip this or they stay
     dark against it. */
  color-scheme: var(--color-scheme, dark);
  --color-scheme: dark;

  /* Typography */
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-heading: var(--font-body);
  --font-mono: monospace;

  /* Shape */
  --radius: 12px;
  --radius-sm: 10px;
  --radius-lg: 16px;
  --radius-xs: 8px;
  --radius-pill: 999px;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --nav-blur: 12px;
  --overlay-blur: 4px;

  /* Surfaces */
  --bg: #0a0a0f;
  --surface: rgba(255, 255, 255, 0.03);
  --surface-strong: rgba(255, 255, 255, 0.06);
  --surface-hover: rgba(255, 255, 255, 0.1);
  --surface-subtle: rgba(255, 255, 255, 0.02);
  --surface-nav: rgba(14, 14, 20, 0.85);
  --surface-modal: #101018;
  --surface-toast: #1a1a24;
  --surface-input: rgba(255, 255, 255, 0.04);
  --surface-input-focus: rgba(37, 99, 235, 0.06);
  --surface-option: #14141c;
  --surface-disabled: #1e1e2a;
  --surface-poster: #12121a;
  --surface-code: rgba(0, 0, 0, 0.35);
  --surface-code-inline: rgba(0, 0, 0, 0.3);
  --surface-captcha: #000;
  --overlay-bg: rgba(0, 0, 0, 0.75);

  /* Borders */
  --border: rgba(255, 255, 255, 0.08);
  --border-soft: rgba(255, 255, 255, 0.06);
  --border-hover: rgba(255, 255, 255, 0.18);
  --border-hover-soft: rgba(255, 255, 255, 0.14);

  /* Text */
  --text: #c8cad0;
  --text-strong: #fff;
  --text-bright: #e2e4e9;
  --text-muted: #6b7280;
  --text-dim: #9ca3af;
  --text-faint: #888;
  --text-input: #e0e0e0;
  --text-placeholder: #555;
  --text-disabled: #555;
  --text-on-accent: #fff;
  --link: #6ea8fe;
  --link-hover: #93c5fd;

  /* Accents */
  --accent: #2563eb;
  --accent-dark: #1d4ed8;
  --accent-soft: rgba(37, 99, 235, 0.15);
  --purple: #9333ea;
  --purple-dark: #7c3aed;
  --danger: #ef4444;
  --success: #22c55e;
  --warning: #f59e0b;

  /* Gradients, so a flat theme can drop them in one place */
  --gradient-accent: linear-gradient(135deg, var(--accent), var(--accent-dark));
  --gradient-purple: linear-gradient(135deg, var(--purple), var(--purple-dark));
  --gradient-progress: linear-gradient(90deg, var(--accent), var(--purple));

  /* Shadows */
  --shadow-btn: 0 2px 8px rgba(37, 99, 235, 0.25);
  --shadow-btn-hover: 0 4px 16px rgba(37, 99, 235, 0.35);
  --shadow-ribbon: 0 2px 6px rgba(37, 99, 235, 0.45);
  --shadow-thumb: 0 2px 8px rgba(147, 51, 234, 0.35);
  --shadow-card: 0 12px 32px rgba(0, 0, 0, 0.4);
  --shadow-modal: 0 24px 64px rgba(0, 0, 0, 0.6);
  --shadow-toast: 0 8px 24px rgba(0, 0, 0, 0.5);
  --shadow-drag: 0 8px 20px rgba(0, 0, 0, 0.45);

  /* Danger tints, shared by destructive buttons and error panels */
  --danger-soft: rgba(239, 68, 68, 0.12);
  --danger-tint: rgba(239, 68, 68, 0.14);
  --danger-soft-strong: rgba(239, 68, 68, 0.2);
  --danger-border: rgba(239, 68, 68, 0.3);
  --danger-text: #fca5a5;

  /* Queue status pills */
  --status-queued-bg: rgba(107, 114, 128, 0.2);
  --status-queued-text: #9ca3af;
  --status-running-bg: rgba(37, 99, 235, 0.2);
  --status-running-text: #93c5fd;
  --status-completed-bg: rgba(34, 197, 94, 0.18);
  --status-completed-text: #86efac;
  --status-failed-bg: rgba(239, 68, 68, 0.18);
  --status-failed-text: #fca5a5;
  --status-cancelled-bg: rgba(245, 158, 11, 0.18);
  --status-cancelled-text: #fcd34d;

  /* One pair per site for the site switch. aniworld doubles as the fallback,
     which is what an unknown site gets and what shows before the page has
     finished picking one.

     Give --site-all-bg / --site-all-shadow a value and every site uses it,
     which is how a theme turns per-site colouring off in one line. "initial"
     is how CSS spells "not set" for a custom property: it makes the var()
     below fall through to the per-site token. */
  --site-all-bg: initial;
  --site-all-shadow: initial;
  --site-aniworld-bg: linear-gradient(135deg, #8b5cf6, #6d28d9);
  --site-aniworld-shadow: 0 2px 8px rgba(139, 92, 246, 0.35);
  --site-sto-bg: linear-gradient(135deg, #38bdf8, #2563eb);
  --site-sto-shadow: 0 2px 8px rgba(56, 189, 248, 0.35);
  --site-megakino-bg: linear-gradient(135deg, #ef4444, #b91c1c);
  --site-megakino-shadow: 0 2px 8px rgba(239, 68, 68, 0.35);
  --site-cineby-bg: linear-gradient(135deg, #22d3ee, #0891b2);
  --site-cineby-shadow: 0 2px 8px rgba(34, 211, 238, 0.35);
  --site-kinox-bg: linear-gradient(135deg, #34d399, #059669);
  --site-kinox-shadow: 0 2px 8px rgba(52, 211, 153, 0.35);
  --site-burningseries-bg: linear-gradient(135deg, #fb923c, #ea580c);
  --site-burningseries-shadow: 0 2px 8px rgba(251, 146, 60, 0.35);
  --site-filmpalast-bg: linear-gradient(135deg, #84cc16, #4d7c0f);
  --site-filmpalast-shadow: 0 2px 8px rgba(132, 204, 22, 0.35);
  --site-mangafire-bg: linear-gradient(135deg, #f59e0b, #b45309);
  --site-mangafire-shadow: 0 2px 8px rgba(245, 158, 11, 0.35);
  --site-htv-bg: linear-gradient(135deg, #ff4fa3, #db2777);
  --site-htv-shadow: 0 2px 8px rgba(255, 79, 163, 0.35);

  /* Language badges on the episode rows */
  --badge-german-dub-border: rgba(37, 99, 235, 0.35);
  --badge-german-dub-text: #93c5fd;
  --badge-german-sub-border: rgba(147, 51, 234, 0.35);
  --badge-german-sub-text: #d8b4fe;
  --badge-english-dub-border: rgba(34, 197, 94, 0.35);
  --badge-english-dub-text: #86efac;
  --badge-english-sub-border: rgba(245, 158, 11, 0.35);
  --badge-english-sub-text: #fcd34d;

  /* Notice banner on the settings page */
  --notice-bg: rgba(245, 158, 11, 0.08);
  --notice-border: rgba(245, 158, 11, 0.25);
  --notice-text: #fcd34d;
  --notice-code-text: #fde68a;

  /* Odds and ends */
  --badge-downloaded-bg: rgba(34, 197, 94, 0.9);
  --card-hover-border: rgba(37, 99, 235, 0.3);
  --chip-hover-border: rgba(147, 51, 234, 0.5);
  --progress-track: rgba(255, 255, 255, 0.07);
  --scrollbar: #333;
  --scrollbar-hover: #444;
  --selection-bg: rgba(37, 99, 235, 0.25);
  --selection-text: #fff;
  --skeleton-base: rgba(255, 255, 255, 0.04);
  --skeleton-shine: rgba(255, 255, 255, 0.09);
  --segment-text: #666;
  --segment-text-hover: #999;
  --segment-text-active: #fff;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* display rules on classes would otherwise beat the hidden attribute */
[hidden] {
  display: none !important;
}

/* ===== Theme surfaces =====
   Two empty layers and a shader canvas, sitting behind the whole page. They
   paint nothing on their own, so the stock UI is unchanged, and a theme can
   use them instead of taking over a pseudo-element the app might want back.
   Layer 1 is furthest back, then layer 2, then the content. */
.theme-shader,
.theme-layer {
  position: fixed;
  inset: 0;
  pointer-events: none;
  border: 0;
}

.theme-shader {
  z-index: -3;
  width: 100%;
  height: 100%;
  display: block;
}

.theme-layer[data-layer="1"] {
  z-index: -2;
}

.theme-layer[data-layer="2"] {
  z-index: -1;
}

/* The page colour lives on html, not body, so a theme can put a fixed layer at
   a negative z-index behind the content without body's own background hiding
   it. Identical to look at, and it is what makes .theme-layer work at all. */
html {
  background: var(--bg);
}

body {
  background: transparent;
  color: var(--text);
  font-family: var(--font-body);
  min-height: 100vh;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
}

a {
  color: var(--link);
  text-decoration: none;
  transition: color 0.2s;
}

a:hover {
  color: var(--link-hover);
}

code,
pre {
  font-family: var(--font-mono);
}

::selection {
  background: var(--selection-bg);
  color: var(--selection-text);
}

::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--scrollbar);
  border-radius: 3px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-hover);
}

/* ===== Layout ===== */
.page {
  flex: 1;
}

.container {
  margin: 0 auto;
  padding: 32px 24px;
  max-width: 1400px;
}

.container-narrow {
  max-width: 900px;
}

h1 {
  text-align: center;
  margin-bottom: 20px;
  font-size: 1.75rem;
  font-family: var(--font-heading);
  color: var(--text-strong);
  font-weight: 700;
  letter-spacing: -0.02em;
}

h2 {
  font-size: 1.05rem;
  font-family: var(--font-heading);
  color: var(--text-strong);
  font-weight: 600;
}

h3 {
  font-size: 0.9rem;
  font-family: var(--font-heading);
  color: var(--text-strong);
  font-weight: 600;
  margin-top: 18px;
  margin-bottom: 8px;
}

.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 8px;
}

.page-head h1 {
  text-align: left;
  margin-bottom: 0;
}

.page-hint,
.hint {
  color: var(--text-muted);
  font-size: 0.82rem;
  margin-top: 6px;
}

.page-hint {
  margin-bottom: 20px;
}

/* ===== Navbar ===== */
.top-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 14px 24px;
  background: var(--surface-nav);
  backdrop-filter: blur(var(--nav-blur));
  -webkit-backdrop-filter: blur(var(--nav-blur));
  border-bottom: 1px solid var(--border-soft);
  position: sticky;
  top: 0;
  z-index: 50;
}

.top-bar-brand {
  color: var(--text-strong);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: -0.01em;
  transition: opacity 0.2s;
}

.top-bar-brand:hover {
  opacity: 0.8;
  color: var(--text-strong);
}

.top-bar-version {
  color: var(--text-muted);
  font-weight: 500;
  font-size: 0.8rem;
}

.top-bar-nav {
  display: flex;
  align-items: center;
  gap: 6px;
}

.top-bar-link {
  color: var(--text-dim);
  font-size: 0.85rem;
  font-family: inherit;
  padding: 6px 12px;
  border-radius: 6px;
  border: none;
  background: none;
  cursor: pointer;
  transition: color 0.2s, background 0.2s;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.top-bar-link:hover {
  color: var(--text-strong);
  background: var(--surface-strong);
}

.top-bar-icon {
  padding: 6px 10px;
}

.top-bar-user {
  color: var(--text-muted);
  font-size: 0.85rem;
  padding-left: 6px;
}

/* Diagonal "New" flash over the nav button, so people notice Auto-Sync was
   reworked instead of assuming it is the old one. */
.has-ribbon {
  position: relative;
  overflow: visible;
  /* room for the ribbon so it does not sit on the next nav item */
  margin-right: 14px;
}

.new-ribbon {
  position: absolute;
  top: -7px;
  right: -12px;
  transform: rotate(18deg);
  background: var(--gradient-accent);
  color: var(--text-on-accent);
  font-size: 0.58rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 4px;
  box-shadow: var(--shadow-ribbon);
  pointer-events: none;
}

.queue-badge {
  background: var(--accent);
  color: var(--text-on-accent);
  font-size: 0.7rem;
  font-weight: 700;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.queue-badge[hidden] {
  display: none;
}

.nav-toggle {
  display: none;
  flex-direction: column;
  gap: 4px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px;
}

.nav-toggle span {
  display: block;
  width: 20px;
  height: 2px;
  background: var(--text-dim);
  border-radius: 1px;
}

/* ===== Buttons ===== */
.btn {
  padding: 10px 20px;
  border-radius: var(--radius-sm);
  border: none;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.15s, box-shadow 0.2s, background 0.2s, color 0.2s;
  white-space: nowrap;
}

.btn:disabled {
  background: var(--surface-disabled);
  color: var(--text-disabled);
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}

.btn-primary {
  background: var(--gradient-accent);
  color: var(--text-on-accent);
  box-shadow: var(--shadow-btn);
}

.btn-primary:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: var(--shadow-btn-hover);
}

.btn-secondary {
  background: var(--surface-strong);
  color: var(--text);
  border: 1px solid var(--border);
}

.btn-secondary:hover:not(:disabled) {
  background: var(--surface-hover);
  color: var(--text-strong);
}

.btn-ghost {
  background: none;
  color: var(--text-dim);
  border: 1px solid var(--border);
  padding: 7px 14px;
  font-size: 0.82rem;
}

.btn-ghost:hover:not(:disabled) {
  color: var(--text-strong);
  border-color: var(--border-hover);
}

.btn-danger {
  background: var(--danger-soft);
  color: var(--danger-text);
  border: 1px solid var(--danger-border);
  padding: 6px 12px;
  font-size: 0.8rem;
}

.btn-danger:hover:not(:disabled) {
  background: var(--danger-soft-strong);
  color: var(--text-on-accent);
}

.btn-block {
  display: block;
  width: 100%;
  text-align: center;
}

.icon-btn {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  padding: 4px 7px;
  border-radius: 6px;
  transition: color 0.2s, background 0.2s;
}

.icon-btn:hover {
  color: var(--danger-text);
  background: var(--danger-soft);
}

/* the second press on a stopping download, which kills it mid episode */
.icon-btn-danger {
  color: var(--danger-text);
  background: var(--danger-tint);
}

.icon-btn-danger:hover {
  color: var(--text-on-accent);
  background: var(--danger);
}

/* ===== Inputs ===== */
input[type="text"],
input[type="password"],
input[type="search"],
select {
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface-input);
  color: var(--text-input);
  font-family: inherit;
  font-size: 0.9rem;
  outline: none;
  transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;
}

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

input::placeholder {
  color: var(--text-placeholder);
}

select option {
  background: var(--surface-option);
  color: var(--text-input);
}

.field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  flex: 1;
  min-width: 160px;
}

.field-label {
  font-size: 0.76rem;
  color: var(--text-muted);
  font-weight: 500;
}

.control-row {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 14px;
}

.checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.88rem;
  color: var(--text);
  cursor: pointer;
  margin-top: 14px;
}

.checkbox input {
  accent-color: var(--accent);
  cursor: pointer;
  width: 15px;
  height: 15px;
}

.inline-form {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
}

.inline-form input {
  flex: 1;
  min-width: 150px;
}

.action-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 16px;
}

/* ===== Site switch =====
   Every site carries its own colour, the way it did before v5. Nothing here is
   hardcoded into a rule: the colours are tokens, and body[data-site] only maps
   the current site's pair onto --active-site-*, which is what the switch reads.
   A theme has two ways in, both from the tokens block above:

     --site-kinox-bg: ...      recolour one site
     --site-all-bg: ...        one colour for every site, which is how you turn
                               per-site colouring off entirely

   --site-all-* wins because it is read first, with the per-site token as the
   fallback. Overriding --active-site-bg directly does not work from a theme:
   body[data-site="..."] outranks a plain :root or body rule, which is exactly
   why --site-all-* exists. */
body,
body[data-site="aniworld"] {
  --active-site-bg: var(--site-all-bg, var(--site-aniworld-bg));
  --active-site-shadow: var(--site-all-shadow, var(--site-aniworld-shadow));
}

body[data-site="sto"] {
  --active-site-bg: var(--site-all-bg, var(--site-sto-bg));
  --active-site-shadow: var(--site-all-shadow, var(--site-sto-shadow));
}

body[data-site="megakino"] {
  --active-site-bg: var(--site-all-bg, var(--site-megakino-bg));
  --active-site-shadow: var(--site-all-shadow, var(--site-megakino-shadow));
}

body[data-site="cineby"] {
  --active-site-bg: var(--site-all-bg, var(--site-cineby-bg));
  --active-site-shadow: var(--site-all-shadow, var(--site-cineby-shadow));
}

body[data-site="kinox"] {
  --active-site-bg: var(--site-all-bg, var(--site-kinox-bg));
  --active-site-shadow: var(--site-all-shadow, var(--site-kinox-shadow));
}

body[data-site="burningseries"] {
  --active-site-bg: var(--site-all-bg, var(--site-burningseries-bg));
  --active-site-shadow: var(--site-all-shadow, var(--site-burningseries-shadow));
}

body[data-site="filmpalast"] {
  --active-site-bg: var(--site-all-bg, var(--site-filmpalast-bg));
  --active-site-shadow: var(--site-all-shadow, var(--site-filmpalast-shadow));
}

body[data-site="mangafire"] {
  --active-site-bg: var(--site-all-bg, var(--site-mangafire-bg));
  --active-site-shadow: var(--site-all-shadow, var(--site-mangafire-shadow));
}

body[data-site="htv"] {
  --active-site-bg: var(--site-all-bg, var(--site-htv-bg));
  --active-site-shadow: var(--site-all-shadow, var(--site-htv-shadow));
}

.segmented {
  display: flex;
  justify-content: center;
  margin-bottom: 24px;
}

.segmented-track {
  position: relative;
  display: inline-flex;
  background: var(--surface-strong);
  border-radius: var(--radius);
  padding: 3px;
  border: 1px solid var(--border);
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}

.segmented-track::-webkit-scrollbar {
  display: none;
}

.segmented-thumb {
  position: absolute;
  top: 3px;
  left: 0;
  height: calc(100% - 6px);
  border-radius: 9px;
  background: var(--active-site-bg);
  box-shadow: var(--active-site-shadow);
  /* the colour fades a touch slower than the slide, so switching sites reads
     as one movement rather than a jump to a new colour */
  transition: transform 0.3s var(--ease), width 0.3s var(--ease),
    background 0.4s, box-shadow 0.4s;
  z-index: 0;
  pointer-events: none;
}

.segmented-btn {
  position: relative;
  z-index: 1;
  padding: 8px 20px;
  border: none;
  background: none;
  color: var(--segment-text);
  font-size: 0.88rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: color 0.3s;
}

.segmented-btn.active {
  color: var(--segment-text-active);
}

.segmented-btn:hover:not(.active) {
  color: var(--segment-text-hover);
}

/* ===== Search ===== */
.search-bar {
  display: flex;
  gap: 10px;
  max-width: 960px;
  margin: 0 auto 32px;
}

.search-bar input {
  flex: 1;
  padding: 12px 16px;
  font-size: 0.95rem;
}

.spinner {
  display: none;
  text-align: center;
  padding: 24px;
  color: var(--text-muted);
  font-size: 0.9rem;
}

.spinner.active {
  display: block;
}

/* ===== Cards ===== */
.results,
.browse-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  justify-content: center;
}

.poster-card {
  position: relative;
  width: 170px;
  flex-shrink: 0;
  background: var(--surface);
  border-radius: var(--radius);
  overflow: hidden;
  cursor: pointer;
  border: 1px solid var(--border-soft);
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease), border-color 0.25s;
}

.poster-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-card);
  border-color: var(--card-hover-border);
}

.poster-card img {
  width: 100%;
  height: 260px;
  object-fit: cover;
  background: var(--surface-poster);
  display: block;
}

.poster-card .info {
  padding: 12px 14px;
}

.poster-card .title {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-bright);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.poster-card .subtitle {
  font-size: 0.75rem;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 2px;
}

.downloaded-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  background: var(--badge-downloaded-bg);
  color: var(--text-on-accent);
  font-size: 0.7rem;
  font-weight: 700;
  padding: 3px 7px;
  border-radius: 6px;
}

.empty-state {
  width: 100%;
  text-align: center;
  color: var(--text-faint);
  padding: 40px 0;
  font-size: 0.9rem;
}

.browse-section {
  margin-bottom: 40px;
}

.browse-heading {
  font-size: 1.05rem;
  color: var(--text-strong);
  margin-bottom: 16px;
  font-weight: 600;
}

/* ===== Genres ===== */
.genre-bar {
  max-width: 960px;
  margin: -14px auto 32px;
}

.genre-bar-title {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 10px;
}

.genre-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}

.genre-chip {
  padding: 6px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s, background 0.2s;
}

.genre-chip:hover {
  color: var(--text-strong);
  border-color: var(--chip-hover-border);
}

.genre-chip:focus-visible {
  outline: 2px solid var(--purple);
  outline-offset: 2px;
}

.genre-chip.active {
  background: var(--gradient-purple);
  border-color: transparent;
  color: var(--text-on-accent);
}

.genre-more {
  display: flex;
  justify-content: center;
  margin: 28px 0 8px;
}

/* ===== Modal ===== */
.overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: var(--overlay-bg);
  backdrop-filter: blur(var(--overlay-blur));
  z-index: 100;
  padding: 24px;
  overflow-y: auto;
}

.overlay.open {
  display: flex;
}

.modal {
  position: relative;
  background: var(--surface-modal);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  max-width: 860px;
  /* auto margins centre the box, and collapse to 0 once it is taller than the
     viewport, so tall modals still scroll from the top instead of being clipped */
  margin: auto;
  width: 100%;
  padding: 28px;
  box-shadow: var(--shadow-modal);
}

.modal-narrow {
  max-width: 620px;
}

.modal-close {
  position: absolute;
  top: 14px;
  right: 16px;
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  transition: color 0.2s;
}

.modal-close:hover {
  color: var(--text-strong);
}

.modal-title {
  font-size: 1.15rem;
  color: var(--text-strong);
  margin-bottom: 16px;
}

.modal-actions {
  display: flex;
  gap: 12px;
  margin-top: 20px;
  flex-wrap: wrap;
}

/* ===== Series modal ===== */
.series-header {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
  padding-right: 30px;
}

.series-header img {
  width: 140px;
  height: 200px;
  object-fit: cover;
  border-radius: var(--radius);
  background: var(--surface-poster);
  flex-shrink: 0;
}

.series-meta h2 {
  font-size: 1.3rem;
  margin-bottom: 8px;
}

.series-genres,
.series-year {
  font-size: 0.8rem;
  color: var(--text-muted);
  margin-bottom: 4px;
}

.series-desc {
  font-size: 0.85rem;
  color: var(--text);
  margin-top: 10px;
  max-height: 120px;
  overflow-y: auto;
}

.episodes-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 22px;
  margin-bottom: 10px;
  flex-wrap: wrap;
}

.episodes-header .checkbox {
  margin-top: 0;
}

/* ===== Loading skeleton =====
   Mirrors the series modal layout so nothing jumps when the real content
   replaces it. */
.skeleton {
  background: linear-gradient(
    90deg,
    var(--skeleton-base) 25%,
    var(--skeleton-shine) 37%,
    var(--skeleton-base) 63%
  );
  background-size: 400% 100%;
  animation: skeleton-shimmer 1.4s ease infinite;
  border-radius: 6px;
}

@keyframes skeleton-shimmer {
  from {
    background-position: 100% 50%;
  }

  to {
    background-position: 0 50%;
  }
}

.skeleton-header {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
  padding-right: 30px;
}

.skeleton-poster {
  width: 140px;
  height: 200px;
  border-radius: var(--radius);
  flex-shrink: 0;
}

.skeleton-meta {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 4px;
}

.skeleton-title {
  height: 22px;
  width: 55%;
  border-radius: 7px;
}

.skeleton-line {
  height: 11px;
}

/* child 1 is the title bar, 2-5 stand in for genres, year and description */
.skeleton-meta .skeleton-line:nth-child(2) {
  width: 80%;
}

.skeleton-meta .skeleton-line:nth-child(3) {
  width: 30%;
}

.skeleton-meta .skeleton-line:nth-child(4) {
  width: 95%;
}

.skeleton-meta .skeleton-line:nth-child(5) {
  width: 70%;
}

.skeleton-controls {
  display: flex;
  gap: 12px;
  margin-bottom: 26px;
}

.skeleton-field {
  flex: 1;
  height: 42px;
  border-radius: var(--radius-sm);
}

.skeleton-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.skeleton-row {
  height: 34px;
  border-radius: var(--radius-xs);
}

.skeleton-row:nth-child(even) {
  opacity: 0.7;
}

.skeleton-status {
  text-align: center;
  color: var(--text-muted);
  font-size: 0.85rem;
  padding: 20px 0 4px;
}

@media (prefers-reduced-motion: reduce) {
  .skeleton {
    animation: none;
  }
}

@media (max-width: 820px) {
  .skeleton-header {
    flex-direction: column;
    padding-right: 0;
  }

  .skeleton-poster {
    width: 110px;
    height: 158px;
  }
}

/* ===== Season accordion ===== */
.season-accordion {
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  overflow: hidden;
}

.season-accordion:empty {
  border: none;
}

.season-section + .season-section {
  border-top: 1px solid var(--border-soft);
}

.season-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  cursor: pointer;
  background: var(--surface);
  transition: background 0.2s;
}

.season-header:hover {
  background: var(--surface-strong);
}

.season-label {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-bright);
}

.arrow {
  display: inline-block;
  font-size: 0.65rem;
  color: var(--text-muted);
  transition: transform 0.2s;
}

.arrow.expanded,
.season-header.expanded .arrow {
  transform: rotate(90deg);
}

.season-body {
  display: none;
  padding: 4px 0;
}

.season-body.expanded {
  display: block;
}

.episode-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 14px;
  font-size: 0.85rem;
  transition: background 0.15s;
}

.episode-item:hover {
  background: var(--surface-subtle);
}

.episode-item input[type="checkbox"] {
  accent-color: var(--accent);
  cursor: pointer;
}

.ep-num {
  color: var(--text-muted);
  font-size: 0.78rem;
  font-weight: 600;
  min-width: 42px;
}

.ep-main {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
  flex-wrap: wrap;
}

.ep-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ep-title-missing {
  color: var(--text-placeholder);
  font-style: italic;
}

.ep-done {
  color: var(--success);
  font-weight: 700;
}

.lang-badges {
  display: inline-flex;
  gap: 5px;
  flex-wrap: wrap;
  justify-content: flex-end;
  /* sit against the right edge of the row instead of trailing the title */
  margin-left: auto;
  flex-shrink: 0;
}

.lang-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  border-radius: 5px;
  font-size: 0.68rem;
  font-weight: 600;
  background: var(--surface-strong);
  border: 1px solid var(--border);
  color: var(--text-dim);
}

.lang-badge img {
  width: 13px;
  height: 9px;
  border-radius: 1px;
  object-fit: cover;
}

.badge-german-dub {
  border-color: var(--badge-german-dub-border);
  color: var(--badge-german-dub-text);
}

.badge-german-sub {
  border-color: var(--badge-german-sub-border);
  color: var(--badge-german-sub-text);
}

.badge-english-dub {
  border-color: var(--badge-english-dub-border);
  color: var(--badge-english-dub-text);
}

.badge-english-sub {
  border-color: var(--badge-english-sub-border);
  color: var(--badge-english-sub-text);
}

.accordion-message {
  padding: 14px;
  text-align: center;
  color: var(--text-faint);
  font-size: 0.85rem;
}

/* A second sentence inside a notice, on its own line under the first. */
.notice-line {
  margin-top: 6px;
}

/* A section heading with its "resets after restart" badge next to it. The badge
   has to sit outside the h2: data-i18n replaces the heading's textContent,
   which would take any child element with it. */
.card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* Warns that this section lives in the process environment only. Deliberately
   quiet: it is a note, not an error. */
.reset-badge {
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--notice-border);
  background: var(--notice-bg);
  color: var(--notice-text);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

/* ===== Queue ===== */
.queue-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.filter-chips {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  transition: color 0.2s, background 0.2s, border-color 0.2s;
}

.chip:hover {
  color: var(--text-strong);
  border-color: var(--border-hover);
}

.chip.is-active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--text-strong);
}

.chip-count {
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

.chip.is-active .chip-count {
  color: var(--text-strong);
}

.queue-tools {
  display: flex;
  align-items: center;
  gap: 8px;
}

.queue-search {
  width: 200px;
}

.queue-search,
.queue-sort {
  padding: 8px 12px;
  font-size: 0.83rem;
}

.queue-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Shown instead of the rows when the very first load fails, so a queue that
   cannot be reached says so rather than sitting on "Loading..." for good. */
.queue-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 28px 18px;
  text-align: center;
  color: var(--danger-text);
  background: var(--danger-soft);
  border: 1px solid var(--danger-border);
  border-radius: var(--radius-sm);
}

.pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 18px;
}

.pager-label {
  font-size: 0.83rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.queue-item {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
}

.queue-item-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.queue-item-title {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-bright);
}

.queue-item-meta {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin-top: 2px;
}

.queue-item-actions {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

/* inline-flex, not inline-block: the pill is a flex item next to the row
   buttons and gets stretched to their height, which would leave the text
   pinned to the top. */
.status-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1;
  padding: 4px 8px;
  border-radius: 5px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.status-queued {
  background: var(--status-queued-bg);
  color: var(--status-queued-text);
}

.status-running {
  background: var(--status-running-bg);
  color: var(--status-running-text);
}

.status-completed {
  background: var(--status-completed-bg);
  color: var(--status-completed-text);
}

.status-failed {
  background: var(--status-failed-bg);
  color: var(--status-failed-text);
}

.status-cancelled {
  background: var(--status-cancelled-bg);
  color: var(--status-cancelled-text);
}

.progress-track {
  height: 5px;
  background: var(--progress-track);
  border-radius: 3px;
  overflow: hidden;
  margin-top: 10px;
}

/* The width is set once per poll. Animating for exactly that long means the
   bar is always still moving when the next value lands, instead of jumping
   and then standing still. queue.js sets the duration from its interval. */
.progress-fill {
  height: 100%;
  background: var(--gradient-progress);
  border-radius: 3px;
  transition: width var(--progress-step, 0.4s) linear;
}

/* Going backwards, a retry or a force cancel, should snap not crawl */
.progress-fill.no-transition {
  transition: none;
}

/* Percentage under the left end of the bar, speed under the right. Tabular
   figures stop the numbers jittering sideways as they tick. */
.progress-stats {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 5px;
  font-size: 0.72rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.queue-errors {
  margin-top: 8px;
  font-size: 0.75rem;
  color: var(--danger-text);
}

.queue-errors summary {
  cursor: pointer;
}

.queue-errors ul {
  margin: 6px 0 0 16px;
  color: var(--text-muted);
}

/* ===== Captcha ===== */
.captcha-hint {
  font-size: 0.85rem;
  color: var(--text-muted);
  margin-bottom: 12px;
}

.captcha-screen-wrap {
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--surface-captcha);
}

.captcha-screen {
  display: block;
  width: 100%;
  cursor: crosshair;
}

/* ===== Cards / tables (settings, library) ===== */
.card {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  padding: 22px;
  margin-bottom: 20px;
}

.notice {
  background: var(--notice-bg);
  border: 1px solid var(--notice-border);
  border-radius: var(--radius-sm);
  padding: 12px 16px;
  font-size: 0.83rem;
  color: var(--notice-text);
  margin-top: 16px;
  margin-bottom: 20px;
}

/* A notice that ends its card would add its own bottom margin on top of the
   card's padding, leaving a gap twice the size of the one above it. */
.notice:last-child {
  margin-bottom: 0;
}

.notice code {
  display: inline-block;
  background: var(--surface-code-inline);
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 0.8rem;
  color: var(--notice-code-text);
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 14px;
  font-size: 0.85rem;
}

.data-table th {
  text-align: left;
  padding: 8px 10px;
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border-soft);
}

.data-table td {
  padding: 10px;
  border-bottom: 1px solid var(--border-soft);
  vertical-align: middle;
}

.data-table tr:last-child td {
  border-bottom: none;
}

.data-table .empty-row td {
  color: var(--text-muted);
  text-align: center;
  padding: 18px;
}

/* ===== API keys ===== */
.new-key {
  background: var(--surface-strong);
  border: 1px solid var(--accent-soft);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  margin-top: 14px;
}

.new-key-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
  flex-wrap: wrap;
}

.new-key-row code {
  flex: 1;
  min-width: 200px;
  background: var(--surface-code);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 0.8rem;
  color: var(--text-strong);
  word-break: break-all;
}

.key-expired {
  color: var(--danger);
}

.api-docs {
  margin-top: 18px;
  border-top: 1px solid var(--border-soft);
  padding-top: 14px;
}

.api-docs summary {
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-dim);
}

.api-docs summary:hover {
  color: var(--text-strong);
}

.api-docs h3 {
  font-size: 0.85rem;
  margin-top: 18px;
  color: var(--text-strong);
}

/* the endpoint column must not wrap mid-path, so the table scrolls on narrow screens */
.api-scroll {
  overflow-x: auto;
}

.api-endpoints td:first-child {
  white-space: nowrap;
}

.api-endpoints code {
  font-size: 0.78rem;
  color: var(--text-strong);
}

.api-example {
  background: var(--surface-code);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  margin-top: 8px;
  overflow-x: auto;
  font-size: 0.78rem;
  line-height: 1.6;
  color: var(--text-dim);
}

.site-toggles {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
}

.site-toggle {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.76rem;
  color: var(--text-dim);
  cursor: pointer;
}

.site-toggle input {
  accent-color: var(--accent);
  width: 13px;
  height: 13px;
  cursor: pointer;
}

.provider-order {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
}

.provider-row {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--surface-strong);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-xs);
  padding: 8px 12px;
  font-size: 0.85rem;
  cursor: grab;
  /* keeps a touch drag from scrolling the page instead */
  touch-action: none;
  user-select: none;
  transition: border-color 0.2s, background 0.2s;
}

.provider-row:hover {
  border-color: var(--border-hover-soft);
}

.provider-row:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.provider-row.dragging {
  cursor: grabbing;
  position: relative;
  z-index: 2;
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: var(--shadow-drag);
}

/* 2 columns x 3 rows of dots. The box has to be an exact multiple of the tile
   or the pattern repeats past the edge and shows half a row of dots. */
.drag-grip {
  width: 10px;
  height: 15px;
  flex-shrink: 0;
  color: var(--text-muted);
  background-image: radial-gradient(currentColor 1px, transparent 1.5px);
  background-size: 5px 5px;
}

.provider-row:hover .drag-grip,
.provider-row.dragging .drag-grip {
  color: var(--text-dim);
}

.provider-rank {
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 700;
  min-width: 18px;
}

.provider-name {
  flex: 1;
}

.ip-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: var(--surface-strong);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  padding: 16px;
  margin-top: 12px;
  flex-wrap: wrap;
}

.ip-label {
  font-size: 0.75rem;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.ip-value {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--text-strong);
  margin: 4px 0;
  font-variant-numeric: tabular-nums;
}

.ip-meta {
  font-size: 0.76rem;
  color: var(--text-muted);
}

/* ===== Custom CSS box ===== */
.code-input {
  display: block;
  width: 100%;
  margin-top: 12px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface-code);
  color: var(--text-input);
  font-family: var(--font-mono);
  font-size: 0.82rem;
  line-height: 1.55;
  tab-size: 2;
  /* only vertical, a wider box would push the card out of the page */
  resize: vertical;
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s;
}

.css-warning {
  margin: 12px 0 0;
}

.css-warning p + p {
  margin-top: 6px;
}

.css-warning code {
  display: inline-block;
  background: var(--surface-code-inline);
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 0.8rem;
  color: var(--notice-code-text);
  word-break: break-all;
}

.code-input-short {
  min-height: 190px;
}

.code-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.code-input::placeholder {
  color: var(--text-placeholder);
}

/* ===== Library ===== */
.library-tree {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.library-node {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.library-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 11px 14px;
  cursor: pointer;
  transition: background 0.15s;
}

.library-row:hover {
  background: var(--surface-strong);
}

.library-row-left {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  /* basis auto so the name keeps its own width instead of starting at zero */
  flex: 1 1 auto;
}

.library-row-right {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  /* a long path shrinks here rather than squeezing out the name */
  flex: 0 1 auto;
  overflow: hidden;
}

.library-row-right .library-sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* the location label stays readable, a long path truncates instead */
.library-row[data-toggle="location"] .library-name {
  flex-shrink: 0;
}

.library-name {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-bright);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.library-sub {
  font-size: 0.75rem;
  color: var(--text-muted);
}

.library-children {
  display: none;
  border-top: 1px solid var(--border-soft);
}

.library-children.expanded {
  display: block;
}

.library-children .library-row {
  padding-left: 30px;
}

.library-children .library-children .library-row {
  padding-left: 48px;
}

.library-episode {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 14px 7px 66px;
  font-size: 0.82rem;
}

.library-episode:hover {
  background: var(--surface-subtle);
}

.library-ep-num {
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 600;
  min-width: 42px;
}

.library-ep-file {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.library-ep-size {
  color: var(--text-muted);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

/* ===== Toast ===== */
.toast {
  display: none;
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--surface-toast);
  border: 1px solid var(--border);
  color: var(--text-strong);
  padding: 12px 20px;
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
  box-shadow: var(--shadow-toast);
  z-index: 200;
  max-width: calc(100vw - 48px);
}

.toast.show {
  display: block;
}

/* ===== Auth pages ===== */
.auth-body {
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: 32px;
  margin: auto;
}

.auth-card h1 {
  font-size: 1.3rem;
  margin-bottom: 8px;
}

.auth-hint {
  text-align: center;
  color: var(--text-muted);
  font-size: 0.83rem;
  margin-bottom: 18px;
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 18px;
}

.auth-error {
  background: var(--danger-soft);
  border: 1px solid var(--danger-border);
  color: var(--danger-text);
  border-radius: var(--radius-xs);
  padding: 10px 14px;
  font-size: 0.83rem;
  margin-top: 12px;
}

.auth-divider {
  text-align: center;
  color: var(--text-muted);
  font-size: 0.8rem;
  margin: 16px 0;
}

/* ===== Responsive ===== */
@media (max-width: 820px) {
  .nav-toggle {
    display: flex;
  }

  .top-bar {
    flex-wrap: wrap;
  }

  /* three across rather than one per line, so the open menu costs a third of
     the screen instead of most of it */
  .top-bar-nav {
    display: none;
    width: 100%;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 2px;
    padding-top: 10px;
  }

  .top-bar-nav.open {
    display: grid;
  }

  .top-bar-link,
  .top-bar-user {
    justify-content: center;
    text-align: center;
    min-height: 40px;
    min-width: 0;
    padding: 8px 6px;
    white-space: nowrap;
  }

  /* the desktop rule reserves room to the right of Auto-Sync for the ribbon,
     which here would just make that one column narrower than the other two */
  .has-ribbon {
    margin-right: 0;
  }

  .new-ribbon {
    top: -5px;
    right: -2px;
    transform: rotate(12deg);
  }

  /* the search box and the sort dropdown get a line of their own rather than
     being squeezed next to the filter chips */
  .queue-controls {
    flex-direction: column;
    align-items: stretch;
  }

  .queue-tools {
    width: 100%;
  }

  .queue-search {
    flex: 1;
    width: auto;
    min-width: 0;
  }

  .queue-sort {
    min-width: 0;
  }

  .pager .btn {
    padding: 10px 14px;
  }

  /* a horizontal scroller hides the sites that do not fit and gives no hint
     that they are there, so wrap them into a grid instead */
  .segmented {
    width: 100%;
    max-width: 520px;
    margin-left: auto;
    margin-right: auto;
  }

  .segmented-track {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    width: 100%;
    overflow-x: visible;
  }

  /* the sliding thumb only tracks one row, so the active button carries the
     highlight itself once the buttons wrap */
  .segmented-thumb {
    display: none;
  }

  .segmented-btn {
    min-height: 40px;
    min-width: 0;
    padding: 8px;
    border-radius: 9px;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .segmented-btn.active {
    background: var(--active-site-bg);
    box-shadow: var(--active-site-shadow);
  }

  /* A row of these does not fit a phone: an unbreakable path or URL plus the
     site toggles push the last column, and with it the Remove button, off the
     right edge of the card. Stack each record instead. Only tables whose cells
     read fine without their column header get this, so nothing is left as an
     unlabelled value. */
  .stacked-table,
  .stacked-table tbody,
  .stacked-table tr,
  .stacked-table td {
    display: block;
    width: 100%;
  }

  .stacked-table thead {
    display: none;
  }

  .stacked-table tr {
    padding: 12px 0;
    border-bottom: 1px solid var(--border-soft);
  }

  .stacked-table tr:last-child {
    border-bottom: none;
  }

  .stacked-table td {
    padding: 3px 0;
    border-bottom: none;
  }

  /* with the column header gone the name has to carry the block itself */
  .stacked-table td:first-child {
    font-weight: 600;
    color: var(--text-strong);
  }

  /* a path or URL has no spaces to break at, so let it break anywhere */
  .stacked-table code,
  .stacked-table a {
    overflow-wrap: anywhere;
  }

  .stacked-table td:last-child {
    padding-top: 8px;
  }

  .series-header {
    flex-direction: column;
    padding-right: 0;
  }

  .series-header img {
    width: 110px;
    height: 158px;
  }

  .modal {
    padding: 22px 18px;
  }

  .search-bar {
    flex-wrap: wrap;
  }

  .search-bar input {
    flex-basis: 100%;
  }

  .search-bar .btn {
    flex: 1;
  }

  /* the full path never fits next to the name on a phone */
  .library-row[data-toggle="location"] .library-sub {
    display: none;
  }

  /* no room for title and badges side by side, so stack them.
     nowrap matters: a column container that is allowed to wrap sizes its line
     to the widest item's max-content width instead of to the row, which let
     long titles and badge groups spill off the right edge. */
  .ep-main {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 6px;
  }

  /* keep the checkbox and number on the title's line, not floating mid-row */
  .episode-item {
    align-items: flex-start;
  }

  .ep-num,
  .ep-done {
    line-height: 1.45;
  }

  /* show the whole title over as many lines as it needs instead of cutting it
     off, and break inside a word when a single one is wider than the row */
  .ep-title {
    flex: none;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: anywhere;
  }

  /* under a wrapped title the badges read better aligned with its first
     character than pushed to the right edge */
  .lang-badges {
    margin-left: 0;
    justify-content: flex-start;
  }

  .library-children .library-row {
    padding-left: 22px;
  }

  .library-children .library-children .library-row {
    padding-left: 34px;
  }

  .library-episode {
    padding-left: 46px;
  }
}

@media (max-width: 520px) {
  .poster-card {
    width: calc(50% - 9px);
  }

  .poster-card img {
    height: 220px;
  }
}

/* ===== Auto-Sync page ===== */
.explainer {
  margin: 10px 0 0 18px;
  font-size: 0.88rem;
  color: var(--text);
}

.explainer li {
  margin-bottom: 8px;
}

.sync-stats {
  display: flex;
  gap: 28px;
  flex-wrap: wrap;
  margin-top: 12px;
}

.sync-value {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-strong);
  margin-top: 4px;
}

.sync-report {
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sync-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--surface-strong);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-xs);
  padding: 10px 12px;
}

.sync-row-main {
  min-width: 0;
}

.sync-row-title {
  display: block;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-bright);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Which library and language folder this row is about, shown when the same
   show sits on disk more than once. */
.sync-row-where {
  margin-left: 8px;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--text-muted);
}

.sync-row-detail {
  font-size: 0.76rem;
  color: var(--text-muted);
}

.sync-report .status-pill {
  flex-shrink: 0;
}

.exclude-results {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
}

.exclude-results:empty {
  display: none;
}

.exclude-result {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--surface-strong);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-xs);
  padding: 8px 12px;
}

.exclude-result-title {
  font-size: 0.85rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
