
@font-face {
  font-family: 'Unbounded';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('assets/fonts/unbounded-cyrillic.woff2') format('woff2-variations');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Unbounded';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('assets/fonts/unbounded-latin.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root{
  --ink:#100e10;
  --text:#ffffff;
  --text-dim:#c9c9c9;
  --text-mute:#9b9b9b;
  --text-faint:#8a8a8a;
  --accent:#e46998;
  --accent-a:#f5c7d9;
  --card-fill:rgba(255,255,255,.045);
  --card-fill-hover:rgba(255,255,255,.07);
  --line-soft:rgba(255,255,255,.09);
  --font:'Unbounded','Segoe UI',sans-serif;
  --maxw:1180px;
  --glow-alpha:.3;   /* how strong the pink glow gradient itself is — bump this up/down to taste */
  --glow-opacity:.85; /* how visible each blob is overall, on top of --glow-alpha */
}

*,*::before,*::after{box-sizing:border-box;}
html{scroll-behavior:smooth;overflow-x:clip;}
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto;}
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important;scroll-behavior:auto !important;}
}

body{
  margin:0;background:var(--ink);color:var(--text-dim);
  font-family:var(--font);font-weight:300;font-size:16px;line-height:1.6;
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
}
img{max-width:100%;display:block;}
a{color:inherit;text-decoration:none;}
::selection{background:var(--accent);color:#12080d;}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px;}

h1,h2,h3{font-family:var(--font);font-weight:600;margin:0;text-wrap:balance;color:var(--text);}
p{margin:0;}

/* position:relative + z-index:1 here (not just on .hero-grid/.cta-inner
   individually) guarantees every section's actual content paints above its
   glow blobs — without it, plain (non-.card) text sits at the default
   stacking level and a glow positioned later in that section's markup can
   end up layered visually on top of it instead of behind, since a
   position:absolute glow always beats non-positioned content regardless of
   DOM order. */
.wrap{position:relative;z-index:1;max-width:var(--maxw);margin:0 auto;padding:0 32px;}
@media (max-width:640px){.wrap{padding:0 20px;}}

/* ---- text weight helpers matching source system ---- */
.w-light{font-weight:300;}
.w-reg{font-weight:400;}
.w-med{font-weight:500;}
.w-semi{font-weight:600;}

/* ---- kicker label (matches "ЗАДАЧА"/"ЧТО СДЕЛАНО" style) ---- */
.kicker{
  font-weight:500;font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--accent);display:block;
}
.eyebrow{font-weight:500;font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--accent);}

.bar{width:78px;height:3px;border-radius:2px;background:var(--accent);margin:18px 0 26px;}

/* ---- glow blobs (recreates the soft pink radial art from the deck) ---- */
.glow{position:absolute;border-radius:50%;filter:blur(70px);pointer-events:none;z-index:0;opacity:var(--glow-opacity);}
.glow-pink{
  background:radial-gradient(circle,rgba(228,105,152,var(--glow-alpha)),rgba(228,105,152,0) 70%);
}
.glow-soft{width:720px;height:720px;filter:blur(90px);}
/* the actual slow wander is driven from script.js (driveGlowDrift) via the
   standalone `translate` property, not a CSS @keyframes loop — see the note
   there for why */

/* glow positions — paste at the end of style.css, replacing the previous such block */
[data-glow="hero-1"] { top:-275px !important; left:1380px !important; right:auto !important; bottom:auto !important; transform:none !important; }
[data-glow="hero-2"] { top:292.313px !important; left:135.011px !important; right:auto !important; bottom:auto !important; transform:none !important; }
[data-glow="about"] { top:-380.453px !important; left:-166.04px !important; right:auto !important; bottom:auto !important; transform:none !important; }
[data-glow="services"] { top:-71.8603px !important; left:898.111px !important; right:auto !important; bottom:auto !important; transform:none !important; }
[data-glow="services-2"] { top:803.516px !important; left:926.364px !important; right:auto !important; bottom:auto !important; transform:none !important; }
[data-glow="cases-1"] { top:868.057px !important; left:-18.636px !important; right:auto !important; bottom:auto !important; transform:none !important; }
[data-glow="cases-2"] { top:2314.36px !important; left:454.158px !important; right:auto !important; bottom:auto !important; transform:none !important; }
[data-glow="blog"] { top:-463.366px !important; left:-96.6561px !important; right:auto !important; bottom:auto !important; transform:none !important; }
[data-glow="stack"] { top:106px !important; left:-47px !important; right:auto !important; bottom:auto !important; transform:none !important; }
[data-glow="education"] { top:-238.424px !important; left:1206.33px !important; right:auto !important; bottom:auto !important; transform:none !important; }
[data-glow="terms"] { top:75px !important; left:1170px !important; right:auto !important; bottom:auto !important; transform:none !important; }
[data-glow="cta"] { top:-160.528px !important; left:749.598px !important; right:auto !important; bottom:auto !important; transform:none !important; }

/* ---- card: translucent fill + soft pink gradient border (matches deck shapes) ---- */
.card{
  position:relative;background:var(--card-fill);border-radius:18px;
  transition:background .25s ease;
}
.card::before{
  content:"";position:absolute;inset:0;border-radius:inherit;padding:1.4px;
  background:linear-gradient(135deg,var(--accent-a) 0%,var(--accent) 22%,var(--accent-a) 42%,var(--accent) 64%,var(--accent-a) 84%,var(--accent) 100%);
  opacity:.65;
  -webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
  mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
  pointer-events:none;
}
.card:hover{background:var(--card-fill-hover);}

