/* ============================================================
   DevCo · Section 05 — The Ecosystem
   The centrepiece. A coordinated-network diagram that assembles
   on scroll over a layered survey-document backdrop.
   ============================================================ */
.ecosystem{position:relative;isolation:isolate;}

/* ── Layered backdrop ─────────────────────────────────────── */
.ecosystem__backdrop{position:absolute;inset:0;overflow:hidden;
  z-index:0;pointer-events:none;}
.ecosystem__backdrop>*{position:absolute;}

/* warm horizon glow + cool top wash on the base */
.ecosystem__glow{inset:0;
  background:
    radial-gradient(80% 60% at 50% 110%,rgba(168,90,58,.18) 0%,
      rgba(168,90,58,.05) 25%,transparent 55%),
    radial-gradient(60% 40% at 50% -10%,rgba(111,126,99,.10) 0%,transparent 60%);}

/* drifting coordinate grid */
.ecosystem__grid{inset:-8% 0;width:100%;height:116%;opacity:.12;}
.ecosystem__grid-fine line{stroke:var(--bone);stroke-width:.25;}
.ecosystem__grid-major line{stroke:var(--sage);stroke-width:.4;opacity:.6;}
.ecosystem__coords text{fill:var(--bone);opacity:.4;
  font-family:var(--font-mono);font-size:8px;letter-spacing:.1em;}

/* primary drifting contour layer */
.ecosystem__contours{inset:-10% 0;width:100%;height:120%;
  opacity:.22;mix-blend-mode:screen;}

/* abstract Indian-Ocean shoreline silhouette */
.ecosystem__shore{inset:-6% 0;width:100%;height:112%;opacity:.18;}
.ecosystem__shore-fill{fill:var(--bone);opacity:.04;}
.ecosystem__shore-line{fill:none;stroke:var(--sage);stroke-width:.5;
  stroke-dasharray:3 4;opacity:.6;}
.ecosystem__shore-label{fill:var(--bone);opacity:.55;
  font-family:var(--font-mono);font-size:8px;letter-spacing:.18em;}

/* survey dot-field */
.ecosystem__dots{inset:-4% 0;width:100%;height:108%;opacity:.5;}
.ecosystem__dots circle{fill:var(--bone);}
.ecosystem__dot-halo{fill:none;stroke:var(--bone);stroke-width:.3;opacity:.25;}

/* giant faint ghost serif word */
.ecosystem__ghost{right:-3%;top:6%;
  font-family:var(--font-display);font-style:italic;
  font-size:clamp(160px,22vw,380px);line-height:.85;
  color:var(--bone);opacity:.06;letter-spacing:-.03em;
  white-space:nowrap;user-select:none;}

/* warm horizon band + hairline at the very bottom */
.ecosystem__horizon{left:0;right:0;bottom:0;height:280px;
  background:linear-gradient(180deg,transparent 0%,
    rgba(168,90,58,.07) 60%,rgba(168,90,58,.18) 100%);}
.ecosystem__horizon-line{left:0;right:0;bottom:0;height:var(--hair);opacity:.6;
  background:linear-gradient(90deg,transparent 0%,var(--rust) 40%,
    var(--rust) 60%,transparent 100%);}

/* ── Foreground layout ────────────────────────────────────── */
.ecosystem__inner{position:relative;z-index:2;}
.ecosystem__grid-layout{display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.2fr);
  gap:clamp(48px,6vw,96px);align-items:center;}

/* — copy column — */
.ecosystem__headline{margin:clamp(28px,4vh,40px) 0 clamp(24px,3.4vh,36px);
  max-width:13ch;}
.ecosystem__headline em{font-style:italic;}
.ecosystem__lead{max-width:460px;margin:0 0 clamp(32px,4.6vh,44px);}

.ecosystem__figure{max-width:460px;padding-top:clamp(24px,3.4vh,30px);
  border-top:var(--hair) solid var(--bone-hair);}
