/* =============================================================================
   Design tokens
   -----------------------------------------------------------------------------
   Every colour, space, radius and type size in this file comes from here. Use the
   semantic token (what the value is FOR), not a raw value, so a theme change is a
   remap in this block rather than a hunt through the rules below.

   What is deliberately NOT a token: component dimensions (sidebar width, thumbnail
   sizes, icon boxes), motion curves/durations (left for the animate pass), and the
   per-category data palette at the bottom of the category-tag rules -- each category
   colour is defined exactly once, on its own class.
   ============================================================================= */
:root {
  /* ---- Type ------------------------------------------------------------------ */
  --font-family: 'Inter', system-ui, -apple-system, sans-serif;
  --font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;

  /* Role scale. 12px is the floor: nothing that carries words goes below it. */
  --fs-caption: 12px;   /* metadata, badges, hints, counters */
  --fs-control: 13px;   /* buttons, chips, tabs, inputs in dense rows, secondary body */
  --fs-body: 14px;      /* body copy, inputs, nav */
  --fs-title: 15px;     /* card titles, editor heading */
  --fs-heading: 18px;   /* brand, queue column headings */
  --fs-display: 24px;   /* stat values */

  --icon-sm: 12px;
  --icon-md: 16px;
  --icon-lg: 20px;
  --icon-xl: 48px;

  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;

  --lh-tight: 1.3;
  --lh-snug: 1.4;
  --lh-normal: 1.5;
  --lh-relaxed: 1.6;

  --tracking-tight: -0.03em;
  --tracking-caps: 0.04em;

  /* ---- Space (4px base) -------------------------------------------------------- */
  --space-0-5: 2px;
  --space-1: 4px;
  --space-1-5: 6px;
  --space-2: 8px;
  --space-2-5: 10px;
  --space-3: 12px;
  --space-3-5: 14px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-9: 36px;

  /* ---- Radius -------------------------------------------------------------------- */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
  --border-radius: 12px;      /* cards, inputs, buttons (pre-existing name) */
  --border-radius-lg: 16px;   /* glass panels (pre-existing name) */
  --radius-pill: 999px;

  /* ---- Control sizes -------------------------------------------------------------- */
  --target-min: 32px;         /* smallest hit area for chips, checkboxes, compact buttons */
  --control-h-sm: 32px;
  --target-touch: 44px;       /* the same, on a coarse pointer: both above are remapped to it */
  --checkbox-size: 18px;      /* the drawn box; the hit area around it is --target-min */

  /* ---- Colour: surfaces (zucchini dark) ------------------------------------------- */
  --bg-main: #060c08;
  --bg-sidebar: #0b140e;
  --surface-raised: #111e16;              /* popovers, dropdowns, editor toolbar */
  --surface-editable: rgba(17, 30, 22, 0.85);
  --surface-input: rgba(15, 22, 38, 0.4);
  --surface-code: rgba(15, 22, 38, 0.7);
  --surface-overlay: rgba(11, 20, 14, 0.95);  /* sticky bars over scrolling content */
  --surface-toast: #15221a;
  --scrim: rgba(0, 0, 0, 0.88);
  --scrim-image: rgba(6, 12, 8, 0.8);
  --scrim-image-fade: rgba(6, 12, 8, 0.1);
  --scrim-control: rgba(0, 0, 0, 0.3);

  --glass-bg: rgba(255, 255, 255, 0.02);
  --glass-subtle: rgba(255, 255, 255, 0.04);
  --glass-border: rgba(255, 255, 255, 0.05);
  --glass-hover: rgba(255, 255, 255, 0.06);
  --glass-active: rgba(255, 255, 255, 0.1);

  --border-subtle: rgba(255, 255, 255, 0.08);
  --border-strong: rgba(255, 255, 255, 0.12);
  --border-hover: rgba(255, 255, 255, 0.2);
  --border-control: rgba(255, 255, 255, 0.38);  /* checkbox outline: >=3:1 on the panel */

  /* ---- Colour: text --------------------------------------------------------------- */
  --text-main: #f3f4f6;
  --text-soft: #cbd5e1;
  --text-muted: #9ca3af;      /* 7:1 on the panel */
  --text-dark: #7d8590;       /* tertiary; was #6b7280 (4.1:1), now >=5:1 */
  --text-on-accent: #04110a;  /* text on any bright fill (green, amber, status fills) */
  --text-on-fill: #ffffff;    /* text on the deep fills (danger, facebook) */

  /* ---- Colour: accent and semantic ------------------------------------------------- */
  --primary: #2ecc71; /* Zucchini Neon Green */
  --primary-hover: #27ae60;
  --primary-glow: rgba(46, 204, 113, 0.35);
  --primary-tint: color-mix(in srgb, var(--primary) 12%, transparent);
  --primary-tint-strong: color-mix(in srgb, var(--primary) 22%, transparent);
  --primary-border: color-mix(in srgb, var(--primary) 35%, transparent);
  --primary-text-hover: #6ee7a0;

  --success: #1abc9c; /* Mint/Teal Green */
  --success-hover: #16a085;
  --success-glow: rgba(26, 188, 156, 0.35);
  --success-tint: color-mix(in srgb, var(--success) 14%, transparent);
  --success-border: color-mix(in srgb, var(--success) 40%, transparent);

  --warning: #f59e0b; /* Amber */
  --warning-hover: #d97706;
  --warning-glow: rgba(245, 158, 11, 0.4);
  --warning-tint: color-mix(in srgb, var(--warning) 8%, transparent);

  --danger: #ef4444; /* Rose Red: text and icons on dark */
  --danger-fill: #dc2626;           /* button fill: white text 4.8:1 */
  --danger-fill-hover: #b91c1c;
  --danger-glow: rgba(239, 68, 68, 0.4);
  --danger-tint: color-mix(in srgb, var(--danger) 10%, transparent);
  --danger-border: color-mix(in srgb, var(--danger) 40%, transparent);
  --danger-strong: color-mix(in srgb, var(--danger) 80%, transparent);

  --info: #60a5fa;
  --info-tint: color-mix(in srgb, var(--info) 15%, transparent);
  --info-border: color-mix(in srgb, var(--info) 35%, transparent);

  --brand-facebook: #166fe5;        /* white text 4.7:1 */
  --brand-facebook-hover: #1460c8;

  /* One focus ring for every interactive element (see "Focus" below the reset). */
  --focus-ring: var(--primary);
  --focus-ring-width: 2px;
  --focus-ring-offset: 2px;
  --focus-ring-inset: -2px;   /* inside scroll strips and clipped containers */

  /* ---- Colour: article status -------------------------------------------------------
     One hue per pipeline status. Each is used three ways: as the icon/text colour on
     the dark panel, as a 14% tint behind a badge, and as the fill of the active filter
     chip with --text-on-accent on top. All three pairs clear 4.5:1. */
  --status-translation: #c4b5fd;   /* PENDING_TRANSLATION  fa-language */
  --status-review: var(--primary); /* PENDING_REVIEW       fa-star */
  --status-consideration: #fbbf24; /* FOR_CONSIDERATION    fa-triangle-exclamation */
  --status-irrelevant: #f87171;    /* NOT_RELEVANT         fa-circle-xmark */
  --status-cms-queued: #93c5fd;    /* PENDING_CMS_UPLOAD   fa-hourglass-half */
  --status-cms-uploading: #a5b4fc; /* CMS_UPLOADING        fa-cloud-arrow-up */
  --status-sent: #38bdf8;          /* SENT_TO_CMS          fa-paper-plane */
  --status-published: #2dd4bf;     /* PUBLISHED            fa-circle-check */
  --status-neutral: var(--text-muted);

  /* ---- Elevation -------------------------------------------------------------------- */
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.15);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3);
  --shadow-card: 0 8px 32px rgba(0, 0, 0, 0.2);
  --shadow-lg: 0 10px 25px rgba(0, 0, 0, 0.5);
  --shadow-xl: 0 20px 50px rgba(0, 0, 0, 0.9);

  /* ---- Motion -----------------------------------------------------------------------
     Named properties only, never "all": a layout or font change must not animate by
     accident. Under prefers-reduced-motion the movement goes and the colour change
     stays (see the end of this file). */
  --ease-out: cubic-bezier(0.2, 0, 0, 1);
  --dur-fast: 150ms;
  --dur-base: 200ms;
  --transition: color var(--dur-base) var(--ease-out),
    background-color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out),
    opacity var(--dur-base) var(--ease-out),
    transform var(--dur-base) var(--ease-out);
}

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

/* Browser surfaces: native controls, scrollbars, selection and caret in the palette. */
:root {
  color-scheme: dark;
  accent-color: var(--primary);
  scrollbar-color: var(--border-hover) transparent;
}

::selection {
  background: var(--primary-tint-strong);
  color: var(--text-main);
}

input,
textarea,
[contenteditable] {
  caret-color: var(--primary);
}

/* ---- Focus ---------------------------------------------------------------------------
   One ring, keyboard only (:focus-visible), on everything interactive. :where() keeps it
   at zero specificity so a component can move the ring (inset inside a scroll strip, onto
   the wrapper of a borderless input) without !important. Nothing removes it without
   drawing a replacement. */
:where(a[href], button, input, select, textarea, summary, [tabindex], [role="button"],
  [role="tab"], [contenteditable="true"]):focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
}

/* Visually hidden, still read by screen readers. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

body {
  font-family: var(--font-family);
  background-color: var(--bg-main);
  color: var(--text-main);
  overflow: hidden;
  height: 100vh;
  -webkit-font-smoothing: antialiased;
}

/* App Container Layout */
.app-container {
  display: flex;
  height: 100vh;
  width: 100vw;
}

/* Sidebar Navigation */
.sidebar {
  width: 260px;
  flex-shrink: 0;
  background-color: var(--bg-sidebar);
  border-right: 1px solid var(--glass-border);
  display: flex;
  flex-direction: column;
  padding: var(--space-6) var(--space-4);
  overflow: hidden;
  transition: width 0.2s ease, padding 0.2s ease;
}

/* Collapsed icon rail. Toggled via .sidebar-toggle-btn (setupCollapsible in main.js,
   storageKey 'ui.sidebar.open'), state remembered in localStorage like the other
   collapsible sections. */
.sidebar.sidebar-collapsed {
  width: 64px;
  padding-left: var(--space-2);
  padding-right: var(--space-2);
}

.sidebar-brand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-9);
  padding-left: var(--space-2);
}

.sidebar-brand-left {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.sidebar.sidebar-collapsed .sidebar-brand {
  flex-direction: column;
  justify-content: center;
  padding-left: 0;
  margin-bottom: var(--space-6);
}

.sidebar.sidebar-collapsed .brand-text,
.sidebar.sidebar-collapsed .lang-toggle-container {
  display: none;
}

.sidebar-toggle-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--target-min);
  height: var(--target-min);
  flex-shrink: 0;
  background: var(--glass-border);
  border: 1px solid var(--glass-active);
  border-radius: var(--radius-md);
  color: var(--text-muted);
  font-size: var(--icon-sm);
  cursor: pointer;
  transition: var(--transition);
}

.sidebar-toggle-btn:hover {
  background-color: var(--glass-hover);
  color: var(--text-main);
}

/* Language switch (sidebar and sign-in page share it). */
.lang-toggle-container {
  display: flex;
  margin-left: auto;
  padding: var(--space-0-5);
  background: var(--glass-border);
  border: 1px solid var(--glass-active);
  border-radius: var(--radius-md);
}

.lang-toggle-btn {
  min-height: calc(var(--target-min) - 6px);  /* plus the track: a 32px target */
  padding: var(--space-0-5) var(--space-2);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: background-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}

