/* ═══════════════════════════════════════════════════════════════════════════
   rzv.studio — mission.css  (/mission/ only)

   ONE PINNED STAGE (#mission-stage, 9 Sep) and then the page continues.
   Four layers inside the stage, crossed over in order by mission.js's single
   master scrub: (a) the hero, (b) the purpose row — head, 3:4 portrait,
   belief, three equal columns, both text columns centred, (c) the
   personal-projects line, (d) the ring field — a pearl at the centre,
   concentric rings of discs (6 / 12 / 12 / 12, phones 6 / 12 / 14: projects,
   mockup shots and about a third blank, tapering outward) that turn in
   alternate directions and bloom on scroll. Then the project modal (the .jm
   shell from work.css, a round logo head) and, below the pin, the three
   giving-back columns.

   ── Three states, one markup ──────────────────────────────────────────────
   STATIC (no JS): four blocks in document order, projects in a centred row.
   .mp-live (JS laid the rings out): seeds at their measured seats, fully
   visible, the rings spinning — still four blocks in document order.
   .ms-scrub (GSAP + ScrollTrigger + motion on): a 640vh runway, one sticky
   view under the header (top:var(--header-h), 100vh less that band), the four
   layers stacked and scrubbed. Nothing starts hidden.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── hero 1: the mission line IS the hero ────────────────────────────────
   .page-hero / .page-title / .page-lede are work.css's; only the size moves:
   the lede takes .range-line's display clamp (form.css). */
.mi-lede{max-width:24ch;font-size:var(--fs-statement);letter-spacing:-0.04em;line-height:1.06}
/* 9 Sep, his brief: "center the hero content". Same treatment the service and
   contact pages take — the wrap centres its text, the lede centres its box. */
.mi-hero .wrap{text-align:center}
.mi-lede{margin-inline:auto}

/* §THE GLASS — the home hero's half-star, at rest, on THE VIEW rather than the
   hero (9 Sep, his brief: "keep 3d glass object all the way till project
   circles"). lava-hero.js's RZV.lavaStill mounts its canvas here
   (data-lava-still) as soon as this host has a real box, so display:none until
   the stage is scrubbed IS the gate: no .ms-scrub (no JS, no GSAP, motion off,
   reduced motion) and nothing mounts. It never fades — mission.js's master
   morphs it to a sphere on the field's centre instead — and never takes a
   pointer, so everything under it stays live.

   THE STACK (9 Sep, revised): the object is at the BACK (1); the purpose row
   and the field sit over it (2) — he reversed "3 columns section goes behind
   the glass" once he saw it — and the hero and the personal-projects line are
   over both (3), so their words stay the page's own type. */
.ms-glass{display:none}
.ms-scrub .ms-glass{display:block;position:absolute;inset:0;z-index:1;pointer-events:none}   /* 9 Sep: back BEHIND the columns */
.ms-scrub .ms-layer--tri,.ms-scrub .ms-layer--field{z-index:2}
.ms-scrub .ms-layer--hero,.ms-scrub .ms-layer--line{z-index:3}

/* Line masks — form.css's .rw / .rw-i word recipe, restated block-level for the
   smaller copy, which rises a whole LINE at a time (mission.js splitLines). */
.rl{display:block;overflow:hidden;padding-bottom:0.12em;margin-bottom:-0.12em;
  -webkit-clip-path:inset(0);clip-path:inset(0)}
.rl-i{display:block;will-change:transform}

/* ── THE STAGE: one runway, one sticky view, four layers ─────────────────
   9 Sep, his brief: "one pinned sequence: hero full screen - scroll driven
   words anim out > 3 columns animate in > 3 columns anims out > line about
   personal projects anims in > anims out > project circles anim in > hold >
   pin released rest of page continues."

   .ms-run is the runway (640vh); .ms-fv is the ONE sticky view — top at the
   header's band, standing 100vh less that band — so the
   stage holds still for 540vh of scroll while mission.js's single master
   ScrollTrigger crosses the four .ms-layer children over in order. Sticky,
   not ScrollTrigger.pin — on a coarse pointer the page scrolls inside
   #scroller and a pin-spacer there fights the shell (RZV.stShell points GSAP
   at that scroller either way).

   .ms-scrub is added by mission.js only once GSAP + ScrollTrigger + motion
   are confirmed. Without it — no JS, no GSAP, motion off, reduced motion —
   none of these rules apply: the four layers are ordinary blocks in document
   order, nothing is pinned and nothing is hidden. */