.ecosystem__figcap{display:block;margin-bottom:14px;}
.ecosystem__figbody{font-size:var(--fs-body-sm);line-height:1.66;margin:0;}

/* ── The diagram ──────────────────────────────────────────── */
.ecosystem__diagram{position:relative;margin:0;
  width:100%;max-width:560px;justify-self:center;
  /* clears the fixed nav when the diagram is scrolled to / centred */
  scroll-margin-top:120px;}
.ecosystem__diagram-cap{display:flex;align-items:center;gap:10px;
  margin-bottom:18px;padding-bottom:14px;
  border-bottom:var(--hair) solid var(--bone-hair);}
.ecosystem__diagram-cap-mark{width:6px;height:6px;flex:none;
  border:var(--hair) solid var(--accent);transform:rotate(45deg);}

/* viewBox already carries the internal gutters; height tracks width via
   the compact 560×630 aspect ratio. max-height caps it to the viewport so
   the diagram is never cropped by the fixed nav, and aspect-ratio keeps it
   centred when the height cap engages. */
.ecosystem__svg{display:block;width:100%;height:auto;
  max-height:78vh;aspect-ratio:560 / 630;margin-inline:auto;
  overflow:visible;scroll-margin-top:120px;}

/* connector lines — dotted sage; motion.js draws them via data-draw */
.ecosystem__link{stroke:var(--sage);stroke-opacity:.7;stroke-width:.55;}

/* hub dots on DevCo */
.ecosystem__hubdot{fill:var(--accent);}

/* node boxes */
.ecosystem__node-box{fill:none;}
.ecosystem__node-box--dashed{stroke:var(--bone-soft);stroke-width:.5;
  stroke-dasharray:2 2;}
.ecosystem__node-box--devco{fill:var(--ink);stroke:var(--accent);stroke-width:.7;}
.ecosystem__node-box--halco{stroke:var(--bone-soft);stroke-width:.7;}
.ecosystem__node-tick line{stroke:var(--accent);stroke-width:.7;}

/* node text */
.ecosystem__node-label{fill:var(--bone-soft);
  font-family:var(--font-mono);font-size:9.5px;letter-spacing:.05em;}
.ecosystem__node-name{fill:var(--bone);
  font-family:var(--font-display);font-size:28px;letter-spacing:-.01em;}
.ecosystem__node-sub{fill:var(--bone-faint);
  font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;
  text-transform:uppercase;}
/* axis labels — rotated -90° in the diagram's left gutter, centred on
   their tier so they sit clear of every node box */
.ecosystem__axis{fill:var(--bone-faint);
  font-family:var(--font-mono);font-size:8.5px;letter-spacing:.22em;
  text-transform:uppercase;}

/* ── Diagram assembly motion ──────────────────────────────────
   Nodes start hidden + offset; the Motion layer adds .is-assembling
   to the figure once it enters the viewport (IntersectionObserver,
   plays once — round 3: auto-assemble, not scroll-scrubbed). The
   hubdots and ticks ride with their parent node group.
   FAIL-SAFE: if .is-assembling is never added (slow init, a JS
   error), a CSS animation reveals the whole diagram after 4.5s so
   it is never a permanent void. No-JS / reduced-motion: the nodes
   are not hidden at all, so everything shows immediately.        */
html.js .ecosystem__diagram .ecosystem__node,
html.js .ecosystem__diagram .ecosystem__hubdot{opacity:0;
  animation:ecoFailsafe .6s linear 3s forwards;}
html.js .ecosystem__diagram .ecosystem__node{
  transform:translateY(14px);transform-box:fill-box;transform-origin:center;}
@keyframes ecoFailsafe{from{opacity:0;}to{opacity:1;transform:translateY(0);}}
/* once the Motion layer owns the diagram, it controls the nodes —
   drop the fallback so the choreographed assembly is not cut short */