.lang-toggle-btn:hover {
  color: var(--text-main);
}

.lang-toggle-btn.active {
  background: var(--primary);
  color: var(--text-on-accent);
}

.brand-icon {
  width: 42px;
  height: 42px;
  background: linear-gradient(135deg, var(--primary), var(--success));
  border-radius: var(--border-radius);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--icon-lg);
  color: var(--text-on-accent);
  box-shadow: 0 4px 12px var(--primary-glow);
}

.brand-text h2 {
  font-size: var(--fs-heading);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-tight);
}

.brand-text span {
  font-size: var(--fs-caption);
  color: var(--text-muted);
}

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex: 1;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: none;
  border: none;
  border-radius: var(--border-radius);
  color: var(--text-muted);
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  cursor: pointer;
  text-align: left;
  transition: var(--transition);
  position: relative;
  overflow: hidden;
}

.nav-item i {
  font-size: var(--icon-md);
}

.nav-item:hover {
  background-color: var(--glass-hover);
  color: var(--text-main);
}

.nav-item.active {
  background-color: var(--primary-tint);
  color: var(--primary);
  font-weight: var(--fw-semibold);
}

.nav-item.active::before {
  content: '';
  position: absolute;
  left: 0;
  top: 15%;
  height: 70%;
  width: 3px;
  background-color: var(--primary);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.nav-item .badge {
  margin-left: auto;
  background-color: var(--glass-active);
  color: var(--text-main);
  font-size: var(--fs-caption);
  font-variant-numeric: tabular-nums;
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--border-radius);
  border: 1px solid var(--glass-border);
}

.sidebar-footer {
  border-top: 1px solid var(--glass-border);
  padding-top: var(--space-4);
}

.status-indicator {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-caption);
  color: var(--text-muted);
}

/* Collapsed icon rail: hide labels/badges, center the icons, keep tooltips (title/
   aria-label on each nav item) as the only way to identify them. */
.sidebar.sidebar-collapsed .nav-item {
  justify-content: center;
  padding: var(--space-3) 0;
  gap: 0;
}

.sidebar.sidebar-collapsed .nav-item span {
  display: none;
}

.sidebar.sidebar-collapsed .sidebar-footer {
  display: flex;
  justify-content: center;
}

/* Main Content Area */
.main-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* App bar. Below 900px it is a real bar (menu button, brand mark, view title); on
   desktop it dissolves into its h1, which stays for screen readers only. The phone
   rules are in "Responsive shell" at the end of this file. */
.app-topbar {
  display: contents;
}

.topbar-menu-btn,
.topbar-brand,
.sidebar-close-icon,
.editor-backbar {
  display: none;
}

/* The h1 (.view-title) is .sr-only on desktop; below 900px the app bar shows it. */

/* Behind the open drawer; [hidden] keeps it out of the way the rest of the time. */
.sidebar-scrim {
  position: fixed;
  inset: 0;
  z-index: 899;
  background: var(--scrim-image);
}

.sidebar-scrim[hidden] {
  display: none;
}

/* Glassmorphism Cards */
.glass-card {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--border-radius-lg);
  backdrop-filter: blur(15px);
  box-shadow: var(--shadow-card);
  transition: var(--transition);
}

/* View Container */
.view-container {
  flex: 1;
  padding: var(--space-8);
  overflow-y: auto;
}

.tab-view {
  display: none;
  animation: fadeIn 0.3s ease-out;
}

.tab-view.active {
  display: block;
}

/* Dashboard Tab Styles */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-5);
  margin-bottom: var(--space-8);
}

.stat-card {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-5);
}

.stat-icon {
  width: 50px;
  height: 50px;
  border-radius: var(--border-radius);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--icon-lg);
  color: var(--text-on-fill);
}

/* Dashboard tiles keep their own gradient pairs: decorative, no text on them. */
.stat-icon.bg-blue {
  background: linear-gradient(135deg, #3b82f6, #1d4ed8);
  box-shadow: 0 4px 12px var(--primary-glow);
}

.stat-icon.bg-yellow {
  background: linear-gradient(135deg, var(--warning), #b45309);
  box-shadow: 0 4px 12px var(--warning-glow);
}

.stat-icon.bg-orange {
  background: linear-gradient(135deg, #f97316, #c2410c);
  box-shadow: 0 4px 12px var(--warning-glow);
}

.stat-icon.bg-green {
  background: linear-gradient(135deg, #10b981, #047857);
  box-shadow: 0 4px 12px var(--success-glow);
}

.stat-info h3 {
  font-size: var(--fs-control);
  font-weight: var(--fw-medium);
  color: var(--text-muted);
  margin-bottom: var(--space-1);
}

.stat-value {
  font-size: var(--fs-display);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-tight);
  font-variant-numeric: tabular-nums;
}

.dashboard-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
}

.card-header {
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid var(--glass-border);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-header h2 {
  font-size: var(--fs-title);
  font-weight: var(--fw-semibold);
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
}

.card-header-actions {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

.card-body {
  padding: var(--space-6);
}

.card-body.is-flush {
  padding: 0;
}

/* Forms & Inputs */
.modern-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.form-group label {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--text-muted);
}

/* A field's own heading row: label on the left, a small action (Prompt) on the right. */
.field-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-1-5);
}

.field-head label {
  margin-bottom: 0;
}

/* Section label inside a form group, a step up from the field label. */
.form-group .field-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
  font-weight: var(--fw-semibold);
}

.form-group .field-title.is-accent {
  color: var(--primary);
}

.form-group.is-spaced {
  margin-top: var(--space-4);
}

.form-input, .form-select, .form-textarea {
  background-color: var(--surface-input);
  border: 1px solid var(--glass-border);
  border-radius: var(--border-radius);
  color: var(--text-main);
  padding: var(--space-3) var(--space-4);
  font-size: var(--fs-body);
  transition: var(--transition);
  font-family: var(--font-family);
}

.form-input::placeholder, .form-textarea::placeholder {
  color: var(--text-dark);
}

/* Focus by any input method moves the border to the accent; the keyboard ring from
   "Focus" above sits outside it. */
.form-input:focus, .form-select:focus, .form-textarea:focus {
  border-color: var(--primary);
}

.form-textarea {
  resize: vertical;
  min-height: 240px;
}

.form-textarea.short {
  min-height: 90px;
}

.form-textarea.is-tall {
  height: 300px;
}

.form-textarea.is-medium {
  height: 100px;
  min-height: 100px;
}

/* Compact select for dense toolbars (bulk actions). */
.form-select.form-select-compact {
  width: auto;
  height: auto;
  min-height: var(--control-h-sm);
  margin: 0;
  padding: var(--space-1) var(--space-2);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  border-radius: var(--radius-md);
  cursor: pointer;
}

/* Two fields side by side (title + subtitle). */
.form-row-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  margin-bottom: var(--space-3);
}

.form-row-split > .form-group {
  margin-bottom: 0;
}

/* Spacing between stacked editor blocks that are not inside a .modern-form. */
.editor-block {
  margin-bottom: var(--space-4);
}

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-2-5) var(--space-4);
  border: none;
  border-radius: var(--border-radius);
  font-size: var(--fs-control);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  transition: var(--transition);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Bright fills carry dark text: white on #2ecc71 was 2.1:1. */
.btn-primary {
  background-color: var(--primary);
  color: var(--text-on-accent);
}
.btn-primary:hover {
  background-color: var(--primary-hover);
  box-shadow: 0 4px 12px var(--primary-glow);
}

.btn-success {
  background-color: var(--success);
  color: var(--text-on-accent);
}
.btn-success:hover {
  background-color: var(--success-hover);
  box-shadow: 0 4px 12px var(--success-glow);
}

.btn-warning {
  background-color: var(--warning);
  color: var(--text-on-accent);
}
.btn-warning:hover {
  background-color: var(--warning-hover);
  box-shadow: 0 4px 12px var(--warning-glow);
}

.btn-danger {
  background-color: var(--danger-fill);
  color: var(--text-on-fill);
}
.btn-danger:hover {
  background-color: var(--danger-fill-hover);
  box-shadow: 0 4px 12px var(--danger-glow);
}

.btn-secondary {
  background-color: var(--glass-active);
  color: var(--text-main);
  border: 1px solid var(--glass-border);
}
.btn-secondary:hover {
  background-color: var(--glass-hover);
}

/* Quiet outline button: section toggles inside the editor. */
.btn-quiet {
  background: var(--glass-subtle);
  color: var(--text-main);
  border: 1px solid var(--glass-active);
  border-radius: var(--radius-md);
  padding: var(--space-1-5) var(--space-3);
  min-height: var(--control-h-sm);
  font-size: var(--fs-control);
}
.btn-quiet:hover {
  background: var(--border-subtle);
  border-color: var(--border-hover);
}
.btn-quiet i {
  transition: transform 0.2s ease;
}
.form-group > .btn-quiet {
  align-self: flex-start;
  margin-bottom: var(--space-2);
}

/* Small tinted action chip (copy / regenerate HTML). */
.btn-chip {
  --chip: var(--primary);
  min-height: var(--control-h-sm);
  padding: var(--space-1) var(--space-2-5);
  gap: var(--space-1);
  border-radius: var(--radius-md);
  font-size: var(--fs-caption);
  background: color-mix(in srgb, var(--chip) 15%, transparent);
  color: var(--chip);
  border: 1px solid color-mix(in srgb, var(--chip) 35%, transparent);
}
.btn-chip:hover {
  background: color-mix(in srgb, var(--chip) 25%, transparent);
}
.btn-chip.is-info {
  --chip: var(--info);
}

.btn-sm {
  min-height: var(--control-h-sm);
  padding: var(--space-1-5) var(--space-3);
  font-size: var(--fs-caption);
}

.btn-row {
  display: flex;
  gap: var(--space-2);
}

.action-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

.w-100 {
  width: 100%;
}

/* Custom checkbox: an 18px drawn box inside a 32px hit area. Native boxes were
   15px targets. Used by the article rows and the bulk select-all. */
.article-select-checkbox,
.check-target {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  flex-shrink: 0;
  width: var(--target-min);
  height: var(--target-min);
  margin: 0;
  border-radius: var(--radius-md);
  background: transparent;
  cursor: pointer;
}

.article-select-checkbox::before,
.check-target::before {
  content: '';
  position: absolute;
  inset: calc((var(--target-min) - var(--checkbox-size)) / 2);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-sm);
  background: var(--surface-input);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.article-select-checkbox:hover::before,
.check-target:hover::before {
  border-color: var(--primary);
}

.article-select-checkbox:checked::before,
.check-target:checked::before {
  background: var(--primary);
  border-color: var(--primary);
}

.article-select-checkbox:checked::after,
.check-target:checked::after {
  content: '';
  position: absolute;
  /* Centred in the hit area (13px / 9px at 32px), so it follows --target-min on touch. */
  left: calc(var(--target-min) / 2 - 3px);
  top: calc(var(--target-min) / 2 - 7px);
  width: 6px;
  height: 11px;
  border: solid var(--text-on-accent);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.article-select-checkbox:focus-visible,
.check-target:focus-visible {
  outline-offset: var(--focus-ring-inset);
}

/* Activity List */
.activity-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-height: 300px;
  overflow-y: auto;
}

.activity-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--fs-control);
  padding: var(--space-2-5);
  border-radius: var(--radius-lg);
  background-color: var(--glass-bg);
}

.activity-item.empty {
  justify-content: center;
  color: var(--text-dark);
}

/* Articles Layout */
.articles-layout {
  display: flex;
  gap: 0;
  /* Was 100vh - 160px, which budgeted for the now-removed 70px .top-header row;
     dropping the header reclaims that height for the editor. */
  height: calc(100vh - 90px);
}

