.agenda-layout {
  flex: 1; display: flex; min-width: 0; overflow: hidden;
}

/* ---- Queue of approved videos ---- */
/* A little wider: the rows now carry a countdown as well as a name. */
.agenda-side {
  width: 306px; flex: none;
  background: var(--surface);
  padding: 18px 16px;
  overflow-y: auto;
  box-shadow: 1px 0 0 rgba(0, 0, 0, 0.2);
}
.agenda-side h3 {
  margin: 0 0 4px; font-size: 15px; color: var(--text-strong);
  display: flex; align-items: center; gap: 8px;
}
.agenda-side .pill {
  background: var(--accent); color: #fff; font-size: 12px;
  padding: 1px 8px; border-radius: 999px;
}
.side-hint { margin: 0 0 14px; font-size: 12px; color: var(--muted); line-height: 1.5; }

.queue { display: flex; flex-direction: column; gap: 6px; }
.queue-item {
  display: flex; gap: 10px; align-items: center; text-align: left;
  padding: 8px; border-radius: var(--radius-sm);
  background: var(--surface-2); width: 100%;
}
.queue-item:hover { background: var(--surface-3); }
.queue-item.picked { background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent); }
.queue-thumb {
  width: 52px; height: 32px; flex: none; border-radius: 4px; overflow: hidden;
  background: var(--bg-deep); display: grid; place-items: center; font-size: 15px;
}
.queue-thumb img { width: 100%; height: 100%; object-fit: cover; }
.queue-text { min-width: 0; }
.queue-name {
  font-size: 13px; color: var(--text-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.queue-sub { font-size: 11px; color: var(--muted); }

/* ---- Calendar ---- */
.agenda-main { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.agenda-head {
  display: flex; align-items: center; gap: 6px;
  padding: 12px 20px; background: var(--surface);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
}
.agenda-head .range-title {
  font-size: 16px; font-weight: 600; color: var(--text-strong);
  min-width: 190px; text-align: center;
}
.agenda-head .spacer { flex: 1; }
.agenda-head .hint { font-size: 13px; color: #a5b0ff; }

.view-switch {
  display: flex; margin-left: 8px;
  border-radius: var(--radius-sm); overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--border);
}
.view-switch button {
  padding: 6px 14px; font-size: 13px; border-radius: 0;
  background: transparent; color: var(--muted);
}
.view-switch button:hover { color: var(--text-strong); }
.view-switch button.active { background: var(--accent); color: #fff; }

/* ---- Month grid ---- */
.calendar.month {
  flex: 1; display: grid; gap: 1px;
  grid-template-columns: repeat(7, 1fr);
  /* The weekday strip hugs its text; the six week rows share what is left. */
  grid-template-rows: auto repeat(6, minmax(0, 1fr));
  background: var(--bg-deep);
  padding: 1px;
  overflow-y: auto;
}
.calendar .weekday {
  background: var(--bg);
  padding: 6px 8px; font-size: 11px; font-weight: 700;
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted);
  grid-row: 1;
}
.calendar .day {
  background: var(--bg);
  padding: 4px 5px; min-height: 88px;
  display: flex; flex-direction: column; gap: 3px;
  overflow: hidden;
}
.calendar .day.outside { background: #2a2c31; }
.calendar .day.outside .day-number { color: #5c626b; }
.calendar .day.today { box-shadow: inset 0 0 0 2px var(--accent); }
.calendar .day.droppable { cursor: copy; }
.calendar .day.droppable:hover { background: var(--accent-soft); }
.day-number { font-size: 12px; color: var(--muted); padding: 2px 3px; }
.day-posts { display: flex; flex-direction: column; gap: 3px; overflow-y: auto; }

.post-chip {
  display: flex; gap: 5px; align-items: baseline;
  width: 100%; text-align: left;
  padding: 3px 6px; border-radius: 4px;
  font-size: 11px; line-height: 1.3;
  background: var(--surface-2); color: var(--text-strong);
  border-left: 3px solid var(--muted);
}
.post-chip:hover { background: var(--surface-3); }
.post-chip .chip-time { color: var(--muted); flex: none; font-variant-numeric: tabular-nums; }
.post-chip .chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* One colour per platform, so a glance at the month reads as a mix. */
.post-chip.instagram { border-left-color: var(--instagram); }
.post-chip.tiktok { border-left-color: var(--tiktok); }
.post-chip.youtube { border-left-color: var(--youtube); }
/* Out the door: green in the writing, not in the block. Fading reads as
   "cancelled" at a glance, which is the opposite of what it means — but a
   filled green block shouts over everything else on that day and buries the
   platform stripe on its left, which is what tells you where it went. The
   letters carry the state; the block stays a block. */
.post-chip.posted {
  border-left-color: var(--success) !important;
  color: #5fd894;
}
.post-chip.posted .chip-time { color: #4ac57e; }
.post-chip.failed { border-left-color: var(--danger); }

/* ---- Week grid (Google Calendar style) ----
   One scroll container for both strips: the header is sticky inside it, so the
   day columns can never drift out of line with the hours below them. */
.calendar.week {
  flex: 1; display: block; overflow-y: auto;
  background: var(--bg);
}

.week-head, .week-body {
  display: grid;
  grid-template-columns: 58px repeat(7, minmax(0, 1fr));
}
.week-head {
  position: sticky; top: 0; z-index: 3;
  background: var(--surface);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.35);
}
.week-day-head {
  padding: 8px 6px; text-align: center;
  display: flex; flex-direction: column; gap: 1px;
  box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.22);
}
.week-day-head .dow {
  font-size: 11px; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--muted);
}
.week-day-head .dom { font-size: 20px; color: var(--text-strong); line-height: 1.1; }
.week-day-head.today .dow { color: #a5b0ff; }
.week-day-head.today .dom {
  color: #fff; background: var(--accent);
  width: 30px; height: 30px; line-height: 30px;
  border-radius: 50%; margin: 0 auto;
}

.hour-gutter { position: relative; }
.hour-label {
  height: 46px; position: relative;
  padding-right: 8px; text-align: right;
}
/* The time sits astride its line, the way a printed calendar reads. */
.hour-label span {
  position: absolute; right: 8px; top: -7px;
  font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.hour-gutter .hour-label:first-child span { top: 0; }

.week-col { position: relative; box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.22); }
.hour-slot { height: 46px; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.045); }
/*
 * The hours this audience is actually awake, measured over ninety days of his
 * own posts — each in the colour of the network it is good for, so a slot says
 * what it is good *for* and not just that it is good. An hour that suits two
 * networks wears both stripes.
 */
.hour-slot { position: relative; }

/*
 * A marked hour is a rounded block sitting inside its slot rather than a full
 * bleed square. The grid reads as a calendar with things placed on it, not as a
 * spreadsheet with cells coloured in.
 */
.hour-slot.best-time { --best: var(--success); }
.hour-slot.best-time::before {
  content: '';
  position: absolute; inset: 3px 4px;
  border-radius: 7px;
  background-image: var(--split, color-mix(in srgb, var(--best) 26%, transparent));
  transition: filter 0.12s ease, inset 0.12s ease;
  pointer-events: none;
}
.hour-slot.best-time.for-instagram { --best: var(--instagram); }
.hour-slot.best-time.for-tiktok { --best: var(--tiktok); }
.hour-slot.best-time.for-youtube { --best: var(--youtube); }

/*
 * An hour two or three networks share is split into equal bands, each in its
 * own colour, rather than one colour with a hairline of the second down the
 * edge. A shared hour is the most useful thing the grid can tell you — post
 * once, reach two audiences — and it used to be the hardest thing to see.
 */
.hour-slot.best-time.shared-2::before,
.hour-slot.best-time.shared-3::before { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.09); }
.hour-slot.best-time.shared-3::before { filter: saturate(1.15); }

/*
 * Where the next video would go if nobody touched anything. Yellow, and only a
 * ring: it is not a good hour in its own right, it is a plan — and a plan that
 * changes the moment something else is scheduled.
 */
.hour-slot.next-up::after {
  content: '';
  position: absolute; inset: 3px 4px;
  border-radius: 7px;
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--warning) 70%, transparent);
  background: color-mix(in srgb, var(--warning) 10%, transparent);
  pointer-events: none;
}