.ms-run{position:relative}   /* 9 Sep: no forced ground — the page's own backdrop shows through */
.ms-fv{position:relative}
.ms-layer{position:relative}
/* IN FLOW ONLY (no .ms-scrub): the layers are four blocks that need their own
   breathing room — the hero has .page-hero's, these two had .mp-view's. */
.ms-layer--tri,.ms-layer--line{padding:clamp(48px,7vh,104px) 0}

.ms-scrub .ms-run{height:calc(var(--vh,1vh) * 720)}
/* 9 Sep, Haseeb: "pinned section hasn't properly compensated the header so there's
   an extra small scroll bump." The view stuck at top 0 and stood a full 100vh, so the
   header's band was counted twice — the stage had to travel its own height before the
   pin took, and that travel is the bump. It sticks BELOW the header now and stands
   exactly the space that leaves. */
.ms-scrub .ms-fv{position:sticky;top:var(--header-h,72px);
  height:calc(var(--vh,1vh) * 100 - var(--header-h,72px));overflow:hidden}
.ms-scrub .ms-layer{position:absolute;inset:0;margin:0;
  padding:clamp(20px,3vh,40px) 0 44px;   /* 9 Sep: the view already sits below the header */
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  pointer-events:none;will-change:transform,opacity}
/* the wrap is the only thing that wants the layer's full width — the field
   layer's child is sized in px by mission.js and must not be stretched. */
.ms-scrub .ms-layer > .wrap{width:100%}
.ms-scrub .ms-layer--field{padding:0 var(--gutter);pointer-events:auto}

/* ── hero 2: three equal columns — head · portrait · belief ───────────────
   9 Sep, his brief: "1/3 1/3 1/3; striving for a greater purpose, image of me
   portraits aspect ratio parallax on scroll, my core beliefs". The full-bleed
   silhouette behind the copy is retired with this layout: the same file is now
   a 3:4 portrait in the middle third, sized 118% of its frame and centred, so
   mission.js can slide it ±9% of the frame without ever showing an edge. No
   JS, motion off, reduced motion: it simply sits centred. */
.mp-copy{position:relative;z-index:2}
.mp-tri{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(24px,4vw,64px);align-items:center}
/* 9 Sep, his follow-up: "make both text columns centered". The portrait
   between them is untouched. */
.mp-head{margin:0 auto;max-width:14ch;font-size:var(--fs-xl);text-align:center}
.mp-col{margin:0;color:var(--text);text-align:center}
.mp-portrait{margin:0;min-width:0}
/* Pinned, the row has exactly one viewport to live in: the portrait can never
   be taller than what the stage leaves it (3:4, so width = 0.75 × that).
   width:100% is load-bearing: margin-inline:auto alone makes a grid item
   shrink-to-fit, and a figure whose only child is width:100% collapses. */
.ms-scrub .mp-portrait{width:100%;margin-inline:auto;
  /* 9 Sep: the circle is a third smaller than the space it was taking. */
  max-width:min(67%, calc((var(--vh,1vh) * 100 - var(--header-h,72px) - 150px) * 0.50))}
/* 9 Sep, Haseeb: "make my image cropped in a circle." A square frame with a full
   radius — the parallax still runs inside it, the circle just clips more of it. */
.mp-portrait-frame{position:relative;display:block;width:100%;aspect-ratio:1 / 1;
  overflow:hidden;border-radius:50%;border:1px solid var(--border);
  background:var(--bg-2)}
