/* ============================================================
   HERO — FAN OF WORK (12 recent builds)
   Full-bleed panel, centred editorial headline, and an
   overlapping tilted fan of project shots that keeps drifting
   after it lands and opens in a lightbox on click.

   Per-card geometry (--r rotation, --y arc offset, --z stacking,
   --d reveal delay) is written into the markup server-side, so
   the fan is correct from CSS alone. Breakpoints never rewrite
   it — they scale it through the --rs / --ys multipliers on .fan.

   The pre-reveal hidden state hangs off .fan-pre, which an inline
   script adds at parse time — without JS the cards render in place.
   Loaded by digibro-v5.php after digibro-v5.css.
   ============================================================ */
.hero-fan{position:relative;border-bottom:1px solid var(--line)}
/* Full bleed. Both rules have to out-weigh digibro-v5.css, which gives
   .e-con.hero its own padding and pins .e-con.wrap to the 1180px measure. */
.digibro-page .e-con.hero.hero-fan{padding-block:0;background:none}
.digibro-page .e-con.hero-fan .e-con.wrap,
.digibro-page .e-con.hero-fan .e-con.wrap>.e-con-inner{width:100%;max-width:none;margin-inline:0}
.fan-panel{
  position:relative;text-align:center;overflow:hidden;
  background:
    radial-gradient(120% 78% at 50% 0%,#EFEDFF 0%,rgba(239,237,255,0) 60%),
    linear-gradient(180deg,#F7F8FD 0%,#FFFFFF 62%);
  padding:clamp(2.2rem,4.4vw,4rem) clamp(1.1rem,4vw,3rem) clamp(1.8rem,3.2vw,2.8rem);
}
.digibro-page .fan-panel h1{
  max-width:20ch;margin-inline:auto;
  font-size:clamp(2.05rem,1.1rem + 3.9vw,4.1rem);line-height:1.02;letter-spacing:-.035em;
}
.fan-panel h1 span{color:var(--blue)}
.digibro-page .fan-sub{
  margin:clamp(.9rem,1.6vw,1.25rem) auto 0;max-width:52ch;
  color:var(--body);font-size:clamp(.98rem,.95rem + .25vw,1.14rem);
}

/* ---- the fan ---- */
.fan{
  --cw:clamp(96px,10.6vw,168px);
  --ov:clamp(30px,2.7vw,42px);
  --rs:1;   /* rotation multiplier per breakpoint */
  --ys:1;   /* arc-depth multiplier per breakpoint */
  margin-top:clamp(1.9rem,4vw,3.1rem);
  padding-bottom:clamp(1.2rem,2.4vw,2.2rem);
}
.fan-track{display:flex;justify-content:center;align-items:flex-start}
.fan-card{
  flex:0 0 var(--cw);width:var(--cw);position:relative;display:block;
  border-radius:clamp(9px,1.1vw,15px);overflow:hidden;background:var(--paper-3);
  border:3px solid #fff;box-shadow:0 0 0 1px rgba(11,11,18,.11),0 10px 26px rgba(11,11,18,.18);
  transform-origin:50% 100%;z-index:var(--z,1);text-decoration:none;cursor:zoom-in;
  transform:translateY(calc(var(--y,0px) * var(--ys))) rotate(calc(var(--r,0deg) * var(--rs)));
  transition:opacity .7s var(--ease),transform .8s var(--ease),box-shadow .3s var(--ease);
  transition-delay:var(--d,0ms);
}
.fan-card+.fan-card{margin-left:calc(-1 * var(--ov))}
.fan-pre .fan-card{opacity:0;transform:translateY(46px) rotate(0deg) scale(.92)}
.fan-pre.is-in .fan-card{
  opacity:1;transform:translateY(calc(var(--y,0px) * var(--ys))) rotate(calc(var(--r,0deg) * var(--rs)))
}

/* ---- the fan keeps breathing once it has landed ----
   .is-live is added by digibro-hero.js after the staggered reveal
   finishes. Each card drifts on its own clock: the duration and the
   (negative, so it starts mid-cycle) delay are both derived from the
   card's reveal delay, which puts every card at a different phase. */
@keyframes dg-fan-float{
  0%,100%{transform:translateY(calc(var(--y,0px) * var(--ys))) rotate(calc(var(--r,0deg) * var(--rs)))}
  50%{transform:translateY(calc(var(--y,0px) * var(--ys) - 11px)) rotate(calc(var(--r,0deg) * var(--rs) + .9deg))}
}
.fan.is-live .fan-card{
  animation:dg-fan-float calc(4.8s + var(--d,0ms) * 3.2) ease-in-out infinite;
  animation-delay:calc(var(--d,0ms) * -4.5)
}
/* nothing should drift while the visitor is reading a card or a preview */
.fan.is-live .fan-track:hover .fan-card,
body.dg-lb-open .fan.is-live .fan-card{animation-play-state:paused}

.fan-card::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(11,11,18,0) 46%,rgba(11,11,18,.62) 100%);
  opacity:0;transition:opacity .25s var(--ease)
}
.fan-card img{width:100%;aspect-ratio:3/4;object-fit:cover;object-position:50% 0}
.fan-cap{
  position:absolute;left:0;right:0;bottom:0;z-index:3;padding:.5rem .45rem;
  font-size:.66rem;font-weight:700;letter-spacing:.02em;color:#fff;line-height:1.25;
  opacity:0;transform:translateY(6px);transition:opacity .25s var(--ease),transform .25s var(--ease)
}
@media (hover:hover){
  .fan .fan-card:hover,.fan .fan-card:focus-visible{
    animation:none;
    transform:translateY(calc(var(--y,0px) * var(--ys) - 20px)) rotate(0deg) scale(1.09);
    z-index:60;box-shadow:0 0 0 1px rgba(11,11,18,.14),0 22px 50px rgba(11,11,18,.28);
    transition-delay:0ms
  }
  .fan-card:hover::after,.fan-card:focus-visible::after{opacity:1}
  .fan-card:hover .fan-cap,.fan-card:focus-visible .fan-cap{opacity:1;transform:none}
  .fan-track:hover .fan-card:not(:hover){opacity:.72}
}

