/* The queue: every image in the run, and which one the stage is showing.
 *
 * It is a listbox, not a set of cards. Each row carries four facts in a fixed
 * order - a thumbnail, the name, what it weighs now, and how much that saved -
 * so the column of numbers can be read down without reading any row. A row that
 * is still working says what it is doing in place of the numbers it does not
 * have yet, rather than showing a placeholder where a result will later appear.
 */

/* First in the sidebar now - the pictures are step one of the story - so the
   dividing rule belongs to the plan below, not to this region's top edge. */
#queue-sec {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  min-height: 0;
}

#plan-sec { border-top: 1px solid var(--c-line); }

#queue-list {
  overflow-y: auto;
  min-height: 0;
  padding: 0 var(--s-2) var(--s-2);
}
#queue-list:focus-visible { outline-offset: -2px; }

.row {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  align-items: center;
  gap: 0 var(--s-3);
  width: 100%;
  padding: var(--s-2);
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition:
    background-color var(--dur-fx) var(--ease-fx),
    border-color var(--dur-fx) var(--ease-fx),
    box-shadow var(--dur-fx) var(--ease-fx);
}
.row:hover { background: var(--c-raised); box-shadow: var(--elev-1); }

/* The one on the stage. Marked with the system's selected fill and a left
   edge, not colour alone, and aria-selected carries the same fact to anything
   not looking at pixels. */
.row[aria-selected="true"] {
  background: var(--c-selected);
  border-color: var(--c-border-selected);
  box-shadow: inset 2px 0 0 var(--c-accent);
}

.row > .thumb {
  grid-row: 1 / span 2;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  object-fit: cover;
  background: var(--c-sunk);
  box-shadow: var(--elev-1);
}
/* Not decoded yet: a quiet shimmer says "coming", where a blank square says
   "broken". The global reduced-motion rule in base.css stills it. */
.row > .thumb:not([src]) {
  background-image: linear-gradient(100deg,
    var(--c-sunk) 40%, var(--c-raised) 50%, var(--c-sunk) 60%);
  background-size: 200% 100%;
  animation: thumb-wait 1.4s linear infinite;
}
@keyframes thumb-wait {
  from { background-position: 120% 0; }
  to { background-position: -80% 0; }
}

/* The standing invitation under the list. */
#queue-hint {
  padding: var(--s-1) var(--s-4) var(--s-2);
  font-size: 13px;
  text-align: center;
}

/* Middle truncation: the head gives way, the tail - the distinguishing
   characters and the extension - survives at any width. */
.row > .name {
  grid-column: 2;
  display: flex;
  min-width: 0;
  white-space: nowrap;
}
.row .name-head {
  flex: 0 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.row .name-tail { flex: none; }

/* What this row is holding, when that is not obvious from the thumbnail: a
   video, and how long it runs. It sits after the name and never gives way to
   truncation, because "why is this one taking two minutes" is answered here
   and nowhere else on the row. */
.row .kind {
  flex: none;
  margin-left: var(--s-2);
  padding: 0 var(--s-1);
  border: 1px solid var(--c-line);
  border-radius: var(--radius-sm);
  font-size: 13px;
  line-height: 1.5;
  color: var(--c-ink-3);
}

/* Decision D5: video is purple where an image is the brand accent. The badge
   already says "Video" in words and carries the running time - the colour is
   a second and faster signal in a mixed queue, never the only one, so a
   person who does not separate these two hues loses nothing. */
.row[data-kind="video"] .kind {
  border-color: var(--c-media-video);
  color: var(--c-media-video);
}

/* The row's own actions, revealed by attention: hover or focus on a pointer,
   always present where there is no hover to have. They sit over the size
   column so nothing jumps when they appear. */
.row > .row-acts {
  grid-column: 3;
  grid-row: 1 / span 2;
  display: none;
  align-items: center;
  gap: var(--s-1);
  justify-self: end;
}
.row:hover > .row-acts,
.row:focus-within > .row-acts { display: inline-flex; }
.row:hover > .now,
.row:focus-within > .now { visibility: hidden; }
/* No hover to have: the actions get their own column and the size stays. */
@media (pointer: coarse) {
  .row { grid-template-columns: 40px minmax(0, 1fr) auto auto; }
  .row > .row-acts { display: inline-flex; grid-column: 4; grid-row: 1 / span 2; }
  .row > .now { visibility: visible; }
  .row:hover > .now { visibility: visible; }
  .row-act { width: var(--s-target); }
}
.row-act {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid var(--c-line);
  border-radius: var(--radius-sm);
  background: var(--c-raised);
  color: var(--c-ink-2);
  cursor: pointer;
  transition:
    color var(--dur-fx) var(--ease-fx),
    border-color var(--dur-fx) var(--ease-fx);
}
.row-act:hover { color: var(--c-ink); border-color: var(--c-line-hover); }
.row-act.rm:hover { color: var(--c-bad); border-color: var(--c-bad); }

/* The weight after compressing, right-aligned so the column reads as a column */
.row > .now {
  grid-column: 3;
  grid-row: 1;
  font-size: 14px;
  color: var(--c-ink-2);
}

/* Second line: either the saving, or what this row is doing right now. */
.row > .sub {
  grid-column: 2 / span 2;
  grid-row: 2;
  font-size: 14px;
  color: var(--c-ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.row > .sub.good { color: var(--c-good); }
.row > .sub.bad { color: var(--c-bad); }

/* Per-row progress, under the row it belongs to. */
.row > .track {
  grid-column: 1 / span 3;
  grid-row: 3;
  height: 2px;
  margin-top: var(--s-1);
  background: var(--c-line);
  border-radius: 2px;
  overflow: hidden;
}
/* A transform, not a width - see the note on #batch in layout.css. */
.row > .track > i {
  display: block;
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: var(--c-accent);
  transition: transform 0.2s linear;
}

/* ------------------------------ empty state ------------------------------ */

/* What to do, and nothing else. No headline, no pitch, no format badges - the
   one sentence that tells a first-time visitor which action starts the work.
   It is also the drop target, which is why it fills its region rather than
   sitting centred in a box of its own.

   A flex column, not a grid: a grid's auto column is sized by max-content, so
   the unwrapped width of one sentence propagated up through the sidebar's own
   column and pushed every region under the stage. Flex children get exactly
   the region's width and the sentences wrap inside it. */
#queue-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  padding: var(--s-6) var(--s-4);
  text-align: center;
  color: var(--c-ink-3);
}
#queue-empty > * { max-width: 100%; }

/* The whole window accepts a drop. Saying so only while something is being
   dragged keeps the affordance out of the way the rest of the time. */
body[data-drag="1"] #side { outline: 2px dashed var(--c-accent); outline-offset: -4px; }

#queue-foot {
  padding: var(--s-2) var(--s-4);
  border-top: 1px solid var(--c-line);
  font-size: 14px;
  color: var(--c-ink-3);
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