.week-col.droppable .hour-slot { cursor: copy; }
.week-col.droppable .hour-slot:hover { background: var(--accent-soft); }
.week-col.droppable .hour-slot.best-time:hover::before { filter: brightness(1.5) saturate(1.2); }

.week-event {
  position: absolute; left: 3px; right: 3px;
  /* Set per event, so the hover rule below has something to override. */
  width: var(--full, auto);
  min-height: 30px; padding: 3px 6px;
  display: flex; flex-direction: column; gap: 1px;
  text-align: left; overflow: hidden;
  border-radius: 4px; z-index: 1;
  font-size: 11px; line-height: 1.25;
  background: var(--surface-2); color: var(--text-strong);
  border-left: 3px solid var(--muted);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}
.week-event:hover { background: var(--surface-3); z-index: 2; }

/* Sharing a minute means sharing the width, so every one of them is clickable. */
.week-event.shared { right: auto; font-size: 10px; padding: 3px 4px; }
.week-event.shared .ev-time { display: none; }
.week-event .ev-time { color: var(--muted); font-variant-numeric: tabular-nums; }
.week-event .ev-name,
.week-event .ev-platform { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.week-event .ev-platform { color: var(--muted); }

.week-event.instagram { border-left-color: var(--instagram); }
.week-event.tiktok { border-left-color: var(--tiktok); }
.week-event.youtube { border-left-color: var(--youtube); }
.week-event.posted {
  border-left-color: var(--success) !important;
  color: #5fd894;
}
.week-event.posted .ev-time, .week-event.posted .ev-platform { color: #4ac57e; }
.week-event.failed { border-left-color: var(--danger); }

/* ---- Dialog ---- */
.agenda-dialog {
  position: fixed; inset: 0; background: rgba(8, 9, 12, 0.7);
  display: none; place-items: center; z-index: 120; padding: 20px;
}
.agenda-dialog.open { display: grid; }
/*
 * Wider, and never taller than the screen.
 *
 * Three platform boxes side by side with a caption and hashtags in each is a
 * tall dialog, and without a ceiling it simply grew past the bottom of the
 * window — the Schedule button ended up somewhere below the glass. Now the card
 * stops at the viewport and the middle scrolls.
 */
.dialog-card {
  background: var(--surface); border-radius: var(--radius);
  padding: 22px; width: 100%; max-width: 1000px;
  max-height: calc(100dvh - 40px);
  display: flex; flex-direction: column;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4);
}

/* Everything but the buttons scrolls, so the buttons are always reachable. */
.dialog-card > .schedule-body { flex: 1; min-height: 0; overflow-y: auto; }
.dialog-card > .dialog-actions { flex: none; padding-top: 12px; }
.dialog-card h3 {
  margin: 0 0 6px; font-size: 17px; color: var(--text-strong); word-break: break-all;
}
.dialog-meta { font-size: 12px; color: var(--muted); margin-bottom: 16px; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.dialog-card .field { margin-bottom: 14px; }
.dialog-card .two-up { display: flex; gap: 12px; }
.dialog-card .two-up .field { flex: 1; }
.dialog-card .hint { font-size: 13px; margin: 0 0 12px; }
.dialog-card .hint a { color: #a5b0ff; }
.dialog-actions { display: flex; gap: 8px; align-items: center; margin-top: 4px; }
.dialog-actions .spacer { flex: 1; }

.empty.small { padding: 20px 8px; font-size: 13px; }
.badge.planned { background: var(--accent-soft); color: #a5b0ff; }
.badge.posted { background: rgba(35, 165, 90, 0.15); color: #4ac57e; }
.badge.failed { background: rgba(242, 63, 67, 0.15); color: #f77b7e; }

/* Three platforms in one dialog: pick which ones, each with its own moment. */
/* Three boxes beside each other: one glance shows all three posts, and the
   dialog widens to fit rather than squeezing them. */
.platform-boxes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 16px; }
.platform-box {
  padding: 10px; border-radius: var(--radius-sm);
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--border);
  border-top: 3px solid var(--muted);
  display: flex; flex-direction: column; gap: 7px;
}
.platform-box.instagram { border-top-color: var(--instagram); }
.platform-box.tiktok { border-top-color: var(--tiktok); }
.platform-box.youtube { border-top-color: var(--youtube); }
.platform-pick { display: flex; align-items: center; gap: 7px; cursor: pointer; }
.platform-pick input { width: auto; margin: 0; }
.platform-name { font-size: 13px; font-weight: 600; color: var(--text-strong); }
.platform-box input[type=date],
.platform-box input[type=time] { width: 100%; font-size: 12px; padding: 5px 7px; }

/* An unticked platform stays readable but stops asking for attention. */
.platform-box:has(input:not(:checked)) { opacity: 0.45; }

@media (max-width: 620px) {
  .platform-boxes { grid-template-columns: 1fr; }
}
.dialog-card textarea { resize: vertical; }

/* The side panel holds two lists: what is planned, and what is waiting. Each
   scrolls on its own so a long queue never pushes the schedule off screen. */
/* Three stacked lists you can drag taller or shorter.
   `flex: 1` on the list used to win over whatever height the drag set, so the
   handle moved and the list sprang straight back. The blocks size to their
   content and the panel scrolls instead. */
/*
 * One scrollbar, not two.
 *
 * The panel scrolled and so did every list inside it, so the Scheduled block
 * carried two bars side by side — one for the list and one for the panel it
 * sits in, six pixels apart and doing different things. The panel holds its
 * height now and the blocks share it out; each list scrolls on its own, which
 * is the bar that belongs to what you are reading.
 */
/*
 * Het paneel scrolt, de blokken niet.
 *
 * Ik had dit op `hidden` gezet om van twee schuifbalken naast elkaar af te
 * komen, en daarmee moesten zes blokken samen op één scherm passen: lijstjes
 * van negenenvijftig pixels met elk hun eigen balkje. Dat is erger dan het
 * probleem dat het oploste.
 *
 * Nu groeien de blokken mee met hun inhoud en loopt de kolom door onder de
 * onderrand, zoals elke lijst dat doet. Eén balk voor het geheel; een blok
 * krijgt er pas zelf een als je hem met de greep korter maakt dan zijn inhoud,
 * en dan is dat precies wat slepen betekent.
 */
.agenda-side {
  display: flex; flex-direction: column; gap: 16px;
  overflow-y: auto; min-height: 0;
}
/*
 * The whole block is what you drag, not the list inside it.
 *
 * The grip used to sit on the list, which is a box with no heading and no edge
 * of its own — so grabbing the bottom of the panel, which is where a panel is
 * grabbed, did nothing. The block resizes; the list fills whatever is left.
 */
.side-block {
  display: flex; flex-direction: column;
  /* Zo hoog als zijn inhoud, en niet meer dan driekwart scherm. Geen `flex: 1`:
     dat verdeelde de beschikbare hoogte over zes blokken, waardoor er van elk
     een strookje overbleef. De greep zet een vaste hoogte wanneer je dat wil. */
  flex: 0 0 auto;
  overflow: hidden;
  min-height: 0; max-height: 75vh;
  padding-bottom: 4px;
}
.side-block h3 { margin-bottom: 4px; flex: none; }
.side-block .side-hint { flex: none; }
/* Alleen scrollen als er een hoogte is opgelegd. Zonder die hoogte groeit het
   blok mee en scrolt de kolom, wat één balk oplevert in plaats van twee. */
.queue.scroll { flex: 1; min-height: 0; overflow: visible; }
.side-block[style*="height"] .queue.scroll { overflow: auto; }

/*
 * The grip runs the whole width of the block.
 *
 * `resize: vertical` gives one grip, in the bottom-right corner, twelve pixels
 * across — so making a list taller meant hunting for a spot the size of a full
 * stop. This is the same drag, over the whole bottom edge, with a line down the
 * middle of it so it looks like something you can pull.
 */
.side-grip {
  flex: none; height: 12px; margin-top: 4px;
  cursor: ns-resize; display: grid; place-items: center;
  touch-action: none;
}
.side-grip::after {
  content: ''; display: block;
  height: 3px; width: 34px; border-radius: 2px; background: var(--border);
  transition: background 0.12s ease, width 0.12s ease;
}
.side-grip:hover::after { background: var(--muted); width: 56px; }
.side-block.dragging .side-grip::after { background: var(--accent); width: 72px; }
body.resizing-block { cursor: ns-resize; user-select: none; }

/*
 * Planned and Posted are laid out exactly like Ready to schedule: the same row,
 * the same 52x32 thumbnail, the same width. They used to be stacked columns
 * with a wide short thumbnail, so the same video looked like a different kind
 * of thing in each of the three lists it passes through.
 *
 * What differs is the colour: each carries the platform it goes out on down its
 * left edge and behind it, so a glance at the column says where, without
 * reading the two-letter tags.
 */
/*
 * All three lists are the same card: the same thumbnail, the same width, the
 * same line under it. Only what is on that line differs — a time and the
 * platforms for a planned one, the countdown for a ready one.
 */
.queue-foot .when-day, .queue-foot .when-time {
  font-size: 11px; color: var(--text-strong); font-variant-numeric: tabular-nums;
}
.queue-foot .when-platforms { font-size: 11px; color: var(--muted); margin-left: auto; }

/*
 * The platform colour is a strip along the bottom of the card, not the card.
 *
 * A whole card washed in platform colour fought with everything written on it —
 * the name, the time, the countdown. Five per cent along the bottom edge reads
 * at a glance and leaves the card legible.
 */
.queue-item.planned,
.queue-item.posted {
  --net: var(--muted);
  position: relative;
  background: var(--surface-2);
  padding-bottom: 12px;
}
/* A video still waiting to be scheduled is not on a platform yet, so a platform
   colour would be inventing one. Only a trial reel gets a strip here — that is
   a fact about the video itself, true before anything is planned. A strip under
   every row regardless would be decoration under everything, which is exactly
   what it was on the Videos tab. */
.queue-item.waiting.is-trial {
  position: relative;
  padding-bottom: 12px;
}
.queue-item.planned::after,
.queue-item.posted::after,
.queue-item.waiting.is-trial::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 10%; min-height: 6px;
  background: var(--split, var(--net));
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}
.queue-item.planned:hover,
.queue-item.posted:hover { background: var(--surface-3); }

/*
 * A trial reel is yellow, whatever it is going out on.
 *
 * It only ever goes to Instagram, so the platform colour says nothing you did
 * not already know — but which of these are trials, at a glance, is the thing
 * you actually want off this list.
 */
.queue-item.is-trial { --net: var(--warning); }
.queue-item.is-trial::after { background: var(--warning); }

.queue-item.for-instagram { --net: var(--instagram); }
.queue-item.for-tiktok { --net: var(--tiktok); }
.queue-item.for-youtube { --net: var(--youtube); }

/* Going out on more than one: the strip below is split between the colours. */
.queue-item.for-many { background-image: none; }
.queue-title {
  font-size: 12px; color: #a5b0ff;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.queue-when {
  display: flex; align-items: baseline; gap: 7px;
  font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.queue-when .when-time { color: var(--text-strong); font-weight: 600; }
.queue-when .when-platforms { margin-left: auto; text-transform: uppercase; letter-spacing: 0.04em; }

/* One colour per category, matching the tags in the logbook. */
.style-dot { padding: 1px 6px; border-radius: 999px; font-size: 10px; }
.style-dot.style-reel { background: rgba(88, 101, 242, 0.25); color: #a5b0ff; }
.style-dot.style-tiktok { background: var(--tiktok-soft); color: #7ed2ee; }
.style-dot.style-trial { background: rgba(217, 131, 36, 0.22); color: #f0b232; }
.style-dot.style-longform { background: rgba(35, 165, 90, 0.2); color: #5fd894; }
.style-dot.style-none { background: var(--surface-3); color: var(--muted); }

/* Per-platform caption, hashtags and how much room is left. */
.platform-box .when-row { display: flex; gap: 6px; }
.platform-box textarea { width: 100%; font-size: 12px; resize: vertical; }
.platform-title { width: 100%; font-size: 12px; }
.counter { font-size: 10px; color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }
.counter.over { color: #ff9093; font-weight: 600; }

.group-note {
  margin-bottom: 12px; padding: 8px 10px;
  background: var(--accent-soft); border-radius: var(--radius-sm);
  font-size: 12px; color: #a5b0ff; line-height: 1.5;
}

/* One strip at the top saying how close the schedule is to running dry. */
.runway {
  font-size: 12px; font-weight: 600;
  padding: 3px 10px; border-radius: 999px;
}
.runway.red { background: rgba(242, 63, 67, 0.2); color: #ff9093; }
.runway.orange { background: rgba(217, 131, 36, 0.25); color: #f0b232; }
.runway.yellow { background: rgba(240, 178, 50, 0.18); color: #ffcc4d; }
.runway.green { background: rgba(35, 165, 90, 0.2); color: #5fd894; }

/* The video beside the boxes: ready to play, not playing. */
.schedule-body { display: flex; gap: 14px; align-items: flex-start; }
.schedule-preview { flex: none; width: 190px; }
.schedule-preview video {
  width: 100%; max-height: 330px; border-radius: var(--radius-sm);
  background: #000; display: block;
}
.schedule-fields { flex: 1; min-width: 0; }

@media (max-width: 720px) {
  .schedule-body { flex-direction: column; }
  .schedule-preview { width: 100%; }
}

/* A video already on some platforms says which, and can be pulled off. */
.queue-item { position: relative; }
.queue-on {
  font-size: 10px; color: #5fd894;
  background: rgba(35, 165, 90, 0.15); padding: 1px 6px; border-radius: 999px;
  align-self: center;
}
/* Two of them now, side by side: the calendar drops the plan, the bin removes
   the video. Both hidden until the row is hovered, so a list of videos is a
   list of videos and not a wall of icons. */
.queue-actions {
  position: absolute; top: 5px; right: 5px;
  display: flex; gap: 4px;
}
.queue-actions:empty { display: none; }

.queue-auto,
.queue-drop,
.queue-remove {
  width: 24px; height: 24px; padding: 0; line-height: 0;
  border-radius: 50%; background: rgba(8, 9, 12, 0.7); color: #ff9093;
  display: grid; place-items: center; opacity: 0;
  transition: opacity 0.12s, background 0.12s, color 0.12s;
}
.queue-item:hover .queue-auto,
.queue-item:hover .queue-drop,
.queue-item:hover .queue-remove { opacity: 1; }
/* Zelf inplannen is de gewone weg vooruit, niet iets om voorzichtig mee te zijn:
   blauw in plaats van het rood van de twee die iets weghalen. */
.queue-auto { color: #a5b0ff; }
.queue-auto:hover { background: var(--accent); color: #fff; }
.queue-auto.bezig { opacity: 1; animation: draai 1.1s linear infinite; }
@keyframes draai { to { transform: rotate(360deg); } }
/* Taking it off the schedule is undoable; removing it is not. Only the second
   turns the full danger colour, so the hand slows down on the right one. */
.queue-drop:hover { background: var(--surface-3); color: #fff; }
.queue-remove:hover { background: var(--danger); color: #fff; }

.queue-drop svg,
.queue-remove svg {
  width: 13px; height: 13px; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}

/* A touch screen has no hover, so they are simply always there. */
@media (hover: none) {
  .queue-drop, .queue-remove { opacity: 1; }
}

/* Each list can be dragged taller or shorter, so the one you are working in
   gets the room. */


.queue-item.posted.gone { opacity: 0.5; cursor: default; }
.queue-item.posted.gone .queue-name { text-decoration: line-through; }

/* On a phone the side panel goes above the calendar rather than beside it. */
@media (max-width: 720px) {
  .agenda-layout { flex-direction: column; overflow-y: auto; }
  .agenda-side { width: auto; max-height: 45vh; }
  .agenda-main { min-height: 60vh; }
  .agenda-head { flex-wrap: wrap; padding: 10px 12px; }
  .agenda-head .range-title { min-width: 0; flex: 1; font-size: 14px; }
  .platform-boxes { grid-template-columns: 1fr; }
  .dialog-card { padding: 16px; max-height: 88vh; overflow-y: auto; }
}

/*
 * Which platforms a change touches. It used to say "changes apply to all of
 * them" and mean it — removing one post removed three.
 */
.platform-ticks { display: flex; gap: 8px; flex-wrap: wrap; }
.platform-ticks .tick {
  display: flex; align-items: center; gap: 7px; cursor: pointer;
  padding: 7px 12px; border-radius: var(--radius-sm);
  background: var(--surface-2); font-size: 13px;
  box-shadow: inset 0 0 0 1px var(--border);
}
.platform-ticks .tick input { width: auto; margin: 0; }
.platform-ticks .tick.instagram { box-shadow: inset 0 0 0 1px var(--instagram); }
.platform-ticks .tick.tiktok { box-shadow: inset 0 0 0 1px var(--tiktok); }
.platform-ticks .tick.youtube { box-shadow: inset 0 0 0 1px var(--youtube); }
.platform-ticks .tick:has(input:not(:checked)) { opacity: 0.45; }

/* The same idea at the top of the tab: which platforms the calendar shows. */
.platform-filter { display: flex; align-items: center; gap: 6px; }
.platform-filter .tick {
  display: flex; align-items: center; gap: 5px; cursor: pointer;
  font-size: 12px; padding: 3px 9px; border-radius: 999px;
  background: var(--surface-2); color: var(--muted);
}
.platform-filter .tick input { width: auto; margin: 0; }
.platform-filter .tick.instagram:has(input:checked) { background: var(--instagram-soft); color: #f39ec0; }
.platform-filter .tick.tiktok:has(input:checked) { background: var(--tiktok-soft); color: #7ed2ee; }
.platform-filter .tick.youtube:has(input:checked) { background: var(--youtube-soft); color: #ef8f93; }

/*
 * The window between a video passing the check and going out on its own.
 * Only drawn while it is running: a control with nothing to control is worse
 * than none at all.
 */
.queue-hold {
  display: flex; align-items: center; gap: 8px;
  margin-top: 6px; font-size: 11px;
  color: var(--warning);
}
.queue-hold.idle { color: var(--muted); }
.hold-clock { flex: 1; min-width: 0; }
.hold-stop {
  flex: none; padding: 2px 9px; border-radius: 999px; font-size: 11px; cursor: pointer;
  border: 1px solid var(--line); background: transparent; color: var(--muted);
}
.hold-stop:hover { border-color: var(--danger); color: var(--danger); }

/* Hashtags are kept but not posted for now, and the box says so. */
.tags-note { margin-top: 2px; font-size: 10px; color: var(--muted); opacity: 0.8; }

/*
 * One day on a phone.
 *
 * Seven columns in 366px is 45px apiece, which is a video name of two letters
 * and an ellipsis over hour marks reduced to stripes. So the week grid draws a
 * single day and the arrows step a day at a time.
 */
@media (max-width: 720px) {
  .calendar.week.one-day .week-head,
  .calendar.week.one-day .week-body { grid-template-columns: 52px minmax(0, 1fr); }
  .calendar.week.one-day .week-day-head .dom { font-size: 22px; }
  .agenda-head .range-title { min-width: 0; flex: 1; }
  .agenda-side { width: 100%; }
}

/*
 * A ready video is a row with the clock underneath it, not beside it.
 *
 * Squeezed onto the same line it took the width the name needed, so every
 * filename ended in an ellipsis. Below, it has the whole card to say what it
 * has to say, and the card is a little taller for it.
 */
.queue-item.stacked { flex-direction: column; align-items: stretch; gap: 6px; }
.queue-item.stacked .queue-main { display: flex; gap: 10px; align-items: center; }
.queue-item.stacked .queue-hold {
  margin-top: 0; padding-top: 6px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}

/* A trial reel that earned a second outing. */
.queue-item.winner {
  background: color-mix(in srgb, var(--success) 10%, var(--surface-2));
  box-shadow: inset 3px 0 0 var(--success);
}
.queue-item.winner .queue-thumb { background: transparent; font-size: 20px; }
.winner-left {
  display: flex; align-items: center; gap: 8px;
  padding-top: 6px; font-size: 11px; color: var(--muted);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.winner-left button { margin-left: auto; }

/*
 * What a posted trial did, on every network it reached.
 *
 * Opened from the Posted list rather than only from the winners block: a trial
 * under the bar still has numbers worth reading, and is still something you may
 * want to put on TikTok anyway.
 */
.perf-box { width: min(520px, 100%); }
.perf-title { margin: 0 26px 10px 0; font-size: 15px; color: var(--text-strong); }
.perf-rows { display: flex; flex-direction: column; gap: 6px; }
.perf-row {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  padding: 8px 10px; border-radius: var(--radius-sm); background: var(--surface-2);
}
.perf-net { font-weight: 700; font-size: 12px; min-width: 74px; }
.perf-views { font-size: 15px; color: var(--text-strong); font-weight: 700; }
.perf-rest { font-size: 11px; color: var(--muted); }
.perf-open { margin-left: auto; font-size: 11px; }
.perf-note { margin: 10px 0 8px; font-size: 12px; color: var(--muted); }
.perf-take { width: 100%; }

/*
 * The name gets the whole width of the row.
 *
 * "on Instagram" and the countdown used to sit on the same line as the name and
 * took the space it needed, so every filename ended in an ellipsis. They live
 * on a line of their own underneath now, which is what makes the card a little
 * taller and the name readable.
 */
.queue-item.stacked .queue-text { flex: 1; min-width: 0; }
.queue-foot {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding-top: 6px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.queue-foot .queue-hold { margin-top: 0; padding-top: 0; box-shadow: none; flex: 1; }
.queue-foot .queue-on { font-size: 11px; color: var(--muted); }

/*
 * An event gets out of the way while you are placing a video.
 *
 * A taken moment used to cover its whole slot, so putting a second video at the
 * same time meant there was nothing left under the pointer to click. With a
 * video picked, pointing at an event shrinks it — to half the width, or two
 * thirds when two already share the moment — and what it gives up is the slot
 * behind it.
 */
.week-col.droppable .week-event:hover {
  width: var(--shrunk);
}
.week-event { transition: width 0.12s ease; }

/*
 * Where the day has got to.
 *
 * Only on today, and only in the week grid. It sits above the hour marks and
 * below the events, and takes no clicks — the slot behind it is still a slot
 * you can schedule into.
 */
.now-line {
  position: absolute; left: 0; right: 0; height: 0;
  border-top: 2px solid var(--danger);
  z-index: 2; pointer-events: none;
}
.now-dot {
  position: absolute; left: -1px; top: -4px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--danger);
}

/* Videos whose moment came and went without the platform publishing them. */
.queue-item.failed {
  --net: var(--danger);
  background: color-mix(in srgb, var(--danger) 12%, var(--surface-2));
  box-shadow: inset 3px 0 0 var(--danger);
}
.queue-item.failed:hover { background: color-mix(in srgb, var(--danger) 20%, var(--surface-2)); }

/*
 * The next good hour still to come.
 *
 * `.next-up` marks where the scheduler intends to put something, which is
 * usually days away — so on the day you are looking at, nothing was lit and an
 * hour this afternoon read the same as one that went by this morning. This is
 * the first one you can still act on, so it is filled rather than outlined.
 */
.hour-slot.next-best::after {
  content: '';
  position: absolute; inset: 3px 4px;
  border-radius: 7px;
  box-shadow: inset 0 0 0 2px var(--warning);
  background: color-mix(in srgb, var(--warning) 26%, transparent);
  pointer-events: none;
}
/* Both at once: the plan wins the fill, this keeps the brighter ring. */
.hour-slot.next-best.next-up::after {
  box-shadow: inset 0 0 0 2px var(--warning), inset 0 0 0 5px color-mix(in srgb, var(--warning) 35%, transparent);
}

/* Hoeveel uren gemarkeerd worden, naast de platformvinkjes. */
.tick.marks { display: inline-flex; align-items: center; gap: 6px; }
.tick.marks select {
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 1px 4px; font-size: 12px;
}

/* Wat op een titel wacht, achter één knop bovenin.
   Het stond als eigen blok in de zijkolom, direct onder Gepland en met zijn
   eigen schuifbalk — dus daar stonden er twee naast elkaar waar de andere
   blokken er een hadden. Een video zonder titel is ook niet gepland. */
.untitled-backdrop {
  position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, 0.6);
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.untitled-box {
  background: var(--surface); border-radius: 12px; padding: 14px;
  width: min(560px, 100%); max-height: 80vh; overflow: auto;
}
.untitled-box header { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.untitled-box h3 { margin: 0; flex: 1; font-size: 15px; }

/* Uit een lijst halen. Verschijnt bij het aanwijzen, zoals de prullenbak in de
   chat: er als je hem zoekt, weg als je leest. */
.queue-item { position: relative; }
.queue-dismiss {
  /* Geen eigen hoek meer: hij staat in de rij met de andere knoppen, want twee
     dingen in dezelfde hoek betekent dat er één onbereikbaar is. */
  border: none; background: rgba(8, 9, 12, 0.7); color: var(--muted);
  font-size: 12px; line-height: 1; cursor: pointer;
  opacity: 0; transition: opacity 0.12s ease;
  width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
}
.queue-item:hover .queue-dismiss { opacity: 1; }
.queue-dismiss:hover { color: var(--danger, #e5484d); background: var(--surface-2); }

/*
 * De cijfers naast een geposte video.
 *
 * Ze zaten achter een klik, en dat is één klik te veel voor het enige getal dat
 * telt: van vier trial reels wil je in één blik zien welke won.
 */
.when-views { margin-left: auto; font-variant-numeric: tabular-nums; color: var(--text-strong); }
.when-views.won { color: #5fd894; font-weight: 700; }
.trial-tools { padding-top: 6px; }
.trial-tools button { width: 100%; }

/* Waarom een rij in deze lijst staat. "Mislukt" en "Metricool is hem kwijt"
   zijn twee verschillende dingen en vragen om twee verschillende acties. */
.when-why { margin-left: auto; font-size: 11px; color: var(--muted); }
.queue-item.withdrawn .when-why { color: var(--warning); }

/*
 * Een trial reel is geel, geen Instagram-roze.
 *
 * Het streepje links vertelt naar welk platform iets gaat, en trials gaan altijd
 * naar Instagram — dus stonden vier proeven en de echte reel in exact dezelfde
 * kleur op dezelfde dag. Bij een trial is niet het platform de vraag maar dat
 * het een proef is, en dat is wat de kleur nu zegt.
 */
.post-chip.is-trial, .week-event.is-trial { border-left-color: var(--warning) !important; }
.week-event.is-trial .ev-platform, .post-chip.is-trial .chip-time { color: var(--warning); }

/* Een proef die op zijn hoofdvideo wacht: geen storing maar een volgorde. */
.queue-hold.wacht { color: var(--warning); }
.queue-hold.wacht .hold-clock { color: var(--warning); }
