/* AI Transformation ops widget: requests in -> agents -> checks + review -> shipped + watched.
   Shared by / and /ai-transformation/. Markup lives in each page (the .ops block and the
   og-* SVG symbols); this file and ops-widget.js are the single source for style
   and motion. Board rule (15 Oct 2026): the visual keeps one height while it
   animates -- the fixed-height tokens below reserve that space. */
.ops {
  --trg-stack-h: 122px;
  --log-rows-h: 94px;
  --mon-lines-h: 69px;
}

/* —— Hero visual: requests in → agents → checks + review → shipped + watched —— */
/* One accent state (.is-on: white border, soft fill) marks whatever is active. */
.ops {
  margin-top: 22px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(250px, 22%);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--bg);
  overflow: hidden;
}
.ops-stage {
  position: relative;
  display: grid;
  /* Four equal columns with a wide gutter: no card is narrower than the queue's, and every label has air to its right. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: 32px;
  padding: 18px 16px 20px;
  min-width: 0;
}
.ops-wires, .ops-fx {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
.ops-wires { z-index: 0; }
.ops-fx { z-index: 3; }
.ops-col { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.ops-label {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 500;
  white-space: nowrap;
}
.ops-label .n {
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  font-size: 10px;
  letter-spacing: 0;
  color: var(--fg);
}
.gl {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ops-card {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 12px;
  transition: border-color .3s ease, background-color .3s ease, box-shadow .3s ease, opacity .4s ease;
}
.ops-card.is-on {
  border-color: var(--fg);
  background: var(--soft);
}

/* 1 · Triggers */
.trg-wrap { position: relative; flex: 1; min-height: 0; }
.trg-list {
  position: absolute;
  inset: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow: hidden;
}
.trg { flex-shrink: 0; padding: 9px 11px 10px; }
.trg-src { display: flex; align-items: center; gap: 7px; font-size: 11px; line-height: 1.3; color: var(--muted); white-space: nowrap; }
.trg-src b { color: var(--fg); font-weight: 600; }
.trg-src .gl { color: var(--fg); }
.trg-to { margin-left: auto; color: var(--fg); opacity: 0; transition: opacity .3s ease; }
.trg-line { margin-top: 4px; font-size: 12.5px; line-height: 1.35; color: var(--fg); }
/* The head card slides in once its room has opened (260 ms); older requests dim down the queue. */
.trg.is-new { animation: ops-slide .3s cubic-bezier(.2,.7,.2,1) .2s both; }
.trg.is-done { opacity: 0.5; }
.trg.is-done:nth-child(n+3) { opacity: 0.32; }
.trg.is-done .trg-to { opacity: 1; }
.trg.is-pulse { animation: ops-pulse .7s ease-out; }

/* 2 · Agents */
.ags { display: flex; flex-direction: column; gap: 8px; }
/* Idle agents are one row (glyph, name, count); only a working agent opens up. */
.ag { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 0 10px; align-items: center; padding: 7px 11px; }
.ag-more { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .35s ease; }
.ag-more > div { min-height: 0; overflow: hidden; }
.ag.is-busy .ag-more { grid-template-rows: 1fr; }
.ops.is-measuring .ag-more { transition: none; }
.ag-av {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  display: grid;
  place-items: center;
  transition: background-color .3s ease, color .3s ease, border-color .3s ease;
}
.ag-top { display: flex; align-items: baseline; gap: 6px; }
.ag-name { font-family: 'Space Grotesk', sans-serif; font-weight: 600; font-size: 14px; letter-spacing: -0.01em; line-height: 1.2; }
.ag-count { margin-left: auto; font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ag-task { margin-top: 1px; font-size: 11.5px; line-height: 1.35; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ag-prog { display: flex; align-items: center; gap: 8px; margin-top: 7px; padding-bottom: 2px; }
.ag-track { flex: 1; height: 3px; border-radius: 2px; background: rgba(255,255,255,0.1); overflow: hidden; }
.ag-bar { display: block; height: 100%; background: var(--fg); transform: scaleX(0); transform-origin: left center; }
.ag-phase { min-width: 6.4em; text-align: right; font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }
.ag.is-on .ag-task, .ag.is-on .ag-phase { color: var(--fg); }
.ag.is-on .ag-av { background: var(--fg); border-color: var(--fg); color: var(--accent-fg); }

/* 3 · Checks + human review */
.chk-now { display: flex; align-items: center; gap: 7px; min-height: 18px; font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chk-now b { color: var(--fg); font-weight: 600; }
.gates { display: flex; flex-direction: column; gap: 6px; }
.gate { position: relative; display: flex; align-items: center; gap: 10px; padding: 8px 10px; }
.gate-txt { min-width: 0; }
.gate-txt b { display: block; font-size: 13px; font-weight: 600; line-height: 1.25; }
.gate-txt small { display: block; font-size: 10.5px; line-height: 1.3; color: var(--muted); white-space: nowrap; }
.st {
  margin-left: auto;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  display: grid;
  place-items: center;
  font-size: 10px;
  line-height: 1;
}
[data-st="run"] > .st { border-color: rgba(255,255,255,0.2); border-top-color: var(--fg); animation: ops-spin .7s linear infinite; }
[data-st="pass"] > .st { background: var(--fg); border-color: var(--fg); color: var(--accent-fg); }
[data-st="pass"] > .st::after { content: '✓'; font-weight: 700; }
[data-st="fail"] > .st { border: 1px dashed var(--fg); color: var(--fg); }
[data-st="fail"] > .st::after { content: '✕'; }
.gate[data-st="fail"] { border-style: dashed; border-color: var(--fg); }
.rev { padding: 10px 11px 11px; }
.rev-who { display: flex; align-items: center; gap: 9px; }
.rev-who > .st { margin-left: auto; }
.rev-av {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--soft);
  border: 1px solid var(--line-strong);
  display: grid;
  place-items: center;
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 600;
  font-size: 12px;
}
.rev-who b { display: block; font-size: 13px; font-weight: 600; line-height: 1.25; }
.rev-who small { display: block; font-size: 10.5px; line-height: 1.3; color: var(--muted); white-space: nowrap; }
/* Every lane's reviewer sits in the same cell; one shows at a time and they crossfade, so the card never resizes. */
.rev-av, .rev-ids { display: grid; }
.rev-av > *, .rev-ids > * { grid-area: 1 / 1; opacity: 0; transition: opacity .45s ease; }
.rev-av > *.is-on, .rev-ids > *.is-on { opacity: 1; }
.rev-av > * { place-self: center; }
.rev-ids { min-width: 0; }
.rev-what {
  margin-top: 8px;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--muted);
  min-height: 2.8em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.rev.is-on .rev-what { color: var(--fg); }
.rev-btns { display: flex; gap: 6px; margin-top: 8px; }
.rev-btn {
  flex: 1;
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  padding: 5px 0;
  border-radius: 8px;
  border: 1px solid var(--line-strong);
  color: var(--muted);
  transition: background-color .2s ease, color .2s ease, border-color .2s ease;
}
.rev-btn.is-press { background: var(--fg); border-color: var(--fg); color: var(--accent-fg); }
.rev-btn[data-act="back"].is-press { background: transparent; color: var(--fg); border: 1px dashed var(--fg); }

/* 4 · Shipped + monitor */
.shp { padding: 10px 12px 11px; }
.shp-top { display: flex; align-items: center; gap: 8px; }
.shp-verb { display: inline-block; font-family: 'Space Grotesk', sans-serif; font-weight: 600; font-size: 15px; letter-spacing: -0.01em; }
.shp-time { margin-left: auto; font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.shp-what { margin-top: 3px; font-size: 11.5px; line-height: 1.35; color: var(--muted); }
.shp.is-idle { opacity: 0.45; }
.shp.is-on .shp-what { color: var(--fg); }
.shp-verb.is-new { animation: ops-in .45s ease both; }
.mon { padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 10px; }
.mon-top { display: flex; align-items: center; justify-content: space-between; font-size: 10.5px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.live { display: inline-flex; align-items: center; gap: 6px; color: var(--fg); }
.live::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--fg); animation: ops-live 1.6s ease-in-out infinite; }
.spark-wrap small { display: block; font-size: 10.5px; color: var(--muted); margin-bottom: 4px; }
.spark { display: block; width: 100%; height: 34px; }
.spark-line { fill: none; stroke: var(--fg); stroke-width: 1.4; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.spark-area { fill: rgba(255,255,255,0.07); stroke: none; }
.mon-lines { list-style: none; display: flex; flex-direction: column; gap: 2px; margin-inline: -7px; font-size: 11.5px; line-height: 1.35; }
.mon-lines li { display: flex; align-items: baseline; gap: 7px; padding: 2px 6px; border: 1px solid transparent; border-radius: 6px; color: var(--muted); transition: border-color .3s ease, background-color .3s ease; }
.mon-lines li.is-on { border-color: var(--fg); background: var(--soft); }
.mon-lines li:first-child { color: var(--fg); }
.mon-lines li.is-new { animation: ops-in .45s ease both; }
.mon-dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; flex-shrink: 0; transform: translateY(-2px); }
.mon-txt { min-width: 0; }
.mon-lines time { margin-left: auto; font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.bud-top { display: flex; justify-content: space-between; gap: 8px; font-size: 11px; color: var(--muted); }
.bud-top b { color: var(--fg); font-weight: 600; font-variant-numeric: tabular-nums; }
.bud-track { height: 4px; margin-top: 6px; border-radius: 2px; background: rgba(255,255,255,0.1); overflow: hidden; }
.bud-fill { display: block; height: 100%; width: 0; background: var(--fg); transition: width .6s ease; }

/* Event sidebar: the log, in sync with the motion */
.ops-side { display: flex; flex-direction: column; min-width: 0; padding: 18px 20px 14px; border-left: 1px solid var(--line); background: var(--bg); }
.ctrs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; padding-bottom: 14px; border-bottom: 1px solid var(--line); }
.ctr b { display: block; font-family: 'Space Grotesk', sans-serif; font-size: 22px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.1; font-variant-numeric: tabular-nums; }
.ctr span { display: block; margin-top: 3px; font-size: 10.5px; line-height: 1.3; color: var(--muted); }
.ctr.is-bump b { animation: ops-bump .5s ease; }
.log-head { display: flex; align-items: center; justify-content: space-between; margin: 14px 0 6px; }
.log-head .ops-label { margin-bottom: 0; }
.log-clock { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.log-wrap { position: relative; flex: 1; min-height: 0; }
.ops-log {
  position: absolute;
  inset: 0;
  list-style: none;
  overflow: hidden;
  font-size: 12px;
  line-height: 1.4;
}
.ops-log li { display: grid; grid-template-columns: 3em minmax(0, 1fr); gap: 8px; padding: 7px 0; overflow: hidden; border-bottom: 1px solid rgba(255,255,255,0.05); color: var(--muted); }
.ops-log time { color: rgba(255,255,255,0.4); font-variant-numeric: tabular-nums; }
.ops-log li:first-child { color: var(--fg); }
.ops-log li:last-child { border-bottom: 0; }

/* Flying work item (the card that hops) and the short-lived connector */
.chip {
  position: absolute;
  left: 0;
  top: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 9px 0 7px;
  border-radius: 8px;
  background: var(--fg);
  color: var(--accent-fg);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  transition: opacity .3s ease;
  will-change: transform;
}
.chip .gl { width: 12px; height: 12px; stroke-width: 1.6; }
/* Fade in place: a scale here would also scale the ride's translate and drag the chip toward the stage corner. */
.chip.is-land { opacity: 0; }
.wire { fill: none; stroke: rgba(255,255,255,0.6); stroke-width: 1.3; transition: opacity .6s ease; }
.wire.is-back { stroke-dasharray: 4 5; }
.wire.is-fade { opacity: 0; }

@keyframes ops-slide { from { opacity: 0; transform: translateX(-28px); } to { opacity: 1; transform: none; } }
@keyframes ops-pulse {
  0% { box-shadow: 0 0 0 0 rgba(255,255,255,0.55); }
  100% { box-shadow: 0 0 0 14px rgba(255,255,255,0); }
}
@keyframes ops-spin { to { transform: rotate(360deg); } }
@keyframes ops-live { 50% { opacity: 0.25; } }
@keyframes ops-bump { 40% { transform: translateY(-3px); } }
@keyframes ops-in {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}

/* Below 1200: the four columns keep the width (labels stay on one line), the log drops under them. */
@media (max-width: 1199px) {
  .ops { grid-template-columns: minmax(0, 1fr); }
  .ops-side { border-left: 0; border-top: 1px solid var(--line); padding: 16px 20px 12px; }
  .log-wrap { flex: none; }
  /* Three rows, fixed: a new line grows in at the top, the oldest slides out under the edge, the visual never resizes. */
  .ops-log { position: static; -webkit-mask-image: none; mask-image: none; height: var(--log-rows-h); overflow: hidden; }
  .ops-log li:nth-child(3) { border-bottom: 0; }
  /* One line per event: a wrapping line would resize the whole visual every time the log moves. */
  .ops-log li > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .mon-lines { min-height: var(--mon-lines-h); }
}

@media (min-width: 721px) and (max-width: 919px) {
  .ops-stage .ops-label { white-space: normal; align-items: flex-start; min-height: 32px; line-height: 1.3; }
}

/* Phone: one vertical pipeline, trigger → agent → checks → ship. */
@media (max-width: 720px) {
  .ops { margin-top: 28px; border-radius: 20px; }
  .ops-stage { grid-template-columns: minmax(0, 1fr); row-gap: 22px; padding: 16px 14px 18px; }
  .trg-wrap { flex: none; }
  /* Two cards' worth, fixed: a card sliding in must not resize the pipeline below it. */
  .trg-list { position: static; height: var(--trg-stack-h); overflow: hidden; }
  .trg:nth-child(n+3) { display: none; }
  .trg.is-new { animation-name: ops-in; }
  .trg-line { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* Agents: a row of five icons; the agent at work opens one card under the row. */
  .ags { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 5px 4px; }
  .ag, .ag-body { display: contents; }
  .ag-av { grid-row: 1; justify-self: center; width: 36px; height: 36px; }
  .ag-av .gl { width: 16px; height: 16px; }
  .ag-top { grid-row: 2; display: block; text-align: center; }
  .ag-name { font-family: 'Inter', system-ui, sans-serif; font-size: 11px; font-weight: 500; letter-spacing: 0; color: var(--muted); }
  .ag.is-busy .ag-name { color: var(--fg); }
  .ag-count { display: none; }
  /* Every agent's card shares one reserved row and crossfades, so opening one never pushes the pipeline down. */
  .ag-more { display: grid; grid-template-rows: 1fr; grid-row: 3; grid-column: 1 / -1; margin-top: 3px; opacity: 0; visibility: hidden; transition: opacity .4s ease, visibility 0s linear .4s; }
  .ag.is-focus .ag-more { opacity: 1; visibility: visible; transition: opacity .4s ease; }
  /* The reserved row never sits empty: between stories it says the team is waiting. */
  .ags:not(:has(.ag.is-focus))::after { content: 'Waiting for the next request'; grid-row: 3; grid-column: 1 / -1; align-self: stretch; display: flex; align-items: center; margin-top: 3px; padding: 8px 11px 9px; border: 1px dashed var(--line); border-radius: 12px; font-size: 12px; color: var(--muted); }
  /* The stacked pipeline reads top to bottom on its own; wires and flying chips only add noise at this width. */
  .wire, .chip { display: none; }
  .ag-more > div { padding: 8px 11px 9px; border: 1px solid var(--line); border-radius: 12px; background: var(--bg); transition: border-color .3s ease, background-color .3s ease; }
  .ag-more > div::before { content: attr(data-name); display: block; font-family: 'Space Grotesk', sans-serif; font-size: 13px; font-weight: 600; line-height: 1.25; }
  .ag.is-on .ag-more > div { border-color: var(--fg); background: var(--soft); }
  /* One lit icon, and it is the agent whose card is open: focus lights it, not work alone. */
  .ag-av { transition: none; }
  .ag.is-on .ag-av { background: transparent; border-color: var(--line-strong); color: inherit; }
  .ag.is-focus .ag-av { background: var(--fg); border-color: var(--fg); color: var(--accent-fg); }
  .ag-phase { min-width: 0; }
  /* Compliance is the long label: its column gets the room, so no label meets its status circle. */
  .gates { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 1fr); gap: 6px; }
  .gate { gap: 8px; padding: 8px 7px 8px 9px; justify-content: space-between; }
  .gate > .gl, .gate-txt small { display: none; }
  .gate-txt b { font-size: 11.5px; }
  .st { width: 16px; height: 16px; margin-left: 0; }
  .ops-side { padding: 14px 14px 10px; }
  .ctr b { font-size: 19px; }
}

@media (prefers-reduced-motion: reduce) {
  .ops *, .ops *::before, .ops *::after { animation: none !important; transition: none !important; }
}