/* ---- icon badge (outlined circle + small brand icon) ---- */
.icon-badge{
  width:54px;height:54px;border-radius:50%;flex:none;
  background:rgba(255,255,255,.08);border:1px solid rgba(228,105,152,.75);
  display:flex;align-items:center;justify-content:center;
}
.icon-badge img{width:24px;height:24px;object-fit:contain;}

/* ---- pill link/button (matches "Читать на vc.ru" pill, always-on glow) ---- */
.pill-btn{
  display:inline-flex;align-items:center;gap:10px;
  padding:13px 24px;border-radius:999px;
  border:1px solid var(--accent);
  background:rgba(228,105,152,.10);
  color:var(--text);font-weight:500;font-size:14px;
  box-shadow:0 0 26px -4px rgba(228,105,152,.5);
  transition:box-shadow .3s ease,border-color .3s ease,background .3s ease,color .3s ease,transform .3s ease;
}
.pill-btn:hover{
  background:var(--accent);color:#180a10;
  box-shadow:0 10px 34px -6px rgba(228,105,152,.7);
  transform:translateY(-2px);
}
.pill-btn svg{color:var(--accent);transition:transform .25s ease,color .3s ease;flex:none;}
.pill-btn:hover svg{transform:translateX(3px);color:#180a10;}
.pill-btn.sm{padding:9px 18px;font-size:13px;}

/* same growing-underline mechanism as .navlinks a: position:relative + an
   ::after that animates width 0 -> 100% on hover — scoped to the text span
   only (not the whole flex row), so the arrow icon stays un-underlined */
.linklet{display:inline-flex;align-items:center;gap:8px;color:var(--accent);font-weight:500;font-size:13.5px;}
.linklet span{position:relative;padding-bottom:3px;}
.linklet span::after{content:"";position:absolute;left:0;bottom:0;width:0;height:1px;background:var(--accent);transition:width .25s ease;}
.linklet:hover span::after{width:100%;}
.linklet svg{transition:transform .25s ease;}
.linklet:hover svg{transform:translateX(4px);}

/* ---- nav ---- */
#progress{position:fixed;top:0;left:0;height:2px;width:0%;background:var(--accent);z-index:100;transition:width .1s linear;}
nav{
  position:fixed;top:0;left:0;right:0;z-index:90;padding:20px 32px;
  display:flex;align-items:center;justify-content:space-between;
  transition:background .35s ease,border-color .35s ease,padding .35s ease,backdrop-filter .35s ease;
  border-bottom:1px solid transparent;
}
nav.scrolled{
  background:rgba(11,10,11,.52);backdrop-filter:blur(14px) saturate(140%);-webkit-backdrop-filter:blur(14px) saturate(140%);
  border-bottom:1px solid var(--line-soft);padding:14px 32px;
}
.brand{font-weight:600;font-size:14px;letter-spacing:.05em;color:var(--text);white-space:nowrap;}
.navlinks{display:flex;gap:28px;list-style:none;margin:0;padding:0;}
.navlinks a{font-weight:400;font-size:13.5px;color:var(--text-dim);position:relative;padding-bottom:3px;transition:color .2s ease;}
.navlinks a::after{content:"";position:absolute;left:0;bottom:0;width:0;height:1px;background:var(--accent);transition:width .25s ease;}
.navlinks a:hover{color:var(--text);}
.navlinks a:hover::after{width:100%;}
/* mobile nav: drop the brand name and "Написать" pill (the CTA is already
   repeated further down the page — #cta, the hero buttons) and show the
   section links instead, since those are what's actually missing/useful in
   a fixed bar you carry through the whole scroll. Also applies to any
   short landscape viewport regardless of width — a wide-but-short phone
   (e.g. 956px landscape) is past the 820px cutoff but still has no room to
   spare for the taller full-size nav, which was forcing hero's padding-top
   to grow to match it instead. */
@media (max-width:820px), (orientation:landscape) and (max-height:500px){
  .brand,nav .pill-btn.sm{display:none;}
  nav{padding:14px 16px;justify-content:center;}
  nav.scrolled{padding:10px 16px;}
  .navlinks{display:flex;gap:14px;align-items:center;}
  /* line-height:1 + padding-bottom:0 here: the base .navlinks a inherits
     body's line-height:1.6 and only pads its OWN bottom (room for the
     hover underline), so with the brand/button gone and nav.align-items
     centering just this one row, that lopsided box read as extra space
     above the text and too little below it — the nav's own (symmetric)
     padding wasn't the issue. */
  .navlinks a{font-size:11px;line-height:1;padding-bottom:0;}
}
@media (max-width:400px){
  .navlinks{gap:10px;}
  .navlinks a{font-size:10px;}
}
* { min-width: 0; }
img, svg { max-width: 100%; }

/* ---- section rhythm ---- */
/* overflow-x, not overflow-y: keeps each section's oversized glow blobs from
   pushing the page wider on narrow screens, without clipping the deliberate
   vertical bleed some glows have across section boundaries (negative top) */
/* scroll-margin-top: without it, clicking a nav link scrolls the target
   section's top edge to y:0 — which is exactly where the fixed nav sits,
   so the section's own kicker/heading landed hidden underneath it instead
   of just below it. Set to nav's own real (scrolled-state) height ONLY —
   not nav height plus extra breathing room, since the section's own
   padding-top already supplies that once the section's top edge clears
   the nav; adding both stacked into a much bigger gap than intended.
   Desktop value here; overridden below for the shorter mobile/landscape
   nav. */
section{position:relative;padding:120px 0;border-top:1px solid var(--line-soft);overflow-x:clip;scroll-margin-top:70px;}
section:first-of-type{border-top:none;}
@media (max-width:760px){section{padding:38px 0;}}
.section-head{margin-bottom:56px;max-width:760px;}
.section-head h2{font-size:clamp(22px,2.7vw,31px);font-weight:500;}
.section-head .lede{margin-top:14px;font-weight:300;font-size:15px;color:var(--text-mute);max-width:54ch;}
.reveal{opacity:0;transform:translateY(24px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1);}
.reveal.in{opacity:1;transform:translateY(0);}

/* ---- staggered reveal: direct children (each carrying its own .reveal)
   fade in one after another instead of all at once — pair with .stagger
   on the parent (see .svc-grid, .terms-grid, .stack-grid, .shot-stack) ---- */
.stagger > *:nth-child(1){transition-delay:0s;}
.stagger > *:nth-child(2){transition-delay:.08s;}
.stagger > *:nth-child(3){transition-delay:.16s;}
.stagger > *:nth-child(4){transition-delay:.24s;}
.stagger > *:nth-child(5){transition-delay:.32s;}
.stagger > *:nth-child(6){transition-delay:.4s;}

/* ---- hero ---- */
#hero{padding:180px 0 120px;border-top:none;overflow:hidden;}
.glow-1{width:620px;height:620px;top:-260px;right:-180px;}
.glow-2{width:420px;height:420px;bottom:-180px;left:-160px;opacity:.35;}
.hero-grid{position:relative;z-index:1;display:grid;grid-template-columns:1.2fr .8fr;gap:60px;align-items:center;}
@media (max-width:900px){.hero-grid{grid-template-columns:1fr;}#hero{padding:150px 0 70px;}}
.hero-tags{font-weight:400;font-size:15px;color:var(--text-dim);letter-spacing:.01em;}
.hero-name{font-size:clamp(30px,4.4vw,50px);font-weight:600;margin-top:20px;letter-spacing:.01em;line-height:1.08;color:var(--text);}
.hero-tagline{margin-top:20px;font-weight:500;font-size:18px;color:var(--accent);max-width:38ch;line-height:1.4;}
.hero-actions{margin-top:38px;display:flex;gap:14px;flex-wrap:wrap;}
.hero-contacts{margin-top:46px;font-weight:300;font-size:12.5px;color:var(--text-mute);display:flex;gap:2px 10px;flex-wrap:wrap;}
.hero-contacts a{transition:color .2s ease;}
.hero-contacts a:hover{color:var(--accent);}

.portrait-wrap{position:relative;display:flex;justify-content:center;align-items:flex-end;min-height:420px;}
.portrait-wrap img{max-width:400px;width:100%;height:auto;position:relative;z-index:1;}

.scroll-cue{position:absolute;bottom:28px;left:50%;transform:translateX(-50%);display:flex;flex-direction:column;align-items:center;gap:8px;font-size:10.5px;letter-spacing:.14em;color:var(--text-faint);text-transform:uppercase;font-weight:400;}
.scroll-cue .line{width:1px;height:28px;background:linear-gradient(var(--text-faint),transparent);animation:cue 1.9s ease-in-out infinite;}
@keyframes cue{0%{opacity:.15;transform:scaleY(.4);transform-origin:top;}50%{opacity:.9;transform:scaleY(1);transform-origin:top;}100%{opacity:.15;transform:scaleY(.4);transform-origin:top;}}
@media (max-width:900px){.scroll-cue{display:none;}}

/* ---- about ---- */
.about-grid{display:grid;grid-template-columns:.85fr 1.5fr;gap:60px;}
@media (max-width:860px){.about-grid{grid-template-columns:1fr;gap:40px;}}
.stat-card{padding:38px 32px;display:flex;flex-direction:column;justify-content:center;}
.stat-item + .stat-item{margin-top:26px;padding-top:26px;border-top:1px solid var(--line-soft);}
.stat-item .big{font-size:clamp(38px,4.6vw,50px);font-weight:600;color:var(--accent);font-variant-numeric:tabular-nums;line-height:1;}
.stat-item .big.big-label{font-size:clamp(19px,2.1vw,24px);letter-spacing:.08em;}
.stat-item .cap{margin-top:10px;font-weight:300;font-size:13.5px;color:var(--text-mute);max-width:34ch;}

.count{font-variant-numeric:tabular-nums;}

.trait{padding:22px 0;}
.trait + .trait{border-top:1px solid var(--line-soft);}
.trait h3{font-size:17px;font-weight:500;}
.trait p{margin-top:9px;font-weight:300;font-size:14px;color:var(--text-dim);max-width:60ch;}

/* ---- services ---- */
.svc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;}
@media (max-width:900px){.svc-grid{grid-template-columns:repeat(2,1fr);}}
@media (max-width:580px){.svc-grid{grid-template-columns:1fr;}}
.svc-card{padding:28px 24px;}
.svc-card h3{margin-top:20px;font-size:16.5px;font-weight:500;}
.svc-card p{margin-top:9px;font-weight:300;font-size:13px;color:var(--text-mute);}

/* ---- cases ---- */
.case{padding:80px 0;border-top:1px solid var(--line-soft);}
.case:first-of-type{border-top:none;padding-top:6px;}
.case-grid{display:grid;grid-template-columns:1fr 1fr;gap:60px;align-items:center;}
@media (max-width:900px){.case-grid{grid-template-columns:1fr;gap:36px;}}
.case-media{order:2;}
.case-body{order:1;}
.case.flip .case-media{order:1;}
.case.flip .case-body{order:2;}
@media (max-width:900px){.case-media,.case.flip .case-media{order:2 !important;}.case-body,.case.flip .case-body{order:1 !important;}}

.case-index{font-weight:400;font-size:12.5px;color:var(--text-faint);}
.case-index b{color:var(--accent);font-weight:500;}
.case-title{font-size:clamp(21px,2.4vw,27px);font-weight:500;margin-top:10px;}
.case-label{margin-top:26px;margin-bottom:10px;}
.case-body p.body-text{font-weight:300;font-size:14.5px;color:var(--text-dim);}

.done-card{padding:24px 26px;}
.done-list{list-style:none;margin:0;padding:0;}
.done-list li{position:relative;padding-left:20px;font-weight:300;font-size:14px;color:var(--text-dim);}
.done-list li + li{margin-top:14px;padding-top:14px;border-top:1px solid var(--line-soft);}
.done-list li::before{content:"✦";position:absolute;left:0;top:-2px;font-size:16px;color:var(--accent);}
/* li+li adds padding-top:14px for the divider spacing above — the marker
   needs that same offset added on top of its own position, or it stays
   pinned near the li's top edge (by the border) instead of next to the
   text, which sits 14px lower there than in the first (border-less) item */
.done-list li + li::before{top:12px;}

.result-line{margin-top:20px;font-weight:500;font-size:14.5px;color:var(--accent);max-width:56ch;}
.result-line b{font-weight:600;}

.stack-line{margin-top:20px;font-weight:300;font-size:13px;color:var(--text-mute);}
.stack-line b{color:var(--text-faint);font-weight:400;}
.case-link{margin-top:22px;}

.shot-stack{position:relative;aspect-ratio:4/3.15;}
.shot{position:absolute;border-radius:12px;overflow:hidden;background:var(--card-fill);padding:5px;transition: all 0.3s ease-in-out;}
.shot::before{
  content:"";position:absolute;inset:0;border-radius:inherit;padding:1.3px;
  background:linear-gradient(135deg,var(--accent-a) 0%,var(--accent) 22%,var(--accent-a) 42%,var(--accent) 64%,var(--accent-a) 84%,var(--accent) 100%);
  opacity:.6;-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
  mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;pointer-events:none;
}
.shot:hover{scale:1.02;transition: all 0.3s ease-in-out;}
.shot img{border-radius:8px;width:100%;height:100%;object-fit:cover;display:block;position:relative;}
.shot-a{width:76%;top:0;right:0;z-index:2;aspect-ratio:16/10.2;}
.shot-b{width:64%;bottom:0;left:0;z-index:3;aspect-ratio:16/10.2;box-shadow:0 20px 44px -18px rgba(0,0,0,.7);}
.shot-stack.has3{aspect-ratio:4/3.65;}
.shot-stack.has3 .shot-a{width:62%;top:0;right:0;z-index:1;}
.shot-stack.has3 .shot-b{width:60%;top:33%;left:0;bottom:auto;z-index:2;box-shadow:0 18px 36px -16px rgba(0,0,0,.7);}
.shot-stack.has3 .shot-c{width:54%;bottom:0;right:8%;left:auto;z-index:3;aspect-ratio:16/10.2;box-shadow:0 22px 42px -16px rgba(0,0,0,.75);}
.shot img{cursor:zoom-in;}

.stat-panel{padding:40px 36px;display:flex;flex-direction:column;justify-content:center;min-height:280px;}
.goal-tag{align-self:flex-start;font-weight:500;font-size:10.5px;letter-spacing:.09em;text-transform:uppercase;color:var(--text-mute);border:1px solid var(--line-soft);border-radius:999px;padding:5px 12px;margin-bottom:18px;}
.stat-panel .cap{font-weight:300;font-size:14.5px;color:var(--text-dim);max-width:36ch;line-height:1.5;}
.stat-panel .cap b{color:var(--accent);font-weight:500;}
.stat-panel .steps{margin-top:26px;display:flex;flex-direction:column;gap:12px;}
.stat-panel .step{display:flex;align-items:center;gap:12px;font-weight:300;font-size:12.5px;color:var(--text-mute);}
.stat-panel .step .n{width:22px;height:22px;border-radius:6px;border:1px solid rgba(228,105,152,.6);color:var(--accent);display:flex;align-items:center;justify-content:center;font-size:10.5px;flex:none;}

/* ---- stack ---- */
.stack-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 60px;}
@media (max-width:760px){.stack-grid{grid-template-columns:1fr;}}
.stack-cat{padding:22px 0;border-top:1px solid var(--line-soft);}
.stack-cat h3{font-weight:500;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--accent);margin-bottom:10px;}
.stack-cat p{font-weight:300;font-size:14px;color:var(--text-mute);}

