/* ——— Кейс-страница проекта (scrollytelling) ——— */
:root{
  --nm-red:#E01A17;
  --nm-ink:#142531;
}

/* the case pages render on white, not the global page grey */
body.case-page{ background:#fff; color:var(--nm-ink); }

/* nav carries its background from the top of the page (hero sits under a photo) */
body.case-page [data-nav]{
  background:rgba(233,236,240,0.82);
  -webkit-backdrop-filter:blur(14px);
  backdrop-filter:blur(14px);
  border-bottom-color:rgba(40,62,78,0.1);
}

/* accent brand-red selection inside a case */
body.case-page ::selection{ background:var(--nm-red); color:#fff; }

@keyframes nmPhoneIntro{ from{ opacity:0; transform:translateY(46px) scale(.955); } to{ opacity:1; transform:none; } }
@keyframes nmBgReveal{ from{ opacity:0; transform:scale(1.07); } to{ opacity:1; transform:none; } }
@keyframes nmHeroFade{ from{ opacity:0; } to{ opacity:1; } }

.nm-reveal{
  opacity:0; transform:translateY(30px);
  transition:opacity .85s var(--iw-ease), transform .85s var(--iw-ease);
}
.nm-reveal.nm-in{ opacity:1; transform:none; }

/* ——— sticky scrollytelling track ——— */
#nm-track{ position:relative; height:760vh; background:#fff; }
#nm-stage{ position:sticky; top:0; height:100vh; overflow:hidden; background:#fff; }

/* Anti-FOUC gate. The scroll engine positions #nm-phone and reveals the
   stacked #nm-showtext captions only in its first frame (apply(0), on
   DOMContentLoaded). Until then the raw CSS state paints — a giant phone
   pinned top-left and all four captions overlapping. Locally the script
   runs in the same frame so it's invisible; over a network (Netlify) the
   raw state lingers and flashes. The inline <head> script adds .nm-init
   before first paint; the engine removes it once positioned. No-JS users
   never get .nm-init, so nothing is hidden from them. */
.nm-init #nm-phone,
.nm-init #nm-showtext,
.nm-init #nm-herobg-img,
.nm-init #nm-herotext{ opacity:0 !important; }
#nm-phone,
#nm-showtext{ transition:opacity .45s var(--iw-ease); }

/* Entrance animations play only once the critical images have decoded AND
   web-fonts are ready — the engine adds .nm-lit at that point (the head
   fallback adds it too). Gating them off a readiness class stops the reveal
   from animating a blank/undecoded frame (the "breathing empty stage" + the
   sudden phone pop) and lets the hero title appear already in Manrope, so it
   never re-flows/jumps when the font swaps in. */
#nm-herobg{ position:absolute; inset:0; z-index:1; will-change:transform,opacity; }
#nm-herobg-img{
  width:100%; height:100%; object-fit:cover; object-position:50% 42%; display:block;
}
.nm-lit #nm-herobg-img{ animation:nmBgReveal 1.5s var(--iw-ease) both; }
.nm-herobg-grad{
  position:absolute; inset:0;
  background:linear-gradient(180deg,rgba(20,37,49,.05) 0%,rgba(20,37,49,0) 28%,rgba(20,37,49,.44) 74%,rgba(20,37,49,.72) 100%);
}
#nm-herotext{
  position:absolute; left:clamp(28px,7vw,120px); bottom:clamp(48px,9vh,96px); z-index:2;
  max-width:min(56vw,760px);
}
/* hero title fades in on its own place — no vertical slide (kept the .7s
   delay so it still appears right after the photo settles, not with a pop) */
.nm-lit #nm-herotext{ animation:nmHeroFade 1.1s var(--iw-ease) both; animation-delay:.7s; }
#nm-herotext .nm-eyebrow{
  font-family:'IBM Plex Mono',monospace; font-size:12px; letter-spacing:var(--iw-eyebrow-track); text-transform:uppercase;
  color:#fff; opacity:.82; margin-bottom:16px;
}
#nm-herotext h1{
  margin:0; font-weight:800; font-size:clamp(26px,3.2vw,48px); line-height:1.08; letter-spacing:-.02em;
  color:#fff; text-shadow:0 2px 18px rgba(15,28,38,.4);
}
/* hero wordmark + tagline (replaces the eyebrow + h1 headline on the
   projects whose hero leads with the brand logo — SalamPay, Гольфстрим, Томато) */
