/* ═══════════════════════════════════════════════════════════════════════════
   rzv.studio — services.css  (#services only)

   Loads after work.css, before glass.css. Declares NO tokens and invents NO
   colours: everything below reads base.css's :root, so the section is correct
   in both phases with nothing extra to maintain.

   PREFIX `svc-`, NOT `sv-`. work.css owns `sv-` for the /services/ SUBPAGE
   (.sv-pillar, .sv-head, .sv-name, .sv-body, .sv-desc, .sv-subs, .sv-close,
   .sv-step*, …) and BOTH sheets load on index.html — work.css first, so this
   file only won where it happened to declare the same property. It did not:
   .sv-name inherited the subpage's DISPLAY scale (clamp(1.5rem,3vw,2.5rem)/300
   /-0.04em) instead of the card scale base.css `.t-lg` gives it
   (clamp(1.3rem,2.2vw,1.95rem)/400/-0.03em); .sv-subs inherited
   flex-wrap:wrap, which quietly un-stacked the pills at narrow columns; and
   worst, the modal's 34px round close button inherited .sv-close's
   `flex-direction:column; padding:clamp(60px,8vw,130px) 0 0`. Scoping under
   `#services` was the rejected alternative — it fixes the cascade but leaves
   two unrelated components answering to one name, so the next `.sv-` rule
   written on the subpage is the same bug again. A separate prefix cannot
   collide by construction. Nothing on /services/ was renamed.

   THE SECTION IS COMPOSED BY CSS ALONE. Nothing here starts hidden waiting for
   services.js — that is the house rule. JS adds the pill physics and the
   tile→modal morph; with JS dead the tiles are still six readable cards with
   their sub-services listed.

   Surface reuse: the tile wears base.css `.tilt` for its material (card
   background, cursor sheen, glow ring, and the ≤760px de-blur that keeps it
   off the iOS backdrop-filter × mix-blend-mode trap). .svc-tile below adds
   layout and nothing else. `transform` is deliberately ABSENT from every
   transition list in this file — GSAP owns transform on the pills and on the
   morphing modal (trap 2).
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1 ── THE GRID ───────────────────────────────────────────────────────
   3 → 2 → 1. minmax(0,1fr) rather than 1fr so a long sub-service pill can
   never push a column wider than its share. ── */
.svc-grid{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(14px,1.6vw,24px);
}
/* 7 Sep: three tiles — one row down to 900px, then stacked (a 2+1 step read as a leftover) */
@media(max-width:900px){ .svc-grid{grid-template-columns:1fr} }

/* 8 Sep 2026 — the way into the package builder, under the tiles. Layout only;
   the pill's material is base.css .pearl + work.css §BUTTON SYSTEM. */
.svc-build{display:flex;justify-content:center;margin-top:clamp(28px,3.6vw,52px)}

/* ── 2 ── THE TILE ───────────────────────────────────────────────────────
   A real <button> (keyboard-operable, announced as a control) reset to a
   block-level card: `text-align:left` and `font:inherit` are the two things a
   UA stylesheet gets wrong on a button used as a surface.
   min-height keeps the six boxes on an even baseline whatever the description
   length; .svc-subs takes `margin-top:auto` so the pills sit on the floor of
   every tile regardless (Haseeb: pills at the bottom). ── */
.svc-tile{
  display:flex;flex-direction:column;align-items:flex-start;
  gap:clamp(16px,1.8vw,22px);
  width:100%;min-height:clamp(250px,25vw,310px);
  padding:clamp(22px,2.2vw,30px);
  text-align:left;font:inherit;color:var(--text);
  cursor:pointer;
}
/* 8 Sep: no separate .svc-ico — the tile's name IS the service chip (icon +
   label, chips.css item step), as a <span> inside the <button>. */

.svc-body{display:flex;flex-direction:column;gap:9px}
.svc-name{display:block}
.svc-desc{display:block;max-width:34ch}

/* ── 3 ── THE PILLS ──────────────────────────────────────────────────────
   STACKED, one per line — his word. Each is its own inline-flex box so it has
   a real, independent bounding box for the physics to push around, and so it
   never stretches to the tile's width.

   --r-pill (100px) per the house radius scale. `transform` is NOT in the
   transition list: services.js writes x / y / rotation on these every frame
   while the cursor is over the tile (trap 2). ── */
.svc-subs{
  margin-top:auto;
  display:flex;flex-wrap:wrap;align-items:center;   /* 8 Sep: "the service pills need to stack in line" — a wrapping row, in the tile as in the modal */
  gap:7px;
}
/* 8 Sep, Haseeb: the pills ARE the service chip (chips.css .chip--pill, markup
   from _tools/chips.mjs). 9 Sep they became ANCHORS — every chip in the tile
   is now a real link to the page it names, so the section is navigable with no
   JS at all and svc-modal.js only intercepts. The tile lifts its whole set
   together on hover, as it lifted the old pills; the chip's own static hover
   (chips.css) is overridden here by specificity. Border only: hover never
   touches the icon (chips.css STATES). :focus-within, not :focus-visible —
   the focus now lands on a chip INSIDE the tile, not on the tile itself. */
.svc-tile:hover .chip,.svc-tile:focus-within .chip{border-color:var(--border-hi)}


/* ── 5 ── MOBILE (≤760px) ──────────────────────────────────────────────── */
@media(max-width:760px){
  .svc-tile{min-height:0}
}


