/* ============================================================
   17 — PIPELINE

   The shape a bridge actually is, drawn as the shape it is:

       SOURCE  →  READ  →  CHECK  →  ACCOUNT

   A signal enters on the left and a position opens on the right,
   and every setting in this product belongs to one of those four
   stages. The old setup was nine menu items with no relationship
   between them, so a customer had no way to know that "Symbol
   map" happens before "Order size" or that "Protection" is the
   last thing standing between a bad parse and their money.

   THE MOTION IS THE EXPLANATION, NOT DECORATION

   One dot travels the line, left to right, and pauses at each
   stage. That is the only animation here that carries meaning:
   it says the stages are ORDERED and that a signal passes
   through all of them. Everything else is a hover state.

   Every animation stops under prefers-reduced-motion, and the
   layout does not depend on any of them — with motion off the
   pipeline is a row of cards with arrows between them, which is
   the same information at rest.
   ============================================================ */

/* ------------------------------------------------------- the rail */
.pipe {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(4, 1fr);
  position: relative;
  margin: 26px 0 8px;
}

/*  The line the dot runs along, behind the cards. Drawn as one
    element rather than a border on each, so the pipeline reads as
    continuous rather than as four separate boxes.  */
.pipe::before {
  content: "";
  position: absolute;
  left: 8%;
  right: 8%;
  top: 46px;
  height: 2px;
  background: linear-gradient(90deg,
              transparent,
              rgba(233, 168, 255, .22) 12%,
              rgba(233, 168, 255, .22) 88%,
              transparent);
  z-index: 0;
}

.pipe-dot {
  position: absolute;
  top: 41px;
  left: 8%;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--cyan);
  box-shadow: 0 0 18px rgba(255, 79, 216, .85);
  z-index: 2;
  animation: pipe-run 9s cubic-bezier(.7, 0, .3, 1) infinite;
}

/*  Four stages, so four pauses. The dot rests at each one long
    enough to be read as "this happens here", not as a loading
    spinner going round.  */
@keyframes pipe-run {
   0%,  6% { left: 8%;    opacity: 0; }
   8%      { left: 8%;    opacity: 1; }
  20%      { left: 8%; }
  30%, 42% { left: 34.6%; }
  52%, 64% { left: 61.3%; }
  74%, 92% { left: 88%; }
  97%      { left: 88%;   opacity: 1; }
 100%      { left: 88%;   opacity: 0; }
}

/* ----------------------------------------------------- the stages */
.pipe-stage {
  position: relative;
  z-index: 1;
  background: var(--deep);
  border: 1px solid var(--line);
  border-radius: var(--r-lg, 14px);
  padding: 16px 14px 18px;
  text-align: center;
  transition: border-color .22s ease, transform .22s ease;
}

.pipe-stage:hover { border-color: rgba(233, 168, 255, .38); transform: translateY(-2px); }

.pipe-ic {
  width: 44px;
  height: 44px;
  margin: 0 auto 12px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  background: var(--spectrum-soft);
  border: 1px solid var(--line);
  font: 600 13px/1 var(--mono);
  color: var(--cyan);
  letter-spacing: .06em;
}

.pipe-stage h3 { margin: 0 0 6px; font: 600 15px/1.3 var(--ui); }
.pipe-stage p  { margin: 0; font: 400 12.5px/1.55 var(--ui); color: var(--dim); }

/*  The arrow between stages. Hidden on the last one and on narrow
    screens, where the cards stack and the arrow would point at a
    wall.  */
.pipe-stage::after {
  content: "→";
  position: absolute;
  right: -12px;
  top: 38px;
  font: 500 17px/1 var(--ui);
  color: var(--faint);
  z-index: 3;
}
.pipe-stage:last-child::after { content: none; }

/* --------------------------------------------- choosing a bridge */
/*  A grid of source → destination pairs. Each is one card, and the
    card SHOWS the pair rather than naming it in prose, because the
    thing being chosen is a relationship between two logos.  */
.bgrid {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  margin-top: 6px;
}

.bcard {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--deep);
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  text-align: left;
  width: 100%;
  transition: border-color .2s ease, background .2s ease, transform .2s ease;
}

.bcard:hover {
  border-color: rgba(233, 168, 255, .45);
  background: var(--lift);
  transform: translateY(-2px);
}
.bcard[aria-pressed="true"] {
  border-color: var(--cyan);
  background: var(--spectrum-soft);
}

.bcard .pair { display: flex; align-items: center; gap: 7px; flex: 0 0 auto; }
.bcard .chip-ic {
  width: 30px; height: 30px; border-radius: 8px;
  display: grid; place-items: center;
  background: var(--lift); border: 1px solid var(--line);
  font: 600 10.5px/1 var(--mono); color: var(--text);
}
.bcard .arrow { color: var(--faint); font-size: 13px; }
.bcard .txt b { display: block; font: 600 13.5px/1.3 var(--ui); }
.bcard .txt span { font: 400 11.5px/1.4 var(--ui); color: var(--dim); }

