/* KaiOrb — Capabilities constellation.
   Page-specific, loaded only by /capabilities/. Extends site.css tokens. */

/* ---------- No-JS fallback ----------
   The plain card list that the page ships with. constellations.js hides it
   once the interactive stage is up, so this is what a visitor without
   JavaScript — or with a script blocker — actually reads. It stays a complete
   description of all eight families for that reason. */
.constellation-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem; width: 100%;
}
.constellation-card {
  border: 1px solid var(--line); border-radius: 16px; padding: 1.25rem;
  background: var(--surface);
  transition: transform .2s ease, border-color .2s ease, box-shadow .2s ease;
}
.constellation-card:hover { transform: translateY(-2px); border-color: var(--gold); box-shadow: 0 0 20px var(--gold-soft); }
.constellation-card h3 {
  font-size: 1.05rem; color: var(--ink); margin-bottom: .5rem;
  display: flex; align-items: center; gap: .5rem;
}
.constellation-card h3::before {
  content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--blue);
}
.constellation-card:hover h3::before { background: var(--gold); box-shadow: 0 0 8px var(--gold-soft); }

/* ---------- Stage above, panel below ----------
   The wheel sits centred; opening a constellation unfolds a full-width panel
   underneath it (owner direction, 2026-08-08: workflows read better wide —
   flows get the container's whole width instead of a thin side column). */
.cst-layout { width: 100%; }

/* ---------- The orbital stage ---------- */
.cst-stage { position: relative; width: 100%; max-width: 760px; margin: 0 auto; }
.cst-svg { width: 100%; height: auto; display: block; overflow: visible; }

.cst-orbit { fill: none; stroke: var(--line); stroke-width: 1.2; }
.cst-orbit.dashed { stroke-dasharray: 3 9; opacity: .7; }
.cst-spoke { stroke: var(--line); stroke-width: 1; opacity: .35; transition: stroke .3s ease, opacity .3s ease; }

.cst-core-glow { opacity: .9; }
.cst-core-label {
  fill: var(--ink); font: 700 13px "Space Grotesk", sans-serif; text-anchor: middle;
  letter-spacing: .16em;
}
.cst-core-sub { fill: var(--mut); font: 400 10px Inter, sans-serif; text-anchor: middle; }

/* A capability node: circle + label, the whole group is the hit target. */
.cst-node { cursor: pointer; }
.cst-node .disc {
  fill: var(--surface); stroke: var(--line); stroke-width: 1.5;
  transition: stroke .25s ease, fill .25s ease;
}
.cst-node .ring {
  fill: none; stroke: var(--gold); stroke-width: 1.5; opacity: 0;
  transition: opacity .25s ease, r .25s ease;
}
.cst-node .glyph { fill: none; stroke: var(--mut); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; transition: stroke .25s ease; }
.cst-node .name {
  fill: var(--ink); font: 600 11.5px "Space Grotesk", sans-serif; text-anchor: middle;
  transition: fill .25s ease;
}
.cst-node:hover .disc, .cst-node:focus-visible .disc { stroke: var(--gold); }
.cst-node:hover .glyph, .cst-node:focus-visible .glyph { stroke: var(--gold); }
.cst-node:focus-visible { outline: none; }
.cst-node:focus-visible .ring { opacity: .5; }

.cst-node[aria-selected="true"] .disc { stroke: var(--gold); fill: var(--surface); }
.cst-node[aria-selected="true"] .ring { opacity: 1; }
.cst-node[aria-selected="true"] .glyph { stroke: var(--gold); }
.cst-node[aria-selected="true"] .name { fill: var(--gold); }
.cst-spoke.is-active { stroke: var(--gold); opacity: .8; }

/* Slow drift on the outer ring — relationship, not decoration. */
.cst-rotor { transform-origin: 50% 50%; animation: cst-spin 240s linear infinite; }
@keyframes cst-spin { to { transform: rotate(360deg); } }

/* ---------- The panel underneath ---------- */
.cst-panel {
  width: 100%; margin: 2.25rem auto 0;
  border: 1px solid var(--line); border-radius: 20px;
  background: var(--surface); overflow: hidden;
}