/* 8 Sep, Haseeb: "Make the smaller chips inside modal tiles smaller": the
   pills step down from 13px. */
.svc-subs .chip--pill{--chip-s:11px}

/* 8 Sep, Haseeb: "Service title chip when inside modal - no border or padding."
   The tile's name is the borderless form; the PAGE's h1 chip keeps its pill,
   in the modal exactly as on the page — svc-modal.js tweens the ghost's border
   between the two on the way, so neither end has to give up its own look. */
.svc-name .chip{border:0;padding:0;background:none}


/* ═══ 6 ── THE PAGE MODAL (svc-modal.js) ════════════════════════════════
   Built at open and appended to <body>, on work.css's .wm chassis: .wm-bg is
   the plate that Flips out of the tile and back into it, .wm-scroll is the
   scroller, .wm-close / .wm-arrow are the glass circles, .wm-skel the loading
   bars, html.wm-lock the scroll lock. Only the three things that page markup
   (not portfolio markup) needs are new.

   NO glass is mounted in here: svc-modal.js unwraps .glass-run.st-page-run on
   the way in, and the root carries data-glass-skip. The modal's own ground is
   the surface — a refracting solid behind a full-screen panel has nothing to
   refract. ═══ */
.svm .svm-hero{padding-bottom:0}
/* The fetched .page-lede rides up beside the title, where the page puts it. */
.svm .svm-lede:empty{display:none}
/* The body is the rest of <main>. Its first section already carries the
   page's own top padding, so the modal adds none. */
.svm .svm-body > .section:first-child{padding-top:0}
/* The back arrow only exists once there is somewhere in here to go back to;
   svc-modal.js shows it. */
.svm .svm-back{opacity:0}

/* 10 Sep, Haseeb: "why not just extend the modal tile BG as the BG for the modal?
   that way everything stays seamless. maybe go 95% full screenn."

   Two earlier attempts put an aurora behind, then inside, the plate. Both were
   the wrong idea: the plate is what Flips out of the tile, so anything that is
   not the tile's own material shows the join. The plate now wears .tilt exactly
   — var(--card), the same 1px border, the same 20px backdrop blur — and lands
   at 98% instead of edge to edge, so the tile simply becomes a big card.
   svc-modal.js reads --svm-m for the landing inset. The ≤760px de-blur mirrors
   base.css's own rule for .tilt (the iOS backdrop-filter × blend trap). */
.wm.svm{--svm-m:clamp(6px,1vmin,14px);
  --wm-pad:calc(clamp(16px,2vw,28px) + var(--svm-m))}
.svm .wm-bg{background:var(--card);border:1px solid var(--border);
  backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px)}
/* 10 Sep, Haseeb: "service modal backdropfilter didnt apply on ios safari".
   My own doing: I had mirrored base.css's ≤760px de-blur for .tilt onto the
   plate. That rule exists because a GRID of blurring tiles is expensive on a
   phone GPU; the modal is one full-screen layer, and without the blur its 58%
   background left the page legible straight through it. The blur stays on at
   every width now. Where the engine genuinely has no backdrop-filter the plate
   goes opaque instead of transparent. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .svm .wm-bg{background:var(--bg)}
}
.svm .wm-scroll{inset:var(--svm-m);border-radius:var(--r-tile);overflow-x:hidden}
@media(max-width:760px){
  .wm.svm{--svm-m:clamp(4px,0.9vmin,10px)}
}

/* 10 Sep: the same dead air the bio page had. ribbon.css gives any hero carrying
   a ribbon a 64vh floor and centres the copy inside it, so on 1440×900 the hub's
   hero measured 439px of content inside a 576px box — 137px of nothing between
   the lede and the tiles. The hero is sized by its own content now; the ribbon
   band is shorter, which is all it ever was. Sub-service pages carry no ribbon,
   so the rule cannot reach them. */
body[data-page="services"] .page-hero:has(> .ribbon-hero){min-height:calc(var(--vh,1vh) * 46)}
@media (max-width:760px){
  body[data-page="services"] .page-hero:has(> .ribbon-hero){min-height:calc(var(--vh,1vh) * 42)}
}

/* 10 Sep, Haseeb: the closing sentence of the hub lede breaks onto its own line,
   with "an empty line break above it". A block span rather than a second <br>:
   the gap is one tunable number and it scales with the type, so it holds at any
   size the lede is set at. */
.page-lede .lede-gap{display:block;height:0.9em}

/* 10 Sep, Haseeb: "i want to see the ribbon go behind the modal tiles a little
   like on contact page." Same contract as .ct-ribbon (work.css): the section is
   the containing block, the layer is full-bleed inside it and masked away before
   its edges, and the tiles sit above. data-ribbon-copy="0" keeps the hero copy
   out of the raster — there is no copy in this section to refract. */
.svc-band{position:relative}
.svc-band > .section{position:relative;z-index:1}   /* hero copy and tiles above the glass */
.ribbon-hero.svc-ribbon{position:absolute;inset:0;z-index:0;
  top:calc(var(--header-h) * -1);height:auto;
  /* full at the top so it reads behind the hero, gone before the marquee below */
  -webkit-mask-image:linear-gradient(to bottom,#000 0,#000 76%,transparent 100%);
          mask-image:linear-gradient(to bottom,#000 0,#000 76%,transparent 100%)}