/* ---- education ---- */
.edu-grid{display:grid;grid-template-columns:1.5fr 1fr;gap:60px;}
@media (max-width:860px){.edu-grid{grid-template-columns:1fr;gap:44px;}}
.edu-feature{padding:24px 26px;margin-bottom:6px;}
.edu-feature h3{font-size:17.5px;font-weight:500;}
.edu-feature p{margin-top:8px;font-weight:400;font-size:13px;color:var(--accent);}
.edu-row{padding:18px 0;border-top:1px solid var(--line-soft);}
.edu-row h4{font-size:14.5px;font-weight:500;margin:0;color:var(--text);}
.edu-row p{margin-top:6px;font-weight:400;font-size:12.5px;color:var(--accent);}
.edu-grid div .edu-row:first-child {border-top:0px;}
.cert-row{display:flex;justify-content:space-between;gap:16px;padding:16px 0;border-top:1px solid var(--line-soft);}
.cert-row .name{flex:1;min-width:0;}
.cert-row .date{flex:none;}
.cert-row .name{font-weight:300;font-size:13.5px;color:var(--text);max-width:30ch;}
.cert-row .date{font-weight:400;font-size:12px;color:var(--accent);white-space:nowrap;font-variant-numeric:tabular-nums;}
.subhead{font-weight:500;font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--text-faint);margin-bottom:20px;}