/* On a large monitor the 1080px container is the binding constraint, not the
   screen — so the panel breaks out of it and centres on the viewport. A
   horizontal pipeline is worth the extra 240px; the wheel above stays put.
   100vw includes the scrollbar, hence the 3rem inset. */
@media (min-width: 1200px) {
  .cst-panel {
    position: relative; left: 50%; transform: translateX(-50%);
    width: min(1320px, calc(100vw - 3rem));
  }
}
.cst-panel[hidden] { display: none; }

.cst-panel-head {
  display: flex; align-items: flex-start; gap: 1rem; flex-wrap: wrap;
  padding: 1.5rem 1.75rem 1.1rem;
  border-bottom: 1px solid var(--line);
}
.cst-panel-mark { width: 44px; height: 44px; flex: none; display: grid; place-items: center; position: relative; }
.cst-panel-mark::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, var(--gold-soft), transparent 70%);
}
.cst-panel-mark::after {
  content: ''; position: absolute; inset: -4px; border-radius: 50%; border: 1px dashed var(--line);
}
.cst-panel-mark svg { position: relative; width: 20px; height: 20px; }
.cst-panel-mark svg * { stroke: var(--gold); }
.cst-panel-title { flex: 1; min-width: 220px; }
.cst-panel-title h2 { font-size: 1.35rem; margin: 0 0 .25rem; }
.cst-panel-title p { color: var(--mut); font-size: .92rem; margin: 0; }
.cst-panel-close {
  margin-left: auto; background: transparent; border: 1px solid var(--line);
  color: var(--mut); border-radius: 999px; width: 34px; height: 34px; cursor: pointer;
  font-size: 1rem; line-height: 1; flex: none;
}
.cst-panel-close:hover { border-color: var(--gold); color: var(--gold); }

.cst-panel-body { padding: 1.5rem 1.75rem 1.75rem; }

.cst-illustrative {
  display: inline-flex; align-items: center; gap: .5rem;
  font-size: .74rem; letter-spacing: .08em; text-transform: uppercase; font-weight: 700;
  color: var(--mut); border: 1px dashed var(--line); border-radius: 999px;
  padding: .35rem .85rem; margin-bottom: 1.4rem;
}

/* ---------- A workflow ----------
   Each workflow is a soft container so the panel reads as a set of distinct
   automations rather than one undifferentiated column. */
.cst-wf {
  border: 1px solid var(--line); border-radius: 16px;
  background: var(--surface);
  padding: 1.1rem 1.25rem 1.3rem;
  margin-bottom: 1.25rem;
}
.cst-wf:last-child { margin-bottom: 0; }
.cst-wf-head { margin-bottom: 1rem; }
.cst-wf-head h3 { font-size: 1.02rem; margin: 0 0 .5rem; }
.cst-wf-tags { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.cst-wf-trigger {
  display: inline-flex; align-items: center; gap: .35rem;
  font-size: .66rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--blue); border: 1px solid var(--line); border-radius: 999px; padding: .22rem .65rem;
}
.cst-wf-trigger svg { flex: none; }
.cst-wf-shape {
  font-size: .66rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--violet); border: 1px solid var(--line); border-radius: 999px; padding: .22rem .65rem;
}

/* Shown only when this flow actually overflows — see wireScrollHints(). */
.cst-wf-scroll {
  display: none;
  font-size: .66rem; font-weight: 600; letter-spacing: .04em;
  color: var(--mut);
}
.cst-wf.can-scroll .cst-wf-scroll { display: inline; }

/* ---------- The flow, two orientations ----------
   One DOM, two renderings:

   Below 720px  — flows read TOP TO BOTTOM down a spine rail fixed at x=14px
                  (chip centre). Narrow screens cannot host a horizontal
                  pipeline, and a vertical flow can never wrap.
   720px and up — the panel spans the container, so flows read LEFT TO RIGHT,
                  n8n-style: uniform node cards on a horizontal rail, branches
                  stacked between fork/join bars, a loop's return path drawn
                  underneath. A flow longer than the panel scrolls inside its
                  own container — the page never scrolls sideways.

   In the vertical rendering, sequence (airy rows) and parallelism (bordered
   cells) look deliberately different. In the horizontal one, every node is
   the same card and GEOMETRY carries the semantics: what stacks between the
   bars is parallel, what sits on the rail is sequence. */