.articles-list-panel {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  width: 40%;
  min-width: 300px;
  max-width: 60%;
  flex-shrink: 0;
}

.panel-header {
  padding: var(--space-4);
  border-bottom: 1px solid var(--glass-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.search-row {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
}

.search-row > .search-bar {
  flex: 1;
}

.search-row > .btn {
  flex-shrink: 0;
}

.search-bar {
  display: flex;
  align-items: center;
  background-color: var(--surface-input);
  border: 1px solid var(--glass-border);
  border-radius: var(--border-radius);
  padding: var(--space-2-5) var(--space-4);
  gap: var(--space-2-5);
  color: var(--text-muted);
}

.search-bar:focus-within {
  border-color: var(--primary);
}

.search-bar:has(input:focus-visible) {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
}

/* Replaced by the ring on the pill around it (above). */
.search-bar input:focus-visible {
  outline: none;
}

.search-bar input {
  background: none;
  border: none;
  color: var(--text-main);
  width: 100%;
  font-size: var(--fs-body);
}

.search-bar input::placeholder {
  color: var(--text-dark);
}

/* Chip rows: the status filter and the per-source toggles. Each keeps to one line and
   scrolls sideways (wrapped, the seven status chips took three rows of the list header
   at desktop width). No native scrollbar: responsive.js marks the end(s) with more
   chips past them (data-fade), that edge fades out instead, and a vertical mouse wheel
   scrolls the row. */
/* The padding / negative-margin pair gives the outward focus ring room inside the
   scroller (overflow-x: auto clips on both axes) without moving the chips. */
.filter-bar {
  --strip-fade: var(--space-6);
  display: flex;
  gap: var(--space-1-5);
  padding: var(--space-1);
  margin: calc(var(--space-1) * -1);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}

.filter-bar::-webkit-scrollbar {
  display: none;
}

/* Only the mask's alpha is used, so its colour is irrelevant. */
.filter-bar[data-fade="end"],
.tabs-editor-nav[data-fade="end"] {
  mask-image: linear-gradient(to right, black calc(100% - var(--strip-fade)), transparent);
}

.filter-bar[data-fade="start"],
.tabs-editor-nav[data-fade="start"] {
  mask-image: linear-gradient(to left, black calc(100% - var(--strip-fade)), transparent);
}

.filter-bar[data-fade="both"],
.tabs-editor-nav[data-fade="both"] {
  mask-image: linear-gradient(to right, transparent, black var(--strip-fade),
    black calc(100% - var(--strip-fade)), transparent);
}

/* Status filter chips. --status is the chip's hue: it colours the icon at rest and
   becomes the fill when the chip is active, with dark text on top (white on green
   was 2.4:1 at 11px). "All" uses the brand green. */
.filter-btn {
  --status: var(--primary);
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  flex-shrink: 0;
  min-height: var(--control-h-sm);
  padding: 0 var(--space-3-5);
  background: none;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  color: var(--text-muted);
  font-family: var(--font-family);
  font-size: var(--fs-control);
  font-weight: var(--fw-medium);
  cursor: pointer;
  transition: var(--transition);
  white-space: nowrap;
}

.filter-btn i {
  color: var(--status);
  font-size: var(--icon-sm);
}

.filter-btn:hover {
  background-color: var(--glass-hover);
  border-color: var(--border-strong);
  color: var(--text-main);
}

.filter-btn.active {
  background-color: var(--status);
  border-color: var(--status);
  color: var(--text-on-accent);
  font-weight: var(--fw-semibold);
}

.filter-btn.active i {
  color: inherit;
}

.filter-btn[data-filter="PENDING_TRANSLATION"] { --status: var(--status-translation); }
.filter-btn[data-filter="PENDING_REVIEW"]      { --status: var(--status-review); }
.filter-btn[data-filter="FOR_CONSIDERATION"]   { --status: var(--status-consideration); }
.filter-btn[data-filter="NOT_RELEVANT"]        { --status: var(--status-irrelevant); }
.filter-btn[data-filter="SENT_TO_CMS"]         { --status: var(--status-sent); }
.filter-btn[data-filter="PUBLISHED"]           { --status: var(--status-published); }

/* Per-source toggles: lit = shown, struck through = hidden. Tinted rather than filled
   so they read as on/off switches, apart from the single-choice status chips above. */
#source-filter-bar {
  margin-top: calc(var(--space-1) * -1);
}

.source-filter-btn {
  gap: var(--space-1);
  padding: 0 var(--space-3);
  font-size: var(--fs-caption);
}

.source-filter-btn i {
  color: inherit;
  font-size: var(--icon-sm);
}

.source-filter-btn .chip-count {
  margin-left: var(--space-0-5);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.source-filter-btn.active {
  background-color: var(--success-tint);
  border-color: var(--success-border);
  color: var(--text-main);
  font-weight: var(--fw-medium);
}

.source-filter-btn:not(.active) {
  color: var(--text-dark);
  text-decoration: line-through;
}

.panel-body {
  flex: 1;
  overflow-y: auto;
}

.articles-list-container {
  display: flex;
  flex-direction: column;
}

/* Loading and empty messages in the list. */
.list-loading {
  text-align: center;
  padding: var(--space-8);
  color: var(--text-soft);
  font-size: var(--fs-control);
}

/* The Articles list's loading / empty / error states: icon, one sentence, and the
   way out (retry, clear search) when there is one. */
.list-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-8) var(--space-4);
  color: var(--text-soft);
  font-size: var(--fs-control);
  line-height: var(--lh-normal);
  text-align: center;
}

.list-state-icon {
  font-size: var(--icon-lg);
  color: var(--text-dark);
}

.list-state.is-error .list-state-icon {
  color: var(--danger);
}

.list-state-title {
  color: var(--text-main);
  font-weight: var(--fw-semibold);
}

.list-state-detail {
  max-width: 40ch;
  color: var(--text-muted);
  font-size: var(--fs-caption);
  overflow-wrap: anywhere;
}

.list-state .btn {
  margin-top: var(--space-2);
}

/* "Showing n/m" under the list, and the load-more button above it. */
.list-counter {
  padding: var(--space-2) var(--space-4) var(--space-6);
  color: var(--text-muted);
  font-size: var(--fs-caption);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.btn.list-load-more {
  width: calc(100% - 2 * var(--space-4));
  margin: var(--space-3) var(--space-4) var(--space-1);
}

.bulk-actions-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background: var(--surface-overlay);
  border-bottom: 1px solid var(--glass-border);
  backdrop-filter: blur(8px);
  position: sticky;
  top: 0;
  z-index: 15;
  transition: var(--transition);
  animation: slideDown 0.2s ease-out;
}

.bulk-actions-bar.hidden {
  display: none !important;
}

.bulk-actions-group {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.bulk-selected-count {
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  color: var(--text-main);
  font-variant-numeric: tabular-nums;
}

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

/* Row checkbox sits in the card's top-left; the 32px hit area is pulled back into
   the card padding so the row keeps its alignment. */
.article-select-checkbox {
  margin: calc(var(--space-1-5) * -1) var(--space-1-5) 0 calc(var(--space-1-5) * -1);
}

/* Article List Item */
.article-item-card {
  display: flex;
  align-items: flex-start;
  padding: var(--space-4);
  border-bottom: 1px solid var(--glass-border);
  cursor: pointer;
  transition: var(--transition);
}

.article-item-card:hover {
  background-color: var(--glass-hover);
}

.article-item-card.selected {
  background-color: var(--primary-tint);
  border-left: 3px solid var(--primary);
}

/* Wraps so a narrow list drops the status badge under the source tag instead of
   clipping it at the card edge. */
.card-top-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-1-5);
  margin-bottom: var(--space-2);
}

.site-tag {
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--primary);
}

/* Status badge: Font Awesome icon + label, tinted from the status hue. The same
   classes land on the editor's status <select> (editorPanel.js), styled below. */
.status-badge {
  --status: var(--status-neutral);
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  flex-shrink: 0;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--status);
  background-color: color-mix(in srgb, var(--status) 14%, transparent);
  white-space: nowrap;
}

.status-badge i {
  font-size: 0.9em;
}

.status-badge.pending_translation { --status: var(--status-translation); }
.status-badge.pending_review      { --status: var(--status-review); }
.status-badge.for_consideration   { --status: var(--status-consideration); }
.status-badge.not_relevant        { --status: var(--status-irrelevant); }
.status-badge.pending_cms_upload  { --status: var(--status-cms-queued); }
.status-badge.cms_uploading       { --status: var(--status-cms-uploading); }
.status-badge.sent_to_cms         { --status: var(--status-sent); }
.status-badge.published           { --status: var(--status-published); }

/* Text column beside the thumbnail. min-width: 0 lets a long title wrap instead of
   pushing the thumbnail off the card. */
.card-main-content {
  flex: 1;
  min-width: 0;
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
}

.card-text {
  flex: 1;
  min-width: 0;
}

.card-tags {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-1-5);
}

/* Triage tier: dark text on the bright fills, white on the deep red. */
.priority-mini-badge {
  margin-left: var(--space-2);
  padding: var(--space-0-5) var(--space-1-5);
  border-radius: var(--radius-sm);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  white-space: nowrap;
}

.priority-mini-badge.tier-1 { background: var(--danger-fill); color: var(--text-on-fill); }
.priority-mini-badge.tier-2 { background: var(--warning); color: var(--text-on-accent); }
.priority-mini-badge.tier-3 { background: var(--primary); color: var(--text-on-accent); }

.card-title-text {
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  margin-bottom: var(--space-2);
  overflow-wrap: anywhere;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.card-title-text:focus-visible {
  border-radius: var(--radius-sm);
}

.card-meta-row {
  font-size: var(--fs-caption);
  color: var(--text-dark);
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  font-variant-numeric: tabular-nums;
}

.article-item-card .card-meta-row {
  margin-top: var(--space-1-5);
}

/* The AI's one-line reason, under the title. */
.card-triage-reason {
  margin-top: var(--space-1-5);
  padding: var(--space-1) var(--space-2);
  background: var(--glass-subtle);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-size: var(--fs-caption);
  line-height: var(--lh-snug);
  overflow-wrap: anywhere;
}

.card-triage-reason i {
  margin-right: var(--space-1);
  color: var(--info);
}

.card-thumbnail-container {
  flex-shrink: 0;
  width: 80px;
  height: 60px;
  margin-top: var(--space-1);
  overflow: hidden;
  background: var(--glass-subtle);
  border: 1px solid var(--glass-active);
  border-radius: var(--radius-md);
}

.card-thumbnail-container img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Editor Panel */
.articles-editor-panel {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  flex: 1;
  min-width: 400px;
}

.editor-empty-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--text-dark);
  text-align: center;
  padding: var(--space-8);
  gap: var(--space-3);
}

.editor-empty-state i {
  font-size: var(--icon-xl);
}

.editor-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.editor-header {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--glass-border);
}

.editor-header-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-5);
}

.editor-header-main {
  flex: 1;
  min-width: 0;
}

.edit-status-container {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.edit-status-label {
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-caps);
  color: var(--text-muted);
  text-transform: uppercase;
}

/* The status <select>. editorPanel.js rewrites its className to
   "form-select status-select-dropdown status-badge <status>", so the status hue comes
   from .status-badge; this rule only restores select geometry over the badge's. */
.form-select.status-select-dropdown {
  display: inline-block;
  width: auto;
  min-height: var(--control-h-sm);
  margin: 0;
  padding: var(--space-1) var(--space-3);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  border-radius: var(--radius-sm);
  border-color: color-mix(in srgb, var(--status, var(--text-muted)) 35%, transparent);
  cursor: pointer;
}