.mp-portrait-img{position:absolute;inset:0;display:block;
  width:100%;height:100%;object-fit:cover;object-position:50% 32%;will-change:transform}

/* ── the field ────────────────────────────────────────────────────────────
   STATIC (no JS): the label, then the six project circles in a centred row;
   shots stay hidden — a ring needs a measured radius. mission.js adds
   .mp-live once it has laid the seeds out (every seed gets left/top/size in px
   from the field's centre; each ring <ul> turns by its --ra, each disc turns
   back by the same so logos and shots stay upright); .ms-scrub goes on the
   stage once GSAP + ScrollTrigger + motion are confirmed — only then does the
   runway grow and the view stick. Motion off: .mp-live without .ms-scrub —
   the rings, fully bloomed and still, one viewport tall, not sticky. */
.ms-layer--field{display:flex;align-items:center;justify-content:center;
  padding:48px var(--gutter) 64px}
/* Beat (c) — the line — is its own layer now, centred in the stage. */
.mp-intro{position:relative;z-index:2;margin:0 auto;max-width:56ch;text-align:center}
/* 9 Sep, his brief: "personal projects - lose the brow. make the text white."
   The overline is out of the markup and the line takes the text token. */
.mp-lede{margin:0;color:var(--text)}
.mp-field{position:relative;--mp-side:auto;width:100%}
.mp-core{display:none;--pearl-size:22px;--pearl-glow:0.6}
.mp-seeds{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;justify-content:center;gap:16px}
.mp-seed{position:relative;margin:0;padding:0}
.mp-seed--project{width:clamp(96px,12vw,140px);aspect-ratio:1}
.mp-seed--shot,.mp-seed--blank{display:none}

/* Every seed is a circle: the button (projects) or the span (shots) fills
   the seed. Three transforms, three elements, never a fight: the ring turns
   (--ra), the scrub scales the seed, and THIS counter-turns by --ra and takes
   the pointer magnification (--mag, a quickTo'd custom property). */
.mp-tile,.mp-seed-in{position:absolute;inset:0;display:block;width:100%;height:100%;margin:0;
  --mag:1;border-radius:50%;will-change:transform;-webkit-tap-highlight-color:transparent}
.mp-tile{padding:0;border:0;background:none;color:var(--text);cursor:pointer}
.mp-seed[hidden]{display:none}
.mp-tile:focus-visible{outline:2px solid var(--a2);outline-offset:4px;border-radius:50%}
/* .mp-tile-in is the disc that flies into the modal's logo slot. */
.mp-tile-in{position:absolute;inset:0;display:block;overflow:hidden;border-radius:50%;
  background:var(--bg-2);border:1px solid var(--border-hi);
  box-shadow:0 18px 44px -18px rgba(0,0,0,0.7)}
.mp-logo-box{position:absolute;inset:0;display:grid;place-items:center;padding:22%}
.mp-logo{display:block;max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain}
/* Marks that carry their own ground (MFH, The Awaited One) fill the disc. */
.mp-seed[data-fit="cover"] .mp-logo-box{padding:0}
.mp-seed[data-fit="cover"] .mp-logo{width:100%;height:100%;object-fit:cover}
/* Who is Hussain: no logo file survives locally — a typographic disc in the
   brand red, the mono overline spec; type scales with the seed (--mp-d). */
.mp-logo--type{display:grid;place-items:center;width:100%;height:100%;padding:14%;
  background:#E1242C;color:#FFFFFF;text-align:center;
  font-family:var(--mono);font-weight:700;text-transform:uppercase;letter-spacing:0.14em;
  font-size:calc(var(--mp-d,120px) * 0.075);line-height:1.45}
.mp-name{position:absolute;left:50%;top:calc(100% + 10px);transform:translateX(-50%);
  white-space:nowrap;color:var(--text);opacity:0;transition:opacity .35s var(--ease);pointer-events:none}
