/* ============================================================
   GRAPHICXO — SERVICES
   Loaded only by services.php, on top of main.css + pages.css.

   The page's one idea is THE FIELD: a particle canvas behind everything
   that takes the colour of whichever pillar you are reading. Every accent
   in here — the slab glow, the chips, the index rows, the path — reads the
   same --svc-accent, which services.js rewrites as you scroll. Nothing on
   this page picks a colour of its own.
   ============================================================ */

/* Registered so the accent *eases* between pillars instead of snapping.
   Same technique story.css uses for --gx-pick on the homepage. */
@property --svc-accent      { syntax:"<color>"; inherits:true; initial-value:#6D28FF }
@property --svc-accent-soft { syntax:"<color>"; inherits:true; initial-value:#8b5cff }

.svc{
  --svc-accent:#6D28FF;
  --svc-accent-soft:#8b5cff;
  --svc-accent-rgb:109,40,255;      /* the same colour as rgba() ingredients */
  position:relative;
  transition:--svc-accent 1.1s var(--ease), --svc-accent-soft 1.1s var(--ease);
}

/* ------------------------------------------------------------
   THE FIELD
   Fixed behind the page. z-index:-1 keeps it under .main's in-flow
   content while still painting above the body's background — a
   positioned z-index:0 child would paint OVER the text.
   ------------------------------------------------------------ */
.svc-field{position:fixed;inset:0;z-index:-1;pointer-events:none;overflow:hidden}
.svc-field canvas{position:absolute;inset:0;width:100%;height:100%;opacity:0;transition:opacity 1.4s var(--ease)}
.svc-field canvas.is-live{opacity:1}

/* The wash is the floor the particles sit on, and the whole effect on its
   own when the canvas never starts (reduced motion, no 2D context). */
.svc-field__wash{
  position:absolute;inset:0;
  background:
    radial-gradient(58vw 58vw at 78% 8%,  rgba(var(--svc-accent-rgb),.16), transparent 62%),
    radial-gradient(46vw 46vw at 8% 62%,  rgba(var(--svc-accent-rgb),.11), transparent 66%),
    radial-gradient(40vw 40vw at 62% 96%, rgba(212,175,55,.07), transparent 64%);
  transition:background 1.1s var(--ease);
}

/* ------------------------------------------------------------
   HEAD
   ------------------------------------------------------------ */
.svc-head{position:relative;padding-top:clamp(9rem,18vh,13rem);padding-bottom:clamp(2.5rem,6vh,4.5rem)}
.svc-head__eyebrow{display:flex;align-items:center;gap:.9rem;margin-bottom:1.4rem}
.svc-head__eyebrow::before{content:"";width:40px;height:1px;background:var(--gold)}

.svc-head__title{
  font-family:var(--serif);
  font-size:clamp(2.8rem,10vw,9rem);
  line-height:.92;letter-spacing:-.03em;
}
.svc-head__title em{color:var(--gold);font-style:italic;font-weight:300}
/* Each line rises out of its own mask. The extra bottom padding keeps
   descenders from being shaved by the overflow. */
.svc-head__mask{display:block;overflow:hidden;padding-bottom:.08em}
.svc-head__mask > span{display:block;transform:translateY(115%);transition:transform 1.05s var(--ease)}
.svc-head__title.is-in .svc-head__mask > span{transform:none}
.svc-head__title.is-in .svc-head__mask:nth-child(2) > span{transition-delay:.1s}

.svc-head__desc{
  margin-top:1.9rem;max-width:56ch;
  color:var(--grey);font-size:clamp(1rem,1.5vw,1.25rem);font-weight:300;
  opacity:0;transform:translateY(24px);
  transition:opacity 1s var(--ease) .2s, transform 1s var(--ease) .2s;
}
.svc-head__desc.is-in{opacity:1;transform:none}

/* The three counts. Numerals in the serif, labels in the sans — the same
   pairing the preloader's read-out uses. */
.svc-stats{
  list-style:none;display:flex;flex-wrap:wrap;gap:clamp(2rem,6vw,5rem);
  margin-top:clamp(2.6rem,6vh,4rem);padding-top:1.8rem;
  border-top:1px solid var(--line);
  opacity:0;transform:translateY(24px);
  transition:opacity 1s var(--ease) .34s, transform 1s var(--ease) .34s;
}
.svc-stats.is-in{opacity:1;transform:none}
.svc-stat{display:flex;flex-direction:column;gap:.35rem}
.svc-stat__n{
  font-family:var(--serif);font-size:clamp(2.2rem,5vw,3.4rem);line-height:1;
  color:var(--gold);font-variant-numeric:tabular-nums;
}
.svc-stat__l{font-size:.64rem;font-weight:600;letter-spacing:.3em;text-transform:uppercase;color:var(--grey-dim)}

/* ------------------------------------------------------------
   THE SLAB STACK
   Each slab sticks a little lower than the one before, so scrolling
   deals them over each other and the pillar being read is always on
   top. The panels are translucent on purpose — the field has to stay
   visible through them, and the overlap reads as depth.
   ------------------------------------------------------------ */
.svc-slabs{padding-bottom:clamp(4rem,10vh,8rem)}
.svc-stack{
  position:relative;display:flex;flex-direction:column;
  /* The gutter lives here rather than on each slab's inner, so the cards
     themselves are inset and their rounded corners actually read. */
  max-width:var(--maxw);margin-inline:auto;padding-inline:var(--pad);
}

.svc-slab{
  --accent:var(--svc-accent);
  --accent-rgb:109,40,255;          /* overridden inline, per pillar */
  position:sticky;
  /* 5.2rem clears the fixed nav; each slab then steps 1.15rem lower so the
     edge of every card underneath stays visible. */
  top:calc(5.2rem + var(--i) * 1.15rem);
  display:flex;align-items:center;
  min-height:clamp(24rem,58vh,34rem);
  margin-bottom:clamp(1.2rem,3vh,2.2rem);
  border:1px solid var(--line);
  border-top-color:rgba(var(--accent-rgb),.5);
  border-radius:18px;
  overflow:hidden;
  background:linear-gradient(168deg,rgba(14,14,16,.93),rgba(7,7,7,.88));
  backdrop-filter:blur(14px);
  -webkit-backdrop-filter:blur(14px);
  box-shadow:0 -1px 0 rgba(var(--accent-rgb),.28), 0 30px 70px -40px rgba(0,0,0,.9);
  transition:border-color .7s var(--ease), box-shadow .7s var(--ease), transform .7s var(--ease);
}
.svc-slab:last-child{margin-bottom:0}

/* The active pillar's own light, lit only while it owns the page. */
.svc-slab__glow{
  position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(42rem 26rem at 6% 108%, rgba(var(--accent-rgb),.30), transparent 68%),
    radial-gradient(28rem 20rem at 96% -12%, rgba(var(--accent-rgb),.18), transparent 70%);
  opacity:.25;transition:opacity 1s var(--ease);
}
.svc-slab.is-live{border-color:rgba(var(--accent-rgb),.34);box-shadow:0 -1px 0 rgba(var(--accent-rgb),.7), 0 30px 80px -38px rgba(var(--accent-rgb),.5)}
.svc-slab.is-live .svc-slab__glow{opacity:1}

.svc-slab__inner{
  position:relative;z-index:2;width:100%;
  display:grid;grid-template-columns:minmax(0,7.5rem) minmax(0,1fr) minmax(0,21rem);
  /* The number and the mark line up with the title, not with the middle of
     a column the copy decides the height of. Only the drawing centres. */
  align-items:start;
  gap:clamp(1.6rem,4vw,3.2rem);
  padding-block:clamp(2.2rem,5vh,3.4rem);
  padding-inline:clamp(1.5rem,3.4vw,3.2rem);
}

.svc-slab__lead{display:flex;flex-direction:column;align-items:flex-start;gap:1.3rem}
.svc-slab__count{font-size:.62rem;font-weight:600;letter-spacing:.24em;text-transform:uppercase;color:var(--grey-dim)}

/* The mark draws itself in. The dash length is deliberately longer than any
   path in gx_icon(), so every stroke is fully hidden at rest and fully drawn
   at the end — the exact length per path doesn't have to be known. */
.svc-slab__icon{width:clamp(34px,3vw,46px);height:auto;color:var(--svc-accent-soft);overflow:visible}
.svc-slab__icon > *{stroke-dasharray:220;stroke-dashoffset:220;transition:stroke-dashoffset 1.4s var(--ease)}
.svc-slab__icon > *:nth-child(2){transition-delay:.14s}
.svc-slab__icon > *:nth-child(3){transition-delay:.28s}
.svc-slab__icon > *:nth-child(4){transition-delay:.42s}
.svc-slab__icon > *:nth-child(5){transition-delay:.56s}
.svc-slab__icon > *:nth-child(6){transition-delay:.7s}
.svc-slab.is-in .svc-slab__icon > *{stroke-dashoffset:0}

.svc-slab__body{min-width:0}
.svc-slab__title{
  font-size:clamp(2rem,5.4vw,4.2rem);line-height:1;letter-spacing:-.025em;
  color:var(--white);
  opacity:0;transform:translateY(30px);
  transition:opacity .95s var(--ease) .08s, transform .95s var(--ease) .08s;
}
.svc-slab.is-in .svc-slab__title{opacity:1;transform:none}

.svc-slab__text{
  margin-top:1.1rem;max-width:48ch;
  color:var(--grey);font-size:clamp(.95rem,1.3vw,1.1rem);font-weight:300;line-height:1.65;
  opacity:0;transform:translateY(22px);
  transition:opacity .95s var(--ease) .2s, transform .95s var(--ease) .2s;
}
.svc-slab.is-in .svc-slab__text{opacity:1;transform:none}

.svc-slab__list{list-style:none;display:flex;flex-wrap:wrap;gap:.6rem;margin-top:clamp(1.6rem,3.4vh,2.4rem)}
.svc-chip{
  font-size:.8rem;color:var(--grey);
  border:1px solid var(--line);border-radius:100px;
  padding:.5rem 1.05rem;
  background:rgba(255,255,255,.02);
  opacity:0;transform:translateY(14px);
  /* --k staggers the chips off their own index, so a pillar's services
     arrive in the order they are listed rather than all at once. */
  transition:opacity .6s var(--ease) calc(.34s + var(--k) * .06s),
             transform .6s var(--ease) calc(.34s + var(--k) * .06s),
             border-color .45s, color .45s, background .45s;
}
.svc-slab.is-in .svc-chip{opacity:1;transform:none}
.svc-slab.is-live .svc-chip{border-color:rgba(var(--accent-rgb),.34);color:var(--white)}
@media (hover:hover){.svc-chip:hover{border-color:rgba(var(--accent-rgb),.8);background:rgba(var(--accent-rgb),.12)}}

/* --- The pillar's visual ---------------------------------------------
   gx_art() draws it in the pillar's own accent; drop a photo into
   assets/images/services/ and service_art() swaps in an <img> with the
   same class, which is why the sizing below is shared between the two. */
.svc-slab__art{position:relative;display:grid;place-items:center;min-width:0;align-self:center}

/* A ring behind the drawing, so the composition sits in something rather
   than floating in the middle of the panel. */
.svc-art__ring{
  position:absolute;width:min(100%,21rem);aspect-ratio:1;border-radius:50%;
  background:radial-gradient(circle,rgba(var(--accent-rgb),.16),transparent 66%);
  border:1px solid rgba(var(--accent-rgb),.12);
  opacity:0;transform:scale(.9);
  transition:opacity 1.2s var(--ease) .1s,transform 1.2s var(--ease) .1s;
}
.svc-slab.is-in .svc-art__ring{opacity:.6;transform:none}
.svc-slab.is-live .svc-art__ring{opacity:1}

.svc-art{
  position:relative;z-index:1;
  width:100%;max-width:20rem;aspect-ratio:1;height:auto;
  color:var(--accent-soft,var(--svc-accent-soft));
  overflow:visible;
  /* The drawings are authored at 400x400 and shown much smaller, so the
     stroke has to thicken as the box shrinks or the whole composition goes
     to grey mush. CSS wins over the presentation attribute on the <svg>. */
  stroke-width:1.5;
  opacity:0;transform:scale(.94);
  transition:opacity 1.1s var(--ease) .22s,transform 1.1s var(--ease) .22s;
}
.svc-slab.is-in .svc-art{opacity:.62;transform:none}
.svc-slab.is-live .svc-art{opacity:1}

/* A photograph gets the same footprint, cropped square and toned into the
   pillar's colour so a supplied image can't break the page's palette. */
.svc-art--photo{
  object-fit:cover;border-radius:14px;
  border:1px solid rgba(var(--accent-rgb),.28);
  filter:saturate(.85) contrast(1.05);
}

/* transform-origin is in viewBox units — the drawings are all 400x400, so
   200px 200px is dead centre for every one of them. */
.art-spin,.art-spin-rev{transform-origin:200px 200px}
.art-spin{animation:artSpin 46s linear infinite}
.art-spin-rev{animation:artSpin 34s linear infinite reverse}
@keyframes artSpin{to{transform:rotate(360deg)}}

/* The lit nodes breathe. Staggered so a node graph reads as traffic rather
   than as one thing blinking. */
.art-pulse{animation:artPulse 3.6s var(--ease) infinite}
.art-pulse:nth-of-type(2n){animation-delay:-1.2s}
.art-pulse:nth-of-type(3n){animation-delay:-2.4s}
@keyframes artPulse{0%,100%{opacity:.28}50%{opacity:1}}

/* ------------------------------------------------------------
   THE INDEX
   ------------------------------------------------------------ */
.svc-index-sec{position:relative}
.svc-index__head{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:clamp(1.6rem,4vw,3rem)}
.svc-index__head .stitle{opacity:0;transform:translateY(26px);transition:opacity 1s var(--ease),transform 1s var(--ease)}
.svc-index__head .stitle.is-in{opacity:1;transform:none}

.svc-filter{display:flex;flex-wrap:wrap;gap:.5rem;max-width:min(100%,44rem)}
.svc-chipbtn{
  --accent:var(--svc-accent);
  position:relative;
  font-size:.76rem;font-weight:500;letter-spacing:.02em;color:var(--grey-dim);
  border:1px solid var(--line);border-radius:100px;
  padding:.55rem 1.1rem;
  transition:color .4s,border-color .4s,background .4s;
}
@media (hover:hover){.svc-chipbtn:hover{color:var(--white);border-color:rgba(247,247,247,.28)}}
.svc-chipbtn.is-on{color:#0a0a0a;border-color:transparent;background:var(--accent)}
.svc-chipbtn:focus-visible{outline:2px solid var(--gold-soft);outline-offset:3px}

.svc-tally{
  margin:2.2rem 0 .4rem;
  font-size:.64rem;font-weight:600;letter-spacing:.3em;text-transform:uppercase;color:var(--grey-dim);
}
.svc-tally span{font-family:var(--serif);letter-spacing:0;font-size:.95rem;color:var(--gold)}

.svc-index{border-top:1px solid var(--line)}
.svc-row{
  --mx:50%;
  --accent:var(--svc-accent);
  --accent-rgb:109,40,255;          /* overridden inline, per pillar */
  position:relative;overflow:hidden;
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  gap:clamp(1rem,3vw,2rem);align-items:baseline;
  padding:clamp(1.05rem,2.3vw,1.6rem) 0;
  border-bottom:1px solid var(--line);
  opacity:0;transform:translateY(16px);
  transition:opacity .7s var(--ease),transform .7s var(--ease),padding-left .45s var(--ease),border-color .45s;
}
.svc-row.is-in{opacity:1;transform:none}
/* The highlight tracks the pointer (services.js writes --mx), so the row
   lights from where the cursor is rather than from a fixed edge. */
.svc-row::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(16rem 7rem at var(--mx) 50%, rgba(var(--accent-rgb),.16), transparent 72%);
  opacity:0;transition:opacity .45s var(--ease);
}
@media (hover:hover){.svc-row:hover::before{opacity:1}}
@media (hover:hover){.svc-row:hover{padding-left:1.2rem;border-color:rgba(var(--accent-rgb),.4)}}
.svc-row > *{position:relative;z-index:1}

.svc-row__name{
  font-family:var(--serif);font-size:clamp(1.2rem,2.6vw,2rem);
  line-height:1.1;letter-spacing:-.01em;color:var(--grey);transition:color .4s;
}
@media (hover:hover){.svc-row:hover .svc-row__name{color:var(--white)}}
.svc-row__pillar{font-size:.74rem;letter-spacing:.06em;color:var(--grey-dim);text-align:right;transition:color .4s}
@media (hover:hover){.svc-row:hover .svc-row__pillar{color:var(--accent)}}
/* A hairline in the row's own pillar colour, drawn across on hover. */
.svc-row__rule{
  position:absolute;left:0;bottom:-1px;height:1px;width:100%;
  background:linear-gradient(90deg,var(--accent),transparent);
  transform:scaleX(0);transform-origin:left;
  transition:transform .6s var(--ease);
}
@media (hover:hover){.svc-row:hover .svc-row__rule{transform:scaleX(1)}}

/* ------------------------------------------------------------
   THE PATH
   One rule drawn across the four steps as the section is read.
   services.js writes --draw 0->1; everything below is derived from it,
   including which nodes have lit — no per-step JS.
   ------------------------------------------------------------ */
.svc-path{--draw:0;position:relative;margin-top:clamp(3rem,7vh,5rem)}
.svc-path__rail{position:absolute;left:0;right:0;top:0;height:1px;background:var(--line)}
.svc-path__rail span{
  display:block;height:100%;
  width:calc(var(--draw) * 100%);
  background:linear-gradient(90deg,var(--purple),var(--purple-soft) 55%,var(--gold));
  box-shadow:0 0 12px rgba(139,92,255,.55),0 0 30px rgba(109,40,255,.3);
}

.svc-path__steps{list-style:none;display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(1.5rem,3vw,2.5rem)}
.svc-step{
  position:relative;padding-top:2.4rem;
  /* Where along the rail this step sits — the midpoint of its column. */
  --at:calc((var(--k) + .5) / 4);
  opacity:0;transform:translateY(22px);
  transition:opacity .8s var(--ease),transform .8s var(--ease);
}
.svc-step.is-in{opacity:1;transform:none}
/* Lights as the drawn line reaches it. The multiplier is the ramp width:
   opacity clamps to 0..1 on its own, so no clamp() is needed. */
.svc-step__node{
  position:absolute;left:0;top:-4.5px;width:9px;height:9px;border-radius:50%;
  background:var(--gold);
  box-shadow:0 0 12px rgba(212,175,55,.8),0 0 26px rgba(212,175,55,.35);
  opacity:calc((var(--draw) - var(--at)) * 16);
}
.svc-step__title{font-size:clamp(1.4rem,2.4vw,2rem);margin:0 0 .8rem}
.svc-step__text{color:var(--grey);font-size:.95rem;font-weight:300;line-height:1.65}

/* ------------------------------------------------------------
   RESPONSIVE
   ------------------------------------------------------------ */
@media (max-width:1180px){
  /* Not enough width for three columns: the visual takes its own row under
     the copy rather than being squeezed beside it. */
  .svc-slab__inner{grid-template-columns:minmax(0,7rem) minmax(0,1fr)}
  .svc-slab__art{grid-column:1 / -1;justify-items:start;margin-top:.6rem}
  .svc-art{max-width:15rem;width:15rem;stroke-width:2}
  .svc-art__ring{max-width:16.2rem;width:16.2rem}
}
@media (max-width:860px){
  /* Five stacked backdrop-filter panels is a real cost on a phone GPU, and
     the effect is barely visible at this size. The gradient stays. */
  .svc-slab{min-height:auto;top:calc(4.4rem + var(--i) * .8rem);backdrop-filter:none;-webkit-backdrop-filter:none;background:linear-gradient(168deg,rgba(14,14,16,.97),rgba(7,7,7,.95))}
  .svc-slab__inner{grid-template-columns:1fr;gap:1.4rem}
  .svc-slab__lead{flex-direction:row;align-items:center;gap:1rem}
  .svc-slab__count{margin-left:auto}
  .svc-art{max-width:11rem;width:11rem;stroke-width:2.7}
  .svc-art__ring{max-width:12rem;width:12rem}
  .svc-path__steps{grid-template-columns:1fr 1fr}
  /* A horizontal rail can't describe a two-column wrap, so it goes and the
     nodes go with it — the numbered steps still read in order. */
  .svc-path__rail,.svc-step__node{display:none}
  .svc-step{padding-top:1.6rem;border-top:1px solid var(--line)}
}
@media (max-width:640px){
  .svc-row{grid-template-columns:minmax(0,1fr)}
  .svc-row__pillar{display:none}
  .svc-path__steps{grid-template-columns:1fr}
  .svc-stats{gap:1.8rem 2.4rem}
}

/* ------------------------------------------------------------
   REDUCED MOTION
   The wash stays (it is a background, not a movement), the canvas never
   starts, and everything that animates in is simply already in.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion:reduce){
  .svc-field canvas{display:none}
  .svc-head__mask > span,
  .svc-head__desc,.svc-stats,
  .svc-slab__title,.svc-slab__text,.svc-chip,
  .svc-index__head .stitle,.svc-row,.svc-step{opacity:1;transform:none;transition:none}
  .svc-slab__icon > *{stroke-dashoffset:0;transition:none}
  .svc-slab__glow{opacity:1}
  .svc-art,.svc-art__ring{opacity:1;transform:none;transition:none}
  .art-spin,.art-spin-rev,.art-pulse{animation:none}
  .svc-step__node{opacity:1}
}