/* ---- panel footer ---- */
.digibro-page .fan-note{
  margin:clamp(1.2rem,2.4vw,1.9rem) auto 0;max-width:58ch;
  font-size:.9rem;color:var(--grey)
}
.fan-btns{justify-content:center;margin-top:clamp(1.1rem,2.2vw,1.5rem)}
/* .digibro-page ul{margin:0} in digibro-v5.css outweighs a bare class,
   so this rule has to carry .digibro-page too or the rule above the
   border collapses onto the buttons. */
.digibro-page .fan-meta{
  display:flex;flex-wrap:wrap;justify-content:center;gap:.7rem 1.6rem;
  max-width:820px;margin:clamp(2.1rem,3.8vw,3rem) auto 0;
  padding-top:clamp(1.4rem,2.6vw,2rem);
  border-top:1px solid var(--line)
}
.fan-meta li{display:flex;align-items:center;gap:.4rem;font-size:.84rem;font-weight:600;color:var(--body)}
.fan-meta svg{width:16px;height:16px;color:var(--accent);flex:0 0 auto}

/* The phone/tablet block lives at the END of this file. Parked here it was
   silently dropped by the CSS parser (the rule never reached the cascade,
   though the bytes were served); moved to the end it applies. If you add
   breakpoint rules for the fan, put them there too and verify with
   document.styleSheets rather than by eye. */

/@media (prefers-reduced-motion:reduce){
  .fan-card{transition:none}
  .fan-pre .fan-card{
    opacity:1;transform:translateY(calc(var(--y,0px) * var(--ys))) rotate(calc(var(--r,0deg) * var(--rs)))
  }
  .fan.is-live .fan-card{animation:none}
}

/* ============================================================
   LIGHTBOX
   One overlay, built once by digibro-hero.js and reused.
   The arrows sit BESIDE the image in a flex stage rather than on
   top of it, so they never cover the shot and never need a
   separate mobile layout. Close is pinned top-right, clear of the
   WordPress admin bar for logged-in users.
   ============================================================ */
