/* Enrolment hub diagram.
 *
 * Ported from prototypes/benely-home-light.html. Replaces GIF28.gif (1099x741,
 * 17 frames, 82,886 bytes) whose labels were baked pixels - 15px cap height in
 * the source rendered 4.7px at a 390px viewport. The diagram reflows instead of
 * scaling, so the labels are real text at every width.
 *
 * Every selector is scoped under .bnly-hub. The markup ships from
 * template-parts/enrol-hub.php via the [benely_hub] shortcode; the geometry is
 * generated in assets/js/enrol-hub.js.
 */
/* Bound to the Global Kit. --rule-l is a hairline with no kit token; it is
   declared locally rather than invented as one, because adding a kit token is an
   editor-UI action (see CLAUDE.md) and this colour is local to the diagram. */
.bnly-hub{
  --brand:var(--e-global-color-primary,#0092D5);
  --navy:var(--e-global-color-secondary,#154478);
  --mist:var(--e-global-color-mist,#F1F6FA);
  --paper:var(--e-global-color-surface,#FFFFFF);
  --body:var(--e-global-color-deep,#4A4A4A);
  --rule-l:#DCE5EC;
  position:relative;
}
.bnly-hub .hub__card{position:relative;z-index:2;background:var(--paper);
             padding:clamp(20px,2.4vw,34px);
             box-shadow:0 34px 74px -38px rgba(16,29,43,.4);
             border:1px solid var(--rule-l)}.bnly-hub .hub__plinth{position:absolute;z-index:1;inset:auto -28px -28px 40px;height:78%;
               background:var(--mist);border:1px solid var(--rule-l);pointer-events:none}/* The hub graphic replaces GIF28.gif (1099x741, 17 frames, 82,886 bytes), whose
   labels were baked pixels: 15px cap height in the source rendered 9.9px at
   1440 and 4.7px at 390. A raster cannot survive a 0.314 scale factor, so the
   diagram reflows instead of scaling. */
.bnly-hub .hub{margin:0}.bnly-hub .hub__stage{
  --tile:clamp(46px,5.4vw,62px);
  --row:clamp(84px,9.4vw,116px);
  --span:clamp(18px,3.2vw,54px);
  --wire-w:clamp(30px,4vw,58px);
  --wire:var(--rule-l);
  --cyc:5.6s;
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:var(--span);
  /* the sides are 1fr, so in a wide card the diagram just stretches and the
     wire runs grow with it. Cap it and centre instead. */
  max-width:700px;margin-inline:auto;
}.bnly-hub .hub__side{position:relative}.bnly-hub .hub__side-t{position:absolute;width:1px;height:1px;margin:0;overflow:hidden;
             clip-path:inset(50%);white-space:nowrap}.bnly-hub .hub__rail{list-style:none;margin:0;padding:0;position:relative;display:grid;
           grid-template-rows:repeat(4,var(--row))}/* The wire column always sits on the core side; the tiles take the rest. Getting
   this wrong on one rail only puts the two tile columns at different distances
   from the centre - it was out by exactly --wire-w. */
.bnly-hub .hub__rail--in{grid-template-columns:1fr var(--wire-w)}.bnly-hub .hub__rail--out{grid-template-columns:var(--wire-w) 1fr}.bnly-hub .hub__rail--in .hub__node{grid-column:1}.bnly-hub .hub__rail--out .hub__node{grid-column:2}/* Taking the label out of flow makes the tile centre coincide with the row
   centre, which is what lets the wire geometry be derived from the row height
   alone. The label returns to flow in the stacked layout below. */
.bnly-hub .hub__node{position:relative;display:flex;align-items:center;justify-content:center}.bnly-hub .hub__tile{position:relative;width:var(--tile);height:var(--tile);
           border-radius:calc(var(--tile)*.29);background:var(--brand);
           display:grid;place-items:center;flex:0 0 auto}.bnly-hub .hub__i{width:54%;height:54%;fill:none;stroke:#fff;stroke-width:1.9;
        stroke-linecap:round;stroke-linejoin:round}.bnly-hub .hub__label{position:absolute;left:0;right:0;top:calc(50% + var(--tile)/2 + 10px);
            text-align:center;font-size:13px;line-height:1.3;font-weight:600;
            color:var(--navy)}/* ---- the wires -------------------------------------------------------------
   Drawn as SVG paths, not CSS boxes. A box grown with scaleX/scaleY cannot
   follow a curve - the corner has to be a separate piece that pops in, and the
   trace turns a right angle where the wire is round. stroke-dashoffset follows
   the path, arc included.
   The grey wire and the lit wire are the SAME path data, one drawn over the
   other, so they can never disagree about where the wire is. (They did: an
   earlier version drew them separately and the grey one painted on top.)
   Geometry comes from measured pixels via drawHubWires() at the end of this
   file, so arcs stay circular and the trace speed stays constant at any width. */
/* The SVG reaches from the spine to just short of the tile, so the branch
   actually meets what it connects instead of floating near it. Insets rather
   than a width, so the tiles stay put and the geometry script just measures a
   wider box. (100% - --wire-w) is the node column; half of it is the tile
   centre. */
.bnly-hub .hub__wires{position:absolute;top:0;height:100%;overflow:visible;
            pointer-events:none;
            /* an <svg> is a replaced element: left+right will NOT stretch it,
               it just falls back to the default 300x150 intrinsic size. The
               width has to be stated. */
            --reach:calc((100% - var(--wire-w))/2 + var(--tile)/2 + 12px);
            width:calc(100% - var(--reach))}.bnly-hub .hub__wires--in{right:0}.bnly-hub .hub__wires--out{left:0;transform:scaleX(-1)}.bnly-hub .hub__wbase path,
.bnly-hub .hub__wlit path{fill:none;stroke-width:1;
  stroke-linecap:round;stroke-linejoin:round}.bnly-hub .hub__wbase path{stroke:var(--wire)}.bnly-hub .hub__wlit path{stroke:var(--brand);stroke-dasharray:100;stroke-dashoffset:100}.bnly-hub .hub__wlit{opacity:0}.bnly-hub .hub__core{position:relative;display:grid;justify-items:center}.bnly-hub .hub .hub__face{width:clamp(96px,11vw,132px);height:clamp(96px,11vw,132px);
                border-radius:50%;object-fit:cover;background:var(--mist)}.bnly-hub .hub__facewrap{display:block;position:relative}.bnly-hub .hub__link{position:relative;width:2px;height:clamp(24px,3.4vw,44px);
           margin-block:11px;
           background:repeating-linear-gradient(var(--wire) 0 4px,transparent 4px 9px)}.bnly-hub .hub__disc{position:relative;width:clamp(96px,11vw,132px);
           height:clamp(96px,11vw,132px);border-radius:50%;background:var(--mist);
           display:grid;place-items:center}.bnly-hub .hub__b{width:34%;height:auto;display:block}.bnly-hub .hub__link::after,
.bnly-hub .hub__facewrap::after,
.bnly-hub .hub__disc::after,
.bnly-hub .hub__tile::after{
  content:"";position:absolute;pointer-events:none;opacity:0;z-index:1}.bnly-hub .hub__facewrap::after,
.bnly-hub .hub__disc::after{inset:-3px;border-radius:50%;
  border:1.5px solid var(--brand);transform:scale(.96)}.bnly-hub .hub__link::after{inset:0;background:var(--brand);transform:scaleY(0)}.bnly-hub .hub__tile::after{inset:0;border-radius:inherit;border:1.5px solid var(--brand);
  transform:scale(1)}

@media (prefers-reduced-motion:no-preference){.bnly-hub .hub__facewrap::after,
.bnly-hub .hub__disc::after{animation:hubInit var(--cyc) linear infinite}.bnly-hub .hub__link::after{animation:hubLink var(--cyc) linear infinite}.bnly-hub .hub__tile::after{animation:hubLand var(--cyc) linear infinite}.bnly-hub .hub__node:nth-child(1) .hub__tile::after,
.bnly-hub .hub__node:nth-child(4) .hub__tile::after{animation-name:hubLandOut}/* one opacity animation for the whole lit group, one dash animation per path */
.bnly-hub .hub__wlit{animation:wRelease var(--cyc) linear infinite}.bnly-hub .hub__wlit path{animation-duration:var(--cyc);animation-timing-function:linear;
                  animation-iteration-count:infinite}.bnly-hub .hub__wlit .w-trunk{animation-name:wTrunk}.bnly-hub .hub__wlit .w-spine-up,
.bnly-hub .hub__wlit .w-spine-down{animation-name:wSpine}.bnly-hub .hub__wlit .w-b2,
.bnly-hub .hub__wlit .w-b3{animation-name:wInner}.bnly-hub .hub__wlit .w-b1,
.bnly-hub .hub__wlit .w-b4{animation-name:wOuter}/* Held at frame 0 until the section is revealed. Must come after the
     shorthands - `animation` resets animation-play-state to running. */
.bnly-hub .hub__facewrap::after,
.bnly-hub .hub__disc::after,
.bnly-hub .hub__link::after,
.bnly-hub .hub__tile::after,
.bnly-hub .hub__wlit,
.bnly-hub .hub__wlit path{animation-play-state:paused}.bnly-hub.is-in .hub__facewrap::after,
.bnly-hub.is-in .hub__disc::after,
.bnly-hub.is-in .hub__link::after,
.bnly-hub.is-in .hub__tile::after,
.bnly-hub.is-in .hub__wlit,
.bnly-hub.is-in .hub__wlit path{animation-play-state:running}
}

/* Windows are sized so the trace runs at a near-constant speed rather than each
   stage taking an equal slice: the spine is ~2.5x the length of a branch, so it
   gets ~2.5x the time. Uneven slices are what made it feel like it stopped and
   restarted at every joint. */
@keyframes wTrunk{0%,9%{stroke-dashoffset:100}13.9%,100%{stroke-dashoffset:0}}
@keyframes wSpine{0%,13.9%{stroke-dashoffset:100}30.7%,100%{stroke-dashoffset:0}}
@keyframes wInner{0%,20.1%{stroke-dashoffset:100}26.1%,100%{stroke-dashoffset:0}}
@keyframes wOuter{0%,30.7%{stroke-dashoffset:100}37.7%,100%{stroke-dashoffset:0}}
@keyframes wRelease{0%,74%{opacity:1}88%,100%{opacity:0}}
@keyframes hubInit{
  0%{transform:scale(.96);opacity:0;animation-timing-function:ease-out}
  2%{opacity:.9;animation-timing-function:ease-out}
  9%,100%{transform:scale(1.22);opacity:0}}
@keyframes hubLink{
  0%,4%{transform:scaleY(0);opacity:1}
  9%{transform:scaleY(1);opacity:1}
  74%{transform:scaleY(1);opacity:1;animation-timing-function:ease-in}
  88%,100%{transform:scaleY(1);opacity:0}}
@keyframes hubLand{
  0%,26%{transform:scale(1);opacity:0;animation-timing-function:ease-out}
  29%{opacity:.85;animation-timing-function:ease-out}
  41%,100%{transform:scale(1.28);opacity:0}}
@keyframes hubLandOut{
  0%,37.7%{transform:scale(1);opacity:0;animation-timing-function:ease-out}
  41%{opacity:.85;animation-timing-function:ease-out}
  53%,100%{transform:scale(1.28);opacity:0}}.bnly-hub .hub__cap{margin:clamp(18px,2.4vw,30px) auto 0;max-width:46ch;
          font-size:13.5px;line-height:1.6;color:var(--body);text-align:center}

/* Below the stack breakpoint the diagram cannot shrink - it reflows. Wires off,
   core on top, nodes 2-up, labels back in flow at full size. */
/* Stacked: the core moves ABOVE and the two rails stay side by side, spines on
   their inner edges. The first version dropped the wires entirely and laid the
   eight nodes out 2-up, which threw away the one thing the diagram actually
   says - that Benely sits between the benefits and the systems. Moving the core
   out from between the rails is what frees the width to keep the connectors:
   with it still in the middle at 320 each rail gets 66px, less than one tile. */
@media (max-width:860px){.bnly-hub .hub__stage{grid-template-columns:1fr 1fr;
              /* zero, so the two rails meet and their spines land on the same
                 x - one central line rather than two 14px apart */
              column-gap:0;row-gap:0;
              --wire-w:clamp(26px,7vw,44px);
              --row:clamp(78px,20vw,104px);
              max-width:540px}.bnly-hub .hub__core{grid-column:1 / -1;order:-1;margin-bottom:clamp(14px,4vw,28px)}.bnly-hub .hub__link{height:clamp(18px,4vw,30px);margin-block:9px}.bnly-hub .hub__label{font-size:12.5px}/* Both rails author the same central drop and spine, landing a rounded pixel
     apart and reading as one 2px line. They are exact duplicates, so only the
     left rail draws them. */
.bnly-hub .hub__wires--out .w-trunk,
.bnly-hub .hub__wires--out .w-spine-up,
.bnly-hub .hub__wires--out .w-spine-down{display:none}

}

/* Top-down wavefront: drop, upper spine, lower spine, with each branch firing as
   the spine passes it. Distinct keyframes rather than animation-delay - a delay
   shifts the whole loop, so a delayed path reads as already-drawn at the start
   of every cycle (the group's opacity release is not delayed).
   Guarded on motion as well as width: outside the guard these names would be
   set with no duration to go with them. */
@media (max-width:860px) and (prefers-reduced-motion:no-preference){.bnly-hub .hub__wlit .w-spine-up{animation-name:wSpineA}.bnly-hub .hub__wlit .w-spine-down{animation-name:wSpineB}.bnly-hub .hub__wlit .w-b1{animation-name:wN1}.bnly-hub .hub__wlit .w-b2{animation-name:wN2}.bnly-hub .hub__wlit .w-b3{animation-name:wN3}.bnly-hub .hub__wlit .w-b4{animation-name:wN4}.bnly-hub .hub__tile::after,
.bnly-hub .hub__node:nth-child(1) .hub__tile::after,
.bnly-hub .hub__node:nth-child(4) .hub__tile::after{animation-name:hubLandAll}
}
@keyframes wSpineA{0%,14%{stroke-dashoffset:100}24%,100%{stroke-dashoffset:0}}
@keyframes wSpineB{0%,24%{stroke-dashoffset:100}34%,100%{stroke-dashoffset:0}}
@keyframes wN1{0%,14%{stroke-dashoffset:100}20%,100%{stroke-dashoffset:0}}
@keyframes wN2{0%,20%{stroke-dashoffset:100}26%,100%{stroke-dashoffset:0}}
@keyframes wN3{0%,28%{stroke-dashoffset:100}34%,100%{stroke-dashoffset:0}}
@keyframes wN4{0%,34%{stroke-dashoffset:100}40%,100%{stroke-dashoffset:0}}
@keyframes hubLandAll{
  0%,40%{transform:scale(1);opacity:0;animation-timing-function:ease-out}
  43%{opacity:.85;animation-timing-function:ease-out}
  55%,100%{transform:scale(1.28);opacity:0}}


/* The section stacks well before the diagram does. Side by side, the card only
   gets ~5.4/12 of the width, which left the wire runs at 18px of straight line
   at 861 - the arc alone is 16px. Stacking the section to 1200 hands the card
   the full width, so the diagram stays side by side and readable down to the
   point where it stacks on its own at 860. */

@media (max-width:860px){.bnly-hub .hub__plinth{display:none}
}


