/* ============================================================
   Vishal K. — Portfolio · MOBILE
   ------------------------------------------------------------
   Built 1:1 from the Figma frames — a 390 x 5633 artboard, now 5555 after
   the About copy was shortened (see the running order below). The hero
   and Brand Identities / Campaigns blocks come from "Hero Sections.svg"
   (390x938) and "Section 2.svg" (390x835); the rest is still the
   original "iPhone 13 & 14 - 1.svg" cut, shifted down 173px.

   This sheet does NOT reflow the desktop 1440 artboard. It
   rebuilds the phone frame as its own artboard: every box below
   is in the SVG's own design px, and the whole page is scaled by
   --km = clientWidth / 390 (set in the inline <head> script next
   to --k). Because the frame is one continuous coordinate space,
   every section is absolutely positioned at its design y rather
   than left in flow — which is also why s7 and s8 can appear in
   the frame's order (compositing before logofolio) without
   touching the desktop DOM order.

   Type was recovered from the outlines, not guessed: each text
   layer's glyph subpaths were clustered into baselines, and size
   / letter-spacing solved against a painted-pixel ink scan. All
   58 layers land on round px sizes within 0.74px of the drawn
   ink width and 0.23px of its height.

   Loaded AFTER style.css. Breakpoint 768px — tablets keep the
   desktop artboard, which reads fine at --k >= 0.53.
   ============================================================ */