.dg-lb{
  position:fixed;inset:0;z-index:400;display:flex;align-items:center;justify-content:center;
  padding:clamp(3.6rem,7vw,4.6rem) clamp(.5rem,2vw,1.5rem) clamp(1rem,3vw,2rem);
  background:rgba(11,11,18,.9);
  opacity:0;transition:opacity .22s var(--ease)
}
.dg-lb.is-open{opacity:1}
.dg-lb[hidden]{display:none}
.dg-lb-stage{
  display:flex;align-items:center;justify-content:center;
  gap:clamp(.35rem,1.6vw,1.2rem);width:100%;max-width:1180px
}
.dg-lb-fig{
  margin:0;min-width:0;flex:0 1 auto;
  display:flex;flex-direction:column;align-items:center;gap:.9rem
}
.dg-lb-fig img{
  max-width:100%;max-height:68vh;width:auto;height:auto;object-fit:contain;
  border-radius:var(--r);background:#fff;box-shadow:0 30px 80px rgba(0,0,0,.5)
}
.dg-lb-cap{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:.35rem 1.1rem;color:#fff}
.dg-lb-cap b{font-size:1rem;font-weight:700}
.dg-lb-cap .count{font-size:.82rem;color:rgba(255,255,255,.62)}
.dg-lb-cta{margin-top:.15rem}
.dg-lb .btn.dg-lb-cta{background:var(--blue);color:#fff}
.dg-lb .btn.dg-lb-cta:hover{background:var(--blue-deep);color:#fff}

.dg-lb button{
  flex:0 0 auto;display:grid;place-items:center;cursor:pointer;
  width:clamp(40px,6vw,52px);height:clamp(40px,6vw,52px);
  background:rgba(255,255,255,.2);color:#fff;
  border:1px solid rgba(255,255,255,.42);border-radius:50%;
  font-size:1.5rem;line-height:1;padding:0 0 .12em;
  transition:background .18s var(--ease),border-color .18s var(--ease)
}
.dg-lb button:hover{background:rgba(255,255,255,.3);border-color:rgba(255,255,255,.5)}
.dg-lb-x{
  position:absolute;top:clamp(.9rem,2.4vw,1.6rem);right:clamp(.9rem,2.4vw,1.6rem);
  font-size:1.7rem;padding-bottom:.16em
}
.admin-bar .dg-lb-x{top:calc(32px + clamp(.9rem,2.4vw,1.6rem))}
@media screen and (max-width:782px){
  .admin-bar .dg-lb-x{top:calc(46px + clamp(.9rem,2.4vw,1.6rem))}
}
.dg-lb :focus-visible{outline:3px solid #8CE8C4;outline-offset:3px}
@media (max-width:620px){
  .dg-lb-fig img{max-height:62vh}
  .dg-lb-cap b{font-size:.92rem}
}
body.dg-lb-open{overflow:hidden}
@media (prefers-reduced-motion:reduce){.dg-lb{transition:none}}


/* ---- phone and tablet: the arc belongs to the screen ----
   Five cards across a phone. digibro-hero.js clones the set, slides the
   track right to left forever and recomputes each card's tilt and rise
   from its distance to the centre line, so the middle slot is always the
   peak of the curve and the images flow through it. The script writes
   transforms inline every frame, so the CSS transform, its transition and
   the idle float animation all have to get out of the way in .is-flow. */
@media (max-width:1024px){
  .fan{--cw:clamp(104px,31vw,158px);--ov:clamp(28px,8.5vw,44px);
    margin-inline:calc(-1 * clamp(1.1rem,4vw,3rem));overflow:hidden;
    padding-bottom:clamp(3rem,9vw,4.5rem);
    -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
    mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
  .fan-track{justify-content:flex-start;width:max-content;will-change:transform}
  .fan-cap{opacity:1;transform:none;font-size:.62rem;padding:.45rem .4rem}
  .fan-card::after{opacity:1}
  .fan.is-flow .fan-card{animation:none;transition:opacity .7s var(--ease),box-shadow .3s var(--ease)}
  .fan.is-flow.fan-pre .fan-card{transform:none}
  .fan.is-flow .fan-card:hover,.fan.is-flow .fan-card:focus-visible{transform:none}
}
/* reduced motion: no flow, no drift - a plain arc the visitor can swipe */
@media (max-width:1024px) and (prefers-reduced-motion:reduce){
  .fan{overflow-x:auto;overflow-y:hidden;scrollbar-width:none;overscroll-behavior-x:contain}
  .fan::-webkit-scrollbar{display:none}
  .fan-track{padding-inline:clamp(1.1rem,4vw,3rem)}
}

/* ============================================================
   Rotating capability line (2026-09-12)
   Replaces the single .fan-sub sentence under the H1.
   Markup: .fan-sub.fan-rota > .rota-lead + .rota (.rota-name/.rota-sub)
           + .rota-src, visually hidden, holding every item - that is what a
           screen reader reads, so the animated slot carries aria-hidden.
   Driven by the "hero capability rota" IIFE in digibro-hero.js.
   ============================================================ */
.digibro-page .fan-sub.fan-rota{
  display:flex;flex-direction:column;align-items:center;gap:.35rem;max-width:56ch;
}
.fan-rota .rota-lead{
  font-size:.76rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--grey);
}
.fan-rota .rota{display:block;width:100%}
.fan-rota .rota-name{
  display:block;font-weight:700;letter-spacing:-.026em;color:var(--ink);
  font-size:clamp(1.16rem,1rem + .8vw,1.62rem);line-height:1.2;
}
.fan-rota .rota-sub{
  display:block;margin-top:.2rem;min-height:1.4em;line-height:1.4;
  font-size:clamp(.86rem,.84rem + .15vw,.95rem);color:var(--grey);
}
/* the swap: the pair fades and lifts out, new text is written, then it settles */
.fan-rota .rota-name,.fan-rota .rota-sub{
  opacity:1;transform:none;
  transition:opacity .26s var(--ease),transform .26s var(--ease);
}
.fan-rota .rota.is-out .rota-name,
.fan-rota .rota.is-out .rota-sub{opacity:0;transform:translateY(-6px)}
/* sub-lines wrap to two lines on a phone - reserve the space so nothing jumps */
@media (max-width:700px){.fan-rota .rota-sub{min-height:2.8em}}
/* reduced motion: the rota still cycles, but the text only swaps - no fade,
   no travel (digibro-hero.js also slows the interval down) */
@media (prefers-reduced-motion:reduce){
  .fan-rota .rota-name,.fan-rota .rota-sub{transition:none}
  .fan-rota .rota.is-out .rota-name,
  .fan-rota .rota.is-out .rota-sub{opacity:1;transform:none}
}
.fan-rota .rota-src{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;
  overflow:hidden;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);
}