.cst-flow, .cst-stack { display: flex; flex-direction: column; align-items: stretch; }

.cst-step {
  display: flex; align-items: flex-start; gap: .7rem;
  padding: .3rem .5rem .3rem 0; border-radius: 10px;
  /* Nodes light in turn — a system working steadily, not a spinner. */
  animation: cst-row-lite var(--cycle, 12s) ease-in-out infinite;
  animation-delay: calc(var(--i) * 1.05s);
}
.cst-step-text { min-width: 0; padding-top: 1px; }
.cst-step .cst-kind { display: block; margin-bottom: 1px; }

.cst-dot {
  width: 28px; height: 28px; flex: none; display: grid; place-items: center;
  border-radius: 50%; color: var(--mut); background: rgba(148,163,199,.16);
  animation: cst-dot-lite var(--cycle, 12s) ease-in-out infinite;
  animation-delay: calc(var(--i) * 1.05s);
}
.cst-dot svg { width: 13px; height: 13px; }

.cst-kind {
  font-size: .6rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--mut);
}
.cst-label { font-size: .86rem; font-weight: 600; line-height: 1.35; color: var(--ink); }

/* Kind colouring — one hue per role so a flow is readable at a glance. */
[data-kind="trigger"] .cst-dot { background: rgba(122,174,252,.16); color: var(--blue); }
[data-kind="ai"]      .cst-dot { background: var(--gold-soft); color: var(--gold); }
[data-kind="action"]  .cst-dot { background: rgba(148,163,199,.16); color: var(--mut); }
[data-kind="check"]   .cst-dot { background: rgba(167,139,250,.18); color: var(--violet); }
[data-kind="human"]   .cst-dot { background: rgba(122,174,252,.16); color: var(--blue); }
[data-kind="output"]  .cst-dot { background: rgba(127,214,168,.18); color: #2f9e6a; }

/* Connector segments on the spine, with a dot that travels down. */
.cst-seg { position: relative; width: 2px; height: 20px; margin-left: 13px; flex: none; }
.cst-seg::before {
  content: ''; position: absolute; inset: 0;
  background: repeating-linear-gradient(180deg, var(--line) 0 5px, transparent 5px 10px);
}
.cst-seg::after {
  content: ''; position: absolute; left: 50%; top: 0; width: 6px; height: 6px;
  margin-left: -3px; border-radius: 50%; background: var(--gold);
  box-shadow: 0 0 8px var(--gold-soft); opacity: 0;
  animation: cst-travel var(--cycle, 12s) ease-in-out infinite;
  animation-delay: calc(var(--i) * 1.05s + .35s);
}
@keyframes cst-travel {
  0%, 4% { top: 0; opacity: 0; }
  6%     { opacity: 1; }
  13%    { top: calc(100% - 6px); opacity: 1; }
  16%    { top: calc(100% - 6px); opacity: 0; }
  100%   { top: calc(100% - 6px); opacity: 0; }
}
.cst-seg-junction { height: 22px; }
.cst-seg-lane { margin-left: 0; align-self: center; height: 14px; }

/* ---------- Parallel sections ----------
   A cell is the same step drawn as a centred mini-card. */
.cst-cell {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: .3rem; flex: 1;
  border: 1px solid var(--line); border-radius: 12px; background: var(--bg0);
  padding: .65rem .55rem .7rem;
  animation: cst-cell-lite var(--cycle, 12s) ease-in-out infinite;
  animation-delay: calc(var(--i) * 1.05s);
}
.cst-cell .cst-kind { font-size: .58rem; }
.cst-cell .cst-label { font-size: .78rem; }

/* Parallel sections, vertical rendering: a bracketed list off the spine —
   one lane per row, each hung on the bracket by a stub, cells folded to row
   orientation. --lanes (set by the renderer) is used by the horizontal
   rendering below. */
.cst-lanes {
  position: relative; display: flex; flex-direction: column; gap: .55rem;
  margin-left: 13px; padding-left: 16px;
  border-left: 2px dashed var(--line);
}
.cst-lane { position: relative; display: flex; flex-direction: column; align-items: stretch; }
.cst-lane::before {
  content: ''; position: absolute; left: -16px; top: 50%; width: 14px; height: 2px;
  background: repeating-linear-gradient(90deg, var(--line) 0 4px, transparent 4px 8px);
}
.cst-lanes .cst-cell {
  flex-direction: row; text-align: left; align-items: center;
  gap: .6rem; padding: .5rem .6rem;
}
.cst-lanes .cst-cell .cst-kind { display: none; }

/* grid: independent checks, no order implied — a collector bar underneath. */
.cst-grid {
  position: relative; display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: .6rem; width: 100%; padding-bottom: 14px;
}
.cst-grid::after {
  content: ''; position: absolute; bottom: 0; left: 13px; right: 13px; height: 2px;
  background: repeating-linear-gradient(90deg, var(--line) 0 5px, transparent 5px 10px);
}

/* loop, vertical rendering: return bracket on the right, retry condition
   pinned to it. Steps keep clear of the bracket via padding. */
.cst-loop { position: relative; padding-right: 84px; }
.cst-back {
  position: absolute; top: 16px; bottom: 16px; right: 32px; width: 28px;
  border: 2px dashed var(--line); border-left: 0;
  border-radius: 0 16px 16px 0;
}
.cst-back::before {
  content: ''; position: absolute; left: -4px; top: -4px; width: 7px; height: 7px;
  border-left: 2px solid var(--violet); border-bottom: 2px solid var(--violet);
  transform: rotate(45deg);
}
.cst-back-label {
  position: absolute; top: 50%; right: -36px; transform: translateY(-50%);
  width: 72px; text-align: center;
  background: var(--bg0); border: 1px dashed var(--line); border-radius: 10px;
  padding: .3rem .4rem; font-size: .6rem; line-height: 1.35; color: var(--mut);
}

/* ---------- 720px and up: the flow turns horizontal ---------- */
@media (min-width: 720px) {
  .cst-flow {
    flex-direction: row; align-items: center;
    overflow-x: auto; padding: 6px 2px 10px;
    scrollbar-width: thin; scrollbar-color: var(--line) transparent;
  }
  .cst-flow::-webkit-scrollbar { height: 8px; }
  .cst-flow::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }

  /* A flow wider than the panel scrolls inside itself — and a scroll nobody
     can see is a diagram that looks truncated. Fade whichever edge still has
     pipeline behind it. Classes are maintained by constellations.js. */
  .cst-flow.can-scroll:not(.at-end) {
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 64px), transparent);
            mask-image: linear-gradient(90deg, #000 calc(100% - 64px), transparent);
  }
  .cst-flow.can-scroll:not(.at-start) {
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 64px);
            mask-image: linear-gradient(90deg, transparent, #000 64px);
  }
  .cst-flow.can-scroll:not(.at-start):not(.at-end) {
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 64px, #000 calc(100% - 64px), transparent);
            mask-image: linear-gradient(90deg, transparent, #000 64px, #000 calc(100% - 64px), transparent);
  }
  .cst-stack { flex-direction: row; align-items: center; flex: 1 1 auto; min-width: 0; }

  /* Uniform node card, flexible between 120 and 168px: mid-length chains
     compress to fit the panel instead of scrolling; only the longest flows
     scroll. display:contents flattens the text wrapper so the kind and
     label centre under the chip. */
  .cst-step {
    flex: 1 1 140px; min-width: 120px; max-width: 168px;
    flex-direction: column; align-items: center;
    text-align: center; gap: .3rem;
    border: 1px solid var(--line); border-radius: 12px; background: var(--bg0);
    padding: .65rem .55rem .7rem;
    animation-name: cst-cell-lite;
  }
  .cst-step-text { display: contents; }
  .cst-step .cst-kind { display: inline; margin: 0; font-size: .58rem; }
  .cst-step .cst-label { font-size: .78rem; }
  .cst-cell { flex: none; width: 152px; }
  .cst-lanes .cst-cell {
    flex-direction: column; text-align: center; align-items: center;
    gap: .3rem; padding: .65rem .55rem .7rem;
  }
  .cst-lanes .cst-cell .cst-kind { display: inline; }

  .cst-seg { width: 26px; height: 2px; margin-left: 0; align-self: center; }
  .cst-seg::before {
    background: repeating-linear-gradient(90deg, var(--line) 0 5px, transparent 5px 10px);
  }
  .cst-seg::after {
    top: 50%; left: 0; margin: -3px 0 0 0;
    animation-name: cst-travel-h;
  }
  .cst-seg-junction { width: 26px; height: 2px; }
  .cst-seg-lane { width: 18px; height: 2px; }

  /* Branches stack between a fork bar and a join bar; each lane runs
     rightward, hung on the bars by stubs at its vertical centre. */
  .cst-lanes {
    flex: none; margin: 0; padding: 0 14px;
    border-left: 0; gap: .6rem;
  }
  .cst-lanes::before, .cst-lanes::after {
    content: ''; position: absolute; width: 2px;
    top: calc(50% / var(--lanes, 2)); bottom: calc(50% / var(--lanes, 2));
    background: repeating-linear-gradient(180deg, var(--line) 0 5px, transparent 5px 10px);
  }
  .cst-lanes::before { left: 0; }
  .cst-lanes::after { right: 0; }
  .cst-lane { flex-direction: row; align-items: center; }
  .cst-lane::before, .cst-lane::after {
    content: ''; position: absolute; top: 50%; margin: -1px 0 0 0; width: 14px; height: 2px;
    background: repeating-linear-gradient(90deg, var(--line) 0 5px, transparent 5px 10px);
  }
  .cst-lane::before { left: -14px; }
  .cst-lane::after { right: -14px; }

  /* fanin sources converge: no fork bar on the left, join bar only. */
  .cst-lanes-in::before { display: none; }
  .cst-lanes-in .cst-lane::before { display: none; }

  /* grid: the collector turns vertical and sits on the right. */
  .cst-grid { flex: 1 1 auto; min-width: 320px; width: auto; padding: 0 14px 0 0; }
  .cst-grid::after {
    left: auto; right: 0; top: 13px; bottom: 13px; width: 2px; height: auto;
    background: repeating-linear-gradient(180deg, var(--line) 0 5px, transparent 5px 10px);
  }

  /* loop: the return path runs UNDER the row, back to the start. The top
     margin mirrors the bracket's space so the row stays centred on the rail. */
  .cst-loop {
    display: flex; align-items: center; flex: 1 1 auto; min-width: 0;
    padding: 0 0 34px; margin-top: 34px;
  }
  .cst-back {
    top: auto; left: 20px; right: 20px; bottom: 4px; width: auto; height: 24px;
    border: 2px dashed var(--line); border-top: 0;
    border-radius: 0 0 14px 14px;
  }
  .cst-back::before {
    left: -1px; top: -4px;
    border-bottom: 0; border-top: 2px solid var(--violet);
  }
  .cst-back-label {
    top: auto; bottom: 0; left: 50%; right: auto;
    transform: translate(-50%, 55%);
    width: auto; white-space: nowrap;
    font-size: .64rem; padding: .25rem .6rem;
  }
}

