/* ===== KANBAN BOARD ===== */
.kanban-board {
  display: flex;
  gap: 0;
  overflow-x: auto;
  align-items: stretch;
  /* Bottom padding removed (was 16px) — per direct request, the columns should reach the true
     bottom of the window on both desktop and mobile, not stop short by a fixed gap underneath
     them. */
  padding: 4px 2px 0;
  /* Fills whatever height .kanban-wrap actually has left after its own contents (e.g. a
     tutorial banner) — see .grid-area:has(.kanban-wrap) below for why this reaches the true
     bottom of the window instead of the old calc(100vh - 180px) guess, which fell short and
     left the column divider lines/scroll areas stopping short of the window's bottom edge. */
  flex: 1;
  min-height: 0;
}

.kanban-column {
  position: relative;
  flex: 1 1 0;
  min-width: 220px;
  display: flex;
  flex-direction: column;
  /* Bottom side removed (was 12px all around) — same reasoning as .kanban-board's own bottom
     padding above: the column's content (.kanban-cards) should reach the true bottom edge, not
     stop 12px short of it, per direct request. */
  padding: 12px 12px 0;
  border-right: 1px solid var(--border);
  overflow: hidden;
  transition: background 0.15s;
}

/* :hover background removed entirely, per direct request — with the columns now correctly
   stretching to the true bottom of the window, hovering the empty space below a sparse column's
   last card lit up gray all the way down, reading as a separate "gap" area rather than as part
   of the same column. */

.kanban-column:last-child { border-right: none; }

/* ===== Expanded column mode ===== */
/* Board switches from the 4-up flex row to a single full-width block — the other three columns
   are omitted from the render entirely (see kanban.js), not just hidden here. */
.kanban-board--expanded {
  display: block;
}
.kanban-column--expanded {
  width: 100%;
  border-right: none;
  background: var(--hover-bg);
}

.kanban-expand-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
  cursor: pointer;
  z-index: 1;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.kanban-expand-btn:hover {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
/* The currently-expanded column's own button — purple "−", so clicking it again visibly reads
   as "shrink back down" rather than looking like every other column's plain "+" button. */
.kanban-expand-btn--active {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}

/* Format picker — pill shape matching .btn-board-filter (the "Categories" filter button), rather
   than the plain small icon-button treatment .kanban-sort-btn uses. Positioned in the top-right
   corner of the expanded column, just to the left of the collapse button (which stays pinned at
   right:10px) instead of sitting inline in the centered title row. */
.kanban-format-btn {
  position: absolute;
  top: 6px;
  right: 38px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 24px;
  color: var(--text-primary);
  cursor: pointer;
  padding: 6px 12px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  white-space: nowrap;
  z-index: 1;
  transition: background 0.15s, border-color 0.15s;
}
.kanban-format-btn:hover { background: var(--hover-bg); border-color: var(--primary); }
.kanban-format-btn svg { opacity: 0.5; flex-shrink: 0; }
.kanban-format-btn-label { text-transform: uppercase; }

.kanban-format-dropdown {
  position: absolute;
  top: 40px;
  right: 38px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 4px;
  z-index: 100;
  min-width: 140px;
  box-shadow: 0 6px 20px rgba(0,0,0,0.2);
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.kanban-format-dropdown[hidden] { display: none; }

.kanban-format-option {
  background: none;
  border: none;
  text-align: left;
  padding: 7px 12px;
  font-size: 12px;
  color: var(--text-secondary);
  cursor: pointer;
  border-radius: 7px;
  transition: background 0.12s, color 0.12s;
}
.kanban-format-option:hover { background: var(--bg); color: var(--text); }
.kanban-format-option.active { color: var(--primary); font-weight: 600; }

.kanban-column-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
  margin-bottom: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  position: relative;
}

.kanban-cards {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: none;
}

.kanban-cards::-webkit-scrollbar {
  display: none;
}

/* Grid-density modifiers — only applied while a column is expanded (see kanban.js); the normal
   4-column board's .kanban-cards stays the plain vertical flex list above, untouched. */
.kanban-cards--two-col  { display: grid; grid-template-columns: repeat(2, 1fr); align-content: start; }
.kanban-cards--four-col { display: grid; grid-template-columns: repeat(4, 1fr); align-content: start; }
.kanban-cards--large    { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); align-content: start; }
.kanban-cards--detail   { display: grid; grid-template-columns: repeat(2, 1fr); align-content: start; }
.kanban-cards--simple   { display: grid; grid-template-columns: repeat(2, 1fr); align-content: start; gap: 8px; }