.blog-banner{
  padding:42px 44px;display:flex;justify-content:space-between;align-items:center;gap:32px;flex-wrap:wrap;
}
.blog-banner h3{margin-top:12px;font-size:21px;font-weight:500;color:var(--text);}
.blog-banner p{margin-top:10px;font-weight:300;font-size:14.5px;color:var(--text-dim);max-width:50ch;}
@media (max-width:640px){.blog-banner{padding:32px 26px;}}

.cert-marquee-wrap{margin-top:56px;padding-top:44px;border-top:1px solid var(--line-soft);}
.marquee{
  position:relative;overflow:hidden;margin:0 -32px;padding:0 32px;cursor:grab;
  touch-action:pan-y;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
}
.marquee.dragging{cursor:grabbing;}
.marquee-track{display:flex;gap:16px;width:max-content;will-change:transform;}
.marquee-nav{
  position:absolute;top:50%;transform:translateY(-50%);width:44px;height:44px;border-radius:50%;
  background:rgba(15,13,15,.32);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  border:1px solid rgba(228,105,152,.5);color:var(--text);
  display:flex;align-items:center;justify-content:center;cursor:pointer;
  opacity:0;pointer-events:none;transition:opacity .25s ease,background .2s ease,border-color .2s ease;
  z-index:2;
}
.marquee:hover .marquee-nav{opacity:1;pointer-events:auto;}
.marquee-nav:hover{background:rgba(228,105,152,.22);border-color:var(--accent);}
.marquee-prev{left:8px;}
.marquee-next{right:8px;}
@media (max-width:640px){
  .marquee-nav{opacity:.55;pointer-events:auto;width:36px;height:36px;}
  .marquee-prev{left:2px;}
  .marquee-next{right:2px;}
}
.cert-card{position:relative;flex:none;width:176px;background:var(--card-fill);border-radius:14px;padding:14px;}
.cert-card-photo{aspect-ratio:3/4;border-radius:9px;background:rgba(255,255,255,.035);border:1px solid var(--line-soft);display:flex;align-items:center;justify-content:center;margin-bottom:12px;overflow:hidden;}
.cert-card-photo img{width:30px;height:30px;opacity:.4;object-fit:contain;}
.cert-card-photo.has-photo{border-color:rgba(228,105,152,.35);}
.cert-card-photo.has-photo img{width:100%;height:100%;opacity:1;object-fit:cover;cursor:zoom-in;}
.cert-card-title{font-size:12px;font-weight:500;color:var(--text);line-height:1.32;}
.cert-card-date{margin-top:6px;font-size:11px;color:var(--accent);font-weight:400;font-variant-numeric:tabular-nums;}