.mp-tile:hover .mp-name,.mp-tile:focus-visible .mp-name{opacity:1}
.mp-more[hidden]{display:none}
/* 9 Sep, his brief: "use the same bg style properties from Project card
   (backdrop blur etc)". form.css's .offer-door surface, restated round:
   translucent ground, hairline, backdrop blur + saturate. Every non-project
   seed is that one material — a blank and a shot mid-crossfade are the same
   disc, which is what makes the crossfade read as the image arriving rather
   than the circle changing. */
.mp-seed-in{background:rgba(22,22,28,0.52);border:1px solid var(--border);
}   /* 9 Sep, Haseeb: "remove backdrop filter blur from project circles" — 42 blurred discs was the page's heaviest paint */
/* Mockup shots: a circular crop of a gallery image, centred. The image is the
   only thing that fades — mission.js owns its opacity. */
.mp-shot{overflow:hidden}
.mp-shot img{display:block;width:100%;height:100%;object-fit:cover;object-position:50% 50%;
  will-change:opacity}

/* ── live: seeds on the rings ─────────────────────────────────────────── */
.mp-live .ms-layer--field{min-height:calc(var(--vh,1vh) * 100);padding:0 var(--gutter)}
/* …but PINNED the layer is inset:0 of a view that already stands 100vh LESS the
   header, so a 100vh floor makes the layer overflow the view's overflow:hidden
   by the header's band and seats the field that much low (measured 9 Sep: the
   field 36px under the view's centre at 1440, 31px at 390). Under the pin the
   layer is exactly the view. */
.mp-live.ms-scrub .ms-layer--field{min-height:0}
.mp-live .mp-field{width:var(--mp-side);height:var(--mp-side);flex:none}
.mp-live .mp-core{display:block;position:absolute;left:50%;top:50%;margin:-11px 0 0 -11px;z-index:2}
.mp-live .mp-ring{position:absolute;inset:0;display:block;--ra:0deg;
  transform:rotate(var(--ra));will-change:transform}
.mp-live .mp-ring[hidden]{display:none}
.mp-live .mp-seed{position:absolute;left:50%;top:50%;width:var(--mp-d);height:var(--mp-d);
  margin:calc(var(--mp-d) * -0.5) 0 0 calc(var(--mp-d) * -0.5);aspect-ratio:auto;display:block}
.mp-live .mp-seed--project{z-index:3}
.mp-live .mp-tile,.mp-live .mp-seed-in{transform:rotate(calc(var(--ra) * -1)) scale(var(--mag))}

/* ── the project modal: work.css's .jm shell, a logo head ───────────────── */
.pm .jm-head{align-items:center;flex-wrap:nowrap;justify-content:flex-start;gap:20px;
  padding-right:84px}
.pm-logo{position:relative;flex:none;width:72px;height:72px;overflow:hidden;
  border-radius:50%;background:var(--bg-2);border:1px solid var(--border)}
.pm-logo > .mp-tile-in{position:absolute;inset:0;border-radius:50%;border:0;box-shadow:none}
.pm-logo .mp-logo--type{font-size:5.5px;padding:14%}
.pm-ident{min-width:0;display:flex;flex-direction:column;gap:8px}
.pm .jm-h2{white-space:normal;overflow:visible}
.pm-chips{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0}
.pm-chip{color:var(--dim)}
.pm .jm-body .t-body{color:var(--text);font-size:var(--fs-body);line-height:1.6}
.pm .btn-secondary{margin-top:8px;padding:1.2em 1.7em;font-size:var(--fs-btn)}
.pm .btn-secondary span{transition:transform .35s var(--ease)}
.pm .btn-secondary:hover span{transform:translateX(3px)}
/* In flight: the seed's disc, scaled onto the logo slot. */
.pm-ghost{z-index:3;border-radius:50%}

/* ── giving back: three icon columns ────────────────────────────────────── */
.mo-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(28px,4vw,64px);
  margin-top:clamp(36px,4.6vw,64px)}
.mo-col{display:flex;flex-direction:column;gap:clamp(18px,2vw,26px)}
.mo-ico{display:block;height:30px;width:auto;fill:currentColor;color:var(--text)}
.mo-col > p{margin:0;color:var(--text)}