.nm-hero-logo{
  display:block; width:clamp(280px,40vw,620px); height:auto;
  filter:drop-shadow(0 2px 18px rgba(15,28,38,.32));
}
.nm-hero-tagline{
  margin:clamp(18px,2.6vh,30px) 0 0;
  font-weight:700; font-size:clamp(22px,2.4vw,34px); line-height:1.16; letter-spacing:-.01em;
  color:#fff; text-shadow:0 2px 18px rgba(15,28,38,.4);
}

/* showcase captions */
#nm-showtext{
  position:absolute; left:clamp(28px,7vw,120px); top:50%; transform:translateY(-50%);
  z-index:3; width:min(42vw,540px); height:0;
}
.nm-txt{ position:absolute; left:0; top:0; transform:translateY(-50%); width:100%; will-change:opacity,transform; }
.nm-txt .nm-idx{
  font-family:'IBM Plex Mono',monospace; font-size:13px; letter-spacing:var(--iw-eyebrow-track); text-transform:uppercase;
  color:var(--nm-red); margin-bottom:20px;
}
.nm-txt h2{
  margin:0 0 20px; font-weight:800; font-size:clamp(30px,3.7vw,54px); line-height:1.0;
  letter-spacing:-.03em; color:var(--nm-ink);
}
.nm-txt p{ margin:0; max-width:30ch; font-size:clamp(15px,1.1vw,18px); line-height:1.55; color:var(--nm-ink); opacity:.7; }

/* soft progressive-blur glow behind the phone (right-hand showcase area) */
#nm-glow{
  position:absolute; top:0; left:0; z-index:2;
  width:70vh; height:70vh;
  background:url("../files/projects/neftmagistral/glow-circle.webp") center center / contain no-repeat;
  opacity:0; will-change:transform,opacity; pointer-events:none;
}

/* the one persistent phone */
#nm-phone{
  position:absolute; top:0; left:0; width:1989px; height:3258px;
  transform-origin:center center; z-index:4; will-change:transform;
}
#nm-phone-inner{
  position:absolute; inset:0;
  /* Shadow is a pre-baked PNG (.nm-shadow, first child) instead of
     filter:drop-shadow(). A live drop-shadow on this ~1989×3258px element —
     which is transform-scaled every scroll frame — forced Safari to
     re-rasterise (and tile) the blur continuously: janky scroll + seamed
     "broken" shadow. The baked image is just composited by the GPU. */
}
/* phone slide-in plays with the reveal, once its screen bitmap has decoded */
.nm-lit #nm-phone-inner{ animation:nmPhoneIntro 1.25s var(--iw-ease) both; animation-delay:.4s; }
/* baked drop-shadow, behind the screens. The PNG is authored with a 320px
   transparent margin on every side (canvas 2629×3898) so the blur fades out
   fully inside the image instead of being cut off at the box edge. It is
   offset back by that margin and sized box+2×320 so the phone silhouette still
   lands 1:1 on the screens above. Overrides the blanket #nm-phone-inner img box. */
#nm-phone-inner .nm-shadow{
  left:-320px; top:-320px;
  width:calc(1989px + 640px); height:auto;
  max-width:none;               /* escape the global img{max-width:100%} clamp */
  pointer-events:none;
}
#nm-phone-inner img{ position:absolute; top:0; left:0; width:1989px; height:3258px; pointer-events:none; }
/* Crossfade screens start hidden. will-change is applied by the scroll engine
   ONLY to the two screens involved in the current crossfade (see
   case-scrollytelling.js) — promoting every screen at once was fine for 4 but
   blew the GPU layer budget at 7 and left stale tiles of the previous screen. */
#nm-phone-inner .nm-screen{ opacity:0; }

/* full-width app-screens showcase — scroll-scrubbed frame sequence.
   Base state is the plain static image: it is what shows without JS,
   below the 900px breakpoint, and until the sequence has loaded. */
#nm-fourshots{ width:100%; background:#1a2a3a; line-height:0; margin-top:clamp(16px,4vh,56px); }
#nm-shots-stage{ position:relative; }
#nm-fourshots picture{ display:block; }
#nm-fourshots img{ display:block; width:100%; height:auto; }
#nm-shots-canvas{ display:none; }