/* ---- terms ---- */
.terms-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px;}
@media (max-width:640px){.terms-grid{grid-template-columns:1fr;}}
.term-card{padding:30px 28px;display:flex;gap:20px;align-items:flex-start;}
.term-card h3{font-size:16px;font-weight:500;}
.term-card p{margin-top:8px;font-weight:300;font-size:13px;color:var(--text-mute);}

/* ---- cta ---- */
#cta{border-top:1px solid var(--line-soft);padding:120px 0 90px;position:relative;overflow:hidden;}
.cta-glow{width:560px;height:560px;top:-200px;left:50%;transform:translateX(-50%);opacity:.4;}
.cta-inner{position:relative;z-index:1;max-width:820px;}
.cta-inner h2{font-size:clamp(30px,4.4vw,44px);font-weight:600;}
.cta-inner .lede{margin-top:18px;font-weight:400;font-size:15.5px;color:var(--text-dim);max-width:52ch;}

/* ---- cta contacts ---- */
.contact-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:44px;}
@media (max-width:640px){.contact-cards{grid-template-columns:1fr;}}
.contact-card{padding:28px 24px;display:flex;flex-direction:column;align-items:flex-start;gap:18px;transition:transform .25s ease;}
.contact-card:hover{transform:translateY(-3px);}
.contact-card:hover .contact-card-val{color:var(--accent);}
.contact-card-icon{width:48px;height:48px;border-radius:14px;object-fit:contain;flex:none;}
.contact-card-icon.icon-max{width:42px;height:42px;}
.contact-card-body{display:flex;flex-direction:column;gap:5px;}
.contact-card-label{font-weight:500;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--text-faint);}
.contact-card-val{font-weight:500;font-size:16px;color:var(--text);word-break:break-word;transition:color .2s ease;}

.cta-footer-note{margin-top:32px;font-weight:300;font-size:12px;color:var(--text-faint);}
.cta-footer-note a{transition:color .2s ease;}
.cta-footer-note a:hover{color:var(--accent);}

footer{padding:34px 0;}
.footer-row{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;font-weight:300;font-size:11.5px;color:var(--text-faint);}
.footer-row a{transition:color .2s ease;}
.footer-row a:hover{color:var(--accent);}

