/* ---------- canvas ---------- */
.canvas{position:relative;flex:1;min-width:0;overflow:hidden;touch-action:none;cursor:grab;
  background:radial-gradient(circle at 1px 1px,var(--bg-dot) 1px,transparent 0),var(--bg);
  background-size:var(--grid,24px) var(--grid,24px),auto;
  background-position:var(--gx,0px) var(--gy,0px),0 0}
.canvas:active{cursor:grabbing}
.canvas.linking,.canvas.linking *{cursor:crosshair}
.world{position:absolute;top:0;left:0;transform-origin:0 0;will-change:transform}
.edges{position:absolute;top:0;left:0;overflow:visible;pointer-events:none}
.edges path.hit{pointer-events:stroke;stroke:transparent;stroke-width:20;fill:none;cursor:pointer}

/* ---------- node card ---------- */
.node{position:absolute;top:0;left:0;padding:14px;border-radius:18px;
  background:linear-gradient(180deg,var(--card-a),var(--card-b));border:1px solid var(--stroke);
  box-shadow:var(--card-shadow);cursor:grab;user-select:none;will-change:transform}
.node:hover{border-color:var(--stroke-hi)}
.node.sel{border-color:var(--accent-ink);box-shadow:0 0 0 1px var(--accent-ink),0 18px 44px -22px var(--accent-ink)}
.node.dragging{cursor:grabbing;z-index:5}
.node.droptarget{border-color:var(--accent-ink);box-shadow:0 0 0 2px var(--accent-ink)}

/* ---- flow playback: which box the agent is touching right now ---- */
.node.done{opacity:.62}
/* Glow only -- never transform, the card's transform is its position. */
.node.active{border-color:var(--accent-ink);animation:nodeGlow 1.5s ease-in-out infinite}
@keyframes nodeGlow{
  0%,100%{box-shadow:0 0 0 2px var(--accent-ink),0 0 22px -8px var(--accent-ink),var(--card-shadow)}
  50%    {box-shadow:0 0 0 2px var(--accent-ink),0 0 40px 2px var(--accent-ink),var(--card-shadow)}}
.node.waiting{animation:none;border-color:var(--amber);
  box-shadow:0 0 0 2px var(--amber),0 0 34px -6px var(--amber),var(--card-shadow)}
/* The box in play sits above its neighbours -- the gate grows taller than its slot. */
.node.active,.node.waiting{z-index:6}
.node.active .tile{animation:tilePulse 1.5s ease-in-out infinite}
@keyframes tilePulse{0%,100%{transform:scale(1)}50%{transform:scale(1.07)}}
.tile.m365{background:none;border:0}

/* The wire draws itself downward into the box that just appeared, then a
   travelling spark keeps running while that box is the one in play. */
.edges g.live path.draw{stroke-dasharray:1;stroke-dashoffset:1;
  animation:wireDraw .52s cubic-bezier(.4,0,.2,1) forwards}
@keyframes wireDraw{to{stroke-dashoffset:0}}
.edges g.live .pulse{stroke-dasharray:.08 .92;stroke-linecap:round;opacity:0;
  animation:wireSpark 1.25s linear .5s infinite}
@keyframes wireSpark{0%{stroke-dashoffset:1;opacity:.95}100%{stroke-dashoffset:0;opacity:.95}}
.edges g.spent path:not(.hit){stroke:var(--accent-ink);opacity:.5}

/* A box fades up as the flow reaches it. No delay: opening an app is now a step
   of its own, so nothing has to wait for the machine to catch up. */
.node{animation:nodeIn .3s cubic-bezier(.34,1.2,.5,1) both}
@keyframes nodeIn{from{opacity:0}to{opacity:1}}

/* The camera glides to the step instead of jumping. Only while auto-panning --
   dragging the canvas must stay pinned to the pointer. */
.world.glide{transition:transform .55s cubic-bezier(.4,0,.2,1)}

/* Before the first step there is nothing on the canvas but this. */
.startcue{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:4;
  display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center;
  color:var(--muted);pointer-events:none}
.startcue b{font-size:15px;font-weight:600;color:var(--text)}
.startcue span{font-size:12.5px;max-width:300px;line-height:1.55}
/* An address with no scenario behind it: the cue alone, with a way out. */
.canvas.nothing{cursor:default}
.nothing .startcue{pointer-events:auto}
.nothing .startcue a{text-decoration:none;margin-top:6px}