.form-select.status-select-dropdown option {
  background: var(--surface-raised);
  color: var(--text-main);
}

.status-tag {
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  background-color: var(--glass-active);
  padding: var(--space-1) var(--space-2-5);
  border-radius: var(--radius-pill);
  display: inline-block;
  margin-bottom: var(--space-1-5);
}

.editor-header h2 {
  font-size: var(--fs-title);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  margin-bottom: var(--space-1-5);
  overflow-wrap: anywhere;
  text-wrap: pretty;
}

.editor-header h2.editor-title {
  margin-top: var(--space-2);
}

.meta-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2-5);
  font-size: var(--fs-caption);
  color: var(--text-muted);
}

.meta-row a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  /* No min-height with a mouse: the row's 10px gaps meet WCAG 2.5.8's spacing rule,
     and every pixel here comes out of the article body. 44px on a coarse pointer. */
  color: var(--primary);
  text-decoration: none;
}

.meta-row a:hover {
  color: var(--primary-text-hover);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* AI triage summary under the editor title. */
.triage-info-row {
  margin-top: var(--space-3);
  padding: var(--space-3);
  background: var(--primary-tint);
  border: 1px solid var(--primary-border);
  border-radius: var(--radius-md);
  font-size: var(--fs-control);
}

.triage-info-head {
  display: flex;
  align-items: center;
  gap: var(--space-3-5);
  margin-bottom: var(--space-1-5);
}

/* editorPanel.js adds tier-1/2/3; same fills as the list's .priority-mini-badge. */
.status-badge.triage-priority-badge {
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-pill);
  font-weight: var(--fw-semibold);
}

.status-badge.triage-priority-badge.tier-1 { background: var(--danger-fill); color: var(--text-on-fill); }
.status-badge.triage-priority-badge.tier-2 { background: var(--warning); color: var(--text-on-accent); }
.status-badge.triage-priority-badge.tier-3 { background: var(--primary); color: var(--text-on-accent); }

.triage-suggestion {
  font-weight: var(--fw-semibold);
}

.triage-reason {
  color: var(--text-muted);
  font-style: italic;
  line-height: var(--lh-snug);
}

/* No vertical padding here: this is the sticky scroll container for the CKEditor
   toolbar, and Blink anchors sticky offsets to the content box. Any padding-top
   parks the toolbar that far below the tab bar and lets content scroll through
   the gap. The inset lives on .tab-edit-view instead. */
.editor-body {
  flex: 1;
  overflow-y: auto;
  padding: 0;
}

.tabs-editor-nav {
  display: flex;
  border-bottom: 1px solid var(--glass-border);
  gap: var(--space-4);
  padding: 0 var(--space-6);
  background-color: var(--bg-sidebar);
  z-index: 10;
}

.tab-edit-btn {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: var(--fs-control);
  font-weight: var(--fw-semibold);
  padding: var(--space-2-5) var(--space-1);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: var(--transition);
}

.tab-edit-btn:hover {
  color: var(--text-main);
}

.tab-edit-btn:focus-visible {
  outline-offset: var(--focus-ring-inset);
  border-radius: var(--radius-sm);
}

.tab-edit-btn.active {
  color: var(--primary);
  border-bottom-color: var(--primary);
}

.tab-edit-view {
  display: none;
}

/* Each panel is a column on one rhythm (the Original tab's fields used to touch). At
   600px and up the article body field also takes whatever height is left, down to
   the gallery bar ("Body fills the panel" below). */
.tab-edit-view.active {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-6);
}

.tab-edit-view .editor-block,
.tab-edit-view .form-row-split {
  margin-bottom: 0;
}

#editor-fields-standard,
#editor-fields-photo {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.tab-edit-view .form-group > .btn-quiet {
  margin-bottom: 0;
}

/* Body fills the panel. Fields above keep their natural height; the body field takes
   the rest (min 240px) and scrolls inside itself. Pure flex, so it follows window
   resizes and the gallery opening. Below 600px the editor scrolls as one page and
   the body keeps its natural height. */
@media (min-width: 600px) {
  .editor-body {
    display: flex;
    flex-direction: column;
  }

  .tab-edit-view.active {
    flex: 1 0 auto;
  }

  .editor-fill {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .form-textarea.is-fill {
    flex: 1 1 0;
    min-height: 240px;
    height: auto;
    resize: none;
  }

  #web-ckeditor-container > .ck-editor {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
  }

  #web-ckeditor-container .ck-editor__main {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
  }

  /* Unlike the textareas, the rich editor grows with a long article (basis auto) so the
     panel keeps one scrollbar and the toolbar stays pinned; a short one fills the rest. */
  #web-ckeditor-container .ck-editor__main > .ck-editor__editable {
    flex: 1 0 auto;
    min-height: 240px !important;
  }
}

/* "Prompt" toggle beside a field label, and the per-field custom prompt it opens.
   main.js recolours the toggle inline while its prompt is open. */
.btn-prompt-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  min-height: var(--target-min);
  padding: 0;
  background: none;
  border: none;
  color: var(--primary);
  font-size: var(--fs-control);
  cursor: pointer;
}

.btn-prompt-toggle:hover,
.btn-prompt-toggle[aria-expanded="true"] {
  color: var(--primary-text-hover);
}

.form-textarea.prompt-textarea {
  height: 60px;
  min-height: 60px;
  margin-bottom: var(--space-2);
  padding: var(--space-2);
  font-size: var(--fs-control);
  background: var(--primary-tint);
  border: 1px dashed var(--primary-border);
  color: var(--primary);
}

.prompt-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: calc(var(--space-1) * -1);
  margin-bottom: var(--space-2);
}

.btn-apply-prompt {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  min-height: var(--control-h-sm);
  padding: var(--space-1) var(--space-2-5);
  background: var(--primary-tint);
  color: var(--primary);
  border: 1px solid var(--primary-border);
  border-radius: var(--radius-sm);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  cursor: pointer;
}

.btn-apply-prompt:hover {
  background: var(--primary-tint-strong);
}

.czech-content {
  background-color: var(--glass-bg);
  border: 1px solid var(--glass-border);
  padding: var(--space-4);
  border-radius: var(--border-radius);
}

.czech-content h4 {
  margin-bottom: var(--space-3);
}

.czech-body-text {
  font-size: var(--fs-control);
  line-height: var(--lh-relaxed);
  white-space: pre-wrap;
  color: var(--text-muted);
}

/* Website tab: selected categories, autocomplete, available-category grid. */
.category-picker {
  position: relative;
  margin-bottom: var(--space-3);
}

.selected-categories-tags-container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  min-height: 48px;
  padding: var(--space-3);
  background: var(--glass-bg);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  cursor: text;
}

.selected-categories-tags-container:focus-within {
  border-color: var(--primary);
}

.selected-categories-tags-container:has(.category-search-input:focus-visible) {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
}

/* Replaced by the ring on the tag box around it (above). */
.category-search-input:focus-visible {
  outline: none;
}

.category-search-input {
  flex: 1;
  min-width: 120px;
  background: transparent;
  border: none;
  color: var(--text-main);
  font-size: var(--fs-control);
}

.category-search-input::placeholder {
  color: var(--text-dark);
}

.no-categories-placeholder {
  color: var(--text-muted);
  font-size: var(--fs-caption);
  font-style: italic;
}

/* categories.js shows/hides this with an inline display. */
.autocomplete-dropdown {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin-top: var(--space-1);
  max-height: 180px;
  overflow-y: auto;
  z-index: 1000;
  background: var(--surface-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}

/* Starts closed; collapse.js writes the inline display from the remembered state. */
.collapsible-region {
  display: none;
}

#available-categories-wrapper {
  margin-bottom: var(--space-3);
}

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

.media-item {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius-lg);
  border: 1px solid var(--glass-border);
}

/* Cover image preview + URL on one row. */
.cover-row {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: var(--space-3);
  align-items: center;
}

.cover-preview {
  position: relative;
  width: 140px;
  height: 90px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--glass-subtle);
  border: 1px solid var(--glass-active);
  border-radius: var(--radius-md);
}

/* editorPanel.js toggles the image and the placeholder with an inline display. */
.cover-preview-img {
  display: none;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cover-placeholder {
  color: var(--text-dark);
  font-size: var(--fs-caption);
  font-style: italic;
}

.raw-html-wrapper {
  width: 100%;
  margin-top: var(--space-2);
}

.form-textarea.code-textarea {
  width: 100%;
  height: 260px;
  padding: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--fs-control);
  line-height: var(--lh-normal);
  background: var(--surface-code);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-md);
}

/* Facebook tab. editorPanel.js sets the audit result as is-ok / is-warn / is-error. */
.resolution-audit {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-2-5);
  margin-bottom: var(--space-3);
  border: 1px solid var(--glass-active);
  border-radius: var(--radius-md);
  background: var(--glass-subtle);
  color: var(--text-muted);
  font-size: var(--fs-control);
  font-weight: var(--fw-medium);
  font-variant-numeric: tabular-nums;
}

.resolution-audit.is-ok {
  background: var(--success-tint);
  border-color: var(--success-border);
  color: var(--success);
}

.resolution-audit.is-warn {
  background: var(--warning-tint);
  border-color: color-mix(in srgb, var(--warning) 40%, transparent);
  color: var(--warning);
}

.resolution-audit.is-error {
  background: var(--danger-tint);
  border-color: var(--danger-border);
  color: var(--danger);
}

/* No cover image: a local empty state in the post's 1.91:1 frame, no placeholder
   service request. */
.fb-cover-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 100%;
  max-width: 600px;
  aspect-ratio: 1.91 / 1;
  padding: var(--space-5);
  background: var(--glass-subtle);
  border: 1px dashed var(--border-hover);
  border-radius: var(--radius-md);
  color: var(--text-muted);
  font-size: var(--fs-caption);
  line-height: var(--lh-normal);
  text-align: center;
}

.fb-cover-empty[hidden] {
  display: none;
}

.fb-cover-empty i {
  font-size: var(--icon-lg);
  color: var(--text-dark);
}

.fb-cover-empty strong {
  color: var(--text-soft);
  font-size: var(--fs-control);
  font-weight: var(--fw-semibold);
}

.fb-image-preview {
  max-width: 100%;
  max-height: 350px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-strong);
}

/* Scraped-image gallery block between the editor body and the footer. */
.editor-gallery-section {
  margin: var(--space-3) var(--space-5) 0;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border-subtle);
}

.editor-footer {
  padding: var(--space-1) var(--space-3-5);
  border-top: 1px solid var(--glass-border);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.footer-left,
.footer-right {
  display: flex;
  gap: var(--space-2);
}

/* Shorten the footer/header control row at large OS scaling. The footer buttons get
   their own tighter padding (labels stay readable at the 12px floor, no icon-only
   buttons) since the row has five of them and needs to be as short as possible; the
   header buttons keep the vertical-only trim they already had.
   .collapse-toggle-inline is excluded in the header so its own already-compact
   vertical padding (see the collapse-toggle rules below) isn't overridden by this
   higher-specificity selector. */
.editor-footer button {
  min-height: var(--control-h-sm);  /* the row stays short; the targets stay 32px */
  padding: var(--space-1) var(--space-2-5);
  font-size: var(--fs-caption);
  gap: var(--space-1-5);
}

.editor-header button:not(.collapse-toggle-inline) {
  padding-top: var(--space-1);
  padding-bottom: var(--space-1);
}

@media (max-height: 900px) {
  .editor-header {
    padding: var(--space-2) var(--space-3);
  }

  .editor-header h2 {
    font-size: var(--fs-body);
  }

  .editor-footer {
    padding: var(--space-1) var(--space-2-5);
  }

  .editor-footer button {
    padding: var(--space-0-5) var(--space-2);
  }
}

.hidden {
  display: none !important;
}

/* n8n Tab styles */
.n8n-layout {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.n8n-status-card {
  padding: var(--space-6);
}

.n8n-status-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-3);
}

