/* ==========================================================================
   THE CONNECTIONS BOARD: the looping hero. A port of the live Good Call hero
   Armen approved (concept 2, 2026-09-01: "a network of automations and
   connections, like n8n"). Three inputs run into the business number and out
   to three results, one path at a time, then all at once, then the payoff line.
   Same layout, geometry, timing and loop as the original.
   Armen 2026-10-01 on the first port ("this looks stupid"): no faded grey
   cards, no grey hub, no box around the board, no dot texture behind it. So
   the board sits straight on the hero with no panel or frame; a card waiting
   for the run is a solid dark card (one step lighter than night, paper text);
   the card the run reaches turns paper with ink text and a saddle edge; the
   hub is always paper with the full-colour logo. State changes by colour,
   never by opacity. Flat colours, no gradients, no glow, one 1px border.
   Authored at 400x480 and scaled to the column by js/connections.js, so one
   set of coordinates serves every width and the wires can never miss a node.
   Every rule is scoped to .stage: site.css has its own .ico and .row.
   ========================================================================== */
.stage{position:relative;justify-self:end;align-self:center;width:400px;max-width:100%;
  cursor:pointer;color:var(--c-on-dark);
  /* a grid item's min-width:auto is its MIN-CONTENT width, and the board is a 400px block
     that is only ever scaled by transform, so without this the stage refuses to shrink
     and the phone gets a horizontal scrollbar. */
  min-width:0}
.stage .scenelab{display:flex;flex-direction:column;align-items:center;text-align:center;margin:0 0 18px}
.stage .scenelab .sl1{font-family:var(--f-body);font-size:17px;font-weight:700;line-height:1.4;
  color:var(--c-accent-on-dark);text-wrap:balance;max-width:360px}
.stage .cvfit{position:relative;overflow:hidden}
.stage .cv{position:relative;width:400px;transform-origin:top left}
.stage .cv svg.wires{position:absolute;inset:0;width:100%;height:100%;max-width:none;overflow:visible;pointer-events:none}
.stage .wires .base{fill:none;stroke:var(--c-wire);stroke-width:1.6;stroke-linecap:round}
/* linecap MUST stay butt. With pathLength=1 + dasharray:1 the hidden state is a zero-length
   dash, and a round cap paints a dot at the node before the run reaches it. */
.stage .wires .live{fill:none;stroke:var(--c-wire-live);stroke-width:2;stroke-linecap:butt;
  stroke-dasharray:1;stroke-dashoffset:1;transition:stroke-dashoffset .55s linear}
.stage .wires .live.go{stroke-dashoffset:0}

/* the nodes. Waiting: a solid dark card with paper text. Text and icon inherit the card's
   colour so the whole card changes in one transition. */
.stage .nd{position:absolute;display:flex;align-items:center;gap:8px;padding:0 10px;
  background:var(--c-node-off);border:1px solid var(--c-node-off-edge);border-radius:var(--radius);
  color:var(--c-node-off-text);transition:background-color .3s ease,border-color .3s ease,color .3s ease}
.stage .nd .ico{flex:none;display:flex;align-items:center;justify-content:center;width:28px;height:28px;
  border-radius:var(--radius);background:var(--c-node-off-ico);color:inherit;transition:background-color .3s ease}
.stage .nd .txt{min-width:0}
.stage .nd b{display:block;font-family:var(--f-body);font-weight:700;font-size:17px;line-height:1.25;color:inherit}
.stage .nd i{display:block;font-style:normal;font-family:var(--f-body);font-size:15px;line-height:1.3;
  color:inherit;margin-top:3px}
/* the three inputs sit three-across in 400px, so their label wraps to two lines */
.stage .nd.in b{font-size:16px;line-height:1.2}

/* Lit: the run has reached it. Paper, ink text, saddle edge. Without .js-motion (no JS, or
   reduced motion) nothing animates and the board shows its finished frame: every card lit. */
.stage .nd.on,html:not(.js-motion) .stage .nd{background:var(--c-node);border-color:var(--c-node-edge-on);color:var(--c-node-text)}
.stage .nd.on .ico,html:not(.js-motion) .stage .nd .ico{background:var(--c-node-ico)}

/* the hub: the Top Crew logo in full colour and the business number, always on paper and
   always readable. The run reaching it only turns its edge saddle. */
.stage .hub{position:absolute;display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;padding:0 14px;background:var(--c-node);border:1px solid var(--c-node);
  border-radius:var(--radius);color:var(--c-node-text);transition:border-color .3s ease}
.stage .hub.on,html:not(.js-motion) .stage .hub{border-color:var(--c-node-edge-on)}
.stage .hub .lockup{height:44px;width:auto;max-width:100%;margin:0 auto}
.stage .hub em{display:block;font-style:normal;font-family:var(--f-body);font-size:15px;line-height:1.35;
  color:var(--c-node-text);margin-top:10px}

.stage .cvcap{font-family:var(--f-body);font-size:17px;line-height:1.4;color:var(--c-on-dark);text-align:center;
  margin-top:18px;opacity:0;transition:opacity .4s ease}
.stage .cvcap.on{opacity:1}
/* at this size the line no longer fits in one, so the second sentence wraps whole */
.stage .cvcap b{font-weight:700;display:inline-block}

/* Playback gating, the rest of the finished frame: every wire drawn, the payoff line shown. */
html:not(.js-motion) .stage .wires .live{stroke-dashoffset:0}
html:not(.js-motion) .stage .cvcap{opacity:1}

@media (min-width:901px) and (max-height:760px){
  .stage .scenelab{margin-bottom:12px}
}
@media (max-width:900px){
  /* below the text column the board is full width, capped */
  .stage{justify-self:start;width:100%;max-width:400px}
}