/* Approval waiting on a person: the only thing on the canvas you click. */
.gate{margin-top:13px;padding-top:13px;border-top:1px solid var(--panel-bd)}
.gq{font-size:14px;color:var(--text);line-height:1.55}
.gbtns{display:flex;gap:8px;margin-top:11px}
.gbtns button{display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 12px;border-radius:9px;
  border:1px solid var(--stroke-hi);background:var(--card-b);color:var(--text);font:inherit;font-size:13px;
  font-weight:600;cursor:pointer}
.gbtns .gy{background:var(--brand);border-color:transparent;color:var(--brand-fg)}
.gbtns .gy:hover{filter:brightness(1.08)}
.gbtns .gn:hover{border-color:#7f1d1d;color:#fca5a5}

/* Transport, pinned to the bottom of the canvas. */
.transport{position:absolute;left:50%;bottom:16px;transform:translateX(-50%);z-index:20;
  display:flex;align-items:center;gap:6px;padding:6px;border-radius:12px;
  background:var(--panel);border:1px solid var(--stroke-hi);box-shadow:var(--pop-shadow)}
.transport button{display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 10px;border-radius:8px;
  border:1px solid transparent;background:transparent;color:var(--text);font:inherit;font-size:13px;
  cursor:pointer;white-space:nowrap}
.transport button:hover:not(:disabled){background:var(--panel-hi)}
.transport button:disabled{opacity:.34;cursor:default}
.transport .tsep{width:1px;height:20px;background:var(--stroke);flex:none;margin:0 2px}
.transport .ticon{padding:0;width:30px;justify-content:center}
/* The caption is what the presenter reads out before clicking Forward. */
.transport .tcap{display:flex;flex-direction:column;align-items:center;justify-content:center;
  min-width:216px;padding:0 12px;line-height:1.3;text-align:center}
.transport .tcap b{font-size:13px;font-weight:600;color:var(--text);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;max-width:280px}
.transport .tcap span{font-size:10.5px;color:var(--muted);font-variant-numeric:tabular-nums}
/* The end of a run: Copilot, a thumbs up, and the sign-off underneath. */
.transport .tcap.done b{display:flex;align-items:center;gap:7px;line-height:1}
.transport .tcap.done b img{display:block}
.transport .tcap.done .thumb{font-size:17px;line-height:1}
.transport .tcap.done > span{font-size:13px;font-weight:600;color:var(--brand);margin-top:3px}
.transport .tfwd{background:linear-gradient(160deg,var(--brand),var(--brand-2));
  border-color:transparent;color:var(--brand-fg);font-weight:600;padding:0 13px}
.transport .tfwd:hover:not(:disabled){filter:brightness(1.08);background:
  linear-gradient(160deg,var(--brand),var(--brand-2))}
.nhead{display:flex;align-items:center;gap:12px}
.tile{width:44px;height:44px;border-radius:12px;flex:none;display:grid;place-items:center;
  background:linear-gradient(160deg,var(--accent),var(--accent-2));color:var(--tile-fg)}
.nmeta{min-width:0;flex:1}
.nkind{font-size:11px;letter-spacing:.10em;text-transform:uppercase;color:var(--muted);font-weight:600}
.ntitle{display:block;width:100%;margin-top:1px;padding:0;border:0;background:transparent;color:var(--text);
  font:inherit;font-size:19px;font-weight:600;letter-spacing:-.015em;outline:none;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
input.ntitle{cursor:text}

.panel{margin-top:12px;padding:12px 13px;border-radius:12px;background:var(--panel-bg);border:1px solid var(--panel-bd)}

/* Card body copy. 14px at 1.55 sits in the 1.5-1.7 band good for reading, and
   the card is 330px wide so lines land around 45-55 characters. Space below a
   paragraph is roughly one font size, so a second thought reads as a second
   thought instead of running on. */
.pnote{font-size:14px;line-height:1.55;color:var(--text)}
.pnote > p{margin:0 0 14px}
.pnote > ul{margin:0 0 14px;padding:0;list-style:none}
.pnote > :last-child{margin-bottom:0}
.pnote li{position:relative;padding-left:17px;margin-bottom:6px}
.pnote li:last-child{margin-bottom:0}
/* Hanging bullet, so a wrapped list item lines up under its own text. */
.pnote li::before{content:'';position:absolute;left:4px;top:9px;width:4px;height:4px;
  border-radius:50%;background:var(--accent-ink)}

/* Status pill: the state this box ended in. A dot rather than a tick -- at this
   size a checkmark turns to mush, and a dot is the usual pattern for state. */
.pstatus{display:inline-flex;align-items:center;gap:8px;margin-top:13px;
  padding:4px 12px 4px 10px;border-radius:999px;background:var(--card-b);
  border:1px solid var(--panel-bd);color:var(--accent-ink);
  font-size:12px;font-weight:600;line-height:1.5}
.pstatus .dot{width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
.pstatus.deny{color:#f2a3a3;border-color:#7f1d1d;background:rgba(127,29,29,.18)}
.prow{display:flex;align-items:center;gap:8px}
.plabel{display:flex;align-items:center;gap:7px;color:var(--accent-ink);font-weight:600;font-size:14px}
.selwrap{margin-left:auto;display:flex;align-items:center;gap:2px;color:var(--accent-ink)}
.selwrap select{appearance:none;-webkit-appearance:none;background:transparent;border:0;outline:none;
  color:var(--accent-ink);font:inherit;font-size:14px;font-weight:600;cursor:pointer;padding:2px 0 2px 4px}
.selwrap select option{background:var(--panel);color:var(--text)}
.pinput{display:block;width:100%;margin-top:6px;padding:0;border:0;background:transparent;outline:none;
  color:var(--text);font:inherit;font-size:14px}
.pinput::placeholder{color:var(--faint)}

.port{position:absolute;left:50%;width:14px;height:14px;margin-left:-7px;border-radius:50%;
  background:var(--card-b);border:2px solid var(--stroke-hi);opacity:0;transition:opacity .12s,transform .12s}
.port.out{bottom:-7px;cursor:crosshair}
.port.in{top:-7px}
.node:hover .port,.node.sel .port{opacity:1}
.port.out:hover{background:var(--accent-ink);border-color:var(--accent-ink);transform:scale(1.3)}

.badge{position:absolute;top:-13px;right:22px;width:28px;height:28px;border-radius:50%;display:grid;
  place-items:center;background:var(--card-b);border:1px solid var(--panel-bd);color:var(--accent-ink)}

.hidden-file{display:none}

/* ============================================================
   Left panel: a window frame hosting a simulated Windows desktop
   ============================================================ */
.body{flex:1;display:flex;min-height:0;position:relative}
/* floating restore affordance shown while the toolbar is hidden */
.barpeek{position:absolute;top:8px;right:14px;z-index:25;display:flex;align-items:center;gap:6px;
  height:28px;padding:0 10px;border-radius:8px;border:1px solid var(--stroke);color:var(--muted);
  background:var(--panel);box-shadow:var(--card-shadow);
  font:inherit;font-size:11.5px;cursor:pointer;opacity:.6;transition:opacity .15s,color .15s,border-color .15s}
.barpeek:hover{opacity:1;color:var(--text);border-color:var(--stroke-hi)}
.side{flex:none;display:flex;flex-direction:column;background:var(--chrome);min-width:0;overflow:hidden;
  position:relative}
/* At the end of a run the machine dims away, so the eye goes to the last box
   and the "Job done!" sign-off rather than back to the screenshot. */
.side::after{content:'';position:absolute;inset:0;background:#000;opacity:0;pointer-events:none;
  transition:opacity .55s ease;z-index:60}
.side.dim::after{opacity:.5}
/* Locked: the emulated machine is a picture. Nothing inside it takes a click,
   so a stray tap during a demo cannot open a window or dismiss the sign-in. */
.side.locked .deskouter{pointer-events:none}
.side.locked{cursor:default}
.lockmark{display:grid;place-items:center;width:24px;height:24px;flex:none;color:var(--amber);
  opacity:.75}
.resizer{flex:none;width:6px;cursor:col-resize;position:relative;background:var(--chrome);
  border-left:1px solid var(--stroke);border-right:1px solid var(--stroke)}
.resizer::after{content:'';position:absolute;inset:0 2px;background:var(--brand);opacity:0;transition:opacity .12s}
.resizer:hover::after{opacity:.55}