/* scrub mode — sticky track, same pattern as #nm-track above */
#nm-fourshots.nm-shots-live{ height:190vh; }
.nm-shots-live #nm-shots-stage{
  position:sticky; top:0; height:100svh; overflow:hidden; background:#1a2a3a;
}
.nm-shots-live #nm-shots-canvas{ display:block; width:100%; height:100%; }

/* reduced motion — one still frame, no track, no pinning */
.nm-shots-flat #nm-shots-canvas{ display:block; width:100%; height:auto; aspect-ratio:1360/766; }

/* the <img> stays for screen readers once the canvas takes over */
.nm-shots-live #nm-shots-still,
.nm-shots-flat #nm-shots-still{
  position:absolute; width:1px; height:1px; overflow:hidden;
  clip-path:inset(50%); white-space:nowrap;
}

/* ——— results / key metrics ——— */
.nm-results{ background:var(--iw-surface); padding:clamp(56px,9vw,120px) clamp(18px,5vw,72px); }
.nm-results-inner{ max-width:var(--iw-container); margin:0 auto; }
.nm-results-grid{
  display:grid; grid-template-columns:repeat(3,1fr); gap:clamp(16px,1.6vw,24px);
}
.nm-stat{
  display:flex; flex-direction:column; justify-content:space-between;
  min-height:clamp(300px,26vw,380px);
  padding:clamp(28px,3vw,40px);
  background:var(--iw-white);
}
.nm-stat-value{
  font-weight:800; font-size:clamp(56px,7vw,104px); line-height:.9; letter-spacing:-.03em;
  color:var(--nm-ink); display:flex; align-items:flex-start; gap:.06em;
}
.nm-stat-unit{ font-size:.38em; font-weight:700; line-height:1; margin-top:.18em; color:var(--iw-label); }
.nm-stat-value--count{ align-items:center; gap:.24em; }
.nm-stat-value--count .nm-stat-num{ display:inline-flex; align-items:flex-start; gap:.06em; }
.nm-stat-ico{ width:clamp(48px,5.6vw,76px); height:clamp(48px,5.6vw,76px); color:var(--nm-ink); flex:none; }
.nm-stat-value--mark{ color:var(--nm-ink); gap:.32em; align-items:center; }
.nm-stat-value--mark svg{ width:clamp(44px,5.2vw,72px); height:clamp(44px,5.2vw,72px); }
.nm-stat-value--mark svg:nth-of-type(2){ width:clamp(29px,3.47vw,48px); height:clamp(29px,3.47vw,48px); }
.nm-stat-text{ margin-top:auto; }
.nm-stat-title{
  font-weight:700; font-size:clamp(17px,1.5vw,21px); line-height:1.2; letter-spacing:-.015em;
  color:var(--nm-ink); margin-bottom:12px;
}
.nm-stat-desc{ font-size:clamp(14px,1.1vw,16px); line-height:1.5; color:var(--iw-body); }

@media (max-width:860px){
  .nm-results-grid{ grid-template-columns:1fr; }
  .nm-stat{ min-height:0; }
}