/* ---- lightbox ---- */
.lightbox{
  position:fixed;inset:0;z-index:200;padding:56px;
  display:flex;align-items:center;justify-content:center;
  background:rgba(6,5,6,.9);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  opacity:0;pointer-events:none;transition:opacity .28s ease;
  /* the swipe-to-navigate gesture is handled entirely in JS (touchmove
     there calls preventDefault) — this stops the browser's own default
     touch scrolling/rubber-banding from ever kicking in first and
     dragging the page underneath along with the finger */
  touch-action:none;
}
.lightbox.open{opacity:1;pointer-events:auto;}
.lightbox img{
  max-width:min(1100px,90vw);max-height:86vh;
  box-shadow:0 50px 100px -20px rgba(0,0,0,.7);
  transform:scale(.96);transition:transform .28s ease;
}
.lightbox.open img{transform:scale(1);}
/* per-photo paging transition (see setLightboxImage in script.js): the exit
   states push the current photo toward the side it's leaving from, the
   enter states start it from the opposite side so swapping the src while
   invisible/off-position reads as a slide, not a plain swap — and never
   flashes the previous photo since it's hidden the moment src changes */
#lightboxImg{transition:transform .22s cubic-bezier(.2,.7,.2,1),opacity .2s ease;}
#lightboxImg.lb-hidden{opacity:0;}
#lightboxImg.lb-exit-left{transform:translateX(-36px) scale(.97);opacity:0;}
#lightboxImg.lb-exit-right{transform:translateX(36px) scale(.97);opacity:0;}
#lightboxImg.lb-enter-left{transform:translateX(-36px) scale(.97);opacity:0;}
#lightboxImg.lb-enter-right{transform:translateX(36px) scale(.97);opacity:0;}
#lightboxImg.lb-no-transition{transition:none !important;}
.lightbox-close{
  position:absolute;top:24px;right:28px;width:44px;height:44px;border-radius:50%;
  background:rgba(255,255,255,.06);border:1px solid var(--line-soft);color:var(--text);
  display:flex;align-items:center;justify-content:center;cursor:pointer;
  transition:background .2s ease,border-color .2s ease;
}
.lightbox-close:hover{background:var(--accent-soft-bg,rgba(228,105,152,.12));border-color:rgba(228,105,152,.5);}
.lightbox-nav{
  position:absolute;top:50%;transform:translateY(-50%);width:52px;height:52px;border-radius:50%;
  background:rgba(255,255,255,.06);border:1px solid var(--line-soft);color:var(--text);
  display:flex;align-items:center;justify-content:center;cursor:pointer;
  transition:background .2s ease,border-color .2s ease;
}
.lightbox-nav:hover{background:rgba(228,105,152,.14);border-color:rgba(228,105,152,.5);}
.lightbox-prev{left:24px;}
.lightbox-next{right:24px;}
/* touch devices page through the lightbox by swiping — the buttons are
   redundant there and just sit on top of the photo. !important because JS
   also toggles this element's inline display (show/hide depending on
   whether the group has more than one photo), which would otherwise win. */
@media (hover:none), (pointer:coarse){
  .lightbox-nav{display:none !important;}
}
.lightbox-count{
  position:absolute;bottom:22px;left:50%;transform:translateX(-50%);
  font-weight:400;font-size:12.5px;color:var(--text-mute);font-variant-numeric:tabular-nums;
  letter-spacing:.04em;
}
/* swipe hint — same label styling, same pulse animation and same 28px
   "line" length as the hero's .scroll-cue, just laid out sideways with an
   arrowhead on each end instead of one vertical bar, to hint paging left/
   right instead of scrolling down */
.lightbox-swipe-cue{
  display:none; /* swipe is a touch/mobile gesture — irrelevant with a mouse
    on desktop, where the always-visible prev/next circles already say
    "there's more". Turned back on for touch devices below (any
    orientation) — short landscape mobile additionally shrinks/repositions
    it further down this file so it doesn't sit on top of the photo. */
  position:absolute;bottom:50px;left:50%;transform:translateX(-50%);
  align-items:center;gap:10px;
  font-size:10.5px;letter-spacing:.14em;color:var(--text-faint);text-transform:uppercase;font-weight:400;
  pointer-events:none;
}
@media (hover:none), (pointer:coarse){
  .lightbox-swipe-cue{display:flex;}
}
/* drawn along the stroke, not scaled/masked. Each arrow is one SVG with
   three paths, all pathLength="100" so the dash math is the same
   regardless of real geometry:
     .cue-shaft — the straight line back to the text
     .cue-arm × 2 — each half of the arrowhead, as its own path starting at
       the *tip* (the same point the shaft ends at — not the arms' free
       ends) and drawn out to its own free end. Sharing that single
       coordinate with the shaft is what actually closes the gap: two
       elements meeting at one exact point can't misalign the way a
       roundedcap's own geometry can. The two arms animate together since
       they're symmetric strokes flaring from the same shared point — that
       reads as one reveal, unlike the earlier bug where unrelated
       *subpaths of a single path* dashed in parallel when they shouldn't
       have.
   Timing: the arms start a bit before the shaft finishes and are timed to
   land on "fully drawn" at the same moment (25–40%), rather than waiting
   for the shaft to completely stop before starting. */
.lightbox-swipe-cue svg{display:block;overflow:visible;color:var(--text-faint);}
/* opacity stays at 1 through the whole draw→hold→erase span, so "removed"
   reads as the stroke un-drawing itself, not fading out — but a round
   linecap can leave a tiny stray fragment right at stroke-dashoffset:-100
   (fully retracted), so opacity only drops *after* that point is reached,
   briefly, purely to hide that leftover speck while nothing should be
   visible anyway (not perceptible as the arrow itself fading). */