html.js .ecosystem__diagram.is-assembling .ecosystem__node,
html.js .ecosystem__diagram.is-assembling .ecosystem__hubdot{animation:none;}

html.js .ecosystem__diagram.is-assembling .ecosystem__node{
  opacity:1;transform:translateY(0);
  transition:opacity .62s var(--ease),transform .62s var(--ease);
  transition-delay:var(--eco-delay,0ms);}
html.js .ecosystem__diagram.is-assembling .ecosystem__hubdot{
  opacity:1;transition:opacity .4s var(--ease);
  transition-delay:var(--eco-delay,0ms);}

/* per-tier choreography — lines (1.6s draw) lead, nodes follow */
.ecosystem__diagram.is-assembling .ecosystem__node--input{
  --eco-delay:calc(900ms + var(--eco-i) * 90ms);}
.ecosystem__diagram.is-assembling .ecosystem__node--devco{--eco-delay:1500ms;}
.ecosystem__diagram.is-assembling .ecosystem__hubdot:nth-of-type(1){--eco-delay:1600ms;}
.ecosystem__diagram.is-assembling .ecosystem__hubdot:nth-of-type(2){--eco-delay:1780ms;}
.ecosystem__diagram.is-assembling .ecosystem__node--halco{--eco-delay:2000ms;}
.ecosystem__diagram.is-assembling .ecosystem__node--output{
  --eco-delay:calc(2350ms + var(--eco-i) * 120ms);}

/* settled-state glow pulse on the two hub nodes */
.ecosystem__diagram.is-assembling .ecosystem__node--devco .ecosystem__node-box--devco{
  animation:ecoPulse 6s var(--ease-inout) 2.6s infinite;}
@keyframes ecoPulse{
  0%,100%{stroke-opacity:1;}
  50%{stroke-opacity:.55;}}

/* ── Closing statement lines ──────────────────────────────── */
.ecosystem__close{margin-top:clamp(72px,10vh,116px);text-align:center;}
.ecosystem__close-rule{display:block;width:var(--hair);
  height:clamp(40px,6vh,56px);margin:0 auto clamp(28px,4vh,40px);
  background:var(--bone-hair);}
.ecosystem__close-line{margin:0 auto;max-width:24ch;
  font-family:var(--font-display);font-weight:400;
  font-size:clamp(2.5rem,1.1rem + 4.4vw,5.75rem);
  line-height:1.04;letter-spacing:-.022em;color:var(--bone);}
.ecosystem__close-line--soft{margin-top:.18em;}

/* ── Responsive ───────────────────────────────────────────── */
@media (max-width:960px){
  .ecosystem__grid-layout{grid-template-columns:1fr;
    gap:clamp(48px,8vw,72px);}
  .ecosystem__diagram{max-width:520px;justify-self:stretch;}
  .ecosystem__lead,.ecosystem__figure{max-width:none;}
  .ecosystem__ghost{top:3%;font-size:clamp(140px,30vw,300px);}
}

/* ── Stacked fallback — narrow viewports ──────────────────────
   Always in the DOM, hidden above 640px. Below 640px the SVG is
   swapped for this vertical CSS-flow of the same network so text
   never shrinks below a readable size.                          */
.ecosystem__stack{display:none;}

.ecosystem__stack-axis{color:var(--bone-faint);text-align:center;}
.ecosystem__stack-tier{display:flex;flex-wrap:wrap;justify-content:center;
  gap:8px;margin:0;padding:0;list-style:none;width:100%;}
.ecosystem__chip{font-family:var(--font-mono);font-size:var(--fs-mono);
  letter-spacing:.05em;text-transform:uppercase;color:var(--bone-soft);
  padding:9px 12px;text-align:center;}
.ecosystem__chip--dashed{
  border:var(--hair) dashed var(--bone-soft);}

.ecosystem__stack-flow{position:relative;display:block;
  width:var(--hair);height:34px;opacity:.8;
  background:linear-gradient(180deg,transparent,var(--sage),transparent);}