@media (max-width: 768px){

/* ---------- page frame ----------
   Running order of the phone artboard, 2026-09-08. Every top below is the
   sum of the heights above it, and the heights themselves never changed:

     hero    0     938
     s3    938 +  365  Campaigns
     s2   1303 +  479  Brand Identities
     s4   1782 +  494  Selected Social Work
     s5   2276 +  820  Visual Exploration - posters
     s8   3096 +  366  Image compositing
     s6   3462 +  542  Thumbnails and reels
     s9   4004 +  394  Print & Collateral
     s7   4398 +  366  The Logofolio
     s10  4764 +  891  About                     = 5655

   s10 lost 78 when the bio was rewritten (156 -> 78 design px); the whole
   Experience / expertise / colophon column moved up by exactly that, so every
   gap Vishal had is preserved and only the vacated space is gone.

   Re-solve the whole column if a section is reordered or resized again. */
/* `overflow-x:hidden` computes the OTHER axis to `auto`, so the old
   `html,body{overflow-x:hidden}` turned BOTH the root and the body into real
   scroll containers. Blink collapses that back to one scroller; WebKit does
   not — on iOS the viewport scrolls the root, the root still holds a second
   scrollport of its own, and the page runs about a screen past its last line
   into black. `clip` clips on one axis without creating a scroller at all, so
   the marquee rows are still contained and the document ends where the
   artboard ends. */
@supports not (overflow:clip){ html,body{ overflow-x:hidden } }
@supports (overflow:clip){
  html{ overflow-x:clip }     /* propagates to the viewport; y stays visible */
  body{ overflow:visible }    /* undo style.css's overflow-x:hidden */
}
/* and no rubber-band past the end, so a flick at the bottom cannot expose
   black below the artboard either */
html{ overscroll-behavior-y:none }
body{
  position:relative;
  height:calc(5655px * var(--km));
  background:var(--c-bg);
}
.curtain{ display:none }

/* Desktop-only / mobile-only copy. The frame rewords several
   blocks (hero body, the Péndulo column, the s5 CTA), so both
   strings live in the markup and the breakpoint picks one. */
.dsk{ display:none }
.mob{ display:inline }
/* the frame sets the hero tagline as ONE tracked-out line */
.mob-br{ display:none }

/* Every artboard root: 390 design px scaled into the viewport. */
.stage,.s2__art,.s3__art,.s4__art,.s5__art,.s6__art,
.s7__art,.s8__art,.s9__art,.s10__art{
  position:absolute;
  left:0 !important; top:0 !important; margin:0 !important;
  width:390px !important;
  transform-origin:0 0;
  transform:scale(var(--km));
}
.s2,.s3,.s4,.s5,.s6,.s7,.s8,.s9,.s10{
  position:absolute; left:0; width:100%;
  margin:0; padding:0;
  background:none;
  /* CLIP, not visible. Each section's height IS the frame's height and every
     child was checked to fit inside it, so nothing is cut — but a section
     that does not clip lets any stray descendant add real scroll height to
     the document, which is how the page grew a few hundred px of black
     below the last link. The artboard height is the page height, full stop. */
  overflow:hidden;
}
.s2__sticky,.s4__sticky{ position:static; height:auto; overflow:visible }
.s2__inner,.s4__stage{ position:static }

/* The pinned cross-fades are skipped on mobile, so the layer
   hints they need are pure cost on the device with the least
   memory to spare. */
.s2__text,.s2__card,.s2__card img,.s2 .line > span,
.s2__frame img,.s2__frame video,
.s4__slide,.s4__media,.s4__copy,.s4__panel,
.s6__frame,.s6__frame img,
.s3 .line > span,.s5 .line > span,.s7 .line > span,
.s8 .line > span,.s9 .line > span{ will-change:auto }

/* Desktop line breaks are wrong for a 390 frame; the widths set
   per block below reproduce the breaks the frame actually draws. */
.s2__body br,.s3__body br,.s4__body br,.s4__intro br,.s5__intro br,
.s6__intro br,.s7__intro br,.s8__intro br,.s9__intro br,.s9__body br,
.s10__bio br,.s10__desc br{ display:none }
.hero__body .line,.s2 .line,.s3 .line,.s5 .line,.s6 .line,.s7 .line,.s8 .line,
.s9 .line,
.hero__body .line > span,.s2 .line > span,.s3 .line > span,.s5 .line > span,
.s6 .line > span,.s7 .line > span,.s8 .line > span,.s9 .line > span{
  display:inline; overflow:visible; margin:0; padding:0;
}
.s2__heading .line,.s3__heading .line,.s4__heading .line,.s5__heading .line,
.s6__heading .line,.s7__heading .line,.s8__heading .line,.s9__heading .line{
  display:block;
}

/* A ground under every media box: the page is ~5555 design px of
   mostly lazy imagery, so there is always a frame still filling. */
.s2__frame,.s3__media,.s4__media .s4__frame,.s5__frame,
.s6__block--deck .s6__frame,.s6__tile,.s7__tile,.s8__card,.s9__card{
  background:var(--c-media-bg);
}

/* Shared: every positioned text block. */
.hero__meta p,.hero__headline,.hero__cats li,.hero__wordmark,
.hero__tagline,.hero__body,
.s2__heading,.s2__title,.s2__tagline,.s2__body,
.s3__heading,.s3__title,.s3__subtitle,.s3__body,
.s4__heading,.s4__body,.s5__heading,.s5__intro,
.s6__intro,.s7__heading,.s7__intro,.s8__heading,.s8__intro,
.s9__heading,.s9__body,.s9__intro,
.s10__label,.s10__bio,.s10__job,.s10__date,.s10__desc,.s10__list,
.s10__colophon,.s10__link{
  position:absolute; margin:0; white-space:normal; text-align:left;
}
.hero__headline,.s2__heading,.s3__heading,.s4__heading,.s5__heading,
.s6__heading,.s7__heading,.s8__heading,.s9__heading,
.s2__title,.s3__title,.s10__label{ width:auto !important; white-space:nowrap }
.hero__headline{ width:340px !important; white-space:normal }

/* ============================================================
   NAV — rect x=55 y=27 w=280 h=19 r=9.5, #EAEAEA at 45%.
   Fixed: the frame draws it once at the top, and it stays put.
   ============================================================ */
.navlayer__scale{
  position:fixed; left:0; top:0; z-index:80;
  width:390px; height:0; padding:0;
  transform-origin:0 0;
  transform:scale(var(--km));
}
.nav{
  position:absolute; left:55px; top:27px;
  width:280px; height:19px;
  display:block; padding:0; border:0;
  border-radius:9.5px;
  background:rgba(240,235,227,.5);   /* the ivory, at the frame's 45% */
  -webkit-backdrop-filter:none; backdrop-filter:none;
}
.nav a,.nav a.is-on-dark{ position:absolute; color:var(--c-charcoal); white-space:nowrap }

/* Below the hero the pill is Section 2.svg's, not Hero Sections.svg's: no
   fill, a 0.5px white hairline, white labels — the same pill the four
   case-study phone frames draw. js/main.js's initMobileNavTone toggles
   .is-dark-m at the scroll position where the black plate crosses it.

   The hairline is an inset box-shadow rather than a border: a border would
   shrink the padding box the four absolute labels are placed against and
   drift every ink left by the stroke width. Transitions match the .4s the
   desktop sampler uses. */
.nav{ transition:background .4s cubic-bezier(.4,0,.2,1), box-shadow .4s cubic-bezier(.4,0,.2,1) }
.nav a{ transition:color .4s cubic-bezier(.4,0,.2,1) }
.nav.is-dark-m{
  background:transparent;
  box-shadow:inset 0 0 0 .5px var(--c-ivory);
}
.nav.is-dark-m a,.nav.is-dark-m a.is-on-dark{ color:var(--c-ivory) }

@media (prefers-reduced-motion:reduce){
  .nav,.nav a{ transition:none }
}
.nav a .roll{ display:block; height:auto; overflow:visible; transform:none !important }
.nav a .roll i{ display:none; font-style:normal }
.nav a .roll i:first-child{ display:block }

/* ============================================================
   HERO — frame y 0 → 938  ("Hero Sections.svg")
   White ground to y=651, then the black plate the rest of the
   page sits on. Portrait bleeds both edges (x=-48, 653 wide).
   ============================================================ */
.stage-wrap{
  position:absolute; left:0; top:0;
  width:100%; height:calc(938px * var(--km));
  overflow:hidden;
}
.stage{ height:938px }
.hero{
  position:absolute; left:0; top:0;
  width:390px; height:938px;
  overflow:hidden;
}
.hero::before{
  content:""; position:absolute; left:0; top:0;
  width:390px; height:651px; background:var(--c-ivory);   /* exempt from the theme */
}
.hero__photo{
  position:absolute; left:-48px; top:191px;
  width:653px; height:478px; overflow:hidden;
}
.hero__photo img{
  position:absolute; left:0; top:-0.15px;
  width:653px; height:478.31px;
  max-width:none; object-fit:cover;
}
.hero__band{
  position:absolute; left:-12px; top:605px;
  width:412px; height:74px;
  background:rgba(39,39,39,.1);
}
.hero__plate{
  /* the frame draws 0,651 400x393 — clipped by the hero box */
  position:absolute; left:0; top:651px;
  width:390px; height:287px; background:var(--c-soft-black);   /* exempt */
}
.hero__veil,.hero__cta{ display:none }
/* The seam, re-solved for the 390 frame: the plate ends at 938 and body--b
   wraps to three lines ending at 909.56, so the ramp gets the 28.5 between
   them. See the note in css/style.css for why it stays inside the hero. */
.hero__ramp{ left:0 !important; top:909.5px !important; width:390px !important; height:28.5px !important }

.hero__meta{ position:absolute; left:0; top:0; width:390px; height:0; margin:0 }
.hero__meta p{ left:0 !important; width:370px !important; text-align:right !important; color:var(--c-charcoal) }
.hero__headline{ color:var(--c-charcoal); width:340px }
.hero__cats{
  position:absolute; left:0; top:0; width:390px;
  margin:0; padding:0; list-style:none;
}
.hero__cats li,.hero__cats li:nth-child(n){ color:var(--c-ivory) !important; white-space:nowrap }
.hero__wordmark,.hero__tagline,.hero__body{ color:var(--c-ivory) }
/* overflow:visible, and it matters. The 1440 wordmark is a masked reveal, so
   css/style.css clips it and buys the italic caps back with padding-top:14px
   against a margin-top:-14px. Here the shared block above resets margin to 0
   and this rule kills the padding — the clip box stays, but the space that
   kept the caps inside it does not, so PP Editorial New's ascenders were
   being shaved off the top of VISHAL K. Nothing is masked on the phone
   anyway: the span below is inline, and transforms do not apply to it. */
.hero__wordmark{ width:auto !important; text-align:left !important; white-space:nowrap; text-indent:0 !important; padding:0 !important; overflow:visible !important }
.hero__wordmark > span{ display:inline }
.hero__tagline{ left:24px !important; width:auto !important; text-align:left; white-space:nowrap }
/* the two boxes are genuinely different widths (351 / 353), not one
   shared column. Set ragged-right at Vishal's request — the frame draws
   them justified, but he does not want that on the phone. */
.hero__body--a{ width:351px }
.hero__body--b{ width:353px }
/* The two paragraphs reflow from the SAME markup the 1440 column uses — their
   masked .line rows go inline in the group above, and the newline between each
   row is the word space that joins them. There is no second, phone-only copy
   of the sentence any more. The intro's transform is a no-op here because it
   does not apply to inline boxes; it never ran on the phone anyway, since the
   block it moved was display:none. */

/* ============================================================
   SECTION 2 — Brand Identities ("fire island.svg", a standalone
   390x479 frame drawn on the Fire Island slide; page y 938 → 1417).
   The Campaigns/Social cuts below still come from "Section 2.svg".
   ============================================================ */
.s2{ top:calc(1303px * var(--km)); height:calc(479px * var(--km)) }
.s2__art{ height:479px }
.s2__inner{ position:absolute; left:0; top:0; width:390px; height:479px }

.s2__slide{
  position:absolute; left:0; top:0;
  width:390px; height:479px;
  opacity:1; pointer-events:auto; transform:none;
}
.s2__slide[aria-hidden="true"]{ opacity:1; pointer-events:auto }
.s2__text{ position:absolute; left:0; top:0; width:390px; height:0 }
.s2__card{ position:absolute; left:0; top:0; width:390px; height:0; transform:none }
.s2__card .s2__frame{
  left:25px !important; top:108px !important;
  width:341px !important; height:221px !important;
  border-radius:5px !important; overflow:hidden;
}
.s2__card .s2__frame video,.s2__card .s2__frame img{
  /* !important on left/top too: the Sarson video carries an INLINE
     top:-437.73px (the desktop crop of a 1607px-tall render), and an inline
     style beats a plain rule — so it sat 437px above a 221px overflow:hidden
     frame, invisible, and never intersected to start playing. The CSS poster
     background below made that read as a still that simply never moved. */
  position:absolute; left:0 !important; top:0 !important;
  width:341px !important; height:221px !important;
  max-width:none; object-fit:cover;
}
/* Bloom & Body and Fire Island carry their film inside the grain frame.
   Dropping it here hid both films — and left slide 3, whose ONLY frame is
   this one, as bare #141414 ground. It is shown now, sized into the same
   341x221 box as every other card by the .s2__card .s2__frame rules above.
   The grain texture stays; its 75ms background-position loop does not —
   a full-frame repaint every frame is not worth 5% opacity on a phone. */
.s2__frame--grain::after{ animation:none }
/* Bloom's paragraph used to start a line higher to fit a 311px box. The
   frame's box is wider, so it now sets in four lines from the same top as the
   other two — the old lift collided with its tagline. Four lines from 409.56
   close at 477.56, inside the 479 frame. */
.s2__credits{ display:none }
/* The frame sets the slide title as TWO lines ("Luxury Fire / Island Homes"),
   so the authored .line spans have to break here — .s2 .line{display:inline}
   above would otherwise run them into one 329px line straight through the CTA
   pill. line-height carries !important because slide 3's markup holds an
   INLINE line-height:60px (the desktop pair) that a plain rule cannot beat. */
.s2__title{ left:22px !important; top:343.05px !important }
.s2 .s2__title .line{ display:block }
.s2__tagline{ left:22px !important; top:382.52px !important }
/* 365 is the frame's measured wrap, not its drawn box: the copy breaks after
   "elevated" (354.28) and "presentations" (355.58) and the next word overruns
   at 375.55, so any width in [355.6, 375.5) draws the frame's three lines.
   Middle of that band, so a device that renders a hair wide still breaks the
   same way. */
.s2__body{ left:22.02px !important; top:409.56px !important; width:365px; opacity:.5 }
.s2__cta{
  left:271.25px !important; top:355.25px !important;
  width:94.5px !important; height:25.5px !important;
  border-radius:4.75px;
}

/* ============================================================
   SECTION 3 — Campaigns ("Section 2.svg" y 470 → 835,
   page y 1417 → 1782). Coordinates below are frame y minus 470.
   The 127x258 media box plays pendulo.mp4, the same film desktop uses.
   ============================================================ */
.s3{ top:calc(938px * var(--km)); height:calc(365px * var(--km)) }
.s3__art{ height:365px }
/* `left` deliberately carries NO !important. It used to, and an !important
   declaration beats a normal one whatever the specificity — so this rule
   outranked the paging block's own `.s3__col:nth-of-type(2){ left:390px }`
   further down, which is more specific but not important. A second campaign
   column could therefore never leave x=0 and the two rendered stacked on each
   other. Harmless only while Raffeta is hidden on mobile; this is the fix, not
   the mask. top/width stay important — nothing competes for those. */
.s3__col{ position:absolute; left:0; top:0 !important; width:390px !important; height:365px }
.s3__media{
  position:absolute;
  left:24px !important; top:87px !important;
  width:127px !important; height:258px !important;
  border-radius:5px; overflow:hidden;
  /* the frame exports this slot as flat #D9D9D9 because Figma renders a video
     fill that way — the phone plays the same pendulo.mp4 the desktop does,
     over its own poster so the box is never bare while the film loads. */
  background:var(--c-media-bg) url(../assets/img/s2b/pendulo-poster.jpg) center / cover no-repeat;
  box-shadow:0 4px 12px rgba(0,0,0,.35);
}
.s3__media video{
  position:absolute; left:0; top:0;
  width:100% !important; height:100% !important;
  object-fit:cover; display:block;
}

.s3__col .s3__body--a{ width:200px !important }
.s3__col .s3__body--b{ width:185px !important }
.s3__cta{
  position:absolute;
  left:173.25px !important; top:311.25px !important;
  width:94.5px !important; height:25.5px !important;
  border-radius:4.75px;
}

/* ============================================================
   SECTION 4 — Social Media ("Section 2.svg" y 835 → 1329,
   page y 1782 → 2276). Coordinates below are frame y minus 835.
   One slide of the four (Burger Bae). The re-export inverts the
   old stacking: the copy panel is now ABOVE the 8-up grid, the
   backdrop runs unmirrored at 62%, and the panel carries ONE
   paragraph, not two.
   ============================================================ */
.s4{ top:calc(1782px * var(--km)); height:calc(494px * var(--km)) }
.s4__art{ height:494px }
.s4__deck{ position:absolute; left:0; top:0; width:390px; height:494px }
.s4__slide{
  position:absolute; left:0; top:0; width:390px; height:494px;
  opacity:1; pointer-events:auto; transform:none;
}
.s4__slide[aria-hidden="true"]{ opacity:1; pointer-events:auto }
.s4__media,.s4__copy{ position:absolute; left:0; top:0; width:390px; height:0 }
.s4__intro,.s4__mark{ display:none }
.s4__panel{
  left:20px !important; top:120px !important;
  width:350px !important; height:109px !important;
  border-radius:5px !important;
  background:rgba(0,0,0,.32) !important;
  opacity:1 !important;
  -webkit-backdrop-filter:none !important; backdrop-filter:none !important;
}
/* Figma's background blur does not survive an SVG export — the frame carries
   only a flat 32% black. Vishal bakes the real glass instead, one 350x109 PNG
   per slide (blur + tint together, so it replaces the fill rather than sitting
   over it). One per slide, each baked over that slide's own backdrop. */
.s4__slide--2 .s4__panel{ background:url(../assets/img/m/bb-panel.png)    center / 100% 100% no-repeat !important }
.s4__slide--3 .s4__panel{ background:url(../assets/img/m/bloom-panel.png) center / 100% 100% no-repeat !important }
.s4__slide--4 .s4__panel{ background:url(../assets/img/m/bgs-panel.png)   center / 100% 100% no-repeat !important }
.s4__frame{ position:absolute; overflow:hidden }
.s4__frame img{ position:absolute; max-width:none; object-fit:cover }

/* backdrop — the crop the pattern matrix defines: matrix(0.0019137 0 0
   0.00186999 -1.10089 -0.82903) over a 1586x992 source in a 365x373 box.

   FULL STRENGTH. The frames drew this at 62% and Baddie at 61%, which is an
   artifact of exporting a stacked slider — each frame carries its own card
   AND the previous slide's showing through underneath. Vishal's call: the
   photograph behind each deck is the slide's own, at 100%. */
.s4__slide .s4__media .s4__frame:nth-child(1){
  left:13px !important; top:106px !important;
  width:365px !important; height:373px !important;
  border-radius:5px !important; opacity:1 !important;
  transform:none !important;
}
.s4__slide .s4__media .s4__frame:nth-child(1) img{
  left:-401.82px !important; top:-309.23px !important;
  width:1107.75px !important; height:691.96px !important;
}
.s4__slide--2 .s4__media .s4__frame:nth-child(1) img{ visibility:hidden }
.s4__slide--2 .s4__media .s4__frame:nth-child(1){
  background:var(--c-media-bg) url(../assets/img/m/bb-backdrop.jpg) no-repeat;
  background-size:1107.75px 691.96px;
  background-position:-401.82px -309.23px;
}


/* the 8-up grid, each frame at the slot that holds its own image */
.s4__slide .s4__media .s4__frame:nth-child(2){ left:108.116px !important; top:241px !important; width:85.4454px !important; height:113.927px !important }
.s4__slide .s4__media .s4__frame:nth-child(3){ left:108.116px !important; top:358.49px !important; width:85.4454px !important; height:113.927px !important }
.s4__slide .s4__media .s4__frame:nth-child(4){ left:285.049px !important; top:241px !important; width:85.4454px !important; height:113.927px !important }
.s4__slide .s4__media .s4__frame:nth-child(5){ left:20px !important; top:358.49px !important; width:85.4454px !important; height:113.927px !important }
.s4__slide .s4__media .s4__frame:nth-child(6){ left:196.044px !important; top:241px !important; width:85.7792px !important; height:114.372px !important }
.s4__slide .s4__media .s4__frame:nth-child(7){ left:284.159px !important; top:358.93px !important; width:85.7792px !important; height:114.372px !important }
.s4__slide .s4__media .s4__frame:nth-child(8){ left:20px !important; top:241px !important; width:85.4454px !important; height:113.927px !important }
.s4__slide .s4__media .s4__frame:nth-child(9){ left:196.044px !important; top:358.49px !important; width:85.7792px !important; height:114.372px !important }
.s4__slide .s4__media .s4__frame:nth-child(n+2) img{
  left:0 !important; top:0 !important; width:100% !important; height:100% !important;
}
.s4__slide .s4__media .s4__frame:nth-child(n+10){ display:none }

/* ------------------------------------------------------------
   The other three slides, from "Social media 2/3/4.svg" — each a
   390x391 crop of the card band, so section y = frame y + 97.
   Only the resting slide (Burger Bae) carries the copy panel;
   the rest are card + logo + grid, which is what the frames draw.

   Every frame layers TWO full-card images: its own, and the
   previous slide's showing through at that slide's own opacity —
   an artifact of exporting a stacked slider. Only the top one is
   this slide's, and each card keeps a fixed opacity across every
   frame it appears in (Burger .62, Pizza .9, Bloom 1, Baddie .61),
   which is what confirms the reading.

   Slot -> image was settled by perceptual-hashing each embedded
   tile against assets/img/s4c/, not by eyeballing the grid.
   ------------------------------------------------------------ */
/* Vishal wants the panel and copy on EVERY slide, not just the resting one
   the frames happen to draw. Same box on all of them; each wraps to 5 lines
   at 10/14 in a 181.25 box, so 89px inside a 109px panel. */

/* ---- slide 3 · Bloom & Body Co. ---- */
.s4__slide--3 .s4__media .s4__frame:nth-child(1){
  left:12px !important; top:106px !important;
  width:366px !important; height:373px !important;
}
.s4__slide--3 .s4__media .s4__frame:nth-child(1) img{
  left:-334.32px !important; top:-239px !important;
  width:996.59px !important; height:623.38px !important;
}
/* The frame places only the monogram (a 36x34 box) and the repo has no
   lockup, so this is rebuilt: the SVG's own crisp 270x261 mark composited
   with the "Bloom & Body Co." wordmark lifted off Vishal's artboard. Sized
   so the MARK still lands at 36x34.8 on 77,148 — the frame's own slot — with
   the wordmark hanging below it inside the panel. */
.s4__slide--3 .s4__logo{
  left:59.68px !important; top:148px !important;
  width:69.91px !important; height:53.41px !important;
  background:url(../assets/img/m/bloom-logo.png) center / 100% 100% no-repeat !important;
}
.s4__slide--3 .s4__logo img{ display:none !important }
.s4__slide--3 .s4__media .s4__frame:nth-child(2){ left:108.021px !important; top:357.768px !important; width:85.9356px !important; height:114.102px !important }
.s4__slide--3 .s4__media .s4__frame:nth-child(3){ left:196.043px !important; top:242px !important; width:85.9356px !important; height:114.102px !important }
.s4__slide--3 .s4__media .s4__frame:nth-child(4){ left:20px !important; top:357.768px !important; width:85.9356px !important; height:114.102px !important }
.s4__slide--3 .s4__media .s4__frame:nth-child(5){ left:196.043px !important; top:357.768px !important; width:85.9356px !important; height:114.102px !important }
.s4__slide--3 .s4__media .s4__frame:nth-child(6){ left:284.064px !important; top:242px !important; width:85.9356px !important; height:114.102px !important }
.s4__slide--3 .s4__media .s4__frame:nth-child(7){ left:108.021px !important; top:242px !important; width:85.9356px !important; height:114.102px !important }
.s4__slide--3 .s4__media .s4__frame:nth-child(8){ left:284.064px !important; top:357.768px !important; width:85.9356px !important; height:114.102px !important }
.s4__slide--3 .s4__media .s4__frame:nth-child(9){ left:20px !important; top:242px !important; width:85.9356px !important; height:114.102px !important }

/* ---- slide 4 · Baddie Got Style — three big tiles. The frame strokes two
   of them (an SVG rect strokes from the CENTRE, so its 113x151 at 21,173 is
   a 115x153 border-box at 20,269); the stroke is dropped at Vishal's request,
   and the outer 115x153 is kept, which is also tile 2's box — so the three
   now read as one row rather than one plain and two outlined. ---- */
.s4__slide--4 .s4__media .s4__frame:nth-child(1){
  left:12px !important; top:106px !important;
  width:366px !important; height:373px !important;
}
.s4__slide--4 .s4__media .s4__frame:nth-child(1) img{
  left:-121.4px !important; top:-3.95px !important;
  width:609.05px !important; height:380.71px !important;
}
.s4__slide--4 .s4__logo{ left:52px !important; top:149px !important; width:75px !important; height:45px !important }
.s4__slide--4 .s4__logo img{ left:0 !important; top:-0.46px !important; width:75px !important; height:45.92px !important }
.s4__slide--4 .s4__media .s4__frame:nth-child(2){ left:255px !important; top:269px !important; width:115px !important; height:153px !important; border-radius:5px }
.s4__slide--4 .s4__media .s4__frame:nth-child(3){ left:20px !important; top:269px !important; width:115px !important; height:153px !important; border-radius:5px }
.s4__slide--4 .s4__media .s4__frame:nth-child(4){ left:138px !important; top:269px !important; width:114px !important; height:153px !important; border-radius:5px }
.s4__slide--4 .s4__media .s4__frame:nth-child(n+5){ display:none }

/* the frame's still for the Sarson slot, under the film */
.s2__slide--1 .s2__card .s2__frame{
  background:var(--c-media-bg) url(../assets/img/m/sarson-poster.jpg) center/cover no-repeat;
}
.s4__logo{
  left:54px !important; top:152px !important;
  width:73px !important; height:44px !important;
}
.s4__logo img{ left:0 !important; top:-0.14px !important; width:73px !important; height:44.27px !important }
/* the panel now holds ONE justified paragraph; the frame drops the second */
.s4__body{ left:166px !important; top:139.42px !important; width:181.25px }
/* the second paragraph is dropped. Not an index — .s4__mark is a <p> too, and
   slide 4 carries only one body, so any nth-of-type counting is wrong on one
   slide or another. This hides a body only when another body precedes it. */
.s4__body ~ .s4__body{ display:none }

/* ============================================================
   SECTION 5 — Visual Exploration ("Visual Exploration page- 6.svg"
   y 0 → 820, page y 2276 → 3096). The same export carries section 6.
   ============================================================ */
.s5{ top:calc(2276px * var(--km)); height:calc(820px * var(--km)) }
.s5__art{ height:820px }
.s5__card{ display:none }
.s5__frame{ position:absolute; overflow:hidden; border-radius:5px }
.s5__frame img{ position:absolute; max-width:none; object-fit:cover }
/* The re-export stacks them: one 334 square, then the two 9:16 posters
   side by side underneath, instead of the old three-up strip. */
.s5__frame--c{ left:27px !important; top:171px !important; width:334px !important; height:334px !important }
.s5__frame--c img{ left:0 !important; top:0 !important; width:334px !important; height:334px !important }
.s5__frame--l{ left:27px !important; top:510px !important; width:165px !important; height:294px !important }
.s5__frame--l img{ left:-0.21px !important; top:0 !important; width:165.42px !important; height:294px !important }
.s5__frame--r{ left:196px !important; top:510px !important; width:165px !important; height:294px !important }
.s5__frame--r img{ left:-0.19px !important; top:0 !important; width:165.38px !important; height:294px !important }
.s5__intro{ width:212.5px }
.s5__cta{
  position:absolute;
  left:288.25px !important; top:104.25px !important;
  width:72.5px !important; height:25.5px !important;
  border-radius:4.75px;
}

/* ============================================================
   SECTION 6 — YouTube deck + reels ("Visual Exploration page- 6.svg"
   y 820 → 1362, page y 3096 → 3638). Coordinates are frame y minus 820.
   The fan is gone: both rows are now uniform strips drawn wider than
   the frame on purpose, each with its own copy ABOVE it.
   ============================================================ */
.s6{ top:calc(3462px * var(--km)); height:calc(542px * var(--km)) }
.s6__art{ height:542px }
.s6__heading{ display:none }
/* the deck copy lives INSIDE this block, so the block has to start at the
   top of the section and the TRACK carries the 62px offset — moving the
   block itself put the copy at 82 and then clipped it away. */
.s6__block--deck{ position:absolute; left:0; top:0; width:390px; height:245px; overflow:hidden }
.s6__block--deck .s6__frame{
  position:absolute; overflow:hidden; border-radius:5px !important;
}
.s6__block--deck .s6__frame img{
  position:absolute; left:0 !important; top:0 !important;
  width:100% !important; height:100% !important;
  max-width:none; object-fit:cover;
}
.s6__frame[data-n="1"]{ left:-118px !important; top:15px !important; width:174px !important; height:98px !important }
.s6__frame[data-n="2"]{ left:350.96px !important; top:14.05px !important; width:176.96px !important; height:99.54px !important }
.s6__frame[data-n="3"]{ left:46.35px !important; top:32.63px !important; width:110.79px !important; height:62.32px !important }
.s6__frame[data-n="4"]{ left:229.98px !important; top:32.71px !important; width:110.67px !important; height:62.25px !important }
.s6__frame[data-n="5"]{ left:177.7px !important; top:15.66px !important; width:171.3px !important; height:96.35px !important }
.s6__frame[data-n="6"]{ left:38px !important; top:15.58px !important; width:171.43px !important; height:96.43px !important; filter:drop-shadow(0 2px 6px rgba(0,0,0,.45)) }
.s6__frame[data-n="7"]{ left:104.96px !important; top:14px !important; width:177.05px !important; height:99.59px !important; filter:drop-shadow(0 2px 6px rgba(0,0,0,.45)) }
/* same reasoning as the desktop slot shadows — see css/style.css */
html.inv .s6__frame[data-n="6"],
html.inv .s6__frame[data-n="7"]{ filter:none }

.s6__intro--a{ left:25px !important; width:341px !important; text-align:center }
.s6__intro--b{ left:30px !important; width:343.5px !important; text-align:left }

.s6__block--reels{ position:absolute; left:0; top:0; width:390px; height:0 }
.s6__reels{ position:absolute; left:0; top:322px; width:390px; height:209px; overflow:hidden }
.s6__reels--2{ display:none }
.s6__track{ position:absolute; left:0; top:0; display:flex; gap:0; animation:none; transform:none }
.s6__set{ display:contents }
.s6__tile{ position:absolute; overflow:hidden; border-radius:5px }
.s6__tile img{ position:absolute; max-width:none; object-fit:cover; width:100%; height:100% }

/* ============================================================
   SECTION 8 — Image compositing ("Image page.svg", 390x366,
   page y 3638 → 4004)
   Two before/after cards; the dividers sit where the frame puts
   them (50.3% and 51.2%) and stay draggable.
   ============================================================ */
.s8{ top:calc(3096px * var(--km)); height:calc(366px * var(--km)) }
.s8__art{ height:366px }
.s8__intro{ left:52.6px !important; width:303.8px !important; text-align:center }
.s8__card{
  position:absolute; overflow:hidden; border-radius:5px;
}
.s8__card[data-card="a"]{ left:10px !important; top:133.39px !important; width:181.6px !important; height:222.04px !important }
.s8__card[data-card="b"]{ left:198.09px !important; top:133.39px !important; width:181.3px !important; height:221.75px !important }
.s8__after{
  position:absolute; left:0 !important; top:0 !important;
  width:100% !important; height:100% !important;
  object-fit:cover; max-width:none;
}
.s8__before{
  position:absolute; left:0; top:0; height:100% !important;
  overflow:hidden; box-shadow:none !important;
}
.s8__before img{
  position:absolute; left:0 !important; top:0 !important;
  height:100% !important; max-width:none; object-fit:cover;
}
.s8__card[data-card="a"] .s8__before img{ width:181.6px !important }
.s8__card[data-card="b"] .s8__before img{ width:181.3px !important }
.s8__divider{
  position:absolute; top:0; width:2px; height:100%;
  margin-left:-1px; background:var(--c-ink);
}
.s8__divider::after{
  content:""; position:absolute; left:0.1px;
  width:1.79px; height:11.8px; border-radius:.9px; background:var(--c-ink);
}
.s8__card[data-card="a"] .s8__divider::after{ top:105.16px }
.s8__card[data-card="b"] .s8__divider::after{ top:168.84px }

/* ============================================================
   SECTION 7 — The Logofolio ("logo page.svg", 390x366,
   page y 4004 → 4370)
   Two rows of 101.5 tiles at a 124.36 pitch, offset from each
   other and running off both edges — pushed sideways by finger.
   ============================================================ */
.s7{ top:calc(4398px * var(--km)); height:calc(366px * var(--km)) }
.s7__art{ height:366px }
.s7__intro{ left:59.5px !important; width:271px !important; text-align:center }
.s7__row{ position:absolute; left:0; width:390px; height:101.5px; overflow:hidden }
.s7__row--1{ top:117px }
.s7__row--2{ top:244px }
.s7__track{ position:absolute; top:0; height:101.5px; display:block; animation:none }
.s7__row--1 .s7__track{ left:-41px !important }
.s7__row--2 .s7__track{ left:14px !important }
.s7__tile{
  position:absolute; top:0;
  width:101.5px; height:101.5px;
  border-radius:5px; overflow:hidden;
}
.s7__tile img{ width:101.5px; height:101.5px; max-width:none; object-fit:cover; display:block }

/* ============================================================
   SECTION 9 — Print & Collateral ("Print page.svg", 390x394,
   page y 4370 → 4764). The frame drops the panel, logo and body.
   ============================================================ */
.s9{ top:calc(4004px * var(--km)); height:calc(394px * var(--km)) }
.s9__art{ height:394px }
.s9__card{
  left:11px !important; top:74px !important;
  width:369px !important; height:226px !important;
  border-radius:5px !important; overflow:hidden; position:absolute;
}
.s9__card img{
  position:absolute;
  left:-36px !important; top:-19.39px !important;
  width:424.13px !important; height:265.44px !important;
  max-width:none; object-fit:cover;
}
.s9__panel{
  position:absolute; left:22px; top:103px;
  width:139px; height:167px;
  background:rgba(24,24,24,.15); border-radius:5px;
}
.s9__logo{
  position:absolute;
  left:71px !important; top:124px !important;
  width:48px !important; height:38px !important; overflow:hidden;
}
.s9__logo img{
  position:absolute; left:-0.14px !important; top:0 !important;
  width:48.28px !important; height:38px !important; max-width:none;
}
.s9__heading{ word-spacing:-0.44px }
.s9__heading .amp{ font-size:21.5px }
.s9__body{ width:108px }
.s9__intro{ width:203.5px }
.s9__cta{
  position:absolute;
  left:291.25px !important; top:329.25px !important;
  width:72.5px !important; height:25.5px !important;
  border-radius:4.75px;
}

/* ============================================================
   SECTION 10 — About ("last section.svg", drawn 390x869; 791 since the
   bio was rewritten and the column below it moved up by the 78 it lost.
   page y 4764 → 5655)
   ============================================================ */
.s10{ top:calc(4764px * var(--km)); height:calc(891px * var(--km)) }
.s10__art{ height:891px }
/* the same #1A1A1A at .6 the 1440 artboard lifts this panel off black
   with — it used to be hidden here, so About sat flat on the body's
   #000. inset:0 on .s10__art covers the frame's whole 390x791. */
.s10__bio{ width:314px }
/* the frame separates paragraphs by exactly one blank line */
.s10__bio .para{ display:block; margin-top:13px }
.s10__bio .para:first-child{ margin-top:0 }
.s10__job,.s10__date,.s10__colophon{ white-space:nowrap }
/* the role lines wrap here rather than using the 1440 breaks; 334 is the
   frame's own column, 28 in from each edge */
.s10__desc{ width:334px; color:var(--c-secondary) }
.s10__list{ width:120px }
/* the frame drew one column of six; the eight-item list runs as a single
   column here, list--2 continuing directly under list--1. */
.s10__date{ color:var(--c-secondary); opacity:1 }
.s10__colophon{ color:var(--c-secondary); opacity:.75 }
.s10__link{ white-space:nowrap; display:block }

/* ============================================================
   CTA pills — rect 65.5x17.5 (or 49.5 wide), r=1.75, black on a
   0.5px white stroke, with the label and the 4.9px arrow set to
   the positions the frame draws.
   ============================================================ */
.cta{
  display:block; padding:0; border:0;
  border-radius:1.75px;
  background:var(--c-accent);
  box-shadow:none;
}
.cta .label{ position:absolute; white-space:nowrap; color:var(--c-ivory) }
.cta .arrow{ position:absolute; width:4.9px; height:4.9px }
.cta .arrow path{ stroke-width:2.5 }
/* the two re-exported pills carry a bigger 6.25 arrow; s5/s9 still draw 4.9 */
.s2__cta .arrow,.s3__cta .arrow{ width:6.25px; height:6.25px; left:79.13px; top:10.13px }
.s5__cta .arrow{ width:6.25px; height:6.25px; left:55.13px; top:10.13px }
.s9__cta .arrow{ width:6.25px; height:6.25px; left:55.13px; top:10.13px }
/* the print re-export drops the panel, the brand logo and the body copy —
   the frame is heading, one 369x226 card, the intro and the pill. */
.s9__panel,.s9__logo,.s9__body{ display:none }

/* the contact arrows are <svg class="s10__arrow">, and their viewBox maps
   10 units onto an 8.34-unit path — so a 3.82px drawn mark is a 4.58px box */
.s10__arrow{
  position:absolute;
  width:4.58px !important; height:4.58px !important;
  top:1.39px !important;
}

/* the labels' own left/top are pill-relative and come from the
   solved ink boxes in the generated block below. */


/* ---- type, solved from the outlines (size / ls / baseline) ---- */
.nav a:nth-child(1){ left:33.97px !important; top:6.88px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:6px; line-height:6px }
.nav a:nth-child(2){ left:93.04px !important; top:6.89px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:6px; line-height:6px; letter-spacing:-0.01px }
.nav a:nth-child(3){ left:150.07px !important; top:6.88px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:6px; line-height:6px }
.nav a:nth-child(4){ left:222.98px !important; top:6.91px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:6px; line-height:6px }
/* the role line that used to sit above this one is gone — it repeated the
   wordmark's tagline — so this is the frame's second slot, kept where it was */
.hero__meta p{ top:226.46px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:11px; line-height:11px; letter-spacing:-0.19px }
.hero__headline{ left:27px !important; top:91.75px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:400; font-size:25px; line-height:32px }
.hero__cats li:nth-child(1){ left:32.04px !important; top:629.53px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:400; font-size:7px; line-height:7px }
.hero__cats li:nth-child(2){ left:127.44px !important; top:629.57px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:400; font-size:7px; line-height:7px }
.hero__cats li:nth-child(3){ left:213.26px !important; top:629.56px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:400; font-size:7px; line-height:7px }
.hero__cats li:nth-child(4){ left:314.44px !important; top:629.56px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:400; font-size:7px; line-height:7px }
.hero__wordmark{ left:24px !important; top:696.35px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:400; font-size:35px; line-height:35px; letter-spacing:-0.01px }
.hero__tagline{ top:737.56px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:11px; line-height:11px; letter-spacing:1.68px }
.hero__body--a{ left:23px !important; top:784.56px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:11px; line-height:17px }
.hero__body--b{ left:23px !important; top:858.56px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:11px; line-height:17px }
.s2__heading{ left:85px !important; top:61.35px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:35px; line-height:35px; letter-spacing:0.01px }
.s2__slide .s2__title{ left:22px !important; top:343.05px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:25px; line-height:28px !important }
.s2__slide .s2__tagline{ left:22px !important; top:382.52px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:12px; line-height:12px; letter-spacing:-0.17px }
.s2__slide .s2__body{ left:22.02px !important; top:409.56px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:350; font-size:11px; line-height:17px }
.s2__cta .label{ left:7.75px !important; top:8.02px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:9px; line-height:9px; letter-spacing:-0.02px }
.s3__heading{ left:119px !important; top:27.35px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:35px; line-height:35px }
.s3__col .s3__title{ left:173px !important; top:91.12px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:500; font-size:22px; line-height:22px; letter-spacing:-0.09px }
.s3__col .s3__subtitle{ left:173px !important; top:118.31px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:11px; line-height:11px }
.s3__col .s3__body--a{ left:173px !important; top:148.56px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:11px; line-height:15px }
.s3__col .s3__body--b{ left:173px !important; top:222.56px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:11px; line-height:15px }
.s3__cta .label{ left:7.75px !important; top:8.03px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:9px; line-height:9px; letter-spacing:-0.02px }
/* 310.62 at 35px, centred in the 390 frame the same way the export centred
   the old title: (390 - w) / 2, plus the 0.1 the frame itself carries. */
.s4__heading{ left:39.79px !important; top:47.35px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:35px; line-height:35px; letter-spacing:-0.10px }
.s4__slide .s4__body{ left:166px !important; top:139.42px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:10px !important; line-height:14px !important }
.s5__heading{ left:68px !important; top:33.35px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:35px; line-height:35px }
.s5__intro{ left:24px !important; top:88.57px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:11px; line-height:15px }
.s5__cta .label{ left:7.75px !important; top:8.02px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:9px; line-height:9px; letter-spacing:-0.07px }
.s6__intro--a{ top:20.06px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:11px; line-height:14px }
.s6__intro--b{ top:281.06px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:11px; line-height:14px }
.s8__heading{ left:78px !important; top:28.35px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:35px; line-height:35px; letter-spacing:0.01px }
.s8__intro{ top:82.56px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:11px; line-height:15px }
.s7__heading{ left:107px !important; top:22.35px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:35px; line-height:35px }
.s7__intro{ top:69.56px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:11px; line-height:15px }
.s9__heading{ left:80.17px !important; top:23.35px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:35px; line-height:35px; letter-spacing:-0.61px }
.s9__body{ left:41.05px !important; top:183.5px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:7px; line-height:12px; letter-spacing:-0.01px }
.s9__intro{ left:30px !important; top:319.56px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:11px; line-height:15px }
.s9__cta .label{ left:7.75px !important; top:8.02px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:9px; line-height:9px; letter-spacing:-0.07px }
/* About / Experience / Areas of expertise, on one rhythm.

   Re-solved 2026-09-08, when each role gained a description line. The rhythm
   the previous pass established is kept exactly: 16px between a title and its
   own content, 75px between one block's content and the next title, the About
   label and the trailing gap where the frame drew them.

   Role pitch is 71: title at the base, date at +13.85 (the frame's own
   offset), the description at +29 running two lines of 12. Every description
   wraps to 2 lines at 9px in 334 — measured against the face, not assumed —
   so the four roles stand 253.78 -> 519.78 where they used to end at 442.64.

   Everything below moved by the difference and nothing else changed:
     Experience content 188.86 -> 266
     list               184    -> 207   (a ninth item, 5 in list--1 now)
     s10                791    -> 891, and body 5555 -> 5655 with it.

   The old nth-of-type indexing is GONE. It counted p's across the whole
   About block, so these four new <p>s would have renumbered every job and
   date silently; index.html now carries a class per role and nothing here
   counts anything. */
.s10__label--about{ left:32px !important; top:32.78px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:18px; line-height:18px; letter-spacing:-0.13px }
.s10__label--exp{   left:28px !important; top:219.78px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:18px; line-height:18px }
.s10__label--areas{ left:29px !important; top:594.78px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:18px; line-height:18px; letter-spacing:-0.10px }
.s10__bio{ left:28px !important; top:66.78px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:10px; line-height:13px }

.s10__job--1{  left:28px !important;    top:253.78px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:10px; line-height:10px }
.s10__date--1{ left:28.02px !important; top:267.63px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:9px; line-height:9px }
.s10__desc--1{ left:28px !important;    top:282.78px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:9px; line-height:12px }

.s10__job--2{  left:28px !important;    top:324.78px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:10px; line-height:10px }
.s10__date--2{ left:28.02px !important; top:338.63px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:9px; line-height:9px }
.s10__desc--2{ left:28px !important;    top:353.78px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:9px; line-height:12px }

.s10__job--3{  left:28px !important;    top:395.78px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:10px; line-height:10px }
.s10__date--3{ left:28.02px !important; top:409.63px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:9px; line-height:9px }
.s10__desc--3{ left:28px !important;    top:424.78px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:9px; line-height:12px }

.s10__job--4{  left:28px !important;    top:466.78px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:10px; line-height:10px }
.s10__date--4{ left:28.02px !important; top:480.63px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:9px; line-height:9px }
.s10__desc--4{ left:28px !important;    top:495.78px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:9px; line-height:12px }

.s10__list--1{ left:29px !important; top:628.78px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:10px; line-height:23px }
.s10__list--2{ left:29px !important; top:743.78px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:10px; line-height:23px }
.s10__colophon{ left:29px !important; top:857.28px !important; font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif; font-weight:400; font-size:8px; line-height:8px; letter-spacing:-0.01px }
.s10__link--email{  left:209px !important; top:858.99px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:8px; line-height:8px; letter-spacing:-0.01px }
.s10__link--li{     left:259px !important; top:858.99px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:8px; line-height:8px }
.s10__link--cv{     left:318px !important; top:858.99px !important; font-style:italic; font-family:'PP Editorial New',Georgia,serif; font-weight:200; font-size:8px; line-height:8px }
.s10__link--email .s10__arrow{ left:23.32px !important }
.s10__link--li    .s10__arrow{ left:32.32px !important }
.s10__link--cv    .s10__arrow{ left:27.32px !important }


/* ============================================================
   SWIPE ROWS
   The frame draws one brand, one campaign and one social slide,
   and draws the YouTube deck running off the edges. Those are pushed
   sideways by finger: the drawn offsets are the resting frame. The two
   logofolio rows drift on their own as well — see initMobileLogofolio.
   ============================================================ */
.s2__inner,.s3__art,.s4__deck{ touch-action:pan-y }
.s2__slide,.s4__slide,.s3__col{
  transform:translateX(var(--dx,0px)) !important;
  transition:none;
}
.s2__slide:nth-of-type(1),.s4__slide:nth-of-type(1),.s3__col:nth-of-type(1){ left:0 }
.s2__slide:nth-of-type(2),.s4__slide:nth-of-type(2),.s3__col:nth-of-type(2){ left:390px }
.s2__slide:nth-of-type(3){ left:780px }
/* Paged by MODIFIER, not by nth-of-type: these carry !important and so
   outrank the generic nth-of-type rules above, which means the phone order is
   set here and is independent of the DOM. Both now read
   Burger Bae -> Baddie Got Style -> Bloom & Body Co. */
/* Three pages, not four — Pizza Near Me came out (it told the same story as
   Burger Bae, in the same category). The deck is a paged swipe, so the pages
   below it close up rather than leaving a blank 390 where it stood. */
.s4__slide--2{ left:0 !important }
.s4__slide--4{ left:390px !important }
.s4__slide--3{ left:780px !important }
.s2__art,.s3__art,.s4__art{ overflow:hidden }

/* Campaigns is a two-up on desktop; the phone shows only Péndulo. The Raffeta
   column stays in the markup for the desktop layout and is hidden here, which
   also settles a latent collision: .s3__col carries left:0 !important above, so
   the nth-of-type(2) rule below could never push the second column to 390 and
   the two rendered stacked on each other. initMobileSwipe filters on computed
   display, so the row correctly stops being a paged row at all. */
.s3__col--2{ display:none }

/* Swipe affordance for the paged rows (Brand Identities, Social Media). A
   chevron at the right edge, nudging until the first real drag retires it.
   pointer-events:none — it must never eat the gesture it is advertising. */
.swipe-hint{
  position:absolute; right:10px;
  width:26px; height:26px; margin-top:-13px;
  z-index:5; pointer-events:none;
  opacity:.8;
  filter:drop-shadow(0 1px 2px var(--c-hint-shadow));
  transition:opacity .35s ease;
}
.swipe-hint::before{
  content:''; position:absolute; left:6px; top:7px;
  width:11px; height:11px;
  border-top:2px solid var(--c-ink); border-right:2px solid var(--c-ink);
  transform:rotate(45deg);
}
/* centred on each row's media band, not on the row box — the copy sits low
   in both and an arrow floating over text reads as a stray glyph */
.s2__inner .swipe-hint{ top:218.5px }
.s4__deck  .swipe-hint{ top:356.75px }
.has-swiped .swipe-hint{ opacity:0 }

@media (prefers-reduced-motion: no-preference){
  .swipe-hint{ animation:swipe-nudge 1.9s ease-in-out infinite }
}
@keyframes swipe-nudge{
  0%,55%,100%{ transform:translateX(0) }
  25%        { transform:translateX(5px) }
}

/* The deck is a marquee now, not a finger-only row. It must NOT carry a
   var(--dx) transform of its own: --dx is set on .s6__dtrack and inherits
   down to every frame, so a rule here would translate each card by the
   track's offset a SECOND time and push the row clean off the canvas. */
.s6__block--deck{ touch-action:pan-y }
.s7__row{ touch-action:pan-y }
.s7__track{ transform:translateX(var(--dx,0px)) }

/* Logofolio tiles sit on a 124.36 pitch (101.5 tile + 22.86 gap).
   All three authored sets run on the phone now, so the row can loop
   seamlessly under initMobileLogofolio instead of dead-ending after six.
   A flex track holds the pitch without a left rule per tile — eighteen
   of those, and the eight the old list never reached stacked on slot 1. */
.s7__track{ display:flex; gap:22.86px; width:max-content }
.s7__tile{ position:relative; left:auto; top:auto; flex:0 0 auto }

/* The reel strip. The frame drew three static thumbnails (.s6__mreels, at
   11/136/263 x 117-118 wide); the real desktop row runs here instead so all
   fifteen scroll past under initMobileReels. The drawn positions survive as
   the metrics: a 117.5px tile on a 126 pitch, the track resting at left:11px,
   which is the same 209px band the three thumbnails occupied.

   .s6__mreels itself is GONE from index.html. It was hidden here and nowhere
   else, so on desktop its three images rendered unpositioned at full size down
   the left of the section, painted over the artboard — and they cost 800K on
   every visit at both widths. */
.s6__block--reels{ display:block }
.s6__reels{ touch-action:pan-y }
.s6__track{
  left:11px; height:209px; width:max-content; gap:0;
  transform:translateX(var(--dx,0px));
}
.s6__set{ display:contents }
.s6__set > .s6__tile{ margin-right:8.5px }   /* GAP — part of the 126 pitch */
.s6__tile{
  position:relative; left:auto; top:auto;
  flex:0 0 auto; width:117.5px; height:209px;
}

/* The YouTube deck, rebuilt by buildMobileDeckRow as one uniform row rather
   than the fan the frame draws. 171.4x96.4 is the 16:9 the big drawn cards
   already were, centred in the 130px band; 12px of gap holds the same tile:gap
   ratio as the reel strip below, for a 183.4 pitch. */
.s6__dtrack{
  position:absolute; left:33px; top:62px;
  display:flex; gap:5px; width:max-content;
  transform:translateX(var(--dx,0px));
}
.s6__dtrack .s6__frame{
  position:relative !important; left:auto !important; top:auto !important;
  flex:0 0 auto;
  width:325px !important; height:183px !important;
  filter:none;
}

}