.kanban-empty {
  font-size: 12px;
  color: var(--text-muted);
  text-align: center;
  padding: 20px 0;
}

.progress-drop-hint {
  height: 100px;
  border: 2px dashed var(--primary);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 500;
  color: var(--primary);
  opacity: 0.5;
  transition: opacity 0.15s;
  pointer-events: none;
}

.kcard {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  display: flex;
  flex-direction: row;
  align-items: stretch;
  overflow: hidden;
  transition: box-shadow 0.15s;
  position: relative;
  height: 100px;
  flex-shrink: 0;
  /* REAL BUG, found and reverted: touch-action: none used to live here, meant to stop the
     browser's own scroll from racing the drag-vs-tap threshold check — but it blocked ALL native
     touch scrolling starting from a card (most of a column's surface) unconditionally, which is
     worse: it broke the ability to scroll a column via touch at all (reported live: "unable to
     scroll"). Removed now that kanban.js/adminKanban.js's touch handlers use a long-press to
     engage a drag instead of a movement threshold — nothing is preventDefault'd until a drag is
     actually confirmed, so normal scrolling never needs to be blocked at the CSS level. */
  /* The long-press that starts a touch drag is the exact same gesture iOS Safari uses to select
     text and pop up its own "Copy / Look Up / Translate…" menu over a card's title/notes text
     (reported live) — these cards are drag handles, not selectable text, so turn text selection
     off entirely rather than let the two gestures fight. -webkit-touch-callout specifically
     suppresses that iOS callout menu; user-select alone doesn't. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.kcard > .kcard-badge {
  position: absolute;
  bottom: 8px;
  right: 8px;
}

.kcard:hover { box-shadow: 0 2px 10px var(--shadow-card); }

.kcard--demo {
  border-style: dashed;
  opacity: 0.7;
}

.kcard-thumb {
  width: 80px;
  flex-shrink: 0;
  object-fit: cover;
  display: block;
}

.kcard-thumb--placeholder {
  width: 80px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  font-weight: 700;
  color: rgba(255,255,255,0.9);
}

.kcard-content {
  flex: 1;
  min-width: 0;
  padding: 10px 10px 28px 10px;
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.kcard-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.kcard-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.kcard-author {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Byline layout (any item with an author — Music Album, Book, etc.), matching the main grid's
   album cards: .card-author-name/.card-title--album/.card-album-year in cards.css. */
.kcard-artist {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.kcard-title--byline {
  font-size: 15px;
}

.kcard-year {
  font-size: 12px;
  color: var(--text-secondary);
  margin-top: 2px;
}

.kcard-badge {
  font-size: 11px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 10px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  width: fit-content;
}

.kcard-demo-badge {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  text-transform: uppercase;
}

.kcard-remove {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 12px;
  cursor: pointer;
  padding: 2px 4px;
  border-radius: 4px;
  line-height: 1;
  flex-shrink: 0;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s;
}

.kcard:hover .kcard-remove { opacity: 1; }
.kcard-remove:hover { color: #EF4444; }

/* ===== Expanded-column card format variants ===== */
/* Large Card / Detail Card go vertical (thumb on top, text below) — better suited to the extra
   notes/date content than a row layout at that size. Two Column keeps the default row layout
   (image on the left) but with a taller/wider thumb, since it still shows notes/date. Four
   Column also keeps the row layout, just narrower and denser (no notes/date — see
   renderKanbanCard()). */
.kcard--two-col {
  height: auto;
  min-height: 100px;
}
.kcard--two-col .kcard-thumb, .kcard--two-col .kcard-thumb--placeholder { width: 110px; }
.kcard--two-col .kcard-content { align-items: center; }

.kcard--large,
.kcard--detail {
  flex-direction: column;
  height: auto;
}

.kcard--large  .kcard-thumb, .kcard--large  .kcard-thumb--placeholder { width: 100%; height: 220px; }
.kcard--detail .kcard-thumb, .kcard--detail .kcard-thumb--placeholder { width: 100%; height: 90px; }

.kcard-note {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Detail Card's whole point is showing the note in full, not clamped like every other format. */
.kcard-note--full {
  -webkit-line-clamp: unset;
  overflow: visible;
}

/* Simple Text — a two-column list of plain rows, no thumbnail. Two columns (instead of as many
   narrow ones as would fit) leaves enough width per row for the title to actually be readable
   rather than truncated after a few characters. */
.kcard--simple {
  height: auto;
  min-height: 44px;
  flex-direction: row;
  align-items: center;
  padding: 10px 14px;
  gap: 10px;
}
.kcard--simple .kcard-title {
  flex: 1;
  min-width: 0;
  -webkit-line-clamp: 2;
  font-size: 14px;
  line-height: 1.35;
}
/* Overrides the base rule's absolute corner positioning (meant for the taller default card) —
   simple format is a single row, the badge sits inline instead. */
.kcard--simple > .kcard-badge {
  position: static;
  flex-shrink: 0;
}

/* Drag-and-drop states */
.kcard--dragging {
  cursor: grabbing;
  /* Same dashed-purple outline language as .kanban-column--over below, plus a light purple wash
     (same inset box-shadow technique as .kcard--just-dropped) so the card visibly turns purple
     the moment a drag engages — per direct request, replacing the earlier plain-dim treatment. */
  outline: 2px dashed var(--primary);
  outline-offset: -2px;
  box-shadow: inset 0 0 0 999px rgba(91, 91, 239, 0.25);
}

.kanban-column--over {
  background: var(--primary-bg);
  outline: 2px dashed var(--primary);
}

/* Touch drag's floating ghost (kanban.js/adminKanban.js's createTouchGhost) — a cloned card that
   tracks the finger. Full opacity and lifted (scale + shadow), unlike the dimmed, flat original
   it's covering — reads as "this is the thing actually moving," distinct from the origin card
   left behind underneath it. */
.kcard--ghost {
  opacity: 1;
  transform: scale(1.04);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.35);
  outline: 2px solid var(--primary);
  outline-offset: -2px;
}

/* Flashed on the card once it lands in its new column (kanban.js/adminKanban.js's performDrop,
   after the re-render) — per direct request, so it's still identifiable as "the one that just
   moved" for a moment. A purple wash via inset box-shadow rather than animating background-color
   directly — a plain opacity/gray fade (tried first) didn't read as "purple," and box-shadow
   layers as an overlay on top of whatever the card's own resting background already is (fixed
   white for Admin Kanban cards, var(--surface) for the real board's), instead of needing to
   target either one specifically. */
@keyframes kcard-drop-flash {
  0%   { box-shadow: inset 0 0 0 999px rgba(91, 91, 239, 0.35); }
  /* Holds at full strength through 87% of the 1.15s run (~1s solid), per direct request — the
     original version started fading immediately, so it never actually read as "staying" purple.
     Only the last ~150ms fades out. */
  87%  { box-shadow: inset 0 0 0 999px rgba(91, 91, 239, 0.35); }
  100% { box-shadow: inset 0 0 0 999px rgba(91, 91, 239, 0); }
}
.kcard--just-dropped {
  animation: kcard-drop-flash 1.15s ease-out;
}

/* Shows exactly where a dragged card will land within a column, above/below whichever card
   the cursor is currently over — see the per-card dragover tracking in kanban.js. */
.kcard--drop-before { box-shadow: 0 -3px 0 0 var(--primary); }
.kcard--drop-after  { box-shadow: 0 3px 0 0 var(--primary); }

/* Reorder placeholder (kanban.js/adminKanban.js's showPlaceholderAt/showPlaceholderAtEnd) — a
   dashed "landing spot" that takes a card's place in the list while dragging within its own
   section, same floating-card language as the touch ghost, per direct request ("I want to use
   the same floating card affect for up and down dragging"). Sized dynamically via inline
   style.height to match whatever card it's standing in for; width comes for free from
   .kanban-cards' flex column stretch, same as every real card. */
.kcard-placeholder {
  border: 2px dashed var(--primary);
  border-radius: 10px;
  background: var(--primary-bg);
  flex-shrink: 0;
}

/* ===== ADMIN KANBAN ===== */
/* Extra bottom room so the last card in a column can scroll clear of the floating "+ Add card"
   button (.admin-kcard-add-btn below) instead of sitting permanently hidden behind it. */
.admin-kanban-cards {
  padding-bottom: 44px;
}

/* Cards reuse .kcard directly (same 100px fixed box, hover shadow, drag/drop-indicator classes as
   the real board) — .admin-kcard only replaces the thumb+content row layout with a single text
   block, since a task card has no thumbnail/badge to show. */
.admin-kcard-body {
  flex: 1;
  min-width: 0;
  padding: 10px 24px 22px 12px; /* right clears the remove button, bottom clears the urgency dot */
  display: flex;
  flex-direction: column;
  justify-content: center; /* vertically centers name+details as a block, rather than pinned to the top */
  gap: 4px;
  overflow: hidden;
}

/* Fixed white card / black text here, not the theme-adaptive var(--surface)/var(--text-primary)
   the rest of this board (and the real Queue board's own .kcard) use — per direct request, and
   scoped to just Admin Kanban so it doesn't touch the real board's cards. */
.kcard.admin-kcard {
  background: #ffffff;
  border-color: #E0E0E0;
}

.admin-kcard-name {
  font-size: 13px;
  font-weight: 600;
  color: #111111;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.admin-kcard-details {
  font-size: 12px;
  color: #444444;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

/* Same hover-revealed treatment as the real board's .kcard-remove — fixed dark gray rather than
   var(--text-muted) (a light gray meant for the dark theme's own cards, low-contrast against
   this card's fixed white background). Absolutely positioned in the top-right corner — the
   urgency dot below now lives in the bottom-right instead (per direct request; the two used to
   share the top-right corner and visibly collided there). */
.admin-kcard-remove {
  position: absolute;
  top: 6px;
  right: 6px;
  background: none;
  border: none;
  color: #888888;
  font-size: 12px;
  cursor: pointer;
  padding: 2px 4px;
  border-radius: 4px;
  line-height: 1;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s;
}
.kcard:hover .admin-kcard-remove { opacity: 1; }
.admin-kcard-remove:hover { color: #EF4444; }

/* Urgency dot — bottom-right corner (per direct request; was top-right, where it collided with
   the remove "✕" above), colored by the Low/Medium/High level set in the edit popup. The number
   inside it is the card's order/position in the list (top card is always 1), not the urgency
   level — per direct request. */
.admin-kcard-urgency {
  position: absolute;
  bottom: 6px;
  right: 6px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
}
.admin-kcard-urgency--blue   { background: #3B82F6; } /* Low */
.admin-kcard-urgency--orange { background: #16A34A; } /* Medium — green, per direct request; deep enough that white text stays readable */
.admin-kcard-urgency--red    { background: #EF4444; } /* High */

/* Left-edge urgency strip — reuses the same three color classes as the dot above (just their
   `background`). .kcard's own overflow: hidden clips this flush to the card's rounded left
   corners instead of it poking out square. */
.admin-kcard-urgency-strip {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 5px;
}

/* Same reasoning as .admin-kcard-remove above — .kcard-demo-badge's own var(--text-muted) is
   near-invisible against this card's fixed white background. */
.admin-kcard .kcard-demo-badge {
  color: #888888;
}

/* Circular icon button (was a full-width dashed "+ Add card" rectangle) — same recipe as
   .kanban-expand-btn above (circle, bordered, purple-fill hover). Floats over the bottom of the
   column now (was a normal flex sibling below .kanban-cards, which shortened the scrollable card
   area by its own height and kept the column itself from ever reaching the bottom of the screen)
   — .kanban-column is already position: relative, so this just pins to its bottom edge and lets
   .kanban-cards use the column's full height, scrolling underneath it, per direct request. */
.admin-kcard-add-btn {
  position: absolute;
  bottom: 12px;
  left: 50%;
  transform: translateX(-50%);
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
  cursor: pointer;
  box-shadow: 0 2px 10px var(--shadow-card); /* separates it from cards scrolling underneath */
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.admin-kcard-add-btn:hover {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}


/* Trimmed down from .grid-area's own base 24px top/bottom (cards.css) — this page's real content
   starts with .admin-kanban-header right away (#grid-title/#sort-select are both hidden here, see
   renderAdminKanbanBoard), so the full base padding just read as excess empty space above the
   title, and again as a gap below the columns that kept them from ever reaching the bottom edge
   of the screen, per direct request. Also grows the columns themselves by the same amount either
   way, since .kanban-wrap/.kanban-board both flex:1 to fill whatever .grid-area has left. */
.grid-area:has(.admin-kanban-wrap) {
  padding-top: 15px;
  padding-bottom: 4px;
}

/* Page header — title + the dedicated sort dropdown (SORT_MODES in adminKanban.js), both
   rendered as this board's own content rather than the shared #grid-title/#sort-select elements
   (see renderAdminKanbanBoard's own comment on why). */
.admin-kanban-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}
.admin-kanban-title {
  font-size: 20px;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0;
}
.admin-kanban-sort-wrap {
  position: relative;
  flex-shrink: 0;
}
/* .btn-board-filter's own base width (148px, sized for short labels like "CATEGORIES") clips
   this dropdown's longer ones ("Urgency (High → Low)") — auto-width with a min instead, and the
   dropdown's own min-width bumped to match its longest option. Right-aligned (not the base
   rule's left: 0) so it opens under the button rather than spilling past the page's right edge. */
.admin-kanban-sort-btn {
  width: auto;
  min-width: 148px;
}
.admin-kanban-sort-dropdown {
  left: auto;
  right: 0;
  min-width: 200px;
}

/* Card editor modal (injected by adminKanban.js) — reuses the shared .modal/.form-group shell,
   just its own actions-row layout: Delete pinned left (as a quiet text link, not a full button —
   matches this app's other destructive-but-secondary actions, e.g. Profile's "Delete account"),
   Cancel/Save grouped right like every other modal's own .modal-actions. */
.admin-kcard-modal-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.admin-kcard-modal-actions-right {
  display: flex;
  gap: 10px;
}
.admin-kcard-delete-link {
  background: none;
  border: none;
  padding: 0;
  color: var(--text-secondary);
  font-size: 13px;
  cursor: pointer;
  transition: color 0.15s;
}
.admin-kcard-delete-link:hover {
  color: #EF4444;
}

/* Kanban wrap — outer column container so tutorial sits above board row */
.kanban-wrap {
  display: flex;
  flex-direction: column;
  gap: 0;
  flex: 1;
  min-height: 0;
}

/* The Kanban board is designed to fill exactly the available height below the toolbar row
   (any tutorial banner takes its natural height, .kanban-board flexes to fill the rest) —
   it should never make the whole page scroll, only the individual columns inside it, unlike
   every other view (which still needs normal overflow-y:auto for long lists). Scoped to just
   this view via :has(), mirroring .grid-area:has(.dashboard-wrap) in dashboard.css. */
.grid-area:has(.kanban-wrap) {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* Trimmed the same way .grid-area:has(.admin-kanban-wrap) already is below — the header's own
     two-row layout (misc.css, mobile) freed up room here, per direct request, so the board itself
     can reach further down the page instead of leaving it as unused padding. */
  padding-top: 15px;
  padding-bottom: 4px;
}

/* Board info icon + popup */
.board-info-wrap {
  position: relative;
  display: flex;
  align-items: center;
  margin-left: -6px;
}

.btn-board-info {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: color 0.15s;
  flex-shrink: 0;
}

.btn-board-info:hover {
  color: var(--text-secondary);
}

.board-info-popup {
  position: fixed;
  top: 50%;
  left: calc(50vw + 150px);
  transform: translate(-50%, -50%);
  width: min(580px, calc(100vw - 280px));
  background: var(--primary);
  border: none;
  border-radius: 24px;
  padding: 48px 64px;
  box-shadow: 0 16px 48px rgba(0,0,0,0.36);
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  text-align: center;
  animation: info-popup-in 0.18s ease;
}

.board-info-popup[hidden] { display: none; }

@keyframes info-popup-in {
  from { opacity: 0; transform: translate(-50%, calc(-50% - 8px)); }
  to   { opacity: 1; transform: translate(-50%, -50%);  }
}

.board-info-icon {
  font-size: 52px;
  margin-bottom: 18px;
  line-height: 1;
}

.board-info-title {
  font-size: 20px;
  font-weight: 700;
  color: #fff;
  margin-bottom: 14px;
}

.board-info-tips {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
}

.board-info-tip {
  font-size: 14px;
  color: rgba(255,255,255,0.82);
  line-height: 1.4;
}

/* No-results state inside kanban */
.kanban-no-results {
  grid-column: 1 / -1;
  text-align: center;
  padding: 60px 24px;
  color: var(--text-secondary);
  font-size: 15px;
  width: 100%;
}

/* Per-column sort button + dropdown */
.kanban-sort-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--text-secondary);
  cursor: pointer;
  padding: 2px 4px;
  border-radius: 4px;
  opacity: 0.6;
  transition: opacity 0.15s, background 0.15s;
}

.kanban-sort-btn:hover { opacity: 1; background: var(--border); }

.kanban-sort-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 4px;
  z-index: 100;
  min-width: 130px;
  box-shadow: 0 6px 20px rgba(0,0,0,0.2);
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.kanban-sort-dropdown[hidden] { display: none; }

.kanban-sort-option {
  background: none;
  border: none;
  text-align: left;
  padding: 7px 12px;
  font-size: 12px;
  color: var(--text-secondary);
  cursor: pointer;
  border-radius: 7px;
  transition: background 0.12s, color 0.12s;
}

.kanban-sort-option:hover { background: var(--bg); color: var(--text); }
.kanban-sort-option.active { color: var(--primary); font-weight: 600; }

/* "‹ Dashboard" — a quick way back to the homepage, per direct request. Sits first in
   .grid-header (index.html), so it's naturally the leftmost element wherever .grid-header itself
   is shown — currently the Kanban board (its own render function shows it alongside its other
   controls) and the "Cause Curated" bare list (which shows it alone, see
   renderCuratedBareList() in renderCuratedPages.js). On desktop, .saves-list-wrap's own
   margin-left: auto below pushes the Kanban board's other three controls (My Saves/Categories/
   info) to the right, leaving this alone on the left; mobile stacks it onto its own row above
   them instead (misc.css). */
.kanban-dashboard-link {
  background: none;
  border: none;
  color: var(--primary);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  padding: 6px 4px;
  border-radius: 6px;
  transition: color 0.15s, background 0.15s;
}
.kanban-dashboard-link:hover,
.kanban-dashboard-link:active {
  color: #fff;
  background: var(--primary);
}
@media (min-width: 769px) {
  .saves-list-wrap {
    margin-left: auto;
  }
}

/* MY SAVES list button + dropdown */
.saves-list-wrap,
.board-filter-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.btn-board-filter {
  display: flex;
  align-items: center;
  gap: 0;
  padding: 7px 10px 7px 14px;
  width: 148px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 24px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--text-primary);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  transition: background 0.15s, border-color 0.15s;
}

.btn-board-filter:hover {
  background: var(--hover-bg);
  border-color: var(--primary);
}

.btn-board-filter svg {
  opacity: 0.5;
  flex-shrink: 0;
}

.board-filter-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 150px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.18);
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  z-index: 200;
}

.board-filter-dropdown[hidden] { display: none; }

.btn-saves-list {
  display: flex;
  align-items: center;
  gap: 0;
  padding: 7px 10px 7px 14px;
  width: 148px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 24px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--text-primary);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  transition: background 0.15s, border-color 0.15s;
}

.btn-saves-list:hover {
  background: var(--hover-bg);
  border-color: var(--primary);
}

.btn-saves-list span,
.btn-board-filter span {
  flex: 1;
}

.btn-saves-list svg {
  opacity: 0.5;
  flex-shrink: 0;
}

.saves-list-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 160px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 4px;
  z-index: 300;
  box-shadow: 0 8px 24px rgba(0,0,0,0.18);
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.saves-list-dropdown[hidden] { display: none; }

.saves-list-option {
  background: none;
  border: none;
  text-align: left;
  padding: 8px 12px;
  font-size: 13px;
  color: var(--text-secondary);
  cursor: pointer;
  border-radius: 24px;
  transition: background 0.12s, color 0.12s;
}

.saves-list-option:hover { background: var(--hover-bg); color: var(--text-primary); }
.saves-list-option.active { color: var(--primary); font-weight: 600; }

.saves-list-divider {
  height: 1px;
  background: var(--border);
  margin: 3px 4px;
}

.saves-list-add {
  color: var(--primary);
}

.saves-list-add:hover { background: var(--primary-bg); color: var(--primary); }

/* Queue accordion section (mirrors .detail-streaming) */
.detail-queue {
  width: 100%;
  margin-top: 10px;
}

.detail-queue--tight:not(.open) {
  /* Removed from layout entirely while collapsed — guarantees zero footprint (no margin,
     no residual height) after the standalone Add to Queue button, instead of relying on
     max-height/margin cancellation math that wasn't fully closing the gap. */
  display: none;
}

.detail-queue--tight.open {
  margin-top: 8px; /* plain header-to-pills gap, matching every other accordion row's spacing */
  /* Deliberately no margin-bottom compensation — see #btn-standalone-queue in detailModal.css for
     why flushing this against the modal's bottom padding would look wrong once .detail-body
     actually scrolls, which the same reasoning applies to here for the last pill. */
}

.detail-queue.open .streaming-links-wrap {
  /* Generously large rather than a tight cap — same as Web Links/Book Summary/Chapters, defers
     to .detail-body's own scroll instead of hard-clipping a growing kanban-list tag count. */
  max-height: 2000px;
  margin-top: -2px;
}

/* List tag pills inside queue accordion */
.queue-tag {
  padding: 5px 12px;
  border-radius: 20px;
  border: 1px solid rgba(255,255,255,0.25);
  background: transparent;
  color: rgba(255,255,255,0.7);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.queue-tag:hover { background: rgba(255,255,255,0.12); color: #fff; }

.queue-tag.active {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}

.queue-tag-add {
  border-color: rgba(91,91,239,0.6);
  color: #5B5BEF;
}

.queue-tag-add:hover { background: rgba(91,91,239,0.15); border-color: #5B5BEF; color: #5B5BEF; }

/* Inline new-list input inside queue accordion */
.queue-new-wrap {
  display: flex;
  gap: 6px;
  width: 100%;
}

.queue-new-input {
  flex: 1;
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 20px;
  padding: 5px 12px;
  font-size: 12px;
  color: #fff;
  outline: none;
}

.queue-new-input::placeholder { color: rgba(255,255,255,0.35); }
.queue-new-input:focus { border-color: #5B5BEF; }

.queue-new-confirm {
  background: #5B5BEF;
  border: none;
  border-radius: 20px;
  padding: 5px 14px;
  font-size: 12px;
  font-weight: 600;
  color: #fff;
  cursor: pointer;
  white-space: nowrap;
}

/* MY SAVES new list inline input */
.saves-list-new-wrap {
  display: flex;
  gap: 6px;
  padding: 6px;
}

.saves-list-new-input {
  flex: 1;
  min-width: 0;
  background: var(--hover-bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 12px;
  color: var(--text-primary);
  outline: none;
}

.saves-list-new-input:focus { border-color: var(--primary); }

.saves-list-new-confirm {
  background: var(--primary);
  border: none;
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 12px;
  font-weight: 600;
  color: #fff;
  cursor: pointer;
  white-space: nowrap;
}
.saves-list-new-confirm:hover,
.saves-list-new-confirm:active {
  background: #fff;
  color: var(--primary);
}

.queue-new-cancel,
.saves-list-new-cancel {
  background: none;
  border: none;
  color: rgba(255,255,255,0.5);
  font-size: 13px;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 6px;
  flex-shrink: 0;
  transition: color 0.15s;
}
.queue-new-cancel:hover { color: #fff; }
.saves-list-new-cancel { color: var(--text-secondary); }
.saves-list-new-cancel:hover { color: var(--text-primary); }

