/* ==========================================================================
   Workflow Studio — showreel
   rundown.css
   The capability and architecture boards: entries drawn as nodes, their ports, their wires, and the dragging.
   ========================================================================== */

/* --- Rundowns (capabilities, architecture) ---------------------------------
   One pattern, two sections. The heading holds the top left, a line drawing
   sits opposite it, and the numbered entries run underneath across the full
   measure. Six entries down a single column came to some 970px on their own —
   a screen and a half of scrolling that no amount of tightening was going to
   recover, so the height comes out of the distribution instead. Entry count is
   the only thing that differs, hence --rundown-cols.
   -------------------------------------------------------------------------- */

.rundown {
  position: relative;
  /* Tighter than the shared .section rhythm: a column of entries is a lot of
     scrolling, so the section earns some of its padding back. */
  padding: 88px 0;
  /* The graph canvas the entries are dragged around on. Faint enough to be
     read as a surface rather than as a pattern. */
  background-image: radial-gradient(
    circle,
    rgba(255, 255, 255, 0.06) 1px,
    transparent 1px
  );
  background-size: 22px 22px;
}

.rundown-inner {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1fr);
  column-gap: clamp(40px, 6vw, 104px);
  row-gap: clamp(28px, 3vw, 44px);
}

.rundown-head {
  grid-area: 1 / 1;
  max-width: 460px;
}

.rundown-head h2 {
  font-size: clamp(28px, 3.4vw, 40px);
  margin: 0 0 12px;
}

/* Its own line, in accent: the rest of the heading lands as the answer to it. */
.rundown-lead {
  display: block;
  color: var(--accent);
}

.rundown-head p {
  color: var(--text-muted);
  font-size: 16px;
  max-width: 34ch;
}

.rundown-list {
  /* The full measure, under the heading rather than beside it. */
  grid-area: 2 / 1 / 3 / -1;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(var(--rundown-cols, 2), minmax(0, 1fr));
  column-gap: clamp(32px, 5vw, 80px);
  row-gap: clamp(30px, 3vw, 44px);
}

/* Three entries do not divide into two columns without leaving a hole. */
.rundown-list.is-three {
  --rundown-cols: 3;
}

/* --- Rundown entries as nodes -----------------------------------------------
   The entries are drawn as Workflow Studio draws a node: a header strip with a
   thumbnail and a name, then a body holding a collapsible parameter block. It
   is the product's own chrome quoted back, so the proportions come from it —
   a dense header, a tight body, and a title sized for a node rather than for a
   section heading.
   -------------------------------------------------------------------------- */

.rundown-item {
  /* Carries the drag offset and the stacking order. */
  position: relative;
  border: 1px solid var(--border);
  border-radius: 10px;
  /* Translucent so the line drawing behind still reads through a card that
     lands on top of it. */
  background: rgba(18, 18, 20, 0.92);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35);
}

/* The ports. One in, one out, sitting off the edge rather than on it. The box
   is 18px so there is something to aim at; the dot inside it is the 7px the
   design actually wants. */
.node-port {
  position: absolute;
  width: 18px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.node-port::after {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--port);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.node-port-in {
  left: -9px;
  top: calc(44% - 9px);
}

.node-port-out {
  right: -9px;
  bottom: 19px;
}

/* Wiring is a pointer-fine affordance like the dragging, so the crosshair and
   the hover only show up where a wire can actually be pulled. */
.rundown-inner.is-board .node-port {
  cursor: crosshair;
}

.rundown-inner.is-board .node-port:hover::after,
.node-port.is-live::after {
  transform: scale(1.5);
  box-shadow: 0 0 0 4px rgba(255, 45, 155, 0.18);
}

/* --- Wires ------------------------------------------------------------------
   One overlay per board, drawn in the board's own pixel space so a card's
   offset and a wire's endpoints are read off the same box. Behind the cards,
   as they are in the product: a graph is nodes over wires.
   -------------------------------------------------------------------------- */

.node-wires {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  overflow: visible;
  /* Only the wires themselves take the pointer, never the empty overlay. */
  pointer-events: none;
}

.node-wire {
  fill: none;
  stroke: var(--port);
  stroke-width: 2;
  stroke-linecap: round;
  opacity: 0.75;
}

/* The click target: invisible, and the only part of a wire that is hit. */
.node-wire-hit {
  fill: none;
  stroke: transparent;
  stroke-width: 14;
  pointer-events: stroke;
  cursor: pointer;
}

.node-wire-hit:hover + .node-wire {
  opacity: 1;
  stroke-width: 3;
}

/* Nothing is connected to it yet, so it is drawn as a proposal. */
.node-wire.is-live {
  stroke-dasharray: 5 5;
  opacity: 0.9;
}

/* Over the wires, and the last card picked up over the rest. */
.rundown-item {
  z-index: 1;
}

/* Told to the pointer that can act on it, and only once the script is in. */
.board-hint {
  margin-top: 14px;
  font-size: 13px;
  color: var(--text-muted);
  opacity: 0.75;
}

.board-hint b {
  font-weight: 500;
  color: var(--text-dim);
}

.node-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: rgba(255, 255, 255, 0.045);
  border-bottom: 1px solid var(--border);
  /* Matched to the card, one pixel of border in: a square corner over a round
     one is the giveaway that the strip is painted on rather than part of it. */
  border-radius: 9px 9px 0 0;
}