@keyframes cst-travel-h {
  0%, 4% { left: 0; opacity: 0; }
  6%     { opacity: 1; }
  13%    { left: calc(100% - 6px); opacity: 1; }
  16%    { left: calc(100% - 6px); opacity: 0; }
  100%   { left: calc(100% - 6px); opacity: 0; }
}
@keyframes cst-row-lite {
  0%, 6%    { background: transparent; }
  9%        { background: var(--gold-soft); }
  16%, 100% { background: transparent; }
}
@keyframes cst-dot-lite {
  0%, 6%    { box-shadow: none; }
  9%        { box-shadow: 0 0 0 3px var(--gold-soft); }
  16%, 100% { box-shadow: none; }
}
@keyframes cst-cell-lite {
  0%, 6%    { border-color: var(--line); box-shadow: none; transform: none; }
  9%        { border-color: var(--gold); box-shadow: 0 0 0 3px var(--gold-soft); transform: translateY(-2px); }
  16%, 100% { border-color: var(--line); box-shadow: none; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .cst-rotor, .cst-step, .cst-dot, .cst-cell { animation: none; }
  .cst-seg::after { animation: none; opacity: .8; top: calc(50% - 3px); }
}
@media (min-width: 720px) and (prefers-reduced-motion: reduce) {
  .cst-seg::after { top: -2px; left: calc(50% - 3px); }
}