/* ——— development stages + stores band ——— */
.nm-process{ background:#fff; padding:clamp(56px,9vw,120px) clamp(18px,5vw,72px); }
.nm-process-inner{ max-width:var(--iw-container); margin:0 auto; }
.nm-process-head .nm-process-eyebrow{
  font-family:'IBM Plex Mono',monospace; font-size:12px; letter-spacing:var(--iw-eyebrow-track); text-transform:uppercase;
  color:var(--nm-red); display:block; margin-bottom:16px;
}
.nm-process-head h2{
  font-weight:800; font-size:clamp(28px,3.7vw,50px); line-height:1.06; letter-spacing:-.025em;
  color:var(--nm-ink);
}

.nm-process-body{
  margin-top:clamp(40px,6vw,72px);
  display:grid; grid-template-columns:minmax(0,1.4fr) minmax(280px,.9fr); gap:clamp(40px,6vw,90px);
  align-items:start;
  border-top:1px solid var(--iw-border); padding-top:clamp(28px,3vw,44px);
}

/* stages list */
.nm-steps{ list-style:none; }
.nm-step{
  display:flex; align-items:center; gap:clamp(16px,2vw,26px);
  padding:clamp(14px,1.6vw,20px) 0; border-bottom:1px solid var(--iw-border);
  transition:padding-left .35s var(--iw-ease), opacity .85s var(--iw-ease), transform .85s var(--iw-ease);
  /* Safari: keep each row on its own compositor layer so the 1px border and
     inner icon rasterize once and slide as one texture (no per-frame shimmer,
     no end-of-transition pixel snap). */
  will-change:transform; -webkit-backface-visibility:hidden; backface-visibility:hidden;
}
/* 3d translate (not translateY) so the layer persists at rest too — avoids the
   composited→flat handoff that Safari renders as an extra jump. */
.nm-step.nm-reveal{ transform:translate3d(0,30px,0); }
.nm-step.nm-reveal.nm-in{ transform:translate3d(0,0,0); }
.nm-step:first-child{ padding-top:0; }
.nm-step-ico{
  flex-shrink:0; width:46px; height:46px; display:grid; place-items:center;
  border:1px solid var(--iw-border); color:var(--nm-ink);
  transition:border-color .35s ease, color .35s ease, background .35s ease;
}
.nm-step-ico svg{ width:23px; height:23px; }
.nm-step-name{
  flex:1; font-weight:600; font-size:clamp(16px,1.4vw,20px); letter-spacing:-.01em; color:var(--nm-ink);
}
.nm-step-num{
  font-family:'IBM Plex Mono',monospace; font-size:13px; letter-spacing:var(--iw-eyebrow-track); color:var(--iw-label);
  transition:color .35s ease;
}
/* Ховер этапов — только для мыши: на тач-устройствах :hover «залипает»
   после тапа и иконка оставалась подсвеченной. */
@media (hover:hover) and (pointer:fine){
  .nm-step:hover{ padding-left:8px; }
  .nm-step:hover .nm-step-ico{ border-color:var(--nm-red); color:var(--nm-red); }
  .nm-step:hover .nm-step-num{ color:var(--nm-red); }
}

/* store buttons */
.nm-stores{ display:flex; flex-direction:column; gap:14px; position:sticky; top:96px; }
.nm-stores-label{
  font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:var(--iw-eyebrow-track); color:var(--iw-label);
  font-weight:500; margin-bottom:6px;
}
.nm-store{
  display:flex; align-items:center; gap:16px;
  padding:16px 22px; background:var(--nm-ink); color:#EDF3F7;
  box-shadow:var(--iw-shadow-soft);
  transition:background .3s ease, transform .3s var(--iw-ease);
}
.nm-store-ico{ flex-shrink:0; width:26px; height:26px; display:grid; place-items:center; color:currentColor; }
.nm-store-ico svg{ width:26px; height:26px; }
.nm-store-txt{ display:flex; flex-direction:column; line-height:1.15; }
.nm-store-small{ font-size:11px; letter-spacing:.02em; opacity:.7; }
.nm-store-big{ font-weight:700; font-size:18px; letter-spacing:-.01em; }
.nm-store-arrow{ margin-left:auto; font-family:'IBM Plex Mono',monospace; opacity:.6; transition:transform .35s var(--iw-ease); }
.nm-store:hover{ background:var(--nm-red); }
.nm-store:hover .nm-store-arrow{ transform:translateX(6px); opacity:1; }
.nm-store:active{ transform:translateY(1px); }

@media (max-width:860px){
  .nm-process-body{ grid-template-columns:1fr; gap:clamp(32px,6vw,48px); }
  .nm-stores{ position:static; }
}

/* ——— CTA card (mirrors projects.css so the shared CTA block renders here too) ——— */
.cta-card{ background:var(--iw-surface-dark); border:1px solid #2C3D49; padding:clamp(30px,3.4vw,48px); display:flex; flex-direction:column; gap:26px; }
.cta-card p{ font-size:clamp(19px,2.2vw,26px); font-weight:700; line-height:1.3; letter-spacing:-0.015em; }

/* ——— next-project pager (shared style with the generic project template) ——— */
.pr-pager{
  border-top:1px solid var(--iw-border);
  background:var(--iw-white);
}
.pr-pager-inner{
  max-width:var(--iw-container); margin:0 auto;
  padding:clamp(28px,4vw,44px) clamp(20px,5vw,64px);
  display:grid; grid-template-columns:1fr auto 1fr; align-items:center; gap:24px;
}
.pr-pager-side{
  display:inline-flex; align-items:center; gap:12px;
  font-family:'IBM Plex Mono',monospace; font-size:12px; letter-spacing:var(--iw-eyebrow-track); text-transform:uppercase;
  color:var(--iw-label);
  transition:color .3s ease;
}
.pr-pager-side.is-next{ justify-self:end; }
.pr-pager-side:hover{ color:var(--iw-accent); }
.pr-pager-center{
  justify-self:center; text-align:center;
  font-weight:800; font-size:clamp(20px,3vw,34px); letter-spacing:-.02em; color:var(--iw-ink);
  transition:color .3s ease;
}
.pr-pager-center:hover{ color:var(--iw-accent); }

@media (max-width:640px){
  .pr-pager-inner{ grid-template-columns:1fr; justify-items:center; gap:14px; text-align:center; }
  .pr-pager-side,
  .pr-pager-side.is-next{ justify-self:center; }
}

@media (max-width:720px){
  #nm-herotext{ max-width:78vw; }
  #nm-showtext{ width:min(78vw,440px); }
  .nm-txt p{ max-width:26ch; }
}

@media (prefers-reduced-motion: reduce){
  #nm-phone-inner,#nm-herobg-img,#nm-herotext{ animation:none !important; }
  .nm-reveal{ transition:none; opacity:1; transform:none; }
}

/* ═══════════ MOBILE (≤880px) ═══════════
   The pinned scrollytelling is replaced by a simple stacked flow:
   a plain hero (photo + title, no phone) followed by one
   "phone-on-a-glow + caption" card per app screen.
   The scrollytelling JS is gated off at this width (see
   case-scrollytelling.js), so nothing writes inline transforms here. */
#nm-mobile{ display:none; }

@media (max-width:880px){
  /* collapse the 760vh pinned track back into normal document flow */
  #nm-track{ height:auto; }
  #nm-stage{ position:static; height:auto; overflow:visible; }

  /* hero becomes a normal block: just photo + gradient + title */
  #nm-herobg{ position:relative; height:min(76vh,560px); }
  #nm-herotext{ max-width:none; right:clamp(28px,7vw,120px); }
  #nm-herotext h1{ font-size:clamp(24px,6.4vw,34px); }

  /* everything that belonged to the animation is hidden on mobile */
  #nm-phone,#nm-showtext,#nm-glow{ display:none !important; }

  /* the stacked mobile showcase */
  #nm-mobile{
    display:block;
    padding:clamp(40px,10vw,72px) clamp(20px,6vw,40px) clamp(8px,3vw,24px);
    /* .nmm-glow blooms to 120% of the stage and its soft (transparent-edged)
       halo bled ~8px past the viewport, causing a phantom horizontal scroll.
       Clip the horizontal bleed at the section edge; the visible bloom is kept. */
    overflow-x:clip;
  }
  .nmm-card{ max-width:520px; margin:0 auto; }
  .nmm-card + .nmm-card{ margin-top:clamp(56px,14vw,96px); }

  .nmm-stage{
    position:relative; display:grid; place-items:center;
    /* top padding keeps the block-to-block gap; bottom padding is reduced
       1.5× so the caption sits closer to its own phone */
    padding:clamp(20px,7vw,40px) 0 clamp(13px,4.7vw,27px);
  }
  /* soft brand glow "подложка" blooming behind each phone */
  .nmm-glow{
    position:absolute; z-index:0;
    width:min(120%,500px); aspect-ratio:1;
    background:url("../files/projects/neftmagistral/glow-circle.webp") center/contain no-repeat;
    pointer-events:none;
  }
  .nmm-phone{
    position:relative; z-index:1;
    width:min(77%,340px); height:auto; display:block;
    filter:drop-shadow(0 22px 40px rgba(20,37,49,.18));
  }

  .nmm-cap{ margin-top:clamp(12px,3.3vw,19px); }
  .nmm-cap h2{
    margin:0 0 12px; font-weight:800; font-size:clamp(28px,8vw,40px);
    line-height:1.02; letter-spacing:-.03em; color:var(--nm-ink);
  }
  .nmm-cap p{
    margin:0; max-width:36ch;
    font-size:clamp(15px,4.1vw,17px); line-height:1.55; color:var(--nm-ink); opacity:.7;
  }
}