/*  A destination that exists but cannot be enabled yet. Shown
    rather than hidden, with the reason, because a customer who
    cannot find Zerodha assumes the product does not support it.  */
.bcard[disabled],
.bcard.locked { opacity: .5; cursor: not-allowed; }
.bcard.locked:hover { transform: none; border-color: var(--line); background: var(--deep); }
.bcard .lock {
  margin-left: auto; font: 500 10px/1 var(--mono);
  color: var(--gold); letter-spacing: .08em; text-transform: uppercase;
}

/* ------------------------------------------------- my bridges list */
.blist { display: grid; gap: 12px; }

.brow {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--deep);
  transition: border-color .2s ease;
}
.brow:hover { border-color: rgba(233, 168, 255, .34); }

.brow .pair { display: flex; align-items: center; gap: 8px; }
.brow .meta { flex: 1 1 auto; min-width: 0; }
.brow .meta b { display: block; font: 600 15px/1.3 var(--ui); }
.brow .meta span { font: 400 12px/1.5 var(--ui); color: var(--dim); }
.brow .act { display: flex; gap: 8px; flex: 0 0 auto; }

/*  Running / stopped / unfinished. A dot AND a word, never colour
    alone — the same rule the rest of this product follows.  */
.bstate { display: inline-flex; align-items: center; gap: 6px;
          font: 500 11.5px/1 var(--mono); letter-spacing: .06em;
          text-transform: uppercase; }
.bstate i { width: 8px; height: 8px; border-radius: 50%; background: var(--faint); }
.bstate.run  { color: var(--mint); } .bstate.run i  { background: var(--mint);
                box-shadow: 0 0 10px rgba(49, 229, 164, .7); }
.bstate.stop { color: var(--gold); } .bstate.stop i { background: var(--gold); }
.bstate.part { color: var(--dim);  } .bstate.part i { background: var(--faint); }

/* ------------------------------------------ settings, in one page */
/*  Every setting for one bridge, as sections that open in place.
    They used to be nine separate pages, which meant a customer
    finishing a setup had to remember where they were nine times.  */
.sect {
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--deep);
  margin-bottom: 10px;
  overflow: hidden;
}

.sect > summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 15px 16px;
  cursor: pointer;
  list-style: none;
  transition: background .18s ease;
}
.sect > summary::-webkit-details-marker { display: none; }
.sect > summary:hover { background: var(--lift); }

.sect .num {
  width: 26px; height: 26px; flex: 0 0 auto;
  border-radius: 50%; display: grid; place-items: center;
  background: var(--lift); border: 1px solid var(--line);
  font: 600 11.5px/1 var(--mono); color: var(--dim);
}
.sect[open] .num { background: var(--spectrum-soft); color: var(--cyan);
                   border-color: rgba(255, 79, 216, .4); }

.sect .head { flex: 1 1 auto; min-width: 0; }
.sect .head b { display: block; font: 600 14.5px/1.3 var(--ui); }
.sect .head span { font: 400 12px/1.5 var(--ui); color: var(--dim); }

.sect .caret { color: var(--faint); transition: transform .2s ease; flex: 0 0 auto; }
.sect[open] .caret { transform: rotate(180deg); }