.ecosystem__stack-flow::after{content:"";position:absolute;
  left:50%;bottom:2px;width:5px;height:5px;transform:translateX(-50%) rotate(45deg);
  border-right:var(--hair) solid var(--sage);
  border-bottom:var(--hair) solid var(--sage);}

.ecosystem__stack-node{display:flex;flex-direction:column;
  align-items:center;gap:6px;width:100%;
  padding:22px 18px;background:var(--ink);text-align:center;}
.ecosystem__stack-node--devco{border:var(--hair) solid var(--accent);
  position:relative;}
.ecosystem__stack-node--halco{border:var(--hair) solid var(--bone-soft);}
.ecosystem__stack-name{font-family:var(--font-display);
  font-size:clamp(1.6rem,7vw,2rem);line-height:1;color:var(--bone);}
.ecosystem__stack-sub{color:var(--bone-faint);}

@media (max-width:640px){
  /* compound selector — beats the shared base.css rule
     `body.devco-site svg{display:block}` (specificity 0,1,1) so the SVG
     truly hides and the stacked fallback takes over below 640px. */
  .ecosystem__diagram .ecosystem__svg{display:none;}
  .ecosystem__diagram{max-width:440px;margin-inline:auto;}
  .ecosystem__stack{display:flex;flex-direction:column;
    align-items:center;gap:12px;}
}

@media (max-width:480px){
  .ecosystem__close-line{max-width:18ch;}
}

/* ── Reduced motion ───────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  html.js .ecosystem__diagram .ecosystem__node,
  html.js .ecosystem__diagram .ecosystem__hubdot{
    opacity:1 !important;transform:none !important;}
  .ecosystem__diagram .ecosystem__node-box--devco{animation:none !important;}
}

/* ============================================================
   ELEMENTOR COMPATIBILITY LAYER — Section 05 Ecosystem
   ------------------------------------------------------------
   The homepage is rebuilt as native Elementor content
   (decision 0003). This section's surrounding copy is native
   Elementor widgets; the network diagram ships inside a single
   Elementor HTML widget (the one documented exception in the
   spec — the diagram is complex SVG, not edited widget-by-widget).

   Elementor wraps every widget in `.elementor-element` and adds
   flex classes (`e-con`, `e-flex`) to containers. The design-
   system classes (`ecosystem__*`, `dc-*`) are applied to those
   Elementor wrappers via the CSS-Classes control. This block
   bridges the two so the styling above applies unchanged, and
   re-creates the layered survey-document BACKDROP — which lived
   as markup in ecosystem.php — as pure CSS keyed to `.ecosystem`
   (decoration is never rebuilt as editable widgets).

   Scoped to `.devco-site` so it never touches WP admin / other
   themes. This block lives in the section's OWN stylesheet — the
   shared elementor-compat.css is not edited (other agents work
   concurrently).
   ============================================================ */

/* ── Section shell — host the absolutely-positioned backdrop ── */
.devco-site #ecosystem.ecosystem{position:relative;isolation:isolate;
  overflow:clip;}

/* warm horizon glow + cool top wash — ported from .ecosystem__glow */
.devco-site #ecosystem.ecosystem::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(80% 60% at 50% 110%,rgba(168,90,58,.18) 0%,
      rgba(168,90,58,.05) 25%,transparent 55%),
    radial-gradient(60% 40% at 50% -10%,rgba(111,126,99,.10) 0%,transparent 60%);}

/* warm horizon band + accent hairline at the very bottom —
   ported from .ecosystem__horizon + .ecosystem__horizon-line */
.devco-site #ecosystem.ecosystem::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:280px;
  z-index:0;pointer-events:none;
  background:linear-gradient(180deg,transparent 0%,
    rgba(168,90,58,.07) 60%,rgba(168,90,58,.18) 100%);
  border-bottom:2px solid transparent;
  border-image:linear-gradient(90deg,transparent 0%,var(--rust) 40%,
    var(--rust) 60%,transparent 100%) 1;}