.lightbox-swipe-cue path{fill:none;stroke-dasharray:100;}
.lightbox-swipe-cue .cue-shaft{animation:cue-line-shaft 2.1s ease-in-out infinite;}
.lightbox-swipe-cue .cue-arm{animation:cue-line-arm 2.1s ease-in-out infinite;}
@keyframes cue-line-shaft{
  0%{stroke-dashoffset:100;opacity:0;}
  4%{opacity:1;}
  40%{stroke-dashoffset:0;}
  65%{stroke-dashoffset:0;}
  96%{stroke-dashoffset:-100;opacity:1;}
  100%{stroke-dashoffset:-100;opacity:0;}
}
@keyframes cue-line-arm{
  0%{stroke-dashoffset:100;opacity:0;}
  25%{stroke-dashoffset:100;opacity:0;}
  29%{opacity:1;}
  40%{stroke-dashoffset:0;}
  65%{stroke-dashoffset:0;}
  78%{stroke-dashoffset:-100;opacity:1;}
  82%{opacity:0;}
  100%{stroke-dashoffset:-100;}
}
/* short landscape mobile: this is where swiping is the natural gesture
   (finger already on the photo) and there's the least vertical room, so the
   hint earns its place here but has to shrink and give the photo space —
   at full size it was tall enough to sit on top of the image instead of
   below it. */
@media (orientation:landscape) and (max-height:500px){
  .lightbox{padding:14px 46px;}
  .lightbox-close{top:10px;right:10px;width:36px;height:36px;}
  .lightbox-nav{width:38px;height:38px;}
  .lightbox-prev{left:6px;}
  .lightbox-next{right:6px;}
  .lightbox img{max-height:70vh;}
  .lightbox-swipe-cue{
    display:flex;
    bottom:24px;
    gap:6px;
    font-size:9px;
  }
  .lightbox-swipe-cue svg{width:26px;height:11px;}
  .lightbox-count{bottom:6px;font-size:11px;}
}
@media (max-width:640px){
  .lightbox{padding:24px;}
  .lightbox-close{top:14px;right:14px;}
  .lightbox-nav{width:42px;height:42px;}
  .lightbox-prev{left:8px;}
  .lightbox-next{right:8px;}
}

/* ---- cursor glow trail: a chain of the exact same background-glow blobs,
   following the mouse. Bends/arcs because each link chases the one before
   it (not the raw cursor), instead of stretching a single rigid shape. ---- */