.n8n-badge {
  font-weight: var(--fw-bold);
  font-size: var(--fs-title);
  color: var(--primary);
}

.connection-status {
  font-size: var(--fs-caption);
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
}

.connection-status .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: var(--text-dark);
}

.connection-status.active .dot {
  background-color: var(--success);
  box-shadow: 0 0 6px var(--success);
}

.connection-status.inactive .dot {
  background-color: var(--danger);
  box-shadow: 0 0 6px var(--danger);
}

.n8n-desc {
  font-size: var(--fs-control);
  color: var(--text-muted);
  line-height: var(--lh-normal);
}

/* Modern Tables */
.table-responsive {
  width: 100%;
  overflow-x: auto;
}

.modern-table {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
  font-size: var(--fs-control);
}

.modern-table th {
  padding: var(--space-3) var(--space-4);
  font-weight: var(--fw-semibold);
  color: var(--text-muted);
  border-bottom: 1px solid var(--glass-border);
}

.modern-table th.cell-center {
  text-align: center;
}

.modern-table td {
  padding: var(--space-4);
  border-bottom: 1px solid var(--glass-border);
}

.table-loading {
  text-align: center;
  color: var(--text-dark);
  padding: var(--space-8);
}

.workflow-status-badge {
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-pill);
  display: inline-block;
}

.workflow-status-badge.active {
  background-color: var(--success-tint);
  color: var(--success);
}

.workflow-status-badge.inactive {
  background-color: var(--glass-border);
  color: var(--text-muted);
}

/* Queue view: three columns of pending sends. */
.queue-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--space-5);
  margin-top: var(--space-2-5);
}

.card-header.queue-card-header {
  justify-content: flex-start;
  gap: var(--space-2-5);
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-3-5);
  border-bottom-color: var(--border-subtle);
}

.queue-card-icon {
  font-size: var(--fs-display);
}

.queue-card-icon.is-translation { color: var(--status-translation); }
.queue-card-icon.is-cms         { color: var(--primary); }
.queue-card-icon.is-fb          { color: var(--info); }

.card-header h2.queue-card-title {
  font-size: var(--fs-heading);
  font-weight: var(--fw-bold);
  margin: 0;
}

.queue-list-container {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-height: 600px;
  overflow-y: auto;
  padding: var(--space-1);
}

/* Settings view */
.settings-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-5);
}

.settings-grid > .is-full {
  grid-column: span 2;
}

.settings-card + .settings-card {
  margin-top: var(--space-6);
}

.form-input.settings-textarea {
  height: 120px;
  font-family: inherit;
  font-size: var(--fs-control);
  line-height: var(--lh-normal);
  resize: vertical;
}

.form-input.settings-textarea.is-tall {
  height: 320px;
}

.settings-note {
  margin: var(--space-1) 0 var(--space-2);
  font-size: var(--fs-caption);
  color: var(--text-dark);
  line-height: var(--lh-normal);
}

.settings-subhead {
  display: block;
  margin-top: var(--space-5);
  font-weight: var(--fw-semibold);
}

.settings-divider {
  border: none;
  border-top: 1px solid var(--glass-border);
  margin: var(--space-6) 0 var(--space-4);
}

.settings-divider + .settings-subhead {
  margin-top: 0;
}

.settings-hint {
  margin: var(--space-1) 0 var(--space-2-5);
  font-size: var(--fs-caption);
  color: var(--text-muted);
}

/* OpenAI usage tiles */
.openai-usage-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
  padding: var(--space-2-5) 0;
  text-align: center;
}

.usage-stat-box {
  padding: var(--space-5);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
}

.usage-stat-label {
  margin-bottom: var(--space-2);
  font-size: var(--fs-control);
  color: var(--text-muted);
}

.usage-stat-value {
  font-size: var(--fs-display);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
}

.usage-stat-value.is-input  { color: var(--primary); }
.usage-stat-value.is-output { color: var(--warning); }
.usage-stat-value.is-spend  { color: var(--danger); font-family: var(--font-mono); }

.usage-breakdown {
  margin-top: var(--space-3);
  font-size: var(--fs-caption);
  color: var(--text-muted);
  line-height: var(--lh-relaxed);
}

.usage-footnote {
  margin-top: var(--space-4);
  font-size: var(--fs-caption);
  color: var(--text-muted);
  text-align: right;
  font-style: italic;
}

.form-actions {
  margin-top: var(--space-6);
  display: flex;
  justify-content: flex-end;
}

/* Toast Container */
.toast-container {
  position: fixed;
  bottom: var(--space-6);
  right: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-2-5);
  z-index: 1000;
}

.toast {
  background-color: var(--surface-toast);
  color: var(--text-main);
  padding: var(--space-4) var(--space-6);
  border-radius: var(--border-radius);
  border-left: 4px solid var(--primary);
  font-size: var(--fs-control);
  font-weight: var(--fw-medium);
  box-shadow: var(--shadow-lg);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  animation: slideIn 0.3s ease-out;
}

.toast.success { border-left-color: var(--success); }
.toast.error { border-left-color: var(--danger); }
.toast.warning { border-left-color: var(--warning); }

@keyframes slideIn {
  from { transform: translateX(100%); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}

.gallery-card {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  cursor: pointer;
  box-shadow: var(--shadow-md);
  transition: transform 0.3s cubic-bezier(0.165, 0.84, 0.44, 1), border-color 0.3s ease, box-shadow 0.3s ease;
}

/* No translateY here: the gallery now lives in a height-capped scroll wrapper and a
   lifted card would just clip against it. */
.gallery-card:hover {
  border-color: var(--primary);
  box-shadow: 0 8px 24px var(--primary-glow);
}

/* Inset: the gallery scrolls inside a height-capped wrapper that clips outward rings. */
.gallery-card:focus-visible {
  outline-offset: var(--focus-ring-inset);
}

.gallery-flag-badge {
  position: absolute;
  top: var(--space-1-5);
  left: var(--space-1-5);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-0-5) var(--space-1-5);
  border-radius: var(--radius-sm);
  background: var(--success);
  color: var(--text-on-accent);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
}

/* "No images" / "couldn't read images" inside the gallery grid. */
.gallery-note {
  grid-column: 1 / -1;
  padding: var(--space-5);
  color: var(--text-muted);
  font-size: var(--fs-caption);
  text-align: center;
}

.gallery-item-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s ease;
}

.gallery-card:hover .gallery-item-img {
  transform: scale(1.08);
}

.gallery-card-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(to top, var(--scrim-image) 0%, var(--scrim-image-fade) 60%);
  opacity: 0;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  padding: var(--space-3);
  transition: opacity 0.3s ease;
}

.gallery-card:hover .gallery-card-overlay {
  opacity: 1;
}

.btn-gallery-action {
  background-color: var(--primary);
  color: var(--text-on-accent);
  border: none;
  padding: var(--space-1-5) var(--space-3);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  border-radius: var(--radius-sm);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  transition: background-color 0.2s ease, transform 0.2s ease;
  box-shadow: 0 2px 8px var(--primary-glow);
}

.btn-gallery-action:hover {
  background-color: var(--primary-hover);
  transform: scale(1.05);
}

/* Tab and modal fade. (Was defined twice; the second, opacity-only one always won.) */
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

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

/* Resize Handle split divider style */
.resize-handle {
  width: 12px;
  cursor: col-resize;
  background: transparent;
  position: relative;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s;
  flex-shrink: 0;
}

.resize-handle::after {
  content: "";
  width: 2px;
  height: 40px;
  background-color: var(--glass-border);
  border-radius: 1px;
  transition: background-color 0.2s, height 0.2s;
}

.resize-handle:hover::after, .resize-handle.active::after {
  background-color: var(--primary);
  height: 60px;
}

.resize-handle:hover {
  background: var(--primary-tint);
}

/* Thumbnail preview link style */
.editor-thumbnail-container {
  flex-shrink: 0;
}

/* A block link, so its focus ring wraps the image rather than one line box. */
#editor-thumbnail-link {
  display: block;
  border-radius: var(--radius-md);
}

.editor-thumbnail-container img {
  width: 120px;
  height: 80px;
  object-fit: cover;
  border-radius: var(--radius-md);
  border: 1px solid var(--glass-border);
  transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.25s, box-shadow 0.25s;
}

.editor-thumbnail-container img:hover {
  border-color: var(--primary);
  transform: scale(1.05);
  box-shadow: 0 4px 12px var(--primary-glow);
}

/* Category tags. Each category class sets one --cat hue (its single definition, the
   data palette below); the pill is a tint of it with a light text mix of the same hue,
   so every category clears 4.5:1 -- white on the bright fills (amber, lime, cyan)
   did not. */
.category-tag-pill,
.category-tag-card {
  --cat: var(--primary);
  background-color: color-mix(in srgb, var(--cat) 22%, transparent);
  color: color-mix(in srgb, var(--cat) 45%, var(--text-main));
  border: 1px solid color-mix(in srgb, var(--cat) 45%, transparent);
}

.category-tag-pill {
  display: inline-block;
  font-size: var(--fs-caption);
  padding: 1px var(--space-1-5);
  border-radius: var(--radius-sm);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  margin-left: var(--space-2);
  white-space: nowrap;
}

/* The editor-header copy of the pill. editorPanel.js rewrites its className, so it is
   addressed by id. */
#edit-category-badge {
  padding: var(--space-0-5) var(--space-2-5);
  border-radius: var(--radius-pill);
  margin-left: var(--space-2);
}