.sect .body {
  padding: 4px 16px 18px;
  border-top: 1px solid var(--line-2);
  animation: sect-open .24s ease both;
}
@keyframes sect-open {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

/*  Which sections still need attention. A number in a circle is
    not enough on its own: it says where you are, not what is
    left.  */
.sect .flag {
  font: 500 10px/1 var(--mono); letter-spacing: .08em;
  text-transform: uppercase; padding: 4px 8px; border-radius: 999px;
  flex: 0 0 auto;
}
.sect .flag.todo { color: var(--gold); background: rgba(255, 201, 60, .12); }
.sect .flag.done { color: var(--mint); background: rgba(49, 229, 164, .12); }

/* ---------------------------------------------------- the manual */
.manual { display: grid; grid-template-columns: 220px 1fr; gap: 26px; }
.manual nav { position: sticky; top: 84px; align-self: start; }
.manual nav a {
  display: block; padding: 7px 10px; border-radius: 8px;
  font: 400 13px/1.4 var(--ui); color: var(--dim); text-decoration: none;
}
.manual nav a:hover { background: var(--lift); color: var(--text); }
.manual h2 { margin: 30px 0 10px; font: 600 19px/1.3 var(--display); }
.manual h2:first-child { margin-top: 0; }
.manual ol { padding-left: 20px; }
.manual li { margin: 0 0 10px; line-height: 1.65; }

/* ------------------------------------------------------ responsive */
@media (max-width: 900px) {
  .pipe { grid-template-columns: 1fr 1fr; }
  .pipe::before, .pipe-dot { display: none; }
  .pipe-stage::after { content: none; }
  .manual { grid-template-columns: 1fr; }
  .manual nav { position: static; }
}
@media (max-width: 560px) {
  .pipe { grid-template-columns: 1fr; }
  .brow { flex-wrap: wrap; }
  .brow .act { width: 100%; }
}

/* -------------------------------------------------- reduced motion */
/*  Nothing here is load-bearing. With motion off the pipeline is a
    row of cards with arrows, which says the same thing at rest.  */
@media (prefers-reduced-motion: reduce) {
  .pipe-dot { animation: none; left: 8%; }
  .sect .body { animation: none; }
  .bcard, .brow, .pipe-stage { transition: none; }
  .bcard:hover, .pipe-stage:hover { transform: none; }
}

/* ============================================================
   CONSTELLATION

   One source at the centre, its accounts fanned out beneath it
   on dotted lines that crawl. Used twice, with the same markup
   and different data:

     the dashboard   the bridges this customer actually has,
                     so it is a picture of their setup rather
                     than a menu of possibilities
     the home page   every source and every destination, which
                     is the product's whole claim in one image

   The curves are one inline SVG sized in viewBox units and
   stretched with preserveAspectRatio="none". That is why the
   nodes are positioned in percentages rather than pixels: the
   two layers have to agree at every width, and only percentages
   survive the stretch.
   ============================================================ */

.constel { position: relative; }
.constel svg.wires {
  position: absolute; inset: 0; width: 100%; height: 100%;
  overflow: visible; pointer-events: none; z-index: 0;
}

/*  The crawl is the only motion here that means anything: it says
    a signal TRAVELS this line, in that direction.  */
.constel .wire {
  fill: none;
  stroke: var(--cyan);
  stroke-width: 1.4;
  stroke-dasharray: 3 7;
  opacity: .42;
  animation: wire-crawl 2.4s linear infinite;
}
.constel .wire.live { opacity: .85; stroke-width: 1.9; }
.constel .wire.idle { stroke: var(--faint); opacity: .3; animation: none; }
@keyframes wire-crawl { to { stroke-dashoffset: -40; } }

.constel .hub {
  position: absolute; left: 50%; top: 0; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center;
  z-index: 2; text-align: center;
}
.hubcore {
  width: 78px; height: 78px; border-radius: 24px;
  display: grid; place-items: center;
  background: var(--spectrum);
  box-shadow: 0 0 46px rgba(255, 79, 216, .40);
}
.hubcore .mark-mono { background: transparent; border: 0; color: #12061F; }

.constel .ring {
  position: absolute; left: 0; right: 0;
  display: flex; justify-content: center; gap: 24px; flex-wrap: wrap;
  z-index: 2;
}

.constel .node {
  display: flex; flex-direction: column; align-items: center;
  width: 78px; text-decoration: none; color: inherit;
}
.constel .node .tag {
  display: block; margin-top: 9px; text-align: center;
  font: 400 9.5px/1.3 var(--mono); letter-spacing: .12em;
  text-transform: uppercase; color: var(--faint);
}
.constel a.node:hover .tag { color: var(--dim); }

/* ------------------------------------------------------- the marks */
/*  One box, two contents: the operator's official SVG, or our
    monogram. The box is identical either way so the layout does not
    shift the day a logo is dropped in.  */
.mark {
  width: var(--mk, 44px); height: var(--mk, 44px);
  border-radius: calc(var(--mk, 44px) * .27);
  display: grid; place-items: center; flex: 0 0 auto;
  position: relative;
}
.mark-real {
  background: #fff;
  border: 1px solid rgba(255, 255, 255, .12);
  padding: calc(var(--mk, 44px) * .14);
}
/*  A white plate under every official mark, always. Brand guidelines
    assume a light ground; dropping a dark-on-transparent logo onto
    aubergine makes it vanish, and the fix for that is NOT to recolour
    the logo.  */
.mark-real svg { width: 100%; height: 100%; display: block; }

.mark-mono {
  background: var(--lift);
  border: 1px solid var(--line);
  color: var(--mt, var(--text));
  font: 600 calc(var(--mk, 44px) * .27) / 1 var(--mono);
  letter-spacing: .02em;
}

.mark .badge {
  position: absolute; right: -4px; top: -4px;
  width: 14px; height: 14px; border-radius: 50%;
  border: 2.5px solid var(--deep); background: var(--faint);
}
.mark .badge.on   { background: var(--mint); }
.mark .badge.off  { background: var(--gold); }

/* ------------------------------------------------- home page hero */
/*  Every node is pinned to a percentage of the SAME coordinate space the
    wires are drawn in, so the two layers cannot drift apart. That is why
    the box keeps its aspect ratio rather than growing with its content:
    a percentage only means something against a known height.  */
.constel-hero {
  position: relative;
  width: 100%;
  aspect-ratio: var(--cw, 1000) / var(--ch, 660);
  margin: 6px 0 0;
  /*  THE MARKS HAVE TO SCALE WITH THE WIRES.

      The wires live in a viewBox that stretches to fill this box; the marks
      were a fixed 42px. So the distance between a mark's edge and the start
      of its wire was only correct at one container width, and opened into a
      gap or closed over the mark at every other — which is what the first
      version of this looked like on the real page.

      `cqw` ties both to the same number: 1cqw is 1% of this box's width,
      which is exactly what one viewBox unit is worth here.  */
  container-type: inline-size;
}

.constel-hero .wires {
  position: absolute; inset: 0; width: 100%; height: 100%;
  overflow: visible; pointer-events: none;
}

.constel-hero .cnode {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex; align-items: center;
  gap: clamp(6px, 1cqw, 12px);
  white-space: nowrap; z-index: 2;
}
/*  The label sits on the OUTSIDE of each column, so nothing sits between a
    mark and the wire leaving it.  */
.constel-hero .cnode.in  { flex-direction: row-reverse; }
.constel-hero .cnode .tag {
  font: 400 clamp(8.5px, 1.05cqw, 11px)/1.2 var(--mono);
  letter-spacing: .13em; text-transform: uppercase; color: var(--faint);
}

/*  4.2cqw is 42 viewBox units, which is the size the geometry in
    inc/constellation.php was written against. The clamps stop it becoming
    unreadable in a narrow column or comically large in a wide one.  */
.constel-hero .cnode.in  .mark { --mk: clamp(30px, 4.2cqw, 52px); }
.constel-hero .cnode.out .mark { --mk: clamp(26px, 3.6cqw, 46px); }

.constel-hero .ccore {
  position: absolute;
  transform: translate(-50%, -50%);
  /*  12.4cqw is 124 viewBox units — the radius the wire endpoints in
      inc/constellation.php stop short of, so the curves meet the block's
      edge at every width instead of only at one.  */
  /*  The ceiling is 176px rather than 150 so 12.4cqw stays the live value
      right across the widths this drawing runs at. Clamping earlier made the
      curves stop short of the block, which is the same drift this whole file
      was rewritten to remove — just at one end of the range instead of all
      of it.  */
  width: clamp(84px, 12.4cqw, 176px);
  height: clamp(84px, 12.4cqw, 176px);
  border-radius: clamp(22px, 3.4cqw, 40px);
  display: grid; place-items: center; z-index: 3;
  background: var(--spectrum);
  box-shadow: 0 0 72px rgba(255, 79, 216, .38);
  font: 600 clamp(9px, 1.15cqw, 13px)/1.5 var(--mono); color: #12061F;
  letter-spacing: .12em; text-align: center; text-transform: uppercase;
}

.constel-band {
  margin: 18px 0 0; text-align: center;
  font: 400 10.5px/1 var(--mono); letter-spacing: .22em;
  text-transform: uppercase; color: var(--faint);
}

@media (max-width: 900px) {
  .constel svg.wires { display: none; }
  .constel .hub, .constel .ring { position: static; transform: none; }
  .constel .hub { margin-bottom: 22px; }
  .constel .ring { margin-top: 20px; }

  /*  Below this width the labels collide and the marks are too small to
      read, so the drawing gives up on being a drawing and becomes what it
      was always saying: two lists and an engine between them.  */
  .constel-hero { aspect-ratio: auto; display: grid; gap: 16px;
                  grid-template-columns: 1fr; }
  .constel-hero .wires { display: none; }
  .constel-hero .cnode, .constel-hero .ccore {
    position: static; transform: none;
  }
  .constel-hero .ccore { width: 100%; height: auto; border-radius: 16px;
                         padding: 20px 16px; order: 2; }
  .constel-hero .cnode.in  { order: 1; flex-direction: row; }
  .constel-hero .cnode.out { order: 3; flex-direction: row; }
  .constel-hero .cnode { justify-content: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
  .constel .wire { animation: none; }
}

/*  The step label above each group of sections. Numbered because it genuinely
    is a sequence — a signal reaches step 4 by passing through 1, 2 and 3, and
    nothing below step 4 can happen until the ones above it are done.  */
.steplbl{
  margin:22px 2px 8px;
  font:500 10px/1 var(--mono);letter-spacing:.18em;
  text-transform:uppercase;color:var(--faint);
}
.steplbl:first-child{margin-top:14px}
