:root{
  --bg:#717171;
  --gold:#c3a567;
  --white:#ffffff;
  --footer:#5c5b5b;
  --page-w:1920px;
  --page-h:5372px;
}

*{box-sizing:border-box; margin:0; padding:0;}
html{ -webkit-text-size-adjust:100%; background:var(--bg); }
body{
  font-family:'Montserrat','Segoe UI',Arial,sans-serif;
  color:var(--white);
  background:var(--bg);
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
img{display:block; max-width:none;}
a{color:inherit; text-decoration:none;}

/* ---------- Scale wrapper ---------- */
/* width:100vw (not 100%) on purpose: 100% would shrink by the native
   scrollbar's width (~15-17px), so the scale-to-fit-1920 system below
   computed e.g. 1903/1920 ≈ .991 instead of exactly 1 at a 1920px monitor —
   a hair off 1:1 is enough to force the browser to resample every image/
   font at a fractional size, reading as a soft/blurry page site-wide. 100vw
   ignores the scrollbar the same way clientWidth would if there were none,
   so the design renders pixel-perfect at 1920 again; body's own
   overflow-x:hidden (below) clips the ~1px sliver this can overhang by. */
/* overflow-y:hidden explicit, not left to default: with only overflow-x set,
   the UA computes overflow-y as auto (spec quirk), and .page's *layout* box
   stays at its full unscaled --page-h (transform:scale doesn't shrink layout
   size, only paint) — taller than wrap's own JS-set (scaled) height, so that
   auto-Y was quietly growing its own scrollbar and eating into clientWidth
   at every scale below 1, the same width-off-by-scrollbar problem as above
   just smaller and everywhere instead of only at 1920. */
.page-wrap{ position:relative; width:100vw; overflow:hidden; }
.page{
  position:relative;
  width:var(--page-w);
  height:var(--page-h);
  background:var(--bg);
  overflow:hidden;
  transform-origin:top left;
}

/* Sits above .hero-bottle (which lives outside .page for pinning), scrolls
   normally with the page like everything inside .page does — same
   transform:scale trick as .page itself, kept in sync in JS. */
.pinned-front-layer{
  position:absolute; left:0; top:0;
  transform-origin:top left;
  z-index:3;
  pointer-events:none;
}
.pinned-front-layer a, .pinned-front-layer button{ pointer-events:auto; }

/* helpers */
.c-gold{ color:var(--gold); }
.c-white{ color:var(--white); }
.b{ font-weight:700; }
.r{ font-weight:400; }

/* ---------- Watermark (flattened Figma raster w/ baked-in blur, opaque on --bg) ---------- */
.wm-full{
  position:absolute;
  left:129px; top:179px; width:1622px; height:765px;
  pointer-events:none;
}

/* ---------- Header ---------- */
.logo-header{
  position:absolute;
  left:152px; top:28px;
  width:188.578px; height:27.207px;
  z-index:5;
}
.nav{ position:absolute; left:0; top:0; width:100%; height:0; z-index:5; }
.nav-link{
  position:absolute; top:39px;
  font-family:'Montserrat'; font-weight:300;
  font-size:16px; line-height:normal; letter-spacing:.9px;
  color:var(--white); white-space:nowrap;
}
.nav-link:nth-child(1){ left:688px; }
.nav-link:nth-child(2){ left:835px; }
.nav-link:nth-child(3){ left:958px; }
.nav-link:nth-child(4){ left:1115px; }

.pill{
  position:absolute;
  background:var(--gold);
  border:none; cursor:pointer;
  border-radius:9px;
  height:42.5px;
  display:flex; align-items:center; justify-content:center;
  z-index:5;
}
.pill-order{ left:1591.29px; top:29.25px; width:148.42px; }
.pill-catalog{ left:440px; top:357.25px; width:148.42px; }
.nav-cta{
  font-family:'Montserrat'; font-weight:600;
  font-size:16px; letter-spacing:.9px; color:var(--white); white-space:nowrap;
}

/* ---------- Hero copy ---------- */
.hero-h1{
  position:absolute; left:432px; top:136px;
  font-family:'Montserrat'; font-weight:700;
  font-size:81.6px; line-height:normal; white-space:nowrap;
}
.hero-h1 .r{ font-family:'Montserrat'; }
.hero-h1 .b{ font-family:'Montserrat'; }

.hero-bottle{
  /* Absolute inside page-wrap (like .pinned-front-layer), so it scrolls
     together with the hero and its overlay text and simply leaves the
     viewport as you scroll down — instead of being pinned and drifting
     across the whole site. Exact left/top/width/height set in JS from
     currentScale. */
  position:absolute;
  z-index:2;
  pointer-events:none;
}
#bottleCanvas{
  width:100%; height:100%; display:block;
  /* Soft edge safety net: if scroll drift ever nudges the model near the
     frustum boundary, it fades out instead of hard-clipping against the
     canvas' rectangular edge. Invisible in the normal centered pose. */
  -webkit-mask-image: radial-gradient(ellipse 72% 72% at 50% 50%, #000 78%, transparent 100%);
  mask-image: radial-gradient(ellipse 72% 72% at 50% 50%, #000 78%, transparent 100%);
}

.hero-reliab{
  position:absolute; left:989px; top:545px;
  font-family:'Montserrat'; font-weight:700;
  font-size:81.6px; line-height:normal; white-space:nowrap;
  text-align:right;
  text-shadow:2px 0 0 rgba(0,0,0,0.25);
  z-index:3;
}
.hero-reliab .b{ font-family:'Montserrat'; font-weight:700; }
.hero-reliab .r{ font-family:'Montserrat'; font-weight:400; }

.hero-25{
  position:absolute; left:150px; top:717px;
  font-family:'Montserrat'; font-weight:600;
  font-size:81.6px; line-height:normal; color:var(--gold);
}
.hero-25-sub{
  position:absolute; left:150px; top:805px;
  font-family:'Montserrat'; font-weight:400;
  font-size:18px; letter-spacing:.9px; color:var(--white);
}
.hero-25-p{
  position:absolute; left:150px; top:834px; width:315px;
  font-family:'Montserrat'; font-weight:400; font-size:14px; line-height:normal; color:var(--white);
}
.hero-right-p{
  position:absolute; left:1253px; top:733.34px; width:361px;
  font-family:'Montserrat'; font-weight:400; font-size:14px; line-height:normal; color:var(--white);
}

/* ---------- Range ---------- */
/* left:366 centers the block in the 1920 design (block is 1188 wide, so
   (1920-1188)/2 = 366 gives equal 366px gutters). Centered via `left`, not a
   transform, because .range-h also carries the .reveal class whose own
   transform (translateY) would clobber a translateX centering. Lines stay
   left-aligned as designed. */
.range-h{
  position:absolute; left:366px; top:1034px;
  font-family:'Montserrat'; font-weight:400;
  font-size:81.6px; line-height:normal; color:var(--white); white-space:nowrap;
}
.range-h .c-gold{ font-weight:700; }
.range-h .big{ font-size:135px; }
.range-h p{ margin:0; }

/* ---------- Cards ---------- */
.cards-lead{
  position:absolute; left:150px; top:1531.34px; width:307px; height:49px;
  font-family:'Montserrat'; font-weight:400; font-size:14px; line-height:normal; color:var(--white);
}
.card{
  position:absolute; top:1534px;
  width:357.459px; height:374.17px;
  background:var(--gold);
  border-radius:18.164px;
  box-shadow:0 2.906px 2.906px 0 rgba(255,224,166,0.35);
}
.card-1{ left:593px; }
.card-2{ left:1003.5px; }
.card-3{ left:1412.54px; }

.card-title{
  position:absolute;
  font-family:'Montserrat'; font-weight:600;
  font-size:32.347px; line-height:normal; letter-spacing:1.6174px; color:var(--white);
}
.ct-1{ left:617px; top:1566px; width:242.998px; }
.ct-2{ left:1035px; top:1566px; width:264px; }
.ct-3{ left:1436px; top:1566px; width:264px; }
.card-title p{ margin:0; }

.card-num{
  position:absolute; top:1707px;
  font-family:'Montserrat'; font-weight:600;
  font-size:174.058px; line-height:normal; letter-spacing:8.7029px;
  color:var(--white); opacity:.46;
}
.cn-1{ left:738px; width:226px; }
.cn-2{ left:1115px; width:255px; }
.cn-3{ left:1522px; width:255px; }

.card-lorem{
  position:absolute; width:286px;
  font-family:'Montserrat'; font-weight:400;
  font-size:10.597px; line-height:normal; color:var(--white);
}
.cl-1{ left:617px; top:1660px; }
.cl-2{ left:1035px; top:1694px; }
.cl-3{ left:1436px; top:1655px; }

/* ---------- Standards ---------- */
.std-h{
  position:absolute; left:150px; top:1967px; width:1429px;
  font-family:'Montserrat'; font-weight:700; font-size:81.6px; line-height:normal;
}
.std-h .r{ font-weight:400; }

/* ---------- Splash composition ----------
   Layer order (back to front): ring line -> splash image -> ring dots/labels.
   This makes the ring visually duck behind the splash on the side where
   the golden liquid covers it, and stay on top elsewhere (real z-order,
   not a crop) since splash.png is transparent outside the liquid shape. */
.splash-wrap{
  position:absolute; left:501.02px; top:1968px; /* crown lands at base y~2173, matching the mockup. (Figma node 150:64 reports y=2313.95, but that is the node's internal box, not the visual top — using it pushed the splash ~330px too low.) 60px added on top of the mockup-matched value to open a gap under .std-h. */
  width:1096.975px; height:1088.01px;
  display:flex; align-items:center; justify-content:center;
  z-index:2;
}
.splash-img{
  width:838.26px; height:820.864px;
  object-fit:cover;
  opacity:0;
  transform:rotate(-23.63deg) scale(.92);
  transition:opacity 1.3s ease, transform 1.5s cubic-bezier(.2,.7,.2,1);
}
.splash-img.in{ opacity:1; transform:rotate(-23.63deg) scale(1); }

/* Ring — ellipse fitted to the approved mockup (passes through all 3 dots).
   center (868,2653), semi-axes 352×139, tilted -31.5°. Placed in an SVG that
   uses base-pixel coords (viewBox == position box) so it scales with .page.
   Relying on splash.png alpha for occlusion turned out unreliable (the arc
   drifts on/off the opaque wave as the two get tuned independently), so the
   ring sits in FRONT the whole way (z-index:3) and main.js punches a fixed
   gap in it with stroke-dasharray over the short stretch on the left that
   crosses the splash's pale inner curl — a real crop, not alpha-dependent.
   It's an open ellipse: the gap is never bridged, even mid draw-in. See main.js.
   NOTE: because overflow:visible is set, moving THIS box/viewBox alone does
   NOT move the ellipse on screen — the ellipse's own cx/cy (in index.html)
   is what actually positions it. Box/viewBox here just need to stay in sync
   with cx/cy for cleanliness; they aren't load-bearing for the visual result. */
.ring-svg{
  position:absolute; left:555px; top:2460px;
  width:626px; height:446px;
  overflow:visible; z-index:3; pointer-events:none;
}
.ring-path{ opacity:.9; }

.ring-dot{
  position:absolute; width:55.531px; height:55.531px;
  z-index:3; /* in front of .splash-wrap */
  opacity:0; transform:scale(.3);
  transform-origin:center;
  transition:opacity .6s ease, transform .65s cubic-bezier(.2,.9,.3,1.5);
}
.ring-dot.in{ opacity:1; transform:scale(1); }
.ring-dot[data-d="bottom"]{ left:762.61px; top:2813.4px; }
.ring-dot[data-d="left"]{ left:567.33px; top:2684.1px; }
.ring-dot[data-d="top"]{ left:1105px; top:2415px; }

.marker{
  position:absolute;
  font-family:'Montserrat'; font-weight:400;
  font-size:11.711px; line-height:normal; color:var(--white); z-index:3;
  opacity:0; transform:translateY(10px);
  transition:opacity .75s ease, transform .75s ease;
}
.marker.in{ opacity:1; transform:none; }
.marker p{ margin:0; }
.mk-top{ left:1172px; top:2426px; width:275px; }
.mk-left{ left:349px; top:2700px; width:209px; }
.mk-bottom{ left:669px; top:2880px; width:283px; }

/* ---------- Технологии ---------- */
.tech-h{
  position:absolute; top:2869px; left:657px; width:1113px;
  font-family:'Montserrat'; font-weight:700; font-size:81.6px; line-height:normal;
  text-align:right;
}
.tech-h .r{ font-weight:400; }
.tech-p{
  position:absolute; left:722px; top:3078px; width:1055px; height:49px;
  font-family:'Montserrat'; font-weight:400; font-size:14px; line-height:normal; color:var(--white);
}

/* ---------- "Найдите масло" — подбор продукта (Figma 343:4xx) ---------- */
/* Warm gold glow behind the canister — two blurred gold ellipses in the mockup,
   approximated with soft radial gradients (no filter:blur, keeps scroll cheap). */
.find-wm{
  position:absolute; left:150px; top:3728px; width:1487px; height:213px;
  z-index:0; pointer-events:none; /* opacity is baked into the PNG (~20%) */
}
.find-glow{
  position:absolute; border-radius:50%; z-index:0; pointer-events:none;
  background:radial-gradient(circle, rgba(195,165,103,0.40) 0%, rgba(195,165,103,0.16) 34%, rgba(195,165,103,0) 66%);
}
.find-glow-1{ left:1091px; top:3270px; width:600px; height:600px; }
.find-glow-2{ left:1152px; top:3521px; width:600px; height:600px; }
/* Canister: the wrap slides in from the right (+ slight tilt & fade) when it
   scrolls into view (JS adds .in), while the inner <img> floats forever — two
   separate transforms so they don't fight. */
.find-canister-wrap{
  position:absolute; left:1181px; top:3212px; width:596px; height:850px;
  z-index:1; pointer-events:none;
  opacity:0; transform:translateX(110px) rotate(5deg);
  transition:opacity 1.7s ease, transform 2s cubic-bezier(.2,.7,.2,1);
  will-change:opacity, transform;
}
.find-canister-wrap.in{ opacity:1; transform:translateX(0) rotate(0deg); }
.find-canister{
  width:100%; height:100%; object-fit:contain; display:block;
  animation:find-float 4.5s ease-in-out infinite;
}
@keyframes find-float{
  0%,100%{ transform:translateY(0); }
  50%{ transform:translateY(-16px); }
}
.find-h{
  position:absolute; left:146px; top:3466px;
  font-family:'Montserrat'; font-weight:400; font-size:81.6px; line-height:normal;
  color:var(--white); white-space:nowrap; z-index:2;
}
.find-h .c-gold{ font-weight:700; }
.find-p{
  position:absolute; left:150px; top:3774px; width:661px;
  font-family:'Montserrat'; font-weight:400; font-size:14px; line-height:normal; color:var(--white); z-index:2;
}
/* Heading/paragraph "grow from below": AE-style Scale 0% -> 100% with the
   anchor point pinned to the bottom-left, so the text scales up in place
   from its own baseline instead of fading, sliding, or masking. */
.find-rise{
  transform:scale(0); transform-origin:0% 100%;
  transition:transform 1.8s cubic-bezier(.22,1,.36,1);
  will-change:transform;
}
.find-rise.in{ transform:scale(1); }
.pill-find{ left:662px; top:3834px; width:148.42px; z-index:5; }

/* ---------- Contacts ---------- */
.contacts-h{
  position:absolute; left:143px; top:4084px; /* +872 for the "Найдите масло" block inserted above */
  font-family:'Montserrat'; font-weight:700; font-size:81.6px; line-height:normal; color:var(--gold);
}
.contacts-info{
  position:absolute; left:150px; top:4183px; width:720px;
  font-family:'Montserrat'; font-weight:400; font-size:20px; line-height:normal; color:var(--white);
}
.contacts-info p{ margin:0 0 20px; }
.contacts-info a{ text-decoration:underline; }

.banner{
  position:absolute; left:149px; top:4451px; width:547px; height:247px;
  border-radius:25px; overflow:hidden;
}
.banner img{ width:100%; height:100%; object-fit:cover; }
.banner-tint{ position:absolute; inset:0; background:rgba(135,135,135,0.2); }

/* form — .field positioned at each label's Y; underline lands ~52px below */
.contact-form{ position:absolute; left:0; top:0; width:100%; height:0; }
.field{ position:absolute; left:952px; width:818px; display:block; }
.field span{
  position:absolute; left:0; top:0;
  font-family:'Montserrat'; font-weight:400; font-size:20px; color:var(--white); opacity:.53;
  pointer-events:none; transition:opacity .2s;
}
.field input{
  display:block; margin-top:16px;
  width:818px; height:36px;
  background:transparent; border:none;
  border-bottom:1px solid rgba(255,255,255,0.75);
  font-family:'Montserrat'; font-size:20px; color:var(--white); outline:none;
}
.field input:focus{ border-bottom-color:var(--gold); }
.field input:focus ~ span,
.field input:not(:placeholder-shown) ~ span{ opacity:0; }
.field-name{ top:4208px; }
.field-email{ top:4321px; }
.field-phone{ top:4440px; }
.field-region{ top:4554px; }
.field-msg{ top:4670px; }
.pill-submit{ left:952px; top:4770px; width:148.42px; }
.form-legal{
  position:absolute; left:952px; top:4825px; width:818px;
  font-family:'Montserrat'; font-weight:400; font-size:10px; line-height:normal; color:var(--white); opacity:.53;
}

/* ---------- Footer ---------- */
/* Contacts through footer are all shifted +60px vs. the original mockup-
   matched values (was contacts-h:3222, footer-bar:4099, etc — see git-style
   diff of the numbers below) to restore breathing room that the API/SAE
   section's own +60 shift ate into: .tech-p's declared height:49px doesn't
   match its real wrapped-text height (~73px, confirmed via Range().getBoun
   dingClientRect() — the box's own rect lies about how tall the content
   actually renders), so pushing tech-p down without also pushing Contacts
   left the real paragraph text just ~1px from "Контакты" — found via this
   same measurement technique, not visually (a plain getBoundingClientRect on
   the paragraph itself would have missed it, since it reports the box's
   declared 49px, not the overflowing rendered text). --page-h bumped
   4254->4314 in :root to match, so the scrollable area still reaches the
   (now lower) footer — .page has overflow:hidden and main.js sizes the
   scroll wrapper off this value. */
/* Transform-free marker at the top of the footer region — the scroll-reveal
   in main.js measures progress off this stable point (the logo/texts below
   are translated every frame, so measuring them would feed back on itself). */
.footer-anchor{
  position:absolute; left:0; top:4952px; width:1px; height:1px;
  pointer-events:none;
}
/* Footer plate — darker band that marks the footer zone. Spans from the anchor
   to the page bottom, sits behind the logo/fine print, and rises with them. */
.footer-bar{
  position:absolute; left:0; top:4952px; width:1920px; height:420px;
  background:var(--footer); z-index:0;
  will-change:transform, opacity;
}
/* Big OILRIGHT wordmark (Group (5).png, native 1617x234). Sits above the
   fine print; both rise into view on scroll (opacity/translateY written
   inline by the footer reveal in main.js — no CSS transition, it's scrubbed
   to scroll, not a one-shot). */
.footer-logo{
  position:absolute; left:150px; top:5000px; width:1620px; height:auto;
  z-index:1; pointer-events:none; will-change:transform, opacity;
}
.footer-legal{
  position:absolute; left:150px; top:5292px; width:626px;
  font-family:'Montserrat'; font-weight:400; font-size:10.597px; line-height:normal; color:var(--white); opacity:.66; z-index:1;
  will-change:transform, opacity;
}
.footer-name{
  position:absolute; left:940px; top:5300px;
  font-family:'Montserrat'; font-weight:400; font-size:10.597px; color:var(--white); opacity:.66; z-index:1;
  will-change:transform, opacity;
}
.footer-rights{
  position:absolute; left:1611px; top:5290px;
  font-family:'Montserrat'; font-weight:400; font-size:10.597px; color:var(--white); opacity:.66; z-index:1; white-space:pre-wrap;
  will-change:transform, opacity;
}
.footer-policy{
  position:absolute; left:1553px; top:5316px;
  font-family:'Montserrat'; font-weight:400; font-size:10.597px; color:var(--white); opacity:.66; z-index:1;
  will-change:transform, opacity;
}

/* ============ PRELOADER ============ */
#preloader{
  position:fixed; inset:0; z-index:1000;
  background:var(--bg);
  display:flex; align-items:center; justify-content:center;
  transition:opacity .6s ease, visibility .6s ease;
}
#preloader.hidden{ opacity:0; visibility:hidden; }
.preloader-inner{
  display:flex; flex-direction:column; align-items:center;
  transform:translateY(8px);
}
.preloader-logo{
  width:340px; height:49px; /* keep logo aspect 269.4/38.87 — svg has preserveAspectRatio:none */
  opacity:0;
  transform:scale(.86) translateY(10px);
  filter:drop-shadow(0 10px 30px rgba(0,0,0,0.25));
  animation:logo-in 1s cubic-bezier(.2,.7,.2,1) forwards;
}
.preloader-bar{
  margin-top:44px;
  width:320px; height:4px;
  border-radius:99px;
  background:rgba(255,255,255,0.18);
  overflow:hidden;
  opacity:0;
  animation:bar-appear .6s ease .5s forwards;
}
.preloader-bar-fill{
  display:block; height:100%; width:0%;
  border-radius:99px;
  background:linear-gradient(90deg, #c3a567, #e6cf9a);
  transition:width .3s ease;
}
.preloader-hint{
  display:none;
  margin-top:28px; max-width:420px;
  font-family:'Montserrat','Segoe UI',Arial,sans-serif; font-weight:400;
  font-size:15px; line-height:1.5; text-align:center; color:rgba(255,255,255,0.9);
}
.preloader-hint b{ color:var(--gold); font-weight:600; }

@keyframes logo-in{
  0%{ opacity:0; transform:scale(.86) translateY(10px); }
  60%{ opacity:1; }
  100%{ opacity:1; transform:scale(1) translateY(0); }
}
@keyframes bar-appear{ to{ opacity:1; } }

/* ============ SCROLL REVEAL ============
   Fade + rise + a touch of blur-out — the blur is what pushes this from a
   plain slide-fade into something that reads as "premium"; the expo-out
   curve (cubic-bezier(.16,1,.3,1)) decelerates hard right at the end so it
   still feels crisp/settled rather than mushy despite the added blur. */
.reveal{
  opacity:0; transform:translateY(36px); filter:blur(6px);
  transition:opacity .95s cubic-bezier(.16,1,.3,1), transform .95s cubic-bezier(.16,1,.3,1), filter .95s cubic-bezier(.16,1,.3,1);
  transition-delay:var(--reveal-delay, 0s);
}
.reveal.is-visible{ opacity:1; transform:translateY(0); filter:blur(0); }


/* Same family as .reveal, but a separate class on purpose — .std-h must NOT
   be caught by observeReveals()'s blanket `.reveal` query in main.js (it
   reveals itself via the 'cards:done' event instead, see CARDS/6b in
   main.js). Deliberately lighter/quicker than .reveal, not heavier: this
   text already waits behind the whole cards pin sequence, so its own
   entrance needs to feel prompt, not add another slow beat on top. */
.std-h-gate{
  opacity:0; transform:translateY(8px);
  transition:opacity .16s cubic-bezier(.22,1,.36,1), transform .16s cubic-bezier(.22,1,.36,1);
}
.std-h-gate.is-visible{ opacity:1; transform:translateY(0); }

/* Cards' hidden/rising state is driven entirely by GSAP (see CARDS in
   main.js, gsap.set/timeline) — no CSS class needed here, GSAP writes
   the transform/opacity inline every scrub frame. */

/* ============ HERO STAGED INTRO ============
   After the preloader, the first screen builds up piece by piece
   (canister first, then the copy around it) — see HERO_SEQ in main.js. */
.hero-anim{
  opacity:0; transform:translateY(34px);
  transition:opacity 1.05s ease, transform 1.2s cubic-bezier(.2,.7,.2,1);
  will-change:opacity, transform;
}
.hero-anim.a-bottle{ transform:translateY(34px) scale(.955); }
.hero-anim.a-fade{ transform:none; }            /* watermark / nav — fade only */
.hero-anim.in{ opacity:1; transform:none; }