/* giant faint ghost serif word — ported from .ecosystem__ghost */
.devco-site #ecosystem .ecosystem__inner::before{
  content:"network.";position:absolute;right:-3%;top:4%;z-index:0;
  font-family:var(--font-display);font-style:italic;
  font-size:clamp(160px,22vw,380px);line-height:.85;
  color:var(--bone);opacity:.06;letter-spacing:-.03em;
  white-space:nowrap;user-select:none;pointer-events:none;}

/* keep all real content above the backdrop decoration */
.devco-site #ecosystem .ecosystem__inner{position:relative;z-index:2;}

/* ── Two-column layout — grid must beat Elementor's e-flex ── */
.devco-site #ecosystem .ecosystem__grid-layout.e-con{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.2fr);
  gap:clamp(48px,6vw,96px);align-items:center;}

/* copy column stacks its widgets vertically */
.devco-site #ecosystem .ecosystem__copy.e-con{
  display:flex;flex-direction:column;}

/* ── Eyebrow — flex row of three text widgets ── */
.devco-site #ecosystem .dc-eyebrow.e-con{
  display:flex;flex-direction:row;align-items:center;gap:14px;}
.devco-site #ecosystem .dc-eyebrow__rule{flex:none;}
.devco-site #ecosystem .dc-eyebrow__idx > span,
.devco-site #ecosystem .dc-eyebrow__label > span,
.devco-site #ecosystem .dc-eyebrow__rule > span{display:inline;}

/* ── Headline — Heading widget; push display type to inner tag ── */
.devco-site #ecosystem .ecosystem__headline .elementor-heading-title{
  font:inherit;letter-spacing:inherit;line-height:inherit;
  color:inherit;margin:0;}
.devco-site #ecosystem .ecosystem__headline em{font-style:italic;}

/* ── Lead paragraph — Text Editor widget wraps copy in <p> ── */
.devco-site #ecosystem .ecosystem__lead p{
  font-size:var(--fs-lead);line-height:1.55;margin:0;color:inherit;}

/* ── Figure block (caption + body under a hairline) ── */
.devco-site #ecosystem .ecosystem__figure.e-con{
  display:flex;flex-direction:column;}
.devco-site #ecosystem .ecosystem__figcap span{display:inline;}
.devco-site #ecosystem .ecosystem__figbody p{
  font-size:var(--fs-body-sm);line-height:1.66;margin:0;color:inherit;}

/* ── Diagram column — figure wrapper + caption ── */
.devco-site #ecosystem .ecosystem__diagram.e-con{
  display:flex;flex-direction:column;}
/* the cap mark is an inline-flex child of the caption text widget */
.devco-site #ecosystem .ecosystem__diagram-cap{display:flex;}
.devco-site #ecosystem .ecosystem__diagram-cap .elementor-widget-container{
  display:flex;align-items:center;gap:10px;width:100%;
  margin-bottom:18px;padding-bottom:14px;
  border-bottom:var(--hair) solid var(--bone-hair);}
.devco-site #ecosystem .ecosystem__diagram-cap-mark{
  display:inline-block;width:6px;height:6px;flex:none;
  border:var(--hair) solid var(--accent);transform:rotate(45deg);}

/* the HTML widget carries the SVG + stacked fallback — let it
   fill its column; the SVG/stack styling above applies as-is */
.devco-site #ecosystem .ecosystem__diagram-html .elementor-widget-container{
  width:100%;}

/* ── Closing statement block ── */
.devco-site #ecosystem .ecosystem__close.e-con{
  display:flex;flex-direction:column;align-items:center;
  margin-top:clamp(72px,10vh,116px);text-align:center;}
/* the close-rule is a text widget; its inner span is the hairline */
.devco-site #ecosystem .ecosystem__close-rule{
  margin:0 auto clamp(28px,4vh,40px);}