.category-tag-pill.luat-phap { --cat: #6366f1; }
.category-tag-pill.giao-thong { --cat: #f59e0b; }
.category-tag-pill.thoi-tiet { --cat: #06b6d4; }
.category-tag-pill.y-te { --cat: #10b981; }
.category-tag-pill.cu-tru { --cat: #8b5cf6; }
.category-tag-pill.doi-song { --cat: #ec4899; }
.category-tag-pill.an-ninh { --cat: #ef4444; }

/* Selected Categories Tags and Available Grid */
.category-tag-card {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 28px;
  padding: var(--space-1-5) calc(var(--space-6) + var(--space-1)) var(--space-1-5) var(--space-3);
  border-radius: var(--radius-pill);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  transition: var(--transition);
  cursor: default;
  user-select: none;
}

.category-tag-card .remove-category-btn {
  position: absolute;
  top: 50%;
  right: var(--space-0-5);
  transform: translateY(-50%);
  width: var(--space-6);
  height: var(--space-6);
  padding: 0;
  background: var(--scrim-control);
  color: var(--text-main);
  border: none;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  cursor: pointer;
  opacity: 0.7;
  transition: opacity var(--dur-base) var(--ease-out), background-color var(--dur-base) var(--ease-out);
}

/* Dimmed, never invisible: touch and keyboard have no hover to reveal it. */
.category-tag-card:hover .remove-category-btn,
.category-tag-card .remove-category-btn:focus-visible {
  opacity: 1;
}

.category-tag-card .remove-category-btn:hover {
  background: var(--danger-strong);
}

.available-categories-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--space-1) var(--space-2-5);
  max-height: 200px;
  overflow-y: auto;
  padding: var(--space-3);
  background: var(--glass-bg);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

/* The label wraps its checkbox, so the label is the hit area: keep it 32px tall. */
.available-categories-grid label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--target-min);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  color: var(--text-soft);
  cursor: pointer;
  user-select: none;
  transition: color 0.15s ease;
  padding: var(--space-1);
}

.available-categories-grid label:hover {
  color: var(--text-main);
}

.available-categories-grid input[type="checkbox"] {
  cursor: pointer;
  accent-color: var(--primary);
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* Category data palette: one hue per website category. */
.category-tag-card.tin_the_gioi_international { --cat: #3b82f6; }
.category-tag-card.tin_noi_bat_featured { --cat: #ef4444; }
.category-tag-card.tin_tuc_news { --cat: #10b981; }
.category-tag-card.tin_sec_czech_news { --cat: #8b5cf6; }
.category-tag-card.tin_nong_hot_news { --cat: #f97316; }
.category-tag-card.tin_viet_nam_vietnam_news { --cat: #06b6d4; }
.category-tag-card.thoi_su_current_events { --cat: #ec4899; }
.category-tag-card.kinh_te_economy { --cat: #f59e0b; }
.category-tag-card.kinh_te_sec_czech_economy { --cat: #14b8a6; }
.category-tag-card.giai_tri_entertainment { --cat: #6366f1; }
.category-tag-card.cong_dong_vietnamese_community { --cat: #a855f7; }
.category-tag-card.kinh_te_the_gioi_world_economy { --cat: #eab308; }
.category-tag-card.van_hoa_va_du_lich_culture_and_tourism { --cat: #22c55e; }
.category-tag-card.nguoi_viet_tai_sec_vietnamese_people_in_czech { --cat: #d946ef; }
.category-tag-card.nguoi_viet_5_chau_vietnamese_people_around_the_world { --cat: #f43f5e; }
.category-tag-card.kinh_te_viet_nam_vietnam_economy { --cat: #84cc16; }
.category-tag-card.doi_song_va_phap_luat_life_and_law { --cat: #64748b; }
.category-tag-card.star_stars_and_celebrities { --cat: #db2777; }
.category-tag-card.the_thao_sports { --cat: #2563eb; }
.category-tag-card.meo_vat_cuoc_song_life_tips { --cat: #059669; }
.category-tag-card.tamdamedia_v_cestine_tamdamedia_in_czech { --cat: #7c3aed; }
.category-tag-card.tu_vi_va_phong_thuy_horoscope_and_feng_shui { --cat: #d97706; }
.category-tag-card.v_cestine_in_czech { --cat: #4f46e5; }
.category-tag-card.am_thuc_food { --cat: #ea580c; }
.category-tag-card.zajimavosti_interesting_facts { --cat: #0d9488; }
.category-tag-card.vareni_s_tamdou_cooking_with_tamda { --cat: #be185d; }
.category-tag-card.bang_tin_cong_dong_community_news { --cat: #475569; }
.category-tag-card.cestovani_s_tamdou_travel_with_tamda { --cat: #15803d; }
.category-tag-card.vietnamske_tradice_a_zvyky_vietnamske_traditions_and_customs { --cat: #9333ea; }

/* Autocomplete Dropdown Styles */
.autocomplete-option {
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  font-size: var(--fs-control);
  border-bottom: 1px solid var(--glass-border);
  color: var(--text-main);
  transition: background 0.15s;
}

.autocomplete-option:hover, .autocomplete-option.active {
  background-color: var(--primary);
  color: var(--text-on-accent);
}

.btn-meta-blue {
  background-color: var(--brand-facebook);
  color: var(--text-on-fill);
  border-color: var(--brand-facebook);
}

.btn-meta-blue:hover {
  background-color: var(--brand-facebook-hover);
  border-color: var(--brand-facebook-hover);
}

/* Album Gallery Thumbnails (Smaller + Hover Scale Pop-up) */
.media-gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(85px, 1fr));
  gap: var(--space-2-5);
  padding: var(--space-1) 0;
}

/* The gallery sits outside .editor-body, so without a cap it steals editor height
   one grid row at a time as the image count grows. */
#gallery-wrapper {
  /* vh-relative so a short window doesn't hand the gallery a fixed 200px out of an
     already cramped panel -- .editor-body is the only element that yields here. */
  max-height: min(200px, 25vh);
  overflow-y: auto;
  margin-top: var(--space-2);
}

/* Shared collapsible section header (gallery, AI triage, raw HTML, categories). */
.collapse-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-height: var(--control-h-sm);
  background: var(--glass-subtle);
  color: var(--text-main);
  border: 1px solid var(--glass-active);
  border-radius: var(--radius-md);
  padding: var(--space-1-5) var(--space-2-5);
  font-size: var(--fs-control);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  transition: var(--transition);
}

.collapse-toggle:hover {
  background: var(--border-subtle);
  border-color: var(--border-hover);
}

/* Inline variant for the meta row, where the toggle sits beside links. */
.collapse-toggle-inline {
  width: auto;
  /* Deliberate exception to the 32px target: the editor header's metadata row stays
     24px (WCAG 2.5.8 minimum) with a mouse so the article body keeps its height; a
     coarse pointer gets 44px. */
  min-height: 24px;
  padding: var(--space-0-5) var(--space-2);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  border-radius: var(--radius-sm);
}

.collapse-count {
  margin-left: auto;
  background: var(--primary-tint-strong);
  color: var(--primary);
  border-radius: var(--radius-pill);
  padding: 1px var(--space-2);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
}

/* Remembered collapse preference. Kept separate from .hidden so per-article
   show/hide logic and the user's toggle never overwrite each other. */
.collapsed {
  display: none !important;
}

.gallery-image-thumb-card {
  position: relative;
  width: 100%;
  height: 85px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--glass-border);
  border: 1px solid var(--border-strong);
  cursor: pointer;
  transition: transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.22s ease, border-color 0.2s ease;
}

.gallery-image-thumb-card:hover {
  transform: scale(1.22);
  z-index: 50;
  border-color: var(--primary);
  box-shadow: var(--shadow-lg);
}

.gallery-image-thumb-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Article Card Thumbnail Hover Spotlight trigger */
.card-thumbnail-container img, #web-cover-preview, #fb-image-preview {
  cursor: pointer;
  transition: transform 0.2s ease, filter 0.2s ease;
}

.card-thumbnail-container img:hover, #web-cover-preview:hover, #fb-image-preview:hover {
  transform: scale(1.05);
  filter: brightness(1.15);
}

/* Image Spotlight Lightbox Modal */
.image-spotlight-backdrop {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  /* visibility (delayed until the fade ends) takes the closed lightbox's close button
     out of the Tab order; opacity alone left an invisible focus stop. */
  visibility: hidden;
  transition: opacity 0.25s ease, visibility 0s linear 0.25s;
}

.image-spotlight-backdrop.active {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transition: opacity 0.25s ease, visibility 0s;
}

.image-spotlight-content {
  position: relative;
  max-width: 90vw;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  transform: scale(0.95);
  transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.image-spotlight-backdrop.active .image-spotlight-content {
  transform: scale(1);
}

.image-spotlight-close {
  position: absolute;
  top: -42px;
  right: 0;
  background: var(--glass-active);
  border: 1px solid var(--border-hover);
  color: var(--text-main);
  width: 34px;
  height: 34px;
  border-radius: 50%;
  font-size: var(--icon-md);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s ease, transform 0.2s ease;
}

.image-spotlight-close:hover {
  background: var(--danger-strong);
  transform: scale(1.1);
}

.image-spotlight-img {
  max-width: 100%;
  max-height: 80vh;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  object-fit: contain;
  border: 1px solid var(--border-strong);
}

.image-spotlight-caption {
  margin-top: var(--space-3);
  color: var(--text-main);
  font-size: var(--fs-control);
  text-align: center;
  max-width: 750px;
  background: var(--surface-overlay);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid var(--glass-active);
}

/* CKEditor 5 Dark Theme Styling */
.ck.ck-editor {
  width: 100% !important;
}

.ck.ck-editor__main>.ck-editor__editable {
  background-color: var(--surface-editable) !important;
  color: var(--text-main) !important;
  min-height: 280px !important;
  border-color: var(--border-strong) !important;
  border-radius: 0 0 var(--radius-md) var(--radius-md) !important;
  font-family: var(--font-family) !important;
  font-size: var(--fs-body) !important;
  line-height: var(--lh-relaxed) !important;
}

.ck.ck-editor__main>.ck-editor__editable:focus {
  border-color: var(--primary) !important;
  box-shadow: none !important;
}

/* CKEditor clears outlines on its editable; put the shared ring back. */
.ck.ck-editor__main>.ck-editor__editable:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring) !important;
  outline-offset: var(--focus-ring-offset) !important;
}

/* CKEditor's own StickyPanelView never fires here -- it measures against the window
   viewport and Rect.getVisible() clips to .editor-body, so limiterRect.top is never
   negative. This CSS sticky is the real one; it only lands flush because .editor-body
   carries no padding (see the note there). */
.ck.ck-editor__top {
  position: sticky !important;
  top: 0 !important;
  z-index: 10 !important;
}

.ck.ck-toolbar {
  background-color: var(--surface-raised) !important;
  border-color: var(--border-strong) !important;
  border-radius: var(--radius-md) var(--radius-md) 0 0 !important;
}

.ck.ck-toolbar .ck-button {
  color: var(--text-soft) !important;
}

.ck.ck-toolbar .ck-button:hover {
  background-color: var(--glass-active) !important;
  color: var(--text-main) !important;
}

.ck.ck-toolbar .ck-button.ck-on {
  background-color: var(--primary-tint-strong) !important;
  color: var(--primary) !important;
}

.ck.ck-dropdown__panel {
  background-color: var(--surface-raised) !important;
  border-color: var(--border-strong) !important;
}

.ck.ck-list__item .ck-button {
  color: var(--text-main) !important;
}

.ck.ck-list__item .ck-button:hover {
  background-color: var(--primary-tint-strong) !important;
}

/* Hide raw textarea element when CKEditor 5 is initialized */
#web-ckeditor-container textarea#web-ckeditor {
  display: none !important;
}

/* "Loading the editor" / "Couldn't load" note, shown while CKEditor downloads on first
   use (editorPanel.js). Holds the editable's own minimum height, so nothing jumps when
   the editor replaces it, and never shrinks below its content. */
#web-ckeditor-status {
  flex: 1 0 auto;
  min-height: 240px;
  justify-content: center;
}


/* Article Retention settings */
.retention-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  align-items: flex-end;
}

.retention-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 140px;
}

.retention-field.is-wide {
  flex: 2;
  min-width: 260px;
}

.retention-field label {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caps);
  color: var(--text-muted);
  text-transform: uppercase;
}

.retention-field .form-input {
  margin: 0;
}

.retention-switch {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-control);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  padding-bottom: var(--space-2);
}

.retention-switch input {
  width: 16px;
  height: 16px;
  cursor: pointer;
  accent-color: var(--primary);
}

/* One tile per status, so each age limit is visibly tied to what it deletes. */
.retention-status-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: var(--space-2-5);
}

.retention-status-tile {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2-5);
  background: var(--glass-subtle);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-2-5);
}

.retention-status-tile.is-default {
  border-color: var(--success-border);
  background: var(--success-tint);
}

.retention-status-tile .tile-label {
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
  min-width: 0;
}

.retention-status-tile .tile-name {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.retention-status-tile .tile-count {
  font-size: var(--fs-caption);
  color: var(--text-muted);
}

.retention-status-tile input {
  width: 70px;
  flex-shrink: 0;
  text-align: right;
  margin: 0;
}

.purge-status-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1-5);
  max-height: 108px;
  overflow-y: auto;
  padding: var(--space-1-5);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-md);
  background: var(--glass-bg);
}

.purge-status-chip {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  min-height: 28px;
  font-size: var(--fs-caption);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--glass-border);
  border: 1px solid var(--glass-border);
  cursor: pointer;
  user-select: none;
}

.purge-status-chip input {
  accent-color: var(--primary);
  cursor: pointer;
  margin: 0;
}

.purge-status-chip.checked {
  border-color: var(--primary);
  background: var(--primary-tint);
  color: var(--primary);
}

.retention-result {
  margin-top: var(--space-3-5);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  font-size: var(--fs-control);
  line-height: var(--lh-relaxed);
}

.retention-result.is-flush-top {
  margin-top: 0;
}

.retention-result.is-danger {
  border-color: var(--danger-border);
  background: var(--danger-tint);
}

.retention-result.is-success {
  border-color: var(--success-border);
  background: var(--success-tint);
}

/* CMS auto-push */
.autopush-hint {
  font-size: var(--fs-caption);
  color: var(--text-muted);
  margin: 0 0 var(--space-3);
  line-height: var(--lh-normal);
}

.autopush-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: var(--space-2-5);
}

.autopush-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2-5);
  background: var(--glass-subtle);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
}

/* On is the unusual state -- it is the one that sends without asking, so it is the one
   that has to be readable at a glance across a dozen sources. */
.autopush-row.is-on {
  border-color: color-mix(in srgb, var(--status-sent) 45%, transparent);
  background: color-mix(in srgb, var(--status-sent) 8%, transparent);
}

.autopush-row.is-disabled {
  opacity: 0.55;
}

.autopush-source {
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
  min-width: 0;
}

.autopush-source .autopush-name {
  font-size: var(--fs-control);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.autopush-source .autopush-state {
  font-size: var(--fs-caption);
  color: var(--text-muted);
}

.autopush-row input[type="checkbox"] {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin: 0;
  cursor: pointer;
  accent-color: var(--primary);
}

.autopush-row.is-disabled input[type="checkbox"] {
  cursor: not-allowed;
}

/* Translator glossary */
.glossary-hint {
  font-size: var(--fs-caption);
  color: var(--text-muted);
  margin: var(--space-1) 0 var(--space-2);
  line-height: var(--lh-normal);
}

.glossary-hint code {
  background: var(--glass-hover);
  border-radius: var(--radius-sm);
  padding: 1px var(--space-1);
  font-size: var(--fs-caption);
}

.glossary-textarea {
  font-family: var(--font-mono);
  font-size: var(--fs-control);
  line-height: var(--lh-relaxed);
  resize: vertical;
}

.glossary-invalid {
  margin-top: var(--space-2-5);
}

.glossary-invalid-title {
  font-weight: var(--fw-semibold);
  color: var(--danger);
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
}

.glossary-invalid ul {
  margin: var(--space-2) 0 0;
  padding-left: var(--space-4);
}

.glossary-invalid li {
  margin-bottom: var(--space-1);
}

.glossary-invalid code {
  background: var(--danger-tint);
  border-radius: var(--radius-sm);
  padding: 1px var(--space-1-5);
  font-size: var(--fs-caption);
}

/* Recycle bin */
.bin-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
  margin-top: var(--space-3-5);
}

.bin-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2-5) var(--space-3);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  background: var(--glass-bg);
  transition: var(--transition);
}

.bin-item:hover {
  background: var(--glass-border);
}

.bin-item.selected {
  border-color: var(--primary);
  background: var(--primary-tint);
}

.bin-item input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--primary);
  cursor: pointer;
  flex-shrink: 0;
}

.bin-item-main {
  flex: 1;
  min-width: 0;
}

.bin-item-title {
  font-size: var(--fs-control);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bin-item-meta {
  font-size: var(--fs-caption);
  color: var(--text-muted);
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: var(--space-1);
}

/* Marks statuses that n8n polls, so restoring re-runs paid work or re-publishes. */
.bin-pipeline-flag {
  color: var(--warning);
  font-weight: var(--fw-semibold);
}

.bin-countdown {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  flex-shrink: 0;
  text-align: right;
  min-width: 96px;
  font-variant-numeric: tabular-nums;
}

.bin-countdown.is-soon {
  color: var(--danger);
}

/* ---- YouTube episodes (#26). Rows stack as cards so a phone never scrolls sideways. */
.youtube-hint {
  font-size: var(--fs-caption);
  color: var(--text-muted);
  margin: 0 0 var(--space-3);
}

.youtube-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-3-5);
}

.youtube-item {
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
  padding: var(--space-3);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  background: var(--glass-bg);
  min-width: 0;
}

.youtube-item-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.youtube-show {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.youtube-status {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  border: 1px solid var(--glass-border);
}

.youtube-status.is-success {
  border-color: var(--success-border);
  background: var(--success-tint);
}

.youtube-status.is-warning {
  border-color: var(--warning);
  background: var(--warning-tint);
}

.youtube-status.is-danger {
  border-color: var(--danger-border);
  background: var(--danger-tint);
}

.youtube-title {
  font-size: var(--fs-control);
  font-weight: var(--fw-semibold);
  color: var(--text-main);
  overflow-wrap: anywhere;
  min-height: 44px;
  display: flex;
  align-items: center;
}

.youtube-detail {
  font-size: var(--fs-caption);
  color: var(--text-muted);
}

.youtube-times {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  margin: 0;
  font-size: var(--fs-caption);
  color: var(--text-muted);
}

.youtube-times div {
  display: flex;
  gap: var(--space-1);
}

.youtube-times dd {
  margin: 0;
  color: var(--text-main);
  font-variant-numeric: tabular-nums;
}

/* ---- Warnings (#30): Dashboard warning area, YouTube view, nav badge */
.dashboard-warnings {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.dashboard-warnings:not(:has(> :not(.hidden))) {
  display: none;
}

.warning-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: var(--fw-semibold);
}

.warning-head i {
  color: var(--danger);
}

.warning-list {
  margin: var(--space-1-5) 0 0;
  padding-left: var(--space-4);
  overflow-wrap: anywhere;
}

.warning-list li + li {
  margin-top: var(--space-1);
}

.warning-open-youtube {
  margin-top: var(--space-2);
  min-height: 44px;
}

.nav-item .badge.is-danger {
  background-color: var(--danger-tint);
  border-color: var(--danger-border);
}

/* ---- Account menu (sidebar footer) */
.account-menu {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}
.account-who {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  font-size: var(--fs-caption);
  color: var(--text-muted);
  min-width: 0;
}
.account-name {
  color: var(--text-main);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sidebar.sidebar-collapsed .account-label,
.sidebar.sidebar-collapsed .account-name,
.sidebar.sidebar-collapsed #btn-sign-out span {
  display: none;
}

/* ---- Sign-in page (login.html) */
body.signin-page {
  overflow: auto;
  height: auto;
  min-height: 100vh;
}
.signin-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--space-4);
}
.signin-card {
  width: 100%;
  max-width: 400px;
}
.signin-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
/* The buttons inside share the .lang-toggle-btn rules above. */
.signin-lang {
  display: flex;
  gap: var(--space-0-5);
  padding: var(--space-0-5);
  border-radius: var(--radius-md);
  border: 1px solid var(--glass-border);
}
.signin-error {
  color: var(--danger);
  font-size: var(--fs-control);
  margin: var(--space-1) 0 var(--space-3);
}
.signin-submit {
  width: 100%;
  justify-content: center;
}

/* Password inputs with an eye button to show what was typed (js/passwordToggle.js). */
.password-field {
  position: relative;
  display: block;
}
.password-field .form-input {
  width: 100%;
  padding-right: calc(var(--target-touch) + var(--space-1));
}
.password-toggle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: var(--target-touch);
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  border-radius: var(--border-radius);
  color: var(--text-muted);
  cursor: pointer;
}
.password-toggle:hover {
  color: var(--text-main);
}

/* ---- Roles: Admin-only controls are hidden from Editors (the server refuses them anyway) */
body[data-role="editor"] .admin-only {
  display: none !important;
}

/* ---- Users page (js/users.js) and change-password page (password.html) */
#users-tab.active {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
.users-add-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-3);
  align-items: end;
}
.users-add-form .form-group {
  margin-bottom: 0;
}
.users-hint,
.users-note {
  color: var(--text-muted);
  font-size: var(--fs-caption);
}
.users-hint {
  margin-top: var(--space-3);
}
.users-you {
  color: var(--text-muted);
  font-size: var(--fs-caption);
}
.users-role-select {
  min-width: 140px;
}
.users-actions {
  display: flex;
  gap: var(--space-1-5);
  flex-wrap: wrap;
}
.users-actions .users-danger {
  color: var(--danger);
}
.users-status-disabled {
  opacity: 0.7;
}
#btn-change-password {
  text-decoration: none;
  text-align: center;
}
.sidebar.sidebar-collapsed #btn-change-password span {
  display: none;
}
.password-note {
  color: var(--text-muted);
  font-size: var(--fs-control);
  margin-bottom: var(--space-3);
}
.password-links {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-4);
}
/* This rule was missing its closing brace, which nested every rule below it (API keys,
   article history) under `.password-links a` so none of them matched. */