#cursorGlowChain{
  position:fixed;top:0;left:0;width:0;height:0;pointer-events:none;
  opacity:0;transition:opacity .4s ease;
  filter:blur(90px); /* blurred ONCE for the whole group — blurring each
    link separately (6x filter:blur stacked near-identical circles) is what
    produced the banded/diamond-looking artifact */
}
#cursorGlowChain.visible{opacity:.6;}
.cursor-seg{
  position:fixed !important;top:0 !important;left:0 !important;right:auto !important;bottom:auto !important;
  width:540px;height:540px;border-radius:50%;
  background:radial-gradient(circle,rgba(228,105,152,.3),rgba(228,105,152,0) 70%);
  will-change:transform;
}
@media (max-width:900px){#cursorGlowChain{display:none;}}

/* ---- mobile padding tightening ----
   #hero, #cta and .case each set their own padding earlier in this file
   (ID selectors / a plain class, not covered by the generic `section` rule),
   so at equal specificity the LAST matching rule wins the cascade — these
   have to come after those declarations (including #hero's own 900px
   override above) to actually win on small screens instead of being
   silently overridden back to desktop-scale padding. */
/* nav is the compact ~47px (scrolled-state) version at ≤820px width or any
   short landscape viewport, not the ~70px desktop one the base
   scroll-margin-top rule (in the "section rhythm" block above) was sized
   for — this has to come AFTER that rule in the file to actually win at
   equal specificity, same reasoning as the mobile-padding block below. */
@media (max-width:820px), (orientation:landscape) and (max-height:500px){
  section{scroll-margin-top:47px;}
}
@media (max-width:760px){
  #hero{padding:66px 0 28px;}
  #cta{padding:38px 0 28px;}
  .case{padding:28px 0;}
  /* "Обсудим ваш проект?" used its own larger, bolder scale (clamp 30–44px)
     that only really earns its place as a big full-width closing statement
     on desktop — on mobile it just read as oddly bigger than every other
     section's heading right above it, so match .section-head h2 here. */
  .cta-inner h2{font-size:clamp(22px,2.7vw,31px);font-weight:500;}
}

/* ---- narrow tall phones (e.g. 360x740): the hero's desktop-scale spacing
   pushed the portrait photo well past the first screen, reading as dead
   black space below the buttons — tighten the rhythm so it comes into
   view sooner ---- */
@media (max-width:600px){
  #hero{padding:66px 0 20px;}
  .hero-grid{gap:20px;}
  /* these three sat noticeably larger, proportionally, than their
     equivalent-role elements elsewhere (.kicker, .section-head h2,
     .section-head .lede) once everything else was mobile-scale — H1 should
     still read bigger than an H2, just not by this much. */
  .hero-tags{font-size:13px;}
  .hero-name{font-size:27px;margin-top:16px;}
  .bar{margin:14px 0 18px;}
  .hero-tagline{font-size:16px;margin-top:14px;}
  .hero-actions{margin-top:22px;}
  .hero-contacts{margin-top:26px;}
  .portrait-wrap{min-height:0;}
  .portrait-wrap img{max-width:260px;}
}

/* ---- short landscape mobile viewports (phone turned sideways): portrait-
   scale hero/section padding was built for a tall screen, so here it ate
   most of the visible height regardless of viewport width ---- */
@media (orientation:landscape) and (max-height:500px){
  section{padding:32px 0;}
  .section-head{margin-bottom:32px;}
  /* nav is the compact link-only version everywhere in this query (~54.6px
     tall) — padding-top just needs to clear it, no extra breathing room,
     since vertical space is the scarce resource here. */
  #hero{padding:50px 0 20px;}
  #cta{padding:32px 0 24px;}
  .case{padding:24px 0;}
  .hero-grid{gap:20px;align-items:center;}
  /* the floor matters more than the vw term for most landscape phone
     widths here (~600-800px) — e.g. at 667px, 3.2vw only added ~1.3px over
     the old 20px floor, landing at 21.35px: an imperceptible bump despite
     the numbers looking raised. Pushing the floor itself up is what
     actually reads as bigger at that width; the vw term still takes over
     for the small range approaching the ceiling on wider phones. */
  .hero-tags{font-size:clamp(12px,1.4vw,14px);}
  .hero-name{font-size:clamp(24px,3vw,30px);margin-top:8px;}
  .bar{margin:8px 0 10px;}
  .hero-tagline{margin-top:6px;font-size:clamp(13px,1.6vw,16px);max-width:32ch;}
  .hero-actions{margin-top:14px;gap:8px;}
  .hero-actions .pill-btn{padding:6px 14px;font-size:12px;gap:6px;}
  .hero-contacts{margin-top:18px;font-size:11.5px;}
  .portrait-wrap{min-height:0;}
  .portrait-wrap img{max-width:210px;}
  /* "Листайте" scroll cue was overlapping the second hero button once the
     hero got this short — it's a landing-hint anyway, not needed here */
  .scroll-cue{display:none;}
}
@media (orientation:landscape) and (max-height:500px) and (min-width:560px){
  .hero-grid{grid-template-columns:1.15fr .85fr;}
}
/* ---- short landscape phones only: the desktop side-by-side case-grid
   (text next to a tall overlapping shot-stack) doesn't fit a ~400-500px
   viewport — text first, screenshots in a row below it, scaled down but
   kept at their real (landscape) aspect ratio instead of being cropped to
   fit an arbitrary box. (max-width:900px above already puts text first on
   narrower/portrait mobile — this covers wider short-landscape phones too,
   e.g. 956px-wide ones that rule's width check misses.) ---- */
@media (orientation:landscape) and (max-height:500px){
  .case-grid{grid-template-columns:1fr;gap:20px;}
  .case-media,.case.flip .case-media{order:2 !important;}
  .case-body,.case.flip .case-body{order:1 !important;}

  .shot-stack,.shot-stack.has3{
    position:static;aspect-ratio:auto !important;
    display:flex;flex-wrap:nowrap;gap:10px;
    overflow-x:auto;-webkit-overflow-scrolling:touch;
    /* no scroll-snap here: with scroll-snap-type set, some browsers would
       occasionally "snap" this inner horizontal scroller during an ordinary
       vertical page scroll, yanking it (and the page) up so the row ended
       up hidden under the fixed nav — plain free-scrolling is enough for a
       2-3 image row */
    overscroll-behavior-x:contain;
    padding-bottom:4px;scrollbar-width:none;
  }
  .shot-stack::-webkit-scrollbar{display:none;}
  .shot-stack .shot{
    position:relative !important;top:auto !important;left:auto !important;
    right:auto !important;bottom:auto !important;z-index:auto !important;
    width:auto !important;height:140px;flex:none;aspect-ratio:auto !important;
    box-shadow:none !important;
  }
  .shot-stack .shot img{width:auto;height:100%;object-fit:contain;}
}

/* ---- glow position editor (visit with ?editglows=1) ---- */
.glow.glow-editable{pointer-events:auto;cursor:grab;z-index:5;}
.glow.glow-editable.dragging{cursor:grabbing;opacity:.85;}
.glow-tag{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  background:rgba(10,9,10,.85);color:#fff;font-family:'Unbounded','Segoe UI',sans-serif;
  font-size:11px;font-weight:600;padding:4px 8px 4px 10px;border-radius:999px;
  white-space:nowrap;pointer-events:none;filter:none;
  display:flex;align-items:center;gap:6px;
}
.glow-tag-del{
  pointer-events:auto;cursor:pointer;border:none;border-radius:50%;
  width:16px;height:16px;line-height:16px;padding:0;font-size:12px;
  background:rgba(255,255,255,.15);color:#fff;
}
.glow-tag-del:hover{background:var(--accent);}
#glowEditorPanel{
  position:fixed;top:16px;right:16px;z-index:300;width:280px;
  background:rgba(14,12,14,.95);border:1px solid rgba(228,105,152,.4);border-radius:14px;
  padding:16px 18px;color:#fff;font-family:'Segoe UI',sans-serif;font-size:13px;
  box-shadow:0 20px 50px -10px rgba(0,0,0,.6);
}
#glowEditorPanel strong{font-size:14px;}
#glowEditorPanel p{margin:8px 0 12px;font-weight:400;line-height:1.4;color:#cbc8ce;}
#glowEditorPanel button{
  font-family:inherit;font-size:12.5px;font-weight:600;padding:9px 14px;border-radius:8px;
  border:1px solid rgba(228,105,152,.5);background:rgba(228,105,152,.12);color:#fff;
  cursor:pointer;margin:0 8px 0 0;
}
#glowEditorPanel button:hover{background:#e46998;}
#glowOutput{
  margin-top:12px;max-height:260px;overflow:auto;background:#000;padding:10px;
  border-radius:8px;font-size:10.5px;line-height:1.5;white-space:pre-wrap;word-break:break-all;
}