.devco-site #ecosystem .ecosystem__close-rule-inner{
  display:block;width:var(--hair);
  height:clamp(40px,6vh,56px);background:var(--bone-hair);}
/* close lines are Heading widgets; push the display type inward */
.devco-site #ecosystem .ecosystem__close-line .elementor-heading-title{
  margin:0 auto;max-width:24ch;
  font-family:var(--font-display);font-weight:400;
  font-size:clamp(2.5rem,1.1rem + 4.4vw,5.75rem);
  line-height:1.04;letter-spacing:-.022em;color:var(--bone);}
.devco-site #ecosystem .ecosystem__close-line--soft .elementor-heading-title{
  margin-top:.18em;}

/* ── Responsive — mirror the section's own breakpoints ── */
@media (max-width:960px){
  .devco-site #ecosystem .ecosystem__grid-layout.e-con{
    grid-template-columns:1fr;gap:clamp(48px,8vw,72px);}
  .devco-site #ecosystem .ecosystem__diagram.e-con{justify-self:stretch;}
}
@media (max-width:480px){
  .devco-site #ecosystem .ecosystem__close-line .elementor-heading-title{
    max-width:18ch;}
}

/* ============================================================
   §05 — Round 3: the pinned scroll-assembly is removed. The
   section is normal-flow and sized to its content. The diagram
   AUTO-ASSEMBLES once, when the section enters the viewport
   (the Motion agent's IntersectionObserver adds .is-assembling
   to .ecosystem__diagram — see the assembly choreography above).
   It is not scroll-dependent. No `dc-pin` hooks remain.
   ============================================================ */
.devco-site #ecosystem.ecosystem{position:relative;}

/* reduced-motion / no-JS: the diagram is fully assembled and
   static — the SVG draw is reset to complete */
@media (prefers-reduced-motion:reduce){
  .devco-site #ecosystem .ecosystem__link[data-draw],
  .devco-site #ecosystem [data-draw]{
    stroke-dasharray:none !important;
    stroke-dashoffset:0 !important;
  }
  .devco-site #ecosystem .ecosystem__node{
    opacity:1 !important;transform:none !important;
  }
}

/* ============================================================
   §05 — CONNECTOR FLOW ANIMATION
   ------------------------------------------------------------
   After assembly completes, motion.js adds .is-assembled to
   .ecosystem__diagram. Only then do these rules engage, so
   the flowing-energy effect never fights the draw-in.

   Technique: a dash pattern (4px dash / 220px gap) is placed
   on each .ecosystem__link. Animating stroke-dashoffset by
   -224px (one full dash+gap cycle) makes the dash travel
   forward along the path at a slow, continuous pace — the
   "network is live" effect. A second layered opacity pulse
   breathes very gently over the top.

   The gap (220px) is large enough that only one travelling
   dot is visible on most connector lengths, keeping it quiet.
   Stagger offsets (--eco-flow-delay) spread the starts so
   all lines feel independent yet coordinated.

   On-palette: sage for the travelling dash, rust/accent for
   a ghost-highlight on the two hub connectors (DevCo <->
   HALCO tier), achieved by a higher stroke-opacity variant.

   Reduced-motion: block is fully suppressed by the guard
   at the bottom of this file.
   ============================================================ */

/* -- keyframes -------------------------------------------- */
@keyframes ecoFlow {
  to { stroke-dashoffset: -224; }
}

@keyframes ecoFlowPulse {
  0%,100% { stroke-opacity: .55; }
  50%      { stroke-opacity: .85; }
}