/* ── phones ─────────────────────────────────────────────────────────────── */
@media(max-width:760px){
  .mi-lede{max-width:none;font-size:var(--fs-statement-m)}
  .mp-head{max-width:none;font-size:clamp(2rem,9vw,2.6rem)}
  .mp-tri{grid-template-columns:1fr;gap:clamp(16px,3.6vw,26px)}
  .mp-portrait{width:100%;max-width:228px;margin-inline:auto}
  /* Pinned on a phone the three columns are stacked in one viewport: the
     portrait takes what the two text blocks leave, never a fixed 340px. */
  .ms-scrub .mp-portrait{max-width:min(200px, calc((var(--vh,1vh) * 100 - var(--header-h,62px) - 330px) * 0.50))}
  /* NOT the header's band again — the sticky view already starts below it
     (top:var(--header-h)) and stands exactly what that leaves. Adding it here
     pushed every layer's content down a header inside an already-shortened
     box. Just the phone's own breathing room. */
  .ms-scrub .ms-layer{padding:14px 0 32px}
  .ms-scrub .ms-layer--field{padding:0 12px}
  .mp-live .ms-layer--field{padding:0 12px}
  .pm .jm-head{gap:14px;padding-right:66px}
  .pm-logo{width:56px;height:56px}
  .mo-row{grid-template-columns:1fr;gap:36px}
}

/* ═══ THE PERSONAL-PROJECTS LIST (#mission-list) ═════════════════════════
   9 Sep 2026, Haseeb: "under the project circles i need the proper section
   for listing the personal projects i've worked on. title, meta, short
   description - opens to modal page."

   A LIST, not cards: hairline rules, nothing boxed. Two columns at desk —
   the name and its meta on the left, the description on the right — one
   column stacked on a phone. The arrow is the only affordance and it lives
   at the right edge of the name column, so it sits in the same place on
   every row. The description is clamped to three lines here and whole in
   the modal; with the modal unavailable a row without a case page unclamps
   in place (.is-open, svc-modal.js). The "Read the case study" button that
   travelled with the copy is hidden here — the row itself is that link —
   but stays in the DOM for the circle modal, which shows it. ═════════════ */
.mpl-h{margin:0;color:var(--dim)}
.mpl-list{list-style:none;margin:clamp(22px,3vw,40px) 0 0;padding:0;
  border-bottom:1px solid var(--border)}
.mpl-row{display:grid;grid-template-columns:minmax(0,0.85fr) minmax(0,1.15fr);
  gap:clamp(14px,3.4vw,56px);align-items:start;
  padding:clamp(20px,2.3vw,32px) 0;
  border-top:1px solid var(--border);
  transition:border-color .4s var(--ease)}
/* A row lights its own top rule and the next row's, so a hover reads as one
   band and not as a single brightened edge. */
.mpl-row:hover,.mpl-row:hover + .mpl-row,
.mpl-row:focus-within,.mpl-row:focus-within + .mpl-row{border-top-color:var(--border-hi)}
.mpl-list:hover{border-bottom-color:var(--border-hi)}

.mpl-hit{display:grid;grid-template-columns:minmax(0,1fr);
  gap:9px clamp(12px,1.6vw,22px);align-items:center;
  width:100%;min-height:44px;margin:0;padding:0;border:0;background:none;
  color:inherit;font:inherit;text-align:left;text-decoration:none;cursor:pointer}
.mpl-hit:focus-visible{outline:2px solid var(--a2);outline-offset:4px;border-radius:4px}
.mpl-title{grid-column:1;grid-row:1;margin:0;
  font-size:var(--fs-sub);font-weight:400;letter-spacing:-0.02em;line-height:1.15;
  color:var(--text)}
.mpl-row .mp-meta{grid-column:1;grid-row:2;display:flex;flex-wrap:wrap;
  gap:5px 14px;margin:0}
/* .overline sets its own colour, so the meta is quieted a step at the child:
   title (--text) over description (--muted) over meta (--dim). */