/* Stands in for the workflow thumbnail the product puts here. */
.node-tile {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 24px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: rgb(12, 12, 13);
  color: var(--text-dim);
}

.rundown-icon {
  width: 15px;
  height: 15px;
  opacity: 0.75;
}

/* Sized as a node name, not as a section heading: at heading size the header
   strip stops being a strip. */
.node-head h3 {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: clamp(15px, 1.3vw, 17px);
  font-weight: 600;
  line-height: 1.25;
}

/* Where the run button sits in the product — same corner, same weight, but it
   is the entry number and it does not pretend to be a control. */
.rundown-num {
  flex: none;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 4px;
  padding: 3px 6px;
}

.node-body {
  padding: 12px 12px 16px;
}

.node-section {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

/* Open, like the parameter block of a node being worked on. */
.node-caret {
  width: 7px;
  height: 7px;
  margin-right: 2px;
  border-top: 1.4px solid currentColor;
  border-right: 1.4px solid currentColor;
  transform: rotate(-45deg);
  opacity: 0.7;
}

/* The copy reads as the value of a field, which is what earns the node its
   body: an inset well, darker than the card that holds it. */
.node-field {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgb(12, 12, 13);
  padding: 11px 12px;
}

.rundown-item p {
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1.55;
}

/* The stack behind an entry, set in mono: names of things, not prose. */
.rundown-tech {
  display: block;
  margin-top: 10px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--text-muted);
  opacity: 0.8;
}

/* --- Dragging ---------------------------------------------------------------
   Both transform rules are written against .reveal on purpose: the scroll
   reveal owns transform on this element, and a bare .rundown-item would lose
   to it. The offset is folded into the reveal's own rise instead of fighting
   it.
   -------------------------------------------------------------------------- */

.rundown-item.reveal {
  transform: translate3d(var(--dx, 0px), calc(var(--dy, 0px) + 18px), 0);
}

.rundown-item.reveal.visible {
  transform: translate3d(var(--dx, 0px), var(--dy, 0px), 0);
}

/* Only under .is-board: the affordance is set by the script that can honour
   it, so a pointer that is never given the behaviour is never offered it. */
.rundown-inner.is-board .rundown-item {
  cursor: grab;
  /* A drag across a paragraph is a drag, not a selection. */
  user-select: none;
}

.rundown-inner.is-board .rundown-item:hover {
  border-color: var(--border-strong);
}

.rundown-item.is-dragging {
  cursor: grabbing;
  /* The reveal's 0.6 s ease on transform would run the card a beat behind the
     cursor for the whole drag. */
  transition: none;
  border-color: var(--border-selected);
  box-shadow: 0 22px 46px rgba(0, 0, 0, 0.55);
}

/* --- Rundown line drawings --------------------------------------------------
   Positioned off the section (they are children of it, not of the container)
   but inset to the container's own right edge, so they line up with the type
   rather than floating out into the page margin. No bleed and no mask: every
   shape is meant to be whole. Both are drawn on the same 620x300 field, wide
   and shallow so they clear the list without being clipped to get there.
   -------------------------------------------------------------------------- */

.rundown-art {
  position: absolute;
  top: clamp(36px, 4.5vw, 68px);
  right: max(24px, calc((100% - var(--max-w)) / 2 + 24px));
  width: min(46vw, 520px);
  aspect-ratio: 620 / 300;
  color: var(--accent);
  pointer-events: none;
}

.rundown-art svg {
  width: 100%;
  height: 100%;
}

/* The architecture heading runs a line shorter than the capabilities one, so its
   list starts higher up and the drawing has to be smaller to stay clear of it.
   Same precedent as #showreel's wider measure. */
#architecture .rundown-art {
  top: clamp(28px, 3.4vw, 48px);
  width: min(40vw, 460px);
}

.rundown-art .art-lines {
  opacity: 0.3;
}

.rundown-art .art-ports {
  opacity: 0.55;
}

/* One dash, then a gap longer than any line it runs on, so a single pulse
   travels the length and the line is empty for the rest of the cycle — a queue
   picking jobs up, not a dotted line. Negative delays, so they are already in
   flight rather than setting off together on load. */
.rundown-art .art-flow use {
  stroke-dasharray: 14 320;
  animation: art-flow 3.6s linear infinite;
}

.rundown-art .art-flow use:nth-child(2) {
  animation-delay: -1.6s;
}

.rundown-art .art-flow use:nth-child(3) {
  animation-delay: -3.2s;
}

.rundown-art .art-flow use:nth-child(4) {
  animation-delay: -2.4s;
}

.rundown-art .art-flow use:nth-child(5) {
  animation-delay: -0.8s;
}

@keyframes art-flow {
  from {
    stroke-dashoffset: 0;
  }
  to {
    stroke-dashoffset: -334;
  }
}

@media (prefers-reduced-motion: reduce) {
  .rundown-art .art-flow {
    display: none;
  }
}