/* -- base flow state: only fires once .is-assembled exists - */
.ecosystem__diagram.is-assembled .ecosystem__link {
  /* travelling-dash parameters:
     4px dash riding on a 220px gap gives one visible "spark"
     per connector at a time. The total cycle length is 224px. */
  stroke-dasharray: 4 220;
  /* start each link offset by its own stagger amount
     (set via --eco-flow-delay below, defaulting to 0ms)    */
  animation:
    ecoFlow      8s  linear        var(--eco-flow-delay, 0ms) infinite,
    ecoFlowPulse 6s  ease-in-out   var(--eco-flow-delay, 0ms) infinite;
  /* keep the assembly-draw stroke-opacity but allow pulse to vary */
  stroke-opacity: .65;
}

/* -- per-connector stagger (nth-of-type targets SVG siblings) */
/* Connectors rendered by motion.js are direct SVG children —
   stagger 6 slots across the full link set.                  */
.ecosystem__diagram.is-assembled .ecosystem__link:nth-of-type(1)  { --eco-flow-delay:    0ms; }
.ecosystem__diagram.is-assembled .ecosystem__link:nth-of-type(2)  { --eco-flow-delay:  640ms; }
.ecosystem__diagram.is-assembled .ecosystem__link:nth-of-type(3)  { --eco-flow-delay: 1280ms; }
.ecosystem__diagram.is-assembled .ecosystem__link:nth-of-type(4)  { --eco-flow-delay: 1920ms; }
.ecosystem__diagram.is-assembled .ecosystem__link:nth-of-type(5)  { --eco-flow-delay: 2560ms; }
.ecosystem__diagram.is-assembled .ecosystem__link:nth-of-type(6)  { --eco-flow-delay: 3200ms; }
.ecosystem__diagram.is-assembled .ecosystem__link:nth-of-type(7)  { --eco-flow-delay:  480ms; }
.ecosystem__diagram.is-assembled .ecosystem__link:nth-of-type(8)  { --eco-flow-delay: 1120ms; }
.ecosystem__diagram.is-assembled .ecosystem__link:nth-of-type(9)  { --eco-flow-delay: 1760ms; }
.ecosystem__diagram.is-assembled .ecosystem__link:nth-of-type(10) { --eco-flow-delay: 2400ms; }
.ecosystem__diagram.is-assembled .ecosystem__link:nth-of-type(11) { --eco-flow-delay: 3040ms; }
.ecosystem__diagram.is-assembled .ecosystem__link:nth-of-type(12) { --eco-flow-delay:  320ms; }

/* -- hub-tier connectors: very slightly warmer accent tint --
   Connectors entering/exiting DevCo and HALCO get a touch
   of rust by nudging stroke-opacity up so they read as the
   "primary channel". We cannot change stroke colour without
   JS, but a higher opacity on sage-coloured lines already
   reads as marginally warmer on a dark background.          */
.ecosystem__diagram.is-assembled .ecosystem__link--hub {
  stroke-opacity: .80;
  animation-duration: 6s, 5s;   /* slightly faster on hub links */
}

/* -- Elementor-scoped duplicate (belt + braces) ------------ */
/* The SVG lives inside an Elementor HTML widget; the
   .devco-site + #ecosystem scope ensures Elementor's
   specificity resets cannot strip the animation.            */
.devco-site #ecosystem .ecosystem__diagram.is-assembled .ecosystem__link {
  stroke-dasharray: 4 220;
  animation:
    ecoFlow      8s  linear        var(--eco-flow-delay, 0ms) infinite,
    ecoFlowPulse 6s  ease-in-out   var(--eco-flow-delay, 0ms) infinite;
  stroke-opacity: .65;
}

.devco-site #ecosystem .ecosystem__diagram.is-assembled .ecosystem__link--hub {
  stroke-opacity: .80;
  animation-duration: 6s, 5s;
}

/* -- reduced-motion guard: no flow animation, links static - */
@media (prefers-reduced-motion: reduce) {
  .ecosystem__diagram.is-assembled .ecosystem__link,
  .devco-site #ecosystem .ecosystem__diagram.is-assembled .ecosystem__link {
    stroke-dasharray: none !important;
    animation: none !important;
    stroke-opacity: .7 !important;
  }
}