.password-links a {
  color: var(--primary);
  font-size: var(--fs-control);
}

/* ---- API keys page (#10, js/apiKeys.js). Admin only: hidden until "who am I" says admin. */
body:not([data-role="admin"]) .api-keys-admin-only {
  display: none !important;
}
.api-keys-hint {
  color: var(--text-muted);
  margin-bottom: var(--space-4);
}
.api-key-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.api-key-form .form-group {
  margin-bottom: 0;
  min-width: 200px;
}
.api-key-secret-box {
  border: 1px solid var(--warning);
  background: var(--warning-tint);
  border-radius: var(--border-radius);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
}
.api-key-secret-row {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  margin-top: var(--space-2);
}
.api-key-secret-row .form-input {
  flex: 1;
  font-family: var(--font-mono);
}

/* Article history (#11, js/history.js) */
.history-attribution {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  margin-top: var(--space-1-5);
  font-size: var(--fs-caption);
  color: var(--text-muted);
}
.history-attribution-label {
  font-weight: var(--fw-semibold);
}
.history-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.history-entry {
  display: grid;
  grid-template-columns: minmax(110px, auto) 1fr auto;
  gap: var(--space-1) var(--space-3);
  align-items: baseline;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border-subtle);
  font-size: var(--fs-control);
}
.history-time {
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.history-action {
  font-weight: var(--fw-semibold);
}
.history-actor {
  overflow-wrap: anywhere;
}
.history-actor-deleted {
  color: var(--text-muted);
  font-style: italic;
}
.history-note {
  padding: var(--space-3) 0;
  color: var(--text-muted);
}
@media (max-width: 600px) {
  .history-entry {
    grid-template-columns: 1fr;
  }
}

/* =============================================================================
   Responsive shell
   -----------------------------------------------------------------------------
   Everything above is the desktop layout, and at 1280px and up it is untouched.
   Below that, in widening steps of restructuring (js/responsive.js holds the state):

     < 1280px  tighter page gutter; the Articles view fills the height by flex
               instead of a 100vh sum, and the editor tabs scroll sideways if they
               must.
     < 1024px  Articles is two screens: the list, then the editor with a Back
               control (browser Back and Escape also return). Panels go full width.
     <  900px  the sidebar is an off-canvas drawer behind an app bar with a menu
               button; the main area gets the whole width.
     <  600px  phone density: the editor screen scrolls as one page under a pinned
               tab bar, single-column form rows, smaller thumbnails.

   Touch is a separate axis from width: any coarse pointer gets 44px targets.
   Keep the widths in step with the matchMedia queries in js/responsive.js.
   ============================================================================= */

/* ---- Touch: 44px targets on a coarse pointer, whatever the width ------------------- */
@media (pointer: coarse) {
  :root {
    --target-min: var(--target-touch);
    --control-h-sm: var(--target-touch);
  }

  .btn,
  .nav-item,
  .tab-edit-btn,
  .lang-toggle-btn,
  .collapse-toggle-inline,
  .btn-prompt-toggle,
  .btn-apply-prompt,
  .editor-back-btn,
  .form-input,
  .form-select {
    min-height: var(--target-touch);
  }

  .sidebar-toggle-btn,
  .image-spotlight-close {
    width: var(--target-touch);
    height: var(--target-touch);
  }

  /* The input is the target, not the pill drawn around it. */
  .search-bar {
    padding-top: 0;
    padding-bottom: 0;
  }

  .search-bar input {
    min-height: var(--target-touch);
  }

  .meta-row a {
    min-height: var(--target-touch);
  }
}

/* ---- Below 1280px: gutter and height by flex --------------------------------------- */
@media (max-width: 1279.98px) {
  .view-container {
    display: flex;
    flex-direction: column;
    padding: var(--space-5);
  }

  #articles-tab.active {
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-height: 0;
  }

  .articles-layout {
    flex: 1;
    min-height: 0;
    height: auto;
  }

  .tabs-editor-nav {
    --strip-fade: var(--space-6);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }

  .tabs-editor-nav::-webkit-scrollbar {
    display: none;
  }

  .tab-edit-btn {
    flex-shrink: 0;
    white-space: nowrap;
  }
}