.mpl-row .mp-meta .overline,.mim-meta .overline{color:var(--dim)}

.mpl-row .mp-more{min-width:0}
/* 9 Sep, Haseeb: "kill the pages for the personal projects - no link to anything, just
   what is on the list." The rows lead nowhere, so the description is not a teaser for
   something else: it is shown in full and there is nothing to expand. */
.mpl-desc{margin:0}

/* ═══ THE MODAL, MISSION PROFILE (.wm.svm.mim) ═══════════════════════════
   The home portfolio's full-screen modal (work.css .wm*), dressed for a
   project: the ring seed's own mark, the title, the meta overlines, then
   either the fetched case study or the project's own description.
   The few .svm rules the chassis needs live here too — this page does not
   load services.css. ═════════════════════════════════════════════════════ */
.mim .svm-hero{padding-bottom:0}
.mim .svm-lede:empty{display:none}
.mim .svm-body > .section:first-child{padding-top:0}
.mim-mark{position:relative;width:88px;height:88px;overflow:hidden;
  border-radius:50%;background:var(--bg-2);border:1px solid var(--border)}
.mim-mark[hidden]{display:none}
.mim-mark > .mp-tile-in{position:absolute;inset:0;border-radius:50%;border:0;box-shadow:none}
/* .mp-logo--type sizes itself from --mp-d (the ring's disc). In here the
   disc is 88px, so the type mark is stated outright, as .pm-logo does. */
.mim-mark .mp-logo--type{font-size:6.6px;padding:14%}
.mim .page-head{margin-top:clamp(18px,2.2vw,30px)}
.mim .page-title{font-size:var(--fs-hero)}
.mim-h1{display:inline-block}
.mim-meta{display:flex;flex-wrap:wrap;gap:6px 16px;
  margin:clamp(12px,1.4vw,18px) 0 0;color:var(--dim)}
.mim-meta:empty{display:none}
.mim-solo{padding-top:clamp(26px,3.4vw,48px)}
.mim-solo .t-body{max-width:62ch;font-size:var(--fs-body-lg);color:var(--text)}

@media(max-width:760px){
  .mpl-row{grid-template-columns:1fr;gap:12px;padding:18px 0}
  .mpl-hit{min-height:48px;align-items:center}
  .mpl-title{font-size:1.15rem}
  .mpl-desc{-webkit-line-clamp:2;line-clamp:2}
  .mim .page-title{font-size:var(--fs-hero-m)}
  .mim-mark{width:64px;height:64px}
  .mim-mark .mp-logo--type{font-size:4.8px}
}

/* ═══ THE FLOATING COVER (9 Sep 2026, Haseeb: "make it so it's one continuous thing,
   image slides up down and it tilts on mouse move") — work.css's `.pp-thumbs` recipe,
   the one the /purpose/ project list used: ONE element that lives for the whole list,
   two stacked pictures inside it that crossfade as the cursor moves between rows, and
   a tilt taken from the cursor's own horizontal speed. Fine pointers only. ═══ */
.mpl-list{position:relative}
.mpl-float{position:absolute;top:0;left:0;z-index:5;pointer-events:none;
  width:clamp(150px,14vw,230px);aspect-ratio:4 / 3;opacity:0;will-change:transform}
.mpl-thumb{position:absolute;inset:0;overflow:hidden;
  border-radius:var(--r-card);border:1px solid var(--border-hi);
  background:var(--bg-2);box-shadow:0 22px 48px -26px rgba(0,0,0,0.8)}
.mpl-thumb img{width:100%;height:100%;object-fit:cover}
@media (hover:none),(pointer:coarse){ .mpl-float{display:none} }
html.rzv-no-motion .mpl-float{display:none}

/* 10 Sep, Haseeb: "on mobile - kill the circle image." The three-column row keeps
   its two text columns on a phone; the portrait is the thing that had least room
   and least to say at that width. */
@media (max-width:760px){
  .mp-portrait{display:none}
}