/* ---- Below 1024px: Articles as two screens ----------------------------------------- */
@media (max-width: 1023.98px) {
  .resize-handle {
    display: none;
  }

  .articles-list-panel,
  .articles-editor-panel {
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
    max-width: none;
  }

  .articles-layout:not(.is-detail) .articles-editor-panel,
  .articles-layout.is-detail .articles-list-panel {
    display: none;
  }

  /* The way back to the list: its own row above the editor header, so below 600px it
     can stay pinned while the editor screen scrolls (an element cannot stick past
     the end of its parent, and the header scrolls away). */
  .editor-backbar {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    padding: var(--space-1) var(--space-4) 0;
  }

  .editor-back-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--target-min);
    margin-left: calc(var(--space-2) * -1);
    padding: 0 var(--space-2);
    background: none;
    border: none;
    border-radius: var(--radius-md);
    color: var(--primary);
    font-family: var(--font-family);
    font-size: var(--fs-control);
    font-weight: var(--fw-semibold);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
  }

  .editor-back-btn:hover {
    background: var(--primary-tint);
    color: var(--primary-text-hover);
  }

  .editor-footer {
    flex-wrap: wrap;
    gap: var(--space-2);
  }

  .footer-left,
  .footer-right {
    flex-wrap: wrap;
  }
}

/* ---- Below 900px: drawer navigation and an app bar --------------------------------- */
@media (max-width: 899.98px) {
  body,
  .app-container {
    height: 100vh;
    height: 100dvh;
  }

  .app-container {
    width: 100%;
  }

  .sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 900;
    width: min(300px, 86vw);
    padding: max(var(--space-5), env(safe-area-inset-top)) var(--space-4)
      max(var(--space-4), env(safe-area-inset-bottom)) max(var(--space-4), env(safe-area-inset-left));
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Closed: off-canvas. responsive.js also makes it inert, out of the tab order. */
    transform: translateX(-100%);
    transition: transform 0.25s cubic-bezier(0.2, 0, 0, 1);
  }

  /* The shadow only when open: closed, its blur would bleed in at the screen edge. */
  .sidebar.is-open {
    transform: none;
    box-shadow: var(--shadow-xl);
  }

  .sidebar-brand {
    flex-wrap: nowrap;
    margin-bottom: var(--space-6);
  }

  /* The rail toggle is the drawer's close button here. */
  .sidebar-toggle-btn #icon-sidebar-toggle {
    display: none;
  }

  .sidebar-toggle-btn .sidebar-close-icon {
    display: inline;
  }

  .app-topbar {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
    min-height: 56px;
    padding: env(safe-area-inset-top) max(var(--space-2), env(safe-area-inset-right)) 0
      max(var(--space-2), env(safe-area-inset-left));
    background: var(--bg-sidebar);
    border-bottom: 1px solid var(--glass-border);
  }

  .topbar-menu-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: var(--target-touch);
    height: var(--target-touch);
    background: none;
    border: none;
    border-radius: var(--border-radius);
    color: var(--text-main);
    font-size: var(--icon-lg);
    cursor: pointer;
    transition: background-color 0.15s ease;
  }

  .topbar-menu-btn:hover {
    background: var(--glass-hover);
  }

  /* The sidebar's brand mark, small, so the bar still reads as MediaBot. */
  .topbar-brand {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    background: linear-gradient(135deg, var(--primary), var(--success));
    border-radius: var(--radius-lg);
    color: var(--text-on-accent);
    font-size: var(--icon-sm);
  }

  /* Two classes: beats .sr-only, which Font Awesome also defines in a later sheet. */
  .app-topbar .view-title {
    position: static;
    flex: 1;
    min-width: 0;
    width: auto;
    height: auto;
    margin: 0;
    clip: auto;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: var(--fs-heading);
    font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-tight);
  }

  .view-container {
    padding: var(--space-3) max(var(--space-3), env(safe-area-inset-right))
      max(var(--space-3), env(safe-area-inset-bottom)) max(var(--space-3), env(safe-area-inset-left));
  }

  .toast-container {
    left: var(--space-3);
    right: var(--space-3);
    bottom: max(var(--space-3), env(safe-area-inset-bottom));
  }
}

/* ---- Below 600px: phone density ---------------------------------------------------- */
@media (max-width: 599.98px) {
  .panel-header {
    padding: var(--space-3);
  }

  .article-item-card {
    padding: var(--space-3);
  }

  .card-thumbnail-container {
    width: 64px;
    height: 48px;
  }

  .editor-header-row {
    gap: var(--space-3);
  }

  .editor-thumbnail-container img {
    width: 72px;
    height: 54px;
  }

  /* The editor screen scrolls as one page rather than squeezing the article body
     between a fixed header and a fixed footer (it was about 230px tall at 375x812).
     The tab bar stays pinned at the top and the CKEditor toolbar pins just under it. */
  .editor-content {
    overflow-y: auto;
    overscroll-behavior-y: contain;
  }

  .editor-content > * {
    flex-shrink: 0;
  }

  .editor-body {
    flex: none;
    overflow: visible;
  }

  /* Pinned stack while the editor screen scrolls: Back, then the tabs, then (on the
     Website tab) the CKEditor toolbar. Each is in the flow, so none covers content;
     the offsets are the rows above (44px each, plus a 1px border). */
  .editor-content {
    --backbar-h: calc(var(--target-touch) + 1px);
    --tabbar-h: calc(var(--target-touch) + 1px);
  }

  .editor-backbar {
    position: sticky;
    top: 0;
    z-index: 12;
    min-height: var(--backbar-h);
    padding: 0 var(--space-3);
    background: var(--bg-sidebar);
    border-bottom: 1px solid var(--glass-border);
  }

  .editor-back-btn {
    min-height: var(--target-touch);
    margin-left: calc(var(--space-2) * -1);
  }

  .tabs-editor-nav {
    position: sticky;
    top: var(--backbar-h);
    z-index: 11;
    gap: var(--space-3);
    padding: 0 var(--space-3);
  }

  .tab-edit-btn {
    min-height: var(--target-touch);
  }

  .ck.ck-editor__top {
    top: calc(var(--backbar-h) + var(--tabbar-h)) !important;
  }

  .tab-edit-view.active {
    padding: var(--space-4) var(--space-3);
  }

  .form-row-split,
  .cover-row {
    grid-template-columns: 1fr;
  }

  .cover-row > * {
    min-width: 0;
  }

  .editor-footer {
    padding: var(--space-2) var(--space-3);
  }

  .footer-left,
  .footer-right,
  .editor-footer button {
    flex: 1 1 auto;
  }

  /* ---- An open article gets the whole phone screen ----------------------------------
     The chrome stacked up to ~250px above the first line of text (app bar 56, page gutter
     and card edge, Back row 45, tabs 45, a two-row editor toolbar 88). Back is the way out
     of this screen, as on a native detail view, so the app bar steps aside (its h1 stays
     for screen readers), the card goes edge to edge, and Back becomes an icon that shares
     the tab row once the page scrolls. Pinned while scrolling: tabs + one toolbar row. */
  .main-content:has(.articles-layout.is-detail) .app-topbar {
    position: absolute;
    width: 1px;
    height: 1px;
    min-height: 0;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  .main-content:has(.articles-layout.is-detail) .topbar-menu-btn {
    display: none;
  }

  .view-container:has(.articles-layout.is-detail) {
    padding: env(safe-area-inset-top) env(safe-area-inset-right) 0 env(safe-area-inset-left);
  }

  .articles-layout.is-detail .articles-editor-panel {
    border: 0;
    border-radius: 0;
  }

  .editor-content {
    --backbar-h: 0px;
  }

  /* Back takes no row of its own: a 44px icon pinned at the top-left, over the start of
     the status row before scrolling and over the start of the tab row after. */
  .editor-backbar {
    height: 0;
    min-height: 0;
    padding: 0;
    overflow: visible;
    background: none;
    border-bottom: 0;
  }

  .editor-back-btn {
    position: absolute;
    top: 0;
    left: 0;
    justify-content: center;
    width: var(--target-touch);
    height: var(--target-touch);
    margin: 0;
    padding: 0;
    background: var(--bg-sidebar);
    border-radius: 0;
  }

  .editor-back-btn span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .editor-back-btn i {
    font-size: var(--icon-lg);
  }

  /* Opening an article focuses Back; drawn outside, its ring would cut into the status
     label beside it. */
  .editor-back-btn:focus-visible {
    outline-offset: var(--focus-ring-inset);
  }

  .editor-header .edit-status-container {
    margin-left: calc(var(--target-touch) - var(--space-3) + var(--space-2));
  }

  .tabs-editor-nav {
    padding-left: var(--target-touch);
  }
}

/* Reduced motion: nothing travels, scales or slides; every state change still shows,
   as a colour change or a short fade. Deliberately not a global 0.01ms kill, which
   would also drop the feedback. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --transition: color var(--dur-fast) linear,
      background-color var(--dur-fast) linear,
      border-color var(--dur-fast) linear,
      box-shadow var(--dur-fast) linear,
      opacity var(--dur-fast) linear;
  }

  html {
    scroll-behavior: auto;
  }

  /* The drawer appears in place instead of sliding in. */
  .sidebar,
  .sidebar.is-open {
    transition: none;
  }

  /* Slides become fades. */
  .bulk-actions-bar,
  .toast {
    animation-name: fadeIn;
  }

  .image-spotlight-content,
  .image-spotlight-backdrop.active .image-spotlight-content {
    transform: none;
    transition: none;
  }

  /* Hover zooms off; the border and glow still mark the hover. */
  .gallery-item-img,
  .gallery-image-thumb-card,
  .card-thumbnail-container img,
  #web-cover-preview,
  #fb-image-preview,
  .editor-thumbnail-container img,
  .btn-gallery-action,
  .image-spotlight-close,
  .btn-quiet i {
    transition: none;
  }

  .gallery-card:hover .gallery-item-img,
  .gallery-image-thumb-card:hover,
  .card-thumbnail-container img:hover,
  #web-cover-preview:hover,
  #fb-image-preview:hover,
  .editor-thumbnail-container img:hover,
  .btn-gallery-action:hover,
  .image-spotlight-close:hover {
    transform: none;
  }
}
