/* =========================================================
   VOCAL — cinematic redesign v2
   ========================================================= */

/* ===== Persian brand font (Peyda, as used on vocalphone.com) ===== */
@font-face { font-family:'Peyda'; src:url('assets/fonts/Peyda-Regular.woff') format('woff'); font-weight:400; font-style:normal; font-display:swap; }
@font-face { font-family:'Peyda'; src:url('assets/fonts/Peyda-Medium.woff') format('woff'); font-weight:500; font-style:normal; font-display:swap; }
@font-face { font-family:'Peyda'; src:url('assets/fonts/Peyda-SemiBold.woff') format('woff'); font-weight:600; font-style:normal; font-display:swap; }
@font-face { font-family:'Peyda'; src:url('assets/fonts/Peyda-Bold.woff') format('woff'); font-weight:700; font-style:normal; font-display:swap; }
@font-face { font-family:'Peyda'; src:url('assets/fonts/Peyda-ExtraBold.woff') format('woff'); font-weight:800; font-style:normal; font-display:swap; }
@font-face { font-family:'Peyda'; src:url('assets/fonts/Peyda-Black.woff') format('woff'); font-weight:900; font-style:normal; font-display:swap; }
/* ===== self-hosted Latin webfonts (downloaded from Google Fonts) ===== */
@font-face { font-family:'Cormorant Garamond'; font-style:italic; font-weight:400; font-display:swap; src:url('assets/fonts/cormorantgaramond-400-italic-latin-ext.woff2') format('woff2'); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family:'Cormorant Garamond'; font-style:italic; font-weight:400; font-display:swap; src:url('assets/fonts/cormorantgaramond-400-italic-latin.woff2') format('woff2'); 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; }
@font-face { font-family:'Cormorant Garamond'; font-style:italic; font-weight:500; font-display:swap; src:url('assets/fonts/cormorantgaramond-500-italic-latin-ext.woff2') format('woff2'); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family:'Cormorant Garamond'; font-style:italic; font-weight:500; font-display:swap; src:url('assets/fonts/cormorantgaramond-500-italic-latin.woff2') format('woff2'); 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; }
@font-face { font-family:'Cormorant Garamond'; font-style:italic; font-weight:600; font-display:swap; src:url('assets/fonts/cormorantgaramond-600-italic-latin-ext.woff2') format('woff2'); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family:'Cormorant Garamond'; font-style:italic; font-weight:600; font-display:swap; src:url('assets/fonts/cormorantgaramond-600-italic-latin.woff2') format('woff2'); 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; }
@font-face { font-family:'Great Vibes'; font-style:normal; font-weight:400; font-display:swap; src:url('assets/fonts/greatvibes-400-normal-latin-ext.woff2') format('woff2'); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family:'Great Vibes'; font-style:normal; font-weight:400; font-display:swap; src:url('assets/fonts/greatvibes-400-normal-latin.woff2') format('woff2'); 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; }
@font-face { font-family:'Inter'; font-style:normal; font-weight:400; font-display:swap; src:url('assets/fonts/inter-400-normal-latin-ext.woff2') format('woff2'); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family:'Inter'; font-style:normal; font-weight:400; font-display:swap; src:url('assets/fonts/inter-400-normal-latin.woff2') format('woff2'); 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; }
@font-face { font-family:'Inter'; font-style:normal; font-weight:500; font-display:swap; src:url('assets/fonts/inter-500-normal-latin-ext.woff2') format('woff2'); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family:'Inter'; font-style:normal; font-weight:500; font-display:swap; src:url('assets/fonts/inter-500-normal-latin.woff2') format('woff2'); 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; }
@font-face { font-family:'Inter'; font-style:normal; font-weight:600; font-display:swap; src:url('assets/fonts/inter-600-normal-latin-ext.woff2') format('woff2'); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family:'Inter'; font-style:normal; font-weight:600; font-display:swap; src:url('assets/fonts/inter-600-normal-latin.woff2') format('woff2'); 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; }
@font-face { font-family:'Sora'; font-style:normal; font-weight:400; font-display:swap; src:url('assets/fonts/sora-400-normal-latin-ext.woff2') format('woff2'); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family:'Sora'; font-style:normal; font-weight:400; font-display:swap; src:url('assets/fonts/sora-400-normal-latin.woff2') format('woff2'); 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; }
@font-face { font-family:'Sora'; font-style:normal; font-weight:500; font-display:swap; src:url('assets/fonts/sora-500-normal-latin-ext.woff2') format('woff2'); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family:'Sora'; font-style:normal; font-weight:500; font-display:swap; src:url('assets/fonts/sora-500-normal-latin.woff2') format('woff2'); 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; }
@font-face { font-family:'Sora'; font-style:normal; font-weight:600; font-display:swap; src:url('assets/fonts/sora-600-normal-latin-ext.woff2') format('woff2'); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family:'Sora'; font-style:normal; font-weight:600; font-display:swap; src:url('assets/fonts/sora-600-normal-latin.woff2') format('woff2'); 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; }
@font-face { font-family:'Sora'; font-style:normal; font-weight:700; font-display:swap; src:url('assets/fonts/sora-700-normal-latin-ext.woff2') format('woff2'); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family:'Sora'; font-style:normal; font-weight:700; font-display:swap; src:url('assets/fonts/sora-700-normal-latin.woff2') format('woff2'); 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; }
@font-face { font-family:'Sora'; font-style:normal; font-weight:800; font-display:swap; src:url('assets/fonts/sora-800-normal-latin-ext.woff2') format('woff2'); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family:'Sora'; font-style:normal; font-weight:800; font-display:swap; src:url('assets/fonts/sora-800-normal-latin.woff2') format('woff2'); 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; }
/* ===== Persian font test candidates ===== */
@font-face { font-family:'Vazirmatn'; src:url('assets/fonts/Vazirmatn-Regular.woff2') format('woff2'); font-weight:400; font-display:swap; }
@font-face { font-family:'Vazirmatn'; src:url('assets/fonts/Vazirmatn-Bold.woff2') format('woff2'); font-weight:700; font-display:swap; }
@font-face { font-family:'Vazirmatn'; src:url('assets/fonts/Vazirmatn-ExtraBold.woff2') format('woff2'); font-weight:800; font-display:swap; }
@font-face { font-family:'Sahel'; src:url('assets/fonts/Sahel-Regular.woff2') format('woff2'); font-weight:400; font-display:swap; }
@font-face { font-family:'Sahel'; src:url('assets/fonts/Sahel-Bold.woff2') format('woff2'); font-weight:700; font-display:swap; }
@font-face { font-family:'Shabnam'; src:url('assets/fonts/Shabnam-Regular.woff2') format('woff2'); font-weight:400; font-display:swap; }
@font-face { font-family:'Shabnam'; src:url('assets/fonts/Shabnam-Bold.woff2') format('woff2'); font-weight:700; font-display:swap; }

:root {
  --bg:          #0c0907;
  --bg-2:        #14100c;
  --surface:     #1c1611;
  --surface-2:   #261e16;
  --line:        rgba(212,175,110,0.12);
  --line-2:      rgba(212,175,110,0.26);
  --text:        #f5ebd8;
  --muted:       #a89b7e;
  --dim:         #6e6249;

  --blue:        #d4af37;
  --blue-br:     #f0d088;
  --cyan:        #e8c87a;
  --violet:      #b89260;
  --green:       #d4af37;
  --red:         #d4af37;

  --gold:        #d4af37;
  --gold-br:     #f0d088;
  --gold-deep:   #8b6f2a;

  --grad: linear-gradient(120deg, #8b6f2a 0%, #f0d088 22%, #fff6d8 40%, #d4af37 58%, #8b6f2a 82%, #caa24a 100%);
  --grad-soft: linear-gradient(135deg, rgba(240,208,136,.18), rgba(139,111,42,.10));
  --radius: 22px;
  --section-y: clamp(96px, 11vw, 168px);
  --ease: cubic-bezier(.16,.84,.30,1);
  --ease-out: cubic-bezier(.22,1,.36,1);

  --font-display: 'Sora','Peyda',system-ui,sans-serif;
  --font-body:    'Inter','Peyda',system-ui,sans-serif;
  --font-accent:  'Cormorant Garamond','Playfair Display',serif;
}
:root { --fa-font: 'Shabnam'; }   /* Persian font */
html[dir="rtl"] {
  --font-display: var(--fa-font,'Vazirmatn'),'Sora',system-ui,sans-serif;
  --font-body:    var(--fa-font,'Vazirmatn'),'Inter',system-ui,sans-serif;
}

* { margin:0; padding:0; box-sizing:border-box; }
html { -webkit-text-size-adjust:100%; }
section[id], #home { scroll-margin-top: 90px; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
body.is-loading { overflow: hidden; height: 100vh; }
body.is-locked  { overflow: hidden; }

a { color: inherit; text-decoration: none; }
img { display:block; max-width:100%; }

/* keyboard-only "skip to content" link */
.skip-link {
  position: fixed; inset-inline-start: 16px; top: -60px; z-index: 5000;
  padding: 10px 18px; border-radius: 999px;
  background: #0c0907; color: #f0d088; border: 1px solid rgba(240,208,136,.5);
  font-size: 14px; letter-spacing: .04em;
  transition: top .25s ease;
}
.skip-link:focus-visible { top: 14px; outline: 2px solid #f0d088; outline-offset: 2px; }
button { font: inherit; color: inherit; }
::selection { background: rgba(212,175,110,.30); color:#fff6d8; text-shadow:none; }
::-moz-selection { background: rgba(212,175,110,.30); color:#fff6d8; }

.gradient-text {
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}

/* =========================================================
   Preloader
   ========================================================= */
.preloader {
  position: fixed; inset: 0; z-index: 3000;
  background:
    radial-gradient(1100px 640px at 50% 40%, rgba(240,208,136,.07), transparent 66%),
    var(--bg);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 30px;
  transition: opacity .7s var(--ease), visibility .7s;
}
.preloader.is-done { opacity: 0; visibility: hidden; pointer-events: none; }

/* faint rotating halo behind the logo for life */
.preloader::before {
  content: ""; position: absolute;
  width: 460px; height: 460px; border-radius: 50%;
  background: conic-gradient(from 0deg,
    transparent 0deg, rgba(240,208,136,.16) 60deg, transparent 140deg,
    transparent 220deg, rgba(212,175,110,.12) 290deg, transparent 360deg);
  filter: blur(30px);
  animation: haloSpin 7s linear infinite;
  pointer-events: none;
}
@keyframes haloSpin { to { transform: rotate(360deg); } }

.preloader__stage {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 18px;
}

/* fullscreen video intro loader */
.preloader__video {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  object-fit: cover; display: block;
  opacity: 1; transition: opacity .7s ease;
}

/* ===== START gate: black screen + glowing gold button (home page) ===== */
.preloader__start { display: none; }
.preloader.await-start .preloader__video { opacity: 0; }
.preloader.await-start .preloader__overlay { display: none; }
.preloader.await-start .preloader__start {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 26px; position: absolute; inset: 0; z-index: 3; background: #000;
  animation: gateIn .6s ease both;
}
@keyframes gateIn { from { opacity: 0; } to { opacity: 1; } }

/* attractive animated START — shimmering gold "ARE U READY?" + pulsing play */
.preloader.await-start .preloader__start::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(440px 440px at 50% 44%, rgba(240,208,136,.12), transparent 70%);
  animation: auraBreathe 5s ease-in-out infinite;
}
@keyframes auraBreathe {
  0%, 100% { opacity: .5; transform: scale(1); }
  50%      { opacity: 1; transform: scale(1.14); }
}
.start-cta {
  position: relative; z-index: 1; isolation: isolate;
  cursor: pointer; border: none; background: none; padding: 0;
  display: flex; flex-direction: column; align-items: center; gap: 36px;
  animation: ctaIn .85s cubic-bezier(.22,1,.36,1) both;
}
@keyframes ctaIn {
  from { opacity: 0; transform: translateY(22px) scale(.95); }
  to   { opacity: 1; transform: none; }
}
/* the real VOCAL logo rendered as a moving GOLD gradient (theme gold + shine) */
/* NOTE: do NOT add `filter` here — mask + filter on the same element renders
   the masked element blank in Chromium. The ambient glow comes from the
   .preloader__start::before aura behind it. */
.start-cta__logo {
  width: min(560px, 86vw); aspect-ratio: 512 / 204;
  background: linear-gradient(100deg, #8b6f2a 0%, #caa24a 20%, #f0d088 38%, #fff6d8 50%, #f0d088 62%, #caa24a 80%, #8b6f2a 100%);
  background-size: 250% 100%;
  -webkit-mask: url(assets/logo.png) center / contain no-repeat;
          mask: url(assets/logo.png) center / contain no-repeat;
  animation: ctaShine 3.4s linear infinite, ctaFloat 5.5s ease-in-out infinite;
}
@keyframes ctaShine { 0% { background-position: 175% 0; } 100% { background-position: -175% 0; } }
@keyframes ctaFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-16px); } }
.start-cta__ring {
  position: relative; width: 96px; height: 96px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1.5px solid rgba(240,208,136,.55);
  box-shadow: 0 0 28px rgba(240,208,136,.22), inset 0 0 20px rgba(240,208,136,.08);
  transition: transform .4s var(--ease), box-shadow .4s ease;
}
.ring-ico { width: 48px; height: 48px; overflow: visible; }
.ring-ico .ph {
  transform-box: fill-box; transform-origin: 50% 50%;
  animation: phoneRing 2.2s ease-in-out infinite, phoneGlint 2.2s ease-in-out infinite;
}
@keyframes phoneGlint {
  0%, 48%, 100% { filter: drop-shadow(0 0 6px rgba(240,208,136,.5))  brightness(1); }
  60%           { filter: drop-shadow(0 0 16px rgba(255,247,216,.95)) brightness(1.4); }
  74%           { filter: drop-shadow(0 0 8px rgba(240,208,136,.6))   brightness(1.12); }
}
@keyframes phoneRing {
  0%, 55%, 92%, 100% { transform: rotate(0deg); }
  60% { transform: rotate(-15deg); }
  65% { transform: rotate(13deg); }
  70% { transform: rotate(-11deg); }
  75% { transform: rotate(9deg); }
  80% { transform: rotate(-6deg); }
  86% { transform: rotate(3deg); }
}
.ring-ico .w {
  fill: none; stroke: #f0d088; stroke-width: 2; stroke-linecap: round;
  opacity: 0; filter: drop-shadow(0 0 5px rgba(240,208,136,.6));
}
.ring-ico .w1 { animation: ringWave 2.2s ease-out infinite; }
.ring-ico .w2 { animation: ringWave 2.2s ease-out infinite .14s; }
@keyframes ringWave { 0%, 50% { opacity: 0; } 60% { opacity: 1; } 88% { opacity: 0; } 100% { opacity: 0; } }
/* expanding pulse rings around the phone */
.start-cta__ring::before, .start-cta__ring::after {
  content: ""; position: absolute; inset: -1px; border-radius: 50%;
  border: 1.5px solid rgba(240,208,136,.5); z-index: -1;
  animation: ctaPulse 2.6s ease-out infinite;
}
.start-cta__ring::after { animation-delay: 1.3s; }
@keyframes ctaPulse { 0% { transform: scale(1); opacity: .7; } 100% { transform: scale(2.15); opacity: 0; } }
/* no filter on hover — would blank the masked logo in Chromium */
.start-cta:hover .start-cta__logo { animation-duration: 1.8s, 5.5s; }
.start-cta:hover .start-cta__ring {
  transform: scale(1.09);
  box-shadow: 0 0 44px rgba(240,208,136,.45), inset 0 0 26px rgba(240,208,136,.14);
}

/* gold cube loading bar (real video buffering, no %), bottom of screen */
.start-loadwrap {
  position: absolute; left: 0; right: 0; bottom: 6vh; z-index: 4;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.start-loading {
  font-family: 'Great Vibes', 'Cormorant Garamond', cursive;
  font-size: clamp(28px, 4.4vw, 44px); line-height: 1;
  color: #f0d088; letter-spacing: .02em;
  text-shadow: 0 2px 18px rgba(240,208,136,.45);
  animation: loadingBlink 1.5s ease-in-out infinite;
}
@keyframes loadingBlink { 0%, 100% { opacity: .2; } 50% { opacity: 1; } }
.start-load {
  display: flex; gap: 5px; justify-content: center; align-items: center; direction: ltr;
}
.start-load__seg {
  width: 11px; height: 11px; border-radius: 2px;
  background: rgba(240,208,136,.12);
  box-shadow: inset 0 0 0 1px rgba(240,208,136,.12);
  transition: background .3s ease, box-shadow .3s ease, transform .3s ease;
}
.start-load__seg.is-on {
  background: linear-gradient(158deg, #f7e6b0, #caa24a 55%, #8b6f2a);
  box-shadow: 0 0 10px rgba(240,208,136,.6);
  transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
  .start-cta, .start-cta__logo, .ring-ico .ph, .ring-ico .w,
  .start-cta__ring::before, .start-cta__ring::after, .start-loading,
  .preloader.await-start .preloader__start::before { animation: none; }
  .ring-ico .w { opacity: 1; }
  .start-loading { opacity: .9; }
  .start-load__seg { transition: none; }
}
/* overlay holds the % + bar on top of the video */
.preloader__overlay {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
  display: flex; flex-direction: column; align-items: center; gap: 16px;
  padding: 0 24px 8vh;
  background: linear-gradient(to top, rgba(0,0,0,.62) 0%, rgba(0,0,0,.28) 45%, transparent 100%);
  pointer-events: none;
}

/* ===== two loaders: video intro (first visit) vs classic logo (other pages) ===== */
/* default = video intro is shown, classic is hidden */
.preloader__classic { display: none; }
/* html.no-intro = show the classic gold-logo loader, hide the video */
html.no-intro .preloader__video,
html.no-intro .preloader__overlay { display: none !important; }
html.no-intro .preloader__classic {
  display: flex; flex-direction: column; align-items: center; gap: 30px;
  position: relative; z-index: 1;
}
/* classic loader keeps the original small, thin, centred % + bar
   (double class = higher specificity so it always wins over the video counter) */
.preloader__count.preloader__count--mini {
  font-size: 13px; font-weight: 700; color: var(--blue-br);
  letter-spacing: .2em; text-shadow: none;
}
.preloader__count.preloader__count--mini i { color: var(--dim); font-size: 1em; font-weight: 700; margin: 0; letter-spacing: .2em; vertical-align: baseline; }

/* the real VOCAL wordmark, tinted warm gold, with a moving shine sweep */
.preloader__logo {
  position: relative;
  width: min(280px, 62vw);
  animation: logoRise 1.1s var(--ease) both;
  filter: drop-shadow(0 8px 30px rgba(240,208,136,.40));
}
.preloader__logo img {
  width: 100%; height: auto; display: block;
  /* recolour the white wordmark to champagne gold */
  filter: sepia(1) saturate(2.6) hue-rotate(2deg) brightness(1.04) contrast(1.02);
}
.preloader__logo::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(105deg,
    transparent 38%, rgba(255,247,207,.95) 50%, transparent 62%);
  background-size: 250% 100%;
  -webkit-mask-image: url(assets/logo.png);
          mask-image: url(assets/logo.png);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: contain;     mask-size: contain;
  mix-blend-mode: screen;
  animation: goldShine 2.6s linear infinite;
}
@keyframes goldShine {
  0%   { background-position: 130% 0; }
  100% { background-position: -130% 0; }
}
@keyframes logoRise {
  from { opacity: 0; transform: translateY(16px) scale(.94); filter: blur(8px); }
  to   { opacity: 1; transform: none; filter: none; }
}

.preloader__tagline {
  font-family: var(--font-accent); font-style: italic; font-weight: 500;
  font-size: 16px; letter-spacing: .03em; color: rgba(245,238,222,.92);
  text-shadow: 0 2px 16px rgba(0,0,0,.75);
  opacity: 0; animation: preFade 1s var(--ease) .45s both;
}
html[dir="rtl"] .preloader__tagline { font-family: var(--font-body); font-style: normal; }
@keyframes preFade { from { opacity: 0; transform: translateY(9px); } to { opacity: .82; transform: none; } }

.preloader__count {
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(15px, 2.2vw, 20px); line-height: 1;
  color: rgba(255,255,255,.95); letter-spacing: .24em;
  text-shadow: 0 2px 14px rgba(0,0,0,.65);
}
.preloader__count i {
  color: var(--blue-br); font-style: normal;
  font-size: .72em; font-weight: 400; margin-inline-start: 3px;
  letter-spacing: .12em; vertical-align: baseline;
}
.preloader__bar {
  position: relative;
  width: min(300px, 66vw); height: 2px; border-radius: 2px;
  background: rgba(212,175,110,.14); overflow: hidden;
}
.preloader__bar span {
  display: block; height: 100%; width: 0%;
  background: linear-gradient(90deg, #8b6f2a, #f0d088);
  box-shadow: 0 0 14px rgba(240,208,136,.7);
  transition: width .25s ease;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* =========================================================
   Custom cursor
   ========================================================= */
.cursor { display: none; }
body.has-cursor .cursor { display: block; transition: opacity .2s ease; }
/* fade the cursor out when the mouse leaves the window so it never sticks at an edge */
body.cursor-out .cursor { opacity: 0; }
body.has-cursor, body.has-cursor * { cursor: none !important; }
.cursor__dot, .cursor__ring {
  position: fixed; top: 0; left: 0; z-index: 4000;
  border-radius: 50%; pointer-events: none;
  transform: translate(-50%,-50%);
}
.cursor__dot {
  width: 6px; height: 6px; background: var(--blue-br);
}
.cursor__ring {
  width: 38px; height: 38px;
  border: 1px solid rgba(255,255,255,.45);
  display: grid; place-items: center;
  transition: width .3s var(--ease), height .3s var(--ease),
              background .3s var(--ease), border-color .3s var(--ease);
}
.cursor__label {
  font-family: var(--font-display); font-size: 9px; font-weight: 700;
  letter-spacing: .14em; opacity: 0; transition: opacity .25s;
  color: #06121f;
}
body[data-cursor-state="hover"] .cursor__ring {
  width: 58px; height: 58px;
  background: rgba(255,255,255,.14); border-color: var(--blue-br);
}
body[data-cursor-state="view"] .cursor__ring,
body[data-cursor-state="read"] .cursor__ring {
  width: 74px; height: 74px;
  background: var(--blue-br); border-color: var(--blue-br);
}
body[data-cursor-state="view"] .cursor__label,
body[data-cursor-state="read"] .cursor__label { opacity: 1; }
body[data-cursor-state="view"] .cursor__dot,
body[data-cursor-state="read"] .cursor__dot { opacity: 0; }

/* =========================================================
   Scroll progress
   ========================================================= */
.scroll-progress {
  position: fixed; top: 0; left: 0; height: 4px; width: 0%;
  background: var(--grad); z-index: 1400;
  box-shadow: 0 0 16px rgba(255,255,255,.7);
}
.scroll-progress::after {
  content: ""; position: absolute; right: -1px; top: 50%; transform: translateY(-50%);
  width: 11px; height: 11px; border-radius: 50%;
  background: radial-gradient(circle, #fff6d8 0%, #f0d088 55%, transparent 72%);
  box-shadow: 0 0 16px 3px rgba(240,208,136,.95);
}

/* =========================================================
   Ambient background
   ========================================================= */
.ambient { position: fixed; inset: 0; z-index: -2; overflow: hidden; }
.orb {
  position: absolute; border-radius: 50%;
  filter: blur(58px); opacity: .5;
  will-change: auto;
}
.orb--1 { width: 540px; height: 540px; top: -160px; left: -140px;
  background: radial-gradient(circle, rgba(240,208,136,.55), transparent 70%); }
.orb--2 { width: 640px; height: 640px; top: 44%; right: -240px;
  background: radial-gradient(circle, rgba(212,175,110,.40), transparent 70%); }
.orb--3 { width: 520px; height: 520px; bottom: -200px; left: 30%;
  background: radial-gradient(circle, rgba(184,146,96,.42), transparent 70%); }
.ambient__grid {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(255,255,255,.022) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.022) 1px, transparent 1px);
  background-size: 66px 66px;
  mask-image: radial-gradient(circle at 50% 28%, #000, transparent 75%);
}
.grain {
  position: absolute; inset: 0; opacity: .38; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/></svg>");
}

/* =========================================================
   Shared
   ========================================================= */
.section { padding: var(--section-y) 6vw; max-width: 1340px; margin: 0 auto; }
.section__head { max-width: 720px; margin: 0 auto 64px; text-align: center; }

.eyebrow {
  display: inline-block;
  font-family: var(--font-display);
  font-size: 11px; font-weight: 600;
  letter-spacing: .34em; text-indent: .34em; text-transform: uppercase;
  color: var(--blue-br);
  padding: 7px 16px; border-radius: 100px;
  border: 1px solid rgba(255,255,255,.30);
  background: rgba(255,255,255,.07);
  margin-bottom: 22px;
}
.section__title {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2rem, 4.6vw, 3.5rem);
  line-height: 1.08; letter-spacing: -.025em;
}
.section__sub {
  margin-top: 20px; color: var(--muted);
  font-size: clamp(1rem,1.3vw,1.12rem);
}

/* mask reveal */
.mask { display: block; overflow: hidden; padding-block: .14em; margin-block: -.06em; }
.mask__in {
  display: block; transform: translateY(110%);
  transition: transform 1.05s var(--ease); will-change: transform;
}
.mask__in.in { transform: none; }
[data-anim="fade"] {
  opacity: 0; transform: translateY(38px);
  transition: opacity .9s var(--ease), transform .9s var(--ease); will-change: transform;
}
[data-anim="fade"].in { opacity: 1; transform: none; }

/* fallbacks: never leave content stranded if JS/animation is unavailable */
.no-gsap .mask__in,
.no-gsap [data-anim="fade"] { transform: none; opacity: 1; }

/* =========================================================
   Buttons
   ========================================================= */
.btn {
  --pad: 15px 30px;
  font-family: var(--font-display); font-weight: 600; font-size: 15px;
  padding: var(--pad); border-radius: 100px;
  border: 1px solid transparent;
  display: inline-flex; align-items: center; gap: 10px;
  cursor: pointer; white-space: nowrap;
  transition: transform .35s var(--ease), box-shadow .35s var(--ease),
              background .35s var(--ease), border-color .35s var(--ease);
}
.btn--sm { --pad: 11px 22px; font-size: 14px; }
.btn--lg { --pad: 18px 38px; font-size: 16px; }
.btn--solid {
  position: relative; overflow: hidden;
  background: var(--grad); background-size: 160% 160%; color: #1a1208;
  box-shadow: 0 14px 40px -12px rgba(212,175,110,.65), inset 0 1px 0 rgba(255,231,168,.6);
}
.btn--solid::after {
  content:""; position:absolute; top:0; bottom:0; left:-120%; width:60%;
  transform:skewX(-18deg); pointer-events:none;
  background:linear-gradient(90deg, transparent, rgba(255,246,216,.55), transparent);
}
.btn--solid:hover {
  transform: translateY(-3px);
  box-shadow: 0 26px 62px -12px rgba(240,208,136,.92), inset 0 1px 0 rgba(255,231,168,.6);
  background-position: 100% 50%;
}
.btn--solid:hover::after { animation: btnSheen .9s var(--ease); }
@keyframes btnSheen { to { left: 160%; } }
.btn--line {
  background: rgba(212,175,110,.04);
  border-color: var(--line-2); color: var(--text);
}
.btn--line:hover { transform: translateY(-3px); border-color: var(--blue-br); background: rgba(212,175,110,.12); }
.btn:active { transform: translateY(-1px) scale(.985); }

/* =========================================================
   Navigation
   ========================================================= */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
  padding: 20px 6vw;
  transition: padding .4s var(--ease), background .4s var(--ease),
              border-color .4s var(--ease);
  border-bottom: 1px solid transparent;
}
.nav.is-scrolled {
  padding: 12px 6vw;
  background: rgba(8,9,12,.82);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  backdrop-filter: blur(10px) saturate(140%);
  border-bottom-color: var(--line);
}
.nav__inner {
  max-width: 1340px; margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between;
}
.nav__logo {
  position: relative; z-index: 60;
  display: inline-block; line-height: 0;
  animation: navFloat 4s ease-in-out infinite;
}
@keyframes navFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }
.nav__logo-img {
  height: 40px; width: auto;
  transform-origin: center;
  transition: transform .45s var(--ease), filter .45s ease;
  will-change: transform;
}
/* hover: refined lift — gentle scale, warm glow, and a gold shine that
   sweeps across the wordmark itself (masked by the logo) */
.nav__logo::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(110deg,
    transparent 32%, #fff6d8 46%, #f0d088 50%, #fff6d8 54%, transparent 68%);
  background-size: 240% 100%; background-position: 200% 0;
  -webkit-mask: url(assets/logo.png) center / contain no-repeat;
          mask: url(assets/logo.png) center / contain no-repeat;
  transform-origin: center;
  opacity: 0; transition: opacity .25s ease, transform .45s var(--ease);
}
.nav__logo:hover .nav__logo-img {
  transform: scale(1.07);
  filter: drop-shadow(0 6px 18px rgba(240,208,136,.55));
}
.nav__logo:hover::after {
  opacity: 1; transform: scale(1.07);
  animation: navShine 1.15s ease .05s infinite;
}
@keyframes navShine { from { background-position: 200% 0; } to { background-position: -160% 0; } }
@media (prefers-reduced-motion: reduce) {
  .nav__logo { animation: none; }
  .nav__logo:hover .nav__logo-img { transform: scale(1.05); }
  .nav__logo:hover::after { animation: none; opacity: .9; background-position: 50% 0; }
}
.nav__links { display: flex; gap: 6px; }
.nav__links a {
  position: relative;
  font-family: var(--font-display); font-size: 14px; font-weight: 500;
  color: var(--muted); padding: 9px 16px; border-radius: 100px;
  transition: color .25s, background .25s;
}
.nav__links a::after {
  content:""; position:absolute; inset-inline:16px auto; bottom:4px;
  width:calc(100% - 32px); height:1.5px; background:var(--grad);
  transform:scaleX(0); transform-origin:inline-start;
  transition:transform .38s var(--ease);
}
.nav__links a:hover { color: var(--text); background: transparent; }
.nav__links a:hover::after, .nav__links a.is-current::after { transform:scaleX(1); }
.nav__links a.is-current { color: var(--blue-br); }
.nav__actions { display: flex; align-items: center; gap: 14px; }
.lang {
  display: flex; align-items: center; gap: 6px;
  background: rgba(255,255,255,.04);
  border: 1px solid var(--line); border-radius: 100px;
  padding: 8px 14px; cursor: pointer;
  font-family: var(--font-display); font-size: 13px; font-weight: 700;
  transition: background .25s, border-color .25s;
}
.lang:hover { background: rgba(255,255,255,.07); border-color: var(--line-2); }
.lang__opt { color: var(--dim); transition: color .25s; }
.lang__opt.is-active { color: var(--red); }
.lang__sep { color: var(--line-2); }
.nav__burger {
  display: none; flex-direction: column; gap: 6px;
  background: none; border: none; cursor: pointer; padding: 6px;
}
.nav__burger span {
  width: 24px; height: 2px; background: var(--text); border-radius: 2px;
  transition: transform .35s var(--ease), opacity .25s;
}
.nav__burger.is-open span:nth-child(1){ transform: translateY(8px) rotate(45deg); }
.nav__burger.is-open span:nth-child(2){ transform: translateY(-8px) rotate(-45deg); }
.nav__mobile-backdrop {
  position: fixed; inset: 0; z-index: 980;
  background: rgba(4,5,7,.6); backdrop-filter: blur(4px);
  opacity: 0; visibility: hidden; transition: opacity .35s, visibility .35s;
}
.nav__mobile-backdrop.is-open { opacity: 1; visibility: visible; }

/* =========================================================
   Hero — full-bleed product film
   ========================================================= */
.hero {
  position: relative; min-height: 100vh;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 140px 6vw 96px;
  overflow: hidden;
}
.hero__video-wrap { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
.hero__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  will-change: transform;
}
.hero__scrim {
  position: absolute; inset: 0;
  background:
    radial-gradient(120% 80% at 50% 100%, rgba(139,111,42,.10), transparent 55%),
    radial-gradient(140% 100% at 50% 40%, transparent 55%, rgba(0,0,0,.55)),
    linear-gradient(to top, rgba(6,5,3,.97) 0%, rgba(8,6,3,.72) 30%, rgba(8,6,3,.34) 62%, rgba(6,5,3,.55) 100%),
    linear-gradient(to right, rgba(0,0,0,.85), transparent 60%);
}
.hero__content {
  position: relative; z-index: 2;
  max-width: 1340px; width: 100%; margin: 0 auto;
}
.badge {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--font-display); font-size: 12.5px; font-weight: 600;
  letter-spacing: .08em; color: var(--blue-br);
  padding: 9px 18px; border-radius: 100px;
  border: 1px solid var(--line-2);
  background: rgba(212,175,110,.08); backdrop-filter: blur(8px);
  box-shadow: inset 0 1px 0 rgba(255,231,168,.18);
}
.badge__dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--cyan);
  box-shadow: 0 0 12px var(--cyan);
  animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.4;transform:scale(.7)} }

.hero__title {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2.8rem, 7vw, 6rem);
  line-height: .98; letter-spacing: -.045em;
  margin: 26px 0 24px;
}
.hero__title .em {
  font-family: var(--font-accent); font-style: italic; font-weight: 500;
  letter-spacing: .05em; padding-inline: .08em;
}
.gradient-text.em {
  background: linear-gradient(115deg, #f3d488 0%, #ecc25c 42%, #d4af37 72%, #a8842f 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
/* Persian has no italic serif — keep emphasis upright in the Persian font */
html[dir="rtl"] .em {
  font-family: var(--font-display); font-style: normal; font-weight: 800;
  letter-spacing: -.02em; padding-inline: 0;
}
.hero__sub {
  color: #cdcdd2; max-width: 460px;
  font-size: clamp(1rem,1.35vw,1.18rem);
}
.hero__cta { display: flex; gap: 15px; margin-top: 32px; flex-wrap: wrap; }
.hero__stats { display: flex; gap: 30px; margin-top: 48px; flex-wrap: wrap; }
.hstat { position: relative; }
.hstat::after {
  content: ""; position: absolute; top: 4px; bottom: 4px;
  inset-inline-end: -15px; width: 1px; background: var(--line);
}
.hstat:last-child::after { display: none; }
.hstat__n {
  display: block; font-family: var(--font-display);
  font-weight: 800; font-size: clamp(2.1rem,3.4vw,2.9rem); line-height: 1;
  color: #f0d088; /* solid-gold fallback; the odometer digits carry the gradient (see .odo span rule) */
}
.hstat__l { font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--muted); margin-top: 8px; display: block; }

.hero__scroll {
  position: absolute; bottom: 26px; left: 50%; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  font-family: var(--font-display); font-size: 11px;
  letter-spacing: .2em; text-transform: uppercase; color: var(--dim);
}
.hero__scroll-dot {
  width: 22px; height: 36px; border-radius: 12px;
  border: 1px solid var(--line-2); position: relative;
}
.hero__scroll-dot::after {
  content: ""; position: absolute; top: 7px; left: 50%; transform: translateX(-50%);
  width: 4px; height: 7px; border-radius: 3px; background: var(--blue-br);
  animation: scrolldot 1.7s var(--ease) infinite;
}
@keyframes scrolldot { 0%{opacity:0;transform:translate(-50%,0)} 40%{opacity:1} 80%{opacity:0;transform:translate(-50%,12px)} }

/* =========================================================
   Marquee
   ========================================================= */
.marquee {
  border-block: 1px solid var(--line);
  background: rgba(255,255,255,.018);
  padding: 11px 0; overflow: hidden;
  direction: ltr; /* keep overflow origin on the left so the loop stays seamless in RTL too */
}
.marquee__track {
  display: flex; align-items: center; gap: 24px; width: max-content;
  direction: ltr; /* keep loop identical in RTL (Persian) */
  will-change: transform;
  animation: marquee-loop 38s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
@keyframes marquee-loop {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; }
}
.marquee__item { display: inline-flex; align-items: center; gap: 11px; cursor: default; }
.marquee__img {
  height: 34px; width: auto; object-fit: contain;
  filter: drop-shadow(0 4px 9px rgba(0,0,0,.55));
  transition: transform .35s var(--ease);
}
.marquee__item:hover .marquee__img { transform: translateY(-3px) scale(1.05); }
.marquee__name {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(.72rem, 1.15vw, 1rem); letter-spacing: .04em;
  color: rgba(245,235,216,.22); white-space: nowrap;
  transition: color .3s var(--ease);
}
.marquee__item:hover .marquee__name { color: var(--gold-br); }

/* =========================================================
   Scroll-telling reveal
   ========================================================= */
.reveal { position: relative; min-height: 100vh; overflow: hidden; }

/* one continuous gold-on-black backdrop spanning manifesto + reveal + film.
   background-attachment:fixed anchors the image to the viewport, so all three
   sections share a single seamless backdrop (no joins between them). */
.goldband { position: relative; isolation: isolate; }
/* the gold backdrop is a SEPARATE layer that fades to transparent at its top &
   bottom edges (via mask), so the shared ambient background shows through there
   and the band dissolves seamlessly into the neighbouring sections instead of
   cutting to a different colour */
.goldband::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(rgba(12,9,7,.30), rgba(12,9,7,.30)),
    url(assets/reveal-bg.webp) center center / cover fixed;
  -webkit-mask: linear-gradient(to bottom, transparent 0, #000 210px, #000 calc(100% - 270px), transparent 100%);
          mask: linear-gradient(to bottom, transparent 0, #000 210px, #000 calc(100% - 270px), transparent 100%);
}
@media (max-width: 760px) {
  /* iOS can't render fixed cover backgrounds — fall back to a scrolling one */
  .goldband::after { background-attachment: scroll, scroll; }
}
.reveal__sticky {
  position: relative; width: 100%; min-height: 100vh; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(18px, 4vh, 48px); padding: 10vh 6vw;
}
.reveal__aura {
  position: absolute; top: 54%; left: 50%; transform: translate(-50%, -50%);
  width: 62vmin; height: 62vmin; border-radius: 50%;
  background: radial-gradient(circle, rgba(240,208,136,.16), transparent 70%);
  filter: blur(18px); pointer-events: none; z-index: 1;
}
.reveal__head { position: relative; text-align: center; z-index: 3; }
.reveal__title { font-family: var(--font-display); font-weight: 800; font-size: clamp(2rem, 5vw, 4rem); line-height: 1.05; margin-top: 10px; }
.reveal__phone {
  position: relative; z-index: 2;
  height: min(52vh, 480px); width: auto; object-fit: contain;
  filter: drop-shadow(0 40px 80px rgba(0,0,0,.6));
  will-change: transform;
}
.reveal__spec {
  position: absolute; z-index: 3;
  display: flex; flex-direction: column; gap: 2px;
  padding: 14px 18px; border-radius: 14px;
  background: rgba(20,16,9,.6); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border: 1px solid rgba(240,208,136,.22);
  box-shadow: 0 18px 50px rgba(0,0,0,.5);
  will-change: transform, opacity;
}
.reveal__spec-v { font-family: var(--font-display); font-weight: 800; font-size: clamp(1.1rem, 2vw, 1.6rem); color: #f0d088; }
.reveal__spec-l { font-size: 13px; color: var(--muted); letter-spacing: .04em; }
.reveal__spec--tl { top: 27vh; inset-inline-start: 8vw; }
.reveal__spec--tr { top: 31vh; inset-inline-end: 8vw; }
.reveal__spec--bl { bottom: 22vh; inset-inline-start: 10vw; }
.reveal__spec--br { bottom: 18vh; inset-inline-end: 10vw; }
@media (max-width: 760px) {
  .reveal, .reveal__sticky { min-height: 88vh; }
  .reveal__phone { height: 44vh; }
  .reveal__spec { padding: 10px 12px; }
  .reveal__spec-l { font-size: 11px; }
  .reveal__spec--tl { top: 25vh; inset-inline-start: 4vw; }
  .reveal__spec--tr { top: 25vh; inset-inline-end: 4vw; }
  .reveal__spec--bl { bottom: 15vh; inset-inline-start: 4vw; }
  .reveal__spec--br { bottom: 15vh; inset-inline-end: 4vw; }
}
/* homepage hero: use the SMALL viewport height on mobile so bottom-aligned
   content isn't pushed under the address bar / below the fold */
@media (max-width: 760px) {
  .hero { min-height: 100svh; padding: 108px 6vw 84px; }
}
.marquee__track .dot { color: var(--blue-br); font-size: 1rem; }

/* =========================================================
   Manifesto
   ========================================================= */
.manifesto {
  max-width: 1100px; margin: 0 auto;
  padding: var(--section-y) 6vw; text-align: center;
}
.manifesto__eyebrow {
  font-family: var(--font-display); font-size: 11px; font-weight: 600;
  letter-spacing: .34em; text-indent: .34em; text-transform: uppercase;
  color: var(--blue-br); margin-bottom: 34px;
}
.manifesto__text {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.9rem, 5vw, 4rem);
  line-height: 1.08; letter-spacing: -.035em;
  display: flex; flex-wrap: wrap; gap: .16em; justify-content: center;
}
.manifesto__text .word { display: inline-block; }
.no-gsap .manifesto__text .word { opacity: 1 !important; }

/* =========================================================
   Showcase — flagship panels
   ========================================================= */
.showcase { position: relative; padding: 70px 0 30px; }
.showcase__head {
  text-align: center; max-width: 720px;
  margin: 0 auto 10px; padding: 0 6vw;
}
.showcase__head .section__title { margin-top: 16px; }
.show-panel {
  position: relative;
  min-height: 100vh;
  display: grid; grid-template-columns: 1fr 1fr;
  align-items: center; gap: 30px;
  max-width: 1340px; margin: 0 auto;
  padding: 70px 6vw;
}
.show-panel:nth-child(even) .show-panel__visual { order: 2; }
.show-panel__visual { position: relative; display: grid; place-items: center; perspective: 1400px; }
.show-panel__num {
  position: absolute; top: -10%; inset-inline-start: -6%;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(7rem, 17vw, 15rem); line-height: .8;
  color: rgba(255,255,255,.045); pointer-events: none; z-index: 0;
}
.show-panel__glow {
  position: absolute; width: 84%; height: 76%; border-radius: 50%;
  filter: blur(78px); opacity: .7; z-index: 0;
}
.show-panel__img {
  position: relative; z-index: 1; width: min(440px, 88%);
  filter: drop-shadow(0 48px 58px rgba(0,0,0,.7));
  transform-style: preserve-3d; will-change: transform;
}
.show-panel__info { position: relative; max-width: 470px; }
.show-panel:nth-child(even) .show-panel__info { margin-inline-start: auto; }
.show-panel__cat {
  font-family: var(--font-display); font-size: 11px; font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--accent, var(--blue-br));
}
.show-panel__name {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2.4rem, 5vw, 3.8rem);
  line-height: 1.03; letter-spacing: -.03em; margin: 10px 0 8px;
}
.show-panel__tag { color: var(--muted); font-size: 1.05rem; margin-bottom: 26px; }
.show-panel__specs {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 26px;
}
.spec-chip {
  padding: 14px 16px; border-radius: 14px;
  background: rgba(255,255,255,.03); border: 1px solid var(--line);
}
.spec-chip__l {
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--dim); display: block; margin-bottom: 4px;
}
.spec-chip__v { font-family: var(--font-display); font-weight: 600; font-size: 14px; }

/* technical spec values read left-to-right even in RTL */
.spec-chip__v, .model__key-v, .model__sheet-v,
.show-panel__name, .model__name {
  direction: ltr;
}
html[dir="rtl"] .model__key-v,
html[dir="rtl"] .model__sheet-v { text-align: start; }

/* =========================================================
   Cinematic video band
   ========================================================= */
.filmband { max-width: 1340px; margin: 0 auto; padding: 30px 6vw 60px; }
.filmband__frame {
  position: relative; width: 100%; max-width: 100%; border-radius: 28px; overflow: hidden;
  border: 1px solid rgba(212,175,110,.22);
  aspect-ratio: 16 / 7; min-height: 320px;
  box-shadow: 0 40px 90px -40px rgba(0,0,0,.9);
}
.filmband__video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center;
}
.filmband__scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(to top, rgba(12,9,7,.92) 0%, rgba(12,9,7,.30) 45%, rgba(12,9,7,.45) 100%),
    radial-gradient(circle at 18% 80%, rgba(212,175,110,.18), transparent 55%);
}
.filmband__copy {
  position: absolute; inset-inline-start: 0; bottom: 0; z-index: 2;
  padding: clamp(28px, 5vw, 60px);
}
.filmband__title {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.8rem, 4vw, 3.2rem); line-height: 1.06; letter-spacing: -.03em;
}
.filmband__sub { margin-top: 14px; color: var(--muted); font-size: 1.02rem; }

/* =========================================================
   Collection
   ========================================================= */
.filters {
  display: flex; gap: 10px; justify-content: center;
  margin-bottom: 44px; flex-wrap: wrap;
}
.filter {
  font-family: var(--font-display); font-size: 13.5px; font-weight: 600;
  padding: 10px 22px; border-radius: 100px;
  background: rgba(255,255,255,.03); border: 1px solid var(--line);
  color: var(--muted); cursor: pointer;
  transition: color .25s, background .25s, border-color .25s, transform .28s var(--ease), box-shadow .28s ease;
}
.filter:hover { color: var(--text); transform: translateY(-2px); border-color: var(--line-2); background: rgba(212,175,110,.06); }
.filter.is-active {
  color: #1a1208; background: var(--grad); border-color: transparent; transform: translateY(-2px);
  box-shadow: 0 10px 28px -10px rgba(240,208,136,.55);
}
.filter:active { transform: translateY(0) scale(.96); }
.grid {
  display: grid; grid-template-columns: repeat(3,1fr); gap: 24px;
}
.model {
  border-radius: var(--radius);
  background: linear-gradient(170deg, var(--surface), #15110c);
  border: 1px solid var(--line);
  overflow: hidden;
  transition: transform .5s var(--ease), border-color .5s var(--ease);
}
.model.is-hidden { display: none; }
.model:hover { border-color: var(--line-2); }
.model__stage {
  position: relative; height: 250px;
  display: grid; place-items: center;
  background:
    radial-gradient(circle at 50% 38%, rgba(240,208,136,.16), transparent 62%),
    #1a140e;
  overflow: hidden;
  perspective: 900px;
}
.model__stage::after {
  content: ""; position: absolute; bottom: 0; left: 0; right: 0; height: 50%;
  background: radial-gradient(ellipse 55% 22% at 50% 88%, rgba(240,208,136,.14), transparent 70%), linear-gradient(transparent, rgba(0,0,0,.4));
  transition: background .5s var(--ease);
}
.model:hover .model__stage::after {
  background: radial-gradient(ellipse 60% 24% at 50% 90%, rgba(240,208,136,.24), transparent 72%), linear-gradient(transparent, rgba(0,0,0,.4));
}
/* gold light sweep on hover */
.model__stage::before {
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: linear-gradient(105deg, transparent 40%, rgba(240,208,136,.22) 50%, transparent 60%);
  background-size: 250% 100%; background-position: 130% 0;
  opacity: 0; transition: opacity .35s var(--ease);
}
.model:hover .model__stage::before { opacity: 1; animation: goldShine 1.5s var(--ease); }
.model__img {
  position: relative; z-index: 1;
  max-height: 200px; width: auto;
  transition: transform .5s var(--ease);
  transform-style: preserve-3d; will-change: transform;
  filter: drop-shadow(0 24px 30px rgba(0,0,0,.55));
}
.model:hover .model__img { transform: scale(1.07) translateY(-6px); }
.model__cat {
  position: absolute; top: 16px; inset-inline-start: 16px; z-index: 2;
  font-family: var(--font-display); font-size: 10.5px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  padding: 6px 12px; border-radius: 100px;
  background: rgba(6,8,12,.78); border: 1px solid var(--line-2);
}
.model__cat--smart { color: var(--cyan); }
.model__cat--feature { color: var(--violet); }
.model__body { padding: 24px 24px 26px; }
.model__name {
  font-family: var(--font-display); font-weight: 700; font-size: 1.4rem;
}
.model__tag { color: var(--muted); font-size: .92rem; margin: 5px 0 18px; }
.model__key { display: flex; flex-direction: column; gap: 0; }
.model__key-row {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 9px 0; border-top: 1px solid var(--line);
  font-size: 13px;
}
.model__key-row:first-child { border-top: none; }
.model__key-l { color: var(--dim); }
.model__key-v {
  font-family: var(--font-display); font-weight: 600;
  text-align: end; color: var(--text);
}
.model__toggle {
  margin-top: 16px; width: 100%;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--font-display); font-weight: 600; font-size: 13px;
  color: var(--blue-br);
  padding: 12px; border-radius: 12px;
  background: rgba(255,255,255,.07); border: 1px solid rgba(255,255,255,.22);
  cursor: pointer; transition: background .25s;
}
.model__toggle:hover { background: rgba(255,255,255,.14); }
.model__toggle-ic { transition: transform .35s var(--ease); }
.model.is-open .model__toggle-ic { transform: rotate(180deg); }
.model__sheet {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .45s var(--ease);
}
.model.is-open .model__sheet { grid-template-rows: 1fr; }
.model__sheet-in { overflow: hidden; }
.model__sheet-row {
  display: flex; justify-content: space-between; gap: 16px;
  padding: 10px 0; border-top: 1px solid var(--line);
  font-size: 12.5px;
}
.model__sheet-row:first-child { margin-top: 16px; }
.model__sheet-l { color: var(--dim); flex-shrink: 0; }
.model__sheet-v {
  text-align: end; color: var(--muted);
  font-family: var(--font-display); font-weight: 500;
}

/* =========================================================
   Technology
   ========================================================= */
.tech__grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 60px; align-items: center; margin-bottom: 90px;
}
.tech__visual { position: relative; }
.tech__img-wrap {
  position: relative; border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--line);
}
.tech__img { width: 100%; aspect-ratio: 4/3; object-fit: cover; }
.tech__img-glow {
  position: absolute; inset: 0;
  background: linear-gradient(160deg, transparent 55%, rgba(255,255,255,.22));
}
.tech__badge {
  position: absolute; bottom: -18px; inset-inline-end: 24px;
  font-family: var(--font-display); font-weight: 700; font-size: 14px;
  padding: 13px 22px; border-radius: 14px;
  background: var(--grad); color: #06121f;
  box-shadow: 0 18px 40px -14px rgba(255,255,255,.7);
}
.tech__list { list-style: none; margin-top: 30px; }
.tech__list li {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 0; border-top: 1px solid var(--line);
  font-size: 1rem;
}
.tech__li-ic {
  display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: 11px; flex-shrink: 0;
  color: var(--blue-br); font-size: 16px;
  background: rgba(255,255,255,.10); border: 1px solid rgba(255,255,255,.22);
}
.stats {
  display: grid; grid-template-columns: repeat(4,1fr); gap: 18px;
}
.bigstat {
  padding: 36px 26px; border-radius: var(--radius);
  background: linear-gradient(165deg, var(--surface), #15110c);
  border: 1px solid var(--line);
  transition: transform .45s var(--ease), border-color .45s var(--ease);
}
.bigstat:hover { transform: translateY(-6px); border-color: var(--line-2); }
.bigstat__n {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2.2rem,3.6vw,3rem); line-height: 1;
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
.bigstat__l { display: block; margin-top: 12px; color: var(--muted); font-size: .9rem; }

/* =========================================================
   Updates
   ========================================================= */
.posts { display: grid; grid-template-columns: repeat(3,1fr); gap: 24px; }
.post {
  border-radius: var(--radius); overflow: hidden;
  background: linear-gradient(170deg, var(--surface), #15110c);
  border: 1px solid var(--line);
  transition: transform .5s var(--ease), border-color .5s var(--ease);
}
.post:hover { transform: translateY(-8px); border-color: var(--line-2); }
.post__media { position: relative; height: 210px; overflow: hidden; }
.post__media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .7s var(--ease);
}
.post:hover .post__media img { transform: scale(1.07); }
.post__media::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(transparent 50%, rgba(6,8,12,.85));
}
.post__cat {
  position: absolute; top: 16px; inset-inline-start: 16px; z-index: 1;
  font-family: var(--font-display); font-size: 10.5px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  padding: 6px 12px; border-radius: 100px;
  background: rgba(6,8,12,.78); border: 1px solid var(--line-2); color: #fff;
}
.post__body { padding: 22px 24px 26px; }
.post__date {
  font-family: var(--font-display); font-size: 12px; font-weight: 600;
  color: var(--blue-br); letter-spacing: .06em;
}
.post { cursor: pointer; opacity: 1; animation: postIn .7s var(--ease) both; }
/* opacity stays 1 at all times so cards are always readable, even if the
   animation never plays; only the position eases in */
@keyframes postIn { from { transform: translateY(24px); } to { transform: none; } }
.post__title {
  font-family: var(--font-display); font-weight: 700;
  font-size: 1.12rem; line-height: 1.4; margin-top: 9px;
}
.post__excerpt {
  margin-top: 10px; color: var(--muted); font-size: .92rem; line-height: 1.6;
}
.posts__empty { grid-column: 1 / -1; text-align: center; color: var(--muted); padding: 30px 0; }

/* ===== News reader modal ===== */
.newsmodal { position: fixed; inset: 0; z-index: 2100; display: none; }
.newsmodal.is-open { display: flex; align-items: center; justify-content: center; padding: 5vh 5vw; }
.newsmodal__scrim {
  position: fixed; inset: 0; background: rgba(14,10,7,.92); backdrop-filter: blur(14px);
}
.newsmodal__panel {
  position: relative; z-index: 1; width: 100%; max-width: 720px;
  max-height: 90vh; overflow-y: auto;
  background: linear-gradient(170deg, #221a12, #0c0907);
  border: 1px solid rgba(212,175,110,.28);
  border-radius: 24px; box-shadow: 0 60px 130px -40px rgba(0,0,0,.95);
}
.newsmodal__close {
  position: absolute; top: 16px; inset-inline-end: 16px; z-index: 3;
  width: 42px; height: 42px; border-radius: 50%; cursor: pointer;
  background: rgba(12,9,7,.6); border: 1px solid rgba(212,175,110,.3);
  display: grid; place-items: center; transition: transform .4s var(--ease), background .3s;
}
.newsmodal__close span { position: absolute; width: 15px; height: 2px; background: var(--text); border-radius: 2px; }
.newsmodal__close span:first-child { transform: rotate(45deg); }
.newsmodal__close span:last-child { transform: rotate(-45deg); }
.newsmodal__close:hover { transform: rotate(90deg); background: rgba(212,175,110,.18); }
.newsmodal__media { width: 100%; aspect-ratio: 16 / 9; overflow: hidden; background: #1a140e; }
.newsmodal__media img { width: 100%; height: 100%; object-fit: cover; }
.newsmodal__body { padding: 28px clamp(22px,4vw,40px) 34px; }
.newsmodal__meta {
  font-family: var(--font-display); font-size: 12px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--blue-br);
}
.newsmodal__title {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.4rem, 2.6vw, 2rem); line-height: 1.2; letter-spacing: -.02em;
  margin: 12px 0 14px;
}
.newsmodal__text { color: #d8cdb4; font-size: 1.05rem; line-height: 1.8; }
.newsmodal__src {
  display: block; margin-top: 22px; padding-top: 16px;
  border-top: 1px solid var(--line);
  font-size: .86rem; color: var(--dim);
}

/* =========================================================
   CTA
   ========================================================= */
.cta { max-width: 1340px; margin: 0 auto 70px; padding: 0 6vw; }
.cta__inner {
  position: relative; overflow: hidden; text-align: center;
  padding: 100px 6vw; border-radius: 34px;
  background: linear-gradient(165deg, #221a12, #0c0907);
  border: 1px solid var(--line-2);
}
.cta__glow {
  position: absolute; left: 50%; bottom: -45%; transform: translateX(-50%);
  width: 72%; height: 95%;
  background: radial-gradient(ellipse, rgba(255,244,214,.30), transparent 55%), radial-gradient(ellipse, rgba(240,208,136,.20), transparent 70%);
  pointer-events: none;
}
.cta__title {
  position: relative;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2.1rem,4.8vw,3.7rem);
  line-height: 1.06; letter-spacing: -.025em;
}
.cta__sub { position: relative; margin: 20px auto 0; color: var(--muted); max-width: 470px; }
.cta__actions {
  position: relative; display: flex; gap: 16px;
  justify-content: center; margin-top: 36px; flex-wrap: wrap;
}

/* =========================================================
   Footer
   ========================================================= */
.footer {
  border-top: 1px solid var(--line);
  background: rgba(255,255,255,.012);
  padding: 72px 6vw 34px;
}
.footer__inner {
  max-width: 1340px; margin: 0 auto;
  display: grid; grid-template-columns: 1.7fr 1fr 1fr 1fr 1.2fr; gap: 40px;
}
.footer__logo {
  height: 54px; width: auto; margin-bottom: 18px; will-change: transform;
  animation: footFloat 5s ease-in-out infinite;
  filter: drop-shadow(0 8px 22px rgba(240,208,136,.25));
}
@keyframes footFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }
.footer__tagline { color: var(--muted); font-size: .92rem; max-width: 280px; margin-bottom: 22px; }
.footer__social { display: flex; gap: 10px; }
.footer__social a {
  width: 38px; height: 38px; border-radius: 10px;
  display: grid; place-items: center;
  background: rgba(255,255,255,.04); border: 1px solid var(--line);
  font-size: 14px; color: var(--muted);
  transition: color .25s, border-color .25s, transform .25s;
}
.footer__social a:hover {
  color: var(--blue-br); border-color: var(--blue-br); transform: translateY(-3px);
}
.footer__col h5 {
  font-family: var(--font-display); font-weight: 700; font-size: 14px;
  margin-bottom: 16px;
}
.footer__col a, .footer__contact {
  display: block; color: var(--muted); font-size: .92rem;
  margin-bottom: 11px; transition: color .25s;
}
.footer__col a:hover { color: var(--blue-br); }
.footer__bar {
  max-width: 1340px; margin: 54px auto 0;
  padding-top: 24px; border-top: 1px solid var(--line);
  display: flex; justify-content: space-between;
  font-size: .84rem; color: var(--dim);
}

/* =========================================================
   Model card — clickable enhancements
   ========================================================= */
.model { cursor: pointer; }
.model:hover {
  border-color: rgba(255,255,255,.42);
  box-shadow: 0 34px 70px -34px rgba(255,255,255,.55);
}
.model:hover .model__img { transform: scale(1.12) translateY(-10px) rotate(-2deg); }
.model:focus-visible { outline: 2px solid var(--blue-br); outline-offset: 3px; }
.model__shots {
  position: absolute; top: 16px; inset-inline-end: 16px; z-index: 2;
  font-family: var(--font-display); font-size: 10px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--blue-br);
  padding: 6px 11px; border-radius: 100px;
  background: rgba(6,8,12,.8); border: 1px solid rgba(255,255,255,.3);
}
.model__no {
  position: absolute; bottom: -6px; inset-inline-end: 12px; z-index: 0;
  font-family: var(--font-display); font-weight: 800; font-size: 4.4rem;
  line-height: 1; color: rgba(255,255,255,.045); pointer-events: none;
}
.model__view {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 18px;
  font-family: var(--font-display); font-weight: 600; font-size: 13px;
  color: var(--blue-br);
}
.model__view-arrow { font-style: normal; transition: transform .3s var(--ease); }
.model:hover .model__view-arrow { transform: translateX(6px); }
html[dir="rtl"] .model__view-arrow { transform: scaleX(-1); }
html[dir="rtl"] .model:hover .model__view-arrow { transform: scaleX(-1) translateX(6px); }

/* =========================================================
   Product detail modal
   ========================================================= */
.modal { position: fixed; inset: 0; z-index: 2000; display: none; }
.modal.is-open {
  display: flex; align-items: flex-start; justify-content: center;
  overflow-y: auto; padding: 56px 4vw;
}
.modal__scrim {
  position: fixed; inset: 0;
  background: rgba(3,4,6,.86);
  backdrop-filter: blur(12px);
}
.modal__panel {
  position: relative; width: 100%; max-width: 1120px;
  background: linear-gradient(170deg, #151515, #050505);
  border: 1px solid var(--line-2);
  border-radius: 28px; padding: 46px;
  box-shadow: 0 60px 130px -40px rgba(0,0,0,.95);
}
.modal__close {
  position: absolute; top: 18px; inset-inline-end: 18px; z-index: 5;
  width: 44px; height: 44px; border-radius: 50%;
  background: rgba(255,255,255,.05); border: 1px solid var(--line-2);
  cursor: pointer; display: grid; place-items: center;
  transition: transform .4s var(--ease), background .3s, border-color .3s;
}
.modal__close span {
  position: absolute; width: 16px; height: 2px;
  background: var(--text); border-radius: 2px;
}
.modal__close span:first-child { transform: rotate(45deg); }
.modal__close span:last-child { transform: rotate(-45deg); }
.modal__close:hover {
  background: rgba(255,255,255,.16); border-color: var(--blue-br);
  transform: rotate(90deg);
}
.modal__inner { display: grid; grid-template-columns: 1fr 1fr; gap: 44px; }

.modal__stage {
  position: relative; aspect-ratio: 1 / 1;
  border-radius: 20px; overflow: hidden;
  background: radial-gradient(circle at 50% 38%, rgba(255,255,255,.14), transparent 64%), #1a140e;
  border: 1px solid var(--line);
  display: grid; place-items: center;
}
.modal__glow {
  position: absolute; width: 84%; height: 84%;
  border-radius: 50%; filter: blur(72px);
}
.modal__bignum {
  position: absolute; top: 0; inset-inline-start: 4%;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(5rem, 11vw, 9rem); line-height: .9;
  color: rgba(255,255,255,.05); pointer-events: none;
}
.modal__main {
  position: relative; z-index: 1;
  max-width: 86%; max-height: 86%; width: auto;
  filter: drop-shadow(0 32px 42px rgba(0,0,0,.62));
}
.modal__thumbs { display: flex; gap: 10px; margin-top: 14px; flex-wrap: wrap; }
.modal__thumb {
  width: 72px; height: 72px; border-radius: 12px; overflow: hidden; padding: 0;
  border: 1px solid var(--line); background: #1a140e; cursor: pointer;
  transition: border-color .3s, transform .3s var(--ease);
}
.modal__thumb img { width: 100%; height: 100%; object-fit: cover; }
.modal__thumb:hover { transform: translateY(-3px); }
.modal__thumb.is-active { border-color: var(--blue-br); box-shadow: 0 0 0 1px var(--blue-br); }

.modal__cat {
  font-family: var(--font-display); font-size: 11px; font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase;
}
.modal__cat--smart { color: var(--cyan); }
.modal__cat--feature { color: var(--violet); }
.modal__name {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.9rem, 3.4vw, 2.7rem);
  letter-spacing: -.025em; margin: 10px 0 6px;
}
.modal__tag { color: var(--muted); font-size: 1.05rem; margin-bottom: 22px; }
.modal__specs { display: flex; flex-direction: column; margin-bottom: 26px; }
.modal__spec {
  display: flex; justify-content: space-between; gap: 18px;
  padding: 11px 0; border-top: 1px solid var(--line); font-size: 13px;
}
.modal__spec:first-child { border-top: none; }
.modal__spec-l { color: var(--dim); flex-shrink: 0; }
.modal__spec-v {
  font-family: var(--font-display); font-weight: 600;
  text-align: end; direction: ltr; color: var(--text);
}
.modal__actions { display: flex; gap: 14px; flex-wrap: wrap; }

/* =========================================================
   Sub-pages — shared
   ========================================================= */
.page-hero {
  max-width: 1100px; margin: 0 auto;
  padding: 180px 6vw 60px; text-align: center;
}
.page-hero__title {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2.6rem, 6vw, 5rem); line-height: 1.04;
  letter-spacing: -.03em; margin-top: 16px;
}
.page-hero__sub {
  max-width: 600px; margin: 22px auto 0;
  color: var(--muted); font-size: clamp(1rem,1.3vw,1.1rem);
}

/* ===== About ===== */
.about-story {
  display: grid; grid-template-columns: .9fr 1.1fr;
  gap: 60px; align-items: center;
}
.about-story__media {
  position: relative; border-radius: var(--radius); overflow: hidden;
  background: radial-gradient(circle at 50% 38%, rgba(255,255,255,.08), transparent 64%), var(--surface);
  border: 1px solid var(--line);
  display: grid; place-items: center; padding: 46px; min-height: 360px;
}
.about-story__media img {
  max-height: 340px; width: auto;
  filter: drop-shadow(0 30px 44px rgba(0,0,0,.7));
}
.about-story__badge {
  position: absolute; bottom: 20px; inset-inline-end: 20px;
  font-family: var(--font-display); font-weight: 700; font-size: 13px;
  padding: 10px 16px; border-radius: 100px;
  background: var(--grad); color: #000;
}
.about-story__copy p {
  color: var(--muted); margin-top: 18px;
  font-size: clamp(1rem,1.2vw,1.06rem);
}
.about-story__copy .section__title { margin-bottom: 6px; }
.pillars { display: grid; grid-template-columns: repeat(3,1fr); gap: 24px; }
.pillar {
  padding: 38px 32px; border-radius: var(--radius);
  background: linear-gradient(170deg, var(--surface), #15110c);
  border: 1px solid var(--line);
  transition: transform .45s var(--ease), border-color .45s var(--ease);
}
.pillar:hover { transform: translateY(-8px); border-color: var(--line-2); }
.pillar__ic {
  display: grid; place-items: center;
  width: 54px; height: 54px; border-radius: 14px;
  font-size: 20px; color: var(--blue-br);
  background: rgba(255,255,255,.06); border: 1px solid var(--line-2);
  margin-bottom: 22px;
}
.pillar__t { font-family: var(--font-display); font-weight: 700; font-size: 1.3rem; margin-bottom: 10px; }
.pillar__d { color: var(--muted); font-size: .98rem; }
.about-stats { padding-top: 0; }

/* ===== Contact ===== */
.contact-grid { display: grid; grid-template-columns: 1fr 1.05fr; gap: 54px; }
.contact-block { padding: 22px 0; border-top: 1px solid var(--line); }
.contact-block:first-child { border-top: none; padding-top: 0; }
.contact-block__l {
  font-family: var(--font-display); font-size: 12px; font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase; color: var(--blue-br);
  display: block; margin-bottom: 10px;
}
.contact-block__big {
  font-family: var(--font-display); font-weight: 700; font-size: 1.5rem;
  color: var(--text); transition: color .25s;
}
.contact-block__big:hover { color: var(--blue-br); }
.contact-block__txt { color: #d8cdb4; font-size: 1.02rem; line-height: 1.7; }
.contact-social { display: flex; gap: 16px; flex-wrap: wrap; }
.contact-social a {
  font-family: var(--font-display); font-weight: 600; font-size: 14px;
  color: var(--muted); padding-bottom: 3px;
  border-bottom: 1px solid var(--line-2); transition: color .25s, border-color .25s;
}
.contact-social a:hover { color: var(--blue-br); border-color: var(--blue-br); }
.contact-form {
  padding: 40px; border-radius: var(--radius);
  background: linear-gradient(170deg, var(--surface), #15110c);
  border: 1px solid var(--line);
}
.contact-form__title { font-family: var(--font-display); font-weight: 700; font-size: 1.45rem; margin-bottom: 24px; }
.field { margin-bottom: 18px; }
.field label {
  display: block; font-family: var(--font-display); font-size: 13px;
  color: var(--muted); margin-bottom: 8px;
}
.field input, .field textarea {
  width: 100%; padding: 13px 16px; border-radius: 12px;
  background: rgba(255,255,255,.03); border: 1px solid var(--line-2);
  color: var(--text); font: inherit; resize: vertical;
  transition: border-color .25s, background .25s;
}
.field input:focus, .field textarea:focus {
  outline: none; border-color: var(--blue-br); background: rgba(255,255,255,.05);
}
.contact-form__done {
  display: none; margin-top: 16px; color: var(--blue-br);
  font-family: var(--font-display); font-weight: 600;
}
.contact-form.is-sent .contact-form__done { display: block; }
.contact-form.is-sent button[type="submit"] { display: none; }
.contact-form__err {
  display: none; margin-top: 16px; color: #e0736a;
  font-family: var(--font-display); font-weight: 600; line-height: 1.5;
}
.contact-form.is-error .contact-form__err { display: block; }
.contact-form.is-busy button[type="submit"] { opacity: .7; cursor: progress; }

/* ===== Terms / legal page ===== */
.legal { max-width: 820px; margin: 0 auto; padding-top: 30px; }
.legal__block { padding: 30px 0; border-top: 1px solid var(--line); }
.legal__block:first-child { border-top: none; padding-top: 0; }
.legal__h {
  display: flex; align-items: baseline; gap: 14px;
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.2rem, 2vw, 1.45rem); margin-bottom: 12px;
}
.legal__h .num {
  font-size: .85em; color: var(--gold);
  font-variant-numeric: tabular-nums; flex-shrink: 0;
}
.legal__b { color: var(--muted); font-size: 1.04rem; line-height: 1.85; }
.legal__updated {
  display: inline-block; margin-top: 18px;
  font-family: var(--font-display); font-size: 12.5px; letter-spacing: .04em;
  color: var(--dim);
}
/* numbered step list (update guides) */
.ud-steps { counter-reset: step; list-style: none; margin-top: 18px; }
.ud-steps li {
  position: relative; padding: 13px 0; padding-inline-start: 50px;
  border-top: 1px solid var(--line); color: var(--muted); line-height: 1.7;
}
.ud-steps li:first-child { border-top: none; }
.ud-steps li::before {
  counter-increment: step; content: counter(step);
  position: absolute; inset-inline-start: 0; top: 11px;
  width: 32px; height: 32px; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 700; font-size: 13px;
  color: var(--gold); background: rgba(212,175,110,.08);
  border: 1px solid rgba(212,175,110,.28);
}
.ud-tip {
  margin-top: 16px; color: var(--dim); font-size: .95rem;
  padding: 12px 16px; border-radius: 12px;
  background: rgba(212,175,110,.05); border: 1px solid var(--line);
}

/* ===== Phone detail page ===== */
.phone-page { max-width: 1340px; margin: 0 auto; padding: 116px 6vw 50px; }
.ph-back {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--font-display); font-weight: 600; font-size: 14px;
  color: var(--muted); margin-bottom: 34px;
  transition: color .25s;
}
.ph-back:hover { color: var(--blue-br); }
.ph-back__ar { transition: transform .3s var(--ease); }
.ph-back:hover .ph-back__ar { transform: translateX(-5px); }
html[dir="rtl"] .ph-back__ar { transform: scaleX(-1); }
html[dir="rtl"] .ph-back:hover .ph-back__ar { transform: scaleX(-1) translateX(-5px); }

.ph-hero {
  display: grid; grid-template-columns: 1.05fr .95fr;
  gap: 54px; align-items: center; margin-bottom: 96px;
}
.ph-hero__stage {
  position: relative; aspect-ratio: 1 / 1;
  border-radius: var(--radius); overflow: hidden; cursor: pointer;
  background: radial-gradient(circle at 50% 40%, rgba(255,255,255,.07), transparent 64%), var(--surface);
  border: 1px solid var(--line);
  display: grid; place-items: center;
}
.ph-hero__glow { position: absolute; width: 82%; height: 82%; border-radius: 50%; filter: blur(74px); }
.ph-hero__main {
  position: relative; z-index: 1; max-width: 84%; max-height: 84%; width: auto;
  filter: drop-shadow(0 34px 44px rgba(0,0,0,.7));
}
.ph-hero__thumbs { display: flex; gap: 10px; margin-top: 14px; flex-wrap: wrap; }
.ph-thumb {
  width: 76px; height: 76px; border-radius: 12px; overflow: hidden; padding: 0;
  border: 1px solid var(--line); background: var(--surface); cursor: pointer;
  transition: border-color .3s, transform .3s var(--ease);
}
.ph-thumb:hover { transform: translateY(-3px); }
.ph-thumb.is-active { border-color: var(--blue-br); box-shadow: 0 0 0 1px var(--blue-br); }
.ph-thumb img { width: 100%; height: 100%; object-fit: cover; }
.ph-hero__cat {
  font-family: var(--font-display); font-size: 12px; font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase; color: var(--blue-br);
}
.ph-hero__cat--feature { color: var(--violet); }
.ph-hero__name {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2.4rem, 4.6vw, 3.7rem);
  letter-spacing: -.03em; margin: 10px 0 8px;
}
.ph-hero__tag { color: var(--muted); font-size: 1.1rem; margin-bottom: 26px; }
.ph-key { margin-bottom: 28px; }
.ph-key__row {
  display: flex; justify-content: space-between; gap: 18px;
  padding: 12px 0; border-top: 1px solid var(--line); font-size: 14px;
}
.ph-key__l { color: var(--dim); }
.ph-key__v { font-family: var(--font-display); font-weight: 600; direction: ltr; }
.ph-hero__cta { display: flex; gap: 13px; flex-wrap: wrap; margin-top: 4px; }
.ph-notfound { text-align: center; padding: 60px 6vw 90px; }
.ph-notfound .btn { margin-top: 26px; }

.ph-block { margin-bottom: 90px; }
.ph-block > .eyebrow { margin-bottom: 28px; }
.ph-feats { display: grid; grid-template-columns: repeat(3,1fr); gap: 20px; }
.ph-feat {
  padding: 32px 28px; border-radius: var(--radius);
  background: linear-gradient(170deg, var(--surface), #15110c);
  border: 1px solid var(--line);
  transition: transform .45s var(--ease), border-color .45s var(--ease);
}
.ph-feat:hover { transform: translateY(-6px); border-color: var(--line-2); }
.ph-feat__no {
  font-family: var(--font-display); font-weight: 800; font-size: 13px;
  color: var(--dim); letter-spacing: .12em;
}
.ph-feat__t {
  font-family: var(--font-display); font-weight: 700;
  font-size: 1.15rem; margin: 12px 0 8px;
}
.ph-feat__d { color: var(--muted); font-size: .95rem; line-height: 1.6; }
.ph-gallery__grid { display: grid; grid-template-columns: repeat(3,1fr); gap: 18px; }
.ph-gcell {
  aspect-ratio: 4 / 3; border-radius: 16px; overflow: hidden; padding: 0;
  border: 1px solid var(--line); background: var(--surface); cursor: pointer;
}
.ph-gcell img { width: 100%; height: 100%; object-fit: cover; transition: transform .55s var(--ease); }
.ph-gcell:hover { border-color: var(--line-2); }
.ph-gcell:hover img { transform: scale(1.09); }
.ph-video__frame {
  border-radius: var(--radius); overflow: hidden; border: 1px solid var(--line);
}
.ph-video__frame video { width: 100%; display: block; }
.ph-specs__list {
  display: grid; grid-template-columns: 1fr 1fr; gap: 0 48px;
}
.ph-spec {
  display: flex; justify-content: space-between; gap: 18px;
  padding: 13px 0; border-top: 1px solid var(--line); font-size: 13.5px;
}
.ph-spec__l { color: var(--dim); flex-shrink: 0; }
.ph-spec__v {
  font-family: var(--font-display); font-weight: 600;
  text-align: end; direction: ltr; color: var(--text);
}

/* ===== Phone story — long-form feature sections ===== */
.ph-story { display: flex; flex-direction: column; gap: 120px; margin: 16px 0 96px; }
.ph-sec {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 56px; align-items: center;
}
.ph-sec--flip .ph-sec__media { order: 2; }
.ph-sec__media {
  position: relative; padding: 30px; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
  background: radial-gradient(circle at 50% 38%, rgba(255,255,255,.09), transparent 64%), var(--surface);
  aspect-ratio: 5 / 4; display: grid; place-items: center;
}
.ph-sec__media img {
  width: 100%; height: 100%; object-fit: contain;
  transition: transform .6s var(--ease);
}
.ph-sec__media:hover img { transform: scale(1.05); }
.ph-sec__text { max-width: 470px; }
.ph-sec--flip .ph-sec__text { margin-inline-start: auto; }
.ph-sec__h {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.7rem, 3vw, 2.5rem); line-height: 1.12; letter-spacing: -.025em;
}
.ph-sec__b { margin-top: 16px; color: var(--muted); font-size: 1.04rem; line-height: 1.75; }
.ph-sec__text--center { max-width: 640px; margin: 0 auto 40px; text-align: center; }

.ph-banner {
  border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; background: var(--surface); padding: 30px;
}
.ph-banner img { width: 100%; display: block; }

.ph-trio { display: grid; grid-template-columns: repeat(3,1fr); gap: 16px; }
.ph-trio__cell {
  padding: 0; cursor: pointer; aspect-ratio: 3 / 2; overflow: hidden;
  border: 1px solid var(--line); border-radius: 16px; background: var(--surface);
}
.ph-trio__cell img { width: 100%; height: 100%; object-fit: cover; transition: transform .6s var(--ease); }
.ph-trio__cell:hover img { transform: scale(1.07); }

.ph-statement { text-align: center; max-width: 900px; margin: 0 auto; padding: 20px 0; }
.ph-statement .ph-sec__h { font-size: clamp(1.9rem, 4.2vw, 3.3rem); }
.ph-statement .ph-sec__b { margin: 18px auto 0; max-width: 560px; }

.ph-icons { display: grid; grid-template-columns: repeat(3,1fr); gap: 22px; }
.ph-icon {
  padding: 36px 28px; border-radius: var(--radius); text-align: center;
  background: linear-gradient(170deg, var(--surface), #15110c);
  border: 1px solid var(--line);
  transition: transform .45s var(--ease), border-color .45s var(--ease);
}
.ph-icon:hover { transform: translateY(-6px); border-color: var(--line-2); }
.ph-icon__img {
  width: 66px; height: 66px; margin: 0 auto 18px;
  display: grid; place-items: center; border-radius: 16px;
  background: rgba(255,255,255,.05); border: 1px solid var(--line-2);
}
.ph-icon__img img { width: 40px; height: 40px; object-fit: contain; }
.ph-icon__t { font-family: var(--font-display); font-weight: 700; font-size: 1.16rem; }
.ph-icon__d { margin-top: 9px; color: var(--muted); font-size: .93rem; line-height: 1.65; }

/* ===== Lightbox ===== */
.lightbox { position: fixed; inset: 0; z-index: 2200; display: none; }
.lightbox.is-open { display: grid; place-items: center; }
.lightbox__scrim { position: absolute; inset: 0; background: rgba(0,0,0,.93); backdrop-filter: blur(8px); }
.lightbox__img {
  position: relative; max-width: 92vw; max-height: 88vh;
  border-radius: 12px; border: 1px solid var(--line-2);
}
.lightbox__close {
  position: absolute; top: 24px; inset-inline-end: 24px; z-index: 2;
  width: 46px; height: 46px; border-radius: 50%;
  background: rgba(255,255,255,.06); border: 1px solid var(--line-2);
  cursor: pointer; display: grid; place-items: center;
  transition: transform .4s var(--ease), background .3s;
}
.lightbox__close span { position: absolute; width: 17px; height: 2px; background: var(--text); border-radius: 2px; }
.lightbox__close span:first-child { transform: rotate(45deg); }
.lightbox__close span:last-child { transform: rotate(-45deg); }
.lightbox__close:hover { transform: rotate(90deg); background: rgba(255,255,255,.12); }

/* sub-page responsive */
@media (max-width: 980px) {
  .about-story { grid-template-columns: 1fr; gap: 36px; }
  .pillars { grid-template-columns: 1fr; }
  .contact-grid { grid-template-columns: 1fr; gap: 36px; }
  .ph-hero { grid-template-columns: 1fr; gap: 32px; }
  .ph-gallery__grid { grid-template-columns: repeat(2,1fr); }
  .ph-feats { grid-template-columns: repeat(2,1fr); }
  .ph-specs__list { grid-template-columns: 1fr; }
  .page-hero { padding-top: 150px; }
  .ph-story { gap: 70px; }
  .ph-sec { grid-template-columns: 1fr; gap: 26px; }
  .ph-sec--flip .ph-sec__media { order: 0; }
  .ph-sec__text, .ph-sec--flip .ph-sec__text { max-width: 100%; margin-inline-start: 0; }
  .ph-icons { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .ph-gallery__grid { grid-template-columns: 1fr; }
  .ph-feats { grid-template-columns: 1fr; }
  .ph-trio { grid-template-columns: 1fr; }
  .contact-form { padding: 26px; }
}

/* =========================================================
   Responsive
   ========================================================= */
@media (max-width: 1080px) {
  .tech__grid { grid-template-columns: 1fr; gap: 44px; }
  .grid { grid-template-columns: repeat(2,1fr); }
  .stats { grid-template-columns: repeat(2,1fr); }
  .footer__inner { grid-template-columns: 1fr 1fr 1fr; }
  .footer__brand { grid-column: 1 / -1; }
  .show-panel { grid-template-columns: 1fr; gap: 20px; text-align: center; min-height: auto; }
  .show-panel:nth-child(even) .show-panel__visual { order: 0; }
  .show-panel__info { max-width: 520px; margin: 0 auto; }
  .show-panel:nth-child(even) .show-panel__info { margin-inline: auto; }
  .show-panel__specs { max-width: 440px; margin-inline: auto; margin-bottom: 24px; }
  .show-panel__img { width: min(290px, 66%); }
  .show-panel__num { display: none; }
}
@media (max-width: 760px) {
  .filmband__frame { aspect-ratio: 4 / 5; min-height: 0; }
  .preloader__video { object-fit: contain; background: #000; }
  .nav .nav__links {
    position: fixed; top: 0; inset-inline-end: 0; z-index: 990;
    height: 100svh; width: min(80vw, 320px);
    flex-direction: column; gap: 6px;
    padding: 100px 26px 40px;
    background: var(--surface);
    border-inline-start: 1px solid var(--line);
    transform: translateX(110%);
    transition: transform .45s var(--ease);
  }
  html[dir="rtl"] .nav .nav__links { transform: translateX(-110%); }
  .nav .nav__links.is-open,
  html[dir="rtl"] .nav .nav__links.is-open { transform: translateX(0); }
  .nav__links a { width: 100%; font-size: 16px; padding: 14px 16px; }
  .nav__burger { display: flex; }
  .nav__actions .btn--sm { display: none; }
  .grid, .posts { grid-template-columns: 1fr; }
  .stats { grid-template-columns: 1fr 1fr; }
  .hero__stats { gap: 22px; }
  .hero { padding: 120px 6vw 80px; }
  .hero__title { font-size: clamp(2.6rem, 11vw, 4rem); }
  .manifesto { padding: 100px 6vw; }
  .footer__inner { grid-template-columns: 1fr 1fr; }
  .footer__bar { flex-direction: column; gap: 8px; text-align: center; }
  .cta__inner { padding: 64px 24px; }
  .show-panel__specs { grid-template-columns: 1fr; }
  .show-panel { padding: 50px 6vw; }
  .modal { padding: 16px 10px; }
  .modal__panel { padding: 26px 20px; border-radius: 20px; }
  .modal__inner { grid-template-columns: 1fr; gap: 26px; }
}
@media (max-width: 440px) {
  .footer__inner { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* =========================================================
   Luxury polish — gold accent layer
   ========================================================= */
.eyebrow,
.badge {
  border-color: rgba(212,175,110,.32);
  background: rgba(212,175,110,.07);
}
.section__head > .eyebrow,
.showcase__head > .eyebrow,
.page-hero > .eyebrow {
  position: relative;
}
.section__head > .eyebrow::after,
.showcase__head > .eyebrow::after,
.page-hero > .eyebrow::after {
  content: ""; display: block;
  width: 64px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(240,208,136,.75), transparent);
  margin: 14px auto 0;
}
.section__title,
.cta__title,
.showcase__title,
.modal__name,
.ph-hero__name,
.ph-sec__h,
.page-hero__title,
.manifesto__text {
  letter-spacing: -.028em;
}
.tech__badge {
  color: #1a1208;
  box-shadow: 0 18px 40px -14px rgba(212,175,110,.6);
}
.tech__li-ic,
.feature__icon,
.pillar__ic {
  color: var(--blue-br);
  background: rgba(212,175,110,.10);
  border-color: rgba(212,175,110,.26);
}
.spec-chip {
  background: rgba(212,175,110,.04);
  border-color: rgba(212,175,110,.14);
}
.spec-chip__l { color: var(--blue-br); opacity: .78; }
.model {
  position: relative;
  background: linear-gradient(170deg, #1f1812, #14100c);
  box-shadow: 0 18px 40px -30px rgba(0,0,0,.9), inset 0 1px 0 rgba(240,208,136,.08);
}
.model::before {
  content:""; position:absolute; inset:0; border-radius:inherit; padding:1px; z-index:4;
  background:linear-gradient(160deg, rgba(240,208,136,.34), rgba(212,175,110,.05) 42%, transparent 70%);
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude;
  pointer-events:none; opacity:.85; transition:opacity .5s var(--ease);
}
.model:hover {
  border-color: rgba(212,175,110,.45);
  box-shadow: 0 34px 70px -34px rgba(212,175,110,.55);
}
.model:hover::before { opacity:1; background:linear-gradient(160deg, rgba(255,246,216,.6), rgba(212,175,110,.12) 45%, transparent 72%); }
.bigstat,
.pillar,
.post,
.ph-feat,
.ph-icon {
  background: linear-gradient(170deg, #1f1812, #14100c);
  box-shadow: 0 18px 40px -30px rgba(0,0,0,.9), inset 0 1px 0 rgba(240,208,136,.08);
}
.bigstat:hover, .pillar:hover, .post:hover, .ph-feat:hover, .ph-icon:hover,
.ph-sec__media:hover, .ph-trio__cell:hover {
  border-color: rgba(212,175,110,.38);
  box-shadow: 0 24px 48px -28px rgba(212,175,110,.4);
}
.ph-sec__media,
.ph-banner,
.ph-trio__cell,
.tech__img-wrap,
.modal__stage,
.ph-hero__stage,
.show-panel__glow ~ * {
  border-color: rgba(212,175,110,.16);
}
.modal__scrim, .lightbox__scrim {
  background: rgba(14,10,7,.92);
  backdrop-filter: blur(14px);
}
.modal__panel {
  background: linear-gradient(170deg, #221a12, #0c0907);
  border-color: rgba(212,175,110,.28);
}
.cta__inner {
  border-color: rgba(212,175,110,.30);
}
.cta__inner::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(ellipse at 50% 0%, rgba(240,208,136,.08), transparent 60%);
  pointer-events: none;
}
.scroll-progress {
  background: linear-gradient(90deg, #8b6f2a, #caa24a 45%, #f0d088 80%, #fff6d8);
  box-shadow: 0 0 18px rgba(240,208,136,.85);
}

/* call/ring theme — a tiny ringing-phone icon on every tel: link site-wide */
a[href^="tel:"] { white-space: nowrap; }
a[href^="tel:"]::before {
  content: ""; display: inline-block; width: 1em; height: 1em;
  margin-inline-end: .5em; vertical-align: -0.12em; background: currentColor;
  -webkit-mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2a15.05 15.05 0 0 1-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1z'/></svg>") center / contain no-repeat;
          mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2a15.05 15.05 0 0 1-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1z'/></svg>") center / contain no-repeat;
  transform-origin: 50% 72%;
  animation: telRing 2.4s ease-in-out infinite;
}
@keyframes telRing {
  0%, 58%, 100% { transform: rotate(0deg); }
  62% { transform: rotate(-15deg); }
  66% { transform: rotate(13deg); }
  70% { transform: rotate(-10deg); }
  74% { transform: rotate(8deg); }
  78% { transform: rotate(-4deg); }
  82% { transform: rotate(0deg); }
}
.nav.is-scrolled {
  background: rgba(14,10,7,.78);
  border-bottom-color: rgba(212,175,110,.14);
}
.lang { background: rgba(212,175,110,.04); }
.lang:hover { background: rgba(212,175,110,.08); border-color: rgba(212,175,110,.28); }
.preloader__bar { background: rgba(212,175,110,.12); }
/* luminous gold orb cursor — bright, glowing, no hard outline */
.cursor__dot {
  width: 11px; height: 11px; overflow: visible;
  background: radial-gradient(circle at 42% 38%, #fff8e2 0%, #f3d894 52%, #b9923f 100%);
  box-shadow:
    0 0 10px 2px rgba(240,208,136,.95),
    0 0 26px 8px rgba(240,208,136,.5),
    0 0 52px 16px rgba(240,208,136,.22);
  animation: curGlow 1.5s ease-in-out infinite;
}
@keyframes curGlow {
  0%, 100% { box-shadow: 0 0 10px 2px rgba(240,208,136,.95), 0 0 26px 8px rgba(240,208,136,.5),  0 0 52px 16px rgba(240,208,136,.2); }
  50%      { box-shadow: 0 0 16px 4px rgba(255,248,226,1),   0 0 38px 12px rgba(240,208,136,.7), 0 0 70px 22px rgba(240,208,136,.32); }
}
.cursor__dot::after { display: none; }
/* the ring becomes a soft glowing aura instead of a crisp circle */
.cursor__ring {
  border: 1px solid rgba(240,208,136,.4);
  background: radial-gradient(circle, rgba(240,208,136,.12) 0%, transparent 68%);
  box-shadow: 0 0 18px rgba(240,208,136,.3);
}
body[data-cursor-state="hover"] .cursor__ring {
  background: radial-gradient(circle, rgba(240,208,136,.2) 0%, transparent 70%);
  border-color: #f0d088; box-shadow: 0 0 30px rgba(240,208,136,.55);
}
@media (prefers-reduced-motion: reduce) {
  .cursor__dot { animation: none; }
}

/* refined separators for breathing room */
.marquee {
  background: rgba(212,175,110,.02);
  border-block-color: rgba(212,175,110,.12);
}
.footer { background: rgba(212,175,110,.012); border-top-color: rgba(212,175,110,.14); }
.section[id]::after,
.showcase::after {
  /* leave to existing layout */
}

/* subtle warm wash for sections — relief from pure black */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -3; pointer-events: none;
  background:
    radial-gradient(1200px 600px at 50% -10%, rgba(240,208,136,.06), transparent 60%),
    radial-gradient(900px 500px at 50% 110%, rgba(139,111,42,.05), transparent 60%);
}

/* =========================================================
   Stunning pass — gold dust, letter entrance, headline glint,
   camera compare, finish switcher, 404
   ========================================================= */

/* (1) gold dust drifting in the hero */
.hero__dust { position: absolute; inset: 0; z-index: 1; pointer-events: none; }

/* (3) hero headline — letter-by-letter entrance (words in Persian) */
.mask__in.is-split { transform: none; transition: none; }
.ht-ch {
  display: inline-block; white-space: pre;
  opacity: 0; transform: translateY(.55em); filter: blur(10px);
  animation: htIn .72s var(--ease-out) forwards;
  animation-delay: calc(var(--i) * 38ms);
}
html[dir="rtl"] .ht-ch { animation-duration: .62s; animation-delay: calc(var(--i) * 95ms); }
.ht-ch.ht-grad {
  background: linear-gradient(115deg, #f3d488 0%, #ecc25c 42%, #d4af37 72%, #a8842f 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}
/* once the hero em word is split, ONLY the child .ht-ch paints the gradient;
   stop the parent .em clip-painting a second (offset) copy — that was the ghost/shadow */
.hero__title .em.is-split { background: none !important; }
@keyframes htIn { to { opacity: 1; transform: none; filter: blur(0); } }

/* (5) one-shot gold glint sweeping across gold headlines */
.gradient-text.glint {
  background-image:
    linear-gradient(105deg, rgba(255,255,255,0) 40%, rgba(255,248,222,.95) 50%, rgba(255,255,255,0) 60%),
    var(--grad);
  background-size: 240% 100%, 100% 100%;
  background-position: 200% 0, 0 0;
  animation: textGlint 1.25s ease-out .15s forwards;
}
@keyframes textGlint { to { background-position: -140% 0, 0 0; } }

/* (4) camera before/after compare */
.camcmp { max-width: 1340px; margin: 90px auto 0; }
.camcmp__head { text-align: center; margin-bottom: 28px; }
.camcmp__title {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.6rem, 3.2vw, 2.6rem); margin-top: 10px;
}
.camcmp__stage {
  position: relative; border-radius: var(--radius); overflow: hidden;
  border: 1px solid rgba(240,208,136,.22);
  box-shadow: 0 30px 80px rgba(0,0,0,.5);
  cursor: ew-resize; touch-action: none; user-select: none; -webkit-user-select: none;
  --cut: 50%;
}
.camcmp__stage > img { width: 100%; height: auto; display: block; pointer-events: none; }
.camcmp__before { position: absolute; inset: 0; clip-path: inset(0 calc(100% - var(--cut)) 0 0); }
.camcmp__before img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; pointer-events: none;
  filter: saturate(.45) brightness(.75) contrast(.9);
}
.camcmp__label {
  position: absolute; top: 14px; z-index: 3; padding: 7px 14px; border-radius: 999px;
  font-family: var(--font-display); font-size: 12px; font-weight: 600; letter-spacing: .06em;
  background: rgba(8,6,4,.55); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  border: 1px solid rgba(240,208,136,.25); color: #f0d088;
}
.camcmp__label--l { left: 14px; }
.camcmp__label--r { right: 14px; }
.camcmp__handle { position: absolute; top: 0; bottom: 0; left: var(--cut); z-index: 4; width: 0; outline: none; }
.camcmp__line {
  position: absolute; top: 0; bottom: 0; left: -1px; width: 2px;
  background: linear-gradient(to bottom, rgba(240,208,136,.1), #f0d088 30%, #f0d088 70%, rgba(240,208,136,.1));
  box-shadow: 0 0 14px rgba(240,208,136,.6);
}
.camcmp__knob {
  position: absolute; top: 50%; left: 0; transform: translate(-50%, -50%);
  width: 46px; height: 46px; border-radius: 50%;
  display: grid; place-items: center;
  background: linear-gradient(135deg, #f5e0a0, #caa24a);
  color: #1a1206; font-weight: 800; font-size: 16px;
  box-shadow: 0 6px 22px rgba(0,0,0,.55), 0 0 24px rgba(240,208,136,.35);
}
.camcmp__handle:focus-visible .camcmp__knob { outline: 2px solid #fff6d8; outline-offset: 3px; }
@media (max-width: 760px) {
  .camcmp { margin-top: 64px; }
  .camcmp__stage > img { height: 320px; object-fit: cover; }
  .camcmp__knob { width: 40px; height: 40px; }
}

/* (6) reveal finish switcher */
.rv-colors { position: relative; z-index: 3; display: flex; align-items: center; gap: 14px; }
.rv-dot {
  width: 26px; height: 26px; border-radius: 50%; cursor: pointer; padding: 0;
  background: var(--c); border: 2px solid rgba(255,246,216,.25);
  box-shadow: 0 4px 14px rgba(0,0,0,.45), inset 0 2px 6px rgba(255,255,255,.18);
  transition: transform .25s var(--ease), border-color .25s ease, box-shadow .25s ease;
}
.rv-dot:hover { transform: scale(1.18); }
.rv-dot.is-active {
  border-color: #f0d088; transform: scale(1.12);
  box-shadow: 0 0 0 3px rgba(240,208,136,.28), 0 4px 14px rgba(0,0,0,.45);
}
.rv-cname {
  font-family: var(--font-display); font-size: 13px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: #f0d088; min-width: 86px;
}
html[dir="rtl"] .rv-cname { letter-spacing: 0; }
/* keep the same filter-function order in every state so the change can animate */
.reveal__phone {
  filter: hue-rotate(0deg) saturate(1) brightness(1) contrast(1) drop-shadow(0 40px 80px rgba(0,0,0,.6));
  transition: filter .7s ease;
}
.reveal__phone.tint-sapphire { filter: hue-rotate(175deg) saturate(.78) brightness(.96) contrast(1) drop-shadow(0 40px 80px rgba(0,0,0,.6)); }
.reveal__phone.tint-graphite { filter: hue-rotate(0deg) saturate(.12) brightness(.72) contrast(1.08) drop-shadow(0 40px 80px rgba(0,0,0,.6)); }

/* (7) 404 — "this number is unavailable" */
.nf { min-height: 72vh; display: grid; place-items: center; padding: 150px 6vw 90px; text-align: center; }
.nf__icon {
  position: relative; width: 110px; height: 110px; margin: 0 auto 30px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1.5px solid rgba(240,208,136,.5);
  box-shadow: 0 0 34px rgba(240,208,136,.2), inset 0 0 22px rgba(240,208,136,.08);
}
.nf__icon .ring-ico { width: 52px; height: 52px; }
.nf__code {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(5rem, 16vw, 9rem); line-height: 1.05;
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}
.nf__title { font-family: var(--font-display); font-weight: 800; font-size: clamp(1.5rem, 4vw, 2.4rem); margin-top: 6px; }
.nf__sub { color: var(--muted); margin: 14px auto 30px; max-width: 460px; }
.nf__actions { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }

@media (prefers-reduced-motion: reduce) {
  .ht-ch { animation: none; opacity: 1; transform: none; filter: none; }
  .gradient-text.glint { animation: none; background-image: var(--grad); background-size: 100% 100%; background-position: 0 0; }
  .hero__dust { display: none; }
  .reveal__phone { transition: none; }
}

/* (2) cinematic horizontal showcase (desktop, JS adds body.show-h) */
body.show-h .showcase {
  height: 100vh; padding: 96px 0 64px;
  display: flex; flex-direction: column; justify-content: center;
  overflow: hidden;
  /* layout the pinned strip left-to-right even in Persian — an overflowing
     flex item ignores auto margins (negative free space), so the section
     itself must be LTR; the text inside is flipped back to RTL below */
  direction: ltr;
}
html[dir="rtl"] body.show-h .showcase__head { direction: rtl; }
body.show-h .showcase__head { margin-bottom: 0; flex: 0 0 auto; }
body.show-h .showcase__stage {
  display: flex; flex-wrap: nowrap; align-items: center;
  width: max-content; will-change: transform;
  direction: ltr;             /* the strip itself always runs left-to-right */
  flex: 1 1 auto; min-height: 0;
}
html[dir="rtl"] body.show-h .show-panel { direction: rtl; }  /* content stays RTL */
body.show-h .show-panel {
  width: 84vw; max-width: 1280px; flex: 0 0 auto;
  min-height: 0; height: 100%;
  margin: 0 4vw; padding: 10px 5vw;
}
body.show-h .show-panel__img {
  width: auto; max-width: min(440px, 88%); max-height: 52vh;
}
.show-progress {
  position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%);
  width: min(420px, 56vw); height: 2px; border-radius: 2px;
  background: rgba(240,208,136,.16); overflow: hidden;
}
.show-progress > span {
  position: absolute; inset: 0; border-radius: 2px;
  background: linear-gradient(90deg, #8b6f2a, #f0d088);
  transform-origin: left center; transform: scaleX(0);
}

/* ===== showcase fit-fix + motion graphics ===== */
/* compact chrome so the phones always fit the pinned viewport */
body.show-h .showcase { padding: 80px 0 56px; }
body.show-h .showcase__head .section__title { font-size: clamp(1.5rem, 2.8vw, 2.4rem); }
body.show-h .showcase__head .eyebrow { font-size: 11px; }
body.show-h .showcase__head, body.show-h .showcase__stage { position: relative; z-index: 1; }
/* size the phone against the REAL row height, never the viewport guess */
body.show-h .show-panel__visual { height: 100%; min-height: 0; }
body.show-h .show-panel__img { max-height: 86%; }
body.show-h .show-panel__info { max-height: 100%; min-height: 0; }

/* rotating gold aperture ring behind every phone (motion graphic) */
body.show-h .show-panel__visual::before {
  content: ""; position: absolute; z-index: 0;
  width: min(64vh, 480px); height: min(64vh, 480px); border-radius: 50%;
  background: conic-gradient(from 0deg,
    transparent 0 12%, rgba(240,208,136,.55) 16%, transparent 22% 47%,
    rgba(240,208,136,.28) 52%, transparent 58% 100%);
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - 3px), #000 calc(100% - 1.5px));
          mask: radial-gradient(closest-side, transparent calc(100% - 3px), #000 calc(100% - 1.5px));
  animation: fxSpin 26s linear infinite;
}
body.show-h .show-panel:nth-child(even) .show-panel__visual::before {
  animation-direction: reverse; animation-duration: 34s;
}
@keyframes fxSpin { to { transform: rotate(360deg); } }

/* passing light streaks behind the strip (motion graphic, parallax via JS) */
.show-streaks {
  position: absolute; inset: 0; z-index: 0;
  pointer-events: none; overflow: hidden;
}
.show-streaks span {
  position: absolute; top: -10%; height: 120%; width: 2px;
  background: linear-gradient(to bottom,
    transparent, rgba(240,208,136,.38) 35%, rgba(240,208,136,.12) 65%, transparent);
  transform: skewX(-18deg);
  animation: streakPulse 4.6s ease-in-out infinite;
}
@keyframes streakPulse { 0%, 100% { opacity: .22; } 50% { opacity: .8; } }

/* ===== showcase: bulletproof fit (no viewport guessing) =====
   One definite grid row = panel height, and every vertical metric in the
   copy column compresses with the viewport height — so the phone and the
   button can never spill past the pinned screen, at any height or zoom. */
body.show-h .show-panel {
  height: 100%;
  grid-template-rows: 100%;
  align-items: center;
}
body.show-h .show-panel__visual {
  height: 100%; min-height: 0;
  padding-bottom: 7vh;   /* keep the phone clearly off the floor */
}
/* conservative CSS fallback only — the real cap is measured and set in px by
   JS (fitImgs), because %-max-height inside this grid chain does not resolve
   in every Chrome (it failed at 275% display scale). */
body.show-h .show-panel__img {
  width: auto; max-width: min(440px, 88%);
  max-height: 38vh;
}
body.show-h .show-panel__info { align-self: center; min-height: 0; max-height: 100%; }
body.show-h .show-panel__name { font-size: min(3.4rem, 5.4vh); }
body.show-h .show-panel__tag { font-size: min(1.05rem, 2.2vh); margin-bottom: min(26px, 2.6vh); }
body.show-h .show-panel__specs { gap: min(12px, 1.4vh); margin-bottom: min(26px, 2.6vh); }
body.show-h .spec-chip { padding: min(14px, 1.6vh) 16px; }
body.show-h .show-panel__visual::before { width: min(56vh, 460px); height: min(56vh, 460px); }

/* (5) glass shine — a showcase-window reflection sweeps across phone cards */
.model, .ph-gcell { position: relative; }
.model::after, .ph-gcell::after {
  content: ""; position: absolute; top: -20%; bottom: -20%; left: -75%; width: 55%;
  transform: rotate(20deg); z-index: 2; pointer-events: none; opacity: 0;
  background: linear-gradient(90deg,
    transparent, rgba(255,246,216,.14) 30%, rgba(240,208,136,.34) 50%,
    rgba(255,246,216,.14) 70%, transparent);
}
.model:hover::after, .ph-gcell:hover::after { animation: cardShine .95s ease; }
@keyframes cardShine {
  0%   { left: -75%; opacity: 0; }
  25%  { opacity: 1; }
  100% { left: 130%; opacity: 0; }
}

/* =========================================================
   Practical design pass — dot-nav, back-to-top, form polish,
   news skeletons, gold keyboard focus
   ========================================================= */

/* (1) side dot navigation — homepage wayfinding */
.dotnav {
  position: fixed; top: 50%; transform: translateY(-50%);
  inset-inline-end: 18px; z-index: 900;
  display: flex; flex-direction: column; gap: 14px;
}
.dotnav a {
  position: relative; width: 10px; height: 10px; border-radius: 50%;
  background: rgba(240,208,136,.22); border: 1px solid rgba(240,208,136,.35);
  transition: transform .3s var(--ease), background .3s ease, box-shadow .3s ease;
}
.dotnav a:hover { transform: scale(1.5); background: rgba(240,208,136,.6); }
.dotnav a.is-on {
  background: #f0d088; transform: scale(1.35);
  box-shadow: 0 0 12px rgba(240,208,136,.8);
}
.dotnav a span {
  position: absolute; top: 50%; transform: translateY(-50%);
  inset-inline-end: 22px; white-space: nowrap;
  font-family: var(--font-display); font-size: 11px; font-weight: 600;
  letter-spacing: .08em; color: #f0d088;
  background: rgba(10,8,5,.88); border: 1px solid rgba(240,208,136,.25);
  padding: 4px 10px; border-radius: 99px;
  opacity: 0; pointer-events: none; transition: opacity .25s ease;
}
html[dir="rtl"] .dotnav a span { letter-spacing: 0; }
.dotnav a:hover span { opacity: 1; }
body.is-loading .dotnav { display: none; }
@media (max-width: 1100px) { .dotnav { display: none; } }

/* (2) back-to-top with gold progress ring */
.totop {
  position: fixed; bottom: 26px; inset-inline-end: 22px; z-index: 950;
  width: 52px; height: 52px; border-radius: 50%; border: none; cursor: pointer;
  background: rgba(14,11,7,.85);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  display: grid; place-items: center;
  box-shadow: 0 10px 30px rgba(0,0,0,.5);
  opacity: 0; visibility: hidden; transform: translateY(14px);
  transition: opacity .35s ease, transform .35s var(--ease), visibility .35s;
}
.totop.is-show { opacity: 1; visibility: visible; transform: none; }
.totop:hover { transform: translateY(-3px); }
.totop svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.totop svg circle { fill: none; stroke-width: 2.5; }
.totop svg .bg { stroke: rgba(240,208,136,.18); }
.totop svg .fg { stroke: #f0d088; stroke-linecap: round; }
.totop .arr { position: relative; font-size: 17px; color: #f0d088; line-height: 1; }
@media (max-width: 760px) { .totop { width: 46px; height: 46px; bottom: 18px; inset-inline-end: 16px; } }

/* (6) contact form — gold focus, live validation, copy chips */
.field input, .field textarea { transition: border-color .3s ease, box-shadow .3s ease; }
.field input:focus, .field textarea:focus {
  border-color: rgba(240,208,136,.65);
  box-shadow: 0 0 0 3px rgba(240,208,136,.14);
  outline: none;
}
.field.is-bad input, .field.is-bad textarea { border-color: rgba(255,107,107,.7); }
.field.is-ok input,  .field.is-ok textarea  { border-color: rgba(151,201,154,.5); }
.field__err { display: none; margin-top: 6px; font-size: 12.5px; color: #ff9a9a; }
.field.is-bad .field__err { display: block; }
.copychip {
  display: inline-flex; align-items: center; gap: 6px; vertical-align: middle;
  margin-inline-start: 10px; padding: 4px 11px; border-radius: 99px; cursor: pointer;
  border: 1px solid rgba(240,208,136,.3); background: none; color: #caa24a;
  font-family: var(--font-display); font-size: 11.5px; letter-spacing: .05em;
  transition: border-color .25s ease, color .25s ease, transform .2s ease;
}
.copychip:hover { border-color: #f0d088; color: #f0d088; transform: translateY(-1px); }
.copychip.is-copied { color: #9cd49f; border-color: rgba(151,201,154,.55); }
html[dir="rtl"] .copychip { letter-spacing: 0; }

/* (7) gold shimmer skeleton while news images load */
.post__media, .newsmodal__media {
  background: linear-gradient(100deg, #17120c 40%, #261c10 50%, #17120c 60%);
  background-size: 220% 100%;
  animation: skel 1.6s linear infinite;
}
@keyframes skel { from { background-position: 130% 0; } to { background-position: -130% 0; } }

/* (8) sitewide gold keyboard focus */
a:focus-visible, button:focus-visible, input:focus-visible,
textarea:focus-visible, select:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid rgba(240,208,136,.9); outline-offset: 3px;
}

/* =========================================================
   Design pass 3 — page curtain, real icons, odometer, nav ink,
   drawn dividers, accent theming, announcement bar, OS chips
   ========================================================= */

/* (1) gold curtain page transition (exit only — the loader covers entry) */
.pgx {
  position: fixed; inset: 0; z-index: 5500; pointer-events: none;
  transform: translateY(101%); background: #0c0907;
}
.pgx::before {
  content: ""; position: absolute; left: 0; right: 0; top: -6px; height: 6px;
  background: linear-gradient(90deg, transparent, #f0d088, transparent);
  box-shadow: 0 0 24px rgba(240,208,136,.65);
}
.pgx.is-go {
  transition: transform .45s cubic-bezier(.65,0,.35,1);
  transform: translateY(0); pointer-events: auto;
}

/* (2) footer social — real SVG icons */
.footer__social a svg { width: 17px; height: 17px; display: block; fill: currentColor; }

/* (4) odometer counters — digits roll like an airport board */
.odo { display: inline-flex; overflow: hidden; height: 1.06em; vertical-align: bottom; }
.odo-col { display: inline-block; }
.odo-strip { display: flex; flex-direction: column; transition: transform 1.6s var(--ease-out); }
.odo-strip span, .odo > span { height: 1.06em; line-height: 1.06; display: block; }

/* (5) sliding gold underline in the nav */
.nav__links { position: relative; }
.nav-ink {
  position: absolute; bottom: 2px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, rgba(240,208,136,.2), #f0d088, rgba(240,208,136,.2));
  box-shadow: 0 0 10px rgba(240,208,136,.5);
  opacity: 0; pointer-events: none;
  transition: left .35s var(--ease), width .35s var(--ease), opacity .25s ease;
}
.nav-ink.is-live { opacity: 1; }
@media (max-width: 760px) { .nav-ink { display: none; } }

/* (7) gold dividers drawn on approach */
.sec-line {
  width: min(340px, 46vw); height: 1px; margin: 0 auto; position: relative;
  background: linear-gradient(90deg, transparent, rgba(240,208,136,.75), transparent);
  transform: scaleX(0); transition: transform 1.2s var(--ease-out);
}
.sec-line::after {
  content: "\25C6"; position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%); font-size: 8px; color: #f0d088;
  opacity: 0; transition: opacity .6s ease .6s;
}
.sec-line.is-draw { transform: scaleX(1); }
.sec-line.is-draw::after { opacity: 1; }

/* (8) phone-page accent theming — the page glows in the model's colour */
.ph-accent-aura {
  position: fixed; top: -22vh; left: 50%; transform: translateX(-50%);
  width: 92vmin; height: 92vmin; border-radius: 50%;
  background: radial-gradient(circle, var(--phacc, transparent) 0%, transparent 64%);
  opacity: .13; filter: blur(40px);
  pointer-events: none; z-index: -1;
}
body.ph-tinted .eyebrow { color: var(--phacc, var(--blue-br)); }

/* (9) announcement bar */
.annbar {
  position: fixed; top: 0; left: 0; right: 0; height: 36px; z-index: 1001;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  background: linear-gradient(90deg, #14100a, #1f1812 50%, #14100a);
  border-bottom: 1px solid rgba(240,208,136,.25);
  font-family: var(--font-display); font-size: 12.5px; letter-spacing: .04em;
  color: #e9dcb8; padding: 0 44px;
}
html[dir="rtl"] .annbar { letter-spacing: 0; }
.annbar a { color: #f0d088; font-weight: 600; white-space: nowrap; }
.annbar a:hover { text-decoration: underline; }
.annbar__x {
  position: absolute; inset-inline-end: 10px; top: 50%; transform: translateY(-50%);
  background: none; border: none; color: #caa24a; cursor: pointer;
  font-size: 17px; line-height: 1; padding: 4px 8px;
}
.annbar__x:hover { color: #fff6d8; }
body.has-annbar .nav { top: 36px; }
@media (max-width: 760px) { .annbar { font-size: 11px; gap: 7px; } }

/* (10) VOCAL OS — live UI chips floating over the tech visual */
.vos-chip {
  position: absolute; z-index: 3; display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; border-radius: 14px;
  background: rgba(14,11,7,.82);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border: 1px solid rgba(240,208,136,.28);
  box-shadow: 0 14px 34px rgba(0,0,0,.45);
  font-family: var(--font-display); font-size: 12px; font-weight: 600; color: #f3e9cf;
  opacity: 0; transform: translateY(14px) scale(.95);
  animation: vosChip 9s ease-in-out infinite;
  pointer-events: none;
}
.vos-chip .ic {
  width: 26px; height: 26px; border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center;
  background: rgba(240,208,136,.14); color: #f0d088; font-size: 13px;
}
.vos-chip small { display: block; font-weight: 400; font-size: 10.5px; color: var(--muted); }
.vos-chip--1 { top: 8%; inset-inline-start: -14px; animation-delay: .5s; }
.vos-chip--2 { top: 44%; inset-inline-end: -16px; animation-delay: 3.5s; }
.vos-chip--3 { bottom: 7%; inset-inline-start: 8%; animation-delay: 6.5s; }
@keyframes vosChip {
  0%, 5%   { opacity: 0; transform: translateY(14px) scale(.95); }
  10%, 30% { opacity: 1; transform: none; }
  36%, 100% { opacity: 0; transform: translateY(-10px) scale(.97); }
}
@media (prefers-reduced-motion: reduce) {
  .vos-chip { opacity: 1; transform: none; animation: none; }
  .pgx { display: none; }
  .sec-line { transform: scaleX(1); }
  .sec-line::after { opacity: 1; }
}

/* ===== Arabic (third language) ===== */
html[lang="ar"] { --fa-font: 'Vazirmatn'; }   /* full Arabic glyph coverage */

/* odometer fix — a transformed child no longer receives the parent's
   background-clip:text paint, so every digit carries its own gold gradient */
.bigstat__n .odo span,
.hstat__n .odo-strip span,
.hstat__n .odo > span:not(.odo-col) {
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
/* keep the odometer's structural containers un-clipped so the transformed strip
   never paints a ghost of the hidden digit behind the visible one */
.hstat__n .odo-col, .hstat__n .odo-strip { background: none !important; -webkit-text-fill-color: currentColor !important; }

/* (5) VOCAL OS — live phone showing real generated screens, gentle cross-fade */
.tech__visual--os { position: relative; display: grid; place-items: center; min-height: 420px; }
.os-stage {
  position: relative; width: min(300px, 74%); aspect-ratio: 768 / 1376;
  filter: drop-shadow(0 40px 70px rgba(0,0,0,.6));
}
.os-stage::before {
  content: ""; position: absolute; inset: -18% -12%; z-index: -1; border-radius: 50%;
  background: radial-gradient(circle, rgba(240,208,136,.20), transparent 66%);
  filter: blur(26px);
}
.os-screen {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain;
  opacity: 0; transition: opacity 1s var(--ease); will-change: opacity;
}
.os-screen.is-on { opacity: 1; }
@media (max-width: 760px) { .tech__visual--os { min-height: 360px; } .os-stage { width: min(240px, 64%); } }
@media (prefers-reduced-motion: reduce) { .os-screen { transition: none; } }

/* VOS section — cinematic model-morph film (replaces the OS phone visual) */
.tech__visual--film { position: relative; display: flex; align-items: center; min-height: 420px; }
.tech__filmwrap {
  position: relative; width: 100%; aspect-ratio: 1 / 1; border-radius: 20px; overflow: hidden;
  background: #050505;
  box-shadow: 0 40px 90px -40px rgba(0,0,0,.9), inset 0 0 0 1px rgba(240,208,136,.16);
}
.tech__film { width: 100%; height: 100%; object-fit: cover; display: block; }
.tech__filmwrap::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
  box-shadow: inset 0 0 70px rgba(0,0,0,.55);
  background: radial-gradient(120% 80% at 50% 0%, rgba(240,208,136,.09), transparent 60%);
}
@media (max-width: 1080px) { .tech__visual--film { min-height: 0; } }

/* (3) cinematic gold motion video behind the CTA card */
.cta__bg {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: .5; mix-blend-mode: screen; pointer-events: none;
}
.cta__inner > *:not(.cta__bg) { position: relative; z-index: 1; }
@media (prefers-reduced-motion: reduce) { .cta__bg { display: none; } }

/* (4) "Shot on VOCAL" camera-sample gallery under the compare slider */
.camshots { max-width: 1340px; margin: 30px auto 0; text-align: center; }
.camshots__eyebrow {
  display: inline-block; margin-bottom: 16px;
  font-family: var(--font-display); font-size: 12px; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase; color: #caa24a;
}
html[dir="rtl"] .camshots__eyebrow { letter-spacing: 0; }
.camshots__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.camshot {
  position: relative; padding: 0; border: 1px solid var(--line); cursor: pointer;
  border-radius: 16px; overflow: hidden; aspect-ratio: 16 / 10; background: #000;
}
.camshot img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .6s var(--ease); will-change: transform;
}
.camshot:hover img { transform: scale(1.07); }
.camshot__tag {
  position: absolute; left: 12px; bottom: 12px; z-index: 2;
  font-family: var(--font-display); font-size: 12px; font-weight: 600; color: #fff6d8;
  background: rgba(8,6,4,.6); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  border: 1px solid rgba(240,208,136,.25); padding: 5px 11px; border-radius: 99px;
}
html[dir="rtl"] .camshot__tag { left: auto; right: 12px; }
@media (max-width: 760px) {
  .camshots__grid { grid-template-columns: 1fr 1fr; }
  .camshots__grid .camshot:first-child { grid-column: 1 / -1; }
}

/* shared simple image lightbox (camera samples) */
.imglb {
  position: fixed; inset: 0; z-index: 5200; display: none;
  align-items: center; justify-content: center; padding: 5vh 5vw;
  background: rgba(6,5,3,.92); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.imglb.is-open { display: flex; animation: lbFade .3s ease; }
@keyframes lbFade { from { opacity: 0; } to { opacity: 1; } }
.imglb img {
  max-width: 100%; max-height: 100%; border-radius: 14px;
  box-shadow: 0 30px 90px rgba(0,0,0,.7); border: 1px solid rgba(240,208,136,.25);
}
.imglb__x {
  position: absolute; top: 22px; inset-inline-end: 26px; width: 44px; height: 44px;
  border-radius: 50%; border: 1px solid rgba(240,208,136,.4); background: rgba(14,11,7,.7);
  color: #f0d088; font-size: 22px; cursor: pointer; line-height: 1;
}

/* (5) About story — full-bleed lifestyle photo variant */
.about-story__media--photo { padding: 0; min-height: 0; }
.about-story__media--photo img {
  width: 100%; height: 100%; max-height: none; object-fit: cover;
  aspect-ratio: 16 / 11; filter: none;
}

/* Contact page — cinematic full-bleed hero background (Tehran at dusk) */
.page-hero--contact {
  max-width: none; width: 100%;
  padding: 200px 6vw 130px;
  position: relative; isolation: isolate;
  background:
    linear-gradient(to bottom, rgba(12,9,7,.45) 0%, rgba(12,9,7,.70) 55%, var(--bg) 100%),
    url(assets/contact-bg.webp) center 30% / cover no-repeat;
}
.page-hero--contact::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(120% 80% at 50% 0%, transparent 55%, rgba(12,9,7,.5));
}
.page-hero--contact .page-hero__sub { color: #d9cba6; }
@media (max-width: 760px) {
  .page-hero--contact { padding: 150px 6vw 90px; background-position: center 40%; }
}

/* About page — cinematic full-bleed hero background (Azadi Tower, Tehran) */
.page-hero--about {
  max-width: none; width: 100%;
  padding: 200px 6vw 130px;
  position: relative; isolation: isolate;
  background:
    linear-gradient(to bottom, rgba(12,9,7,.48) 0%, rgba(12,9,7,.72) 58%, var(--bg) 100%),
    url(assets/about-hero.webp) center 35% / cover no-repeat;
}
.page-hero--about::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(120% 80% at 50% 0%, transparent 55%, rgba(12,9,7,.5));
}
.page-hero--about .page-hero__sub { color: #d9cba6; }
@media (max-width: 760px) {
  .page-hero--about { padding: 150px 6vw 90px; background-position: center 40%; }
}


/* =========================================================
   V2 Pro — standalone product page (cinematic, image-forward)
   ========================================================= */
.v2x { overflow-x: clip; }

/* product sub-nav */
.v2x-subnav {
  display: none !important; /* removed: carried a 2nd VOCAL logo and, as the first in-flow element under the fixed nav, overlapped the language switcher (esp. RTL) */
  position: sticky; top: 64px; z-index: 800;
  align-items: center; justify-content: space-between;
  padding: 12px 6vw; max-width: 1340px; margin: 0 auto;
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  background: rgba(12,9,7,.55); border-bottom: 1px solid var(--line);
}
.v2x-subnav__name { display: inline-flex; align-items: center; gap: 10px; font-family: var(--font-display); font-weight: 700; font-size: 15px; }
.v2x-subnav__name img { height: 20px; opacity: .9; }
.v2x-subnav__links { display: flex; gap: 26px; }
.v2x-subnav__links a { font-family: var(--font-display); font-size: 14px; color: var(--muted); padding-bottom: 4px; border-bottom: 2px solid transparent; }
.v2x-subnav__links a:hover { color: #f0d088; border-color: #f0d088; }
body.is-loading .v2x-subnav { display: none; }

/* hero */
.v2x-hero { position: relative; min-height: 100vh; display: grid; align-items: safe center; overflow: hidden; padding-top: clamp(132px, 15vh, 168px); padding-bottom: clamp(48px, 7vh, 92px); }
.v2x-hero__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; }
.v2x-hero::after { content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to right, rgba(8,6,4,.94) 0%, rgba(8,6,4,.6) 40%, transparent 68%),
              linear-gradient(to top, var(--bg) 4%, transparent 36%); }
html[dir="rtl"] .v2x-hero::after {
  background: linear-gradient(to left, rgba(8,6,4,.94) 0%, rgba(8,6,4,.6) 40%, transparent 68%),
              linear-gradient(to top, var(--bg) 4%, transparent 36%); }
.v2x-hero__copy { max-width: 1340px; width: 100%; margin: 0 auto; padding: 0 6vw; }
.v2x-hero__model { display: block; font-family: var(--font-display); font-weight: 800; letter-spacing: -.02em;
  font-size: clamp(3rem, 9vw, 7.5rem); line-height: .92; }
.v2x-hero__model b { font-weight: 500; }
.v2x-hero__title { margin: 0; }
.v2x-hero__title .mask__in { font-family: var(--font-display); font-weight: 700; font-size: clamp(1.7rem, 4.4vw, 3.2rem); line-height: 1.06; }
/* short viewports (laptops, split windows, zoom) — shrink the hero type so the
   giant model word can never crowd or slip under the fixed nav */
@media (min-width: 901px) and (max-height: 780px) {
  .v2x-hero__model { font-size: clamp(2.4rem, 6vw, 4.4rem); }
  .v2x-hero__title .mask__in { font-size: clamp(1.5rem, 3.2vw, 2.3rem); }
  .v2x-hero__cta { margin-top: 22px; }
  .v2x-hero__chips { margin-top: 22px; gap: 20px; }
  .v2x-hero { padding-top: clamp(116px, 14vh, 140px); }
}
.v2x-hero__cta { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 34px; }
.v2x-hero__scroll { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); width: 26px; height: 42px; border: 2px solid rgba(240,208,136,.5); border-radius: 14px; }
.v2x-hero__scroll span { position: absolute; left: 50%; top: 8px; width: 4px; height: 8px; margin-left: -2px; border-radius: 2px; background: #f0d088; animation: v2xScroll 1.6s ease-in-out infinite; }
@keyframes v2xScroll { 0%,100% { transform: translateY(0); opacity: 1; } 60% { transform: translateY(14px); opacity: .2; } }

/* reusable full-bleed cinematic section */
.v2x { }
section.v2x[class*="v2x--"] {
  position: relative; min-height: 100vh; display: flex; align-items: center; overflow: hidden;
}
.v2x__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; }
.v2x__scrim { position: absolute; inset: 0; z-index: -1; pointer-events: none; }
.v2x__scrim--left  { background: linear-gradient(to right, rgba(12,9,7,.9), rgba(12,9,7,.35) 48%, transparent 72%); }
.v2x__scrim--right { background: linear-gradient(to left,  rgba(12,9,7,.9), rgba(12,9,7,.35) 48%, transparent 72%); }
.v2x__scrim--full  { background: radial-gradient(120% 90% at 50% 50%, transparent, rgba(12,9,7,.78)); }
.v2x__copy { max-width: 1340px; width: 100%; margin: 0 auto; padding: 0 6vw; }
.v2x__copy > p { color: #d9cba6; max-width: 440px; margin-top: 16px; }
.v2x--right .v2x__copy { text-align: left; }
.v2x--left .v2x__copy--end { margin-inline-start: auto; text-align: right; max-width: 1340px; }
.v2x--left .v2x__copy--end > * { margin-inline-start: auto; }
.v2x--left .v2x__copy--end p { margin-inline-start: auto; }
.v2x--center .v2x__copy--mid { text-align: center; }
.v2x--center .v2x__copy--mid p { margin: 16px auto 0; }
.v2x__title { font-family: var(--font-display); font-weight: 800; font-size: clamp(2rem, 5.2vw, 4rem); line-height: 1.04; letter-spacing: -.02em; }
.v2x__big { display: block; font-family: var(--font-display); font-weight: 800; font-size: clamp(4rem, 12vw, 9rem); line-height: .9; }
.v2x__chips { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 22px; }
.v2x__chips span { font-family: var(--font-display); font-size: 12.5px; font-weight: 600; color: #f0d088;
  border: 1px solid rgba(240,208,136,.3); border-radius: 99px; padding: 7px 14px; }
.v2x--left .v2x__copy--end .v2x__chips { justify-content: flex-end; }

/* display section */
.v2x-display { text-align: center; padding: 120px 6vw 0; overflow: hidden; }
.v2x-display__stats { display: flex; justify-content: center; flex-wrap: wrap; gap: 40px; margin: 40px 0 10px; }
.v2x-display__stats b { display: block; font-family: var(--font-display); font-weight: 800; font-size: 2rem; color: #f0d088; }
.v2x-display__stats span { font-size: 13px; color: var(--dim); }
.v2x-display__media { margin-top: 10px; }
.v2x-display__media img { width: min(760px, 94%); margin: 0 auto; border-radius: 18px; filter: drop-shadow(0 40px 70px rgba(0,0,0,.7)); }

/* OS */
.v2x-os { text-align: center; }
.v2x-os__v { font-family: var(--font-display); font-weight: 800; font-size: clamp(2rem, 5vw, 3.4rem); margin: 8px 0 12px; }

/* specs + box (shared) */
.v2x-specs__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; max-width: 1200px; margin: 0 auto; }
.spec-card { padding: 24px; border-radius: 18px; border: 1px solid var(--line); background: linear-gradient(168deg, var(--surface), #14100c); }
.spec-card h4 { font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; color: #f0d088; margin-bottom: 14px; }
.spec-card dl { display: grid; grid-template-columns: auto 1fr; gap: 8px 16px; margin: 0; }
.spec-card dt { color: var(--dim); font-size: 13px; }
.spec-card dd { margin: 0; font-size: 14px; }
.v2x-box__grid { list-style: none; display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; max-width: 900px; margin: 0 auto; padding: 0; }
.v2x-box__grid li { display: inline-flex; align-items: center; gap: 10px; padding: 14px 20px; border-radius: 99px; border: 1px solid var(--line); background: var(--surface); font-family: var(--font-display); font-weight: 600; font-size: .95rem; }
.v2x-box__grid span { font-size: 18px; }

@media (max-width: 900px) {
  .v2x-subnav { top: 58px; }
  .v2x-hero { min-height: 100svh; align-items: end; }
  .v2x-hero::after, html[dir="rtl"] .v2x-hero::after { background: linear-gradient(to top, rgba(8,6,4,.97) 3%, rgba(8,6,4,.72) 42%, rgba(8,6,4,.34) 76%, transparent 100%); }
  .v2x-hero__copy { text-align: center; padding-bottom: 13vh; }
  .v2x-hero__cta { justify-content: center; }
  .v2x-hero__scroll { display: none; }
  .v2x__copy, .v2x--left .v2x__copy--end, .v2x--center .v2x__copy--mid { text-align: center; }
  .v2x--left .v2x__copy--end > *, .v2x--left .v2x__copy--end p { margin-inline: auto; }
  .v2x__scrim--left, .v2x__scrim--right { background: linear-gradient(to top, rgba(12,9,7,.92) 8%, rgba(12,9,7,.5) 50%, transparent 86%); }
  .v2x__copy > p { margin-inline: auto; }
  .v2x--left .v2x__copy--end .v2x__chips, .v2x__chips { justify-content: center; }
  .v2x-display__stats { gap: 26px; }
  .v2x-specs__grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 560px) { .v2x-specs__grid { grid-template-columns: 1fr; } }

/* V2 Pro — additions: hero chips, sub-nav active, gallery, colours */
.v2x-hero__chips { list-style: none; display: flex; gap: 28px; margin: 34px 0 0; padding: 0; flex-wrap: wrap; }
.v2x-hero__chips li { display: flex; flex-direction: column; }
.v2x-hero__chips b { font-family: var(--font-display); font-weight: 800; font-size: 1.4rem; color: #f0d088; }
.v2x-hero__chips span { font-size: 12.5px; color: var(--dim); margin-top: 2px; }
@media (max-width: 900px) { .v2x-hero__chips { justify-content: center; gap: 20px; } }

.v2x-subnav__links a.is-on { color: #f0d088; border-color: #f0d088; }

/* shot-on gallery */
.v2x-gallery__grid { display: grid; grid-template-columns: 2fr 1fr; grid-auto-rows: 240px; gap: 16px; max-width: 1200px; margin: 0 auto; }
.v2x-shot { position: relative; margin: 0; border-radius: 16px; overflow: hidden; border: 1px solid var(--line); }
.v2x-shot img { width: 100%; height: 100%; object-fit: cover; transition: transform .6s var(--ease); }
.v2x-shot:hover img { transform: scale(1.06); }
.v2x-shot--wide { grid-row: span 2; }
.v2x-shot figcaption {
  position: absolute; left: 14px; bottom: 12px; z-index: 2;
  font-family: var(--font-display); font-size: 12px; font-weight: 600; color: #fff6d8;
  background: rgba(8,6,4,.6); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  border: 1px solid rgba(240,208,136,.25); padding: 5px 11px; border-radius: 99px;
}

/* colours — static display: phone in white + the two finishes it ships in */
.v2x-colours { text-align: center; overflow: hidden; }
.v2x-colours__stage { display: grid; place-items: center; min-height: 460px; }
.v2x-colours__phone { width: min(360px, 80%); filter: drop-shadow(0 40px 70px rgba(0,0,0,.6)); }
.v2x-colours__legend { display: inline-flex; align-items: center; justify-content: center; gap: 34px; margin-top: 30px; flex-wrap: wrap; }
.v2x-swatch {
  display: inline-flex; align-items: center; gap: 11px;
  font-family: var(--font-display); font-size: 14px; font-weight: 600; color: #e9e0c4;
  letter-spacing: .1em; text-transform: uppercase;
}
.v2x-swatch i {
  width: 26px; height: 26px; border-radius: 50%; background: var(--c);
  border: 1px solid rgba(255,255,255,.22);
  box-shadow: 0 4px 14px rgba(0,0,0,.5), inset 0 2px 6px rgba(255,255,255,.16);
}
html[dir="rtl"] .v2x-swatch { letter-spacing: 0; }
/* interactive swatches (JS wires click → active + optional image swap) */
.v2x-swatch { cursor: pointer; transition: color .25s ease; -webkit-tap-highlight-color: transparent; }
.v2x-swatch:hover { color: #fff; }
.v2x-swatch i { transition: box-shadow .28s var(--ease), transform .28s var(--ease); }
.v2x-swatch.is-active { color: #fff; }
.v2x-swatch.is-active i { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--c), 0 6px 18px rgba(0,0,0,.55); transform: scale(1.1); }
.v2x-swatch:focus-visible { outline: none; }
.v2x-swatch:focus-visible i { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px #f0d088; }
.v2-colours__wide, .v2x-colours__phone { transition: opacity .18s ease; }

@media (max-width: 900px) {
  .v2x-gallery__grid { grid-template-columns: 1fr; grid-auto-rows: 220px; }
  .v2x-shot--wide { grid-row: auto; }
  .v2x-colours__stage { min-height: 360px; }
}

/* V2 Pro — dissolve the cinematic full-bleed sections into each other (no hard cuts).
   Tall, strong top/bottom fades to page bg so adjacent images melt together. */
section.v2x[class*="v2x--"] { isolation: isolate; }
section.v2x[class*="v2x--"]::before,
section.v2x[class*="v2x--"]::after {
  content: ""; position: absolute; left: 0; right: 0; height: 42vh; z-index: -1; pointer-events: none;
}
section.v2x[class*="v2x--"]::before { top: 0;
  background: linear-gradient(to bottom, var(--bg) 0%, var(--bg) 14%, rgba(12,9,7,.6) 46%, rgba(12,9,7,.25) 70%, transparent 100%); }
section.v2x[class*="v2x--"]::after  { bottom: 0;
  background: linear-gradient(to top,    var(--bg) 0%, var(--bg) 14%, rgba(12,9,7,.6) 46%, rgba(12,9,7,.25) 70%, transparent 100%); }
.v2x-hero { isolation: isolate; }

/* fade the plain dark sections that sit between cinematic ones, so the whole
   page reads as one continuous dissolve rather than stacked blocks */
.v2x-gallery, .v2x-display, .v2x-os, .v2x-5g, .v2x-colours { position: relative; }
.v2x-gallery::before, .v2x-os::before, .v2x-5g::before, .v2x-colours::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 22vh; z-index: 0;
  pointer-events: none; background: linear-gradient(to bottom, rgba(12,9,7,.5), transparent); }

/* V2 Pro — 5G spotlight */
.v2x-5g { text-align: center; padding: 130px 6vw; position: relative; overflow: hidden; }
.v2x-5g::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(60% 70% at 50% 40%, rgba(240,208,136,.12), transparent 70%); }
.v2x-5g__inner { max-width: 760px; margin: 0 auto; }
.v2x-5g__big { display: block; font-family: var(--font-display); font-weight: 800;
  font-size: clamp(6rem, 22vw, 16rem); line-height: .82; letter-spacing: -.04em; margin-bottom: 6px; }
.v2x-5g__row { list-style: none; display: flex; justify-content: center; flex-wrap: wrap; gap: 40px; margin: 36px 0 0; padding: 0; }
.v2x-5g__row b { display: block; font-family: var(--font-display); font-weight: 800; font-size: 1.7rem; color: #f0d088; }
.v2x-5g__row span { font-size: 13px; color: var(--dim); }
@media (max-width: 560px) { .v2x-5g__row { gap: 24px; } }

/* V2 Pro — in-page language switch (plain links, navigates between localized files) */
.lang--nav { display: inline-flex; align-items: center; gap: 7px; }
.lang--nav .lang__opt { color: var(--muted); font-family: var(--font-display); font-weight: 600; font-size: 13px; letter-spacing: .04em; text-decoration: none; transition: color .25s ease; }
.lang--nav .lang__opt:hover { color: #f0d088; }
.lang--nav .lang__opt.is-active { color: #f0d088; }
.lang--nav .lang__sep { color: var(--line); }

/* V2 Pro — keep the cinematic copy pinned to its scrim side in RTL (no logical flip),
   so Persian/Arabic text still sits over the darkened half for readability */
html[dir="rtl"] .v2x--left .v2x__copy--end { margin-left: auto; margin-right: 0; }
html[dir="rtl"] .v2x--left .v2x__copy--end > *,
html[dir="rtl"] .v2x--left .v2x__copy--end p { margin-left: auto; margin-right: 0; }
html[dir="rtl"] .v2x--left .v2x__copy--end .v2x__chips { justify-content: flex-end; }

/* V2 — camera-algorithm sample gallery (images carry their own captions) */
.v2-shots { padding-bottom: 40px; }
.v2-shots__grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; max-width: 1120px; margin: 0 auto; padding: 0 6vw; }
.v2-shots__grid figure { margin: 0; border-radius: 16px; overflow: hidden; background: #000; box-shadow: 0 18px 50px rgba(0,0,0,.45); }
.v2-shots__grid figure:first-child { grid-column: 1 / -1; }
.v2-shots__grid img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 760px) { .v2-shots__grid { grid-template-columns: 1fr; } }

/* V2 — gaming feature spotlight (three pillars) */
.v2-game { text-align: center; padding: 120px 6vw; position: relative; overflow: hidden; }
.v2-game::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(60% 70% at 50% 35%, rgba(240,208,136,.10), transparent 72%); }
.v2-game__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; max-width: 1040px; margin: 44px auto 0; text-align: left; }
.v2-game__card { border: 1px solid var(--line); border-radius: 18px; padding: 30px 26px; background: rgba(255,255,255,.02); }
.v2-game__card b { display: block; font-family: var(--font-display); font-weight: 800; font-size: 1.15rem; color: #f0d088; margin-bottom: 10px; }
.v2-game__card p { color: var(--muted); font-size: 14px; line-height: 1.6; }
html[dir="rtl"] .v2-game__grid { text-align: right; }
@media (max-width: 820px) { .v2-game__grid { grid-template-columns: 1fr; } }

/* V2 — colours showcase uses a wide dual-phone image instead of a single render */
.v2-colours__wide { width: min(860px, 92%); border-radius: 18px; display: block; margin: 0 auto; filter: drop-shadow(0 40px 70px rgba(0,0,0,.55)); }

/* V2 Lite — colour pair (two labelled finish shots side by side) */
.v2-colours__pair { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; max-width: 1020px; margin: 0 auto 6px; padding: 0 6vw; }
.v2-colours__pair img { width: 100%; height: 100%; object-fit: cover; border-radius: 16px; display: block; background: #000; box-shadow: 0 18px 50px rgba(0,0,0,.45); }
@media (max-width: 700px) { .v2-colours__pair { grid-template-columns: 1fr; } }

/* V2 Lite — centered performance + product gallery (crisp, native-size assets) */
.v2x__chips--center { justify-content: center; margin-top: 24px; }
.v2-perf__media { width: min(320px, 66%); margin: 36px auto 0; display: block; border-radius: 20px; filter: drop-shadow(0 30px 60px rgba(0,0,0,.6)); }
.v2lite-gallery { padding-bottom: 30px; }
.v2lite-gallery__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; max-width: 1020px; margin: 0 auto; padding: 0 6vw; }
.v2lite-gallery__grid figure { margin: 0; border-radius: 16px; overflow: hidden; aspect-ratio: 16/10; background: #0f0f0f; box-shadow: 0 16px 44px rgba(0,0,0,.42); }
.v2lite-gallery__grid img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 700px) { .v2lite-gallery__grid { grid-template-columns: 1fr; } }

/* V11 — smart-design card icons + super-resolution trio */
.v2-game__card img { width: 54px; height: 54px; object-fit: contain; display: block; margin-bottom: 14px; }
.v11-trio { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; max-width: 1080px; margin: 0 auto; padding: 0 6vw; }
.v11-trio figure { margin: 0; position: relative; border-radius: 16px; overflow: hidden; aspect-ratio: 3/2; background: #0f0f0f; box-shadow: 0 16px 44px rgba(0,0,0,.42); }
.v11-trio img { width: 100%; height: 100%; object-fit: cover; display: block; }
.v11-trio figcaption { position: absolute; left: 0; right: 0; bottom: 0; padding: 12px; text-align: center; font-family: var(--font-display); font-weight: 600; font-size: 13px; letter-spacing: .04em; color: #fff; background: linear-gradient(to top, rgba(0,0,0,.65), transparent); }
@media (max-width: 700px) { .v11-trio { grid-template-columns: 1fr; } }

/* V11 — magical hero with a floating phone + extra motion */
.v11-hero .v2x-hero__copy { position: relative; z-index: 2; }
.v11-hero__phone {
  position: absolute; right: 3vw; top: 0; bottom: 0; margin-block: auto; height: fit-content;
  width: min(560px, 46vw); z-index: 1; pointer-events: none; will-change: transform;
  filter: drop-shadow(0 50px 90px rgba(0,0,0,.55));
}
.v11-hero__glow {
  position: absolute; right: 8vw; top: 0; bottom: 0; margin-block: auto; width: 460px; height: 460px; z-index: 0;
  pointer-events: none; border-radius: 50%; will-change: transform, opacity;
  background: radial-gradient(circle, rgba(150,120,255,.28), rgba(240,208,136,.12) 45%, transparent 70%);
  filter: blur(20px);
}
@media (max-width: 880px) {
  .v11-hero__phone { position: static; transform: none; width: min(380px, 78%); margin: 26px auto 0; display: block; }
  .v11-hero__glow { display: none; }
  .v11-hero .v2x-hero__copy { text-align: center; }
  .v11-hero .v2x-hero__chips { justify-content: center; }
  .v11-hero .v2x-hero__cta { justify-content: center; }
}

/* V11 — colour cards zoom onto the phone (source shots have a lot of empty margin) */
.v11-colours .v2-colours__pair { max-width: 720px; }
.v11-colours .v2-colours__pair img { aspect-ratio: 3/4; object-fit: cover; object-position: 50% 42%; background: #f1f1f3; }
@media (max-width: 700px) { .v11-colours .v2-colours__pair img { aspect-ratio: 4/5; } }

/* V1 Core — living animated aurora background behind the floating phone */
.v1c-hero { background: radial-gradient(140% 130% at 50% -10%, #15161e, #0c0907 60%); }
.v1c-hero .v11-hero__glow { z-index: 2; background: radial-gradient(circle, rgba(96,170,210,.30), rgba(150,210,170,.12) 45%, transparent 70%); }
.v1c-hero .v11-hero__phone { z-index: 3; }
.v1c-hero .v2x-hero__copy { z-index: 4; }
.v1c-hero .v2x-hero__scroll { z-index: 5; }
/* dissolve the hero's foot into the page bg so it flows into the next section */
.v1c-hero__fade { position: absolute; left: 0; right: 0; bottom: 0; height: 40vh; z-index: 1; pointer-events: none;
  background: linear-gradient(to top, var(--bg) 0%, var(--bg) 6%, rgba(12,9,7,.6) 42%, transparent 100%); }

.v1c-aura { position: absolute; inset: -12%; z-index: 0; pointer-events: none; overflow: hidden; filter: blur(46px); }
.v1c-aura span { position: absolute; border-radius: 50%; mix-blend-mode: screen; will-change: transform; }
.v1c-aura span:nth-child(1) { width: 50vw; height: 50vw; left: -6%; top: -10%;
  background: radial-gradient(circle, rgba(72,150,214,.55), transparent 66%); animation: v1cDrift1 19s ease-in-out infinite; }
.v1c-aura span:nth-child(2) { width: 44vw; height: 44vw; right: 2%; top: 6%;
  background: radial-gradient(circle, rgba(92,202,158,.46), transparent 66%); animation: v1cDrift2 23s ease-in-out infinite; }
.v1c-aura span:nth-child(3) { width: 42vw; height: 42vw; left: 28%; bottom: -16%;
  background: radial-gradient(circle, rgba(240,208,136,.38), transparent 66%); animation: v1cDrift3 27s ease-in-out infinite; }
.v1c-aura span:nth-child(4) { width: 30vw; height: 30vw; right: 22%; bottom: 2%;
  background: radial-gradient(circle, rgba(150,120,235,.34), transparent 66%); animation: v1cDrift1 31s ease-in-out infinite reverse; }
@keyframes v1cDrift1 { 0%,100% { transform: translate(0,0) scale(1); } 50% { transform: translate(13%,9%) scale(1.18); } }
@keyframes v1cDrift2 { 0%,100% { transform: translate(0,0) scale(1.06); } 50% { transform: translate(-12%,8%) scale(.9); } }
@keyframes v1cDrift3 { 0%,100% { transform: translate(0,0) scale(1); } 50% { transform: translate(9%,-12%) scale(1.2); } }
.v1c-hero__scrim { position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to right, rgba(10,10,13,.8), rgba(10,10,13,.25) 52%, transparent 78%); }
html[dir="rtl"] .v1c-hero__scrim { background: linear-gradient(to left, rgba(10,10,13,.8), rgba(10,10,13,.25) 52%, transparent 78%); }
@media (prefers-reduced-motion: reduce) { .v1c-aura span { animation: none; } }
@media (max-width: 880px) { .v1c-aura { filter: blur(36px); } .v1c-hero__scrim { background: linear-gradient(to bottom, rgba(10,10,13,.55), rgba(10,10,13,.4)); } }

/* V01 — Nebula Violet aurora (reuses the .v1c-aura / .v1c-hero__fade / __scrim system, recoloured) */
.v01-hero { background: radial-gradient(140% 130% at 50% -10%, #17131f, #0c0907 60%); }
.v01-hero .v11-hero__glow { background: radial-gradient(circle, rgba(162,140,236,.32), rgba(150,180,236,.12) 45%, transparent 70%); }
.v01-hero .v1c-aura span:nth-child(1) { background: radial-gradient(circle, rgba(150,128,236,.55), transparent 66%); }
.v01-hero .v1c-aura span:nth-child(2) { background: radial-gradient(circle, rgba(108,168,236,.46), transparent 66%); }
.v01-hero .v1c-aura span:nth-child(3) { background: radial-gradient(circle, rgba(238,160,206,.40), transparent 66%); }
.v01-hero .v1c-aura span:nth-child(4) { background: radial-gradient(circle, rgba(118,202,212,.32), transparent 66%); }
/* V01 colour swatch — show the iridescent finish on the chip */
.v2x-swatch i.v01-swatch-violet { background: linear-gradient(135deg, #b9a7ef, #a9c6f2 50%, #f0c2dc); }
/* V01 wide media frame for the design banner */
.v2x-display__media--wide img { width: min(1100px, 96%); }
/* V01 two-up colour cards — clean single phones on a soft light card */
.v01-colours .v2-colours__pair { max-width: 760px; }
.v01-colours .v2-colours__pair img { aspect-ratio: 3/4; object-fit: contain; padding: 6% 4%;
  background: radial-gradient(120% 120% at 50% 30%, #fbfbff, #eceef5); }
@media (max-width: 700px) { .v01-colours .v2-colours__pair img { aspect-ratio: 4/5; } }

/* V01 — page-wide drifting Nebula aurora (the motion background, behind all content) */
.v01-page-aura { position: fixed; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; }
.v01-page-aura span { position: absolute; border-radius: 50%; filter: blur(80px); mix-blend-mode: screen; opacity: .42; will-change: transform; }
.v01-page-aura span:nth-child(1) { width: 46vw; height: 46vw; left: -8%; top: 6%;
  background: radial-gradient(circle, rgba(150,128,236,.5), transparent 68%); animation: v1cDrift1 26s ease-in-out infinite; }
.v01-page-aura span:nth-child(2) { width: 42vw; height: 42vw; right: -6%; top: 36%;
  background: radial-gradient(circle, rgba(108,168,236,.44), transparent 68%); animation: v1cDrift2 31s ease-in-out infinite; }
.v01-page-aura span:nth-child(3) { width: 40vw; height: 40vw; left: 22%; bottom: -8%;
  background: radial-gradient(circle, rgba(238,160,206,.36), transparent 68%); animation: v1cDrift3 35s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .v01-page-aura span { animation: none; } }

/* ===== V0 — pastel-iridescent aurora, animated video media, floating close-up ===== */
.v0-hero { background: radial-gradient(140% 130% at 50% -10%, #1b1620, #0c0907 60%); }
/* Higgsfield-generated hero backdrop with a slow ken-burns drift for motion */
.v0-hero .v0-herobg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  z-index: 0; opacity: .95; will-change: transform; animation: v0HeroKen 22s ease-in-out infinite alternate; }
@keyframes v0HeroKen { from { transform: scale(1.05); } to { transform: scale(1.15) translate(-2.5%, -1.5%); } }
@media (prefers-reduced-motion: reduce) { .v0-hero .v0-herobg { animation: none; } }
.v0-hero .v11-hero__glow { background: radial-gradient(circle, rgba(228,150,210,.22), rgba(150,170,236,.08) 45%, transparent 70%); }
.v0-hero .v1c-aura span:nth-child(1) { background: radial-gradient(circle, rgba(236,150,205,.52), transparent 66%); }
.v0-hero .v1c-aura span:nth-child(2) { background: radial-gradient(circle, rgba(150,150,238,.46), transparent 66%); }
.v0-hero .v1c-aura span:nth-child(3) { background: radial-gradient(circle, rgba(150,212,222,.40), transparent 66%); }
.v0-hero .v1c-aura span:nth-child(4) { background: radial-gradient(circle, rgba(244,196,160,.30), transparent 66%); }

.v0-page-aura { position: fixed; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; }
.v0-page-aura span { position: absolute; border-radius: 50%; filter: blur(80px); mix-blend-mode: screen; opacity: .4; will-change: transform; }
.v0-page-aura span:nth-child(1) { width: 46vw; height: 46vw; left: -8%; top: 6%;
  background: radial-gradient(circle, rgba(236,150,205,.5), transparent 68%); animation: v1cDrift1 27s ease-in-out infinite; }
.v0-page-aura span:nth-child(2) { width: 42vw; height: 42vw; right: -6%; top: 36%;
  background: radial-gradient(circle, rgba(150,150,238,.44), transparent 68%); animation: v1cDrift2 32s ease-in-out infinite; }
.v0-page-aura span:nth-child(3) { width: 40vw; height: 40vw; left: 22%; bottom: -8%;
  background: radial-gradient(circle, rgba(150,212,222,.36), transparent 68%); animation: v1cDrift3 36s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .v0-page-aura span { animation: none; } }

/* centered featured animated media (framed) — works for <video> or animated webp <img> */
.v0-video { display: flex; justify-content: center; padding: 0 6vw; }
.v0-video video, .v0-video img { width: min(1000px, 96%); height: auto; border-radius: 18px; display: block;
  box-shadow: 0 40px 80px rgba(0,0,0,.6); background: #050505; }
.v0-video--screen video, .v0-video--screen img { width: min(1180px, 98%); border-radius: 22px; }

/* floating dark product close-up (transparent PNG) */
.v0-float { position: relative; display: flex; justify-content: center; padding: 8px 6vw 0; }
.v0-float img { width: min(560px, 80%); height: auto; display: block;
  filter: drop-shadow(0 50px 90px rgba(0,0,0,.75)); animation: v0FloatY 6s ease-in-out infinite; }
@keyframes v0FloatY { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-16px); } }
@media (prefers-reduced-motion: reduce) { .v0-float img { animation: none; } }

/* camera modes — three feature cards */
.v0-modes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; max-width: 1020px; margin: 0 auto; padding: 0 6vw; }
.v0-modes__card { background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.09); border-radius: 18px; padding: 32px 24px; text-align: center; }
.v0-modes__card img { width: 64px; height: 64px; object-fit: contain; margin: 0 auto 16px; display: block; }
.v0-modes__card h4 { font-size: 1.05rem; margin: 0 0 8px; color: #fff; }
.v0-modes__card p { font-size: .9rem; color: rgba(255,255,255,.6); margin: 0; line-height: 1.5; }
@media (max-width: 760px) { .v0-modes { grid-template-columns: 1fr; max-width: 420px; } }

/* V0 Core — 4-up colour grid (each finish shown separately) */
.v0core-cgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; max-width: 1000px; margin: 0 auto 6px; padding: 0 6vw; }
.v0core-cgrid figure { margin: 0; text-align: center; }
.v0core-cgrid img { width: 100%; height: auto; display: block; border-radius: 14px;
  background: radial-gradient(120% 120% at 50% 28%, #fbfbff, #eceef5); box-shadow: 0 16px 40px rgba(0,0,0,.4); }
.v0core-cgrid figcaption { margin-top: 10px; font-size: .88rem; letter-spacing: .02em; color: rgba(255,255,255,.66); }
@media (max-width: 700px) { .v0core-cgrid { grid-template-columns: 1fr 1fr; } }

/* ===== F-series (F1/F2/F4) — warm living page aura ===== */
.f-page-aura { position: fixed; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; }
.f-page-aura span { position: absolute; border-radius: 50%; filter: blur(90px); mix-blend-mode: screen; opacity: .34; will-change: transform; }
.f-page-aura span:nth-child(1) { width: 48vw; height: 48vw; right: -8%; bottom: -6%;
  background: radial-gradient(circle, rgba(224,168,92,.5), transparent 68%); animation: v1cDrift1 28s ease-in-out infinite; }
.f-page-aura span:nth-child(2) { width: 40vw; height: 40vw; left: -6%; top: 30%;
  background: radial-gradient(circle, rgba(184,120,70,.36), transparent 68%); animation: v1cDrift2 34s ease-in-out infinite; }
.f-page-aura span:nth-child(3) { width: 36vw; height: 36vw; left: 34%; top: -8%;
  background: radial-gradient(circle, rgba(210,150,90,.28), transparent 68%); animation: v1cDrift3 38s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .f-page-aura span { animation: none; } }
/* feature-phone hero: warm glow tint */
.f-hero .v11-hero__glow { background: radial-gradient(circle, rgba(224,168,92,.26), rgba(180,120,70,.1) 45%, transparent 70%); }
/* F2 — cool steel-teal aura variant (use with .f-page-aura for geometry) */
.f2-page-aura span:nth-child(1) { background: radial-gradient(circle, rgba(96,168,184,.46), transparent 68%); }
.f2-page-aura span:nth-child(2) { background: radial-gradient(circle, rgba(70,120,150,.34), transparent 68%); }
.f2-page-aura span:nth-child(3) { background: radial-gradient(circle, rgba(120,170,200,.26), transparent 68%); }
.f2-hero .v11-hero__glow { background: radial-gradient(circle, rgba(120,190,205,.24), rgba(70,120,150,.1) 45%, transparent 70%); }
/* F4 — graphite / platinum aura variant (use with .f-page-aura for geometry) */
.f4-page-aura span:nth-child(1) { background: radial-gradient(circle, rgba(176,186,198,.42), transparent 68%); }
.f4-page-aura span:nth-child(2) { background: radial-gradient(circle, rgba(120,132,148,.32), transparent 68%); }
.f4-page-aura span:nth-child(3) { background: radial-gradient(circle, rgba(150,168,190,.24), transparent 68%); }
.f4-hero .v11-hero__glow { background: radial-gradient(circle, rgba(190,200,214,.22), rgba(120,132,148,.09) 45%, transparent 70%); }

/* ===================================================================== */
/*  "Experience the Unforgettable" — interactive 3D packaging showpiece   */
/* ===================================================================== */
.unforgettable{
  position:relative; overflow:hidden; isolation:isolate;
  padding:clamp(96px,12vw,180px) 6vw;
  background:
    radial-gradient(96% 74% at 58% 30%, rgba(64,66,72,.55), rgba(24,22,22,0) 60%),
    linear-gradient(180deg, var(--bg) 0%, #17151a 34%, #131117 66%, var(--bg) 100%);
}
.unf__aura{
  position:absolute; left:60%; top:42%; width:62vw; height:62vw; max-width:900px; max-height:900px;
  transform:translate(-50%,-50%); pointer-events:none; z-index:0;
  background:radial-gradient(circle, rgba(224,196,150,.18), rgba(180,150,110,.06) 42%, transparent 66%);
  filter:blur(24px);
}
.unf__inner{
  position:relative; z-index:2; max-width:1240px; margin:0 auto;
  display:grid; grid-template-columns:1.05fr 1fr; align-items:center; gap:clamp(30px,5vw,80px);
}
.unf__copy{ max-width:520px; }
.unf__title{ margin:.55rem 0 1.1rem; line-height:1; font-size:clamp(2.2rem,5vw,4rem); font-weight:800; letter-spacing:-.035em; }
.unf__title .mask{ display:block; overflow:hidden; }
.unf__sub{ color:rgba(255,255,255,.62); font-size:clamp(1rem,1.35vw,1.14rem); line-height:1.62; max-width:44ch; }
.unf__actions{ display:flex; align-items:center; gap:22px; margin-top:2rem; flex-wrap:wrap; }
.unf__hint{ display:inline-flex; align-items:center; gap:8px; font-size:.82rem; letter-spacing:.04em; color:rgba(255,255,255,.5); }
.unf__hint-i{ display:inline-block; font-size:1rem; animation:unfSpinHint 3.4s linear infinite; }
@keyframes unfSpinHint{ to{ transform:rotate(360deg); } }
@media (prefers-reduced-motion: reduce){ .unf__hint-i{ animation:none; } }

/* stage + perspective */
.unf__stage{
  position:relative; z-index:2; height:clamp(360px,46vw,560px);
  display:flex; align-items:center; justify-content:center;
  perspective:1700px; perspective-origin:50% 42%;
}
.box3d{
  --bw:clamp(180px,20vw,258px); --bh:clamp(330px,37vw,472px); --bd:clamp(105px,11.4vw,147px);
  position:relative; width:var(--bw); height:var(--bh); direction:ltr;
  transform-style:preserve-3d; cursor:grab; touch-action:pan-y; user-select:none; -webkit-user-select:none;
  transform:rotateX(-8deg) rotateY(-28deg); will-change:transform;
}
.unf__stage.is-grabbing .box3d{ cursor:grabbing; }
.box3d__face{
  position:absolute; left:50%; top:50%; overflow:hidden; border-radius:9px;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.055), inset 0 2px 1px rgba(255,255,255,.06), inset 0 -34px 44px rgba(0,0,0,.4);
  background:linear-gradient(158deg,#161618,#0b0b0c 62%,#050506);
  backface-visibility:hidden;
}
.box3d__face--front { width:var(--bw); height:var(--bh); transform:translate(-50%,-50%) rotateY(0deg)   translateZ(calc(var(--bd)/2)); }
.box3d__face--back  { width:var(--bw); height:var(--bh); transform:translate(-50%,-50%) rotateY(180deg) translateZ(calc(var(--bd)/2)); }
.box3d__face--right { width:var(--bd); height:var(--bh); transform:translate(-50%,-50%) rotateY(90deg)  translateZ(calc(var(--bw)/2)); }
.box3d__face--left  { width:var(--bd); height:var(--bh); transform:translate(-50%,-50%) rotateY(-90deg) translateZ(calc(var(--bw)/2)); }
.box3d__face--top   { width:var(--bw); height:var(--bd); transform:translate(-50%,-50%) rotateX(90deg)  translateZ(calc(var(--bh)/2)); }
.box3d__face--bottom{ width:var(--bw); height:var(--bd); transform:translate(-50%,-50%) rotateX(-90deg) translateZ(calc(var(--bh)/2)); }

/* front artwork */
.box3d__face--front{ display:flex; flex-direction:column; align-items:center; justify-content:center;
  background:
    radial-gradient(115% 68% at 50% 40%, rgba(72,72,80,.5), rgba(12,12,14,0) 58%),
    linear-gradient(160deg,#18181b,#0b0b0c 60%,#050506); }
.bx-face-img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; display:block; }
.bx-glow{ position:absolute; left:50%; top:39%; width:80%; height:54%; transform:translate(-50%,-50%);
  background:radial-gradient(circle, rgba(255,255,255,.17), transparent 62%); filter:blur(7px); pointer-events:none; }
.bx-tl{ position:absolute; top:5.5%; left:8.5%; display:flex; align-items:baseline; gap:5px; }
.bx-tl b{ font-size:clamp(13px,1.7vw,19px); font-weight:900; color:#fff; letter-spacing:.4px; }
.bx-tl i{ font-style:normal; font-size:clamp(7px,.85vw,9px); font-weight:800; letter-spacing:1.4px; color:#c8c8cc; }
.bx-badge{ position:absolute; top:5.2%; right:7%; display:flex; flex-direction:column; align-items:flex-end; line-height:1.05;
  padding:6px 9px; border:1px solid rgba(255,255,255,.32); border-radius:7px; background:rgba(255,255,255,.03); }
.bx-badge b{ font-size:clamp(11px,1.5vw,16px); font-weight:900; color:#fff; letter-spacing:.4px; }
.bx-badge i{ font-style:normal; font-size:clamp(5.5px,.75vw,7.5px); letter-spacing:.3px; color:rgba(255,255,255,.7); margin-top:3px; }
.bx-badge .bx-5g{ font-size:clamp(13px,1.9vw,20px); margin-top:4px; }
.bx-emblem{ position:relative; z-index:2; width:40%; margin-top:2%; }
.bx-emblem svg{ width:100%; height:auto; display:block; filter:drop-shadow(0 4px 16px rgba(0,0,0,.55)); }
.bx-wordmark{ position:relative; z-index:2; width:47%; margin-top:11%; opacity:.96; filter:drop-shadow(0 2px 6px rgba(0,0,0,.5)); }
.bx-tag{ position:absolute; left:0; right:0; bottom:4.5%; text-align:center; font-size:clamp(5px,.72vw,7.5px); letter-spacing:.4px; color:rgba(255,255,255,.45); padding:0 10%; }

/* back */
.box3d__face--back{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:9%; padding:16% 12%; }
.box3d__face--back img{ width:52%; opacity:.8; }
.bx-back{ font-size:clamp(7px,.9vw,10px); letter-spacing:1px; color:rgba(255,255,255,.5); text-align:center; line-height:1.8; }

/* spines */
.box3d__face--right, .box3d__face--left{ display:flex; align-items:center; justify-content:center;
  background:linear-gradient(180deg,#151517,#0a0a0b); }
.bx-spine{ white-space:nowrap; font-weight:800; letter-spacing:5px; font-size:clamp(11px,1.3vw,15px); color:#fff; }
.bx-spine b{ color:#bdbdc0; font-weight:600; margin-left:6px; }
.box3d__face--right .bx-spine{ transform:rotate(-90deg); }
.box3d__face--left  .bx-spine{ transform:rotate(90deg); }

/* top lid + bottom */
.box3d__face--top{ display:flex; align-items:center; justify-content:center; gap:12px;
  background:linear-gradient(120deg,#1b1b1e,#0d0d0e 70%); }
.box3d__face--top img{ width:32%; max-width:96px; opacity:.9; }
.box3d__face--top span{ font-size:clamp(7px,.9vw,10px); letter-spacing:3px; font-weight:800; color:rgba(255,255,255,.7); }
.box3d__face--bottom{ background:linear-gradient(120deg,#101011,#060607); }

/* floor contact shadow */
.box3d__reflection{ position:absolute; left:50%; bottom:9%; width:min(66%,320px); height:44px; transform:translateX(-50%);
  background:radial-gradient(ellipse at center, rgba(0,0,0,.6), transparent 70%); filter:blur(12px); z-index:1; pointer-events:none; }

@media (max-width:900px){
  .unf__inner{ grid-template-columns:1fr; text-align:center; gap:14px; }
  .unf__copy{ margin:0 auto; }
  .unf__sub{ margin-left:auto; margin-right:auto; }
  .unf__actions{ justify-content:center; }
  .unf__stage{ order:-1; height:clamp(320px,80vw,440px); }
}
[dir="rtl"] .unf__actions{ flex-direction:row-reverse; }

/* =========================================================
   EDIT-V01 — global revision (loader, header RTL, icons,
   whole-phrase gradients, copy alignment)
   ========================================================= */

/* ---- new minimal preloader: logo + one linear filling bar ---- */
.preloader__simple { display: flex; flex-direction: column; align-items: center; gap: 34px; }
.preloader__logo { width: clamp(150px, 22vw, 230px); height: auto; display: block; animation: preLogoIn 1s var(--ease-out) both; }
@keyframes preLogoIn { from { opacity: 0; transform: translateY(18px) scale(.96); filter: blur(6px); } to { opacity: 1; transform: none; filter: none; } }
.preloader__line { width: clamp(180px, 26vw, 260px); height: 2px; border-radius: 2px; background: rgba(255,255,255,.14); overflow: hidden; }
.preloader__line span { display: block; height: 100%; width: 0%; border-radius: 2px;
  background: linear-gradient(90deg, #a8842f, #f0d088 55%, #fff6d8);
  box-shadow: 0 0 12px rgba(240,208,136,.65); }
html.no-intro .preloader { display: none !important; }

/* ---- header: identical layout in every language (logo left / menu center / lang right) ---- */
html[dir="rtl"] .nav__inner { direction: ltr; }
html[dir="rtl"] .nav__links a { direction: rtl; }

/* ---- whole-phrase gold gradient once the count-up settles ---- */
.hstat__n.odo-done, .bigstat__n.odo-done, .v2x__big.odo-done, .v2x-hero__model.odo-done {
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}

/* ---- white LINE icons replace emojis (in-the-box grids etc.) ---- */
.v2x-box__grid span.ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; border-radius: 12px;
  border: 1px solid rgba(255,255,255,.18); background: rgba(255,255,255,.05);
}
.v2x-box__grid span.ico svg { width: 24px; height: 24px; stroke: #fff; fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }

/* ---- generic copy vertical centering inside image frames ---- */
section.v2x[class*="v2x--"] { display: flex; align-items: center; }
section.v2x[class*="v2x--"] .v2x__copy { padding-block: clamp(60px, 9vh, 120px); }

/* chips: mixed-script safety so trailing latin glyphs (G / mAh) never clip in RTL */
.v2x-hero__chips b, .hstat__n, .bigstat__n { unicode-bidi: isolate; }
.v2x-hero__chips li b { padding-inline-end: .06em; }

/* hero sub: honour the two-line break after the comma */
.hero__sub { white-space: pre-line; }

/* =========================================================
   EDIT-V01 — layout pass: hero sides, edge heroes, f-series
   duo heroes, colour stages, RTL copy anchoring
   ========================================================= */

/* hero copy pinned to the RIGHT side (v2 / v11 / v0-core EN + v2-lite fa-ar) */
.hero-side-right .v2x-hero__copy { margin-left: auto; max-width: 640px; padding-left: 0; padding-right: 6vw; text-align: left; }
html[dir="rtl"] .hero-side-right .v2x-hero__copy { text-align: right; }
.hero-side-right.v2x-hero::after {
  background: linear-gradient(to left, rgba(8,6,4,.94) 0%, rgba(8,6,4,.6) 40%, transparent 68%),
              linear-gradient(to top, var(--bg) 4%, transparent 36%);
}
html[dir="rtl"] .hero-side-right.v2x-hero::after {
  background: linear-gradient(to right, rgba(8,6,4,.94) 0%, rgba(8,6,4,.6) 40%, transparent 68%),
              linear-gradient(to top, var(--bg) 4%, transparent 36%);
}

/* RTL heroes without the modifier keep the copy on the LEFT, text reads RTL */
html[dir="rtl"] .v2x-hero .v2x-hero__copy { text-align: right; }

/* EN — every section copy anchors LEFT, flush with the header logo */
.v2x--left .v2x__copy--end { margin-inline-start: 0 !important; text-align: left !important; }
.v2x--left .v2x__copy--end > *, .v2x--left .v2x__copy--end p { margin-inline-start: 0 !important; }
.v2x--left .v2x__copy--end .v2x__chips { justify-content: flex-start !important; }

/* FA/AR — section copy block stays LEFT (aligned with logo), text RTL */
html[dir="rtl"] .v2x--right .v2x__copy,
html[dir="rtl"] .v2x--left .v2x__copy--end { text-align: right !important; }
html[dir="rtl"] .v2x--left .v2x__copy--end > *,
html[dir="rtl"] .v2x--left .v2x__copy--end p { margin-inline-start: 0 !important; }
html[dir="rtl"] .v2x--left .v2x__copy--end .v2x__chips { justify-content: flex-start !important; }

/* model wordmark: identical stroke weight for the digits (V1 fa / V11) */
html[dir="rtl"] .v2x-hero__model b { font-weight: 800; }
.v11-hero .v2x-hero__model b { font-weight: 800; }

/* V1 Core — hero image glued to the RIGHT edge */
.v1c-hero__edge {
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  height: min(94vh, 940px); width: auto; max-width: 64vw;
  object-fit: cover; object-position: right center; z-index: -1;
  -webkit-mask-image: linear-gradient(to left, #000 58%, transparent 99%);
          mask-image: linear-gradient(to left, #000 58%, transparent 99%);
}
html[dir="rtl"] .v1c-hero__edge { right: auto; left: 0; -webkit-mask-image: linear-gradient(to right, #000 58%, transparent 99%); mask-image: linear-gradient(to right, #000 58%, transparent 99%); }

/* V01 — bigger hero phones, nudged left */
.v01-hero-big { transform: scale(1.16) translateX(-5%); transform-origin: bottom right; }

/* F-series — duo phone hero with a travelling light on the screens */
.fhero-duo { position: absolute; right: 4vw; bottom: 0; height: 80%; display: flex; align-items: flex-end; gap: 2vw; z-index: -1; overflow: hidden; }
.fhero-duo img { height: 100%; width: auto; object-fit: contain; filter: drop-shadow(0 34px 60px rgba(0,0,0,.6)); animation: ffloat 7s ease-in-out infinite; }
.fhero-duo__b { height: 84%; opacity: .94; animation-delay: -3.5s; }
.fhero-duo__sheen { position: absolute; inset: -5%; pointer-events: none; mix-blend-mode: screen;
  background: linear-gradient(112deg, transparent 38%, rgba(240,208,136,.20) 50%, transparent 62%);
  background-size: 260% 100%; animation: fsheen 5s ease-in-out infinite; }
@keyframes ffloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-14px); } }
@keyframes fsheen { 0% { background-position: 160% 0; } 55%, 100% { background-position: -160% 0; } }
html[dir="rtl"] .fhero-duo { right: auto; left: 4vw; }

/* F-series colour stage — the two new finish photos */
.fcol-stage { display: flex; gap: clamp(16px, 3vw, 42px); align-items: center; justify-content: center; padding: clamp(24px, 4vw, 56px) 0 10px; flex-wrap: wrap; }
.fcol-stage img { width: min(42vw, 430px); height: auto; border-radius: 18px; }

/* V2 Pro finishes — interactive white / graphite black */
.v2x-colours__stage { position: relative; display: grid; place-items: center; }
.v2x-colours__stage .js-colour-img { transition: opacity .45s ease; }
.v2x-colours__stage .js-colour-img:not(.is-active) { position: absolute; inset: 0; opacity: 0; pointer-events: none; }
button.v2x-swatch { cursor: pointer; font: inherit; color: inherit; background: none; }
button.v2x-swatch.is-active { color: #f0d088; }

/* 3D box — the new SVG faces */
.bx-face-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bx-face-img--top { object-fit: contain; padding: 7%; background: #efe7d7; }

/* =========================================================
   EDIT-V02 — new alignment system (Mode 1 / 2 / 3) + assets
   Mode 1 (EN):   left-aligned text, block on the LEFT
   Mode 2 (FA/AR): RTL text, block on the RIGHT (default RTL)
   Mode 3 (all):  fully centered
   .m2l = Mode-2 text kept RTL but block anchored LEFT
   ========================================================= */

/* neutralize the V01 forced-left RTL overrides — RTL default is now Mode 2 */
html[dir="rtl"] .v2x--left .v2x__copy--end { text-align: right !important; }
html[dir="rtl"] .v2x--left .v2x__copy--end > *,
html[dir="rtl"] .v2x--left .v2x__copy--end p { margin-inline-start: auto !important; }
html[dir="rtl"] .v2x--left .v2x__copy--end .v2x__chips { justify-content: flex-end !important; }

/* Mode 3 — centered block, all languages */
.v2x__copy.m3, .v2x-hero__copy.m3 { text-align: center !important; max-width: 720px; margin-inline: auto; }
.v2x__copy.m3 > *, .v2x-hero__copy.m3 > * { margin-inline: auto !important; }
.v2x__copy.m3 .v2x__chips, .v2x-hero__copy.m3 .v2x__chips { justify-content: center !important; }

/* Mode 2 on the LEFT — RTL text, block anchored left (aligned with logo) */
.v2x__copy.m2l, .v2x-hero__copy.m2l {
  width: auto; max-width: 660px; margin-right: auto; margin-left: 0;
  padding-left: 6vw; padding-right: 0; text-align: right !important;
}
.v2x__copy.m2l > *, .v2x-hero__copy.m2l > * { margin-inline: 0 auto !important; }
.v2x__copy.m2l .v2x__chips, .v2x-hero__copy.m2l .v2x__chips { justify-content: flex-start !important; }

/* Mode 1 — left-aligned text even on RTL pages */
.v2x__copy.m1, .v2x-hero__copy.m1 { text-align: left !important; }
.v2x__copy.m1 > *, .v2x-hero__copy.m1 > * { margin-inline: 0 auto !important; }

/* "a bit higher" */
.v2x__copy.hi, .v2x-hero__copy.hi { position: relative; top: -50px; }

/* ---- V2 Pro: flowing-light hero with the transparent phones ---- */
.v2pro-flow {
  position: absolute; inset: 0; z-index: -3; overflow: hidden;
  background:
    radial-gradient(90vw 70vh at 78% 38%, rgba(214,120,40,.34), transparent 62%),
    radial-gradient(70vw 55vh at 62% 72%, rgba(150,32,84,.22), transparent 66%),
    radial-gradient(110vw 80vh at 20% 20%, rgba(240,208,136,.10), transparent 60%),
    linear-gradient(115deg, #120b06 0%, #0c0907 46%, #150a10 78%, #0c0907 100%);
}
.v2pro-flow::before, .v2pro-flow::after {
  content: ""; position: absolute; inset: -30%; border-radius: 50%;
  filter: blur(70px); opacity: .5; mix-blend-mode: screen;
  background: conic-gradient(from 90deg at 50% 50%,
    transparent 0deg, rgba(240,150,60,.30) 70deg, rgba(240,208,136,.16) 130deg,
    transparent 190deg, rgba(190,60,120,.22) 260deg, transparent 330deg);
  animation: v2proSwirl 26s linear infinite;
}
.v2pro-flow::after { animation-duration: 38s; animation-direction: reverse; opacity: .34; }
@keyframes v2proSwirl { from { transform: rotate(0deg) scale(1.05); } to { transform: rotate(360deg) scale(1.05); } }
.v2pro-phones {
  position: absolute; right: 5vw; top: 50%; transform: translateY(-50%);
  height: min(88vh, 780px); width: auto; z-index: -1;
  filter: drop-shadow(0 40px 80px rgba(0,0,0,.66));
  animation: v2proFloat 8s ease-in-out infinite;
}
@keyframes v2proFloat { 0%,100% { transform: translateY(-50%); } 50% { transform: translateY(calc(-50% - 16px)); } }
html[dir="rtl"] .v2pro-phones { right: auto; left: 5vw; }
html[dir="rtl"] .v2pro-flow { background:
    radial-gradient(90vw 70vh at 22% 38%, rgba(214,120,40,.34), transparent 62%),
    radial-gradient(70vw 55vh at 38% 72%, rgba(150,32,84,.22), transparent 66%),
    radial-gradient(110vw 80vh at 80% 20%, rgba(240,208,136,.10), transparent 60%),
    linear-gradient(245deg, #120b06 0%, #0c0907 46%, #150a10 78%, #0c0907 100%); }

/* ---- V0: transparent phones pinned to the RIGHT ---- */
.v0-phones {
  position: absolute; right: 4vw; top: 50%; transform: translateY(-50%);
  height: min(86vh, 760px); width: auto; z-index: -1;
  filter: drop-shadow(0 40px 80px rgba(0,0,0,.6));
}
html[dir="rtl"] .v0-phones { right: auto; left: 4vw; }

/* ---- hero phones 30% bigger ---- */
.v11-hero .v2x-hero__bg { transform: scale(1.3); }
.v0-hero .v0-herobg { transform: scale(1.3); }
.v1c-hero__edge { height: min(94vh, 940px); }
.v1c-hero .v1c-hero__edge { height: min(120vh, 1200px); }
.v01-hero-big { transform: scale(1.3) translateX(-7%); }

/* ---- 5G chip: stop the top of G/5 from shaving ---- */
.v2x-hero__chips b { display: inline-block; line-height: 1.25; padding: .12em .1em .06em 0; }
.v2x-hero__chips li { overflow: visible; }

/* ---- F-series duo always on the RIGHT ---- */
html[dir="rtl"] .fhero-duo { right: 4vw; left: auto; }

/* ---- 3D box: every face shows its full artwork ---- */
.box3d__face { overflow: hidden; }
.bx-face-img { object-fit: fill; }
.bx-face-img--top { object-fit: contain; padding: 5%; background: #efe7d7; }

/* V02 correction: zoom only where explicitly flagged */
.hero-zoom .v2x-hero__bg, .hero-zoom .v0-herobg { transform: scale(1.3); }
.v0-hero .v0-herobg { transform: none; }
.v11-hero .v2x-hero__bg { transform: scale(1.3); }

/* V02: mode classes also work on v2x-display section heads */
.v2x-display .section__head.m2l { max-width: 660px; margin-right: auto; margin-left: 0; padding-left: 6vw; text-align: right !important; }
.v2x-display .section__head.m3 { text-align: center !important; max-width: 720px; margin-inline: auto; }
.v2x-display .section__head.m3 .section__sub { margin-inline: auto; }
.v2x-display .section__head.m1 { text-align: left !important; }
.v2x-display .section__head.hi { position: relative; top: -50px; }

/* V02 fix: every box face stretches its full artwork — nothing clipped */
.bx-face-img, .bx-face-img--top { object-fit: fill; padding: 0; background: none; }

/* =========================================================
   EDIT-V03 — precise anchors: right (header end) / left (logo V)
   ========================================================= */

/* Mode 2 on the RIGHT — RTL text, right edge flush with the header's last item */
.v2x__copy.m2r, .v2x-hero__copy.m2r {
  width: auto; max-width: 660px; margin-left: auto; margin-right: 0;
  padding-right: 6vw; padding-left: 0; text-align: right !important;
}
.v2x__copy.m2r > *, .v2x-hero__copy.m2r > * { margin-inline: auto 0 !important; }
.v2x__copy.m2r .v2x__chips, .v2x-hero__copy.m2r .v2x__chips { justify-content: flex-end !important; }

/* single-line phrases */
.oneline, .v2x__copy.oneline p, .v2x-hero__copy.oneline p { white-space: nowrap; }
.v2x__copy.oneline .mask__in, .v2x-hero__copy.oneline .mask__in { white-space: nowrap; }

/* Mode 3 at the TOP of the frame */
.v2x__copy.m3t, .v2x-hero__copy.m3t {
  text-align: center !important; max-width: 760px; margin-inline: auto;
  margin-bottom: 30vh; align-self: flex-start; margin-top: 10vh;
}
.v2x__copy.m3t > *, .v2x-hero__copy.m3t > * { margin-inline: auto !important; }

/* F-series duo: LEFT on RTL pages (text goes right) */
html[dir="rtl"] .fhero-duo { right: auto; left: 4vw; }

/* BOX round: three PNG sides centered on the plain black face; back is empty */
.bx-face-art { object-fit: contain; padding: 0; background: none; }
.box3d__face--back { background: linear-gradient(158deg, #17171a, #060607 70%); }

/* =========================================================
   V04 — exact header-container anchors (fixed at every viewport)
   Header geometry: max-width 1340px, centered, padding-inline 6vw.
   .m2r = RTL text, right edge flush with the header's right end
   .m2l = RTL text, box hugs the header's LEFT edge (logo column)
   ========================================================= */
.v2x__copy.m2r, .v2x-hero__copy.m2r {
  max-width: 1340px; width: 100%; margin: 0 auto;
  padding-inline: 6vw; text-align: right !important;
}
.v2x__copy.m2r > *, .v2x-hero__copy.m2r > *,
.v2x__copy.m2r p, .v2x-hero__copy.m2r p {
  max-width: 640px; margin-left: auto !important; margin-right: 0 !important;
}
.v2x__copy.m2r .v2x__chips, .v2x-hero__copy.m2r .v2x__chips { justify-content: flex-end !important; }

.v2x__copy.m2l, .v2x-hero__copy.m2l {
  max-width: 1340px; width: 100%; margin: 0 auto;
  padding-inline: 6vw; text-align: right !important;
}
.v2x__copy.m2l > *, .v2x-hero__copy.m2l > *,
.v2x__copy.m2l p, .v2x-hero__copy.m2l p {
  max-width: 640px; margin-right: auto !important; margin-left: 0 !important;
}
.v2x__copy.m2l .v2x__chips, .v2x-hero__copy.m2l .v2x__chips { justify-content: flex-start !important; }

/* hero-side-right (EN right-anchored heroes) gets the same exact geometry */
.hero-side-right .v2x-hero__copy {
  max-width: 1340px; width: 100%; margin: 0 auto;
  padding-inline: 6vw; text-align: left;
}
.hero-side-right .v2x-hero__copy > *, .hero-side-right .v2x-hero__copy p {
  max-width: 640px; margin-left: auto !important; margin-right: 0 !important;
}
html[dir="rtl"] .hero-side-right .v2x-hero__copy { text-align: right; }

/* FIX: the open mobile drawer covered the burger — keep it clickable above the panel */
@media (max-width: 760px) {
  .nav__burger { position: relative; z-index: 1002; }
}

/* title pieces joined onto ONE right-aligned line under the eyebrow */
.title-1line { display: block; }
.title-1line .mask { display: inline-block; padding-block: .14em; margin-block: -.06em; }
.title-1line .mask + .mask { margin-inline-start: .28em; }

/* stacked layout: every text item sits on its own line, shared right edge */
.v2x__copy.stacked .v2x__chips { flex-direction: column; align-items: flex-start; gap: 8px; }
.v2x__copy.stacked .v2x__chips span { display: block; }

/* FIX: inline-block eyebrows ignored the left-anchor margins — make them block-level
   so every m2l stack keeps ONE shared column under its eyebrow */
.v2x__copy.m2l > .eyebrow, .v2x-hero__copy.m2l > .eyebrow,
.v2x__copy.m2r > .eyebrow, .v2x-hero__copy.m2r > .eyebrow { display: block; width: fit-content; }

/* =========================================================
   EDIT-V06 — v2-lite: content column locked to the header container.
   Carried by .hdr-align on v2-lite-fa.html and v2-lite-ar.html, which are
   structural mirrors (same blocks, same line numbers, both dir="rtl"), so
   the two RTL versions stay identical. The 12 other m2r pages and the LTR
   v2-lite.html are untouched. Two independent defects, two gates.
   ========================================================= */

/* --- Part 1: container width. -----------------------------------------
   .nav__inner caps its CONTENT box at 1340px, with the 6vw gutter on .nav
   outside it. .v2x-hero__copy and .v2x__copy cap their BORDER box at 1340px,
   with the same gutter inside. Up to a 1340px viewport the two coincide;
   past it every copy block drifts inward from the header edge — 96px at
   1600, 116px at 1920. Mirroring the nav's geometry (1340px of content plus
   both gutters) removes the drift exactly. Because these containers are
   centre-margined, widening fixes BOTH edges: m2r meets the lang switcher
   on the right, m2l meets the logo on the left.

   Specificity is deliberately 3 classes: .m2r and .m2l each re-declare
   max-width:1340px at 0,2,0 (lines 3484 and 3494), so 0,2,0 here would only
   win on source order. Gated at 1341px, the exact width where the drift
   begins. Not applied to m3 blocks, which are intentionally capped at 720px.
   --------------------------------------------------------------------- */
@media (min-width: 1341px) {
  .v2x-hero .v2x-hero__copy.hdr-align,
  .v2x .v2x__copy.hdr-align { max-width: calc(1340px + 12vw); }

  /* .v2x__copy--end is the one block that is NOT centre-margined: line 3284
     pins it with margin-inline-start:0 !important, so in RTL it sits flush
     against the section's right edge — which carries no padding, making its
     anchor "section edge minus 6vw" instead of the header's centred column.
     Centring it puts it on the same column as the other four. Needs
     !important at 0,3,0 to clear line 3284 (0,2,0 !) and line 2901 (0,3,1). */
  .v2x--left .v2x__copy--end.hdr-align { margin-inline: auto !important; }
}

/* --- Part 2: children of .v2x__copy--end. -----------------------------
   Separate gate, because this defect spans every desktop width, not just
   past 1341px.

   Line 3488 flushes m2r children right (margin-right:0 !important) at 0,2,0.
   For this one block line 3349 overrides with margin-inline-start:auto
   !important at 0,3,1 — in RTL that IS margin-right — so both margins resolve
   to auto and the children centre instead: 200.5px shy of the container edge
   at a 1200px viewport, 471px for the narrow eyebrow pill. The container
   itself was always correct; only its children were adrift.

   0,4,1 to clear line 3349. Physical properties, not logical: the selector is
   already RTL-scoped, and margin-inline-start would flush the wrong way if
   this class ever reached the LTR page.

   Gated at min-width 901px on purpose. Below that, lines 2796-2797 centre
   these children deliberately for the mobile layout, so mobile must keep it.
   --------------------------------------------------------------------- */
@media (min-width: 901px) {
  html[dir="rtl"] .v2x--left .v2x__copy--end.hdr-align > *,
  html[dir="rtl"] .v2x--left .v2x__copy--end.hdr-align p {
    margin-right: 0 !important;
    margin-left: auto !important;
  }
}

/* =========================================================
   EDIT-V07 — v2-lite "8.5mm / beyond slim" block (fa + ar, line 189):
   centred, with the closing sentence clearing the phone in the photo.
   Applies at EVERY width — desktop and mobile alike.

   Centring needed NO new rule: .v2x--center .v2x__copy--mid (line 2757) already
   centres, and line 2796 does the same inside the mobile breakpoint. The block
   only looked left-hugged because .m2l overrode both. Dropping .m2l restores the
   sheet's own centred treatment everywhere.

   The vertical fit is two-sided. Measured at 1600x820 with the section scrolled
   to the top of the frame:
     - the fixed .nav ends at y=101 (36px annbar + 65px bar, stable across scroll)
     - the phone's top edge in v2lite-07.webp sits at y=442 at page centre
     - .hi alone (-50px) left the paragraph at 474-525, squarely on the phone
   A pure lift cannot satisfy both ends: clearing the phone needs about -140px,
   but by -145px the "8.5mm" span reaches y=101 and slides under the header. So
   the lift stops at -140px (10px of header clearance) and the last few pixels
   come from the eyebrow's bottom margin, 22px -> 10px, which raises the title
   and paragraph without moving "8.5mm" at all. Desktop result: paragraph bottom
   at y=429, 13px of clear space above the phone.

   Ungated on purpose. The first revision gated this at min-width 901px, which
   left mobile on .hi's original -50px — and there the paragraph ran straight
   across the phone, illegible. The same two values clear it at 375px too, so one
   unconditional rule serves both rather than two sets of magic numbers.

   NOTE for whoever tunes this next: the mobile figure was settled by eye, from
   screenshots. Sampling the background image with canvas to locate the phone
   returned 386 and 427 for the same edge on two runs — the 1600x900 source is
   cropped hard by object-fit:cover into a 420x909 box at that width, so the
   sampled column lands on different parts of the image. Do not trust a computed
   phone edge at mobile widths; look at it.

   .hi-c carries both, at 0,4,0 and 0,5,0 — above .v2x__copy.hi (0,2,0, line
   3370) and the base .eyebrow margin (0,1,0, line 484), so no !important.
   ========================================================= */
.v2x--center .v2x__copy--mid.hi.hi-c { top: -140px; }
.v2x--center .v2x__copy--mid.hi.hi-c > .eyebrow { margin-bottom: 10px; }

/* =========================================================
   EDIT-V08 — v2-lite "leather design" block (fa + ar, line 201):
   left-anchored on the logo, copy right-aligned, clear of the photo, and
   every child sharing one right edge.

   m2r -> m2l in the markup did the horizontal half by itself: m2l flushes the
   child boxes left (margin-left:0, margin-right:auto) while keeping
   text-align:right — exactly "sit to the left of the photo, aligned with the
   VOCAL logo, but keep the copy right-aligned". With .hdr-align also present
   the content edge lands on x=123, the same column as .nav__logo and
   .nav__inner. No CSS was needed for that half.

   Three rules, all measured at 1600x820 with the section anchored to the top
   of the frame.

   1. The lift is capped by the header, not chosen. The fixed .nav ends at
      y=101 and the eyebrow — the topmost visible child — sat at y=253, so
      142px is the entire available headroom and leaves 10px of clearance.
      position:relative + top mirrors how .hi (line 3370) shifts a block
      without reflowing the section.

   2. The lift alone does NOT get the copy off the photo, and no lift can. The
      bright product edge in v2lite-03.webp runs diagonally: first bright pixel
      at y=546 at x=473, climbing to y=372 by x=748. At the full lift the
      paragraph still sat 71px into it at x=746. Narrowing the copy clears it
      and costs nothing, because the paragraph reflows inside the same two
      lines at every width tested down to 440px, so its bottom stays at y=423
      and the block does not grow taller. 480px is the first width that clears
      the diagonal outright, with 19px to spare (640 -> +71 overlap, 560 -> +22,
      520 -> +3, 480 -> -19). The title is only 403px wide so it does not
      rewrap, and the eyebrow is 98px.

   3. The title and paragraph fill the 480px box, so text-align:right puts them
      both on x=603. The eyebrow did not follow: line 3530 gives it
      width:fit-content, and m2l's child rule then flushes that narrow box left,
      parking its right edge at x=238. Flipping just its margins puts it on the
      same 603 as the title's first line, so all three children share one right
      edge. Needs 0,5,0 + !important to clear m2l's 0,2,0 !important.
      Ungated — a shared right edge is correct at any width, and on mobile the
      eyebrow was out of line with the title for the same reason.

   Rules 1 and 2 are desktop only: the mobile layout stacks differently and
   object-fit:cover crops the photo to another part of the frame, so both
   numbers are meaningless there.
   ========================================================= */
@media (min-width: 901px) {
  .v2x--center .v2x__copy--mid.m2l.lift-max { position: relative; top: -142px; }
  .v2x--center .v2x__copy--mid.m2l.lift-max > * { max-width: 480px; }
}
/* The eyebrow is width:fit-content (line 3530), so m2l's margin-left:0 parks
   its narrow box at the far left while the 480px title and paragraph end at
   content-left + 480. Flushing it right with margin-right:0 would send it to
   the container's own right edge instead — 1463 at a 1600px viewport, 839px
   past the title. Pinning margin-right to (container width - 480) puts its
   right edge exactly on content-left + 480 whatever the container measures,
   and whatever the eyebrow's own text width is, so fa and ar both land right.
   The max(0px, ...) guard matters below 901px, where the 480px cap does not
   apply and the copy fills the column: there the calc would go negative and
   throw the pill off-screen, so it collapses to a plain right flush. */
.v2x--center .v2x__copy--mid.m2l.lift-max > .eyebrow {
  margin-left: auto !important;
  margin-right: max(0px, calc(100% - 480px)) !important;
}

/* =========================================================
   EDIT-V09 — .side-right: move a .v2x__copy block to the right of its section
   WITHOUT flipping the text, for the LTR pages.

   m2r cannot be reused here. It right-flushes the children, which is what we
   want, but it also sets text-align:right !important — on an English page that
   re-aligns the whole paragraph and is not "the same composition". This does
   the half that is missing and nothing else: .v2x--right .v2x__copy (line 2753)
   already supplies text-align:left, and the base .v2x__copy carries the
   container geometry.

   Deliberately declares NO max-width on the container. .hdr-align's rule is
   also 0,3,0, so a max-width here would tie with it and win purely on source
   order, silently undoing the header alignment. Leaving it out lets .hdr-align
   do its job.

   The .eyebrow needs its own line. It is display:inline-block in the base sheet
   (line 476), and auto margins do nothing on an inline-block — they compute to
   0, so it stays parked at the left while the block-level title and paragraph
   move right. Line 3530 solves this for m2r/m2l by making it a fit-content
   block; the same treatment is what it needs here.

   Mirrors the child rule of .hero-side-right (line 3508), which is the same
   idea already applied to the English heroes.
   ========================================================= */
.v2x .v2x__copy.side-right > *,
.v2x .v2x__copy.side-right p {
  max-width: 640px;
  margin-left: auto !important;
  margin-right: 0 !important;
}
.v2x .v2x__copy.side-right > .eyebrow { display: block; width: fit-content; }

/* =========================================================
   EDIT-V10 — .side-left: the mirror of .side-right, for LTR pages, plus the
   lift/narrow pair for v2-lite.html's "tech leather" block (line 201).

   Same reasoning as EDIT-V09, other hand. m2l cannot be reused: it left-flushes
   the child boxes, which is what we want, but it also forces
   text-align:right !important, which on an English page re-aligns the whole
   paragraph and is not the natural composition. Unlike .side-right this one DOES
   need its own text-align, because .v2x--center .v2x__copy--mid (line 2757)
   centres by default.

   The .eyebrow gets display:block + fit-content for the same reason as in
   EDIT-V09: it is inline-block in the base sheet (line 476), and margins do not
   position an inline-block the way they position a block. Once it is a block,
   side-left's margin-left:0 puts it on the same left edge as the title and
   paragraph with no extra rule — the mirror case needed a calc() to find a
   shared RIGHT edge, this one gets it for free.

   Declares no max-width on the container, so .hdr-align (also 0,3,0) is free to
   set the header-matching width without a source-order tie.

   The lift is the EN counterpart of EDIT-V08's rule, and needs its own selector
   because that one is keyed to .m2l. The NUMBER is different on purpose: the
   instruction was "as high as the header allows", and English has more headroom
   than Persian — its topmost child sat at y=270 against a nav ending at y=101,
   so 159px is the ceiling here where Persian's was 142px. Same rule, different
   measurement. 480px matches Persian for consistency; at this width the copy
   clears the photo's diagonal by 122px (at 640px it lands exactly on the edge,
   overlap 0, which is too tight to trust).
   ========================================================= */
.v2x--center .v2x__copy--mid.side-left { text-align: left; }
.v2x .v2x__copy.side-left > *,
.v2x .v2x__copy.side-left p {
  max-width: 640px;
  margin-right: auto !important;
  margin-left: 0 !important;
}
.v2x .v2x__copy.side-left > .eyebrow { display: block; width: fit-content; }

@media (min-width: 901px) {
  .v2x--center .v2x__copy--mid.side-left.lift-max { position: relative; top: -159px; }
  .v2x--center .v2x__copy--mid.side-left.lift-max > * { max-width: 480px; }
}

/* =========================================================
   EDIT-V11 — v2 camera block (line 99, all three languages): centred, heading
   group pinned to the top of the frame, closing line pinned to the bottom.
   ========================================================= */

/* --- horizontal: actually centre it -----------------------------------
   Container width, both directions. .m3 caps this at 720px (528px of content),
   but the single lines it has to hold are wider than that — 943px for the RTL
   paragraph under .oneline, 707px for the longest EN title phrase under the
   nowrap rule below. A line wider than its box cannot be centred by text-align;
   in RTL it spills left, in LTR right. 1340px gives 1148px and holds both.

   text-align is RTL-only. .m3 sets center !important at 0,2,0, but line 3289
   (html[dir="rtl"] .v2x--right .v2x__copy) sets right !important at 0,3,1 and
   wins — which is why the RTL eyebrow sat 228px off centre while v2.html, which
   never matches that rule, was already centred.

   The paragraph needs its own release: line 2752 pins .v2x__copy > p to 440px,
   and .oneline makes its single line 943px, so it was overflowing its OWN box
   and stayed 251px off centre even once the container was wide enough.
   --------------------------------------------------------------------- */
.v2x--right .v2x__copy.m3.cam-mid { max-width: 1340px; }
html[dir="rtl"] .v2x--right .v2x__copy.m3.cam-mid { text-align: center !important; }
html[dir="rtl"] .v2x--right .v2x__copy.m3.cam-mid > p { max-width: none; }

/* --- vertical: split the block ----------------------------------------
   The eyebrow and title go as high as the header allows; the paragraph drops to
   the bottom of the frame. A negative top cannot do this — it moves every child
   together — so the copy stretches to the section's full height and the
   paragraph is pushed down with an auto top margin.

   padding-top is 111px: the fixed .nav ends at y=101 (36px annbar + 65px bar,
   verified constant across four scroll positions) and 10px is the clearance.
   padding-bottom is deliberately NOT set, so it keeps line 3254's
   clamp(60px, 9vh, 120px) — 74px here — which is the sheet's own vertical
   rhythm rather than a number invented for this block.

   position:static/top:auto is needed to cancel .hi (line 3370, -50px) on the RTL
   pages: with the container stretched, that shift would drag the whole column up
   and put the eyebrow under the header. Cancelling it also retires the two
   per-direction lift values this block used to need (-172px RTL, -80px EN) —
   padding positions the top edge identically in both directions, so one rule now
   covers all three languages.

   The eyebrow keeps its pill shape as a flex item because line 3354's
   margin-inline:auto stops it stretching across the cross axis.

   Desktop only: below 901px the section stacks and line 2796 centres this copy
   anyway, so a fixed 111px inset would mean nothing there.
   --------------------------------------------------------------------- */
@media (min-width: 901px) {
  .v2x--right .v2x__copy.m3.cam-mid {
    align-self: stretch;
    display: flex;
    flex-direction: column;
    padding-top: 111px;
    position: static;
    top: auto;
  }
  .v2x--right .v2x__copy.m3.cam-mid > p { margin-top: auto; }

  /* EN only: one line per title phrase. The RTL pages get this from .oneline,
     which v2.html does not carry — and adding .oneline there would also pin its
     paragraph to nowrap, re-introducing the clipping handled below. */
  html:not([dir="rtl"]) .v2x--right .v2x__copy.m3.cam-mid .mask__in { white-space: nowrap; }
}

/* --- narrow widths: wrap instead of clipping --------------------------
   .oneline pins nowrap on the RTL paragraph (line 3460) and title masks (3461).
   Neither fits the column below roughly a 1070px viewport, and nothing scrolls
   horizontally, so the overflow is CLIPPED: measured at 375px the title lost
   160px off the left, at 901px the paragraph lost 280px. Both pre-existing —
   toggling the rules above off reproduces the same 160px — but a line with its
   first third cut off is not centred in any useful sense. Safe to wrap inside
   .mask: it is overflow:hidden but auto-height (line 497), so the box grows.
   --------------------------------------------------------------------- */
@media (max-width: 1199px) {
  html[dir="rtl"] .v2x--right .v2x__copy.m3.cam-mid > p {
    white-space: normal;
    max-width: 440px;
  }
  html[dir="rtl"] .v2x--right .v2x__copy.m3.cam-mid .mask__in { white-space: normal; }
}

/* =========================================================
   EDIT-V12 — v2 battery block (all three languages): centred, heading group at
   the top of the frame, closing line at the bottom.

   Same goal as EDIT-V11's camera block but a harder starting point, because this
   one is .v2x__copy--end inside .v2x--left and that pair carries its own stack of
   rules. Measured before any change, the container sat with margin-left:865px /
   margin-right:0 — pushed to the inline-start edge, its content centred on
   x=1225 while the page centre is 793 — and every child was off centre (+38 for
   the 5000mAh figure, +213 for the eyebrow, -78 title, -140 paragraph).

   So three things have to be undone, not one:
     - the container's own offset: line 2901 (margin-left:auto/margin-right:0 at
       0,3,1) and line 3284 (margin-inline-start:0 !important at 0,2,0)
     - text-align: lines 3290 and 3347, both right !important at 0,3,1, and 3284's
       left !important for the LTR page
     - the children's margins: line 3285 (0 !important, 0,2,0) and line 3349
       (auto !important, 0,3,1)
   Hence the html[dir] prefix on the RTL-specific ones: 0,5,1 clears 0,3,1
   outright rather than relying on source order.

   Container width goes to 1340px for the same reason as the camera block: .m3
   caps it at 720px (528px of content) while the widest single line here is the
   943px-class paragraph, and a line wider than its box cannot be centred by
   text-align. The paragraph also needs line 2752's own 440px cap released.

   Vertical split matches EDIT-V11 exactly — stretch to the section height,
   padding-top 111px (nav ends at 101, 10px clearance), padding-bottom left to
   line 3254's clamp so the bottom gap stays the sheet's own rhythm, and
   position:static to cancel .hi's -50px. Desktop only, for the same reason.
   ========================================================= */
.v2x--left .v2x__copy--end.m3.bat-mid {
  max-width: 1340px;
  margin-inline: auto !important;
  text-align: center !important;
}
.v2x--left .v2x__copy--end.m3.bat-mid > * {
  margin-inline: auto !important;
}
html[dir="rtl"] .v2x--left .v2x__copy--end.m3.bat-mid {
  margin-left: auto !important;
  margin-right: auto !important;
  text-align: center !important;
}
html[dir="rtl"] .v2x--left .v2x__copy--end.m3.bat-mid > *,
html[dir="rtl"] .v2x--left .v2x__copy--end.m3.bat-mid > p {
  margin-left: auto !important;
  margin-right: auto !important;
  max-width: none;
}

@media (min-width: 901px) {
  .v2x--left .v2x__copy--end.m3.bat-mid {
    align-self: stretch;
    display: flex;
    flex-direction: column;
    padding-top: 111px;
    position: static;
    top: auto;
  }
  .v2x--left .v2x__copy--end.m3.bat-mid > p { margin-top: auto !important; }
  /* EN: keep each title phrase on one line, as the RTL pages get from .oneline */
  html:not([dir="rtl"]) .v2x--left .v2x__copy--end.m3.bat-mid .mask__in { white-space: nowrap; }
}

/* narrow widths: wrap rather than clip, same reasoning as EDIT-V11 */
@media (max-width: 1199px) {
  html[dir="rtl"] .v2x--left .v2x__copy--end.m3.bat-mid > p {
    white-space: normal;
    max-width: 440px;
  }
  html[dir="rtl"] .v2x--left .v2x__copy--end.m3.bat-mid .mask__in { white-space: normal; }
}

/* =========================================================
   EDIT-V13 — the "8.5mm" blocks (.hi-c, all three languages on BOTH v2 and
   v2-lite): closing line dropped to the bottom of the frame.

   Why, in one number: this section's scrim is .v2x__scrim--full, a radial that
   is transparent at the CENTRE and only reaches .78 alpha at the edges — the
   exact inverse of what centred copy needs. Measured behind the paragraph the
   scrim contributes alpha 0.02, so the effective background is the raw photo:
   250 against text at 217 on v2-slim.webp, and 241 against 203 on
   v2lite-07.webp. In both cases the text is DARKER than what sits behind it.
   No amount of nudging inside the middle band fixes that; the copy has to leave
   the bright centre. Dropping the closing line to the bottom of the frame does
   it, and matches what EDIT-V11 and EDIT-V12 already do for the camera and
   battery blocks.

   This supersedes .hi-c's own top:-140px (line 3631): the split positions the
   top group by padding instead, so position:static/top:auto cancels both that
   and .hi (line 3370). Same mechanics as EDIT-V11 — stretch to the section
   height, padding-top 111px for the fixed nav's 101px plus 10px of clearance,
   padding-bottom left to line 3254's clamp so the bottom gap stays the sheet's
   own rhythm, and the paragraph pushed down with an auto top margin.

   .hi-c's eyebrow margin (line 3632, 22px -> 10px) is deliberately left alone:
   it was introduced to buy pixels for the old lift, and although the split makes
   it unnecessary, restoring 22px would change spacing that was already reviewed.

   Applies to v2-lite as well as v2, because both carry .hi-c over the same
   radial scrim with the same four-part copy — the contrast reading above is from
   v2-lite. Desktop only, as with the other two blocks.
   ========================================================= */
@media (min-width: 901px) {
  .v2x--center .v2x__copy--mid.hi.hi-c {
    align-self: stretch;
    display: flex;
    flex-direction: column;
    padding-top: 111px;
    position: static;
    top: auto;
  }
  .v2x--center .v2x__copy--mid.hi.hi-c > p { margin-top: auto; }
}

/* EDIT-V13b — two consequences of the split above, both desktop-only.

   The eyebrow pill stretched. Turning the copy into a flex column made every
   child a flex item, and with align-items defaulting to stretch the pill grew to
   the full 1148px content width instead of hugging its text. The camera and
   battery blocks never showed this because they carry .m3, whose line 3354
   (margin-inline:auto on children) blocks cross-axis stretching — this block has
   no .m3, so nothing stopped it. align-self:center restores the compact pill and
   keeps it centred.

   The closing line now sits on one line. It needs 498px and the container gives
   1148px, so the only thing forcing the wrap was line 2752's own 440px cap on
   .v2x__copy > p; releasing that plus nowrap collapses it to a single line. Both
   inside the 901px gate, so the mobile layout — which is not flex and where a
   498px line would not fit — keeps wrapping as before. */
@media (min-width: 901px) {
  .v2x--center .v2x__copy--mid.hi.hi-c > .eyebrow { align-self: center; }
  .v2x--center .v2x__copy--mid.hi.hi-c > p {
    white-space: nowrap;
    max-width: none;
  }
}

/* =========================================================
   EDIT-V14 — v2 "tech-leather durability" block (the second .v2x__copy--end,
   the one with chips): copy on the LEFT of the frame, text reading in its own
   direction — right-aligned on fa/ar, left-aligned on en.

   .m2l alone does not get there. Its child rule (line 3497, margin-left:0 /
   margin-right:auto at 0,2,0) is exactly right, but this is a --end block inside
   .v2x--left and that pair carries RTL rules at 0,3,1 that outrank it:
   lines 2902-2903 (margin-left:auto/margin-right:0), 3292
   (margin-inline-start:0 !important) and 3349 (margin-inline-start:auto
   !important). Measured with .m2l applied, the children were still hard against
   the RIGHT of the column — margin-left 700px, margin-right 0.

   So the flush is re-stated at 0,4,1, which clears 0,3,1 on class count. The
   container half needed nothing new: .hdr-align's line 3565 already centres a
   --end box, which puts the content edge on x=123, the same column as the logo.

   The chips keep .stacked's align-items:flex-start, which in RTL means their
   right edge — the same edge the right-aligned text uses — so text and chips
   still share one margin inside the left-positioned column.

   English is not covered here: it needs .side-left (EDIT-V10), whose child rule
   at 0,3,0 already beats the only LTR competitor, line 3285 at 0,2,0.
   ========================================================= */
html[dir="rtl"] .v2x--left .v2x__copy--end.m2l > *,
html[dir="rtl"] .v2x--left .v2x__copy--end.m2l p {
  margin-left: 0 !important;
  margin-right: auto !important;
}

/* =========================================================
   EDIT-V15 — .hero-side-left: the mirror of .hero-side-right, for an LTR hero
   whose copy sits on the LEFT.

   Only the child flush is needed. Swapping the section from .hero-side-right to
   this class already does the rest by getting out of the way: line 3504's
   container override and line 3508's right flush stop matching, the container
   falls back to the base .v2x-hero__copy (line 2721, 1340px + 6vw gutters, which
   .hdr-align then widens to the header column), text-align returns to the LTR
   default of left, and — the part worth noting — the ::after scrim reverts to the
   base gradient at line 2716, which in LTR is already dark on the LEFT. That is
   exactly what a left-positioned copy wants, so no gradient rule here;
   .hero-side-right only existed to flip it the other way.

   The 640px cap is kept so the block holds the same compact shape it had on the
   right, just mirrored — the composition is unchanged, only the side.
   ========================================================= */
.hero-side-left .v2x-hero__copy > *,
.hero-side-left .v2x-hero__copy p {
  max-width: 640px;
  margin-right: auto !important;
  margin-left: 0 !important;
}

/* EDIT-V16 — the big figure in a left-anchored --end block hugs the left edge.
   .v2x__big is a full-width block, so with m2l putting the box on the content's
   left edge and RTL text-align keeping the glyphs right, "50MP" landed 256px
   inside the column while the title and eyebrow sat on the logo line at 123px.
   fit-content shrinks the box to the glyphs so the box edge IS the text edge —
   the same trick line 3530 already uses for the eyebrow, which is why that one
   was already aligned.
   Chosen over text-align:left because .gradient-text paints through
   background-clip:text: with a 640px box the gradient spans the box and the
   384px of text only shows its left half, whereas a fit-content box maps the
   whole gradient onto the glyphs. Verified the clip and background survive. */
html[dir="rtl"] .v2x--left .v2x__copy--end.m2l > .v2x__big { width: fit-content; }

/* ===================== EDIT-V17 =====================
   V2 PRO performance block (Octa-core T770), all three languages:
   centre the copy, pin the eyebrow + title to the ceiling of the frame and drop
   the closing paragraph + the three chips to the floor.
   Class .perf-c goes on the .v2x__copy at line 157 of v2-pro.html / -fa / -ar.
   Desktop only: the max-width:900px block already centres this copy
   (lines 2796/2799/2800), so mobile is deliberately left untouched. */
@media (min-width: 901px) {

  /* --- the vertical split --------------------------------------------------
     section.v2x[class*="v2x--"] (line 2744) is display:flex; align-items:center,
     so the copy is a vertically centred flex item and there is no frame to pin
     against. align-self:stretch cancels the centring and gives the block the
     section's full height; flex-direction:column then lets margin-top:auto on
     one child absorb all the slack.
     The selector mirrors line 3254 plus .perf-c, giving 0,4,1: line 3254
     (section.v2x[class*="v2x--"] .v2x__copy) already owns padding-block at
     0,3,1, so the obvious .v2x--right .v2x__copy.perf-c (0,3,0) would lose and
     the padding below would silently not apply.
     padding-top exceeds 3254's clamp on purpose: the sticky nav is 101px tall
     (36px announcement bar + 65px bar) and 3254's 9vh floor is only 81px at a
     900px-tall viewport, which would put the eyebrow underneath it. */
  section.v2x[class*="v2x--"] .v2x__copy.perf-c {
    align-self: stretch;
    display: flex;
    flex-direction: column;
    padding-top: clamp(124px, 15vh, 168px);
    padding-bottom: clamp(56px, 8vh, 104px);
    text-align: center;
  }

  /* margin-top:auto absorbs every spare pixel above the paragraph, so the
     paragraph and the .v2x__chips that follow it land on the floor while the
     eyebrow and title stay at the ceiling. Beats .v2x__copy > p margin-top:16px
     (line 2752) at 0,4,1 vs 0,1,0.
     margin-inline:auto is the other half: the paragraph keeps max-width:440px
     from 2752, so text-align:center alone would centre the text inside a box
     that is still pinned to the inline-start edge. */
  section.v2x[class*="v2x--"] .v2x__copy.perf-c > p {
    margin-top: auto;
    margin-inline: auto;
  }

  /* a flex column stretches its children across the cross axis, which would
     blow the eyebrow pill from its fit-content width to the full 1340px — the
     same trap the hi-c block hit at line 3991. */
  section.v2x[class*="v2x--"] .v2x__copy.perf-c > .eyebrow { align-self: center; }

  /* the chips are their own flex row, so centring the surrounding text does not
     move them; they need their own justify-content. Nothing !important targets
     this block (the !important chip rules at 3286/3293/3350/3363/3457/3491/3501
     are all scoped to --end, m2l, m2r or m3, none of which this block carries). */
  section.v2x[class*="v2x--"] .v2x__copy.perf-c .v2x__chips { justify-content: center; }

  /* RTL needs its own line: line 3290 (html[dir="rtl"] .v2x--right .v2x__copy)
     holds text-align:right !important at 0,3,1, so only !important at a heavier
     weight can centre the Persian and Arabic copy. This is 0,5,2. */
  html[dir="rtl"] section.v2x[class*="v2x--"] .v2x__copy.perf-c { text-align: center !important; }
}

/* ===================== EDIT-V18 =====================
   .scrim-strong — a deeper scrim for ONE section: the English V2 PRO battery
   block (line 183 of v2-pro.html).
   Why it exists: that block's copy moved from the right of the frame to the left
   (side-right -> side-left, so it aligns with the VOCAL logo). The left third of
   assets/v2/battery.webp is a near-white glow — measured photo luminance 255 —
   and the section's own scrim was --right, i.e. transparent exactly where the
   text now sits. Flipping the scrim to --left recovered most of it but not
   enough: at a 1920 viewport the paragraph still sat on an effective background
   of 130 against #d9cba6 text, a contrast ratio of 2.37:1. The same paragraph
   measured 10.16:1 in its old right-hand position, so the move would have been a
   real regression. With this gradient it measures 9.57:1, and the eyebrow goes
   from 4.29:1 to 10.9:1.
   Numbers behind the stops: to pull a 255 photo down to <=60 the alpha has to be
   >=0.795 (255*(1-a) + 9.5a <= 60), and the copy extends to 43% of the section
   width, so the .48/.72 stops of the base gradient (0.41 alpha at that point)
   could not do it. .85 held to 55% covers the whole copy with headroom.
   Specificity: .v2x__scrim--left.scrim-strong is 0,2,0 and beats the base
   .v2x__scrim--left (0,1,0, line 2748).
   The @media gate is load-bearing, not cosmetic: line 2798 replaces BOTH scrim
   directions with a bottom-to-top gradient below 901px, and it is only 0,1,0, so
   an ungated 0,2,0 rule here would beat it and break the mobile scrim. Gating
   keeps mobile exactly as it was — which is also why flipping --right to --left
   in the markup has no mobile effect at all.
   ========================================================= */
@media (min-width: 901px) {
  .v2x__scrim--left.scrim-strong {
    background: linear-gradient(to right, rgba(12,9,7,.95), rgba(12,9,7,.85) 55%, transparent 88%);
  }
}

/* ===================== EDIT-V19 =====================
   V11 English page: anchor the hero copy and the camera copy to the RIGHT of the
   frame while the text itself stays left-aligned, right edge on the header column.
   Two new classes, both DESKTOP-ONLY BY CONSTRUCTION.

   Why not reuse .hero-side-right / .side-right, which already do exactly this?
   Because neither is gated, and on this page both break the mobile layout:
     - .hero-side-right .v2x-hero__copy is 0,2,0 and sits LATER in the sheet than
       line 2966 (.v11-hero .v2x-hero__copy { text-align: center } inside
       @media (max-width: 880px)), which is also 0,2,0. The tie goes to source
       order, so hero-side-right wins and the mobile title goes left while the CTA
       and chips stay centred by lines 2967/2968 — measured, not guessed.
     - .side-right right-flushes the children at 0,3,0, which on mobile pushed the
       camera eyebrow from its centred 132..243 to 242..353.
   Gating these rules at min-width:901px keeps mobile byte-identical: verified at
   375px that the hero stays text-align:center, the camera stays center with m3's
   720px cap and the eyebrow back at 132..243, and both scrims keep the vertical
   gradient from line 2798.

   .m3 STAYS in the camera markup on purpose. It is the only thing forcing
   text-align:center on that block at mobile widths — line 2753
   (.v2x--right .v2x__copy { text-align: left }) is 0,2,0 and beats the mobile
   rule at line 2796 (0,1,0), so dropping .m3 would leave the block left-aligned
   on phones. Keeping it and overriding it on desktop is why these selectors carry
   .m3.copy-anchor-r (0,4,0): they have to outrank m3's own
   text-align:center !important, its 720px cap and its margin-inline:auto children.

   The hero's stronger ::after WAS not optional -- EDIT-V42 has since replaced
   it with the stock gradient. The right third of assets/edit/v11-hero.webp is a
   bright gradient wall, and back when the copy sat where .hero-side-right put
   it, the stock gradient (.94 at the edge -> .6 at 40% -> transparent at 68%)
   reached only alpha .36-.66 across it, leaving an effective background of
   152-155: 2.35:1 for "V11" and 2.41:1 for "Unlock". The stronger gradient took
   them to 13.63:1 and 14.11:1. The copy has moved twice since, so none of those
   figures describes this page any more -- EDIT-V42 has the current numbers.

   .v2x__scrim--right.scrim-strong is the mirror of the --left variant added in
   EDIT-V18, needed for the same reason on the camera section: the flipped stock
   scrim still left the paragraph at 1.42:1, and this takes it to 8.73:1.
   ========================================================= */
@media (min-width: 901px) {

  /* --- hero: copy to the right, text still left --- */
  .hero-anchor-r .v2x-hero__copy { text-align: left; }
  .hero-anchor-r .v2x-hero__copy > * {
    max-width: 640px;
    margin-left: auto !important;
    margin-right: 0 !important;
  }
  .hero-anchor-r.v2x-hero::after {
    background: linear-gradient(to left, rgba(8,6,4,.94) 0%, rgba(8,6,4,.6) 40%, transparent 68%),
                linear-gradient(to top, var(--bg) 4%, transparent 36%);
  }

  /* --- camera: same treatment, overriding .m3 --- */
  .v2x--right .v2x__copy.m3.copy-anchor-r {
    max-width: calc(1340px + 12vw);
    text-align: left !important;
  }
  .v2x--right .v2x__copy.m3.copy-anchor-r > *,
  .v2x--right .v2x__copy.m3.copy-anchor-r p {
    max-width: 640px;
    margin-left: auto !important;
    margin-right: 0 !important;
  }
  /* the eyebrow is display:inline-block in the base sheet (line 476) and auto
     margins do not move an inline-block, so it needs to become a block first —
     same fix as EDIT-V09/V10. */
  .v2x--right .v2x__copy.m3.copy-anchor-r > .eyebrow { display: block; width: fit-content; }

  /* --- the mirror of EDIT-V18's scrim, for a right-hand copy --- */
  .v2x__scrim--right.scrim-strong {
    background: linear-gradient(to left, rgba(12,9,7,.95), rgba(12,9,7,.85) 55%, transparent 88%);
  }
}

/* ===================== EDIT-V20 =====================
   V11 Persian + Arabic: the RTL half of EDIT-V19. Hero, camera and performance
   copy anchored to the RIGHT of the frame, right edge on the header column, text
   staying right-aligned. Desktop-gated for the same reasons as EDIT-V19.

   The hero reuses .hero-anchor-r from EDIT-V19 IN PLACE OF .hero-side-right, and
   that swap fixes a real bug rather than just moving the block. .hero-side-right
   puts the copy on the right in both directions (line 3269 margin-left:auto), but
   its RTL ::after at line 3275 paints "to right", i.e. it darkens the LEFT — the
   side the copy is NOT on. Measured on the live fa page: effective background
   244-251 under the headline, giving 1.07:1 for "V11", 1.09:1 for the second
   title line and 1.45:1 for the chip figures. That is invisible text, and it is
   what ships today. .hero-anchor-r's ::after paints "to left" and is stronger, so
   the same glyphs measure 15.18:1, 15.46:1 and 11.27-12.18:1.
   Only one line of new CSS is needed for the hero: .hero-anchor-r sets
   text-align:left unconditionally (correct for the English page it was written
   for), so RTL has to take it back. 0,3,0 beats that rule's 0,2,0, and it mirrors
   how the sheet already handles .hero-side-right at lines 3270 and 3511.

   The section blocks are keyed to .m3t.copy-anchor-r, NOT .m3.copy-anchor-r like
   EDIT-V19, because the fa/ar blocks carry .m3t. Two things about that:
     - .m3t is doing double duty. Besides centring it sets margin-top:10vh,
       margin-bottom:30vh and align-self:flex-start (line 3466) — the vertical
       placement of these blocks. So this rule uses margin-inline, never the
       margin shorthand: .m2r would have been the obvious class to reuse, but its
       line 3484 "margin: 0 auto" zeroes those vertical margins and drops the
       blocks out of position. Verified after the change: margin-top 90px,
       margin-bottom 270px, align-self flex-start, all intact.
     - no text-align is set here. .m3t declares center !important, but line 3289
       (html[dir="rtl"] .v2x--right .v2x__copy) already overrides it to
       right !important at 0,3,1, so RTL text is right-aligned before this block
       does anything. Measured: computed text-align is "right" both before and
       after.
   .v2x--right .v2x__copy.m3t.copy-anchor-r is 0,4,0, which is what it takes to
   outrank .m3t's own 0,2,0 max-width:760px and its margin-inline:auto children.

   Both sections also move from .v2x__scrim--left to --right + .scrim-strong,
   reusing the rule added in EDIT-V19: the copy is leaving the darkened side, and
   the stock scrim was not enough on the English page either. Result: camera
   9.21-13.47:1, performance 7.12-15.03:1.

   Mobile is unchanged apart from one deliberate consequence. Dropping
   .hero-side-right also drops its ungated RTL ::after, so the fa/ar hero finally
   uses the standard mobile vertical gradient ("to top") instead of a horizontal
   left-darkening one — which is what the English hero already does at that width.
   Everything else at 375px measured identical before and after: hero text-align
   right with max-width 1340 and children 23..353, chips centred, camera and
   performance right-aligned at max-width 760 with margins 81.2/243.6 and the
   eyebrow at 284..353.
   ========================================================= */
@media (min-width: 901px) {

  /* hero: take back the text-align that .hero-anchor-r sets for LTR */
  html[dir="rtl"] .hero-anchor-r .v2x-hero__copy { text-align: right; }

  /* camera + performance: right-anchored, m3t's vertical placement preserved */
  .v2x--right .v2x__copy.m3t.copy-anchor-r {
    max-width: calc(1340px + 12vw);
    margin-inline: auto;
  }
  .v2x--right .v2x__copy.m3t.copy-anchor-r > *,
  .v2x--right .v2x__copy.m3t.copy-anchor-r p {
    max-width: 640px;
    margin-left: auto !important;
    margin-right: 0 !important;
  }
  /* inline-block eyebrow again — auto margins do not move one (base sheet line 476) */
  .v2x--right .v2x__copy.m3t.copy-anchor-r > .eyebrow { display: block; width: fit-content; }
  /* the chips are their own flex row, and this is where a physical flex value
     bites. With direction:rtl the flex main axis runs right-to-left, so flex-END
     packs the pills on the LEFT: measured before this fix, the three pills ended
     at x=1054 while the copy's right edge was 1339 — a 285px gap, which is
     exactly what it looked like. flex-START is the visual right under RTL.
     Both directions are spelled out rather than only the RTL one, so the class
     stays correct if it is ever used on an LTR page. The hero chips need no such
     rule: nothing sets justify-content on .v2x-hero__chips, so they inherit the
     default and RTL packs them from the right on its own (verified: rightmost
     item edge 1339, gap 0). */
  html:not([dir="rtl"]) .v2x--right .v2x__copy.m3t.copy-anchor-r .v2x__chips { justify-content: flex-end !important; }
  html[dir="rtl"] .v2x--right .v2x__copy.m3t.copy-anchor-r .v2x__chips { justify-content: flex-start !important; }
}

/* --- EDIT-V20b — guard for a collision EDIT-V19 left open ------------------
   EDIT-V19's .v2x--right .v2x__copy.m3.copy-anchor-r sets text-align:left
   !important. That was written for v11.html, where left is correct, and the .m3
   key looked safe because only the English camera block carried .m3. It is not
   safe: v11-ar.html line 100 also carries .m3 (a leftover next to .m3t), so the
   moment .copy-anchor-r was added there the English rule started matching an
   Arabic block and flipped its text to the left — caught by measuring ar against
   fa, which stayed right.
   0,4,0 with !important also outranks line 3289's right !important at 0,3,1, so
   nothing in the base sheet could take it back. This is 0,5,1 and does.
   The redundant .m3 is being removed from that markup in the same change, so this
   rule is belt-and-braces: it makes the EDIT-V19 selector direction-safe for any
   RTL block that carries .m3 in future, rather than relying on the markup.
   -------------------------------------------------------------------------- */
@media (min-width: 901px) {
  html[dir="rtl"] .v2x--right .v2x__copy.m3.copy-anchor-r { text-align: right !important; }
}

/* ===================== EDIT-V21 =====================
   V1 + V1 Core English pages: copy anchored to the LEFT of the frame, left edge
   on the VOCAL logo column, text staying left-aligned.

   Five of the six blocks needed no new CSS at all — they are already left-aligned
   and only sat 43px inside the logo column, which is exactly what .hdr-align
   exists to fix (v1.html hero + "AI camera · OIS", v1-core.html hero + "Multi AI
   camera" + "Performance"). Measured before: children at x=129 against a logo at
   x=86; after: all at 86.

   The sixth is v1.html's "5000mAh" block, which is .v2x__copy--mid inside a
   .v2x--center section, i.e. centred by line 2757. .side-left already handles
   exactly this shape (EDIT-V10 gave it its own text-align for the --mid case) but
   it is UNGATED, and at 375px it moved that block's text from centre to left and
   pulled the eyebrow from a centred 75/75 to 0/149. Reusing it would also have
   silently changed v2-lite's leather block, which is the sheet's only other
   .side-left --mid user. Hence .copy-anchor-l: the mirror of EDIT-V19's
   .copy-anchor-r, gated so mobile is untouched by construction. Verified at 375px
   after the change: text-align still center, eyebrow back at 75/75.

   .v2x__scrim--full.scrim-strong is the third variant of the EDIT-V18 scrim, and
   this block is the reason it exists. Its paragraph is unreadable TODAY, before
   any of this: the photo behind it runs 186-247 from x=206 rightwards — the phone
   body fills almost the whole width at that height — and against #d9cba6 text the
   paragraph measures 1.25:1 centred. Moving it left only reached 1.71:1, because
   the dark strip on the left is just ~120px wide, far narrower than any usable
   paragraph. Capping the width could not fix it; only a scrim could. With this
   gradient the paragraph measures 9.93:1.
   Applied to --full rather than switching the markup to --left on purpose: line
   2798 rewrites --left and --right to a vertical gradient below 901px but does not
   touch --full, so swapping the class would have changed the mobile scrim too.
   Overriding --full inside a min-width gate leaves the mobile radial exactly as it
   is (verified: still radial-gradient at 375px).
   Specificity 0,2,0, which beats the base .v2x__scrim--full at line 2750 (0,1,0).
   ========================================================= */
@media (min-width: 901px) {

  /* --mid block anchored left, text left. Mirror of .copy-anchor-r (EDIT-V19). */
  .v2x--center .v2x__copy--mid.copy-anchor-l { text-align: left; }
  .v2x--center .v2x__copy--mid.copy-anchor-l > *,
  .v2x--center .v2x__copy--mid.copy-anchor-l p {
    max-width: 640px;
    margin-right: auto !important;
    margin-left: 0 !important;
  }
  /* inline-block eyebrow (base sheet line 476) has to become a block before auto
     margins can position it — same fix as EDIT-V09/V10/V19/V20. */
  .v2x--center .v2x__copy--mid.copy-anchor-l > .eyebrow { display: block; width: fit-content; }

  /* deep left scrim for a radial-scrim section whose copy has moved to the left */
  .v2x__scrim--full.scrim-strong {
    background: linear-gradient(to right, rgba(12,9,7,.95), rgba(12,9,7,.85) 55%, transparent 88%);
  }
}

/* ===================== EDIT-V22 =====================
   .m2r's chips rule is wrong under RTL, and this is the first change that
   exercises it.
   Lines 3457 and 3491 both say .v2x__copy.m2r .v2x__chips { justify-content:
   flex-end !important }. In a flex row with direction:rtl the main axis runs
   right-to-left, so flex-END packs the pills on the LEFT. Until now no .m2r block
   on the site carried .v2x__chips — v2-pro's battery and life blocks have none,
   and the V11 hero uses .v2x-hero__chips, a different class — so the bug was
   never visible. Moving v1-core's "MediaTek G36" block from .m2l to .m2r brought
   a chips row into an .m2r block for the first time: measured, the pills stopped
   at x=1085 while the copy's right edge was 1339, a 254px gap.
   flex-START is the visual right under RTL. Same lesson as EDIT-V20's chips fix,
   one class over.

   Deliberately NOT gated. On mobile these blocks previously carried .m2l, whose
   chips rule is already flex-start, so their pills sat at the right edge at 375px.
   Gating this to desktop would let .m2r's flex-end through on mobile and move them
   to the left — verified: pill gap-right went 0 -> 80 without this rule, and back
   to 0 with it. Ungated is what keeps mobile identical.

   LTR is untouched: the selector is scoped to html[dir="rtl"], so any left-to-
   right page keeps flex-end, which is its correct visual right.
   Specificity 0,4,1 against the base rules' 0,3,0.
   ========================================================= */
html[dir="rtl"] .v2x__copy.m2r .v2x__chips,
html[dir="rtl"] .v2x-hero__copy.m2r .v2x__chips { justify-content: flex-start !important; }

/* ===================== EDIT-V23 =====================
   RTL guard for .copy-anchor-l, the mirror of what EDIT-V20 had to do for
   .copy-anchor-r.
   EDIT-V21 introduced .copy-anchor-l for v1.html's "5000mAh" block and gave it
   text-align:left, which is right for the English page it was written for. The
   Persian and Arabic v1 pages now use the same class on the same block, and there
   left is wrong: the copy has to move to the logo column while the text keeps
   reading right-to-left. Verified after this rule: computed text-align is "right"
   with every child sharing a left edge at the logo, offset 0.
   0,4,1 against .v2x--center .v2x__copy--mid.copy-anchor-l at 0,3,0.
   Gated to match the class it is correcting, so mobile keeps the block centred.

   The fa/ar copies of that block also get .scrim-strong on their --full scrim, for
   the reason EDIT-V21 documents in full: the photo behind the paragraph runs
   bright across almost the whole width, so at the left the Persian paragraph
   measures 1.55:1 without it and 9.21:1 with it. The scrim lives in the markup, so
   each language file carries its own.
   ========================================================= */
@media (min-width: 901px) {
  html[dir="rtl"] .v2x--center .v2x__copy--mid.copy-anchor-l { text-align: right; }
}

/* ===================== EDIT-V24 =====================
   F4 hero: make the floating phone duo actually visible.
   The markup and the CSS for it were already there in all three languages —
   .fhero-duo with a back image, a front image and a sheen — but nothing showed
   except a faint ghost outline, and the reason is one number. Inside #overview
   (which sets isolation:isolate, so it is its own stacking context) the layers
   measured:
       section::after   -1
       .fhero-duo       -1     <- the phones
       .v0-herobg        0     <- the hero photo, opacity .95
       .v1c-hero__scrim  1
       .v1c-hero__fade   1
       .v2x-hero__copy   4
   The duo sat BELOW the background photo, and since that photo is 95% opaque only
   5% of the phones came through — exactly the ghost rectangle that was visible.
   z-index:1 puts them above the photo while leaving them in the same layer as the
   scrim and the fade. Those two come later in the DOM, so they still paint over
   the phones: the duo keeps the same tonal wash as the background and its feet
   still melt into the bottom fade instead of ending on a hard edge. z-index:2 or 3
   would have lifted the phones out of that treatment.

   Scoped to .f-hero, which is exactly the three f-series page families and nothing
   else: f1, f2 and f4 are the only pages in the tree carrying that class or the
   .fhero-duo markup, and all three have now had the same treatment requested.
   An earlier note here claimed f1's artwork was a 789x220 strip rather than a
   phone; that was a misread of truncated file output. It is 789x2200 — a slim
   candybar, the same shape as the others, just narrower.

   No sizing rule was needed. The old artwork was a 2200x2092 frame that was ~79%
   empty, and because .fhero-duo img sizes by frame HEIGHT the layout reserved room
   for all that padding: two frames plus the gap wanted 1543px inside a 1367px box,
   so 176px of the front phone was clipped by overflow:hidden — off the right in
   LTR, off the left in RTL. The replacement artwork is cropped to the phone, so
   the same rules now need 1099px and the container shrink-wraps to 1098px.
   Overflow measured afterwards: 1px.

   Two things found here and deliberately left alone:
   - .fhero-duo__b { height: 84% } at line 3315 never applies. .fhero-duo img at
     line 3314 is 0,1,1 and beats it at 0,1,0, so both phones render at 100% and
     the intended depth cue is missing. Fixing it changes f1 and f2 as well.
   - html[dir="rtl"] .fhero-duo is declared three times (3321, 3425, 3471) with
     conflicting sides. They only resolve because the last one wins on source
     order. It happens to resolve to left, which is what is wanted here.
   Mobile is deliberately left exactly as it is today. Nothing in the sheet ever
   gave .fhero-duo a mobile treatment — there is no media query touching it — and
   at 375px the container is 360px wide while two phones plus the gap want 732px,
   so revealing them there put the front phone at left:-352, entirely off-screen.
   Rather than invent a phone layout nobody specified, this rule is gated to
   min-width:901px: desktop gets the duo, phones keep the plain background they
   have now. Making it work on mobile means choosing a treatment — most likely a
   single phone, the way .v11-hero__phone is handled at line 2964 — and that is a
   design call, not a bug fix.
   ========================================================= */
@media (min-width: 901px) {
  .f-hero .fhero-duo { z-index: 1; }
}

/* ===================== EDIT-V25 =====================
   F4 hero duo, three adjustments. All scoped to .f4-hero and gated to the same
   min-width as EDIT-V24, since the duo only renders on desktop.

   1. 20% smaller. .fhero-duo sizes by height (line 3313, height:80%) and the
      images follow at height:100%, so one number does both views: 80% -> 64%.
      At a 900px hero that takes them from 720px tall to 576px, and the widths
      follow the artwork aspect: front 528 -> 422, back 542 -> 434.

   2. ~10px overlap, front over back. Flex `gap` cannot go negative, so the 2vw
      gap (28.8px) is zeroed and the front image gets a negative inline-start
      margin instead.
      margin-inline-start, not margin-left, is load-bearing here. .fhero-duo__a is
      the second flex item, so its inline-start edge is always the one facing
      .fhero-duo__b — on the left in LTR, on the right in RTL, because the row
      direction flips. A physical margin-left would pull the phones together in
      English and push them apart in Persian and Arabic.
      Front over back is what the DOM already gives: __a comes after __b, so it
      paints on top without needing a z-index.

   3. The golden sheen is switched off. .fhero-duo__sheen (line 3316) is a
      mix-blend-mode:screen band of rgba(240,208,136,.20) at 112deg that the fsheen
      keyframes sweep across the phones every 5s — that is the moving gold.
      display:none rather than deleting the span from three HTML files, so f1 and f2
      keep theirs.
      The ffloat animation on line 3314 is left alone on purpose: that is the slow
      vertical bob, i.e. the floating itself, not a colour effect.
   4. Centred vertically in the frame. The base rule pins the duo with bottom:0 and
      align-items:flex-end, so the phones stood on the floor of the hero. top:50%
      with bottom:auto and translateY(-50%) centres the 64%-tall box instead.
      The transform is safe to put here: ffloat animates transform on the IMG, not
      on this container, so the two never fight over the same property.
   5. overflow:visible. The base rule clips the container, and .fhero-duo img
      animates transform: translateY(-14px) via ffloat, so the top of each phone
      was being cut off at the extreme of every bob — measured 5px of clipping at
      rest, up to 14px mid-cycle. Nothing needs clipping here now.

   6. filter:none on the images. The base rule carries
      drop-shadow(0 34px 60px rgba(0,0,0,.6)) — the soft grey pool under and around
      the phones. Removing the filter rather than the whole rule keeps the ffloat
      animation, which is declared in the same block.

   7. -30px between the two views, i.e. a 30px overlap. Flex gap cannot be
      negative, so gap is 0 and the front image carries margin-left:-30px.
      margin-left, not margin-inline-start: point 8 pins direction:ltr on the
      container, so the front image is always the right-hand one and its left edge
      is always the one facing the back image. With the direction fixed, the
      physical property says what is actually happening.
      The front image paints on top of the back one without a z-index, because
      .fhero-duo__a comes second in the DOM.

   8. direction:ltr on the container, so the internal order is the same in all
      three languages: back on the left, front (the one with the keypad) on the
      right. Without it the flex main axis reverses on the RTL pages and the two
      views swap sides. This governs only the container's own content — the
      container's position on the page still follows the language, right in English
      and left in Persian and Arabic, because that comes from the physical left/right
      declared on .fhero-duo itself.
   ========================================================= */
@media (min-width: 901px) {
  .f-hero .fhero-duo {
    height: 64%;
    gap: 0;
    top: 50%;
    bottom: auto;
    transform: translateY(-50%);
    overflow: visible;
    direction: ltr;
  }
  .f-hero .fhero-duo img { filter: none; }
  .f-hero .fhero-duo__a { margin-left: -30px; }
  .f-hero .fhero-duo__sheen { display: none; }
}

/* ===================== EDIT-V26 =====================
   .copy-flush-r (+ .col-narrow) — an English .v2x__copy--end block moved to the
   RIGHT of its section, right edge on the header column, text still left
   aligned. For f1.html line 108 ("Less noise, more life") and f2.html line 108
   (#design, "Beautiful front, confident back"). Pairs with .hdr-align, which is
   what carries the edge the last 43px out to the nav column.

   Why not .side-right (EDIT-V09), which does exactly this geometry? Because its
   two child rules at lines 3723-3729 are NOT gated to desktop, and one of them
   turns the .eyebrow into a fit-content block with margin-left:auto. At 375px
   that measured the eyebrow pill jumping from 23..246 (its inline-block resting
   place, left) to 129..353 (right-flushed) — the title and paragraph are already
   viewport-width so they do not move, but the pill does. A visible mobile
   change, and mobile was not in scope.

   Leaving .side-right alone rather than gating it is deliberate too:
   v2-lite.html lines 99 and 177 already carry it and are live, line 177 with
   this exact .v2x__copy--end + .side-right + .hdr-align trio. Gating the shared
   rule would have moved their eyebrows on mobile as a side effect on a page
   nobody asked about. So this is a copy of that geometry with a desktop gate
   around it, and .side-right keeps its current users unchanged.

   No text-align here, for the same reason EDIT-V09 omits it: the base sheet
   already computes left for these blocks, and declaring it again would only add
   a rule to fight with later.

   .col-narrow narrows the column from 640px to 420px, and only f1 needs it.
   Measured column profile of assets/f1-flatlay.webp over the copy's vertical
   band: the notebook/pencil/phone subject spans x=440..880, and from x=888
   rightwards the photo is empty and very dark (max luminance 0.022-0.026, mean
   0.020). A 640px column right-flushed to the header column starts at x=699,
   which lands the heading straight across the phone and its lit screen — worst
   glyph contrast 1.92:1 there. 420px starts at x=919: clear of the subject by
   39px, worst glyph contrast 10.87:1 against the EXISTING --right scrim, so no
   scrim change is needed. 440px also clears, by 19px, at 10.86:1; 480px still
   overlaps the subject by 21px. 420 was taken for the margin, and it costs
   nothing here: f1's heading is split by a <br> ("Less noise," / "more life")
   so it stays two lines at every width from 420 to 640, and the paragraph
   returns to the same 3 lines it has today.

   f2's #design block deliberately does NOT take .col-narrow. f2-dark.webp is
   busy edge to edge with no quiet strip, the default 640px column already
   measures 6.98:1 there, and narrowing to 420 wraps that longer heading from
   two lines to three for no legibility gain. Same instruction, two photos, two
   answers. For the record f2 needed this move badly: with the copy in its old
   left position the heading sat on the bright yellow of the phone screen at
   1.26:1.

   Specificity: the child rule is 0,3,0, the .col-narrow override 0,4,0, so the
   narrowing wins on specificity and not on source order.
   ========================================================= */
@media (min-width: 901px) {
  .v2x .v2x__copy.copy-flush-r > *,
  .v2x .v2x__copy.copy-flush-r p {
    max-width: 640px;
    margin-left: auto !important;
    margin-right: 0 !important;
  }
  /* the eyebrow is display:inline-block in the base sheet (line 476) and auto
     margins do not move an inline-block, so it has to become a block first —
     same fix as EDIT-V09/V10/V19. */
  .v2x .v2x__copy.copy-flush-r > .eyebrow { display: block; width: fit-content; }

  .v2x .v2x__copy.copy-flush-r.col-narrow > *,
  .v2x .v2x__copy.copy-flush-r.col-narrow p { max-width: 420px; }
}

/* ===================== EDIT-V27 =====================
   .col-narrow for the RTL path, so it works on .m2r blocks the way EDIT-V26
   made it work on .copy-flush-r ones. Used by f1-fa.html and f1-ar.html
   line 108 — the "less noise, more life" block.

   Asked for directly: the Persian paragraph there should read as three lines
   instead of two. Narrowing the column is what does that, and it also lifts the
   copy clear of the phone in assets/f1-flatlay.webp (subject x=440..880), which
   the 640px column did not: at 640 the Persian paragraph's first line reaches
   left to x=722, crossing the phone by 158px.

   Measured on the fa page, column width vs result:
     640 -> paragraph 2 lines, ink from 722, overlaps phone by 158, worst 5.83:1
     480 -> paragraph 3 lines, ink from 863, overlaps phone by 17,  worst 7.47:1
     460 -> paragraph 3 lines, ink from 889, clears phone by 9,     worst 10.92:1
     440 -> paragraph 3 lines, ink from 920, clears phone by 40,    worst 10.91:1
     420 -> paragraph 3 lines, ink from 920, clears phone by 40,    worst 10.91:1
     400 -> heading breaks to 3 lines as well. Too narrow.
   420 and 440 measure identically for fa, so 420 was taken to keep ONE number
   governing both the LTR and RTL paths of .col-narrow.

   FA and AR diverge here, and it is the copy, not the CSS. The Arabic paragraph
   is 96 characters against Persian's 147, and its total ink is a constant 641px
   (614+27 at a 640px column, 439+202 at 440, 374+267 at 380) — it fits two
   lines at every width down to 380 and no column setting will make it three.
   The parity rule is "the same class edit applies to both", and that is what is
   done: same class, same 420px column, same right edge. AR renders two lines
   because its sentence is shorter. Making it three would need a column near
   320px, which would wrap the heading as well and stop matching FA at all.
   If three lines are wanted in Arabic too, the Arabic sentence has to grow —
   that is a copy decision, not a layout one.

   AR at 420 checks out on its own terms: ink from x=965, clears the phone by
   85px, worst glyph contrast 11.03:1.

   Specificity: .m2r's child rule at lines 3487-3490 sets max-width:640px at
   0,2,0. Adding .col-narrow to .v2x .v2x__copy.m2r makes this 0,4,0, so it wins
   on specificity, not source order. .hdr-align's RTL child rule (line 3587)
   only touches margins, so the two do not collide.

   Gated 901px+ like EDIT-V26. Below that .m2r's own 640px cap is already wider
   than the viewport and inert.
   ========================================================= */
@media (min-width: 901px) {
  .v2x .v2x__copy.m2r.col-narrow > *,
  .v2x .v2x__copy.m2r.col-narrow p { max-width: 420px; }
}

/* ===================== EDIT-V28 =====================
   .col-tight — 390px child column for an .m2l block, so its paragraph reads as
   two balanced lines instead of one long line plus an orphan word.
   Used by f1-fa.html and f1-ar.html line 119 (#reach, "always on, never empty").

   The complaint was the shape of the wrap, not the alignment. At the inherited
   640px column the Persian paragraph measured two lines of 605px and 57px —
   technically two lines, visually one line with a single word stranded under
   it. Total ink is 661px, so a column near half of that splits it evenly.

   Greedy line breaking makes this a window, not a point. Measured on fa:
     column 358..395 -> 358 + 303  (balance 0.85)
     column 396..640 -> 396 + 265  (balance 0.67)
   and the Persian HEADING's widest line is 380px, so anything under 380 wraps
   the heading to three lines as well. That leaves 380..395 as the only window
   that fixes the paragraph and leaves the heading alone. 390 sits in the middle
   of it with 10px of headroom over the heading — 380 would work but sits exactly
   on the heading's limit, and a font metric shifting by a pixel would break it.

   FA and AR both improve, from different starting points, and the divergence is
   again the copy rather than the CSS:
     fa  100 chars, 661px ink: 605+57 -> 358+303, balance 0.09 -> 0.85
     ar   87 chars, 588px ink: ONE line -> 360+224, balance 0.62
   AR's heading is only 297px wide so it has 93px of headroom at 390; its lower
   balance is just its shorter sentence. Same class, same width, same window.

   Contrast improves as a side effect. The scrim here is --left (dark on the
   left, "to right" with alpha .9 -> .35 at 48% -> 0 at 72%), so pulling the
   text's right edge in from x=776 to x=526 moves it toward the dark side:
   worst glyph contrast 2.05:1 -> 3.89:1 on fa, 2.20:1 -> 3.89:1 on ar.

   Still short of 4.5:1, and worth recording why it was left there. Adding
   .hdr-align to this block would move it 35-43px further left onto the logo
   column (where the English copy of this block already sits) and reach 4.25:1,
   but the fa/ar placement of these pages is being driven separately, so only
   the wrap was changed here. The remaining gap needs the scrim, not the column.

   Specificity: .m2l's child rule at lines 3497-3499 sets max-width:640px at
   0,2,0. One more class makes this 0,4,0. Line 3680 (.m2l.lift-max > *, 480px)
   is the same pattern for a different block, with a different number for the
   same reason — the number belongs to the block, not to the class family.

   Gated 901px+. Below that .m2l's own 640px cap is wider than the viewport and
   a 390px cap would start reshaping the mobile layout, which is out of scope.
   ========================================================= */
@media (min-width: 901px) {
  .v2x .v2x__copy.m2l.col-tight > *,
  .v2x .v2x__copy.m2l.col-tight p { max-width: 390px; }
}

/* ===================== EDIT-V29 =====================
   F1 hero duo nudged 25px toward the middle of the frame, all three languages.

   Horizontal placement of .fhero-duo lives in the base rules, not in the
   EDIT-V24/V25 block: line 3313 anchors it with right:4vw for LTR, and
   html[dir="rtl"] .fhero-duo sets left:4vw for RTL. (That RTL rule is declared
   three times — 3321, 3425, 3471 — all at 0,2,1, so the last one wins and the
   effective RTL anchor is left:4vw. Noted again here because anyone editing
   those three lines will change this block's behaviour.)

   "Toward the middle" is therefore a different physical direction per language:
     LTR  duo sits right  (measured 964..1353 in a 1410px frame, gap 57 = 4vw)
          -> move LEFT  -> right: 4vw + 25px
     RTL  duo sits left   (measured 72..462, gap 57)
          -> move RIGHT -> left:  4vw + 25px
   After: LTR 939..1328, RTL 97..487. Same arrangement, same size, same -30px
   overlap from EDIT-V25 — only the anchor moves.

   Written as two mutually exclusive direction-scoped rules rather than one base
   rule plus an RTL override. Both are 0,3,1, they cannot both match, and
   nothing depends on source order. A bare .f1-hero .fhero-duo setting `right`
   would be 0,2,0 and would also apply on the RTL pages, where it would need
   another override to undo — the mistake this avoids.

   Scoped to .f1-hero, a new class added to the hero section of f1.html,
   f1-fa.html and f1-ar.html. f2 and f4 already carry .f2-hero / .f4-hero for
   exactly this purpose; f1 was the one F page without a product class, so the
   shared .fhero-duo rules had no way to single it out. f2 and f4 keep their
   current anchor — this change is f1 only, as asked.

   Gated 901px+. Below that .f-hero .fhero-duo's z-index:1 (EDIT-V24) is itself
   gated, so on mobile the duo falls back to the base z-index:-1 and sits behind
   the .v0-herobg photo, invisible. Measured at 375px: z-index -1 on all three
   F pages. Moving something invisible is pointless, and leaving mobile alone is
   the standing rule anyway.
   ========================================================= */
@media (min-width: 901px) {
  html:not([dir="rtl"]) .f1-hero .fhero-duo { right: calc(4vw + 25px); left: auto; }
  html[dir="rtl"] .f1-hero .fhero-duo { left: calc(4vw + 25px); right: auto; }
}

/* ===================== EDIT-V30 =====================
   F2 hero duo: the two phones 20px closer together, and the pair as a whole
   25px toward the middle of the frame. All three languages.

   1. Overlap. EDIT-V25 line 4563 sets .f-hero .fhero-duo__a { margin-left:-30px }
      for the whole F series. 20px closer means -50px, for F2 only. Flexbox gap
      cannot go negative, which is why this is a negative margin on the second
      item rather than a gap change — the same reason EDIT-V25 gives.

      margin-LEFT, not margin-inline-start, is correct in all three languages
      here: EDIT-V25 pins direction:ltr on .fhero-duo itself, so the row order is
      always __b then __a and the physical left is always the overlapping edge.
      Measured -30 on f2, f2-fa and f2-ar alike before this change.

      Specificity: line 4563 is 0,2,0. Going through the container makes this
      0,3,0, so it wins on specificity rather than on being later in the file.
      A bare .f2-hero .fhero-duo__a would also be 0,2,0 and would only win by
      source order — fine today, fragile the moment either block moves.

   2. Toward the middle, same direction-dependent problem as EDIT-V29 on F1:
        LTR  duo sits right (measured 567..1353, right:4vw) -> right: 4vw + 25px
        RTL  duo sits left                                  -> left:  4vw + 25px
      Written as two mutually exclusive direction-scoped rules, both 0,3,1.

   The two changes compound, and that is intended. The container is anchored by
   one edge and sized by its content, so 20px more overlap makes it 20px
   narrower: at 1425px the pair goes from 567..1353 (787 wide) to 561..1328
   (767 wide). The anchored edge moves the full 25px toward the centre, the far
   edge moves 25-20=5px the other way, and the phones close up by 20px. That is
   what was asked for; if the pair should instead keep its far edge, the anchor
   shift needs to be 5px rather than 25px.

   Scoped to .f2-hero, which already exists on f2.html, f2-fa.html and
   f2-ar.html (its only other use is the hero glow at line 3101). F1 keeps
   EDIT-V29's 25px shift with the -30px overlap, and F4 keeps both defaults —
   this block changes F2 alone.

   Gated 901px+ to match EDIT-V24/V25/V29. Below that the duo falls back to the
   base z-index:-1 and hides behind the .v0-herobg photo, so there is nothing to
   move on mobile.
   ========================================================= */
@media (min-width: 901px) {
  .f2-hero .fhero-duo > .fhero-duo__a { margin-left: -50px; }
  html:not([dir="rtl"]) .f2-hero .fhero-duo { right: calc(4vw + 25px); left: auto; }
  html[dir="rtl"] .f2-hero .fhero-duo { left: calc(4vw + 25px); right: auto; }
}

/* ===================== EDIT-V31 =====================
   .col-370 — 370px child column for the F2 #design copy, so its Persian
   paragraph reads as three lines. f2-fa.html and f2-ar.html line 108.

   Naming, deliberately different from its two predecessors: .col-narrow (420px,
   EDIT-V26/V27) and .col-tight (390px, EDIT-V28) are already vague enough that
   nobody will remember which is wider. The width belongs to the block, not to
   the class family, so from here on the number goes in the name. The two older
   names stay as they are — renaming them would touch five live pages for no
   behavioural gain.

   Why 370 and not the existing 420. Measured on fa (paragraph 132 chars, 927px
   of ink, heading widest line 339px):
     420 -> 3 lines 420 + 414 + 90   (third line a 90px orphan)
     400 -> 3 lines 383 + 393 + 147
     380 -> 3 lines 363 + 324 + 236
     370 -> 3 lines 363 + 324 + 236  <-- taken
     360 -> 3 lines 323 + 308 + 292  (best balance of all, 0.90)
   360 looks best in Persian and was still rejected, because of Arabic:
     ar (102 chars, 694px of ink, heading 317px)
     400..370 -> 2 clean lines, best balance 0.91 at 370
     360..340 -> 3 lines 330 + 320 + 40   <-- a 40px orphan
   So 360 would buy a prettier Persian block by inflicting on Arabic exactly the
   stranded-word shape this whole exercise exists to remove. 370 is the widest
   width that gives Persian a well-formed third line (236px, no orphan) while
   leaving Arabic on two balanced lines. Headroom over the Persian heading is
   31px, so the heading stays two lines with room to spare.

   AR staying on two lines is the copy, not the CSS — same as EDIT-V27 and V28.
   Its sentence is 30 characters shorter and 233px lighter in ink.

   Contrast improves as a side effect: this is an .m2r block right-flushed on the
   header column, and the scrim is --right, so narrowing pulls the ink toward the
   dark side. Worst glyph contrast fa 7.17 -> 8.44, ar 7.12 -> 8.45.

   NOT applied to f2.html. The English heading there is 465px wide, so any column
   under 480 wraps it to three lines, and its paragraph is a different length
   again — that block needs its own number if it is ever asked for.

   Specificity 0,4,0 against .m2r's 0,2,0 child rule at lines 3487-3490, the same
   shape as EDIT-V27. Gated 901px+; below that .m2r's own 640px cap already
   exceeds the viewport.
   ========================================================= */
@media (min-width: 901px) {
  .v2x .v2x__copy.m2r.col-370 > *,
  .v2x .v2x__copy.m2r.col-370 p { max-width: 370px; }
}

/* ===================== EDIT-V32 =====================
   .col-500 — 500px child column for the ENGLISH F2 #design copy, so its
   paragraph reads as three lines in a narrower column. f2.html line 108,
   the .copy-flush-r path (EDIT-V26), companion to .col-370 on the fa/ar side.

   This block cannot be made to look like the Persian one, and the reason is
   arithmetic rather than taste. Measured at 1425px:
     paragraph ink total          1030px  (138 chars)
     heading widest line           487px  ("Beautiful front,")
   The heading floors the column at 487, and 1030/487 = 2.11 lines, so the third
   line can never carry more than about a tenth of a line. Every option in the
   window is a stub:
     col 520 -> 3 lines 506 + 488 + 31   heading 2 lines, 33px headroom
     col 510 -> 3 lines 506 + 488 + 31   heading 2 lines, 23px headroom
     col 500 -> 3 lines 482 + 493 + 50   heading 2 lines, 13px headroom  <-- taken
     col 490 -> 3 lines 482 + 456 + 87   heading 2 lines,  3px headroom
     col 480 -> heading breaks to 3 lines ("confident back" wraps)
     col 470 -> heading breaks to 4 lines (both title spans wrap)
   490 gives the longest third line and the narrowest column, and was still not
   taken: 3px of clearance is inside the range that sub-pixel text measurement
   varies across browsers and DPI, and a heading that silently becomes three
   lines looks far worse than a short third line. 500 keeps 13px, which covers
   roughly 2.5% of drift on a 487px line.

   Note the heading breaks in two stages, not one, because .v2x__title is two
   .mask spans: at 480 only the second wraps (3 lines), at 470 both do (4).

   Contrast improves with the narrowing, same mechanism as .col-370 — this is a
   right-flushed block under a --right scrim, so pulling the ink rightward moves
   it into the dark: worst glyph contrast 6.86:1 -> 7.07:1.

   If a full third line is ever wanted here, the lever is the sentence, and it
   has to get LONGER, not shorter: at a 500px column, three filled lines need
   about 1500px of ink against today's 1030. Shortening it would take the
   paragraph back to two lines.

   Specificity 0,4,0 against .copy-flush-r's 0,3,0 child rule (EDIT-V26). Named
   with its number, per the convention started in EDIT-V31. Gated 901px+; below
   that the base sheet caps the paragraph at 440px on its own.
   ========================================================= */
@media (min-width: 901px) {
  .v2x .v2x__copy.copy-flush-r.col-500 > *,
  .v2x .v2x__copy.copy-flush-r.col-500 p { max-width: 500px; }
}

/* ===================== EDIT-V33 =====================
   F4 hero duo moved 30px toward the middle of the frame, all three languages.
   Third and last of the per-page anchor shifts: F1 +25px (EDIT-V29),
   F2 +25px (EDIT-V30), F4 +30px here.

   CORRECTION to an earlier comment in this file. EDIT-V25's header says its
   three adjustments are "All scoped to .f4-hero". They are not — the rules it
   actually ships (height/gap/top/transform/overflow/direction, img filter,
   __a margin-left, __sheen display) are all keyed to .f-hero and therefore
   apply to F1, F2 and F4 alike. The request that produced them came from the F4
   page, which is presumably how the wrong word got in. Nothing in the CSS is
   broken by it, but anyone reading that block would conclude F4 already has its
   own scoped home for duo tweaks, and it does not. This is that home.
   (Left in place rather than edited: the V25 text is already deployed, and
   appending is safer than rewriting live bytes for a comment.)

   The shift itself, same direction-dependent problem as EDIT-V29/V30:
     LTR  duo sits right (measured 532..1353, right:4vw = 57px at 1425)
          -> right: 4vw + 30px
     RTL  duo sits left  (measured 58..878, left:4vw)
          -> left:  4vw + 30px
   Two mutually exclusive direction-scoped rules, both 0,3,1, so neither depends
   on source order and neither needs the other undone.

   Overlap deliberately untouched. F4 keeps the F-series -30px from EDIT-V25;
   only F2 was asked for -50px. So the container width does not change here and
   both edges move the full 30px, unlike EDIT-V30 where the narrowing and the
   shift compounded.

   .f4-hero already exists on f4.html, f4-fa.html and f4-ar.html; its only other
   use is the hero glow at line 3106. F1 and F2 keep their own anchors.

   Gated 901px+. Below that .f-hero .fhero-duo's z-index:1 (EDIT-V24) is itself
   gated, so the duo falls back to the base z-index:-1 and hides behind the
   .v0-herobg photo. Verified at 375px on all three F families.
   ========================================================= */
@media (min-width: 901px) {
  html:not([dir="rtl"]) .f4-hero .fhero-duo { right: calc(4vw + 30px); left: auto; }
  html[dir="rtl"] .f4-hero .fhero-duo { left: calc(4vw + 30px); right: auto; }
}

/* ===================== EDIT-V34 =====================
   V01 hero: the phone artwork vertically centred in the frame, all three
   languages. v01.html, v01-fa.html, v01-ar.html.

   The layout box was already centred and the transform was undoing it. Line
   2953 gives .v11-hero__phone the absolute-centring idiom (top:0; bottom:0;
   margin-block:auto; height:fit-content), so its box sits dead centre. Then
   .v01-hero-big scales it 1.3 about transform-origin: right bottom, which pins
   the bottom edge and grows the image upward only — lifting the visual centre
   by 0.15 x box height. Measured at 1425px: box 560x560, centre 71-77px above
   the section centre, and 50px at a 900px viewport where the box is smaller.
   Changing only the vertical half of the origin fixes it without touching the
   horizontal composition: left/right edges measured identical before and after
   at 1425, 1200 and 900 (603..1331 fa/ar, 588..1316 en).

   Three things worth writing down, since all three cost time to establish:

   1. .v01-hero-big is declared TWICE, lines 3310 and 3418, both 0,1,0. The
      later one wins for `transform` (scale(1.3) translateX(-7%) beats
      scale(1.16) translateX(-5%)), but transform-origin is only in the FIRST
      one, so the effective state is line 3418's transform with line 3310's
      origin. Two half-rules resolving by source order. This block overrides the
      origin at 0,3,0 rather than editing either of them.

   2. GSAP owns `transform` on this element at runtime — it writes
      translate3d(...) scale(1.3,1.3) inline for the float animation. It does
      NOT write transform-origin, which is why a CSS origin change takes effect
      at all. Anything that tried to fix this via `transform` would be
      overwritten on the first animation frame.

   3. The float is asymmetric by design: sampled over 6 seconds the phone
      oscillates from 0 to +16px below the resting point, never above it. So
      "centred" here means the resting position is exact and the animation
      drifts downward from it. Not compensated — that asymmetry belongs to the
      shared .v11-hero__phone animation, not to V01.

   The artwork itself needed no work: assets/v01.png is 750x750 with an alpha
   bounding box of x 128..622, y 94..654 — 94px of padding above, 96px below, so
   the phones are already centred within the file to within 2px. Centring the
   box centres the phones.

   Gated 881px+, i.e. above the .v11-hero__phone mobile breakpoint at line 2963.
   Mobile is deliberately left exactly as it is, and it is worth knowing why it
   looks the way it does: line 2964 tries to reset the phone with
   `transform: none` there, and that can never take effect, because GSAP's
   inline transform outranks every stylesheet rule regardless of specificity or
   order. So on mobile the image is still scaled 1.3 and translated -7%, which
   puts 55-70px of it off the left edge. Pre-existing, unrelated to this change,
   and not touched here.
   ========================================================= */
@media (min-width: 881px) {
  .v01-hero .v11-hero__phone.v01-hero-big { transform-origin: right center; }
}

/* ===================== EDIT-V35 =====================
   V01 hero, fa + ar: the chips row spans the full copy column, so its LEFTMOST
   pill lands on the logo column instead of floating 144-173px inside it.

   The block itself was already right: .m2l + .hdr-align put the container's left
   padding edge exactly on the logo (measured offset 0, and the h1 spans
   101..741). The problem was one level down. .v2x-hero__chips is a flex row and
   the hero copy is direction:rtl, so the main axis runs right-to-left and the
   default packing puts the pills at main-start = the RIGHT, leaving the slack on
   the left. Content is 411px of pills + 3x28px gaps = 495 in a 640 column, so
   exactly 145px of slack sat on the left. Measured leftmost pill at x=245 (fa)
   and 274 (ar) against a logo at 101.

   Two ways to close it, and the choice is not cosmetic:
     justify-content: flex-end  -> in RTL that packs LEFT. Leftmost pill reaches
       the logo, gaps stay 28px, but the rightmost pill then falls 145px (fa) /
       173px (ar) short of the h1's right edge. That breaks the right edge the
       whole RTL block is built on.
     justify-content: space-between -> both edges flush: leftmost on the logo,
       rightmost still exactly on the h1 (measured delta 0 at 1425, 1200, 1000
       and 960). The price is the inter-pill gap growing 28px -> 76px on fa and
       86px on ar.
   space-between is taken. Losing the right edge to save a gap width would be the
   wrong trade in a right-aligned layout. fa and ar end up with different gap
   widths because their labels differ in width; the EDGES match, which is what
   was asked for.

   Gated 901px+, and the number matters: line 2811 is
   @media (max-width: 900px) { .v2x-hero__chips { justify-content: center } }.
   So from 900px down the pills are deliberately centred for the mobile layout
   and this rule must be off. Note line 2967 also centres them at 880px and
   below for .v11-hero — a second, narrower rule for the same thing. 900 is the
   binding one. Verified: at 900, 881 and 375 the computed value stays `center`.

   Only the chips row is changed. The CTA row has the same RTL slack (its
   leftmost button sits 336px/366px inside the logo column) and is deliberately
   left alone: with just two buttons, space-between would open a ~300px hole
   between them, and flex-end would break the right edge the same way. Neither
   is an improvement, so it needs a decision rather than a default.

   English needs nothing: LTR packs from the left, so v01.html already measures
   0 from the logo for both the chips and the buttons.

   Specificity 0,5,1 — far more than needed, since nothing else sets
   justify-content on .v2x-hero__chips above 900px. Deliberate: this is the one
   place in the sheet where hero chips get a justify-content, and a future rule
   on .v2x-hero__chips should not silently take it over.
   ========================================================= */
@media (min-width: 901px) {
  html[dir="rtl"] .v01-hero .v2x-hero__copy.m2l .v2x-hero__chips { justify-content: space-between; }
}

/* ===================== EDIT-V36 =====================
   .col-480 — 480px child column for the V01 flashlight copy, so its paragraph
   reads as three lines in a narrower column. v01-fa.html and v01-ar.html
   line 156, the .m2l path (same family as .col-tight, EDIT-V28).

   Both languages land on three lines at 480 and both keep two-line headings,
   which is the only width where that is true. Measured at 1425px:

     fa  paragraph 182 chars, heading widest line 441px
       640 -> 2 lines
       520 -> 3 lines, shortest 230
       480 -> 3 lines  404 + 457 + 346   heading 2 lines, 39px headroom  <-- taken
       460 -> same split, heading 2 lines, only 19px headroom
       440 -> heading breaks to 3 lines
     ar  paragraph 152 chars, heading widest line 372px
       640, 560 -> 2 lines
       520 -> 3 lines, shortest 50   (a stub)
       480 -> 3 lines  425 + 456 + 176  heading 2 lines, 108px headroom
       400 -> 3 lines  354 + 360 + 343  balance 0.95, its best

   ar would look best at 400, and that is not available: fa's heading is 441px
   wide, so anything under 460 wraps it. 480 keeps 39px of clearance on the
   binding language and gives both a real third line rather than a stub — 346px
   on fa, 176px on ar. The ar third line is short but it is a line, not an
   orphan word, which is the distinction that matters here.

   Contrast improves a lot as a side effect, and it needed to. This is an .m2l
   block (left-anchored box, right-aligned text) under a --left scrim, so
   narrowing pulls the text's right edge leftward into the dark half. Worst glyph
   contrast 1.91:1 -> 3.36:1 on both languages. Still under the 4.5:1 body-text
   guideline: at 640 the worst point was a chip pill at x=722, now it is the
   paragraph's right edge at x=581. Closing the rest needs the scrim, not the
   column — the same conclusion as the other blocks over this portrait photo.

   The chips row rides along, as it should: it is packed to the flex main-start,
   which under RTL is the right, so it tracks the box's right edge inward from
   x=741 to x=581. No separate rule needed.

   NOT applied to v01.html. The English heading there is a different width again
   and its paragraph is a different length, so it needs its own number if asked.

   Specificity 0,4,0 against .m2l's 0,2,0 child rule at lines 3497-3499.
   Named with its number, per the convention started in EDIT-V31. Gated 901px+,
   the sheet's own desktop breakpoint; below it .m2l's 640px cap already exceeds
   the column and lines 2796-2797 own the mobile layout.
   ========================================================= */
@media (min-width: 901px) {
  .v2x .v2x__copy.m2l.col-480 > *,
  .v2x .v2x__copy.m2l.col-480 p { max-width: 480px; }
}

/* ===================== EDIT-V37 =====================
   .col-500 extended to the HERO .m2l path, for the V01 hero copy on
   v01-fa.html and v01-ar.html line 81. Narrows that column 640 -> 500 so the
   four chips sit at a tight gap instead of the wide one EDIT-V35 produced.

   Same class and same number as EDIT-V32's .copy-flush-r rule, not a new name:
   the width is identical, only the path differs. Same pattern as EDIT-V27
   extending .col-narrow from .copy-flush-r to .m2r at 420px.

   Why this is the fix rather than touching the gap directly. EDIT-V35 set
   justify-content: space-between on that chips row so BOTH its edges pin — the
   leftmost pill on the logo column, the rightmost on the h1. That is what was
   asked for, and it means the gap is whatever is left over: (column - pill
   content) / 3. So the gap is a function of the column, and the column is the
   only honest lever. Measured at 1425px, pill content 412px (fa) / 383px (ar):
     col 640 -> gaps 76 / 86   <- EDIT-V35's result
     col 600 -> gaps 62 / 73
     col 560 -> gaps 49 / 59
     col 520 -> gaps 36 / 46
     col 500 -> gaps 29 / 39   <- taken
     col 480 -> fa's pills WRAP to two rows
   500 is the floor. fa's four pills plus three gaps need 496px to stay on one
   line, so 480 breaks them; and at 500 the fa gap lands on 29px, which is the
   28px the base sheet gives .v2x-hero__chips in the first place. ar keeps 39px
   because its labels are narrower — the edges match, the gap follows the copy.

   A defect this also closes, which is why 500 over 520. The V01 hero title has
   overlapped the phone artwork by 14px of ink for as long as the page has
   existed (h1 right edge 741, phone's first opaque pixel 727 — verified both
   before and after EDIT-V34, so the vertical centring neither caused nor
   worsened it). Pulling the column to 500 moves the copy's right edge to 601 and
   turns that -14px overlap into a +126px clearance.

   The CTA row rides inward with the box (its right edge 741 -> 601) and still
   does not reach the logo on the left — see EDIT-V35's note. Unchanged and
   still awaiting a decision, since neither space-between nor flex-end suits a
   two-button row.

   English untouched: v01.html's hero is plain .v2x-hero__copy + .hdr-align with
   no .m2l, and its chips already start at the logo because LTR packs from the
   left.

   Specificity 0,4,0 against .v2x-hero__copy.m2l > * at line 3497 (0,2,0).
   Gated 901px+ like EDIT-V35, so the mobile band keeps line 2811's centred
   pills and the base 640px cap.
   ========================================================= */
@media (min-width: 901px) {
  .v2x-hero .v2x-hero__copy.m2l.col-500 > *,
  .v2x-hero .v2x-hero__copy.m2l.col-500 p { max-width: 500px; }
}

/* ===================== EDIT-V38 =====================
   .day-mid — V01 "your day, in your hand" block (line 210 on v01.html,
   v01-fa.html, v01-ar.html): centred in all three languages, heading group
   pushed to the top of the frame, closing sentence pinned to the bottom on a
   single line. Same shape as .perf-c (EDIT-V17) and .cam-mid (EDIT-V11).

   1. Centred in all three languages. English already was, via .m3's
      text-align:center !important at 0,2,0. fa and ar were NOT, and the reason
      is recorded in this file at line 4260: line 3289
      (html[dir="rtl"] .v2x--right .v2x__copy) sets text-align:right !important
      at 0,3,1, which outranks .m3t's centre. Measured before this change: en
      center, fa right, ar right. The RTL rule here is 0,5,2 with !important,
      which is what it takes to clear 3289.

   2. Single-line closing sentence. Nothing about the sentences needed changing —
      the only thing forcing two lines was the base cap on the paragraph,
      max-width:440px. True one-line extents measured at 1425px: en 682px,
      fa 505px, ar 453px. So `p { max-width: none }` is the whole fix.
      The container has to grow with it: .m3 caps at 720px and .m3t at 760px, and
      those are border-box caps with padding-inline:6vw INSIDE, so at a 901px
      viewport the usable content was only 612px — narrower than English's 682px
      one-liner. Hence max-width:1340px, the same widening .cam-mid needed for
      the same reason. Verified one row at 1425, 1200 and 901.

      Deliberately NOT using white-space:nowrap. It is unnecessary once the cap
      is gone, and .cam-mid's own comment (lines 3842-3849) records what nowrap
      cost there: below roughly a 1070px viewport the line overflowed and got
      CLIPPED, 280px off a paragraph at 901px. Removing a cap degrades into a
      wrap; nowrap degrades into a truncation.

   3. Heading group at the top. align-self:stretch + flex column + padding-top,
      with the paragraph taking margin-top:auto to fall to the bottom. This also
      has to beat .m3t's margin-top:10vh / margin-bottom:30vh / align-self:
      flex-start, which is why margins are zeroed explicitly here.

      padding-top is 112px, chosen against the header rather than by eye. With
      the section parked at the viewport top the sticky header's bottom edge sits
      at y=101 (announcement strip + 65px nav). Measured eyebrow clearance below
      it: 112px -> 48px clear, 124px -> 60px, 136px -> 72px. 112 is the highest
      of the three that still leaves clean air under the header, and it already
      lifts the eyebrow above where it sits today (174px on fa/ar, 313px on en).
      A fixed px rather than a vh clamp on purpose: the header height does not
      scale with viewport height, so a vh value would go under it on short
      screens. padding-bottom 72px leaves the sentence 34px off the section
      floor.

   Specificity: the selector mirrors line 3254 plus the class, giving 0,4,1.
   Line 3254 (section.v2x[class*="v2x--"] .v2x__copy) owns padding-block at
   0,3,1, so the obvious .v2x--right .v2x__copy.day-mid at 0,3,0 would lose the
   padding and silently keep the old vertical rhythm — the same trap .perf-c
   documents at line 4080.

   Markup note, left alone on purpose: line 210 carries .m3 on v01.html, .m3t on
   v01-fa.html and .m3 .m3t on v01-ar.html — a stray .m3 on the Arabic page of
   exactly the kind that bit v11-ar (see line 4318). It is inert for this block
   now, because everything .m3 and .m3t set here (max-width, margins,
   align-self, text-align) is overridden above. Worth removing as its own
   cleanup, not inside this change.

   Gated 901px+. Below it lines 2796-2797 and 2811 own the mobile layout, fa/ar
   stay right-aligned as they are today, and nothing here applies.
   ========================================================= */
@media (min-width: 901px) {
  section.v2x[class*="v2x--"] .v2x__copy.day-mid {
    max-width: 1340px;
    align-self: stretch;
    display: flex;
    flex-direction: column;
    margin-top: 0;
    margin-bottom: 0;
    padding-top: 112px;
    padding-bottom: 72px;
    text-align: center;
  }
  section.v2x[class*="v2x--"] .v2x__copy.day-mid > p {
    margin-top: auto;
    margin-inline: auto;
    max-width: none;
  }
  section.v2x[class*="v2x--"] .v2x__copy.day-mid > .eyebrow { align-self: center; }
  html[dir="rtl"] section.v2x[class*="v2x--"] .v2x__copy.day-mid { text-align: center !important; }
}

/* ===================== EDIT-V39 =====================
   V0 hero: the transparent phone shot made VISIBLE, floating, and sized ~20%
   larger than the first pass — v0.html, v0-fa.html, v0-ar.html, the
   <img class="v0-phones"> that has been in the markup at line 80 all along.

   1. It was invisible, for exactly the reason the F-series duo was (EDIT-V24).
      #overview carries isolation:isolate, .v0-herobg sits at z-index:0 with
      opacity .95, and .v0-phones was left at z-index:-1 — so the phones rendered
      BEHIND the hero photo and only ~5% bled through. z-index:3 here, not 1: the
      stack in this section is herobg 0, scrim 1, fade 1, glow 2, copy 4,
      scroll 5, so 3 is the only value that clears the glow and still passes
      under the copy. It matches line 2979's .v1c-hero .v11-hero__phone.

   2. Size. The old rule sized by height — min(86vh, 760px) — which with this
      artwork's 1.751 aspect works out to 1331px wide, nearly the whole 1410px
      frame, straight across the copy. Nobody had noticed because it was hidden.
      (It never even reached 760px: a global img { max-width: 100% } capped the
      box at the frame width, so the rendered height was ~575px.)

      A plain vw share does not work, because the copy has a floor — its chips
      row and buttons stop shrinking — while a vw width keeps shrinking. Measured
      room from the copy's furthest ink to the frame edge, English binding:
        1425px viewport -> 805px    1200 -> 628    1024 -> 463    901 -> 347
      i.e. room ~= 0.91 * viewport - 430 once the bleed below is counted.

   3. Why the negative anchor. At a 1440px viewport the full 840px width simply
      does not fit between the copy and the frame edge: 840 + a 40px gap + the
      copy's 605px edge = 1485 against a 1425px frame. So the extra 20% has to
      come out of either the gap or the frame edge, and the gap is the wrong one
      to spend — the copy sits at z-index:4, ABOVE the image, so an overlap puts
      body text over the lit phone screen. Measured at 1440:
        cap 840, anchor 4vw  -> width only 743 (+6%), the vw term binds first
        cap 840, anchor 1vw  -> width 840 but gap -43px, text over the screen
        cap 840, anchor -55px -> width 840, gap +26px            <- taken
      The bleed is safe because #overview already sets overflow:hidden, so the
      overhang is CLIPPED by the section rather than spilling into the document.
      Verified: document.scrollWidth unchanged at 1600/1440/1200/1024/901 on both
      LTR and RTL, no horizontal scrollbar introduced anywhere.
      Bleed sized by what it costs the artwork: 40px -> gap 11, clips 4.8% of the
      image; 55px -> gap 26, clips 6.5%; 70px -> gap 41, clips 8.3%. 55 is the
      balance — a workable gap for a 6.5% overhang, and the artwork fills its box
      edge to edge (solid pixels from x=8 to x=1272 of 1276), so there was no
      transparent margin to spend instead.

      Resulting width and English gap: 840/+82 at 1600, 840/+26 at 1440,
      622/+46 at 1200, 462/+41 at 1024, 350/+37 at 901. fa and ar run 60-140px
      looser at every width because their copy is narrower.

   4. Floating. The keyframes have to carry the centring with them. Line 3407
      centres the image with transform: translateY(-50%), and an animation on
      `transform` REPLACES that — a plain 0 -> -14px float would drop the image
      half its own height down the frame on the first animation frame. So
      v0float animates translateY(-50%) <-> calc(-50% - 14px). Same 7s
      ease-in-out as the F-series ffloat (line 3319), and prefers-reduced-motion
      is honoured the way line 3039 does it for the hero photo.

   Sides: English right, fa+ar left — which is what lines 3407/3411 already did.
   The anchor rules here only change the OFFSET, from 4vw to -55px, and are
   written as two mutually exclusive direction-scoped rules at 0,3,1 so neither
   depends on source order against line 3411's 0,2,1.

   Gated 901px+. Below that .v0-phones keeps exactly today's behaviour — hidden
   behind the photo at z-index:-1 — because mobile was not in scope and the sheet
   has no mobile treatment for this element to match.
   ========================================================= */
@media (min-width: 901px) {
  .v0-hero .v0-phones {
    z-index: 3;
    width: min(840px, calc(91vw - 455px));
    height: auto;
    animation: v0float 7s ease-in-out infinite;
  }
  html:not([dir="rtl"]) .v0-hero .v0-phones { right: -55px; left: auto; }
  html[dir="rtl"] .v0-hero .v0-phones { left: -55px; right: auto; }
}
@keyframes v0float {
  0%, 100% { transform: translateY(-50%); }
  50%      { transform: translateY(calc(-50% - 14px)); }
}
@media (prefers-reduced-motion: reduce) {
  .v0-hero .v0-phones { animation: none; }
}

/* ===================== EDIT-V40 =====================
   .col-full — lets a .v2x__copy use the whole header column and uncaps its
   paragraph, so a closing sentence can sit on one line. Used on the V0 Core
   performance block, line 126 of v0-core.html, v0-core-fa.html and
   v0-core-ar.html, TOGETHER with .perf-c from EDIT-V17.

   .perf-c already does everything else this block needed — centre the text,
   stretch the block, push the heading group to the ceiling, drop the paragraph
   and the chips row that follows it to the floor, keep the eyebrow a
   fit-content pill, and clear line 3290's RTL text-align:right !important at
   0,5,2. Reusing it rather than writing a second copy is the point: this is the
   same shape as the v2-pro T770 block.

   What .perf-c does NOT do is width, and this block needed it, because it
   carries .m3 — whose max-width:720px (line 3353) survives .perf-c untouched —
   and because the base sheet caps the paragraph at 440px (line 2752). Together
   those forced the sentence onto 3 lines on fa/ar and 4 on English.

   One correction to EDIT-V17's own comment while I am here. It says of the
   chips: "Nothing !important targets this block (the !important chip rules at
   3286/3293/3350/3363/3457/3491/3501 are all scoped to --end, m2l, m2r or m3,
   none of which this block carries)." That was true of the v2-pro block. It is
   NOT true here: this block carries .m3, so line 3355's
   .v2x__copy.m3 .v2x__chips { justify-content: center !important } DOES apply
   and outranks .perf-c's plain `center` at 0,4,1. Harmless, because both say
   centre and the measured result is centre — but the reasoning in that comment
   does not transfer, and a future block carrying .m3 with a different chips
   intent would be surprised.

   Measured one-line extent of the paragraph, and this is where the languages
   part company:
     fa   951px      ar   940px      en  1282px
   Usable content width with max-width:1340px and the sheet's 6vw gutters:
     1600px viewport -> 1148    1425 -> 1169    1200 -> 1041    901 -> 778
   So fa and ar reach one line from about 1200px up, and English cannot: 1282px
   does not fit any of those. Dropping the gutter to 2vw was tried and gets
   English onto one line at 1425 and 1600 only, still two lines at 1200, at the
   cost of running the text almost to the frame edges. Not worth it — English
   goes from FOUR lines to two, which is the real improvement, and the standard
   6vw column is kept. Below 901 nothing applies and the block keeps today's
   mobile layout.

   Specificity mirrors line 3254 plus the class, 0,4,1, the same trick .perf-c
   uses: line 3254 owns padding-block at 0,3,1 and .m3 owns max-width at 0,2,0,
   so a plainer selector would lose the width silently.
   ========================================================= */
@media (min-width: 901px) {
  section.v2x[class*="v2x--"] .v2x__copy.col-full { max-width: 1340px; }
  section.v2x[class*="v2x--"] .v2x__copy.col-full > p { max-width: none; }
}

/* ===================== EDIT-V41 =====================
   English V0 Core hero: copy stays left-aligned, moves to the RIGHT of the
   frame, and its visible content ends exactly on the header's language switcher.
   The scrim flips to follow it. v0-core.html line 80. fa/ar sit right already
   and are untouched.

   PART 1 — geometry. .copy-flush-r extended to the hero path.

   Same class and geometry as EDIT-V26's .v2x__copy rule; only the element names
   differ (.v2x-hero / .v2x-hero__copy). Same approach as EDIT-V27 extending
   .col-narrow and EDIT-V37 extending .col-500 to a second path rather than
   inventing a parallel name. The 640px cap is what makes margin-left:auto bite —
   an uncapped block child fills the line box and an auto margin computes to 0.

   Two existing classes do roughly this and both were rejected:
     .hero-side-right (line 3269) is what v0-core-fa/ar carry and is right for
     them, but its .v2x-hero__copy rule is UNGATED at 0,2,0 — the mobile problem
     EDIT-V19 records at lines 4161-4168.
     .hero-anchor-r (EDIT-V19) is gated and geometrically right, and was tried
     here first because it also carries a right-side scrim. It changed nothing
     visible; PART 3 is why.

   PART 2 — width: fit-content, which is what actually lands the content on the
   header edge.

   margin-left:auto puts the BOX's right edge on the header column, but a block
   child fills the width it is given, so left-aligned text inside it stops
   wherever the words stop and the two flex rows pack from the left. Measured at
   1440 with the cap alone: the title's ink ended at 1193, the chips row at 1203,
   and the button row at 1034 — 146, 136 and 305px short of the language
   switcher's right edge at 1339. width:fit-content shrinks each child to its own
   content so the auto margin pushes the CONTENT, not an empty box: all three
   then measure exactly 0 short, at 1600, 1440, 1200 and 901 alike. Text stays
   left-aligned inside each box, so shorter lines still rag to the left, which is
   what left-aligned copy should do.

   Applied only to the hero path on purpose. EDIT-V26's .v2x__copy rule keeps its
   plain 640px cap: f1.html and f2.html's --end blocks are live on it and their
   ragged right edge is correct there.

   PART 3 — the scrim, and a third sighting of the same trap.

   .v2x-hero::after (line 2715) declares content/position/inset and z-index: -1.
   #overview carries isolation:isolate and .v0-herobg sits at z-index 0, opaque —
   so that pseudo-element paints BEHIND the photo and is invisible on this hero
   no matter what background it is given. That is why .hero-anchor-r's ::after
   (line 4205) did nothing, and it is the same trap as .v0-phones in EDIT-V39 and
   the F-series duo in EDIT-V24. Anything scrimming these heroes through ::after
   is painting under the picture.

   The overlay that DOES render is .v1c-hero__scrim at z-index 1 (line 2999). Its
   LTR background is `to right`, darkest at the LEFT, because every hero using it
   had its copy on the left; line 3001 mirrors it for RTL, which is why fa/ar
   read correctly. Moving the English copy right left it on the brightest part of
   the photo with the dark half empty — the title and the outline button were
   barely legible. So for this one hero the LTR scrim takes the RTL gradient.

   Scoped by a new .v0c-hero marker on the section, added to all three v0-core
   pages so the markup stays uniform; the rule is LTR-only, so fa/ar keep line
   3001. A marker was needed because .v0-hero is shared with v0.html and its two
   translations, and .v1c-hero__scrim appears on 21 pages.

   Gated 901px+ throughout. Below it line 3003 swaps the scrim for a vertical
   gradient and the hero copy centres itself, and fit-content there would drag
   all three rows off the centred layout — measured 297-441px of shift at 900px
   with the gate removed, which is exactly what the gate prevents.
   ========================================================= */
@media (min-width: 901px) {
  .v2x-hero .v2x-hero__copy.copy-flush-r > *,
  .v2x-hero .v2x-hero__copy.copy-flush-r p {
    max-width: 640px;
    width: fit-content;
    margin-left: auto !important;
    margin-right: 0 !important;
  }
  html:not([dir="rtl"]) .v0c-hero .v1c-hero__scrim {
    background: linear-gradient(to left, rgba(10,10,13,.8), rgba(10,10,13,.25) 52%, transparent 78%);
  }
}

/* ===================== EDIT-V42 =====================
   V11 English hero: the black ::after wash now matches Persian and Arabic.

   THE CHANGE IS ONE LINE, in place at 4206, inside EDIT-V19's min-width:901px
   block. .hero-anchor-r.v2x-hero::after went from
     to left, rgba(8,6,4,.96) 0% -> .88 at 56% -> transparent at 84%
   to exactly the values the RTL base rule at 2719 already uses
     to left, rgba(8,6,4,.94) 0% -> .6  at 40% -> transparent at 68%

   WHY ONE LINE IS THE WHOLE FIX. Three rules paint this pseudo-element:
     2716  .v2x-hero::after                  to right ...   0,2,0
     2719  html[dir="rtl"] .v2x-hero::after  to left  ...   0,2,1
     4206  .hero-anchor-r.v2x-hero::after    to left  ...   0,2,0   (gated 901+)
   All three v11 pages carry .hero-anchor-r, but in fa/ar the 0,2,1 RTL rule
   outranks it, so 4206 was only ever reaching the English page. That was the
   entire asymmetry: same direction in all three languages, but English got
   alpha .88 out to 84% of the frame where fa/ar get .6 out to 68%.

   WHY NOT SIMPLY DELETE 4205-4208. English would then fall through to 2716,
   which is "to right": it darkens the LEFT while this page's copy sits on the
   RIGHT. The rule still has to exist to flip the direction -- only its stops
   change. Duplicating the RTL values here is deliberate; it keeps ONE rule per
   direction instead of stacking a fourth override onto the same pseudo-element.

   THE GATE IS UNCHANGED, ON PURPOSE. 4206 stays inside @media(min-width:901px).
   Line 2792, inside @media(max-width:900px), replaces the horizontal wash with
   a vertical "to top" one for both directions at 0,2,0 and 0,2,1; an ungated
   override here would have outranked it and broken the mobile hero. Verified at
   375px: computed ::after background is 2792's vertical gradient on all three
   pages, before and after.

   LEGIBILITY, MEASURED AT 1440px. Photo luminance sampled from the bg as
   painted (object-fit cover, hero-zoom's 1.12 transform included), blended
   analytically under both gradient layers, WCAG ratio taken on true glyph rects
   grouped into lines per text node. English before -> after, beside what fa/ar
   already ship:
     h1              14.96 -> 7.85     (fa 8.92, ar 8.90)
     .btn--line      15.50 -> 10.81    (fa 8.15, ar 8.89)
     worst chip       3.07 -> 1.92     (fa 2.04, ar 2.11)
   English lands on the same rung as fa/ar. The one place it sits marginally
   lower is the worst chip, 1.92 against 2.04: its chip row starts 39px further
   into the bright side (x=895 vs fa 934, ar 956) because the English copy is
   wider, so that 0.12 comes from copy width, not from the gradient. The chips
   are the floor in every language and always were -- their own colour is dim
   enough to cap them near 3.1 even under the strong gradient, so that floor is
   a property of the chip colour, not of this change. The 2.35:1 figure quoted
   in EDIT-V19 is stale: it predates .copy-flush-r/.hdr-align moving the copy
   onto the header column.

   NOTHING ELSE CAN SEE THIS. Only v11.html, v11-fa.html and v11-ar.html carry
   .hero-anchor-r.
   ========================================================= */

/* ===================== EDIT-V43 =====================
   V11 Persian + Arabic camera title: the box grows to fit the phrase.

   THE DEFECT. section#camera on v11-fa.html and v11-ar.html:
     .v2x__copy.m3t.oneline.copy-anchor-r > h2.v2x__title > .mask
       > .mask__in.gradient-text.em
   Three rules collide. Line 4294 (EDIT-V20) caps every child of these blocks at
   max-width:640px. Line 3461 pins white-space:nowrap on .oneline .mask__in.
   Line 497 gives .mask overflow:hidden. So a phrase wider than 640px is not
   wrapped, it is CUT -- and because RTL text is right-aligned (3289) the cut
   falls on the LEFT, which is the END of the phrase, so it reads as a missing
   word rather than a missing indent. Measured one-line ink at the pinned 64px
   font (the clamp at 2759 tops out for viewports >= 1230.8px, so the ink is
   constant above that):
     ar  849.1px in a 640px box -> 209.1px cut, the last word gone entirely
     fa  760.0px in a 640px box -> 120.0px cut
   .mask scrollWidth-clientWidth measured 209 / 120 before, 0 after.

   min-width, NOT max-width. The used width is clamped by max-width FIRST and
   min-width SECOND, so a max-content FLOOR leaves 4294's 640px cap in force
   wherever the content fits inside it and only pushes out the boxes that do not.
   That is what makes this surgical, and it is measured, not argued:
                          camera h2         performance h2
     1440  before/after   640 -> 849.1      640 -> 640      (ar)
     1440  before/after   640 -> 760.0      640 -> 640      (fa)
     1024  before/after   640 -> 706.4      640 -> 640      (ar)
     1024  before/after   640 -> 640        640 -> 640      (fa, ink 632.3 fits)
      901  before/after   640 -> 640        640 -> 640      (both, ink < 640)
   The performance block is byte-identical at every width in both languages, and
   the camera block only moves where it was actually clipped.

   WHY THAT MATTERS, AND WHY max-width WAS REJECTED. Every second .mask__in on
   these pages is .gradient-text.em (116/710): a 115deg gold ramp painted through
   background-clip:text, so the ramp spans the BOX -- the trap EDIT-V16 records
   at 4053-4062. max-width:max-content unclips the camera title just as well, but
   it also SHRINKS the untouched performance title from 640px to 358.3 (fa) /
   387.3 (ar), remapping the gradient on a heading nobody complained about.
   max-width:none is worse still: the box becomes the full column and the glyphs
   sample only the tail of the ramp. With min-width the camera box lands exactly
   on the phrase, so its ramp maps 0->100% across the glyphs -- the rendering
   EDIT-V16 argues for -- and the performance ramp is untouched.

   NO GLYPH MOVES. 4295/4296 keep margin-left:auto / margin-right:0 and the auto
   margin still resolves, so the box's right edge stays on the header column and
   grows LEFTWARD into space that was already empty. Measured identical before
   and after at 1600/1440/1280/1200/1024/901: mask right edge (1477.5 / 1353.6 /
   1203.2 / 1128 / 962.6 / 847), eyebrow right, paragraph right, h2 height and
   block height. document.scrollWidth unchanged; no horizontal scrollbar appears.

   THE LETTER-SPACING QUESTION, MEASURED AND DISMISSED. Both 2759 and
   html[dir="rtl"] .em (716) set letter-spacing:-.02em (-1.28px at 64px), which
   raises the worry that the advance box ends inside the final glyph's ink -- and
   in RTL the final glyph is the leftmost, i.e. exactly the clipped edge, with
   .mask's overflow:hidden landing flush on it. A padding-inline-end plus
   negative-margin pair on .mask was considered for that. It is not needed:
   canvas TextMetrics at each element's exact computed font, weight and
   letter-spacing gives (actualBoundingBoxLeft + actualBoundingBoxRight) MINUS
   advance width, for all eight mask lines across the two pages, as -1.63 /
   -1.72 / -1.91 / -2.25 / -2.63 / -3.44 / -4.16 / -5.97 px. The ink sits INSIDE
   the advance box everywhere, by 1.6 to 6.0px, so there is nothing outside the
   box to reveal and no overhang to clip. Left out deliberately, not overlooked.

   LEGIBILITY AT THE NEWLY REVEALED EXTENT, ALSO MEASURED. The phrase's left edge
   moves from x=698.6 to 593.6 (fa) / 504.5 (ar) at 1440, into a thinner part of
   .v2x__scrim--right.scrim-strong (4228: "to left", .95 -> .85 at 55% ->
   transparent at 88%), so scrim alpha at that edge falls from .857 to .737 (fa)
   and .576 (ar). Worst-glyph WCAG, sampling the photo as painted, blending the
   scrim analytically and taking the gold ramp's own colour at each sample point
   (the text is transparent with a gradient behind it, so a flat text colour
   would be the wrong input): fa 5.14, ar 4.58. Both clear AA for large text
   (3.0) and even the normal-text threshold (4.5), so the scrim needs no change.

   GATED 901px+, AND THE GATE IS LOAD-BEARING. Below 901px rule 4294 does not
   apply, the h2 is uncapped, and clamp(2rem,5.2vw,4rem) FLOORS at 2rem = 32px --
   so an ungated floor would force the Arabic h2 to 424.6px inside a 330px
   content box. Inside the gate that cannot happen. Verified at 375/560/768/900
   in both languages: computed min-width reads "auto", and box widths and line
   counts are identical before and after.

   NO CASCADE CONTEST AT ALL. min-width is declared exactly once elsewhere in
   these 5510 lines (2169, .rv-cname), and there is no max-width with !important
   anywhere in the sheet, so this rule wins on weight and not on source order.
   Specificity is 0,6,0 against 4292's 0,4,0 in any case. .v2x__title carries no
   width or max-width of its own -- 2759 is font metrics only.

   ENGLISH CANNOT SEE IT. v11.html's camera copy is .v2x__copy.m3.copy-anchor-r:
   zero occurrences of m3t and zero of oneline in that file, so neither 4292 nor
   this rule matches it. Across the 55 pages .m3t and .copy-anchor-r co-occur on
   exactly two -- v11-fa.html and v11-ar.html. .oneline is in the key because it
   is what creates the hazard (it pins the nowrap at 3461): drop .oneline from
   the markup to let a title wrap, and this floor correctly stops applying.

   SEPARATE OPEN BUG, DELIBERATELY NOT FIXED HERE. That same 32px clamp floor
   means this title is ALSO clipped on phones, and the .oneline paragraphs run
   clean off the left edge of the viewport. Measured at 375px:
     v11-fa    title cut 65.0px    paragraphs 447.5px and 725.9px off-screen
     v11-ar    title cut 109.6px   paragraphs 492.1px and 661.4px off-screen
     v1-core-fa / v1-core-ar / v2-lite-fa   paragraph 403.9 / 337.7 / 593.2 off
   Title breakeven is ~482px (ar) / ~432px (fa), so every common handset width is
   affected in both languages, and the performance paragraph overflows at every
   width below ~1130px. v2-fa and v2-ar are clean because 3856 and 3930 already
   release the nowrap for their .cam-mid / .bat-mid blocks -- the precedent for
   fixing the rest. That is a <=900px change, out of scope for this edit; it needs
   its own, on the user's word. The earlier site-wide .mask scan that found only
   these two clipped headings was run at 1440px only, which is why it missed the
   phone band.
   ========================================================= */
@media (min-width: 901px) {
  .v2x--right .v2x__copy.m3t.oneline.copy-anchor-r > .v2x__title { min-width: max-content; }
}

/* ===================== EDIT-V44 =====================
   V1 Persian + Arabic hero: put the shadow on the same side as English.

   THE DEFECT. section#overview on v1-fa.html and v1-ar.html is a bare
   .v2x-hero, so its ::after comes from line 2719, html[dir="rtl"]
   .v2x-hero::after, which paints "to left" -- i.e. it darkens the RIGHT.
   But the copy on these two pages carries .m2l, which anchors it LEFT, and the
   sheet's own line 3280 states that intent: "RTL heroes without the modifier
   keep the copy on the LEFT, text reads RTL". So the scrim was darkening the
   half the text is NOT in. Measured at 1440px, title ink and the darkened side:
     v1     (en)   ink  86..564  scrim darkens LEFT   -> agree
     v1-fa  (fa)   ink 416..741  scrim darkens RIGHT  -> disagree
     v1-ar  (ar)   ink 460..741  scrim darkens RIGHT  -> disagree
   The visible symptom is not the text, it is the PHOTO: assets/v1-hero.webp is a
   hand holding the phone on the right, and the misplaced scrim was lying over
   the phone screen, dulling it from vivid magenta to flat maroon, while the
   empty left third stayed comparatively open. English has the reverse and
   correct arrangement. This rule gives fa/ar the English gradient.

   THIS IS A LOOK FIX, NOT A LEGIBILITY FIX -- stated plainly because the
   measurement says so. Worst-glyph WCAG over the whole hero copy, photo
   rasterised as painted and both gradient layers blended, with the 120deg
   var(--grad) ramp evaluated per sample for the .gradient-text line:
     to left (before)   fa 4.36   ar 4.36     (white lines all ~17.1-17.5)
     to right (after)   fa 4.32   ar 4.32     (white lines all ~17.0-17.4)
   Essentially unchanged, because the photo is already near-black under the copy
   in both directions. Nothing here was done for contrast.

   SCOPED WITH A CLASS, DELIBERATELY, NOT WITH :has(). Four RTL pages carry a
   bare .v2x-hero #overview: v1-fa, v1-ar, v2-pro-fa and v2-pro-ar. The v2-pro
   pair anchors its copy with .m2r -- title ink 951..1354, on the RIGHT -- so for
   them the inherited "to left" is already correct and must not move. Keying on
   the child instead, html[dir="rtl"] .v2x-hero:has(> .v2x-hero__copy.m2l),
   would have been elegant and would also have swept in v01-fa/v01-ar, which
   carry .m2l and have the same defect but were not in scope for this change.
   A class on the section says exactly which two pages are being changed.
   Added to the markup as: <section class="v2x-hero hero-scrim-l" id="overview">

   NO LTR HALF, ON PURPOSE. .hero-scrim-l means "the scrim darkens the left",
   which is what line 2716 already does for every LTR hero, so on an LTR page the
   class is a correct no-op rather than a missing case. That is why this differs
   from the both-directions treatment at 4310/4311, where the physical flex value
   genuinely needed spelling out twice.

   GATED 901px+, AND THE GATE IS LOAD-BEARING. Line 2792, inside
   @media (max-width:900px), replaces both horizontal washes with a vertical
   "to top" one at specificities 0,1,1 and 0,2,2. This rule is 0,3,2, so ungated
   it would outrank 2792 and put a left-darkening horizontal gradient on the
   phone hero. Inside the gate the mobile band gains no declaration and stays
   byte-identical.

   SPECIFICITY. html[dir="rtl"] .hero-scrim-l.v2x-hero::after is 0,3,2 against
   line 2719's html[dir="rtl"] .v2x-hero::after at 0,2,2 and line 2716's
   .v2x-hero::after at 0,1,1. Neither carries !important, so this wins on weight,
   not on source order.

   SIX MORE PAGES HAVE THIS SAME DEFECT AND ARE LEFT ALONE HERE, measured at
   1440px (scrim side vs title-ink midpoint, viewport centre 720):
     v01-fa   ink mid 497   scrim darkens RIGHT
     v01-ar   ink mid 382   scrim darkens RIGHT
     v2-fa    ink mid 1192  scrim darkens LEFT
     v2-ar    ink mid 1183  scrim darkens LEFT
     v2-lite-fa ink mid 1171 scrim darkens LEFT
     v2-lite-ar ink mid 1171 scrim darkens LEFT
   The v01 pair is the same shape as V1 (bare-ish hero, .m2l copy). The v2 and
   v2-lite quartet comes from a different rule: line 3275,
   html[dir="rtl"] .hero-side-right.v2x-hero::after, paints "to right" while
   .hero-side-right's own copy rule (3269, margin-left:auto) puts the copy on the
   RIGHT in both directions -- so that RTL override is backwards too. Fixing it
   is a one-line change at 3275 rather than a new class, but it touches four
   pages at once and was not requested, so it is recorded here rather than done.
   ========================================================= */
@media (min-width: 901px) {
  html[dir="rtl"] .hero-scrim-l.v2x-hero::after {
    background: linear-gradient(to right, rgba(8,6,4,.94) 0%, rgba(8,6,4,.6) 40%, transparent 68%),
                linear-gradient(to top, var(--bg) 4%, transparent 36%);
  }
}

/* ===================== EDIT-V45 =====================
   V1 Persian + Arabic hero copy: the block moves onto the logo column while the
   text stays right-aligned. .copy-hug, added to the copy div on v1-fa.html and
   v1-ar.html next to the .m2l .hdr-align it already carried.

   THE DEFECT WAS BOX-vs-INK, NOT THE BOX. .m2l's child rule (3497-3499) already
   put the boxes exactly where they belong: measured at 1440px the children run
   101..741 and .nav__inner runs 101..1354, so the box's left edge was ALREADY on
   the logo column. What was wrong is that those boxes are 640px wide while the
   phrases are 117-325px, and line 3495's text-align:right !important pins the
   glyphs to the box's RIGHT edge. So the ink sat at 416..741 / 460..741 with
   315-498px of empty box to its left, and the block read as floating in the
   middle of the frame instead of hanging off the logo.
   (The +15px offset against English's 86 is not a bug: under RTL the scrollbar
   is on the LEFT, so the whole viewport content area starts at 15 and the logo
   with it. 101 in fa/ar is the same visual gutter as 86 in en.)

   width: fit-content IS THE WHOLE FIX. It shrinks each child to its own widest
   line, and .m2l's margin-left:0 / margin-right:auto then parks that narrow box
   on the left column -- so the widest line's left edge IS the logo line. This is
   the sheet's own idiom, recorded at 3668 and used at 4063 (EDIT-V16) and 3530.
   Measured at 1440px, leftmost ink per block, logo column at 101.4:
     fa   h1 416.0 -> 101.4    cta 468.5 -> 132.4    chips 279.0 -> 102.7
     ar   h1 459.9 -> 101.4    cta 499.3 -> 132.4    chips 264.3 -> 102.7
   The 31px on the CTA is the button's own padding-inline, not a miss: English
   measures the identical 31px offset (lines at 86, button ink at 117).

   WHY NOT text-align: left, WHICH WOULD PUT *EVERY* LINE ON 101. That was built
   and shown side by side; it is the exact mirror of English, every line flush
   left and the right edge ragged. The user chose to keep the text right-aligned
   and move only the block, so the left edge stays ragged by design: the widest
   line of each block touches the logo and the shorter ones hang inside it
   (fa h1: 101..427 widest, 284..427 and 309..427 above and below it). Recorded
   because the ragged left edge is a decision, not an oversight.

   ONE CONSEQUENCE, DISCLOSED. The second .mask__in on this title is
   .gradient-text (116), whose ramp spans its BOX -- the EDIT-V16 trap at
   4053-4062. Narrowing the h1 from 640px to fa 326 / ar 383 remaps that ramp
   across "hr br" / the Arabic equivalent: the glyphs used to sample var(--grad)
   from ~82% to 100% and now sample from ~64% to 100%, so that one line reads a
   little lighter and more varied. Not requested, but unavoidable once the box
   narrows, and it moves toward what EDIT-V16 argues is the correct rendering.
   Left as-is rather than pinned, because pinning it would mean a second rule on
   .mask__in and the change is a shade, not a defect.

   GATED 901px+, AND THE GATE IS LOAD-BEARING. Below 901px .m2l's 640px cap is
   already wider than the viewport, so the children are viewport-width blocks and
   fit-content would shrink them to their text and then flush them LEFT, wrecking
   the phone layout. The user explicitly deferred mobile ("I will decide about
   mobile later"), so the <=900px band gains no declaration and stays
   byte-identical -- verified at 375/560/768/900 in both languages: computed
   width on all three children reads the full content-box px value, not
   fit-content, and every box edge is unchanged.

   SPECIFICITY. .v2x-hero .v2x-hero__copy.m2l.copy-hug > * is 0,4,0. It needs to
   beat nothing: no rule in the sheet sets `width` on these children -- 2721 sets
   width:100% on the COPY itself, and 3497-3499 set only max-width and margins on
   the children. No !important used or needed, and .m2l's two margin !importants
   are left in force on purpose, because they are what does the left-flushing.

   SCOPE. .copy-hug appears on exactly two elements in the 55 pages: the hero
   copy of v1-fa.html and v1-ar.html (line 75). English v1.html is untouched --
   it carries no .m2l and no .copy-hug, and its children stay full-width with
   text-align:start, which is what already put every English line on 86.
   Nothing else on either page changes: only the hero copy div carries the class,
   and the rule is keyed to .v2x-hero so no section block can match it.
   ========================================================= */
@media (min-width: 901px) {
  .v2x-hero .v2x-hero__copy.m2l.copy-hug > * { width: fit-content; }
}

/* ===================== EDIT-V46 =====================
   V1, two consecutive sections, all three languages. Both requests were about
   vertical placement inside the frame; neither changed a single horizontal
   position that was not asked for.

   PART 1 - the CRYSTAL DISPLAY section (line 111-120 of v1 / -fa / -ar):
   centre the copy and drop the closing paragraph plus its chips to the floor.
   NO NEW CSS. .perf-c (EDIT-V17, 4072-4123) already does exactly this, and the
   markup was the whole change:
     v1.html      .v2x__copy          -> .v2x__copy perf-c
     v1-fa.html   .v2x__copy m3       -> .v2x__copy m3 perf-c
     v1-ar.html   .v2x__copy m3       -> .v2x__copy m3 perf-c
   Measured at 1440px, y offsets inside the section, all three languages within
   1px of each other afterwards:
     eyebrow  287 -> 149..184        paragraph 516..567 -> 733..785
     chips    589..625 -> 806..843   gap to the floor 275 -> 57
   text-align becomes center in all three (it was left / right / right).

   WHY ENGLISH GETS .perf-c WITHOUT .m3, THOUGH fa/ar CARRY BOTH. .m3 was the
   obvious way to centre the English copy too, and it was tried. It is UNGATED
   (3353), so it also rewrote English on phones: measured at 900px the box went
   0..885 -> 83..803 and text-align left -> center, and at 375/560/768 the
   alignment flipped as well. Mobile was explicitly out of scope, so .m3 came
   back off. It costs nothing: the copy is margin:0 auto (2751) and everything
   inside it is centred by .perf-c, so the box width is irrelevant to where the
   glyphs land. Verified at 1600/1440/1200: titleWhite, titleGold, paragraph and
   chips ink are pixel-identical with .perf-c alone and with .m3 .perf-c, while
   at 900/768/560/375 .perf-c alone is byte-identical to the old layout. The only
   difference is the .gradient-text box (1167px vs 515px at 1440), which decides
   how much of var(--grad) maps onto the glyphs -- and the wide box measures
   slightly BETTER (gold min 9.82 vs 5.99), so nothing was traded away.

   A PRE-EXISTING DEFECT THIS FIXES AS A SIDE EFFECT, measured. The gold title
   line sat over the bright red phone screen. Share of its glyph area below
   3:1 WCAG, sampling the photo as painted and blending .v2x__scrim--left
   analytically: fa 39.0% -> 0%, ar 54.4% -> 4.8% (ar median 2.84 -> 10.42), and
   the white title line 4.9%/4.3% -> 0% in both. English pays for it in the
   paragraph, 0% -> 17% below 3:1, which lands it exactly where fa and ar
   already were (11.6% and 12.8% before this change, 11.8% and 11.9% after).
   Flagged rather than fixed: evening that out means a scrim change, which is
   its own edit.

   PART 2 - the CAMERA section (line 123-132), .copy-bot: move the whole block
   to the floor of the frame and change NOTHING else. The request was explicit
   that the text keeps its current alignment -- left in English, right in fa/ar.

   ONE DECLARATION. section.v2x[class*="v2x--"] is display:flex; align-items:
   center (3253), so the copy is a vertically centred flex item; align-self
   overrides that for this item alone. No flex-direction, no margin-top:auto and
   no padding override are needed, because nothing inside the block moves
   relative to anything else -- unlike .perf-c, which had to split the block in
   two. padding-bottom replaces 3254's padding-block:clamp(60px,9vh,120px) on
   the bottom edge only, because align-self:flex-end alone left the chips 63px
   up, a second pass asked for lower still, and a third asked for ~15px back.
   The value carries that history literally: 4.5vh is half of 3254's 9vh (the
   "lower" step) and the +15px is the correction, so it reads as one intention
   rather than a tuned constant. 55.5px at a 900px-tall viewport, landing the
   chips ~38px off the floor. That is deliberate, not tight: the section's
   own ::after band (2865-2870) is 42vh tall and its bottom 14% -- everything
   below y=847 here -- is opaque var(--bg) painted OVER the photo (band z-index
   -1, photo -2), so the chip row lands on flat background rather than on the
   camera image, and the paragraph above it keeps 33px of clearance from the
   chips. Overriding padding-bottom is the reason this selector is 0,4,1 rather
   than 0,3,0: 3254 owns padding-block at 0,3,1 and would otherwise win.
   Measured at 1440px, before -> after:
     en     block 187..713 -> 400..900   chips bottom 647 -> 861   ink left 86 (unchanged)
     fa     block 200..700 -> 425..900   chips bottom 635 -> 861   ink left 1156 (unchanged)
     ar     block 200..700 -> 425..900   chips bottom 634 -> 860   ink left 1208 (unchanged)
   computed text-align unchanged in all three, gap to the floor 253..266 -> 38.
   The clamp bounds are the same +15px shift, so the whole curve moves together:
   measured padding 46.5 / 51 / 55.5 / 60px at viewport heights 700 / 800 / 900 /
   1000, and the block never reaches the section ceiling at any of them.

   SPECIFICITY 0,4,1, mirroring line 3254 plus the class -- the same trick
   .perf-c (4087) and .day-mid (5225) use, and for the same reason: 3254 owns
   padding-block at 0,3,1, so a plainer .v2x--right .v2x__copy.copy-bot at 0,3,0
   would lose if this rule ever needed to touch padding. Nothing else in the
   sheet sets align-self on a .v2x__copy except .m3t (3466, flex-start), which
   none of these three blocks carries.

   GATED 901px+. Mobile keeps align-self:auto, so the block stays vertically
   centred there exactly as before: verified at 900 and 375 in all three
   languages that computed align-self reads "auto", text-align is unchanged and
   the block's box is identical to the pixel.

   LEGIBILITY IMPROVES, MEASURED, AND NOTHING REGRESSES. Same method as Part 1.
   Minimum WCAG over each run, before -> after:
     en  gold title 2.18 -> 9.33   (share below 3:1  0.1% -> 0%)
     fa  paragraph  1.43 -> 10.30  (0.2% -> 0%)      white title 3.20 -> 14.10
     ar  paragraph  1.44 -> 10.30  (0.3% -> 0%)      white title 13.62 -> 14.10
   Medians are unchanged, so this is the tails improving, not the whole block
   moving onto a darker patch by luck.

   SCOPE. .copy-bot appears on exactly three elements in the 55 pages: the
   camera copy of v1.html, v1-fa.html and v1-ar.html. .perf-c now appears on
   nine: the three V1 display blocks added here plus the six it already had on
   v2-pro and v0-core. No other page is touched by either part.
   ========================================================= */
@media (min-width: 901px) {
  section.v2x[class*="v2x--"] .v2x__copy.copy-bot {
    align-self: flex-end;
    padding-bottom: clamp(43px, calc(4.5vh + 15px), 71px);
  }
}

/* ===================== EDIT-V47 =====================
   V1 fast-charge section (line 135-144 of v1 / -fa / -ar), the "5000mAh" block.
   Two separate requests, two separate classes, because they have different
   safe ranges.

   PART 1 - .flush-l : in fa/ar every line starts on the logo column.
   English was already right and is untouched: .copy-anchor-l (4370) sets
   text-align:left for LTR, so all four of its children put ink on 86 at 1440px
   (the eyebrow reads 107 because of its own pill padding).
   In fa/ar, EDIT-V23's line 4433 sets text-align:right inside those same
   left-flushed 640px boxes, so only the eyebrow -- which 4379 gives
   width:fit-content -- actually reached the column. Measured ink left at 1440px,
   logo column 86:
     fa   .v2x__big 275   eyebrow 103   h2 353/434 (2 lines)   p 107
     ar   .v2x__big 273   eyebrow 103   h2 201                  p 162

   WHY NOT .copy-hug's width:fit-content, WHICH SOLVED THE HERO LAST ROUND.
   It was built and measured here first. It gets .v2x__big and the paragraph onto
   86 in both languages, but it CANNOT move the Persian h2: that title's ink is
   ~665px against the 640px cap from 4373, so it wraps, and for a wrapping box
   fit-content resolves to min(max-content, max(min-content, available)) = 640px
   -- the box does not shrink and the two right-aligned lines stay at 353 and
   434. Measured:
     fit-content   fa  big 86  eyebrow 103  h2 353  p 86   <- h2 still adrift
     fit-content   ar  big 86  eyebrow 103  h2  86  p 86
   That also breaks the fa/ar parity rule this site is built on: the same class
   would land Arabic on the column and leave Persian short, purely because the
   Arabic string happens to fit on one line. text-align:left puts every line of
   every child on 86 in both languages, which is what "all the content" asked
   for, so that is what ships. Recorded because the hero (EDIT-V45) deliberately
   kept its RTL text right-aligned -- the difference is not inconsistency, it is
   that here a wrapping title makes the box trick impossible.
   Specificity 0,5,1 against 4433's 0,4,1. No !important needed.

   PART 2 - .lift-sm : the block sits a little higher. position:relative + top,
   the same idiom as .lift-max (3680), which is -142px for a different block;
   this is the small sibling at -40px and cannot reuse it because .lift-max is
   keyed to .m2l, which this block does not carry. Specificity 0,4,0; nothing
   else in the sheet sets position or top on a .v2x__copy--mid.

   THE HEIGHT GATE IS THE INTERESTING PART, and it is not decoration.
   section.v2x[class*="v2x--"] is display:flex; align-items:center (3253) and
   tracks the viewport height, so the taller the copy the closer its top already
   is to the sticky nav -- and the nav's bottom edge is at y=101 (36px
   announcement bar + 65px bar). Persian is the constraint because its wrapped
   two-line title makes the block 66px taller than English. Measured clearance
   between the block's top and the nav's bottom, fa first:
     viewport 1000   no lift 124 / with -40px  84      en 157 / 117
     viewport  900   no lift  83 / with -40px  43      en 116 /  76
     viewport  800   no lift  42 / with -40px   2      en  75 /  35
     viewport  700   no lift   1 / with -40px -39      en  34 /  -6
     viewport  640   no lift -26 / with -40px -66      en   7 / -33
   So an ungated -40px would push Persian 39px under the nav on a 700px-tall
   viewport and English 6px under it. min-height:900px is the shortest viewport
   where the lift still leaves Persian a 43px gap, so that is the gate. Below it
   the block keeps its centred position exactly as before -- the request was for
   a small lift, not for content under the navigation.

   SEPARATE PRE-EXISTING BUG, MEASURED AND NOT TOUCHED HERE. Those same numbers
   say the Persian block ALREADY grazes the nav at a 700px-tall viewport (1px)
   and already runs 26px under it at 640px, with no lift at all -- and English
   is down to 7px at 640. That is the copy simply being taller than the frame
   can centre, and it needs its own edit (a max-height-gated shrink, or letting
   this section grow past 100vh). It is out of scope for a lift request, and the
   gate here means this change does not make it worse at any height.

   MOBILE. Both parts are gated at min-width:901px, so the <=900px band gains no
   declaration: verified at 900/768/375 in all three languages that computed
   text-align and position are unchanged and every box edge is identical.
   ========================================================= */
@media (min-width: 901px) {
  html[dir="rtl"] .v2x--center .v2x__copy--mid.copy-anchor-l.flush-l { text-align: left; }
}
@media (min-width: 901px) and (min-height: 900px) {
  .v2x--center .v2x__copy--mid.copy-anchor-l.lift-sm { position: relative; top: -40px; }
}

/* ===================== EDIT-V48 =====================
   V1 fast-charge closing sentence: two lines instead of one, so the text column
   narrows. .col-340 on the same .v2x__copy--mid.copy-anchor-l as EDIT-V47, all
   three languages. It caps ONLY the paragraph; the other three children keep
   4373's 640px.

   THE NUMBER COMES FROM A MEASURED WINDOW, NOT A GUESS. Greedy line breaking
   makes "two lines" a range, so the max-width was swept in 5px steps and the
   line count read back from the live layout. Natural single-line ink, the width
   at which the second line appears, and the width at which a THIRD line appears:
     en   628px natural   2 lines from 620px   3 lines from 310px
     fa   619px natural   2 lines from 615px   3 lines from 310px
     ar   564px natural   2 lines from 560px   3 lines from 285px
   So the window where all three are two lines is 315..560px. Inside it the split
   was measured at every candidate:
                 en            fa            ar
     400px    382/241      396/219       400/160
     380px    312/312      356/258       357/203
     360px    312/312      356/258       357/203
     340px    312/312      336/279       315/245
   340px is the most even in every language simultaneously -- perfectly balanced
   in English and the smallest spread of the four in fa (57px) and ar (70px) --
   and it is the narrowest of the candidates, which is what was asked for.
   320px would also give two lines, but the third line starts at 310px in both
   en and fa: 10px of headroom is one translation edit or one font-metric
   difference from silently becoming three lines. 340px leaves 30px.
   ONE value for all three languages, so fa and ar are identical by construction
   rather than by coincidence.

   WHAT THE COLUMN ACTUALLY BECOMES, stated plainly because it is not uniform.
   The paragraph was the widest element in all three, so narrowing it does narrow
   the block -- but the title takes over as the limit, and the titles differ:
     widest ink per child at 1440px, before -> after
     en   eyebrow 143   .v2x__big 426   h2 569   p 628 -> 312    column 628 -> 569
     fa   eyebrow  61   .v2x__big 330   h2 373   p 619 -> 336    column 619 -> 373
     ar   eyebrow  67   .v2x__big 332   h2 525   p 564 -> 315    column 564 -> 525
   Persian narrows the most (246px) because its title wraps to two short lines;
   English and Arabic narrow by 59px and 39px because their single-line titles
   are already the widest thing in the block. Capping the title too would fix
   that, but the request was about the closing sentence, so the title is left
   alone and the numbers are recorded here instead.

   SPECIFICITY 0,4,1 against 4372's .v2x--center .v2x__copy--mid.copy-anchor-l p
   at 0,3,1. The two margin !importants on that rule are untouched on purpose --
   they are what flushes the paragraph left, and EDIT-V47's text-align:left is
   what puts its first character on the logo column.

   GATED 901px+ AND 800px-TALL+. Below 901px the paragraph keeps whatever the
   mobile band gives it (computed max-width reads 440px at 900/768/375 in all
   three languages, unchanged). The HEIGHT half of the gate is the interesting
   one and it exists because of the knock-on below.

   THE KNOCK-ON, AND WHY min-height:800px. A second line makes the block ~26px
   taller, and the section centres it (3253), so its top rises ~13px -- straight
   into the nav clearance EDIT-V47 was gated to protect. Measured, one-line
   versus two-line, clearance between the block top and the nav bottom (y=101),
   Persian first because its wrapped title makes it the tallest:
     viewport 900   fa 43 -> 30    en 76 -> 64
     viewport 850   fa 62 -> 49    en 96 -> 83
     viewport 800   fa 42 -> 29    en 75 -> 63
     viewport 750   fa 21 ->  8    en 55 -> 42
     viewport 700   fa  1 -> -12   en 34 -> 22
     viewport 640   fa -26 -> -39  en  7 ->  -5
   So ungated, the second line would push Persian 12px under the nav at 700px
   tall and English 5px under it at 640px -- turning the pre-existing overflow
   EDIT-V47 recorded into a worse one, and giving English a new one. min-height
   800px is the shortest viewport where the two-line paragraph still leaves
   Persian 29px of clearance, so that is the gate. Below it the paragraph goes
   back to one line and every clearance is exactly what it was before this edit:
   this change makes nothing worse at any height. The pre-existing overflow below
   ~700px is untouched and still needs its own fix.
   ========================================================= */
@media (min-width: 901px) and (min-height: 800px) {
  .v2x--center .v2x__copy--mid.copy-anchor-l.col-340 > p { max-width: 340px; }
}

/* ===================== EDIT-V49 =====================
   .flush-l generalised from the one block EDIT-V47 gave it to any RTL copy whose
   box is anchored LEFT by .m2l. Chosen by the user out of two measured options
   after a site-wide alignment audit of the 27 phone-model pages.

   WHAT THE AUDIT FOUND, AND THE DISTINCTION THAT MATTERS. Two different faults
   were being conflated. For every sided copy block on those pages, measured at
   1440px against .nav__inner's left edge (86.4 in LTR, 101.4 in RTL -- the RTL
   scrollbar sits on the left and shifts the whole content area with it):
     (a) the item's BOX is off the column      -> a structural fault
     (b) the box is on the column but no LINE of text reaches it -> an alignment
         fault of a different kind, fixable only by changing how the text sets
   A third case, box on the column and the widest line on it with shorter lines
   falling short, is ordinary ragged setting and is NOT a fault.
   The audit's first pass also under-reported (a) on titles: .gradient-text does
   carry a real `background`, so a "has a filled box" test wrongly measured its
   full-width box instead of its glyphs. The test now excludes anything with
   background-clip:text or a transparent color, and measures ink for those.

   THE V0 CORE fa/ar CASE, MEASURED. The block is .v2x__copy.m2l in the
   .v2x--right section. Its box was 42.5px inside the column -- the documented
   header drift, because it lacks .hdr-align -- and its text never reached the
   column either, because line 3495 pins text-align:right !important inside
   children that line 3499 caps at 640px. Distance from the column, before:
     eyebrow 42.5   title 310.3 / 522.0   paragraph 51.0 / 142.6   chips 335.9
   Adding .hdr-align alone fixes only the box:
     eyebrow 0      title 267.8 / 479.5   paragraph 8.5 / 100.1    chips 293.4
   Two completions were built and measured side by side:
     B  width:fit-content on the children, text stays right-aligned
        eyebrow 0   title 211.7 / 0   paragraph 8.5 / 100.1   chips 0
        -- only each block's widest line lands; the paragraph cannot land at all
        because it wraps at 640px, so fit-content resolves back to 640px and its
        widest line sits 8.5px inside the box.
     C  text-align:left, plus width:fit-content on the chip row only
        eyebrow 0   title 0 / 0   paragraph 0 / 0   chips 0
   C ships. It is the only one that satisfies "every item aligns", and it is the
   same trade the user already accepted for the V1 fast-charge block in EDIT-V47:
   reading order and wording are untouched, only the paragraph's set edge moves
   from right to left, so the ragged edge lands on the right.

   THE CHIP ROW NEEDS ITS OWN LINE, and this is not optional. .v2x__chips is a
   flex row, so text-align does nothing to it -- with C alone it stayed 293.4px
   inside. Line 3501 gives it justify-content:flex-start !important, and under
   direction:rtl flex-START packs to the RIGHT (the trap EDIT-V22 records).
   Rather than fight that with another !important, width:fit-content shrinks the
   row to its pills and line 3499's margin-right:auto / margin-left:0 then parks
   it on the column -- the same idiom as .copy-hug (EDIT-V45).

   SPECIFICITY. html[dir="rtl"] .v2x__copy.m2l.flush-l is 0,4,1, which is what
   it takes: line 3495 holds text-align:right !important at 0,2,0 and line 3289
   holds it again at 0,3,1, so !important at 0,4,1 is the first weight that wins
   without relying on source order. The chip rule is 0,5,1 and contests nothing
   -- no rule in the sheet sets width on .v2x__chips or .v2x-hero__chips.
   Both hero and section copy are spelled out so the class behaves the same
   wherever .m2l is used.

   GATED 901px+. Mobile keeps .m2l's right-aligned, centred-stack layout exactly
   as before; verified at 900/768/375 that computed text-align on the block reads
   "right" and the chip row's computed width is unchanged.

   SCOPE. Adding .flush-l to a block is opt-in per block, so this rule changes
   nothing until a page's markup asks for it. EDIT-V47's .copy-anchor-l variant
   is left exactly as it is -- that block is not .m2l, so the two never overlap.
   ========================================================= */
@media (min-width: 901px) {
  html[dir="rtl"] .v2x__copy.m2l.flush-l,
  html[dir="rtl"] .v2x-hero__copy.m2l.flush-l { text-align: left !important; }

  html[dir="rtl"] .v2x__copy.m2l.flush-l .v2x__chips,
  html[dir="rtl"] .v2x__copy.m2l.flush-l .v2x-hero__chips,
  html[dir="rtl"] .v2x-hero__copy.m2l.flush-l .v2x__chips,
  html[dir="rtl"] .v2x-hero__copy.m2l.flush-l .v2x-hero__chips { width: fit-content; }
}

/* ===================== EDIT-V50 =====================
   V2 LITE fa/ar, the tech-leather block: release the eyebrow pin so .flush-l can
   finish the job. Last of the four box-off-the-column faults the alignment audit
   found; the other three were markup-only.

   WHY .flush-l ALONE IS NOT ENOUGH HERE. The block is
   .v2x__copy--mid.m2l.stacked.hdr-align.lift-max on line 201 of v2-lite-fa.html
   and v2-lite-ar.html. Its eyebrow is width:fit-content (3530) and line 3693
   pins it with margin-left:auto / margin-right:max(0px, calc(100% - 480px)),
   both !important at 0,5,0, which lands its RIGHT edge on content-left + 480 so
   it shares an edge with the 480px-capped title and paragraph (3681).
   text-align cannot move a fit-content box, so EDIT-V49's flush-l -- which only
   sets text-align -- leaves the eyebrow behind as the single outlier. Measured
   at 1440px, distance from the logo column:
     fa  current            eyebrow 343.6   title 196.3 / 77.9   para 0.9 / 295.6
     fa  flush-l only       eyebrow 343.6   title 0 / 0          para 0 / 0
     fa  flush-l + release  eyebrow 0       title 0 / 0          para 0 / 0
     ar  current            eyebrow 361.6   title 241.8 / 52.4   para 28.3 / 332.4
     ar  flush-l + release  eyebrow 0       title 0 / 0          para 0 / 0

   THE SHARED RIGHT EDGE THIS GIVES UP, AND WHY THAT IS FINE. 3693's comment is
   explicit that the pin exists to put the eyebrow's right edge on the same line
   as the title and paragraph, so losing it is a real change and was worth
   checking rather than assuming. Measured on the ENGLISH twin, which carries
   .side-left instead of .m2l and never gets the pin:
     en  eyebrow L0 R239.6   title L0/0 R470.7/434.1   para L0/0 R442.6/343.2
   English has no shared right edge either -- its right edges are ragged at
   239.6 / 470.7 / 442.6. So that edge only ever existed on the two RTL pages,
   and releasing it makes fa/ar structurally identical to the English reference
   the alignment rule points at, rather than breaking a three-language design.
   Shown to the user side by side before shipping.

   SPECIFICITY 0,7,1 -- html + [dir="rtl"] + six classes -- against 3693's 0,5,0.
   Both carry !important, so this wins on weight, not source order. Scoped to
   .flush-l so the pin stays intact anywhere .flush-l is not asked for: the only
   other .m2l.lift-max user is this same block, and blocks that keep the shared
   right edge keep it.

   GATED 901px+, for the reason 3693's own comment gives: below 901px the 480px
   cap at 3681 does not apply, the copy fills the column, and the max(0px, ...)
   guard collapses the pin to a plain right flush. Verified at 900/768/375 in
   both languages that computed margin-left/margin-right on the eyebrow are
   unchanged and every box edge is identical.
   ========================================================= */
@media (min-width: 901px) {
  html[dir="rtl"] .v2x--center .v2x__copy--mid.m2l.lift-max.flush-l > .eyebrow {
    margin-left: 0 !important;
    margin-right: auto !important;
  }
}

/* ===================== EDIT-V51 =====================
   V2 fa/ar, the two .stacked blocks (performance "Helio G99" on line 145 and
   tech-leather durability on line 204 of v2-fa.html and v2-ar.html): put the chip
   row back on ONE horizontal line, the way the English page has it, and let
   .flush-l land its left edge on the logo column.

   WHY THE FIRST ATTEMPT WAS THE WRONG FIX, recorded because the reasoning was
   sound and the answer still wrong. Line 3524 turns these chip rows into a
   COLUMN with align-items:flex-start, and for flex-direction:column the cross
   axis is the inline axis, so under direction:rtl flex-start packs every pill to
   the RIGHT. Measured at 1440px, distance of each pill's left box edge from the
   logo column, before anything:
     fa:145  546.4 / 556.7 / 557.1 / 548.9      fa:204  504.2 / 491.2 / 532.3
     ar:145  563.1 / 551.9 / 551.5 / 553.1      ar:204  489.3 / 489.9 / 519.9
   EDIT-V49's .flush-l alone leaves them ragged, because its width:fit-content
   shrinks the column to its widest pill and only THAT pill reaches the column:
     fa:145  0 / 10.3 / 10.7 / 2.5              fa:204  13.1 / 0 / 41.2
     ar:145  11.6 / 0.3 / 0 / 1.5               ar:204  0 / 0.6 / 30.6
   The obvious repair was cross-axis -- align-items:flex-end, which in RTL is the
   left edge -- and it does land all four pills on 0. It was built, measured and
   shown. The user rejected it: the complaint was never the pills' edge, it was
   that fa/ar stack four chips into a four-row column at all while English keeps
   them in one row. So the fix is to undo the column, not to re-align it.

   WHAT THIS RULE ACTUALLY DOES. .stacked (3524) changes exactly three properties
   off the base .v2x__chips at line 2761 (display:flex; gap:10px; flex-wrap:wrap;
   margin-top:22px). This restores those three to their base values and nothing
   else: flex-direction back to row, align-items back to normal (2761 sets none,
   so normal/stretch is the base), gap back to 10px. 3525's display:block on the
   pills is deliberately left alone -- flex items are blockified anyway, so it is
   already a no-op and touching it would be noise.

   THE LEFT EDGE NEEDS NO NEW DECLARATION, and that is worth stating because it
   looks like it should. Once the row is horizontal, EDIT-V49's width:fit-content
   shrinks the container to the row's max-content width and line 3499's
   margin-right:auto / margin-left:0 parks it on the column, so the row fills its
   own box and the leftmost pill IS the box edge. Verified: with width:auto
   instead, line 3501's justify-content:flex-start !important packs the row RIGHT
   under RTL and the leftmost pill lands 265px (fa) / 276px (ar) inside -- so the
   fit-content leg is load-bearing here, not incidental.

   MEASURED AFTER, at 1440px:
     fa:145  1 row, left edge 0, span 381, container 380.9px, pills 36px tall
     fa:204  1 row, left edge 0, span 412, container 412.3px
     ar:145  1 row, left edge 0, span 370, container 370.4px
     ar:204  1 row, left edge 0, span 441, container 441.0px
   Pill height 36px and gap 10px match the English row on the same blocks exactly.
   Block heights drop as the four rows collapse to one: fa:145 632->500,
   fa:204 526->438, ar:145 632->500, ar:204 619->531. Re-checked at 901/1024/1366
   in both languages: always one row, left edge 0, no horizontal overflow, and the
   row never wraps (span 370-441 against a 640px child cap).

   SPECIFICITY 0,6,1 -- html + [dir="rtl"] + four classes -- against 3524's 0,3,0.
   Neither carries !important, so this wins on weight, not source order.

   SCOPE. The selector needs .m2l AND .stacked AND .flush-l together. Site-wide,
   .stacked appears on six elements: these four, plus v2-lite-fa.html:202 and
   v2-lite-ar.html:202, which already carry .m2l.stacked.flush-l and so DO match
   -- but those blocks hold only an eyebrow, a title and a paragraph, with no
   .v2x__chips descendant at all, so both 3524 and this rule are inert there.
   Confirmed by reading the markup, not assumed. The English v2.html carries
   neither .m2l nor .stacked and cannot match.

   GATED 901px+. Below that the chips stay a column exactly as before -- verified
   at 900/768/600/480/375/320 in both languages that the computed flex-direction,
   align-items, gap and width are unchanged and every box rect, every pill rect
   and the document's scrollWidth/scrollHeight are byte-identical to the
   pre-change page.
   ========================================================= */
@media (min-width: 901px) {
  html[dir="rtl"] .v2x__copy.m2l.stacked.flush-l .v2x__chips {
    flex-direction: row;
    align-items: normal;
    gap: 10px;
  }
}

/* ===================== EDIT-V52 — logo-motion intro =====================
   Replaces the minimal "logo + filling bar" preloader (EDIT-V01) on the home
   pages with an automatic logo-motion intro carrying the existing 4.018s chime.

   IT IS GATED BEHIND A TAP, AND THAT IS THE ONLY WAY THE SOUND IS GUARANTEED.
   Browsers refuse to begin audio without a user gesture. A gateless version was
   built and shown first: it autoplayed the motion and tried the chime at t=0,
   falling back to arming the first pointer/key event. That works for a returning
   visitor -- Chrome permits audio autoplay once someone has interacted with the
   domain -- and reliably fails for a first-time one, so the music was a coin
   flip. The gate came back on request. The removed video intro solved the same
   problem the same way, and its i18n keys are reused rather than replaced:
   start_btn / start_hint at script.js 640 / 823 / 1006. intro_skip is the one
   genuinely new key.

   THE AUDIO IS THE ORIGINAL, NOT AN IMITATION. assets/chime-b64.js is still
   deployed and still loaded by index/index-fa/index-ar, exposing
   window.__VOCAL_CHIME as a base64 audio/mp4 data-URI, unreferenced since the
   video intro was removed. Measured in the browser: duration 4.017007s, plays to
   completion. The motion below is timed to that number.

   THE OBJECT VOCABULARY IS THE FIRST INTRO'S. No markup of it survives, but its
   CSS does, at lines 137-289, and that is the record this was built from:
     .preloader::before        rotating blurred conic halo   (haloSpin 7s)
     .preloader__start::before breathing radial gold aura    (auraBreathe 5s)
     .start-cta__ring::before  two expanding pulse rings     (ctaPulse -> 2.15)
     .ring-ico .w1/.w2         sound-wave arcs               (ringWave)
     .ring-ico .ph             glinting highlights           (phoneGlint)
     .start-cta__logo          a gold sweep across the wordmark (ctaShine)
   The halo, the aura, the expanding rings and the sweep all reappear here, driven
   off the chime instead of a video's buffer. The cube row and the Great Vibes
   word were built and then removed on request, along with the gate.

   THE WORDMARK IS WHITE, and its outline is a light-line, not a hairline. Three
   SVG layers on one box, each load-bearing:
     .vi__neon  the same five paths at stroke-width 4, blurred 4px. This is the
                soft body of the glowing line -- it is what stops the outline
                reading as a sharp vector edge.
     .vi__svg   the letter itself: a 0.9px white core stroke that draws, then a
                white fill that rises behind it, plus the bloom at 2000ms.
     .vi__tips  the same paths again with a 4px dash that travels the contour, so
                a bright point rides the pen as each letter is written.
   Blur and drop-shadow are used freely here because all three are SVG with no
   mask. The warning at line 194 still binds .vi__shine, which IS masked and
   therefore carries no filter -- mask + filter on one element renders it blank in
   Chromium.

   THE LETTER ORDER IS NOT THE FILE ORDER. Vocal-logo.svg lists its shapes as
   L, O, C, V, A. By x-range: V 0-73, O 73-159, C 169-245, A 251-327, L 339-400.
   The markup carries --i so the pen runs V-O-C-A-L left to right whatever the
   document order.

   TIMELINE, ms from the tap:
        0  chime attempted; halo and aura fade up
      120  V begins; each letter draws in 900, stagger 240; L lands at 1980
      120  the travelling tip rides each letter, one per draw
      620  fills begin, 240 behind each draw, 700 each
      900  first sound-wave ring leaves the wordmark; 4 rings, 320 apart
     1400  sparks start drifting up
     2000  the wordmark's own bloom
     2200  shine sweep, 1100, one pass
     2600  tagline
     3300  settle (scale 1 -> 1.035)
     3700  body.is-loading released so the hero entrance starts as the curtain
           lifts -- the handoff EDIT-V01 used, kept so the hero split-text fires
     4300  curtain gone
   4.3s against a 4.017s chime.

   REDUCED MOTION drops every layer to a still: the wordmark appears filled, holds
   900 and lifts.
   ========================================================================= */

.vi {
  position: fixed; inset: 0; z-index: 3000;
  display: flex; align-items: center; justify-content: center;
  background: #000; overflow: hidden;
  transition: opacity .6s var(--ease), visibility .6s;
}
.vi.is-done { opacity: 0; visibility: hidden; pointer-events: none; }
html.no-intro .vi { display: none !important; }

/* =========================================================
   Ambient layers — the first intro's halo and aura
   ========================================================= */
.vi__halo, .vi__aura { position: absolute; pointer-events: none; opacity: 0; }

.vi__halo {
  width: 900px; height: 900px; border-radius: 50%;
  background: conic-gradient(from 0deg,
    transparent 0deg, rgba(240,208,136,.16) 60deg, transparent 140deg,
    transparent 220deg, rgba(212,175,110,.12) 290deg, transparent 360deg);
  filter: blur(34px);
}
.vi.is-playing .vi__halo { animation: viHaloIn 1.2s var(--ease) forwards, haloSpin 7s linear infinite; }
@keyframes viHaloIn { to { opacity: 1; } }

.vi__aura {
  width: min(1000px, 130vw); aspect-ratio: 1;
  background: radial-gradient(closest-side, rgba(240,208,136,.15), rgba(240,208,136,.04) 45%, transparent 72%);
}
.vi.is-playing .vi__aura { animation: viAuraIn 1s var(--ease) forwards, auraBreathe 5s ease-in-out 1s infinite; }
@keyframes viAuraIn { to { opacity: 1; } }

/* =========================================================
   Sound-wave rings — the ctaPulse / ringWave motif, the chime made visible
   ========================================================= */
.vi__rings { position: absolute; inset: 0; pointer-events: none; display: grid; place-items: center; }
.vi__rings span {
  position: absolute;
  width: 320px; height: 320px; border-radius: 50%;
  border: 1.5px solid rgba(240,208,136,.5);
  box-shadow: 0 0 22px rgba(240,208,136,.28), inset 0 0 18px rgba(240,208,136,.10);
  opacity: 0; transform: scale(.55);
}
.vi.is-playing .vi__rings span {
  animation: viRing 2.4s cubic-bezier(.22,1,.36,1) calc(900ms + var(--i) * 320ms) forwards;
}
@keyframes viRing {
  0%   { opacity: 0;   transform: scale(.55); }
  12%  { opacity: .85; }
  100% { opacity: 0;   transform: scale(3.1); }
}

/* =========================================================
   Gold sparks drifting up — the glint vocabulary, as particles
   ========================================================= */
.vi__sparks { position: absolute; inset: 0; pointer-events: none; }
.vi__sparks i {
  position: absolute; left: var(--x); top: 62%;
  width: var(--s); height: var(--s); border-radius: 50%;
  background: radial-gradient(circle, #fff 0%, #f0d088 45%, rgba(240,208,136,0) 70%);
  opacity: 0;
}
.vi.is-playing .vi__sparks i { animation: viSpark var(--dur) linear calc(1400ms + var(--d)) forwards; }
@keyframes viSpark {
  0%   { opacity: 0;   transform: translateY(0) scale(.6); }
  18%  { opacity: .95; }
  70%  { opacity: .55; }
  100% { opacity: 0;   transform: translateY(-38vh) scale(1.15); }
}

/* =========================================================
   The wordmark — white, written by a light-line
   ========================================================= */
.vi__stage {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: 26px;
  opacity: 0; transition: opacity .35s var(--ease), transform .7s var(--ease);
}
.vi.is-playing .vi__stage { opacity: 1; }
.vi.is-settled .vi__stage { transform: scale(1.035); }

.vi__logo { position: relative; width: clamp(240px, 46vw, 620px); aspect-ratio: 399.75 / 73.32; }

/* EACH SVG SITS IN AN HTML WRAPPER AND THE WRAPPER CARRIES THE GLOW. This is not
   tidiness, it is the fix for the wordmark being clipped. A CSS `filter` on an
   SVG child is rendered through the SVG filter region, which defaults to a 10%
   margin around the element's bbox -- the bloom's 46px shadow and the neon's 4px
   blurred stroke both run past it and were cut off, most visibly at the L's right
   edge and the V's left. A filter on an HTML element has no such region, so the
   glow paints freely. `overflow: visible` on the SVG then stops the viewBox
   clipping the fat stroke at those same two edges, since the outermost paths sit
   exactly on x=0 and x=399.75. */
.vi__lyr, .vi__shine { position: absolute; inset: 0; width: 100%; height: 100%; }
.vi__lyr { pointer-events: none; }
.vi__neon, .vi__svg, .vi__tips { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

/* layer 1 — the soft body of the light-line. Blurred, so no sharp vector edge. */
.vi__lyr--neon { filter: blur(4px); }
.vi__neon path, .vi__neon polygon {
  fill: none; stroke: #ffffff; stroke-width: 4; stroke-linecap: round; stroke-linejoin: round;
  opacity: 0;
  stroke-dasharray: var(--len, 1200);
  stroke-dashoffset: var(--len, 1200);
}
.vi.is-playing .vi__neon path,
.vi.is-playing .vi__neon polygon {
  animation: viDraw .9s var(--ease-out) calc(120ms + var(--i) * 240ms) forwards,
             viNeonOn .5s var(--ease)   calc(120ms + var(--i) * 240ms) forwards;
}
@keyframes viNeonOn { to { opacity: .6; } }

/* layer 2 — the letter: a thin white core that draws, then a white fill */
/* THE WHITE GLOW IS CHOREOGRAPHED ACROSS THE WHOLE INTRO, not a single bloom.
   It used to be one 1.4s flare starting at 2000ms, which meant the wordmark was
   lit the same during the writing as after it, and finished brighter than it
   needed to. Now one 4.3s animation runs the length of the piece, so the light
   has a story and ends softer than it starts:
     0ms     faint, barely there while the first letter is still a line
     520ms   creeping up as V and O arrive
     1290ms  building through C and A
     1980ms  FLARE, on the beat the last letter lands
     2320ms  falls back
     2670ms  a second, smaller lift riding the shine sweep
     3180ms  easing off
     3780ms  low
     4300ms  6px / .26 -- softer than the 14px / .55 it used to end on, which is
             the "a little less at the end" that was asked for
   Percentages are of 4300ms: 12% = 516, 30% = 1290, 46% = 1978, 54% = 2322,
   62% = 2666, 74% = 3182, 88% = 3784. The gold second shadow tracks the white
   one at roughly double the radius so the two never separate into rings. */
.vi__lyr--core { filter: drop-shadow(0 0 6px rgba(255,255,255,.45)) drop-shadow(0 0 12px rgba(240,208,136,.3)); }
.vi.is-playing .vi__lyr--core { animation: viBloom 4.3s var(--ease) forwards; }
@keyframes viBloom {
  0%   { filter: drop-shadow(0 0 6px  rgba(255,255,255,.45)) drop-shadow(0 0 12px rgba(240,208,136,.30)); }
  12%  { filter: drop-shadow(0 0 8px  rgba(255,255,255,.50)) drop-shadow(0 0 16px rgba(240,208,136,.32)); }
  30%  { filter: drop-shadow(0 0 11px rgba(255,255,255,.58)) drop-shadow(0 0 22px rgba(240,208,136,.38)); }
  46%  { filter: drop-shadow(0 0 26px rgba(255,255,255,.90)) drop-shadow(0 0 50px rgba(240,208,136,.55)); }
  54%  { filter: drop-shadow(0 0 15px rgba(255,255,255,.60)) drop-shadow(0 0 30px rgba(240,208,136,.38)); }
  62%  { filter: drop-shadow(0 0 22px rgba(255,255,255,.80)) drop-shadow(0 0 42px rgba(240,208,136,.50)); }
  74%  { filter: drop-shadow(0 0 13px rgba(255,255,255,.50)) drop-shadow(0 0 26px rgba(240,208,136,.32)); }
  88%  { filter: drop-shadow(0 0 9px  rgba(255,255,255,.38)) drop-shadow(0 0 18px rgba(240,208,136,.24)); }
  100% { filter: drop-shadow(0 0 6px  rgba(255,255,255,.26)) drop-shadow(0 0 12px rgba(240,208,136,.16)); }
}

.vi__svg path, .vi__svg polygon {
  fill: #ffffff;
  stroke: #ffffff; stroke-width: .9; stroke-linecap: round; stroke-linejoin: round;
  fill-opacity: 0;
  stroke-dasharray: var(--len, 1200);
  stroke-dashoffset: var(--len, 1200);
}
.vi.is-playing .vi__svg path,
.vi.is-playing .vi__svg polygon {
  animation:
    viDraw .9s var(--ease-out) calc(120ms + var(--i) * 240ms) forwards,
    viFill .7s var(--ease)     calc(620ms + var(--i) * 240ms) forwards;
}
@keyframes viDraw { to { stroke-dashoffset: 0; } }
@keyframes viFill { to { fill-opacity: 1; stroke-opacity: .5; } }

/* layer 3 — a 4px dash riding the contour, so a bright point leads the pen */
.vi__lyr--tips { filter: drop-shadow(0 0 8px #ffffff) drop-shadow(0 0 18px rgba(240,208,136,.8)); }
.vi__tips path, .vi__tips polygon {
  fill: none; stroke: #ffffff; stroke-width: 3; stroke-linecap: round;
  stroke-dasharray: 4 9999; stroke-dashoffset: 0; opacity: 0;
}
.vi.is-playing .vi__tips path,
.vi.is-playing .vi__tips polygon {
  animation: viTip .9s var(--ease-out) calc(120ms + var(--i) * 240ms) forwards;
}
@keyframes viTip {
  0%   { opacity: 0;  stroke-dashoffset: 0; }
  8%   { opacity: 1; }
  88%  { opacity: 1; }
  100% { opacity: 0;  stroke-dashoffset: calc(var(--len, 1200) * -1); }
}

/* layer 4 — one bright sweep across the finished wordmark. Masked: no filter. */
.vi__shine {
  opacity: 0;
  background: linear-gradient(100deg,
    transparent 32%, rgba(255,255,255,.10) 41%, rgba(255,255,255,1) 50%,
    rgba(255,255,255,.10) 59%, transparent 68%);
  background-size: 300% 100%; background-repeat: no-repeat; background-position: 150% 0;
  -webkit-mask: url(assets/edit/vocal-logo.svg) center / contain no-repeat;
          mask: url(assets/edit/vocal-logo.svg) center / contain no-repeat;
}
.vi.is-playing .vi__shine { animation: viShine 1.1s linear 2200ms forwards; }
@keyframes viShine {
  0%   { opacity: 1; background-position: 150% 0; }
  100% { opacity: 1; background-position: -150% 0; }
}

/* tagline (reuses pre_tag) */
.vi__tag {
  font-family: var(--font-accent); font-style: italic; font-weight: 500;
  font-size: clamp(13px, 1.5vw, 17px); letter-spacing: .04em;
  color: rgba(255,255,255,.82); text-align: center;
  text-shadow: 0 0 18px rgba(255,255,255,.22);
  opacity: 0; transform: translateY(8px);
}
html[dir="rtl"] .vi__tag { font-family: var(--font-body); font-style: normal; }
.vi.is-playing .vi__tag { animation: viTag .7s var(--ease) 2600ms forwards; }
@keyframes viTag { to { opacity: .85; transform: none; } }

/* =========================================================
   The start screen — shown before the intro so the chime is allowed to play
   ========================================================= */
.vi__gate {
  position: absolute; inset: 0; z-index: 3;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: #000;
  transition: opacity .25s ease, visibility .25s;
}
.vi.is-playing .vi__gate { opacity: 0; visibility: hidden; pointer-events: none; }

.vi__gate::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(440px 440px at 50% 42%, rgba(240,208,136,.12), transparent 70%);
  animation: viAura 5s ease-in-out infinite;
}
@keyframes viAura {
  0%, 100% { opacity: .5; transform: scale(1); }
  50%      { opacity: 1; transform: scale(1.12); }
}

/* the wordmark on the start screen: masked gold, slow shine, gentle float.
   Masked, so it carries NO filter -- see line 194. */
.vi__gatelogo {
  position: relative; z-index: 1;
  width: clamp(220px, 42vw, 520px); aspect-ratio: 399.75 / 73.32;
  background: linear-gradient(100deg, #8b6f2a 0%, #caa24a 20%, #f0d088 38%, #fff6d8 50%, #f0d088 62%, #caa24a 80%, #8b6f2a 100%);
  background-size: 250% 100%;
  -webkit-mask: url(assets/edit/vocal-logo.svg) center / contain no-repeat;
          mask: url(assets/edit/vocal-logo.svg) center / contain no-repeat;
  animation: viGateShine 3.4s linear infinite, viGateFloat 5.5s ease-in-out infinite;
}
@keyframes viGateShine { 0% { background-position: 175% 0; } 100% { background-position: -175% 0; } }
@keyframes viGateFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }

/* button + its two lines held tight and pushed down -- asked for explicitly;
   the three used to be spaced by the gate's own 34px gap */
.vi__gateact {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  margin-top: 15vh;
}

.vi__btn {
  cursor: pointer; font-family: var(--font-display); font-weight: 700;
  font-size: clamp(13px, 1.5vw, 15px); letter-spacing: .22em;
  color: #1a1408; text-transform: uppercase;
  padding: 15px 42px; border: none; border-radius: 99px;
  background: linear-gradient(158deg, #f7e6b0, #d4af37 55%, #a8842f);
  box-shadow: 0 0 30px rgba(240,208,136,.35), inset 0 1px 0 rgba(255,255,255,.45);
  transition: transform .3s var(--ease), box-shadow .3s ease;
}
html[dir="rtl"] .vi__btn { letter-spacing: .06em; text-transform: none; }
.vi__btn:hover { transform: translateY(-2px) scale(1.03); box-shadow: 0 0 46px rgba(240,208,136,.55), inset 0 1px 0 rgba(255,255,255,.5); }
.vi__btn:focus-visible { outline: 2px solid #fff6d8; outline-offset: 4px; }

.vi__hint {
  font-family: var(--font-body); font-size: 12.5px; letter-spacing: .06em;
  color: rgba(245,235,216,.55); text-align: center; margin: 0;
}
.vi__skip {
  font-family: var(--font-body); font-size: 12px; letter-spacing: .05em;
  color: rgba(245,235,216,.4); background: none; border: none; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px; padding: 0;
  transition: color .25s ease;
}
.vi__skip:hover { color: rgba(245,235,216,.8); }

/* ---- phones ---- */
@media (max-width: 600px) {
  .vi__gatelogo { width: min(74vw, 400px); }
  .vi__gateact { margin-top: 12vh; }
  .vi__btn { padding: 14px 34px; }
  .vi__stage { gap: 20px; }
  .vi__logo { width: min(78vw, 420px); }
  .vi__rings span { width: 210px; height: 210px; }
  .vi__neon path, .vi__neon polygon { stroke-width: 5; }
  .vi__lyr--neon { filter: blur(3px); }
}

/* ---- reduced motion: every layer becomes a still ---- */
@media (prefers-reduced-motion: reduce) {
  .vi__svg path, .vi__svg polygon { stroke-dashoffset: 0; fill-opacity: 1; stroke-opacity: .5; }
  .vi__neon path, .vi__neon polygon { stroke-dashoffset: 0; opacity: .6; }
  .vi.is-playing .vi__svg path,
  .vi.is-playing .vi__svg polygon,
  .vi.is-playing .vi__neon path,
  .vi.is-playing .vi__neon polygon,
  .vi.is-playing .vi__tips path,
  .vi.is-playing .vi__tips polygon,
  .vi.is-playing .vi__shine,
  .vi.is-playing .vi__rings span,
  .vi.is-playing .vi__sparks i,
  .vi.is-playing .vi__halo,
  .vi.is-playing .vi__aura,
  .vi.is-playing .vi__lyr--core { animation: none; }
  .vi.is-playing .vi__tips path, .vi.is-playing .vi__tips polygon { opacity: 0; }
  .vi.is-playing .vi__shine { opacity: 0; }
  .vi.is-playing .vi__halo, .vi.is-playing .vi__aura { opacity: 1; }
  .vi.is-playing .vi__tag { animation: none; opacity: .85; transform: none; }
  .vi__gatelogo, .vi__gate::before { animation: none; }
  .vi.is-settled .vi__stage { transform: none; }
}

/* ===================== EDIT-V53 =====================
   V11 English, the camera block ("Super Resolution on 50MP front & rear"):
   right-align the text so every line lands on the language switcher's edge.
   The last item of the site-wide alignment tidy-up, and the only one that had to
   be decided rather than measured.

   WHY NOTHING CHEAPER WORKS. The block is .v2x__copy.m3.copy-anchor-r on line 101
   of v11.html. Its BOX is already on the switcher edge -- EDIT-V19's child rule at
   4215 gives it max-width:640px and margin-left:auto, and the eyebrow is
   width:fit-content at 4224, which is why the eyebrow measures exactly 0. What
   fell short was the ink. Measured at 1440px, distance from the switcher edge:
     eyebrow 0   title lines 87 / 124 / 512   paragraph lines 32 / 214
   Not one line of the title reached the edge, so this was not ragged setting with
   the widest line landing -- it was case (b) of the audit, "box on the column but
   no line reaches it".
   width:fit-content was the obvious repair and it does NOT work here. Injected at
   0,4,0 and measured: the h2's computed width stayed 640px before and after,
   because the title wraps and fit-content on a wrapping element resolves back to
   the available width. That trap is already recorded from the EDIT-V49 round.
   So the only lever left was text-align.

   THE TRADE, STATED PLAINLY. Right-aligning English buys the right edge at the
   cost of the left one. Measured after:
     title lines   L556 / L593 / L981   all R0
     paragraph     L501 / L682          all R0
   Before, all five lines began at a flat L469. So "rear" now hangs alone on the
   right and the paragraph steps. Both options were built and shown side by side
   with these numbers; the user chose this one. My own recommendation was to leave
   it, on the grounds that English reads from the left and the box already
   satisfied the rule at item level -- recorded here so the reasoning is not lost,
   not to relitigate it.

   SPECIFICITY 0,4,1 with !important, against line 4213's text-align:left
   !important at 0,4,0. The extra weight is html:not([dir="rtl"]), which also
   makes the rule direction-safe -- the same guard EDIT-V20b added at 4314 after
   EDIT-V19's selector turned out to catch RTL pages too. It must not: v11-fa and
   v11-ar use .m3t.copy-anchor-r on the same line and are right-aligned already by
   their own path.

   SCOPE IS EXACTLY ONE ELEMENT, checked rather than assumed. .m3.copy-anchor-r
   appears once in the whole site, on v11.html:101. The four other copy-anchor-r
   blocks (v11-fa/ar lines 101 and 175) all carry .m3t, not .m3, so none of them
   match. v11.html's own hero and performance blocks carry neither class.

   GATED 901px+, matching EDIT-V19's own gate. Below it .m3 centres the block
   (that is what .m3 is kept in the markup for -- see the note at 4183) and a
   right flush would break the centred mobile layout. Verified at
   900/768/600/480/375/320 that computed text-align stays "center" and every box
   rect is unchanged.
   ========================================================= */
@media (min-width: 901px) {
  html:not([dir="rtl"]) .v2x--right .v2x__copy.m3.copy-anchor-r { text-align: right !important; }
}

/* ===================== EDIT-V54 =====================
   .col-560 — a 560px text column for the V11 camera block, all three languages.
   On v11.html line 101 (.m3.copy-anchor-r) and v11-fa/ar line 101
   (.m3t.copy-anchor-r, with .oneline removed from the markup at the same time).

   WHAT THE COLUMN ACTUALLY WAS. EDIT-V19's child rule at 4215 (English) and
   EDIT-V20's at 4292 (fa/ar) cap these children at 640px. English obeyed it. fa
   and ar did not, and by design: .oneline (3460-3461) makes the paragraph and
   every .mask__in nowrap, and EDIT-V43 then adds min-width:max-content to the
   title so the unbreakable phrase is not clipped. min-width clamps AFTER
   max-width, so the title was pinned at its full ink width whatever the cap said.
   Measured at 1440px before this change:
     en   title 3 lines 553/516/128   paragraph 2 lines 608/426   block h509
     fa   title 2 lines 371/760       paragraph 1 line  800       block h442
     ar   title 2 lines 475/849       paragraph 1 line  845       block h442
   So the fa/ar "640px column" was really 800-849px wide. Narrowing it therefore
   had to release both the nowrap and EDIT-V43's floor, and the clean way to do
   that is to drop .oneline from those two elements: EDIT-V43 is keyed to
   .m3t.oneline.copy-anchor-r, so removing the class retires the floor with it
   instead of fighting it with another !important.

   THIS REVERSES AN EARLIER REQUEST, ON PURPOSE. EDIT-V43 exists because the user
   asked for the whole phrase on one line ("باید کانتینر بزرگتر بشه"). Narrowing
   the column costs exactly that: the fa/ar title goes from two long lines to
   three. Both options were measured and shown before shipping and the user
   confirmed the trade.

   WHY 560 AND WHERE IT BREAKS. Swept 600/560/550/545/540/530/520/500/470 in all
   three languages. 560 is the only value that gives the SAME structure in all
   three -- title 3 lines, paragraph 2 lines, block height 509, every line still
   on the switcher edge -- and it also balances the English paragraph best
   (518/516, against 608/426 at 640 and 587/447 at 600).
   THE HEADROOM IS 7px AND THAT IS WORTH KNOWING. The English title's longest
   line needs 553px. At 550 it breaks to four lines and the block grows to 575.
   Arabic holds three title lines down to 500 and breaks to five at 470; Persian
   holds to 470. So English is the binding constraint and it has 7px of slack: if
   the English camera title is ever reworded slightly longer, this block will
   gain a line. 600 was offered as the conservative alternative (50px of slack,
   same line structure) and 560 was chosen.

   A LIVE MOBILE BUG GOES WITH IT. Dropping .oneline also drops its ungated
   nowrap, and that paragraph was being CUT on phones: measured at 900, 768, 480
   and 375 the fa and ar paragraph reported scrollWidth > clientWidth on every
   one, i.e. one 25.6px-tall line with its tail clipped. After the change it wraps
   and reports clean at all four. This is the .oneline overflow already on the
   open-items list, fixed here for these two elements only -- line 175 on both
   pages still carries .oneline and is untouched.

   SPECIFICITY 0,4,1 -- html + four classes -- against the 0,4,0 of both 4215 and
   4292. The bare `html` is there to clear those two on weight rather than on
   source order, and it is direction-neutral so one rule serves en, fa and ar.

   GATED 901px+, matching the gate on both rules it overrides. Below it .m3/.m3t
   centre the block and the cap is not wanted; verified at 900/768/480/375 that
   the computed max-width on these children is unchanged by this rule.
   ========================================================= */
@media (min-width: 901px) {
  html .v2x--right .v2x__copy.col-560.copy-anchor-r > *,
  html .v2x--right .v2x__copy.col-560.copy-anchor-r p { max-width: 560px; }
}

/* ===================== EDIT-V55 =====================
   Two text-integrity fixes found by a site-wide sweep of all 55 pages in all
   three languages, at 1440px and 375px.

   PART 1 — .oneline stops cutting sentences on phones.
   Lines 3460-3461 pin white-space:nowrap on .oneline, on its paragraphs and on
   its .mask__in, UNGATED, so they apply at every width. Above 901px that is the
   intent: a phrase that must not break. On a phone the phrase cannot fit, the
   nearest clipping ancestor is section.v2x (overflow:hidden, line 2744), and
   under RTL the cut lands on the LEFT — which is the sentence's END, so it reads
   as a complete sentence that simply stops. Measured at 375px, pixels of text
   lost past the clip edge:
     v11-fa.html   line 175 paragraph      740.9
     v11-ar.html   line 175 paragraph      676.4
     v2-lite-fa.html line 103 p.oneline    608.2   (fixed in markup instead, see below)
     v1-core-fa.html line 114 section__sub 418.9
     v1-core-ar.html line 114 section__sub 352.7
   At 1440px none of these is clipped — the text overflows its own box but stays
   inside the section — so this is a phone-only defect. All 50 other pages measured
   clean, and English is clean everywhere.

   The release is gated at max-width:900px, the mirror of the 901px gate the rest
   of the sheet uses, so desktop keeps its single-line phrases untouched.
   SPECIFICITY: 3460's bare `.oneline` is 0,1,0 and its `.v2x__copy.oneline p` is
   0,2,0; 3461 is 0,2,0. Prefixing with `html` clears each of them on weight
   rather than on source order, without a single !important.

   PART 2 — .mask stops trimming descenders and Arabic diacritics.
   .mask (line 497) is overflow:hidden with padding-block:.14em, and .14em is less
   than the deepest ink some lines carry. Measured across the same sweep, the worst
   overflow past the clip edge, expressed in em so one value covers every size:
     bottom 0.291em   v0-core-fa  "۵ اینچِ پرشور،"        14.9px at 51.2px
     bottom 0.286em   v2-lite-ar  "ثلاثية 50 ميجابكسل…"   18.3px at 64px
     bottom 0.270em   v1-core-ar / v2-pro-ar               17.3px at 64px
     top    0.131em   index-ar    "نَصِلُك بـ"             12.6px at 96px
   English is affected as much as fa/ar ("Classic luxury," 6.9px, "Making Waves"
   6.9px), so this is not a script issue: the box is simply tighter than the ink.
   New padding .30em top / .46em bottom covers 0.131 and 0.291 with room to spare.

   THE FOOTPRINT IS UNCHANGED, WHICH IS THE WHOLE POINT. Line 497 pairs its
   padding with a negative margin so the mask adds only .16em to the layout:
     before  padding .14+.14 = .28   margin -.06-.06 = -.12   footprint +.16em
     after   padding .40+.70 = 1.10  margin -.32-.62 = -.94  footprint +.16em
   The numbers are .40/.62 and not the .30/.46 the measurements alone call for,
   because `em` on .mask resolves against the MASK's font-size while the ink
   belongs to .mask__in -- and line 2726 gives .v2x-hero__title .mask__in a larger
   font-size of its own. With .30/.46 two Arabic lines still overflowed by 1.8px
   and 4.5px; .40/.62 clears them. Measured, not guessed.
   So the clip box grows by .16em upward and .32em downward while the space the
   element occupies stays identical. Verified by measuring block heights.

   AND THE PRE-REVEAL STATE HAD TO MOVE WITH IT, or the fix would leak. Line 499
   parks .mask__in at translateY(110%) so it sits below the clip box until .in
   lands. A taller clip box means 110% no longer hides it: hidden needs
   1.10*h >= h + .46em, i.e. h >= 4.6em, which no line satisfies. At 160% the
   condition at 185% is 0.85*h >= .70em, which holds for every line box here.
   160% was tried first and left 1.3px of two Arabic hero lines peeking into the
   box on index-ar (translate 102.4px against a 39.7px bottom pad on a 64px line,
   so 0.60*64 = 38.4 < 39.7 -- measured, and the reason for 185%). Verified after
   the change by reading the pre-reveal offset of every .mask on seven pages.

   .title-1line .mask (line 3520) re-declares the same padding/margin pair at
   0,2,0, so it is listed explicitly at 0,2,1 rather than left behind.
   ========================================================= */

/* --- Part 1: let the phrase wrap on phones ------------------------------- */
@media (max-width: 900px) {
  html .oneline,
  html .oneline p,
  html .v2x__copy.oneline p,
  html .v2x-hero__copy.oneline p,
  html .v2x__copy.oneline .mask__in,
  html .v2x-hero__copy.oneline .mask__in { white-space: normal; }
}

/* --- Part 2: room for descenders and diacritics, same footprint ---------- */
html .mask,
html .title-1line .mask {
  padding-block: .40em .70em;
  margin-block: -.32em -.62em;
}
html .mask__in { transform: translateY(185%); }
html .mask__in.in,
html .mask__in.is-split,
html .no-gsap .mask__in { transform: none; }

/* ===================== EDIT-V56 =====================
   The four containers that were smaller than the phrase they hold, so the box
   fits the words instead of the words leaving the box. Asked for directly:
   "مواردی که کانتینر کوچک دارند را اصلاح کن تا کلمات و حروف کامل دیده شود".

   WHAT THE SWEEP FOUND. After EDIT-V55 nothing on the site is clipped any more,
   so this is a different fault: text that IS fully visible but has left its own
   column, because .oneline pins white-space:nowrap while the box stays capped.
   All 55 pages measured at 1440px; exactly four elements overflow their own
   padding box, and every one is the paragraph of a .oneline block:
     v11-fa.html:175    p   box 640  ink 1078  -> 438.4px outside, to the left
     v11-ar.html:175    p   box 640  ink 1014  -> 373.9px
     v1-core-ar.html:114 p.section__sub box 634 ink 773 -> 139.4px
     v1-core-fa.html:114 p.section__sub box 720 ink 847 -> 127.2px
   Left, because these are RTL and right-anchored: the box is pinned on its right
   edge and the sentence grows leftward out of it, over the photograph.

   THE FIX MOVES THE BOX, NOT THE TEXT, and that is the reason to prefer it.
   min-width:max-content grows the box leftward until it meets the ink it already
   had. Measured before and after, the ink stays on exactly the same pixels:
     v11-fa   ink 275..1354 before, 275..1354 after, box 714..1354 -> 275..1354
     v11-ar   ink 340..1354 both, box 714..1354 -> 340..1354
     v1-core-fa ink 240..1088 both, box 368..1088 -> 240..1088
     v1-core-ar ink 314..1088 both, box 454..1088 -> 314..1088
   So nothing on screen shifts; the container simply stops being too small. And
   min-width clamps AFTER max-width, which is why the 640px cap can stay in place
   — the same property pair EDIT-V43 used on the V11 title, on this user's word.
   Verified after the change: overflow 0 on all four, still inside the section,
   never past the logo column, and no horizontal document overflow.

   SCOPE, checked rather than assumed. The selectors reach .v2x__copy.oneline > p
   and .section__head.oneline > p, which is six elements site-wide: the four above
   plus v2-fa/ar lines 100 and 180. Those two pages already fit their boxes, and
   min-width:max-content is a floor, not a width — where max-content is already
   narrower than the box it changes nothing. Confirmed by measurement.

   GATED 901px+, for the reason EDIT-V55 exists: below 901 the nowrap is released
   and the paragraph wraps, so its natural box is correct and a max-content floor
   would force it wide again. Verified at 900/768/375 that computed min-width on
   these paragraphs stays 0px.
   ========================================================= */
@media (min-width: 901px) {
  html .v2x__copy.oneline > p,
  html .section__head.oneline > p { min-width: max-content; }
}

/* ===================== EDIT-V57 =====================
   F1 hero: bring the two phones in from the edge, toward the middle of the frame,
   in all three languages. Their arrangement, size, overlap and float are untouched
   — only the horizontal anchor moves.

   WHY THIS IS NOT A FIXED NUMBER, which was the first thing tried and measured.
   The pair is anchored to the outer edge (right in LTR, left in RTL) by EDIT-V27
   at lines 4769-4770, `calc(4vw + 25px)`. Its images size by hero HEIGHT (line
   3313, height:80%), so the pair keeps roughly its width as the viewport narrows
   while the copy column shrinks — the space between them closes on its own.
   Measured at 1440px, distance from the pair's near edge to the copy's ink:
     1440  en 373   fa 405   ar 416
     1200  en 157   fa 189   ar 200
     1024  en  -2   fa  ...  ar  41
      901  en -113  fa  ...  ar -69
   The pair ALREADY overlaps the copy below about 1024px — that is the existing
   composition, not something introduced here. So a constant inward shift would
   take its biggest bite exactly where there is least room: +225px flat measured
   -43 at 1200, -202 at 1024 and -313 at 901.

   SO THE SHIFT IS TIED TO THE VIEWPORT and starts from zero where the room runs
   out. Below 1200px nothing changes at all. From 1200 up it moves in by .7px per
   extra px of width, and min() caps the whole term at 200px so a very wide
   monitor does not crowd the copy. Measured after:
     1200  unchanged (the anchor point)         gap 157
     1366  off-centre 401 -> 285                gap 306 -> 190
     1440  off-centre 435 -> 267                gap 373 -> 205
     1920  off-centre 656 -> 456                gap 637 -> 437
   RTL mirrors exactly and fa and ar land on the same number: -420 -> -252 at
   1440, the same 168px of travel as English.

   SCOPE IS F1 ONLY, and the sheet already works this way. .fhero-duo is shared by
   nine pages (f1/f2/f4 in three languages), but horizontal placement is set per
   model: EDIT-V27 gives f1 and f2 `4vw + 25px` and EDIT-V31 gives f4 `4vw + 30px`.
   Keying this to .f1-hero follows that, and f2 and f4 keep their own placement.

   SPECIFICITY matches the rule it supersedes exactly — html:not([dir="rtl"])
   .f1-hero .fhero-duo is 0,2,1 — so it wins on source order alone, which is the
   one thing this sheet avoids elsewhere. It is acceptable here and nowhere else:
   EDIT-V27's pair at 4769-4770 is the ONLY other rule setting `right`/`left` on
   .f1-hero .fhero-duo, this block sits after it, and both legs restate `left:auto`
   / `right:auto` so neither direction can inherit a stale opposite offset.
   ========================================================= */
@media (min-width: 1200px) {
  html:not([dir="rtl"]) .f1-hero .fhero-duo {
    right: calc(4vw + 25px + min((100vw - 1200px) * .7, 200px));
    left: auto;
  }
  html[dir="rtl"] .f1-hero .fhero-duo {
    left: calc(4vw + 25px + min((100vw - 1200px) * .7, 200px));
    right: auto;
  }
}

/* ===================== EDIT-V58 =====================
   F2 hero: bring the OUTER phone in close to the inner one, in all three
   languages, without moving the inner one and without changing the pair's
   relationship to the copy.

   WHICH IMAGE IS "OUTER" SWAPS BETWEEN THE TWO DIRECTIONS, and getting this
   backwards is the whole difficulty. EDIT-V25 pins direction:ltr on .fhero-duo
   (line 4560), so the row is always __b then __a left-to-right. But the container
   is anchored to the page's outer edge, which flips:
     LTR  copy on the left,  pair anchored right -> __a is outer, __b is inner
     RTL  copy on the right, pair anchored left  -> __b is outer, __a is inner
   Measured at 1440px before this change:
     en   __b 576..986   __a 936..1342   overlap 50   copy ink ends 578
     fa   __b  98..508   __a 458..864    overlap 50   copy ink starts 901
     ar   identical to fa

   SHRINKING THE OVERLAP ALONE DOES THE WRONG THING. Making __a's negative
   margin deeper narrows the row, and because the container is anchored on its
   outer edge the INNER edge is the one that retreats — so the inner phone walks
   out toward the page edge while the outer one stays put. That is the opposite of
   what was asked. Verified by measurement before choosing this approach.

   SO THE ANCHOR IS COMPENSATED BY THE SAME AMOUNT. Deepen the margin by D and add
   D to the outer offset: the row loses D of width and the container moves D
   inward, which cancels at the inner edge and lands entirely on the outer one.
   Measured at 1440 with D = 160:
     en   __b 576..986  UNCHANGED     __a 936..1342 -> 776..1182
     fa   __a 458..864  UNCHANGED     __b  98..508  -> 258..668
     ar   same as fa
   Overlap 50px -> 210px, pair width 767 -> 607.

   THE COPY IS UNTOUCHED, BY CONSTRUCTION. Because the inner edge does not move,
   the distance from the pair to the copy's ink is identical at every value of D:
   -2px in English and 37px in fa/ar, before and after. This was the reason for
   compensating the anchor rather than simply nudging the pair.

   D = 160 was chosen over 220 after looking at both: at 210px of overlap the two
   phones read as a pair while the back one still shows its full body and its
   "VOCAL F2" engraving; at 270px roughly two thirds of it disappears behind the
   front phone.

   SPECIFICITY. EDIT-V28 sets the same three properties at lines 4815-4817 with
   selectors of 0,3,0 and 0,2,1. Prefixing with `html` and `body` here gives 0,3,1
   and 0,2,2, so each leg wins on weight and not on source order — unlike
   EDIT-V57, which sits in the same family but ties and relies on order. Both
   legs restate left:auto / right:auto so neither direction inherits a stale
   opposite offset.

   GATED 901px+, matching EDIT-V28's own gate; below it EDIT-V25's mobile
   treatment owns the pair and nothing here applies. f1 and f4 keep their own
   placement — this is keyed to .f2-hero.
   ========================================================= */
@media (min-width: 901px) {
  html .f2-hero .fhero-duo > .fhero-duo__a { margin-left: -210px; }
  html:not([dir="rtl"]) body .f2-hero .fhero-duo { right: calc(4vw + 185px); left: auto; }
  html[dir="rtl"] body .f2-hero .fhero-duo { left: calc(4vw + 185px); right: auto; }
}

/* ===================== EDIT-V59 =====================
   F4 hero: bring the phone nearest the frame edge in close to the one nearer the
   middle, in all three languages, without moving the inner one and without
   changing the pair's relationship to the copy. Same request and same method as
   EDIT-V58 did for f2 — see that block for the full reasoning.

   WHICH IMAGE IS "OUTER" SWAPS BETWEEN THE TWO DIRECTIONS. EDIT-V25 pins
   direction:ltr on .fhero-duo (line 4560), so the row is always __b (back view,
   camera) then __a (keypad view) left-to-right. The container is anchored to the
   page's outer edge, and that does flip:
     LTR  copy left,  pair anchored right -> __a is outer, __b is inner
     RTL  copy right, pair anchored left  -> __b is outer, __a is inner
   Measured at 1440px (client 1425) before this change, identical in fa and ar:
     en   __b 516.6..936.2   __a 906.2..1337.4   overlap 30
     fa   __b 102.6..522.2   __a 492.2..923.4    overlap 30

   SHRINKING THE OVERLAP ALONE MOVES THE WRONG PHONE. Deepening __a's negative
   margin narrows the row, and with the box pinned on its outer edge the INNER
   edge is the one that retreats — the inner phone walks out toward the page edge
   while the outer one stays put. So the anchor is compensated by the same amount
   D: the row loses D of width and the box moves D inward, the two cancel at the
   inner edge, and the whole change lands on the outer image. Measured at 1440
   with D = 150, i.e. margin -30 -> -180 and offset 4vw+30px -> 4vw+180px:
     en   __b 516.6..936.2  UNCHANGED   __a 906.2..1337.4 -> 756.2..1187.4
     fa   __a 492.2..923.4  UNCHANGED   __b 102.6..522.2  -> 252.6..672.2
     ar   identical to fa
   Overlap 30 -> 180, pair width 820.8 -> 670.8.

   THE COPY IS UNTOUCHED, BY CONSTRUCTION, and unlike a plain nudge this holds at
   every viewport width, not just the one it was tuned at. Distance from the pair
   to the copy's ink, before and after, at 1920/1440/1200/1024/901:
     en   150 / -114.7 / -330.7 / -489.1 / -599     unchanged at every D
     fa   207.3 / -57.4 / -273.4 / -431.8 / -541.6  unchanged at every D
     ar   207.6 / -57.1 / -273.1 / -431.5 / -541.4  unchanged at every D
   The negative numbers are the existing composition — below about 1600px the pair
   already sits behind the copy on this page — not something introduced here. No
   horizontal document overflow at any of those widths, before or after.

   D = 150 IS THE USER'S CHOICE, from 120 / 150 / 185 / 220 / 260 rendered side by
   side and offered as a question. It hides 43% of the back view. Note this is
   deliberately looser than f2, where EDIT-V58 hides 51% — asked directly, the
   answer here was the more conservative option, so do not "harmonise" the two
   pages to one number later. At 43% the two phones still read as a pair while a
   little air stays visible between the camera module and the front phone's edge.

   __a IS ALWAYS THE ONE ON TOP, in both directions, because it comes second in
   the DOM (EDIT-V25 point 2). So the overlap always hides __b's right-hand side:
   the inner phone loses it in English, the outer phone loses it in fa/ar. Same
   picture, mirrored position — that is the existing design, not a side effect.

   SPECIFICITY. The rules being superseded are `.f-hero .fhero-duo__a` at line
   4563 (0,2,0) and EDIT-V29's pair at 4950-4951 (0,3,1 each). Adding `html` to
   the margin rule gives 0,3,1, and `html`+`body` to the offset rules gives 0,3,2,
   so each leg wins on weight and not on source order. Both legs restate
   left:auto / right:auto so neither direction inherits a stale opposite offset.

   GATED 901px+, matching EDIT-V25 and EDIT-V29's own gates; below it there is no
   media query touching .fhero-duo at all and the mobile treatment is unchanged.
   Keyed to .f4-hero, so f1 (EDIT-V57) and f2 (EDIT-V58) keep their own placement.
   ========================================================= */
@media (min-width: 901px) {
  html .f4-hero .fhero-duo > .fhero-duo__a { margin-left: -180px; }
  html:not([dir="rtl"]) body .f4-hero .fhero-duo { right: calc(4vw + 180px); left: auto; }
  html[dir="rtl"] body .f4-hero .fhero-duo { left: calc(4vw + 180px); right: auto; }
}

/* ===================== EDIT-V60 =====================
   V0 CORE hero: the backdrop photo is replaced by a transparent four-phone
   render that FLOATS on the LEFT, the same on all three pages. Asked for
   directly: "تصویر رو با مسیری که بهت می دم جابجا کن و به صورت floating در همه
   زبان ها در سمت چپ قرار بده". New artwork supplied at
   Desktop\Vocal-Website-Edit-V03\V0core-Hero.webp.

   LEFT IS FREE IN ALL THREE LANGUAGES, which is why one rule covers them and no
   direction-scoped pair is needed here. v0-core-fa/ar carry .hero-side-right and
   English got the same treatment from EDIT-V41, so the copy sits on the RIGHT
   everywhere. Measured left edge of the copy's ink:
     1440 (cw 1425)  en 834.3   fa 886.3   ar 904.2
     1200 (cw 1185)  en 608.7   fa 660.7   ar 678.6
      901 (cw  886)  en 327.7   fa 379.7   ar 397.5
   English binds at every width, so the width formula is fitted to English and
   fa/ar come out 52-70px looser for free.

   THE WIDTH IS TIED TO THE VIEWPORT, not a constant, for the reason EDIT-V39
   found on v0.html: the copy has a floor -- its chips row and buttons stop
   shrinking -- so the room beside it closes faster than any fixed size can allow
   for. But it takes TWO terms, not one, and a single-slope fit is a trap that
   was caught only by measuring above 1500px. The copy tracks the viewport until
   its own max-width binds at a computed 1532px, and from there its ink advances
   at half the rate. Room from the section edge to the English ink, measured:
     cw    886  1009  1185  1351  1425  1485 | 1585  1685  1730  1785  1905  2545
     ink 327.7 443.3 608.7 764.8 834.3 890.7 | 958.2 1008  1031  1058  1118  1438
   Left of the bar the slope is 0.94 (room = 0.94cw - 505.6); right of it it is
   exactly 0.50 (room = 0.50cw + 165.7); they cross at cw 1526. Fitting only the
   left segment -- which is what the first pass did -- overshoots badly in the
   middle: it gave gaps of 34px at 1600 and MINUS 29px at 1745, i.e. the image
   slid under the copy exactly where the sheet claimed 60px of clearance.
   min() of both terms holds the gap at 60px from 901px to about 2170px:
     901 61 | 1024 61 | 1200 61 | 1366 61 | 1440 61 | 1500 61 | 1600 60
     1700 60 | 1745 60 | 1800 60 | 1920 60 | 2200 198 | 2560 378
   Resulting left inset, size and English gap: 54/253x141/+21 at 901,
   61/345x192/+37 at 1024, 66/401x223/+47 at 1100, 72/476x265/+61 at 1200,
   86/687x383/+61 at 1440, 96/802x447/+60 at 1600, 115/943x525/+60 at 1920,
   132/928x517/+198 at 2200.

   THE 1120px CAP IS THE ARTWORK, not taste. The shipped render is 2240 device px
   wide, so 1120 CSS px is the largest it can be drawn without upscaling on a 2x
   screen. It only binds above ~1924px, where the 0.50 term would otherwise keep
   growing; on a 2560px monitor the image is still 44% of the viewport.

   NO OVERLAP WITH THE COPY, deliberately. The copy is z-index 4 and this image
   is 3, so any overlap would put body text over a lit phone body — the same
   trap EDIT-V39 documented. That is what the text gap protects.

   THE GAP TAPERS BELOW 1200px, so the image does not shrink to nothing on a
   narrow laptop. Holding it at a flat 60px left the image at 321x179 at 1024 and
   213x119 at 901, which was reported as too small, so --v0c-gap eases from 60px
   at 1200 down to a 20px floor at 901:
     1201 61 | 1200 61 | 1150 54 | 1100 47 | 1024 37 | 960 29 | 901 21
   and the image gains +2% / +3% / +7% / +12% / +19% of width across that range.
   clamp() rather than a media query on purpose: above 1200 the middle term
   exceeds 60px and clamp returns the 60px ceiling, so the curve is CONTINUOUS
   through the breakpoint. Verified at 1201 vs 1200 — 477x265 vs 476x265, no jump.

   AND THAT IS ALMOST ALL THE ROOM THERE IS, worth writing down so nobody spends
   another round on it. At 901 the total distance from the section edge to the
   English ink is 327.7px. The 6vw gutter takes 54.1 of it, so the absolute
   ceiling for the image — zero clearance, text touching the phone — is 273.7px.
   At 253px it is already 93% of that. The only remaining lever is the gutter
   itself, and that is the alignment the owner chose; do not quietly trade it away.

   NO BLEED OFF THE FRAME EITHER, which was a correction after the first deploy.
   The first version anchored at left:-60px and let the artwork run off the frame
   edge, the way EDIT-V39 does on v0.html at -55px. Shown live, that read as the
   image being cut rather than as a composition continuing past the edge, and the
   instruction was to pull it in: "تصویری که الان برای مدل V0core بخش هیرو آپلود
   کردی در هر سه زبان از کادر بیرون رفته / به مرکز نزدیکش کن تا بیرون رفتگی
   نداشته باشه". Measured, the clip was exactly 60px on the left in all three
   languages and nothing on the other three sides (top -215, right -651,
   bottom -221, i.e. well inside).

   Pulling it in COSTS WIDTH, and that is the part worth understanding. The right
   edge is pinned by the text gap, so every pixel the left edge moves inward is a
   pixel off the image: the width subtracts both the gap and the gutter, and the
   right edge and the gap then come out identical to before at every width.
   Offered as a choice between flush-to-frame (left:0, image 774px at 1440) and
   column-aligned (left:6vw, 687px), the answer was column-aligned.

   6vw IS THE PAGE'S OWN GUTTER, not a guess: measured, .nav has padding-inline
   86.4px at a 1440 viewport, the .v2x-hero__copy has the same 86.4px, and the
   VOCAL logo's left edge sits at x=86. So the artwork's left edge now lines up
   with the logo above it and with the text column, and the placement reads as
   deliberate instead of accidental.

   THE ARTWORK ONLY TOUCHES THREE EDGES WITH A TIP, so there is nothing to feather
   away from. Ink along each canvas edge, out of the full edge length: left 18px
   of 1247 (1.4%), right 4px (0.3%), top 1px (0%), bottom 1326px of 2240 (59.2%).
   Only the BOTTOM is genuinely cropped in the supplied file, and the frame never
   clips there (221px of clearance at 1440), so that crop is the artwork's and no
   CSS change can recover it. The left and right "touches" are single phone
   corners, which is why sitting the image flush would not have looked cut either.

   z-index 3, NOT 1 OR 2. The stack in this section, measured: herobg 0,
   .v1c-hero__scrim 1, .v1c-hero__fade 1, .v11-hero__glow 2, copy 4, scroll 5.
   3 is the only value that clears the glow and still passes under the copy —
   the same slot EDIT-V39 gave .v0-phones. Left at 0 the phones would sit under
   the scrim; note the scrim here is `to left`, darkest at the RIGHT (line 3001
   for fa/ar, EDIT-V41 line 5454 for en), so it is doing its real job of backing
   the copy and leaves the left side clear for the artwork.

   THE FLOAT REUSES @keyframes v0float (line 5327) rather than declaring a second
   copy. That is the one from EDIT-V39, and it exists because the centring has to
   travel with the animation: top:50% is corrected by translateY(-50%), and an
   animation on `transform` REPLACES that, so a plain 0 -> -14px float would drop
   the image half its own height. v0float animates translateY(-50%) <->
   calc(-50% - 14px). Under prefers-reduced-motion the transform has to be
   restated explicitly — with the animation off, line 3434's
   .v0-hero .v0-herobg { transform: none } would take over and the image would
   hang down from the middle of the hero.

   MOBILE IS UNTOUCHED, and that is what the <picture> in the markup is for.
   Below 901px there is no free column at all — the copy takes nearly the whole
   width (fa ink 74..352 of a 375 viewport, English centred) — so a left-floating
   image is not viable there, and the standing rule is not to disturb mobile.
   The <source media="(min-width:901px)"> hands the transparent render to desktop
   and leaves phones on the original opaque photo at exactly today's geometry:
   inset:0, object-fit:cover, opacity .95, v0HeroKen still running. One request
   either way — the 131 KB render is never downloaded on a phone.

   .v0c-bgpic STANDS IN FOR THE IMG'S OLD BOX so nothing else in the section
   moves. position:absolute;inset:0 makes the wrapper exactly the box the <img>
   used to occupy, so the mobile inset:0/100%/100% still resolves against the
   same rectangle, and it takes the wrapper out of flow so no line box appears
   where an inline <picture> would have made one. It carries NO z-index on
   purpose: a z-index there would make it a stacking context and trap the image's
   3 inside it, painting it back under the scrim.

   SCOPED TO .v0c-hero, WHICH MATTERS MORE THAN USUAL HERE. .v0-herobg is on 15
   pages — f1/f2/f4, v0/v0-fa/v0-ar and the three v0-core pages — and .v0-hero
   is shared with v0.html and its translations. .v0c-hero exists on the three
   v0-core pages only (added by EDIT-V41), so it is the right handle.

   SPECIFICITY. The rules being overridden are .v0-hero .v0-herobg (0,2,0, lines
   3036 and 3434) and .hero-zoom .v0-herobg (0,2,0, line 3433). `html` in front
   of .v0c-hero .v0-herobg gives 0,3,1, so this wins on weight, not source order,
   and no !important is needed.

   THE ARTWORK WAS REVISED ONCE, mid-build, at the same path, and the shipped
   version is the SECOND one: 2382x1326, aspect 1.7964, against 2387x1366 and
   1.7474 for the first. The revision is a HARD cutout -- only 0.2% of its pixels
   are partly transparent, against 5.6% in the first version. That difference is a
   baked-in soft drop shadow the revision removed, which is what makes the
   drop-shadow declared below load-bearing rather than decorative. Its ink touches
   the left, right and bottom canvas edges, so the bleed above is reading real
   artwork and not empty margin.

   THE ASSET WAS RE-ENCODED FROM 749 KB TO 131 KB before shipping. The largest it
   is ever drawn is 1120 CSS px, i.e. 2240 device px on a 2x screen. Per-32x32-
   block PSNR against the master resampled to 2240, counting only blocks with ink:
     2382 q90  330 KB  worst block 41.30 dB
     2240 q92  240 KB  worst block 40.40 dB
     2240 q88  169 KB  worst block 38.26 dB
     2240 q85  131 KB  worst block 37.17 dB   <- taken, 0 blocks below 35 dB
     2240 q80  103 KB  worst block 35.98 dB
     2000 q90  172 KB  worst block 30.04 dB
   Note the 2000px row: quality buys nothing there because the bottleneck is the
   upscale back to 2240, not the encoder. 2240 q80 is both smaller AND better than
   2000 q90. Chrome writes the alpha channel LOSSLESSLY: measured alpha PSNR 99 dB
   with a maximum per-pixel error of 0 at every quality listed, so a hard matte is
   safe through this round trip. At 2000px an alpha error does appear (45.8 dB,
   max 97) and that is the resample, not the encoder.
   ========================================================= */
html .v0c-hero .v0c-bgpic { position: absolute; inset: 0; pointer-events: none; }

@media (min-width: 901px) {
  html .v0c-hero .v0-herobg {
    inset: auto;
    left: 6vw;
    top: 50%;
    right: auto;
    bottom: auto;
    --v0c-gap: clamp(20px, calc(60px + (100vw - 1200px) * .134), 60px);
    width: calc(min(1120px, 94vw - 520px, 50vw + 158px) - var(--v0c-gap) - 6vw);
    height: auto;
    object-fit: contain;
    opacity: 1;
    z-index: 3;
    filter: drop-shadow(0 40px 80px rgba(0, 0, 0, .55));
    animation: v0float 7s ease-in-out infinite;
  }
}
@media (min-width: 901px) and (prefers-reduced-motion: reduce) {
  html .v0c-hero .v0-herobg { animation: none; transform: translateY(-50%); }
}

/* ===================== EDIT-V61 =====================
   V0 hero (v0.html, v0-fa.html, v0-ar.html): .v0-phones stops bleeding off the
   frame and lines its outer edge up with the page column, in all three languages.
   Same instruction, same page family, one page later than EDIT-V60 on v0-core:
   "تصویر در همه زبانها بیرون رفتگی داره / به داخل بیار همتراز با ستون صفحه".

   EDIT-V39 anchored this at -55px on purpose and argued the case at length —
   840px of artwork simply does not fit between the copy and the frame at 1440,
   so the extra width was taken out of the frame edge rather than out of the gap.
   That argument was sound but it has now been overruled twice by the owner, on
   v0-core and here, so treat "no negative anchor on a hero float" as the rule for
   this site and do not reopen it.

   Measured before: exactly 55px clipped on the OUTER side at every width — right
   in English, left in fa/ar, since EDIT-V39 mirrors the anchor by direction (the
   copy is left in English and right in fa/ar on this page, unlike v0-core where
   it is right in all three). Nothing clipped on the other three sides.

   THE OUTER INSET IS 6vw, WHICH IS THE PAGE'S OWN COLUMN, not a chosen number:
   .v2x-hero__copy carries padding-inline 6vw at every width, and the measurement
   confirms the image's inset now matches it to the pixel — 54/54.06 at 901,
   61/61.44 at 1024, 72/72 at 1200, 86/86.4 at 1440, 96/96 at 1600, 115/115.2 at
   1920, 132/132 at 2200.

   THE WIDTH TERM IS EDIT-V39's, MINUS THE TWO THINGS THAT MOVED. Its room model
   was `91vw - 455px`. The anchor gave up 55px of bleed and took on 6vw of gutter,
   and both come off the far edge, so 91vw - 455px - 55px - 6vw collapses to
   85vw - 510px. Written that way rather than as a nest of subtractions so the
   next person can see the derivation.

   THE CAP STAYS INSIDE THE min(), WHICH IS NOT COSMETIC. Subtracting the gutter
   from an already-capped value — min(840px, ...) - 6vw — makes the image get
   SMALLER as the screen gets WIDER, because the capped base is constant while
   6vw keeps growing. Measured that mistake: 699px at 1440, 689 at 1600, 670 at
   1920, 653 at 2200, with 494px of unused gap at the wide end. With the cap
   outside the subtraction the width is monotonic and the artwork keeps its full
   840px wherever there is room:
     2200 840/+307 | 1920 840/+184 | 1600 840/+43 | 1500 765/+57 | 1440 714/+55
     1366 651/+53  | 1200 510/+48  | 1024 372/+31 |  901 275/+20   (width/en gap)

   --v0p-regain TAPERS THE GAP BELOW 1200px, the same fix EDIT-V60 needed for the
   same reason: without it the image fell to 256x146 at 901. English clearance was
   already thin on this page (48px at 1200, 39px at 901 before any change), so
   there is only ~19px to reclaim, and the clamp reclaims exactly that — 0px at
   1200 rising to a 20px cap at 901, which returns 11px of width at 1024 and 19px
   at 901 and lands the gap on 20px rather than dropping it further. clamp() not a
   media query, so the curve is continuous through 1200: measured 511x292 at 1201
   against 510x291 at 1200.

   fa and ar are identical to each other and looser than English at every width
   (gap 65-230 against 20-307), because their copy is narrower. English binds.
   Zero clipping on all four sides, and document.scrollWidth unchanged, in all
   three languages at 2200/1920/1600/1500/1440/1366/1200/1024/901.

   SPECIFICITY. EDIT-V39's own rules are .v0-hero .v0-phones at 0,2,0 for the
   width and html:not([dir="rtl"]) .v0-hero .v0-phones at 0,3,1 for each anchor.
   Adding `body` takes these to 0,2,2 and 0,3,2, so each wins on weight rather
   than source order. Both anchor legs restate the opposite offset as auto so
   neither direction can inherit a stale one from lines 3407/3411.

   Gated 901px+, matching EDIT-V39's own gate; below it .v0-phones keeps today's
   behaviour, hidden behind the hero photo at z-index -1. Keyed to
   .v0-hero .v0-phones, which exists only on the three v0 pages — v0-core shares
   .v0-hero but has no .v0-phones element, and its float is EDIT-V60's business.
   ========================================================= */
@media (min-width: 901px) {
  html body .v0-hero .v0-phones {
    --v0p-regain: clamp(0px, calc((1200px - 100vw) * .064), 20px);
    width: min(840px, calc(85vw - 510px + var(--v0p-regain)));
  }
  html:not([dir="rtl"]) body .v0-hero .v0-phones { right: 6vw; left: auto; }
  html[dir="rtl"] body .v0-hero .v0-phones { left: 6vw; right: auto; }
}

/* ===================== EDIT-V62 =====================
   V01 hero: the phone artwork replaced with the supplied transparent render, put
   in exactly the place the old one occupied, in all three languages. v01.html,
   v01-fa.html, v01-ar.html. Asked for as "به صورت فلوتینگ و در جای تصویر کنونی
   در هر سه زبان قرار بده"; source Desktop\Vocal-Website-Edit-V03\V01-Hero.webp.

   IT WAS ALREADY FLOATING, so nothing was added for that. GSAP writes
   translate3d(x, y, 0) scale(1.3, 1.3) inline on this element and oscillates y
   from 0 to +16px — EDIT-V34 point 3 recorded that the bob is asymmetric and
   downward-only. "Floating" here therefore means the transparent cutout sitting
   over the aura, which the new artwork is; the motion is untouched.

   THE TWO FILES ARE FRAMED COMPLETELY DIFFERENTLY, and that is the whole job.
   Measured alpha bounding boxes:
     old  assets/v01.png            750x750 canvas, content 496x563 at (127, 93)
          -> 127px of transparent padding each side, 93/94 top and bottom, 53.2%
             of the file is empty
     new  assets/edit/v01-hero.webp 937x1277 canvas, content 937x1277 at (0, 0)
          -> no padding at all, cropped hard to the phones, 5.4% clear (the gap
             between the two handsets)
   So a plain src swap does two wrong things at once: the aspect goes 1.000 ->
   0.734, and the missing padding throws the artwork ~140px to the right, because
   the old content stopped 127/750 of a box short of the box's own right edge.
   Sizing and offsetting by the CONTENT rather than the canvas is what fixes it.

   THE TWO COEFFICIENTS ARE THE PADDING RATIOS, not tuned numbers.
     width  = old box x 496/750 = x .6613, so the rendered content width is
              unchanged: 481px at 1440, 475 at 1200, 356 at 901 — identical to
              the old file's, measured to the pixel.
     right  = 3vw + old box x .2510, where .2510 = 1.3 x (.07 + 127/750)
              - 1.3 x .07 x .6613. The first term is where the old content's
              right edge sat relative to the box (its own translateX(-7%) plus
              its padding, both magnified by the 1.3 scale); the second is where
              the new content's right edge sits (translateX only, no padding).
              The difference is what has to be given back to `right`.
   Verified against the old file at 1440/1200/901 in all three languages: content
   rect and content width identical, gap to the copy identical, no clipping on any
   side, document.scrollWidth unchanged.

   ONLY THE HEIGHT CHANGES, WHICH IS THE POINT — the new crop shows more of the
   handsets, so at the same width they stand taller: 546 -> 656 at 1440, 539 ->
   647 at 1200, 404 -> 486 at 901. Still comfortably inside the frame; the
   vertical centring is EDIT-V34's and needs nothing.

   DO NOT TRUST AN INJECTED TEST OF THIS RULE. GSAP resolves the CSS
   translateX(-7%) to pixels once, at init, against whatever width the element has
   then. Injecting this rule into a loaded page leaves the old -50.96px in place
   (7% of 560 x 1.3) instead of the correct -33.7px (7% of 370.3 x 1.3), a 17.3px
   error that quietly makes a wrong coefficient look right. The numbers above come
   from the stylesheet, not from an injection.

   THE ASSET IS SHIPPED AS SUPPLIED, 117 KB, no re-encode. Its widest render is
   481 CSS px, i.e. 962 device px on a 2x screen, and the file is 937 wide — a
   2.7% upscale at the very top end, so there is nothing to gain by resampling and
   a lossy round trip would only cost quality. Alpha channel present, and the
   matte is soft (0.3% partly transparent), so no hard-edge concerns either.

   SPECIFICITY. `width` comes from .v11-hero__phone at line 2953 (0,1,0) and
   `right` from the same rule; .v01-hero-big at 3310/3418 sets transform only.
   html body .v01-hero .v11-hero__phone.v01-hero-big is 0,3,2, so both win on
   weight. Nothing here touches `transform` — that belongs to GSAP at runtime and
   any CSS value would be overwritten on the first animation frame.

   Gated 881px+, matching EDIT-V34 and the .v11-hero__phone mobile breakpoint at
   line 2963. Mobile keeps its own rule (position:static, width:min(380px,78%),
   centred in flow) and simply shows the new artwork at its own aspect.

   PART 2 — THE 70px MOBILE CLIP, fixed on the owner's word after being shown it.
   Line 2964 already tries to reset this element on phones with `transform: none`,
   and EDIT-V34 recorded why that never worked: GSAP writes the transform inline,
   and a normal stylesheet declaration cannot outrank a style attribute. So on
   phones the image kept scale(1.3) translateX(-7%) and sat off-centre. Measured
   at 375px with the new artwork: content -55..310 against a 0..375 frame, i.e.
   70px cut off the LEFT and 65px of dead space on the right. Same at 375 in
   English (-70..295) and identical in fa and ar. Pre-existing — the old file was
   cut 55-70px the same way — and 880px and 768px were already clean.

   `!important` IS THE FIX AND IT IS THE RIGHT TOOL HERE, not a shortcut. An
   important author declaration outranks a normal style attribute in the cascade,
   which is the only lever that reaches an inline value GSAP owns. It is doing
   exactly what line 2964 already asks for, so this is making an existing
   intention effective rather than introducing a new one. Nothing else in the
   sheet needs it: `transform` is the single property GSAP writes on this element.

   The trade was stated before it was taken: without the 1.3 scale the phone
   renders 281px wide at a 375px viewport instead of 365px, and all 281px are
   visible instead of 295 of 365. Centring comes free from line 2964's
   `margin: 26px auto 0` once the transform is gone.

   Scoped to .v01-hero, so the eleven other pages that share .v11-hero__phone
   keep their own mobile behaviour untouched.
   ========================================================= */
@media (min-width: 881px) {
  html body .v01-hero .v11-hero__phone.v01-hero-big {
    width: calc(min(560px, 46vw) * .6613);
    right: calc(3vw + min(560px, 46vw) * .2510);
  }
}
@media (max-width: 880px) {
  html body .v01-hero .v11-hero__phone.v01-hero-big { transform: none !important; }
}

/* ===================== EDIT-V63 =====================
   V2 PRO hero: the phone render 5% smaller, pulled in toward the middle, and its
   outer edge lined up with the page column — all three languages. v2-pro.html,
   v2-pro-fa.html, v2-pro-ar.html. Asked for as "تصویر گوشی ها رو 5 درصد کوچکتر و
   به مرکز نزدیک کن و اگه میشه با ستون پیج از راست همتراز کن".

   THE SECOND AND THIRD REQUESTS TURN OUT TO BE THE SAME CHANGE. .v2pro-phones sits
   at 5vw from the outer edge (line 3392, mirrored to `left` for RTL at 3398), and
   the page column is 6vw — measured, .v2x-hero__copy's padding-inline is 86.4px at
   1440, 72 at 1200, 61.44 at 1024, 54.06 at 901, i.e. exactly 6vw at each. So
   moving the anchor 5vw -> 6vw both pulls the artwork inward and lands it on the
   column. After the change the inset matches the copy's padding to the pixel at
   every width: 115/115.2, 86/86.4, 72/72, 61/61.44, 54/54.06.

   MIRRORED, because this hero is direction-scoped and v0-core's was not. English
   carries .hero-side-left so its copy is LEFT and the phones are RIGHT; fa and ar
   have no side class and line 3398 flips the anchor to `left`. "From the right"
   therefore means the outer edge in each direction — right in English, left in
   fa/ar — which is what the two legs below do.

   5% COMES OFF THE HEIGHT, because that is the dimension this element is sized by:
   line 3393 sets height: min(88vh, 780px) with width: auto. Both terms are scaled,
   88vh -> 83.6vh and 780px -> 741px, so the reduction holds whether the viewport
   height or the pixel cap is binding. 780 x .95 = 741 exactly; measured 903x780 ->
   858x741.

   THE THIRD min() TERM FIXES TWO PRE-EXISTING FAULTS AT ONCE, and it is the reason
   this block is more than two numbers. At 901px the old rule asked for 903px of
   width inside an 886px section anchored 45px in, so:
     - 45px of the artwork was CLIPPED off the far edge (left in English, right in
       fa/ar) — measured before the change at 901 in all three languages;
     - and the global img { max-width: 100% } capped the width at 886 while the
       height stayed 780, SQUASHING the render to aspect 1.1359 against the file's
       natural 1.1578. A distorted product photo, not just a cropped one.
   calc((94vw - 15px) * .8636) is the height at which the artwork exactly fills the
   room it has: 94vw - 15px is the section width less the 6vw inset (the 15px is
   the scrollbar), and .8636 is 1/1.1578, the file's own aspect. It only binds below
   about 929px, so it changes nothing at normal desktop widths and simply stops the
   overflow where the room runs out. Measured after, English:
     1920 inset 115  858x741 | 1440 inset  86  858x741 | 1200 inset 72  858x741
     1024 inset  61  858x741 |  901 inset  54  832x718
   zero clipping on all four sides at every width, aspect natural everywhere, and
   document.scrollWidth unchanged. fa and ar are identical to each other and mirror
   English exactly.

   NOTHING HERE TOUCHES `transform`, on purpose. The float is a CSS keyframe
   animation (v2proFloat, line 3397) that animates translateY, and the resting
   -50% centring lives inside those keyframes. Setting transform in this block
   would fight the animation and break the vertical centring.

   SPECIFICITY. The rules being overridden are `.v2pro-phones` (0,1,0, line 3391)
   and `html[dir="rtl"] .v2pro-phones` (0,2,1, line 3398). `html body` in front is
   what makes the anchors clear the RTL rule: html:not([dir="rtl"]) body
   .v2pro-phones is 0,2,2, one type more than 0,2,1. Note that a bare
   `html body .v2pro-phones` would be 0,1,2 and would LOSE to line 3398 on class
   count — the :not([dir]) attribute selector in each leg is load-bearing, not
   decoration. The height rule keeps 0,1,2, which is enough because line 3398 does
   not set height.

   PART 2 — THE MOBILE DISTORTION, fixed on the owner's word after being shown the
   numbers. Below 901px the same element was not merely clipped but STRETCHED, and
   badly: the height stayed at min(88vh, 780px) — about 715px on a phone — while
   the global img { max-width: 100% } crushed the width to whatever was left.
   Measured rendered aspect against the file's natural 1.1578:
     900px  827x715  aspect 1.1578  clean
     768px  753x715  aspect 1.0538  38px clipped off the left
     430px  415x715  aspect 0.5808  22px clipped
     375px  360x715  aspect 0.5038  19px clipped   <- 43% of its true width
   A product photograph of the flagship phone, rendered at 43% of its own width. It
   read as a tall smear behind the copy rather than as two handsets.

   THE SAME THIRD TERM FIXES IT, with the mobile anchor's own 5vw instead of 6vw:
   calc((95vw - 15px) * .8636) is the height at which the artwork exactly fills the
   room left beside a 5vw inset. Measured after: 341x295 at 375, 394x340 at 430,
   714x617 at 768, 827x715 at 900 — natural aspect everywhere, nothing clipped.

   88vh AND 780px ARE LEFT ALONE HERE, deliberately. The 5% reduction was asked for
   on the desktop hero; on a phone the aspect fix already takes the artwork from
   360px wide to 341px, and compounding another 5% on top would shrink it for a
   reason nobody asked for. Only the overflow term is new.

   The phones do end up visibly smaller on a phone than they were — 341x295 against
   360x715. That was stated before it was taken: correctly proportioned and whole,
   against tall, squashed and cut.
   ========================================================= */
@media (min-width: 901px) {
  html body .v2pro-phones {
    height: min(83.6vh, 741px, calc((94vw - 15px) * .8636));
  }
  html:not([dir="rtl"]) body .v2pro-phones { right: 6vw; left: auto; }
  html[dir="rtl"] body .v2pro-phones { left: 6vw; right: auto; }
}
@media (max-width: 900px) {
  html body .v2pro-phones {
    height: min(88vh, 780px, calc((95vw - 15px) * .8636));
  }
}

/* ===================== EDIT-V64 =====================
   V2 and V2 LITE hero scrim, all three languages: the black wash comes OFF the
   photograph, gets lighter, and the spec sub-labels get readable. Supersedes the
   first cut of this block, which only flipped the side; the lighter values and the
   label colour were added after measuring the result.
   Asked for as "سایه ی مشکی روی تصویر دقیقا مانند نسخه انگلیسی شده و از روی تصویر
   برداشته بشه", then "پیشنهادت رو دمو کن".

   PART 1 — THE RTL OVERRIDE WAS BACKWARDS, and the sheet already knew it: EDIT-V45's
   comment records the diagnosis and says the fix is one line at 3275, but that it
   "touches four pages at once and was not requested, so it is recorded here rather
   than done". It was requested.

   .hero-side-right puts the copy on the RIGHT in BOTH directions — its rule at 3269
   is `margin-left: auto`, which is not direction-relative — so the scrim must darken
   the right in both. Line 3271 does that for LTR with `to left`; line 3275 then
   "mirrors" it for RTL with `to right`, darkening the LEFT, which is the side the
   photograph is on. Measured at 1440, copy-ink midpoint against the section midpoint
   of 712: v2 1088 / v2-fa 1107 / v2-ar 1088 / v2-lite 1088 / v2-lite-fa 1103 /
   v2-lite-ar 1088 — the copy is on the right on all six, in both directions.

   AND ON THESE PAGES THE WASH LANDS ON THE ARTWORK, which is what made it visible
   rather than merely wrong. .v2x-hero__bg is z-index -2 (line 2714) and
   .v2x-hero::after is -1, so the gradient paints OVER the photo.

   PART 2 — THE VALUES, and the honest limit of what they can buy. Composited the
   real hero the way the page paints it (1920x1080 cover into 1425x900, then the
   1.12 scale, then both ::after layers) and sampled the phone-and-hand region:
     94/60@40/clear@68  (was)   brightness  38 / 255
     80/45@40/clear@55  (now)               46
     scrim removed entirely                 51
     the raw photograph, no overlay at all  54   <- the ceiling
   So the scrim was never the main reason the phone looked dark: the photograph is
   dark, and the whole available range is 38..54. This change takes 8 of those 16
   units, which is visible side by side but is NOT a substitute for re-grading the
   image if more is ever wanted. Do not chase the rest by weakening the scrim
   further — see Part 3 for what that costs.

   PART 3 — THE SPEC SUB-LABELS WERE ALREADY FAILING, and lightening the scrim would
   have made it worse, so the two changes ship together. .v2x-hero__chips span is
   12.5px at var(--dim) = #6e6249, which needs a 4.50 contrast ratio for body text.
   Measured against the composited background under the worst-placed label, on the
   Arabic and English pages:
     #6e6249 with the old scrim   3.17   fails
     #6e6249 with the new scrim   2.92   fails worse
     #8c7e60 with the new scrim   4.39   still short
     #9e9070 with the new scrim   5.57   passes            <- taken
   #9e9070 is the first step on the same hue that clears 4.50 with the lighter
   scrim, with margin. The global --dim token is deliberately NOT touched: it is
   used site-wide, so the lift is scoped to these heroes' chips only.

   UNGATED, ON PURPOSE, and worth reading before "tidying" it. Line 2792 means to
   replace both directions with a vertical `to top` scrim below 901px, but it can
   never win on these pages: 0,2,2 at best against line 3275's 0,3,2. Measured —
   v2, v2-fa, v2-ar and v2-lite-fa all keep the HORIZONTAL gradient at 375px,
   English included. So English's mobile wash is horizontal too, and matching
   English means matching at every width. (That line 2792 is dead on eight pages is
   a separate pre-existing fault, not touched here.)

   V0-CORE-FA/AR ALSO CARRY .hero-side-right AND ARE ALSO HIT, and that was checked
   rather than assumed. There the artwork is not under the wash: EDIT-V60 put the
   floating render at z-index 3 and the mobile photo sits at 0, both above the
   ::after at -1, and .v1c-hero__scrim at z-index 1 paints over it as well. Verified
   by screenshotting v0-core-fa with the flip applied and without: indistinguishable.
   Their chips lift with everything else, which only helps legibility there.

   V1-FA/AR ARE NOT AFFECTED. They carry .hero-scrim-l, whose EDIT-V45 rule at 5696
   is 0,3,2 and gated 901px+; they do not carry .hero-side-right, so the selectors
   never meet.

   SPECIFICITY. The rules superseded are .hero-side-right.v2x-hero::after (0,2,1,
   line 3271) and html[dir="rtl"] .hero-side-right.v2x-hero::after (0,3,2, line
   3275). Both legs here are 0,3,3 — the attribute selector plus two classes, and
   html, body and the pseudo-element — so each wins on weight, not source order.
   The two legs carry the SAME value on purpose: that identity is the request. The
   chips rule is 0,2,3 against line 2810's 0,1,1.
   ========================================================= */
html:not([dir="rtl"]) body .hero-side-right.v2x-hero::after,
html[dir="rtl"] body .hero-side-right.v2x-hero::after {
  background: linear-gradient(to left, rgba(8,6,4,.80) 0%, rgba(8,6,4,.45) 40%, transparent 55%),
              linear-gradient(to top, var(--bg) 4%, transparent 36%);
}
html body .hero-side-right .v2x-hero__chips span { color: #9e9070; }

/* ===================== EDIT-V65 =====================
   V11 hero: the full-bleed backdrop photo replaced by the supplied transparent
   render, standing on the LEFT with its edge on the page column, the same in all
   three languages. v11.html, v11-fa.html, v11-ar.html. Source
   Desktop\Vocal-Website-Edit-V03\V11-Hero.webp.

   LEFT IS FREE IN ALL THREE LANGUAGES, so one undirected rule covers them. These
   pages carry .hero-anchor-r (EDIT-V19), whose margin-left:auto !important at line
   4200 is physical, not direction-relative, so the copy sits RIGHT in every
   language. Measured ink at 1440: en 895..1338.6, fa 934..1338.6, ar 956.5..1338.6.
   English has the least room and therefore binds the width.

   6vw IS THE PAGE COLUMN, measured not chosen: .v2x-hero__copy padding-inline is
   115.2px at 1920, 86.4 at 1440, 72 at 1200, 54.06 at 901 -- exactly 6vw at each.

   THE HEIGHT TAKES THREE TERMS, and the third is the whole difficulty. This artwork
   is PORTRAIT (1319x1531, aspect 0.8615) where the old backdrop was landscape
   (2200x1006), so in a 900px-tall frame the height runs out long before the width
   at wide viewports, while at narrow ones the width runs out first and would drive
   the artwork straight across the copy. Room from the section edge to the English
   ink, measured:
     cw    886  1009  1185  1351  1425  1485 | 1585  1685  1785  1905  2185  2545
     free  388   504   669   825   895   951 | 1019  1069  1119  1179  1319  1499
   Two slopes again, as on v0-core: 0.94 below cw 1525 (free = .94cw - 444.5) and
   exactly 0.50 above it. Subtracting the 6vw column and a 60px gap to the copy,
   the available width is min(.88vw - 518.6, .44vw + 158.9). The second term is
   ALWAYS redundant against the 800px cap -- it only drops below 800 under vw 1206,
   where the first term is already smaller -- so it is left out rather than carried
   as noise. 1.1607 is 1/0.8615, the artwork reciprocal aspect.
   Resulting height x width and English gap:
      901  318x274/+60 | 1024  444x382/+61 | 1200  623x537/+60
     1366  792x682/+61 | 1440  792x682/+126 | 1920  792x682/+381
   Zero clipping on any side at any width, no horizontal document overflow.

   transform:none !important IS LOAD-BEARING, and this was the trap. GSAP owns
   transform on .v2x-hero__bg at runtime -- it writes translate3d(0,0,0)
   scale(1.12,1.12) inline, which is also why the CSS scale(1.3) at lines
   3414/3433/3435 has never actually rendered -- and it adds a scroll-driven
   translate(0%, 1.6667%) parallax on top. A 1.12 scale about the centre drags the
   left edge 0.06 x width outside the column (41px at 1440), so precise alignment is
   impossible while that inline value stands, and an important author declaration is
   the only thing that outranks a style attribute. The cost, stated plainly: this
   element loses its scroll parallax on these three pages. That is the trade for the
   alignment that was asked for.

   NO CSS TRANSFORM IS USED FOR CENTRING EITHER, for the same reason. Vertical
   centring is the absolute idiom -- top:0; bottom:0; margin-block:auto with a
   definite height -- the same one .v11-hero__phone uses at line 2953. A
   translateY(-50%) would have been overwritten by GSAP on the first frame.

   z-index 1, NOT -2. The stack here, measured: bg -2, .v2x-hero::after -1,
   .v11-hero__glow 0, copy 2, scroll auto. Left at -2 the render would sit UNDER the
   scrim, and EDIT-V19 scrim on this page is `to left` -- transparent only below
   68%, i.e. left of x=456 at 1440 -- so everything from 456 to the artwork right
   edge at 769 would have been washed. 1 is the only value that clears the scrim and
   the glow and still passes under the copy.

   MOBILE IS UNTOUCHED, which is what the <picture> in the markup is for. Below
   901px the copy centres and takes the full width, so there is no free column for a
   floating render, and the transparent cutout stretched by object-fit:cover would
   look broken. <source media="(min-width:901px)"> hands the render to desktop and
   leaves phones on the original opaque photo at exactly today geometry -- inset:0,
   cover, z-index -2 -- and the 201 KB file is never downloaded on a phone. Same
   pattern and same reasoning as EDIT-V60 on v0-core.

   .v11-bgpic STANDS IN FOR THE IMG OLD BOX so nothing else in the section moves,
   and carries NO z-index on purpose: a z-index there would make it a stacking
   context and trap the image z-index 1 inside it, painting it back under the scrim.

   THE ASSET WAS RE-ENCODED FROM 457 KB TO 201 KB. Native resolution kept: the
   widest render is 682 CSS px, i.e. 1364 device px on a 2x screen, and the file is
   1319 wide, so there is nothing to gain by resampling. Per-32x32-block PSNR
   against the master at 1364:
     1319 q92  257 KB  worst 35.96 dB
     1319 q88  201 KB  worst 35.40 dB   <- taken, 0 blocks below 35 dB
     1319 q85  176 KB  worst 34.63 dB   (1 block below 35)
     1200 q90  180 KB  worst 25.21 dB   <- the upscale penalty again
   Alpha survived losslessly (PSNR 99, max per-pixel error 0).

   ONE THING NO CSS CAN FIX, recorded so it is not chased later: the artwork is
   genuinely cropped along its own LEFT edge -- 875 of 1531 pixels of that edge
   carry ink, against 6 on the right, 22 on the top and 1 on the bottom. The back
   phone is cut in the supplied file, exactly as it was in the old backdrop. If it
   should be whole, the file needs re-exporting with margin on the left.

   SPECIFICITY. The rules overridden are .v2x-hero__bg (0,1,0, line 2714) and
   .v11-hero .v2x-hero__bg / .hero-zoom .v2x-hero__bg (0,2,0, lines 3414/3433/3435).
   html body .v11-hero .v2x-hero__bg is 0,2,2, so it wins on weight; the !important
   is only for transform, where the opponent is GSAP style attribute, not the sheet.
   ========================================================= */
html body .v11-hero .v11-bgpic { position: absolute; inset: 0; pointer-events: none; }

@media (min-width: 901px) {
  html body .v11-hero .v2x-hero__bg {
    transform: none !important;
    left: 6vw;
    right: auto;
    top: 0;
    bottom: 0;
    margin-block: auto;
    width: auto;
    height: min(88vh, 800px, calc((88vw - 519px) * 1.1607));
    object-fit: contain;
    z-index: 1;
    filter: drop-shadow(0 34px 70px rgba(0, 0, 0, .55));
  }
}

/* ===================== EDIT-V66 =====================
   V11 hero: the near-black behind the floating render recoloured to match the
   artwork, and the spec sub-labels lifted to a readable contrast. v11.html,
   v11-fa.html, v11-ar.html. Asked for as "میخوام رنگ زمینه ی سیاهی که گذاشتی با
   رنگها بک گوشی همخوانی بیشتری داشته باشه / سه تا پیشنهاد به صورت اسکرین شات بده";
   three candidates were rendered and the indigo one was chosen.

   THE CLASH WAS MEASURABLE, not a matter of taste, which is why this is a fix and
   not a repaint. Hue histogram of the artwork over its opaque, saturated pixels:
     210-219deg 27.9%   200-209deg 19.8%   220-229deg 11.3%   230-239deg 6.8%
       = 65.8% of it sits in the 200-239 COOL BLUE band
     20-29deg 11.3%     30-39deg 8.4%      = 19.7% warm (the skater cap and jeans)
   Against that, the old backdrop was warm: --bg #0c0907 is hsl(24, 26%, 4%) and the
   scrim literal rgba(8,6,4) is hsl(30, 33%, 2%). A brown-black ground under a
   silver-and-blue subject. Reference points sampled from the artwork itself:
     cool pixels mean  #cad6e9  hsl(217, 41%, 85%)   <- its dominant hue
     screen blues      #6686ac  hsl(213, 30%, 54%)
     phone body silver #b9b8bc  hsl(245,  3%, 73%)   <- the iridescence

   THE THREE CANDIDATES, all built from those hues and all rendered before choosing:
     A  #0b1017  217deg  the artwork own dominant hue, purest match
     B  #0d0c1a  245deg  the phone iridescence, and the hue of the violet glow
                         that was already on this page and read as unrelated
                         against a warm ground                          <- CHOSEN
     C  #0e1013  220deg desaturated, warmth removed and nothing added
   B was taken because it is the only one that harmonises with TWO things at once.

   TEXT CONTRAST IS UNCHANGED, checked rather than assumed. On this page no
   photograph sits behind the copy — the render ends at x=769 and the ink starts at
   895 — so the background there is flat colour plus scrim and can be computed
   exactly. Ratios against the composited patch:
                    title #f5ebd8   gold #f0d088   sub-label
       was warm         17.02          13.50          3.36
       B indigo         16.51          13.09          3.26
   So the recolour costs nothing legible. But note both numbers for the sub-label
   are BELOW the 4.50 that 12.5px body text needs, which is the second half of this
   block.

   THE SUB-LABELS GET THE SAME LIFT V2 AND V2-LITE GOT. #6e6249 scores 3.26 here;
   #9e9070 scores 6.20, and it is deliberately the SAME value EDIT-V64 used rather
   than a cool variant invented for this page — the site palette is warm gold, warm
   sand labels are on-brand even over an indigo ground, and one value across the
   heroes is worth more than a per-page optimum. Cool alternatives were measured
   (#8f8d9e 6.01, #9a98ab 6.92) and rejected on that ground, not on contrast.

   THE BOTTOM FADE DELIBERATELY STILL RESOLVES TO var(--bg), i.e. to the warm page
   colour, and that is what prevents a seam. Only the hero's own ground is recoloured
   here; the rest of the page keeps --bg. Redefining the token for these pages was
   considered and rejected: --bg appears in 22 places but its warm literal twin
   rgba(12,9,7) is hard-coded alongside it in several of them (lines 2660, 2678,
   2868, 2870, 2984), so a token swap would leave those washes warm and produce
   exactly the mismatch it was meant to remove. Fading the hero's last 36% back to
   --bg costs nothing visible — #0d0c1a and #0c0907 are both near-black — and
   guarantees the join.

   MOBILE IS RECOLOURED TOO, because the request was about the colour, not the
   layout. Below 901px line 2792 replaces the scrim with a vertical `to top` ramp;
   its shape is kept exactly and only the rgb is changed, so the phone layout is
   untouched while the hue matches desktop.

   SCOPE IS THE THREE V11 PAGES, and .hero-anchor-r is the right handle: it exists
   only on v11.html, v11-fa.html and v11-ar.html. .v11-hero would have been wrong —
   it is shared with v0, v0-core, v01, v1-core and the whole F series.

   SPECIFICITY. The rules overridden are .hero-anchor-r.v2x-hero::after (0,2,1,
   line 4205, gated 901+) and .v2x-hero::after (0,1,1, line 2792, gated to 900),
   plus .v11-hero__glow (0,1,0, line 2957) and .v2x-hero__chips span (0,1,1, line
   2810). Every leg below carries html + body in front, so each wins on weight
   rather than on source order, and no !important is needed anywhere.
   ========================================================= */
html body .hero-anchor-r.v2x-hero { background: #0d0c1a; }

@media (min-width: 901px) {
  html body .hero-anchor-r.v2x-hero::after {
    background: linear-gradient(to left, rgba(11,10,26,.94) 0%, rgba(11,10,26,.6) 40%, transparent 68%),
                linear-gradient(to top, var(--bg) 4%, transparent 36%);
  }
}
@media (max-width: 900px) {
  html body .hero-anchor-r.v2x-hero::after {
    background: linear-gradient(to top, rgba(11,10,26,.97) 3%, rgba(11,10,26,.72) 42%, rgba(11,10,26,.34) 76%, transparent 100%);
  }
}
html body .hero-anchor-r .v11-hero__glow {
  background: radial-gradient(circle, rgba(150,120,255,.30), rgba(220,200,255,.10) 45%, transparent 70%);
}
html body .hero-anchor-r .v2x-hero__chips span { color: #9e9070; }

/* ===================== EDIT-V67 =====================
   MOBILE ONLY. The closed nav drawer goes fully off screen on the Persian and
   Arabic pages. Asked for as "منو کشویی در حالت بسته در زبان های فارسی و عربی
   دیده نشود، کامل بسته شود و بیرون برود".

   THE BUG IS ONE WRONG SIGN, and the reason it survived is that the sign looks
   right. Line 1844 anchors the panel with the LOGICAL property
   `inset-inline-end: 0`, so line 1850 hides it with `translateX(110%)` and line
   1853 "mirrors" that for RTL with `translateX(-110%)`. That mirroring would be
   correct if the panel's inline axis flipped on the RTL pages. It does not:
   measured, `.nav__links` computes `direction: ltr` on index-fa and index-ar as
   well as index, so `inset-inline-end` resolves to `right: 0` in ALL THREE
   languages and the panel is right-anchored everywhere. The negative transform
   therefore drags it LEFT, straight across the viewport.

   AND IT IS NOT A SMALL SLIVER — the amount left on screen grows with the
   viewport, because the travel is a percentage of the panel while the overshoot
   is not. Measured, closed drawer visible width, identical on fa and ar:
     375px   45px showing      (box -255..45)
     430px   78px showing      (box -242..78)
     700px  320px showing      (box   28..348)   the ENTIRE panel
     759px  320px showing      (box   87..407)   the ENTIRE panel
   English is correct at every width: 0px showing, box 405..705 at 375.
   So on a large phone or a small tablet the whole Persian menu panel simply sat
   on top of the page, which is also why the logo read "OCAL" — the panel covered
   the V.

   THE FIX IS TO STOP MIRRORING IT. Since the panel is right-anchored in every
   language, the closed state is the same in every language: translateX(110%).
   110% always clears it, because the travel is measured against its own width
   (`min(80vw, 320px)`), so it can never be less than the panel itself.

   THE DRAWER STILL COMES FROM THE RIGHT, which is correct and is not a
   regression: the burger sits at the top RIGHT on the RTL mobile pages, so a
   right-hand panel matches the control that opens it. Only the direction it
   hides in changes.

   GATED max-width: 760px, NOT 900px, and this matters. The panel is only
   `position: fixed` below 760 — measured, at 761px `.nav__links` is back to
   `position: relative; display: flex` as the horizontal nav row, and the burger
   is `display: none`. A 900px gate would have applied translateX(110%) to that
   horizontal row and pushed the whole menu off screen between 761 and 900. The
   gate matches line 1840, the breakpoint that creates the panel in the first
   place.

   SPECIFICITY, and the trap in it. Line 1853 is html[dir="rtl"] .nav .nav__links
   at 0,3,1; adding `body` gives 0,3,2, which clears it. It must NOT also clear
   line 1855, html[dir="rtl"] .nav .nav__links.is-open at 0,4,1 — that is the
   rule that opens the drawer. 0,3,2 has three class-level components against its
   four, so the open state still wins. This is also why `:not(.is-open)` is
   deliberately NOT used here: it would add a fourth class-level component, make
   this 0,4,2, and the drawer would never open again.

   DESKTOP IS UNTOUCHED BY CONSTRUCTION — the rule lives inside a max-width
   media query. Verified anyway at 1440/1200/1024: `.nav__links` stays
   position:relative with transform:none and identical geometry before and after.
   ========================================================= */
@media (max-width: 760px) {
  html[dir="rtl"] body .nav .nav__links { transform: translateX(110%); }
}

/* ===================== EDIT-V68 =====================
   MOBILE ONLY. V01 hero: the copy centres under the phone in all three languages,
   the way the English page already did it, and the phone above it loses its drop
   shadow. Asked for as "نوشته های هیرو در هر سه زبان به صورت وسط چین نوشته بشه زیر
   تصویر گوشی / در جایگاهی مانند مدل V01 در حالت انگلیسی / و روی تصویر گوشی که در
   بالای آن قرار گرفته، سایه وجود نداشته باشه".

   V01 IS THE ONLY PAGE THIS CAN MEAN, which is worth recording because the request
   named no page. Surveyed all fifteen pages that could carry a phone above the
   copy: only v01/-fa/-ar actually have a `.v11-hero__phone` element in the DOM, and
   line 2964 makes it `position: static; margin: 26px auto 0` below 880px, so it
   stands above the copy in flow. Everywhere else the hero art is a background or an
   absolutely-placed float. So "under the phone image" and "the phone image above
   it" both point here.

   MEASURED BEFORE, at 375px, title ink midpoint minus the section midpoint:
     v01     ltr  text-align center   0px   <- already right, the model
     v01-fa  rtl  text-align right  +119px
     v01-ar  rtl  text-align right   +48px
   and all three carried drop-shadow(0 50px 90px rgba(0,0,0,.55)) from line 2955.

   THE CAUSE IS A CLASS THAT ONLY THE TRANSLATED PAGES CARRY. The fa and ar markup
   has `class="v2x-hero__copy m2l hdr-align col-500"` where English has just
   `class="v2x-hero__copy hdr-align"`. `.v2x-hero__copy.m2l` declares
   `text-align: right !important` — twice, at lines 3360 and 3495 — so line 2966's
   `.v11-hero .v2x-hero__copy { text-align: center }` inside the 880px gate never
   had a chance. Removing `m2l` from the markup was rejected: it is what positions
   the copy on DESKTOP, and this round is mobile-only.

   `!important` IS UNAVOIDABLE HERE, and that is the whole reason it appears. The
   declaration being overridden is itself `!important` at 0,2,0, and no amount of
   specificity beats an important author declaration with a normal one. This block
   is 0,4,2 and important, so it wins on weight; it is not a shortcut past a
   specificity problem.

   TEXT-ALIGN ALONE WAS NOT ENOUGH, and only measuring above 700px showed it. Line
   3499 also pins every child of `.m2l` with `margin-right: auto !important;
   margin-left: 0 !important` under a `max-width: 640px`, and `col-500` narrows that
   to 500px (line 5159). Below about 530px the children fill the column so the pin
   is invisible; above it they do not. Measured with text-align only:
     375  0px    430  0px    700  0px    879  -67px   <- title, chips and cta all
   The chips and cta rows were already -66/-67 at 879 before any change, so this
   half fixes a fault that was there and unnoticed. With `margin-inline: auto` added
   the whole block is 0px off centre at 375 / 430 / 700 / 879 on both fa and ar.

   THE SHADOW IS DROPPED IN ALL THREE LANGUAGES, undirected, because the request
   named none and the three must stay identical. It is dropped ONLY below 880px:
   above that the phone sits beside the copy rather than above it, which is not what
   was described, and the round's rule forbids touching desktop anyway.

   GATED max-width: 880px, NOT 900px, and the difference is real. 880 is the
   breakpoint at line 2963 that makes the phone static and centres the English copy;
   V01 is still in its desktop arrangement from 881 to 900. Verified: at 881 and 900
   fa stays right-aligned with the title 183px and 173px off centre and keeps its
   shadow, before and after, identical.

   DESKTOP UNTOUCHED, measured rather than asserted. v01-fa at 1024/1440:
   align right, title -31px / -238px, shadow present, identical before and after.
   v01 at 1024/1440: align start, title -292px / -454px, shadow present, identical.
   English mobile is untouched too apart from the shadow: center and 0px off centre
   at 375, 700 and 879 both before and after.
   ========================================================= */
@media (max-width: 880px) {
  html[dir="rtl"] body .v01-hero .v2x-hero__copy.m2l { text-align: center !important; }
  html[dir="rtl"] body .v01-hero .v2x-hero__copy.m2l > *,
  html[dir="rtl"] body .v01-hero .v2x-hero__copy.m2l > p { margin-inline: auto !important; }
  html body .v01-hero .v11-hero__phone { filter: none; }
}

/* ===================== EDIT-V69 =====================
   MOBILE ONLY. Every model hero centres its copy, in all three languages, the way
   V01 does. Asked for as "مدل وسط چین را در همه ی مدل ها در هیرو و در همه ی زبان ها
   در همان پوزیشن V01 اعمال کن", after EDIT-V68 did V01 alone and the survey showed
   the same fault on the other eleven models.

   THIS IS NOT A NEW DESIGN — IT IS AN EXISTING ONE THAT NEVER RENDERED. Line 2793,
   `.v2x-hero__copy { text-align: center }`, sits inside @media (max-width: 900px):
   the sheet has always intended a centred hero on phones, on every page. Three
   UNGATED rules defeat it, and this block is what finally lets it through. The
   third sighting of this pattern in one session, after the dead mobile scrim at
   line 2792 and the V01 case in EDIT-V68.

   WHAT WAS DEFEATING IT, all three ungated so they leak into the mobile range:
     3281  html[dir="rtl"] .v2x-hero .v2x-hero__copy   { text-align: right }   0,3,1
           -> every Persian and Arabic page
     3269  .hero-side-right .v2x-hero__copy            { text-align: left }    0,2,0
           -> v2 and v2-lite in ENGLISH, which is why those two were the odd ones
     3360/3495  .v2x-hero__copy.m2l  { text-align: right !important }          0,2,0
           -> v1 and v01 in fa/ar, with the m2r mirror covering most of the rest
   Plus the child pinning at 3499, `.m2l > * { margin-right: auto !important;
   margin-left: 0 !important }` and its m2r twin, which holds the blocks against one
   edge even once the text is centred — the same trap EDIT-V68 hit at 879px.

   MEASURED BEFORE, at 375px, title ink midpoint minus the section midpoint:
     model     English      Persian        hero copy modifier (fa)
     v2-pro    center   0   right   +81    m2r
     v2        left   -64   right   +79    (bare; English has copy-flush-r)
     v2-lite   left   -61   right   +92    m2r
     v11       center   0   right  +119    m2r
     v1        center   0   right   +79    m2l + copy-hug
     v1-core   center   0   right   +81    m2r
     v0        center   0   right  +105    m2r
     v0-core   center   0   right   +82    (bare; English has copy-flush-r)
     v01       center   0   center    0    m2l + col-500  (already done, EDIT-V68)
     f1        center   0   right   +49    m2r
     f2        center   0   right   +89    m2r
     f4        center   0   right   +93    m2r
   Note v2 and v2-lite: English itself was LEFT, not centred. "All languages" was
   explicit, so those two English pages move to centre as well.

   FOUR PROPERTIES, because centring text is not enough on its own: `text-align` on
   the copy, `margin-inline` on its children to release the m2l/m2r pinning, and
   `justify-content` on the chips and cta rows so the whole block reads as one
   centred column. Verified on the hardest combinations — v1-fa (m2l + copy-hug),
   v01-fa (m2l + col-500), v2-lite-fa (m2r), v2 (English copy-flush-r), v2-pro-fa
   (m2r + hero-side-left), v11-fa (m2r + hero-anchor-r), v0-core (English) — all
   land on 0 for title, chips and cta.

   `!important` IS FORCED, not chosen. Two of the declarations being overridden are
   themselves `!important` (3495 and 3499), and no specificity beats an important
   author declaration with a normal one. The selectors are 0,2,2 and 0,3,2, which
   clears the 0,2,0 important pair on weight; the RTL leg needs its own attribute
   selector to clear line 3281's 0,3,1.

   GATED max-width: 900px, matching line 2793's own gate — the breakpoint that
   declared this intent in the first place. Verified at the boundary: v11-fa centres
   at 881 and 900 (title +319 and +325 -> 0) and is IDENTICAL at 901 (right, +326)
   and 1440 (right, +529). Desktop cannot be reached from inside a max-width query.

   EDIT-V68 STAYS. It is gated at 880 and overlaps this harmlessly with the same
   value; it also carries the V01 phone drop-shadow removal, which is not repeated
   here because no other model has a phone standing above its copy.
   ========================================================= */
@media (max-width: 900px) {
  html body .v2x-hero .v2x-hero__copy,
  html[dir="rtl"] body .v2x-hero .v2x-hero__copy { text-align: center !important; }

  html body .v2x-hero .v2x-hero__copy > *,
  html body .v2x-hero .v2x-hero__copy > p,
  html[dir="rtl"] body .v2x-hero .v2x-hero__copy > *,
  html[dir="rtl"] body .v2x-hero .v2x-hero__copy > p { margin-inline: auto !important; }

  html body .v2x-hero .v2x-hero__chips,
  html body .v2x-hero .v2x-hero__cta { justify-content: center !important; }
}

/* ===================== EDIT-V70 =====================
   MOBILE ONLY. Every model hero drops its title block to the bottom of the first
   screen, so the model name and its two lines are what you land on and the buttons
   and spec boxes need a scroll — the arrangement V01 already had in English. Asked
   for as "اسم مدل و عبارت زیرش و عبارت زیر ترش در پایین صفحه نمایش داده بشه (دقیقا
   مثل مدل V01 در انگلیسی) و بقیه محتواهای هیرو و باکس ها با اسکرول دیده بشه".

   WHAT V01 ACTUALLY DOES, measured at 375x812, because the mechanism is not obvious:
     phone   158..557   in flow (line 2964 makes it static, 399px + 26px margin)
     title   557..699   -> ends at 86% of the fold
     cta     716..842   -> straddles the fold
     chips   876..1004  -> entirely below it
     section height 1163, i.e. 351px TALLER than the viewport
   Nothing positions the copy low. The copy is simply pushed there by the phone
   standing above it in the grid, and the section grows past its own
   `min-height: 100svh` to fit.

   THE OTHER ELEVEN MODELS HAD NOTHING IN FLOW, so their section was exactly 812 —
   the whole hero fitted the first screen with room to spare:
     English   title 205..347   cta 364   chips end 652
     fa / ar   title 275..417   cta 434   chips end 652
   Line 2791's `align-items: end` was bottom-pinning the copy inside a box the copy
   did not fill, which is why the copy floated mid-screen instead of low.

   AND THAT 70px ENGLISH/PERSIAN GAP HAD A CAUSE WORTH KNOWING. Bottom-pinning
   positions the copy by its own height, and the English CTA wraps to two lines
   (126px tall against 56px in fa/ar), so the English copy was 70px taller and
   therefore started 70px higher. Setting an explicit padding-top removes the
   dependency on content height entirely: the title now starts at the same y in all
   three languages, which is the point of the request.

   THE VALUE IS DERIVED, NOT TUNED. Title bottom = section padding-top (132px at
   this breakpoint) + copy padding-top + title height. The title measures 142px on
   ALL THIRTY-SIX pages at 375px wide — checked, not assumed, since it is always the
   wordmark plus two masked lines. Solving for a title bottom at 86% of the viewport,
   which is where V01 puts it:
     copy padding-top = 86svh - 274px
   Measured after, title bottom as a share of the fold:
     375x812  698 (86%)   375x667  574 (86%)   390x844  726 (86%)   430x932  809 (87%)
   svh, not vh, so a mobile browser's collapsing toolbar cannot push the title out of
   view; line 2791 already uses svh for the same reason.

   V01 IS EXCLUDED, because the phone image already does this for it — adding the
   padding there would push its copy a second screen down.

   ONE THING FOUND ON THE WAY, worth deciding separately: V01's own spacer is a
   FIXED-height image, so it does not scale with the viewport. At 375x667 its title
   bottom sits at 699, which is 105% of the fold — on a short phone V01 hides the
   very text this request is about. The formula above does not have that failure mode
   (86% at every height tested). Applying it to V01 as well would need the phone
   made absolute again on mobile, which is a change to the page being used as the
   reference, so it was not done unasked.

   SPECIFICITY. `padding-top` on the hero copy is not otherwise declared in the
   mobile range, so 0,2,2 would have been enough; `!important` is there because
   line 2793's block sets `padding-bottom` on the same selector and a future edit
   adding `padding` shorthand there would silently win. Gated max-width: 900px, the
   same gate as line 2791 and 2793 which own this layout.

   DESKTOP UNTOUCHED, measured: v2-pro-fa and v11 at 901/1024/1440 keep
   padding-top 0px, the same section height (812/900/900) and the same title bottom
   (464/517/537) before and after. No horizontal overflow at any width.
   ========================================================= */
@media (max-width: 900px) {
  html body .v2x-hero:not(.v01-hero) .v2x-hero__copy {
    padding-top: calc(86svh - 274px) !important;
  }
}

/* ===================== EDIT-V71 =====================
   MOBILE ONLY. The two hero buttons sit side by side on one row, in every model and
   every language, the way the Persian V11 page already did. Asked for as "دو تا باکس
   زیر سه عبارت اول، در همه ی هیروها در همه مدل و همه زبانها مانند صفحه V11 فارسی
   شده، به صورت افقی و چپ و راست کنار هم قرار بگیره".

   IT WAS ALWAYS MEANT TO BE ONE ROW — the row simply did not fit in English. The
   container is `display: flex; flex-wrap: wrap; gap: 14px; justify-content: center`
   and it measures 330px at a 375px viewport (375 less the copy's 6vw each side).
   Measured pair widths at 375:
     Persian   141 + 149 = 290  + 14 gap = 304  <= 330   one row
     Arabic    132 + 127 = 259  + 14     = 273  <= 330   one row
     English   148 + 174 = 322  + 14     = 336  >  330   WRAPS, by six pixels
     f2 / f4   174 + 174 = 348  + 14     = 362  >  330   wraps, by thirty-two
   So ten of the twelve English pages were losing the row to a 6px overshoot, and
   the two with a longer first label ("Discover more") to 32px. The buttons carry
   `padding-inline: 30px`, a 1px border and `white-space: nowrap` at 15px, so the
   English labels — "Specifications" is 174px wide — simply cannot pair inside 330
   at that padding.

   SOMETHING HAD TO GET SMALLER, and the padding is the right thing. `flex-wrap:
   nowrap` alone would not have worked: the items have `flex-shrink: 1` but their
   text is `white-space: nowrap`, so they would shrink and the labels would spill
   out of the pills. Reducing the padding shrinks the box WITH its content.
     flex-wrap: nowrap        so the row can never break again
     gap: 14px -> 12px
     padding-inline: clamp(12px, 5.2vw, 30px)
   Measured after, every English page goes from two rows at 126px tall to ONE row at
   56px — exactly the height the Persian reference already had. Pair vs container:
     f2 en    306 + 12 vs 330 at 375   294 + 12 vs 306 at 320   316 + 12 vs 378 at 430
     v11 en   280 + 12 vs 330          268 + 12 vs 282          291 + 12 vs 378
   Checked at 320px because that is where it is tightest; a flat 18px padding was
   tried first and overflowed there on f2 by one pixel, which is why the value is a
   clamp and not a constant.

   THE PERSIAN AND ARABIC BUTTONS DO GET A LITTLE NARROWER, and that is a deliberate
   trade, not an oversight: v11-fa's pair goes 290 -> 248 at 375. The padding has to
   be uniform because the three languages must stay identical — that rule outranks
   holding the reference page at exactly its old pill width, and the arrangement the
   request asked for is preserved in all three.

   THE CLAMP REACHES ITS 30px CAP AT 577px WIDE, so from 577 up to the 900px gate the
   buttons keep their normal padding and the pair fits with room to spare (676px of
   container at 768). Only the narrow end is touched.

   SPECIFICITY. The declarations being replaced are on `.v2x-hero__cta` and `.btn`
   at 0,1,0; these selectors are 0,2,2 and 0,3,2. `!important` is not strictly needed
   and is used only because line 2794 sets `justify-content` on the same element
   inside this same media range, where a future `flex` shorthand would silently win.
   Gated max-width: 900px.

   DESKTOP UNTOUCHED, measured: f2 and v11-fa at 901/1024/1440 keep flex-wrap: wrap,
   gap 14px and pair widths 348 and 290, identical before and after.
   ========================================================= */
@media (max-width: 900px) {
  html body .v2x-hero .v2x-hero__cta {
    flex-wrap: nowrap !important;
    gap: 12px !important;
  }
  html body .v2x-hero .v2x-hero__cta > .btn {
    padding-inline: clamp(12px, 5.2vw, 30px) !important;
  }
}

/* ===================== EDIT-V72 =====================
   MOBILE ONLY. Closes a twenty-pixel seam at 881-900 on the three V01 pages, where the
   hero used the MOBILE centred copy together with the DESKTOP phone placement, so the
   title and both buttons landed on the bright phone render and stopped being readable.

   NOT REQUESTED - FOUND. An adversarial audit of EDIT-V67..V71 went looking for a way the
   mobile work could reach desktop. It found no desktop leak, but it did find this, and the
   screenshots confirmed it: at 890 the V01 title and CTA sit over the phone; at 875 they
   sit cleanly below it.

   MY OWN NOTE AT LINE 7892 IS NOW WRONG and this block supersedes it. EDIT-V68 asserted
   "V01 is still in its desktop arrangement from 881 to 900 ... fa stays right-aligned with
   the title 183px and 173px off centre". That was TRUE when V68 shipped. EDIT-V69 then
   centred every hero copy under a max-width:900px gate and silently invalidated it, and
   V69's own claim that V68 "overlaps this harmlessly with the same value" is wrong too:
   across 881-900 the two do not overlap at all. Lesson worth keeping: a verification note
   is only true as of its own round, and a later round with a WIDER gate can falsify it.

   MEASURED, v01-fa, before this block:
     875   phone static    255,158 380x518   title 125,676   title 0%   button 0%    correct
     881   phone absolute  380,180 348x475   title 128,302   title 54%  button 100%
     890   phone absolute  384,178 352x480   title 133,301   title 55%  button 100%
     899   phone absolute  388,176 356x484   title 137,299   title 56%  button 100%
     901   phone absolute  389,176 356x486   title  69,269   title 36%  button 100%  desktop, intended
   The 901 row overlaps too, but that is the deliberate desktop arrangement where the copy
   is off to the side and the phone's transparent margin covers most of the box. The defect
   is the 875 -> 881 DISCONTINUITY: 0% jumping to 100%.

   WHY THE SEAM EXISTS - three gates that disagree:
     line 2963  @media (max-width: 880px)   phone -> position:static, stacked, glow hidden
     line 7393  @media (min-width: 881px)   holds the phone in its desktop absolute spot
     line 7904  @media (max-width: 880px)   EDIT-V68's filter:none
     EDIT-V69   @media (max-width: 900px)   centres the copy
   881-900 therefore gets V69's centring with none of the 880 mobile treatment.

   THE FIX is to make 881-900 behave exactly like <=880 for this hero, since by the site's
   own definition (min-width: 901px, 49 blocks) everything at 900 and below IS mobile. That
   keeps the band inside the mobile-only rule rather than reaching over it.

   !important IS REQUIRED HERE, on purpose, twice over. EDIT-V62 at line 7393 selects
   `html body .v01-hero .v11-hero__phone.v01-hero-big` = 0,3,2, higher than this block's
   0,2,2, so source order alone would NOT win the width and right contest. And GSAP writes
   `transform` as an inline style at runtime, which only !important can outrank.

   The other 33 model pages were checked for the same discontinuity and none has it. v0,
   v0-core, v2-pro and the F series read 100% overlap on BOTH sides of 880 - that is their
   intended full-bleed hero art behind a darkening scrim, continuous and fine.

   Gated (min-width: 881px) and (max-width: 900px): both bounds at or below 900, so desktop
   cannot see it. Verified at 901/1024/1440 that nothing moves.
   ========================================================= */
@media (min-width: 881px) and (max-width: 900px) {
  html body .v01-hero .v11-hero__phone {
    position: static !important;
    transform: none !important;
    width: min(380px, 78%) !important;
    margin: 26px auto 0 !important;
    display: block !important;
    inset: auto !important;
    filter: none !important;
  }
  html body .v01-hero .v11-hero__glow { display: none !important; }
}

/* ===================== EDIT-V73 =====================
   MOBILE ONLY. V2 PRO hero: the phone render moves ABOVE the copy instead of sitting
   behind it, and the shadow comes off it. All three languages. Asked for as
   "تصویر گوشی ها به بالای نوشته ها بیاد و سایه از روی تصویر موبایل برداشته بشه".

   THERE WERE TWO DIFFERENT SHADOWS and only one of them was the obvious one:
     1. `filter: drop-shadow(0 40px 80px rgba(0,0,0,.66))` ON the image (line 3395).
     2. `.v2x-hero::after` at line 2792, the mobile scrim, painting a dark wash OVER it.
   The second is the one that actually made the render look murky, and the reason is a
   z-index TIE: the art is `z-index: -1` (line 3394) and the scrim is `z-index: -1`
   (line 2715). Equal z-index inside the hero's own stacking context
   (`isolation: isolate`, line 2871) means paint order falls to DOM order, and `::after`
   is generated last - so the scrim always painted on top of the phone. Both are removed.

   RAISING THE ART OUT OF THE SCRIM IS SAFE ONLY BECAUSE IT ALSO MOVED. `z-index: 1`
   puts the art above the scrim, but it also puts it above `.v2x-hero__copy`, which is a
   non-positioned in-flow element with `z-index: auto` on this page (line 2721; the
   `z-index: 2` at line 2951 is scoped to `.v11-hero` and does NOT reach v2-pro). That
   would normally cover the text. It does not here because the art no longer overlaps the
   text at all - it only overlaps the copy's empty top PADDING. So the geometry change is
   what makes the stacking change safe; neither is correct without the other.

   THE BAND IS EXACTLY THE COPY'S OWN PADDING-TOP, which is the neat part. The hero is
   `display: grid` with `padding-top: clamp(132px, 15vh, 168px)` (line 2713 - note that
   line 2734's smaller padding is gated `min-width: 901px and max-height: 780px`, i.e.
   narrow-height DESKTOP, not mobile). EDIT-V70 then sets the copy's
   `padding-top: calc(86svh - 274px)`. So the vertical gap between the nav zone and the
   title is precisely `86svh - 274px`, independent of the hero padding. Verified:
     375x812  copyPadTop 424.32  title top in hero 556  hero padding 132  -> 556-132 = 424
     375x667  copyPadTop 299.62  title top 432         hero padding 132  -> 300
     430x932  copyPadTop 527.52  title top 667         hero padding 140  -> 527
     320x568  copyPadTop 214.48  title top 346         hero padding 132  -> 214
   The art therefore gets a box spanning that band minus a 24px gap, plus
   `object-fit: contain`, which centres the render inside it at every size. No aspect
   arithmetic and no per-breakpoint fitting: contain does it.

   BEFORE, the art overlapped the title by 117 to 200px at every size measured
   (375x812 -138, 375x667 -186, 430x932 -117, 320x568 -200). AFTER, the gap is positive
   everywhere: +77 at 375x812, +24 at 320x568, +105 at 430x932.

   ON NORMAL PHONES THE RENDER DOES NOT GET SMALLER. At 375x812 the width cap still
   binds and it stays 341x295, exactly as before; at 430x932 it stays 393x340. Only short
   screens shrink it, which is unavoidable if it has to fit above the text: 320x568 goes
   from 289x250 to 220x190.

   HEIGHT-GATED AT 540px, on purpose. `calc(86svh - 298px)` collapses on a landscape
   phone - at 375px of viewport height it computes to 24px and the render would nearly
   vanish. 540px is chosen to sit below the shortest real PORTRAIT phone (320x568, which
   still gets a 190px band) while excluding landscape. Under 540px tall nothing changes:
   the art keeps its old centred placement AND its old shadows, because `z-index: 1`
   without the repositioning would cover the text. If landscape needs its own answer it
   is a separate change.

   The art is also centred horizontally now rather than offset 5vw to one side. That is
   deliberate: the mobile copy is centred (EDIT-V69), and it makes English identical to
   fa/ar here, where they previously differed by 4px because the English section carries
   `hero-side-left` and fa/ar do not.

   The float animation is KEPT, not dropped - the old keyframes bake `translateY(-50%)`
   into themselves to pair with `top: 50%`, so with a real `top` they would throw the
   render half its height upward. v2proFloatM is the same 8s motion without the centring
   offset. GSAP does not touch this element (checked script.js), so no !important is
   needed for transform.

   SPECIFICITY. `html body .v2pro-phones` is 0,2,2, which beats the base `.v2pro-phones`
   (0,1,0, line 3391) and `html[dir="rtl"] .v2pro-phones` (0,2,1, line 3398) - one more
   type selector at equal class count, the same arithmetic EDIT-V63 documents at line
   7456. EDIT-V63's own mobile height rule is also 0,2,2, so this block wins it on source
   order by being appended. The 6vw side rules from EDIT-V63 are inside
   `min-width: 901px` and never apply here.

   A REPLACED ELEMENT IGNORES AN OVER-CONSTRAINED left/right PAIR. The first version of
   this block used `left`+`right`+`width: auto` to centre the box, which works for a div
   but NOT for an <img>: per the absolutely-positioned replaced-element rules, `width:
   auto` resolves to the INTRINSIC width and `right` is then dropped. The global
   `img { max-width: 100% }` capped that at the container, so the render silently grew
   from 341px to the full 375px viewport width. Measurement caught it. The fix is an
   explicit width plus `left: 0; right: 0; margin-inline: auto`, which is the standard
   way to centre an absolutely positioned box of known width.

   WIDTH IS THE DRIVEN AXIS, height auto, so the file's real aspect ratio applies rather
   than a hard-coded one. Measured intrinsic ratio is 1.15711 (341 / 294.703); EDIT-V63
   approximated it as .8636, i.e. 1.15794, which is slightly WRONG in the unsafe
   direction. The multiplier here is a deliberately conservative 1.15, so the resulting
   height is at most band x 0.994 and the 36px gap can never be eaten by rounding.

   DESKTOP UNTOUCHED: gated max-width 900px. Verified at 901/1024/1440/1920.
   ========================================================= */
@media (max-width: 900px) and (min-height: 540px) {
  html body .v2pro-phones {
    /* SIT THE RENDER AT THE BOTTOM OF THE BAND, just above the title. The first pass
       top-aligned it and the user's verdict was "خیلی بالا رفت / میخوام کمی بالاتر از
       نوشته ها باشه" - it had glued itself under the nav with a 118px hole between it
       and the text at 375x812.

       The trick that avoids all height arithmetic: give the box the WHOLE band as its
       height, set an explicit width, and let `object-fit: contain` +
       `object-position: bottom` park the render against the bottom edge. The gap to the
       title then comes out at a constant ~28px at every viewport size without a single
       per-breakpoint value.

       This only works because BOTH axes are explicit. With `height` set and
       `width: auto`, the global `img { max-width: 100% }` recomputes the height to keep
       the intrinsic ratio, the box collapses onto the image, and contain has no slack
       left to position within - which is the same squash trap recorded for the
       height-sized heroes. An explicit width keeps the box taller than the image, and
       that slack is what object-position consumes. */
    top: clamp(132px, 15vh, 168px);
    bottom: auto;
    width: min(95vw - 15px, calc((86svh - 302px) * 1.15));
    height: calc(86svh - 302px);
    object-fit: contain;
    object-position: bottom;
    z-index: 1;
    filter: none;
    animation: v2proFloatM 8s ease-in-out infinite;
  }
  /* left/right need the DIRECTION-SPECIFIC form. A bare `html body .v2pro-phones` is
     0,1,2 - two type selectors, one class - and LOSES to `html[dir="rtl"] .v2pro-phones`
     at line 3398, which is 0,2,1 because an attribute selector counts at class weight.
     Class count is compared FIRST, so 2 beats 1: Persian and Arabic kept their old
     `left: 5vw` while English centred correctly, and the three languages diverged.
     EDIT-V63 documents this exact trap at line 7457 and I walked into it anyway - the
     measurement caught it, not the reading. One extra type selector on each side brings
     both branches to 0,2,2, which wins on type count at equal class count. This is the
     same selector shape EDIT-V63 uses for its own 6vw side rules. */
  html:not([dir="rtl"]) body .v2pro-phones,
  html[dir="rtl"] body .v2pro-phones {
    left: 0;
    right: 0;
    margin-inline: auto;
  }
}
@keyframes v2proFloatM {
  0%, 100% { transform: none; }
  50% { transform: translateY(-14px); }
}

/* ===================== EDIT-V74 =====================
   MOBILE ONLY. Two fixes for the V2 hero, both found while reviewing that model's image.
   v2.html, v2-fa.html, v2-ar.html for the crop; eight pages for the scrim.

   1. THE PHOTO WAS BEING CROPPED ONTO A THUMB. v2-hero.webp is a 2880x1620 LANDSCAPE
      photograph (ratio 1.778). The mobile hero box is 403x1224 (ratio 0.329), so
      `object-fit: cover` with the default `object-position: 50% 50%` keeps a vertical
      strip just 18.5% of the file's width, taken from the dead centre. Measured column
      profile of the source: the phone is the bright mass at 16-36% (luma 64-71), the
      hand is at 40-52%, and past 56% the frame falls away to black (luma 33 -> 4.5).
      The 18.5% window landed on 40-59% - the hand. The phone was almost entirely outside
      the mobile hero.

      Fixed with a purpose-built portrait crop served ONLY to mobile through
      `<source media="(max-width: 900px)">`, so desktop keeps the original file and no
      browser downloads both. The crop takes source x 12-43%, then extends the plain
      background vertically to reach a 0.40 ratio. Visible range becomes 14.8-40.3% of
      the source, which contains the whole phone.

      IT IS ALSO SHARPER AND SMALLER. Today the mobile hero upscales the source 1.51x at
      DPR 2; the new file upscales 1.10x. And at q0.84 it is 63,654 bytes against the
      88,198-byte original, so mobile downloads LESS than before, not more. Worst 32x32
      block PSNR at true display size is 37.6 dB.

      THE SOURCE FILE HAS A BAD TOP ROW and it cost two attempts to find. Row 0 reads
      (85, 100.5, 84.7) while rows 10-210 sit flat at (62.6, 77.9, 62.3) - about 22 units
      brighter, an encode artefact. The first extensions filled the added band from row 0
      and produced a visible horizontal seam. Trimming the top 12 rows and filling from
      row 12 takes the seam to 0.05/255 at the top join and 0 at the bottom; the largest
      row-to-row step left anywhere in the file is 12.5, which is the phone's own edge.
      LESSON: before extending an image's background, check its first and last rows for
      edge artefacts - do not assume row 0 is representative.

   2. THE MOBILE SCRIM WAS HORIZONTAL ON EIGHT PAGES. Line 2792 defines the vertical
      bottom-up wash every mobile hero is supposed to use, but EDIT-V64's
      `html[dir="rtl"] body .hero-side-right.v2x-hero::after` is 0,3,3 and UNGATED, so it
      beat line 2792's 0,1,1 on mobile too and painted a left-to-right wash designed for
      the desktop side-by-side layout. The bottom of the frame was never darkened, so the
      buttons and the spec chips sat directly on the photograph.

      This is the "dead mobile scrim" logged earlier. The eight pages are v2, v2-fa,
      v2-ar, v2-lite, v2-lite-fa, v2-lite-ar, v0-core-fa and v0-core-ar. Note v2-pro is
      NOT among them - its section is a bare .v2x-hero (fa/ar) or .hero-side-left (en) -
      which is why its mobile scrim was already correct. v11 is not among them either;
      EDIT-V66 already gave .hero-anchor-r its own mobile vertical scrim.

      The selectors below are EDIT-V64's own, so specificity ties at 0,3,3 and this wins
      on source order, inside a max-width: 900px gate. Desktop keeps EDIT-V64's lighter
      horizontal wash untouched. The values are line 2792's, so all mobile heroes now
      match each other rather than each carrying a private variant.

   DESKTOP UNTOUCHED: the scrim block is gated, and the crop reaches desktop only through
   a `max-width: 900px` <source>, which a desktop browser never selects.
   ========================================================= */
/* THE WRAPPER RULE IS UNGATED ON PURPOSE, and it is what keeps desktop identical rather
   than what changes it. Wrapping the hero <img> in <picture> makes the picture an inline
   grid item; with no rule its empty line box pushes the copy DOWN on desktop - measured
   copyTop 277 -> 348 at 1440 and 307 -> 394 at 901. Taking it out of flow restores the
   pre-change geometry exactly.

   `pointer-events: none` was in the first draft, copied from the v0-core and v11 wrappers,
   and it is DELIBERATELY LEFT OUT here. A path-keyed A/B of (old markup + old sheet)
   against (new markup + new sheet) over all 485 computed properties at six desktop widths
   found exactly one differing property on one element, and it was this one, inherited onto
   the image. Testing whether it earns that: hero height, copy position, image rect and
   hit-testing of the CTA are identical with and without it at 1440, 901 and 375 - the
   button stays reachable either way because .btn wins hit-testing over the wrapper anyway.
   Since it buys nothing here and dropping it makes the desktop delta exactly ZERO
   properties, it is dropped. The v0-core and v11 wrappers keep theirs; they are not
   touched. */
html body .v2-bgpic { position: absolute; inset: 0; }

@media (max-width: 900px) {
  html:not([dir="rtl"]) body .hero-side-right.v2x-hero::after,
  html[dir="rtl"] body .hero-side-right.v2x-hero::after {
    background: linear-gradient(to top, rgba(8, 6, 4, .97) 3%, rgba(8, 6, 4, .72) 42%, rgba(8, 6, 4, .34) 76%, transparent 100%);
  }
}

/* ===================== EDIT-V75 =====================
   MOBILE ONLY. V2 LITE hero: a purpose-built portrait crop for mobile, same treatment
   V2 got in EDIT-V74. v2-lite.html, v2-lite-fa.html, v2-lite-ar.html.

   SAME TRAP, WORSE NUMBERS. assets/edit/v2lite-hero.webp is 1920x1080 landscape in a
   403x1224 portrait box, so cover kept 18.5% of the width from dead centre - source
   40.7% to 59.3%, which is the phone's bottom corner and the thumb. The camera module,
   the only real focal point in the shot, sits at 9-34% and was entirely outside the
   frame. And because this file is 1920 wide rather than 2880, the mobile hero was
   upscaling it 2.27x at DPR 2 - visibly soft on a phone. New crop: source 7.2%-36.8%
   visible, upscale down to 1.42x, 54,392 bytes against the desktop file's 101,690.

   TWO FILES SHARE THE NAME v2lite-hero.webp and I analysed the wrong one first:
   assets/v2lite-hero.webp is 2880x1620 while assets/edit/v2lite-hero.webp - the one the
   pages actually load - is 1920x1080. LESSON: read the markup for the exact asset path
   before profiling an image; do not match on filename.

   THE BIGGER FILE IS A DIFFERENT SHOT, NOT A LARGER COPY. Luma correlation between the
   two, measured on matched 320x180 downscales, is 0.716 with a mean absolute difference
   of 11.1 - same subject and similar composition, different exposure and framing. A crop
   from it would have been genuinely sharp (0.90x, no upscaling at all) and it was offered
   as an option, but it was declined in favour of keeping mobile and desktop showing THE
   SAME PHOTOGRAPH, which is the same principle EDIT-V74 followed for V2.

   No edge-row artefact in this file (row 0 reads 66.7,66.5,68 against row 4 at
   66.7,66.4,67.9), unlike v2-hero.webp whose bright row 0 cost two attempts in V74. The
   check is cheap and worth repeating per image rather than assuming.

   .hero-bgpic IS A GENERIC STRUCTURAL HOOK, deliberately, and every model from here on
   uses it. The three wrappers already live carry per-model names - .v0c-bgpic (EDIT-V60),
   .v11-bgpic (EDIT-V65), .v2-bgpic (EDIT-V74) - which would mean a new near-identical
   rule for each of the ten remaining models. Those three are left exactly as they are;
   nothing about them changes.

   UNGATED, and as EDIT-V74 established that is what keeps desktop identical rather than
   what changes it: wrapping the <img> in <picture> makes the picture an inline grid item
   whose empty line box pushes the copy down on desktop if it stays in flow - measured at
   71-87px on the V2 pages. `pointer-events` is deliberately omitted for the same reason
   as V74: it made no measurable difference to geometry or hit-testing, and leaving it out
   keeps the desktop delta at exactly zero properties.

   DESKTOP UNTOUCHED: the crop reaches the page only through a max-width: 900px <source>,
   which a desktop browser never selects, and the wrapper rule restores the pre-change
   geometry exactly. Verified with a path-keyed A/B over all 485 computed properties.
   ========================================================= */
html body .hero-bgpic { position: absolute; inset: 0; }

/* ===================== EDIT-V76 =====================
   MOBILE ONLY. V2 LITE: the render sits higher in the frame, and the dark wash comes off
   it completely. Asked for as "تصویر را کمی بالا ببر و سایه را از روی عکس موبایل حذف کن".

   THE TWO REQUESTS TURNED OUT TO BE ONE CHANGE, and only measurement showed it. Unlike
   V2 Pro, this hero's image is FULL-BLEED - it sits behind the copy as well as above it -
   so removing the scrim puts the title straight onto the photograph. Measured worst-case
   contrast for the title against the brightest pixel under its box:

     lift   0px, no scrim   1.14   FAIL (needs 3.0 for 48px text)
     lift 123px, no scrim   2.03   FAIL
     lift 187px, no scrim   6.60   PASS
     lift 230px, no scrim  13.55   PASS
     for reference, today WITH the scrim: 9.30

   So the lift is not cosmetic - it is what makes removing the scrim legal. At 187px the
   bright phone-and-hand mass clears the title band entirely and the title lands on plain
   dark background. BAKING A DARK BASE INTO THE IMAGE INSTEAD WAS TRIED AND REJECTED: at
   lift 123 it moved the title only from 2.03 to 2.59 even at alpha 0.9, because the
   problem is the bright subject sitting under the text, not the overall level. Geometry
   fixed it; opacity could not.

   Every other text run passes with NO scrim at all, at the real display size:
     title 48px    6.60   needs 3.0
     subline 27px 17.42   needs 3.0
     btn--line     17.76  needs 4.5
     chip value   14.08   needs 4.5
     chip label    6.68   needs 4.5
   The solid CTA measured 1.13 and that is a FALSE READING, checked and dismissed: it
   carries its own opaque gold gradient with dark text (rgb(26,18,8)), so its legibility
   does not depend on the photo at all.

   The lift is done in the CROP, not in CSS, because there is no vertical slack to move:
   the crop's 0.40 ratio against the 403x1224 box makes the HEIGHT fit exactly and the
   width the cropped axis, so object-position's Y has nothing to travel. Moving the top
   gap from 324 to 60 (bottom 324 -> 600) lifts the subject 187 CSS px.

   SCOPED WITH A NEW CLASS BECAUSE THERE WAS NO OTHER HOOK. v2-lite and v2 heroes carry
   the identical `class="v2x-hero hero-side-right"`, so the eight-page scrim rule from
   EDIT-V74 cannot be narrowed by selector alone - .v2lite-hero is added to the three
   v2-lite sections. The two branches below match EDIT-V74's own selector shape so
   specificity ties at 0,3,3 and this wins on source order; a plain
   `html body .v2lite-hero.v2x-hero::after` would be 0,2,3 and would LOSE.

   V2, v0-core-fa and v0-core-ar keep the vertical scrim EDIT-V74 gave them. Only V2 Lite
   loses it, because only V2 Lite has a crop lifted far enough to survive without it.

   DESKTOP UNTOUCHED: gated max-width 900px, and the crop reaches the page only through a
   max-width: 900px <source>.
   ========================================================= */
@media (max-width: 900px) {
  html:not([dir="rtl"]) body .v2lite-hero.v2x-hero::after,
  html[dir="rtl"] body .v2lite-hero.v2x-hero::after {
    background: none;
  }
}

/* ===================== EDIT-V77 =====================
   MOBILE ONLY. V11 hero: mobile now shows the same floating portrait render desktop
   shows, above the copy, instead of a panoramic photo cropped to a sliver.
   v11.html, v11-fa.html, v11-ar.html.

   THE WORST CROP OF THE THREE MODELS SO FAR. assets/edit/v11-hero.webp is 2200x1006,
   ratio 2.187 - a panorama - and the mobile box is 403x1224 at 0.329, so cover kept
   84.9% off the width and showed only source 42.5%-57.5%. The two phones sit at
   12.7%-46.6%, so BOTH were outside the frame; what a phone actually displayed was the
   skateboarder's arm and empty grey background. Upscale was 2.43x at DPR 2.

   NO NEW FILE WAS NEEDED. EDIT-V65 already ships a portrait cutout for desktop -
   v11-hero-float.webp, 1319x1531, and it is a genuine alpha cutout (minimum alpha 0,
   28% of sampled pixels fully transparent). Reusing it means mobile and desktop show the
   same artwork, nothing extra downloads, and at 331px wide the render is scaled to 0.52x
   at DPR 2, i.e. DOWNSCALED - sharper than anything a crop of the panorama could give.

   A PORTRAIT CROP WAS BUILT AND MEASURED AND LOST, which is worth recording so it is not
   re-proposed. Title contrast at the worst pixel under its box, scrim included:
     today, panorama cropped to a sliver   4.25
     purpose-built portrait crop           4.26
     this float render                    16.47
   The crop gained NOTHING on legibility, because the panorama's background is near-white
   (its top row reads 220,243,245 and its bottom row 252,252,252), so any crop of it puts
   light pixels under cream text. It also needed 42.8% synthetic extension - the source is
   only 1006px tall - and still upscaled 1.39x. Three measures, three losses.

   MARKUP: the <source media="(min-width: 901px)"> line is deleted and the <img> points at
   the float render directly, keeping ?v=159 so desktop's URL is byte-identical and it
   stays one cache entry and one download. assets/edit/v11-hero.webp is now referenced by
   zero pages; it is left on the server rather than deleted.

   `transform: none !important` IS LOAD-BEARING and this is the one place !important is
   unavoidable. The v11 pages carry an INLINE GSAP block (identical on all three,
   md5 0f072f54c0e219d3) that runs
     gsap.fromTo('.v2x__bg, .v2x-hero__bg', {yPercent:-5, scale:1.12}, {yPercent:5, scrub})
   so GSAP writes a scroll-linked inline transform. On a full-bleed background that is a
   nice parallax; on a contained floating render it would drift the phone out of its band
   and onto the title as you scroll. Only !important outranks an inline style. The tween
   still runs on `.v2x__bg` in other sections - this rule targets `.v11-hero
   .v2x-hero__bg` only - so mobile parallax is dropped for the hero render alone, on
   purpose.

   `filter` is deliberately NOT set: measured, the mobile computed filter on this element
   is already `none` (EDIT-V65's drop-shadow is gated min-width 901px), so declaring it
   would be noise.

   SPECIFICITY 0,2,2, beating `.v2x-hero__bg` (0,1,0, line 2714) and the three
   `transform: scale(1.3)` rules at 0,2,0 (lines 3414, 3433, 3435). Checked for the trap
   EDIT-V63/V73 hit: there is NO `html[dir="rtl"]` rule on `.v2x-hero__bg` anywhere in the
   sheet, so a dir-specific selector pair is not needed here and `left/right` behave.
   This is the same selector EDIT-V65 already uses on this element.

   Gated `min-height: 540px` for the reason EDIT-V73 documents: `calc(86svh - 314px)`
   collapses on a landscape phone. Under that height the old full-bleed treatment stays.

   The scrim is left alone on purpose. The render sits at z-index 1 and the scrim at -1,
   so nothing washes the artwork, while the copy keeps the dark bed EDIT-V66 gave it -
   which is why the title measures 16.47 rather than needing a new scrim of its own.

   DESKTOP UNTOUCHED: gated, and desktop loads the identical URL it loaded before.
   ========================================================= */
@media (max-width: 900px) and (min-height: 540px) {
  html body .v11-hero .v2x-hero__bg {
    top: calc(clamp(132px, 15vh, 168px) + 12px);
    bottom: auto;
    left: 0;
    right: 0;
    margin-inline: auto;
    width: min(95vw - 15px, calc((86svh - 314px) * 0.86));
    height: calc(86svh - 314px);
    object-fit: contain;
    object-position: bottom;
    z-index: 1;
    transform: none !important;
  }
}

/* ===================== EDIT-V78 =====================
   MOBILE ONLY. V1 hero: mobile shows a supplied transparent cutout, floating above the
   copy, instead of the desktop panorama cropped to a sliver. v1.html, v1-fa.html,
   v1-ar.html. The file is the one handed over at
   Desktop\New folder (2)\V1.webp, copied to assets/edit/v1-hero-mobile.webp
   byte-for-byte (196,664 bytes, sha ae2f8bab988a291f).

   WHAT WAS WRONG. assets/v1-hero.webp is 2880x1626 landscape; the mobile box is 403x1224
   at ratio 0.329, so cover kept 18.6% of the width from dead centre - source 40.7% to
   59.3%. A column-luma profile of that photo reads ZERO from 0% to 50%, then 9, 52, 46,
   48, 45 across 55-80%, then zero again: the phone sits at 55-80% on a pure-black field,
   entirely outside the window. The mobile hero was a black rectangle with a sliver of
   hand at one edge.

   THE SUPPLIED FILE NEEDS NO PREPARATION, which is why no crop was built. Measured:
   1252x1687, ratio 0.742, real alpha (minimum 0, 47.4% of samples fully transparent, all
   four corners transparent), content bounding box 1249x1687 - 100% of the canvas, so the
   art is already trimmed to its subject. Edge ink is 3% top, 0% left, 1% right and 42%
   bottom: it only touches the bottom edge, which is correct for a hand entering frame
   from below. Floated it paints 285x384 at 375x812, an upscale of 0.46x - DOWNSCALED,
   so sharper than the 2.43x-to-1.10x range any crop of the panorama could reach.

   THREE ALTERNATIVES WERE BUILT AND MEASURED BEFORE THIS FILE ARRIVED, recorded so they
   are not re-proposed. Title / chip-label contrast at the worst pixel under each box:
     A  full-bleed portrait crop of the panorama   10.35 / 2.74  <- chip labels REGRESS
     B  the existing assets/v1.webp cutout          -    / -     different composition
     C  the photo's own subject, floated           17.23 / 3.38
   A regressed the small chip labels from today's 3.33-3.38 down to 2.74 because the
   phone's vivid red screen lands under the text, and LIFTING DID NOT HELP - swept top
   gaps 0, 40, 120 and 303 and the labels stayed at 3.24-3.38, since in that photo the
   phone occupies nearly the full frame height and its bright screen can never clear the
   text band. That is the opposite of V2 Lite, where lifting 187px fixed everything.

   THE CHIP LABELS STAY AT 3.38 AND THAT IS NOT A HERO PROBLEM. `--dim: #6e6249` against
   pure black tops out at 3.51, so it cannot reach the 4.5 that 12.5px text needs on ANY
   dark ground. Today's live value is 3.33-3.38; this block leaves it exactly there. It is
   a palette issue, tracked separately.

   NO BACKGROUND MATCHING IS NEEDED because the file has real alpha - unlike candidate C,
   which was a rectangular crop whose pure-black field would have needed the hero's mobile
   ground set to #000 to hide its edge.

   `transform: none !important` IS REQUIRED, and I first shipped it WITHOUT the
   !important on the assumption that only the v11 pages carried the inline GSAP parallax.
   THAT WAS WRONG and the measurement caught it: the render came out 319x429 instead of
   284x384 - exactly 1.12x too big - and the gap to the title collapsed from 28px to 8px,
   because GSAP was still scaling it. `grep -l "toArray('.v2x__bg, .v2x-hero__bg')"`
   returns TWENTY-ONE pages, including all three v1 pages at line 290. So the rule is
   general: ANY mobile rule that repositions .v2x-hero__bg needs !important on transform,
   because an inline style outranks every stylesheet declaration without it.
   V2 and V2 Lite did not need it only because they stay full-bleed `cover`, where the
   parallax is correct and was deliberately left running.

   `filter` is not declared: measured, the mobile computed filter on this element is
   already `none`.

   SPECIFICITY 0,2,2 via `html body .v1-hero .v2x-hero__bg`, beating `.v2x-hero__bg`
   (0,1,0, line 2714) and the 0,2,0 transform rules. There is no `html[dir="rtl"]` rule on
   `.v2x-hero__bg` anywhere in the sheet, so the 0,2,1 trap that bit EDIT-V63 and V73 does
   not apply and left/right behave.

   .v1-hero IS A NEW HOOK, added to the three hero sections, because there was none:
   v1.html carried a bare `class="v2x-hero"` while v1-fa and v1-ar carried
   `"v2x-hero hero-scrim-l"`, so the three languages had no shared model class at all.
   The edit is anchored on `id="overview"` rather than on a class string, which is why it
   matched all three despite that difference. The name was free: `v1-hero` appears in the
   sheet only inside a comment at line 5636.

   The `<picture>` wrapper reuses `.hero-bgpic` from EDIT-V75, already ungated and already
   live, so no new wrapper rule is added.

   Gated max-width 900px and min-height 540px, the latter because `calc(86svh - 314px)`
   collapses on a landscape phone. DESKTOP UNTOUCHED: it keeps loading
   assets/v1-hero.webp?v=88 through the <img>, since the new file is reachable only via a
   max-width: 900px <source> that a desktop browser never selects.
   ========================================================= */
@media (max-width: 900px) and (min-height: 540px) {
  html body .v1-hero .v2x-hero__bg {
    top: calc(clamp(132px, 15vh, 168px) + 12px);
    bottom: auto;
    left: 0;
    right: 0;
    margin-inline: auto;
    width: min(95vw - 15px, calc((86svh - 314px) * 0.74));
    height: calc(86svh - 314px);
    object-fit: contain;
    object-position: bottom;
    z-index: 1;
    transform: none !important;
  }
}

/* ===================== EDIT-V79 =====================
   MOBILE ONLY. V1 hero: the supplied cutout is cut straight across at the wrist, and this
   fades that edge out so it reads as the arm receding rather than as a crop. Asked for as
   "از قسمت پایین دست که حالت بریده شده داره ... یه گرادیانت روش بذاری که دیده نشه".

   DONE WITH A CSS MASK, NOT BY EDITING THE FILE. The user's own artwork stays byte-identical
   on the server, no 196KB re-upload is needed, and the ramp is a number that can be retuned
   later without re-encoding anything. If a browser does not support mask-image the image
   simply shows unmasked, i.e. exactly today's state - a safe degradation.

   WHERE TO START THE FADE WAS MEASURED, NOT GUESSED. Scanning the file's own alpha and
   colour by row:
     last row        521 opaque columns spanning x 3..523 of 1252 - a flat horizontal cut
                     across 42% of the width
     y 82% and below cool/screen pixel count is ZERO - it is hand and wrist only
     y 81% (row 1366) the lowest row still containing phone-screen pixels
   So the bottom 19% is safe to fade and the phone must not be touched. Four ramps were
   rendered onto the real hero ground and compared, with the alpha removed at the phone's
   bottom edge computed for each:
     as supplied              0% at 81%   - hard cut, plainly visible
     from 62%                43% at 81%   - cut gone, but the phone's bottom goes translucent
     from 74%                25% at 81%   - still dims the phone
     from 82%, eased          0% at 81%   - cut gone AND the phone untouched   <- shipped
   Starting at 82% is what keeps the phone at full opacity; a longer, prettier ramp starting
   at 62% looked good on the arm and quietly ate the phone's bottom edge.

   A SHORT LINEAR RAMP IS NOT ENOUGH. A plain `#000 80%, transparent 100%` still left a
   perceptible horizontal termination, because at 90% it is only half removed and the wrist
   is solid skin there. The three-stop eased ramp concentrates the removal lower down
   (45% at 90%, 85% at 96%) so the arm thins out before it ends.

   MASK ALPHA IS WHAT IS KEPT, the inverse of the canvas `destination-out` alpha the
   comparison was built with. The stops below are 1 minus the measured removal: 82% -> 1,
   90% -> .55, 96% -> .15, 100% -> 0. Getting that backwards would have faded the phone and
   left the wrist.

   The mask lines up with the artwork because the box and the image coincide exactly: the
   rule's `width: min(95vw - 15px, band * 0.74)` and `height: band` reproduce the file's
   0.742 ratio, so at every size measured the band binds and `contain` fills the box with no
   letterboxing. Percentages of the box are therefore percentages of the image.

   Gated identically to EDIT-V78, `max-width: 900px and min-height: 540px`, because below
   540px tall that block does not apply and the image is still full-bleed `cover` - masking
   it there would fade the background rather than a wrist. DESKTOP UNTOUCHED: desktop serves
   a different file entirely (assets/v1-hero.webp) and never matches this gate.
   ========================================================= */
@media (max-width: 900px) and (min-height: 540px) {
  html body .v1-hero .v2x-hero__bg {
    -webkit-mask-image: linear-gradient(to bottom, #000 0 82%, rgba(0, 0, 0, .55) 90%, rgba(0, 0, 0, .15) 96%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 0 82%, rgba(0, 0, 0, .55) 90%, rgba(0, 0, 0, .15) 96%, transparent 100%);
  }
}

/* ===================== EDIT-V80 =====================
   MOBILE ONLY. V1 CORE hero: the render floats above the copy, out from under two
   overlays, instead of being a narrow side strip. v1-core.html, v1-core-fa.html,
   v1-core-ar.html.

   THIS MODEL HAD THREE FAULTS AT ONCE, not one, and the layering was the worst of them.

   1. THE IMAGE WAS BURIED UNDER TWO LAYERS. `.v1c-hero__edge` is `z-index: -1`
      (line 3300) while `.v1c-hero__scrim` is `z-index: 1` covering the whole hero
      (line 2999) and `.v1c-aura` is `z-index: 0` on top of it too (line 2986). On mobile
      line 3003 turns the scrim into a flat `linear-gradient(to bottom,
      rgba(10,10,13,.55), rgba(10,10,13,.4))`, so the render was dimmed 40-55% everywhere
      before anything else went wrong. Moving it to `z-index: 2` puts it above both and
      still below the copy, which is `z-index: 4` (measured, line 2951 via .v11-hero).
      Same family as the V2 Pro z-index tie in EDIT-V73, but here the numbers actually
      differ - the render was genuinely behind, not merely tied.

   2. THE FRAMING WAS THE WORST OF THE SIX MODELS SO FAR. assets/edit/v1core-hero.webp is
      976x782 (ratio 1.248, landscape) in a 240x974 box (ratio 0.246), so cover kept
      19.7% of the width - source 40.1% to 59.9% - and the box is a side strip, not the
      full hero.

   3. IT WAS THE SOFTEST TOO: 2.49x upscale at DPR 2, because the source is only 976px
      wide. Worth noting that DESKTOP upscales the same file 2.76x - that is a
      pre-existing condition of this model's artwork and is NOT touched here.

   THE NEW FILE IS A CROP OF AN ASSET ALREADY ON THE SERVER, not a new photograph.
   assets/v1core.webp is 750x750 with real alpha (min 0, 54.7% transparent) and a content
   bounding box of 451x593 at (150,82) - the phones occupy only 47% of the canvas, so
   using it raw with `contain` would render them small inside transparent margins.
   Cropping to that bbox plus a ~12px margin gives 475x617, ratio 0.7699, 35,296 bytes -
   less than half the 81,426-byte file it replaces on mobile, and 0% of its width is
   discarded because the ratio now matches the box by construction.

   HONEST ABOUT THE RESULT: 1.25x upscale is better than 2.49x but not sharp. The content
   bbox is only 451px wide and the largest V1 Core asset on disk is 1400x788 with no alpha
   (v1core-thin.webp), so this is the best any existing file can do. For comparison the
   cutout the user supplied for V1 was 1252x1687 and reached 0.45x. A larger V1 Core render
   would fix it with a one-line srcset change.

   THE HORIZONTAL MASK MUST BE CLEARED. Lines 3300 and 3307 give this element
   `mask-image: linear-gradient(to left|right, #000 58%, transparent 99%)` - correct for an
   image bleeding in from one side, wrong for a centred floating render, which it would
   fade down one flank. `mask-image: none` on both the standard and -webkit- property.

   `transform: none` needs NO !important here, unlike V1 and V11: the only transform is
   `translateY(-50%)` from the base rule at line 3300, paired with its `top: 50%`. Checked
   the v1-core pages - their inline GSAP block targets `.v2x__bg, .v2x-hero__bg` and this
   element is neither, so nothing writes an inline transform to outrank.

   `max-width: none` is required: the base rule caps this element at `max-width: 64vw`,
   which would clamp the box below the width the band allows.

   SPECIFICITY 0,2,2 via `html body .v1c-hero .v1c-hero__edge`. It beats
   `.v1c-hero__edge` (0,1,0, lines 3300/3416), `.v1c-hero .v1c-hero__edge` (0,2,0,
   line 3417) and - the one that matters - `html[dir="rtl"] .v1c-hero__edge` (0,2,1,
   line 3307): equal class count, one more type selector. That is the same 0,2,1 trap that
   bit EDIT-V63 and V73, checked for deliberately this time.

   The `<picture>` wrapper reuses `.hero-bgpic` from EDIT-V75. Note this is the first model
   whose hero art is NOT `.v2x-hero__bg`, so the wrapper script had to target
   `.v1c-hero__edge` instead.

   Gated max-width 900px and min-height 540px. DESKTOP UNTOUCHED: it keeps loading
   assets/edit/v1core-hero.webp through the <img>, keeps its side placement, its 64vw cap,
   its horizontal mask and its z-index -1; the new file is reachable only through a
   max-width: 900px <source>.
   ========================================================= */
@media (max-width: 900px) and (min-height: 540px) {
  html body .v1c-hero .v1c-hero__edge {
    top: calc(clamp(132px, 15vh, 168px) + 12px);
    bottom: auto;
    left: 0;
    right: 0;
    margin-inline: auto;
    width: min(95vw - 15px, calc((86svh - 314px) * 0.7699));
    height: calc(86svh - 314px);
    max-width: none;
    object-fit: contain;
    object-position: bottom;
    z-index: 2;
    transform: none;
    -webkit-mask-image: none;
    mask-image: none;
  }
}

/* ===================== EDIT-V81 =====================
   MOBILE ONLY. V01 hero: the phone now scales with the viewport HEIGHT, so the title and
   both buttons reach the first screen on a short phone, plus the 28px gap the other six
   models already have. v01.html, v01-fa.html, v01-ar.html.

   V01 WAS THE ONE MODEL LEFT OUT of EDIT-V70's "title at the bottom of the first screen",
   deliberately - it was excluded with `:not(.v01-hero)` because its phone was a
   fixed-height spacer and the band formula did not exist yet. The consequence, measured
   now: this hero's geometry is driven entirely by WIDTH (`width: min(380px, 78%)` at line
   2963, copy `padding-top: 0`), so it does not move at all as the viewport shortens:
     375x812   phone 281x383 top 158   title 541   CTA bottom 791   fold 812   ok
     375x740   IDENTICAL                            CTA bottom 791   fold 740   -51
     375x667   IDENTICAL                            CTA bottom 791   fold 667   -124, and
                                                    the TITLE itself is below the fold
     320x568   phone 238x324            title 482   CTA bottom 733   fold 568   -165
   On a 667-tall phone - iPhone SE and 8, still common - the visitor landed on a picture
   with no model name and no buttons at all. For comparison v11-fa, which does get V70, has
   its title at 432 and its CTA only 15px past the fold at the same size.

   THE FIX REUSES THE SAME BAND FORMULA the other six models use, as a HEIGHT CAP:
   `max-height: calc(86svh - 342px)`. The 342 is 314 - the band constant the other models
   share - PLUS the 28px gap, and that difference is the whole point. The first version used
   314 and simply added `margin-bottom: 28px`, which pushed the entire stack down 28px and
   moved the CTA from inside the fold (791 today) to 7px past it at 375x812. Taking the gap
   OUT of the phone's height budget instead of adding it below keeps the totals where they
   were.

   THE DEMO FLATTERED THAT FIRST VERSION, AND THE DIFFERENCE WAS THE SCROLLBAR. The demo ran
   at a 376px viewport with no scrollbar, so the layout width was 376 and the copy wrapped
   shorter. The real page at 375 has a 15px scrollbar, so the layout width is 360, the copy
   is taller, and the CTA lands lower:
     demo   375x812 CTA 783/812 inside    375x667 CTA 658/667 inside
     real   375x812 CTA 819/812 +7        375x667 CTA 696/667 +29
   Confirm a fold measurement at the real layout width, scrollbar included - a demo run one
   pixel wider can hide a 36px error.

   Measured with 342:
     375x812   painted 261x356   CTA bottom ~792 - inside the fold, matching today
     375x667   painted 170x232   CTA bottom ~668 - at the fold
     320x568   painted 107x146   CTA bottom ~583 - 15px past, the same order as the others
   The cost, stated plainly: at 375x812 the phone is 356px tall against 383px today, about
   7% smaller. That is the price of putting the buttons on the first screen, which is what
   EDIT-V70 asked for on every other model.

   `object-fit: contain` IS NOT COSMETIC - IT PREVENTS A STRETCH, and the number caught
   what the eye would not. This element is `object-fit: fill`, and with an explicit width
   plus a capped height the box stops matching the file's ratio, so the render STRETCHES
   instead of scaling. First attempt measured a box of 293x260, ratio 1.127, against the
   file's 0.734 - the phone was visibly fattened. With `contain` the painted size came back
   to 190x260, ratio 0.734 exactly. Same family as the height-sized-hero squash logged for
   the desktop heroes. Note this also fixes a smaller PRE-EXISTING stretch: even where the
   cap does not bite, the width-driven box is ratio 0.763 against the file's 0.734, so the
   phone has been about 4% too wide on mobile all along.

   !important ON margin-bottom ONLY, and only because the opponent is itself !important:
   EDIT-V72's 881-900 seam block sets `margin: 26px auto 0 !important`, whose shorthand
   zeroes margin-bottom. Without !important the new gap would be 28px everywhere except a
   twenty-pixel-wide band at 881-900, which is precisely the kind of seam V72 existed to
   remove. `max-height` and `object-fit` are not declared in V72, so they need nothing.

   SPECIFICITY 0,2,2 via `html body .v01-hero .v11-hero__phone`, beating line 2963's
   `.v11-hero__phone` at 0,1,0. EDIT-V62's desktop rules are 0,3,2 but gated
   `min-width: 881px` on the phone's absolute placement, which this gate never overlaps
   except in the 881-900 band handled above.

   Gated max-width 900px and min-height 540px. DESKTOP UNTOUCHED: V01's desktop hero keeps
   its absolute right-hand placement, its drop-shadow, its GSAP transform and its z-index 3.
   Verified with a path-keyed A/B over 485 properties at seven widths.
   ========================================================= */
@media (max-width: 900px) and (min-height: 540px) {
  html body .v01-hero .v11-hero__phone {
    max-height: calc(86svh - 342px);
    object-fit: contain;
    margin-bottom: 28px !important;
  }
}

/* ===================== EDIT-V82 =====================
   MOBILE ONLY. V0 CORE hero: mobile shows the same transparent four-phone render desktop
   already shows, centred in the space above the copy, instead of a macro crop of one
   corner. v0-core.html, v0-core-fa.html, v0-core-ar.html.

   WHAT WAS WRONG. assets/edit/v0core-hero.webp is 2200x1117 - four phones fanned across a
   grey studio backdrop - and the mobile box is 394x1150, so cover kept 17.4% of the width
   from dead centre. What a phone actually displayed was the edge of the green handset and
   a slab of the white backdrop: no complete product anywhere, and the bright backdrop sat
   directly under the title, washing it out. Upscale was 2.06x at DPR 2.

   IT WAS ALSO BURIED. `.v0-herobg` computed to `z-index: 0` while `.v1c-hero__scrim` sits
   at `z-index: 1` covering the whole hero, so the scrim painted over the artwork before
   anything else went wrong. Same shape as the V1 Core fault in EDIT-V80, one z-level
   milder. `z-index: 2` puts it above the scrim and still below the copy at 4.

   NO NEW FILE. EDIT-V60 already ships v0core-hero-float.webp, 2240x1247, the identical fan
   as a transparent cutout, and desktop has been using it since. Reusing it means mobile
   and desktop show the same artwork, nothing extra downloads, and at 341px wide the render
   scales to 0.30x at DPR 2 - the sharpest of any hero in this pass.

   CENTRED, NOT BOTTOM-ANCHORED, and that was a deliberate choice the user made after
   seeing both. Every other model in this pass parks its render at the BOTTOM of the band
   with `object-position: bottom`, because those renders are portrait and fill the band.
   This one is LANDSCAPE - ratio 1.796 - so in a 356px band it only stands 190px tall and
   bottom-anchoring left a 222px hole between the phones and the title. The box here spans
   the whole band minus the 28px gap and `object-position: center` sits the render in the
   middle of it, which splits that empty space instead of piling it in one place.

   `object-position` IS THE ONLY DIFFERENCE from the other models' rule; the rest of the
   block is the same shape, so the band arithmetic stays comparable across all of them.

   `transform: none !important` IS REQUIRED. The v0-core pages carry the same inline GSAP
   parallax block as the other twenty - `gsap.fromTo('.v2x__bg, .v2x-hero__bg', {yPercent:-5,
   scale:1.12}, ...)` - and although this element is `.v0-herobg` rather than
   `.v2x-hero__bg`, the hero also carries `.hero-zoom`, whose rule at line 3433 scales
   `.v0-herobg` to 1.3. Measured before the change: transform PRESENT. Without the
   override the render would be scaled and clipped.

   SPECIFICITY 0,2,2 via `html body .v0c-hero .v0-herobg`, beating `.v0-herobg` and
   `.hero-zoom .v0-herobg` (0,2,0, line 3433) and EDIT-V60's own `html .v0c-hero
   .v0-herobg` (0,2,1) - equal class count, one more type selector. Checked for a
   `html[dir="rtl"]` rule on this element: there is none, so the 0,2,1 trap from EDIT-V63
   and V73 does not apply.

   MARKUP: the `<source media="(min-width: 901px)">` line is deleted and the `<img>` points
   at the float render directly, keeping `?v=151` so desktop requests a byte-identical URL
   and it stays one cache entry and one download. assets/edit/v0core-hero.webp is now
   referenced by zero pages and is left on the server rather than deleted.

   Gated max-width 900px and min-height 540px. DESKTOP UNTOUCHED: it keeps
   `object-fit: contain`, its left-column placement from EDIT-V60, its z-index 3, its
   drop-shadow, its float animation and the identical file URL. Verified with a path-keyed
   A/B over 485 computed properties at seven widths.
   ========================================================= */
@media (max-width: 900px) and (min-height: 540px) {
  html body .v0c-hero .v0-herobg {
    top: clamp(132px, 15vh, 168px);
    bottom: auto;
    left: 0;
    right: 0;
    margin-inline: auto;
    width: min(95vw - 15px, calc((86svh - 302px) * 1.796));
    height: calc(86svh - 302px);
    object-fit: contain;
    object-position: center;
    z-index: 2;
    transform: none !important;
    animation: none;
  }
}

/* ===================== EDIT-V83 =====================
   MOBILE ONLY. V0 hero: the phone render comes out from BEHIND the background, at its
   true aspect ratio, enlarged so it bleeds off both edges and sits just above the copy.
   The opaque background photo is dropped on mobile. v0.html, v0-fa.html, v0-ar.html.

   THE PRODUCT WAS INVISIBLE. Two layers, and they were in the wrong order:
     .v0-herobg   v0-herobg.webp 1920x1072   OPAQUE, no alpha at all   z-index  0
     .v0-phones   v0-hero.webp   1276x729    real alpha, 45.5% clear   z-index -1
   The transparent product cutout sat UNDER an opaque photograph, so on mobile no phone
   was visible anywhere in the hero - only an abstract violet wash. Confirmed by hit
   testing: at the centre of the phone render's own box the topmost painted element was
   the copy, never the image.

   AND IT WAS CRUSHED. `.v0-phones` is `object-fit: fill` in a 360x698 box - ratio 0.516
   against the file's 1.750 - so had it been visible it would have been squeezed to 29% of
   its proportional width. `object-fit: contain` restores it; measured ratio is now 1.750
   exactly.

   THE BACKGROUND IS DROPPED RATHER THAN RESCUED, chosen by the user after seeing it: it
   was 1920x1072 landscape in a portrait box, discarding 81.6% of its width at a 2.14x
   upscale, and its bright aurora sat directly under the title. With it gone the ground is
   the site's own --bg #0c0907 (this hero's own background-color is transparent) and mobile
   downloads one file instead of two.

   .v0x-hero IS A NEW HOOK AND IT IS NOT OPTIONAL. `.v0-hero` is NOT unique to this model -
   it is on FIFTEEN pages: v0 x3, v0-core x3 and the whole F series x9, all of which also
   carry a `.v0-herobg` element. A rule written as `.v0-hero .v0-herobg { display: none }`
   would have blanked the hero background of the F series, where that background IS the
   hero, and undone EDIT-V82's V0 Core work. Checked before writing, not after.

   CENTRED WITH translateX, NOT auto MARGINS, and this is a real CSS rule worth
   remembering: `left: 0; right: 0; margin-inline: auto` centres a box only while it FITS
   its containing block. Once the box is wider - which is the whole point of bleeding off
   the edges - the auto margins stop splitting equally and the containing block's DIRECTION
   decides which edge sticks. Measured: the first attempt put all 113px of bleed on one
   side, and it would have been the opposite side in English, breaking the fa == ar == en
   rule. `left: 50%` plus `translateX(-50%)` is direction-independent: 56px each side,
   verified.

   Replacing the transform is safe here, unlike on `.v2x-hero__bg`: the only transform on
   `.v0-phones` is `translateY(-50%)` from its own base rule at line 3406, paired with
   `top: 50%`. Checked script.js and the v0 pages - the inline GSAP parallax targets
   `.v2x__bg, .v2x-hero__bg` and never this element, so no !important is needed.

   THE TOP IS COMPUTED FROM THE WIDTH so the gap stays fixed while the render scales:
     top = heroPadding + (86svh - 274px) - 28px - width/1.750
   With `width: 130vw` that is `74.286vw` for the height term. Measured 489x279 with a 28px
   gap at BOTH 375x812 and 375x667 - the render lifts itself as the screen shortens rather
   than crowding the title. 130 is the only number to change if a different size is wanted.

   Still downscaled at 0.77x on a DPR 2 screen, so bigger did not mean softer.

   SPECIFICITY 0,2,2, beating `.v0-phones` (0,1,0, line 3406) and - the one that matters -
   `html[dir="rtl"] .v0-phones` (0,2,1, line 3411), equal class count with one more type
   selector. EDIT-V39/V61's rules at lines 5311-5325 are gated `min-width: 901px` and never
   overlap this block.

   Gated max-width 900px and min-height 540px. DESKTOP UNTOUCHED: it keeps both layers, the
   background photo, the phones at their own placement and z-index, and the drop-shadow.
   Verified with a path-keyed A/B over 485 computed properties at seven widths.
   ========================================================= */
@media (max-width: 900px) and (min-height: 540px) {
  html body .v0x-hero .v0-herobg { display: none; }
  html body .v0x-hero .v0-phones {
    top: calc(clamp(132px, 15vh, 168px) + 86svh - 302px - 74.286vw);
    bottom: auto;
    left: 50%;
    right: auto;
    margin-inline: 0;
    width: 130vw;
    height: auto;
    max-width: none;
    object-fit: contain;
    object-position: center;
    z-index: 2;
    transform: translateX(-50%);
  }
}

/* ===== EDIT-V84 — F-series key-map labels printed on the diagram's white band =====
   Applies to ALL languages and ALL responsive states (not a mobile-only block).
   Scoped to .f-keymap, a class that exists only on the F-series layout-diagram
   wrapper, so no other page or element can be reached by these rules.
   Above 900px the column is absolutely positioned over the white left band of the
   artwork; type is sized in cqi so it tracks the IMAGE width, not the viewport.
   At/below 900px (the site's mobile gate) it falls back to a normal block under
   the image in the dark palette. The column is pinned with the PHYSICAL left edge
   so it stays on the left in en/fa/ar alike; only the text direction flips. */
.v2x-display__media.f-keymap { position: relative; width: min(1100px, 96%); margin-inline: auto; container-type: inline-size; }
.v2x-display__media.f-keymap > img { width: 100%; margin: 0; display: block; }
@media (min-width: 901px) {
  .f-keymap .f-keymap__col { position: absolute; inset: 0 auto 0 0; width: 40%; box-sizing: border-box; display: flex; flex-direction: column; justify-content: center; padding: 3% 3% 3% 5.5%; color: #1a1208; }
  html:not([dir="rtl"]) body .f-keymap .f-keymap__col { direction: ltr; text-align: left; }
  html[dir="rtl"] body .f-keymap .f-keymap__col { direction: rtl; text-align: right; }
  .f-keymap .f-keymap__intro { font-size: max(10.5px, 1.15cqi); line-height: 1.7; margin: 0 0 1.3cqi; color: #5b4a2a; font-weight: 600; }
  .f-keymap .f-keymap__list { margin: 0; padding-inline-start: 1.5em; font-size: max(11.5px, 1.32cqi); line-height: 2.05; font-weight: 500; }
  .f-keymap .f-keymap__list li::marker { color: #8b6f2a; font-weight: 700; }
}
@media (max-width: 900px) {
  .f-keymap .f-keymap__col { margin-top: 18px; color: var(--text, #f5ebd8); }
  html:not([dir="rtl"]) body .f-keymap .f-keymap__col { direction: ltr; text-align: left; }
  html[dir="rtl"] body .f-keymap .f-keymap__col { direction: rtl; text-align: right; }
  .f-keymap .f-keymap__intro { font-size: 13px; color: var(--muted, #9e9070); margin: 0 0 10px; }
  .f-keymap .f-keymap__list { margin: 0; padding-inline-start: 1.4em; font-size: 14.5px; line-height: 1.95; }
  .f-keymap .f-keymap__list li::marker { color: var(--gold, #d4af37); font-weight: 700; }
}

/* ===== EDIT-V85 — companion to EDIT-V84: keep the diagram's box reserved before decode =====
   The six F-series diagrams now carry width/height ATTRIBUTES so the browser knows their
   aspect ratio before the lazy .webp decodes. Without a reserved box the wrapper measured
   0px tall, and the absolutely-positioned label column (inset: 0 auto 0 0 + justify-content:
   center) had nothing to centre inside — it escaped 149px above and 215px below its wrapper
   and landed on the section heading, in near-black ink on the dark page. Measured, not guessed.
   height:auto is REQUIRED here: width/height attributes are presentational hints, so with
   width overridden to 100% and height left alone the image renders stretched to its literal
   attribute height (1100x766 instead of 1100x527). This restores ratio-preserving scaling
   while keeping the pre-decode box reservation. */
.v2x-display__media.f-keymap > img { height: auto; }

/* ===================== EDIT-V86 — F1 MOBILE HERO: one phone, and the chips inside the fold =====
   MOBILE LAYER ONLY. Gated @media (max-width: 900px) and (min-height: 540px); desktop was
   measured with this block on and off across 7 elements x 10 properties -> zero difference.
   Scoped to .f1-hero, NOT .f-hero: f2 and f4 carry .f-hero too and are not in this round.

   WHY. EDIT-V24 deliberately gated `.f-hero .fhero-duo { z-index: 1 }` to min-width:901px,
   because two phones side by side want 732px and a phone screen has 360. Below that gate the
   duo fell back to the base `z-index: -1` (line 3313) and sat BEHIND .v0-herobg, which is
   z-index:0 at opacity .95 — so the artwork was invisible, and .fhero-duo__a measured
   x = -274 of its own 333px width. That comment said the fix "means choosing a treatment...
   a design call, not a bug fix". The call has now been made: show the FRONT render only.

   THE ARITHMETIC, and why it is 100svh and not 86svh.
   Two traps were measured, not guessed:

   1. EDIT-V70 (line 8052) pins the copy with
        html body .v2x-hero:not(.v01-hero) .v2x-hero__copy { padding-top: calc(86svh - 274px) !important }
      That is (0,3,2) AND !important. A `html body .f1-hero .v2x-hero__copy` override is (0,2,2)
      and loses silently — three sweeps with different constants all returned the identical
      title position before this was spotted. Hence `.f1-hero.v2x-hero` here: (0,3,2), later in
      source, plus !important of its own.

   2. `86svh - <constant>` does not survive short viewports. The content below the art is fixed
      height (title 142 + gap 14 + cta 56 + gap 12 + chips 39 = 263px) while 86svh shrinks with
      the screen, so the chips crossed the fold as the viewport got shorter: at 700px tall the
      clearance was +37, at 701px it was -1. A one-pixel seam. Rather than paper over it with a
      second short-screen tier (tried: it put the phone 9px under the nav bar at 360x640), the
      equation was solved directly for "chips bottom sits 24px above the fold":
        chipsBottom = heroPad + copyPad + 263,  want = 100svh - 24,  heroPad = 132 below 880px
        => copyPad = 100svh - 419px,  and art height = copyPad - 28px gap = 100svh - 447px.
      Measured clearance is then a CONSTANT 24px at 640/667/701/844 (16 at 932, where the hero's
      own clamp(132px,15vh,168px) padding starts growing). No seam anywhere.

   THE OTHER PIECES.
   - Centring uses left:50% + translateX(-50%), not margin-inline:auto. Once the box is wider
     than its container margin:auto stops centring and the containing block's `direction` picks
     an edge — which mirrors between fa/ar and en. Measured margins here: 122/121 at 390px in
     Persian and 117/117 in English, i.e. symmetric in both.
   - (0,2,2) beats the three ungated `html[dir="rtl"] .fhero-duo` declarations (lines 3321, 3425,
     3471) at (0,2,1), so left/right do not flip in RTL.
   - The chips were 128px tall on two wrapped rows; nowrap plus .98rem/9px puts them on one row
     at 39px. That 89px is most of what buys them a place above the fold.
   - filter:none and the hidden __sheen match what was asked for on V2 and V2 Lite: no drop
     shadow under a mobile hero render, and the gold sweep reads as a smudge on a single phone.
   - EDIT-V25's `.f-hero .fhero-duo__a { margin-left: -30px }` lives inside min-width:901px, so
     nothing ungated is fighting the margin here; it is zeroed anyway for clarity.

   Trade-off, stated: on 640-700px-tall screens the phone lands at 71-94px wide. At 640px the
   nav zone plus title plus cta plus chips already claim ~370px, so there is no room to be had.
   ========================================================= */
@media (max-width: 900px) and (min-height: 540px) {
  html body .f1-hero .fhero-duo {
    top: clamp(132px, 15vh, 168px);
    bottom: auto;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    height: calc(100svh - 447px);
    width: auto;
    max-width: 95vw;
    z-index: 2;
    overflow: visible;
    gap: 0;
  }
  html body .f1-hero .fhero-duo__b,
  html body .f1-hero .fhero-duo__sheen { display: none; }
  html body .f1-hero .fhero-duo__a { margin-left: 0; height: 100%; width: auto; max-width: none; }
  html body .f1-hero .fhero-duo img { filter: none; }

  html body .f1-hero.v2x-hero .v2x-hero__copy { padding-top: calc(100svh - 419px) !important; }

  html body .f1-hero .v2x-hero__chips { flex-wrap: nowrap; gap: 10px; margin-top: 12px; }
  html body .f1-hero .v2x-hero__chips b { font-size: .98rem; }
  html body .f1-hero .v2x-hero__chips span { font-size: 9px; white-space: nowrap; }
}

/* ===================== EDIT-V87 — F2 MOBILE HERO: same treatment as EDIT-V86, f2 scope =====
   MOBILE LAYER ONLY, same gate as EDIT-V86. Scoped .f2-hero (f4 still untouched).

   F2 was the same defect as F1 but further gone: with the duo at its base z-index:-1 behind
   .v0-herobg, .fhero-duo__a measured x = -367 against its own 374px width — SEVEN pixels of the
   front render were on screen. Chips sat on two rows, 114px below the fold.

   Every f2-specific duo rule in the sheet (lines 4815-4817 and 6967-6969, the margin-left:-210px
   and the right:calc(4vw + 185px) anchor pair) is inside @media (min-width: 901px), so nothing
   ungated fights this block. The constants are EDIT-V86's, unchanged and for the same reason:
     art height = 100svh - 447px,  copy padding-top = 100svh - 419px
   which holds chip clearance at a constant 24px across 640/667/701/844 (16 at 932). See the
   EDIT-V86 comment for why this is 100svh and not 86svh, and for the EDIT-V70 !important trap.

   ONE VISUAL DIFFERENCE, deliberate and signed off. The F2 front render is TILTED where F1's is
   upright, so at equal height its bounding box is much wider: F1 lands at 147x397 (38% of a
   390px screen) and F2 at 280x397 (72%). The DEVICE is about the same size in both; only the
   box that contains it differs. Shrinking F2 to match F1's box width would make the actual
   phone read smaller than F1's, not equal to it.
   ========================================================= */
@media (max-width: 900px) and (min-height: 540px) {
  html body .f2-hero .fhero-duo {
    top: clamp(132px, 15vh, 168px);
    bottom: auto;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    height: calc(100svh - 447px);
    width: auto;
    max-width: 95vw;
    z-index: 2;
    overflow: visible;
    gap: 0;
  }
  html body .f2-hero .fhero-duo__b,
  html body .f2-hero .fhero-duo__sheen { display: none; }
  html body .f2-hero .fhero-duo__a { margin-left: 0; height: 100%; width: auto; max-width: none; }
  html body .f2-hero .fhero-duo img { filter: none; }

  html body .f2-hero.v2x-hero .v2x-hero__copy { padding-top: calc(100svh - 419px) !important; }

  html body .f2-hero .v2x-hero__chips { flex-wrap: nowrap; gap: 10px; margin-top: 12px; }
  html body .f2-hero .v2x-hero__chips b { font-size: .98rem; }
  html body .f2-hero .v2x-hero__chips span { font-size: 9px; white-space: nowrap; }
}

/* ===================== EDIT-V88 — F4 MOBILE HERO: completes the F-series pass =====
   MOBILE LAYER ONLY, same gate and same constants as EDIT-V86/V87. Scoped .f4-hero.

   F4 measured exactly like F2 before this: duo at its base z-index:-1 behind .v0-herobg,
   .fhero-duo__a at x = -367 against its own 374px width (7px on screen), chips on two rows
   114px below the fold, hero 1127px against an 844px viewport. Because F4's background is an
   abstract metal texture rather than a phone photo, the mobile hero showed NO handset at all.

   All f4-specific duo rules are inside min-width:901px — the anchor pairs at 4950-4951 and
   7034-7035, the margin-left:-180px at 7033, and EDIT-V25's height:64% — so the mobile path is
   clean and EDIT-V86's constants drop in unchanged:
     art height = 100svh - 447px,  copy padding-top = 100svh - 419px
   Measured clearance: a constant 25px at 640/667/844 (17 at 932). Hero 1127 -> 989.

   ONE F4-ONLY DIFFERENCE, and it is a real bug this model exposed.
   EDIT-V86/V87 put `white-space: nowrap` on the chip's <span> but NOT on its <b>. F1 and F2 get
   away with that because every <b> they carry is a single token (1.77", MTK6261D, QQVGA, 4 langs).
   F4's English sheet has "Metal body" — TWO words — which wrapped to two lines, grew the row and
   cut chip clearance from 24px to 4px. With nowrap added, the row measured 355px against a 343px
   column, because F4's English labels (MTK6260A, 1200mAh, Metal body, QVGA display) are simply
   longer than the other two models'. Hence the F4-only type step: b at .92rem instead of .98rem
   and gap 8 instead of 10, which lands the row at 309 + 24 = 333 against 343 available, with
   document overflow 0 at 360/375/390/430. A 6% type difference from F1/F2, invisible in practice.
   ========================================================= */
@media (max-width: 900px) and (min-height: 540px) {
  html body .f4-hero .fhero-duo {
    top: clamp(132px, 15vh, 168px);
    bottom: auto;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    height: calc(100svh - 447px);
    width: auto;
    max-width: 95vw;
    z-index: 2;
    overflow: visible;
    gap: 0;
  }
  html body .f4-hero .fhero-duo__b,
  html body .f4-hero .fhero-duo__sheen { display: none; }
  html body .f4-hero .fhero-duo__a { margin-left: 0; height: 100%; width: auto; max-width: none; }
  html body .f4-hero .fhero-duo img { filter: none; }

  html body .f4-hero.v2x-hero .v2x-hero__copy { padding-top: calc(100svh - 419px) !important; }

  html body .f4-hero .v2x-hero__chips { flex-wrap: nowrap; gap: 8px; margin-top: 12px; }
  html body .f4-hero .v2x-hero__chips b { font-size: .92rem; white-space: nowrap; }
  html body .f4-hero .v2x-hero__chips span { font-size: 9px; white-space: nowrap; }
}

/* ===================== EDIT-V89 — the mobile drawer now covers 761-900px too =====
   THE PROBLEM. The burger and the drawer were gated `max-width: 760px` (line 1840), so from
   761 to about 850 the site still rendered the DESKTOP horizontal nav in a bar that was no
   longer wide enough for it. Measured on index-fa/-ar/-en: three of the five labels broke
   mid-phrase — «همه گوشی‌ها» -> «همه»/«گوشی‌ها», «كل الهواتف» -> «كل»/«الهواتف»,
   "All Phones" -> "All"/"Phones" — and the nav row grew from 40px to 63px, 58% taller.
   The exact break is between 845 and 860. That band is iPad Mini portrait (768), iPad
   portrait (810-820), most Android tablets (800) and any half-screen laptop window.

   WHY THIS IS A NEW BLOCK AND NOT AN EDIT TO LINE 1840. EDIT-V67 (line 7818) already recorded
   the trap: simply moving that block's gate to 900px would apply `translateX(110%)` to the
   HORIZONTAL nav row between 761 and 900 — the panel is only `position: fixed` below 760 —
   and push the whole menu off screen. This block instead REPLICATES the drawer for the band,
   supplying `position: fixed` and the transform together, so the two can never disagree.
   Below 760 the original rules still do the work, untouched; above 900 nothing changes.
   Verified there is no seam: at 761 and at 760 the closed panel measures visible-width 0 in
   both, and at 901 the row is back to position:relative with all five links at 40px.

   NO RTL MIRRORING, deliberately. Per EDIT-V67, `.nav__links` computes `direction: ltr` on
   index-fa and index-ar as well as index, so `inset-inline-end` resolves to `right: 0` in all
   three languages and the panel is right-anchored everywhere. The closed state is therefore
   the same `translateX(110%)` in every language; adding a `html[dir="rtl"]` leg here would
   re-introduce the bug EDIT-V67 removed. Measured identical in all three: closed box
   [837,1157] visible 0, open box [500,820] visible 320 at a 820px viewport.

   THE CTA STAYS, and that is the one deliberate difference from the phone layout. Line 1858
   hides `.nav__actions .btn--sm` below 760; this block does NOT repeat that, because tablets
   carry real traffic and "Get in touch" is a conversion control. Checked it fits at the
   narrow end: at 761px the logo ends at x=146 and the button starts at x=416 — 270px of
   clear space — in English ("Get in touch", 134px wide, the longest of the three) and 305px
   in Persian. Row height 46px, no collision, no horizontal overflow.

   DESKTOP UNTOUCHED: 13 nav elements x 11 properties compared with this block on and off at
   901 / 1024 / 1440 -> zero differences at all three.
   ========================================================= */
@media (min-width: 761px) and (max-width: 900px) {
  html body .nav .nav__links {
    position: fixed; top: 0; inset-inline-end: 0; z-index: 990;
    height: 100svh; width: min(80vw, 320px);
    flex-direction: column; gap: 6px;
    padding: 100px 26px 40px;
    background: var(--surface);
    border-inline-start: 1px solid var(--line);
    transform: translateX(110%);
    transition: transform .45s var(--ease);
  }
  html body .nav .nav__links.is-open { transform: translateX(0); }
  html body .nav__links a { width: 100%; font-size: 16px; padding: 14px 16px; }
  html body .nav__burger { display: flex; position: relative; z-index: 1002; }
}

/* ===================== EDIT-V90 — THE PRINT STYLESHEET =====================
   The sheet had NO @media print block and none of its 153 media queries named a
   media type, so every one of them applied to print as well. An A4 page at 96dpi
   is 794 CSS px wide, which is <= 900, so THE PRINTER RECEIVED THE MOBILE LAYOUT.
   Measured on f1-fa.html at 794x1123 before this block:
     - 8.4 A4 sheets for one product page (9456px), hero alone 1398px
     - 11 fixed/sticky elements, four of them full-page (.ambient, .f-page-aura,
       .pgx, .nav__mobile-backdrop) — a fixed box repeats on every printed sheet
     - the nav printed a burger icon and no menu (the links are position:fixed)
     - EVERY gradient headline printed BLANK: .gradient-text, .bigstat__n,
       .ht-ch.ht-grad, .nf__code and friends paint their colour from a background
       image via background-clip:text with color:transparent. The printer drops
       background images by default, so the model name, the big stat numbers and
       the accent word of every headline came out as nothing at all.
     - with backgrounds dropped, --text #f5ebd8 on white paper measures 1.18:1.
       WCAG AA wants 4.5:1. The body copy was effectively invisible.
     - with "background graphics" switched ON instead, 8.4 sheets of #0c0907.

   Both outcomes were unusable, and the audience for a printed page here is a
   dealer or distributor holding a spec sheet — so it is worth getting right.

   THE ONE STRUCTURAL DECISION. Every section on this site is built the same way:
   an absolutely-positioned backdrop image, a scrim over it, and the copy in
   normal flow on top. On screen that is the whole look. On paper the text lands
   on a dark photograph. So in print the backdrops and scrims are dropped and the
   product photography is pulled OUT from behind the copy and stacked above it.
   Text then always sits on white, and each section collapses to its own height.

   MEASURED AFTER (same page, same width):
     sheets 8.4 -> 5.6 | text below WCAG AA: 0 | visible fixed/sticky: 0
     spec-table rows with dark text: 8 of 8 | horizontal overflow: 0

   SCREEN IS UNTOUCHED BY CONSTRUCTION — everything below is inside @media print,
   which a browser does not consult when painting to a display.
   ========================================================= */
@media print {
  @page { size: A4; margin: 14mm 12mm; }
  
  /* --- 1. the paper --------------------------------------------------- */
  :root {
    --bg: #ffffff; --bg-2: #ffffff; --surface: #ffffff; --surface-2: #f6f3ee;
    --text: #1a1208; --muted: #4a4033; --dim: #5b5040;
    --line: rgba(0,0,0,.20); --line-2: rgba(0,0,0,.34);
    /* every accent in the palette is a light gold built for a near-black ground.
       On white the brightest of them (#f0d088) measures 1.49:1. Re-derive them
       dark: #6b5518 measures 7.18:1 and keeps the warm brand character. */
    --blue: #6b5518; --blue-br: #6b5518; --cyan: #6b5518; --violet: #5b4a24;
    --green: #4a5a28; --red: #8a2f2f;
    --gold: #6b5518; --gold-br: #6b5518; --gold-deep: #4f3f14;
    --grad: none; --grad-soft: none;
  }
  
  /* four literals bypass the palette entirely and were measured below AA:
     .v2x-swatch #e9e0c4 (1.32:1), .v2x-swatch.is-active #fff (1.00:1 — invisible),
     .v2x__copy > p and .page-hero__sub #d9cba6 (1.61:1). */
  .v2x-swatch, .v2x-swatch.is-active, button.v2x-swatch.is-active,
  .v2x__copy > p, .page-hero__sub, .v2x-colours__legend,
  .v0core-cgrid figcaption, figcaption, .post__cat, .camshot__tag {
    color: #1a1208 !important; -webkit-text-fill-color: #1a1208 !important;
  }
  .spec-card h4, .v2x-hero__chips b, .v2x__chips span, .v2x-display__stats b {
    color: #6b5518 !important; -webkit-text-fill-color: #6b5518 !important;
  }
  html, body { background: #fff !important; color: #1a1208 !important; overflow: visible !important; height: auto !important; }
  body.is-loading { overflow: visible !important; }
  
  /* --- 2. gradient headlines print BLANK without this ------------------ */
  .gradient-text, .gradient-text.em, .gradient-text.glint,
  .bigstat__n, .bigstat__n.odo-done, .ht-ch.ht-grad, .nf__code,
  .hero__title .em, .hstat__n, .hstat__n.odo-done,
  .hstat__n .odo > span:not(.odo-col),
  .v2x__big.odo-done, .v2x-hero__model.odo-done, .v2x-hero__model {
    background: none !important; background-image: none !important;
    -webkit-background-clip: border-box !important; background-clip: border-box !important;
    -webkit-text-fill-color: #6b5518 !important; color: #6b5518 !important;
    text-shadow: none !important; filter: none !important;
  }
  
  /* --- 3. chrome, controls and decoration off the paper ---------------- */
  .nav, .nav__links, .nav__burger, .nav__mobile-backdrop, .nav-ink, .v2x-subnav,
  .annbar, .annbar__x, .skip-link, .totop, .dotnav, .scroll-progress,
  .cursor, .cursor__dot, .cursor__ring,
  .preloader, .vi, #vintro, .start-loadwrap,
  .modal, .modal__scrim, .newsmodal, .lightbox, .imglb, .copychip,
  .hero__scroll, .v2x-hero__scroll, .hero__dust, .hero__video, .filmband__video,
  .ambient, .ambient__grid, .orb, .pgx, .sec-line,
  .f-page-aura, .f2-page-aura, .f4-page-aura, .v0-page-aura, .v01-page-aura,
  .v1c-aura, .v11-hero__glow, .fhero-duo__sheen, .reveal__aura, .unf__aura,
  .cta__glow, .cta__bg, .modal__glow, .ph-accent-aura, .box3d__reflection,
  .marquee, .filters, .footer__social, .contact-form,
  .btn, .v2x-hero__cta, .cta, .model__toggle, .unf__hint {
    display: none !important;
  }
  
  /* --- 4. release viewport-sized boxes: 8.4 sheets -> a sane document --- */
  section, .section, .hero, .v2x, .v2x-hero, .v2x-display, .reveal, .reveal__sticky,
  .showcase, .show-panel, .filmband, .unf__stage, .v2x-colours__stage, .goldband,
  .fcol-stage, .v0core-cgrid, .v2x-colours, .v11-trio, .v2lite-gallery__grid {
    height: auto !important; min-height: 0 !important; max-height: none !important;
    padding-top: 7mm !important; padding-bottom: 7mm !important;
  }
  .v2x-hero, .hero { padding-top: 0 !important; }
  /* EDIT-V70 pins this with !important at (0,3,2) and EDIT-V86/87/88 at (0,4,2).
     A plain .v2x-hero__copy is (0,1,0) and loses silently — repeat the class to clear both. */
  html body .v2x-hero.v2x-hero.v2x-hero .v2x-hero__copy { padding-top: 0 !important; padding-bottom: 0 !important; }
  
  /* Every section on this site is the same shape: an absolutely-positioned
     BACKDROP image plus a scrim, with the copy in normal flow on top. On screen
     that reads beautifully; on paper the text lands on a dark photograph and
     becomes unreadable, and the photo burns a cartridge. Drop the backdrops and
     the scrims — the copy then stands alone on white and the section collapses
     to the height of its own text. In-flow images are CONTENT and are kept. */
  .v2x__scrim, .v0-herobg, .v2x-hero__bg,
  .v1c-hero__scrim, .v1c-hero__fade, .hero__bg, .hero__scrim, .filmband__scrim,
  .v2x-hero::after, .v2x-hero::before, .v2x::after, .v2x::before {
    display: none !important;
  }
  
  /* the section photography is real product content, so keep it — but pull it
     OUT from behind the copy and stack it above, so no text sits on a photo */
  .v2x__bg, .v1c-hero__edge {
    position: static !important; inset: auto !important; transform: none !important;
    display: block !important; width: auto !important; height: auto !important;
    max-height: 70mm !important; max-width: 100% !important;
    margin: 0 auto 5mm !important; object-fit: contain !important;
  }
  
  /* the product renders ARE the point of a spec sheet: pull them into the flow
     above the copy instead of behind it */
  .v2x-hero { display: block !important; max-height: none !important; overflow: visible !important; }
  .fhero-duo, .v0-phones, .v2pro-phones, .v11-hero__phone {
    position: static !important; inset: auto !important; transform: none !important;
    width: auto !important; height: auto !important; max-height: 85mm !important;
    margin: 0 auto 6mm !important; display: block !important;
  }
  .fhero-duo { display: flex !important; justify-content: center !important; gap: 6mm !important; }
  .fhero-duo img { max-height: 85mm !important; width: auto !important; }
  
  /* --- 5. scroll-revealed content must be visible on paper ------------- */
  [data-anim], [data-anim="fade"], .mask__in, .reveal, .in,
  .v2x-hero__chips, .v2x__chips {
    opacity: 1 !important; transform: none !important; visibility: visible !important;
    clip-path: none !important;
  }
  
  /* --- 6. imagery: keep it, but never let one photo own a whole sheet -- */
  img, picture, video, canvas, svg {
    max-width: 100% !important; height: auto !important;
    max-height: 105mm !important; object-fit: contain !important;
    filter: none !important; box-shadow: none !important; animation: none !important;
  }
  .f-keymap > img { max-height: none !important; }
  
  /* --- 7. type that was sized against the viewport --------------------- */
  body { font-size: 10.5pt !important; line-height: 1.5 !important; }
  h1, .v2x-hero__title, .hero__title { font-size: 22pt !important; line-height: 1.2 !important; }
  h2, .section__title { font-size: 16pt !important; line-height: 1.25 !important; }
  h3, h4 { font-size: 12pt !important; }
  .section__sub, .v2x-hero__sub { font-size: 10.5pt !important; }
  .eyebrow { font-size: 8.5pt !important; letter-spacing: .12em !important; color: #6b5518 !important; }
  
  /* --- 8. tables, cards and page breaks -------------------------------- */
  .spec-card, .v2x-specs__row, .model__key-row, .v2x-box__grid li, figure, tr, li {
    break-inside: avoid !important; page-break-inside: avoid !important;
  }
  h1, h2, h3, h4 { break-after: avoid !important; page-break-after: avoid !important; }
  .section.v2x-specs, .v2x-display { break-before: auto !important; }
  .spec-card, .v2x-specs__row { border-color: rgba(0,0,0,.20) !important; background: #fff !important; }
  
  /* --- 9. flatten every remaining dark panel and effect ---------------- */
  *, *::before, *::after {
    background-image: none !important;
    box-shadow: none !important; text-shadow: none !important;
    animation: none !important; transition: none !important;
    backdrop-filter: none !important; mix-blend-mode: normal !important;
  }
  .footer { border-top: 1px solid rgba(0,0,0,.2) !important; }
  a { color: #6b5518 !important; text-decoration: none !important; }
}

/* ===================== EDIT-V91 — V2 Pro: mobile crops re-aimed onto their subjects =====
   MOBILE LAYER ONLY (max-width: 900px). Desktop is not reached by this block.

   WHY. The full-bleed `.v2x` sections are `min-height: 100vh` (line 2744) and their
   `.v2x__bg` is `object-fit: cover` (line 2746). On a phone that means a 16:9 LANDSCAPE
   photograph is being poured into a portrait box — measured at 390x844, the image box is
   437x945 (the extra 12% is the GSAP parallax overscan, which is deliberate), so only
   **26% of each photograph is on screen**, taken from the dead centre.

   Reviewed all twelve content images on the page with the user, one at a time. Six were
   already fine (v2pro-phones, the three cam-* thumbnails, v2pro-screen-hand, v2pro.png).
   Of the six full-bleed backdrops, three were judged acceptable as centre crops because
   their subject happens to sit mid-frame — v2pro-cam-macro, v2pro-chip, v2pro-network —
   and are deliberately left alone. The three below were not.

   THE OVERSHOOT WORTH RECORDING. The first attempt used `object-position: right center`.
   That is 100%, and it went too far: on v2pro-selfie it framed the man's shoulder and the
   wall with his face off the left edge, and on v2pro-life it framed blurred fingers with
   the phone off-frame. The subject is not AT the right edge, it is about 70% across, so
   the correct value has to be solved rather than guessed:
     visibleCentre/SW = (SW - BW)*X/100/SW + BW/(2*SW)
   With SW = naturalW * (boxH/naturalH) and BW = 437, aiming the window centre at the
   subject gives X = 77% for v2pro-selfie and 76% for v2pro-life. Verified visually: face
   fully in frame, and the camera module legible in the hand.

   `object-position` percentages are physical, so fa, ar and en all frame identically.

   THE BATTERY SECTION is a diagonal composition that loses both ends of the handset to any
   centre crop, so instead of re-aiming it the section itself is shortened: 100vh -> 62svh
   takes the image box from 437x945 to 437x586 and the visible share from 34% to 55%.
   `:has()` scopes that to the one section without touching three HTML files; the sheet
   already requires container queries and svh, which are the same browser generation.

   All three files are used ONLY by v2-pro.html / -fa / -ar (checked), so the src-attribute
   selectors cannot reach another model.
   ========================================================= */
@media (max-width: 900px) {
  html body img.v2x__bg[src*="v2pro-selfie"] { object-position: 77% center; }
  html body img.v2x__bg[src*="v2pro-life"]   { object-position: 76% center; }
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v2/battery"]) { min-height: 62svh; }
}

/* ===================== EDIT-V92 — V2: mobile crops re-aimed and sections shortened =====
   MOBILE LAYER ONLY (max-width: 900px). Same problem and same method as EDIT-V91.

   All twelve content images on v2 were reviewed with the user at 390px. Seven were already
   fine: v2-hero-mobile.webp (the dedicated vertical crop from the hero round, 87% visible),
   the five s1-s5.jpg camera samples and v2-luxury.webp (all 100%). The five full-bleed
   `.v2x__bg` backdrops were all showing 26% — a 1600x900 landscape poured into a 437x945
   portrait box.

   Per-image decisions, each taken by the user after seeing the whole frame with the mobile
   window drawn on it:
     v2-camera        26 -> 42%   section 62svh. The camera module was already centred; the
                                  height cut brings the "50MP" backdrop lettering back.
     v2-gyro          26 -> 36%   62svh + 78%. The WORST of the five: the board sits hard
                                  right, so the centre crop was framing empty black. Mobile
                                  users were looking at a dark rectangle.
     v2-battery-life  26 -> 42%   62svh + 62%. The centre crop bisected the camera module.
     v2-slim          26 -> 59%   44svh, a deeper cut than the others and deliberately so:
                                  the shot is an EDGE-ON profile, a thin horizontal band, so
                                  a portrait crop destroyed the one thing it exists to show.
     v2-leather       26 -> 26%   62% only, height untouched. The leather texture IS the
                                  subject here, so the crop share does not matter; the fix is
                                  that the handset was being cut in half down its middle.

   Mobile page height 13,714 -> 12,359px. No horizontal overflow at 390.
   All five files are used ONLY by v2.html / -fa / -ar (checked), so the src-attribute
   selectors cannot reach another model.
   ========================================================= */
@media (max-width: 900px) {
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v2-camera"])       { min-height: 62svh; }
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v2-gyro"])         { min-height: 62svh; }
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v2-battery-life"]) { min-height: 62svh; }
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v2-slim"])         { min-height: 44svh; }

  html body img.v2x__bg[src*="v2-gyro"]         { object-position: 78% center; }
  html body img.v2x__bg[src*="v2-battery-life"] { object-position: 62% center; }
  html body img.v2x__bg[src*="v2-leather"]      { object-position: 62% center; }
}

/* ===================== EDIT-V93 — V2 Lite: mobile crops re-aimed, sections shortened =====
   MOBILE LAYER ONLY (max-width: 900px). Third model in the per-image review; same method and
   same 26%-visible starting point as EDIT-V91 (V2 Pro) and EDIT-V92 (V2).

   Eleven content images reviewed at 390px. Seven were already fine: v2lite-hero-mobile.webp
   (the dedicated vertical crop from the hero round, 87%), v2lite-05, -08, -09 and the three
   gallery frames g1/g2/g3 (81-100%). The four `.v2x__bg` backdrops were all at 26%.

     v2lite-03   26 -> 42%   62svh. Two handsets in shot; the centre crop cut the second one
                             in half. The height cut fits both.
     v2lite-06   26 -> 42%   62svh + 38%. Camera module sits LEFT of centre and the crop's
                             left edge was slicing through the gold ring.
     v2lite-07   26 -> 59%   44svh. The same edge-on profile problem as v2-slim in EDIT-V92 —
                             a thin horizontal band that a portrait crop destroys. Same 44svh
                             answer, and it works for the same reason.
     v2lite-10   26 -> 42%   62svh + 31%. Handset stands hard LEFT; the centre crop was
                             showing a strip of dark green body and nothing identifiable.

   NOTE THE DIRECTION FLIP. V2's subjects sit right of centre (78%, 62%, 62%); V2 Lite's sit
   left (38%, 31%). There is no house rule to apply here — each photograph has to be looked at.

   Mobile page height 12,816 -> 12,211px. No horizontal overflow at 390.
   All four files are used ONLY by v2-lite.html / -fa / -ar (checked).
   ========================================================= */
@media (max-width: 900px) {
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v2lite-03"]) { min-height: 62svh; }
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v2lite-06"]) { min-height: 62svh; }
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v2lite-07"]) { min-height: 44svh; }
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v2lite-10"]) { min-height: 62svh; }

  html body img.v2x__bg[src*="v2lite-06"] { object-position: 38% center; }
  html body img.v2x__bg[src*="v2lite-10"] { object-position: 31% center; }
}

/* ===================== EDIT-V94 — V11: crop re-aimed, colour frames made tall =====
   MOBILE LAYER ONLY (max-width: 900px). Fourth model in the per-image review.

   Fifteen content images checked at 390px — the largest set of any model. Eleven were already
   fine: v11-hero-float (the floating render from the hero round, contain, 100%), the three
   before/noise/after comparison frames, v11-selfie / -display / -batt, v11-2 and the three
   54px icons. Three needed work, and one of them is a NEW failure mode.

     v11-4     38 -> 42%   56svh + 30%. Two handsets in shot; the centre crop framed one and
                           dropped the other entirely.
     v11-chip  26%         LEFT ALONE by the user's call — the chip happens to sit dead centre
                           and survives the crop intact, like v2pro-chip.

   THE NEW FAILURE MODE: the colour swatches crop VERTICALLY, not horizontally.
   v11-light and v11-grey are 673x2100 — extremely tall portraits of the whole back of the
   handset. Their frame is `aspect-ratio: 4/5` below 700px (line 2974), which is almost square,
   so the image was scaled to match WIDTH and then cut top and bottom: the camera module and
   the VOCAL logo were BOTH outside the frame and all a phone user saw was the iridescent
   middle of the body — a colour, but not a recognisable product, which defeats the point of a
   colour swatch. `aspect-ratio: 2/5` takes them from 40% to 80% and both ends come back.
   Everything before this was a landscape photo losing its sides; this is the mirror image of
   that, and it is worth checking for on every remaining model.

   A LIMIT WORTH RECORDING: on v11-4, min-height could NOT deliver what was asked (both
   handsets). Measured: min-height 56svh = 473px, but the section came out 758px because its
   COPY is 421px tall and content sets the real height — min-height is only a floor. The height
   lever runs out early on any section with a long text block; object-position is what worked.

   Scope: v11-4, v11-light and v11-grey are used only by v11.html / -fa / -ar, and
   .v11-colours only exists on those three pages (checked).
   ========================================================= */
@media (max-width: 900px) {
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v11-4"]) { min-height: 56svh; }
  html body img.v2x__bg[src*="v11-4"] { object-position: 30% center; }
  html body .v11-colours .v2-colours__pair img { aspect-ratio: 2 / 5; }
}

/* ===================== EDIT-V95 — V1: two full-bleed sections shortened =====
   MOBILE LAYER ONLY (max-width: 900px). Fifth model in the per-image review.

   Seven content images at 390px — the smallest set. Four were already fine: v1-hero-mobile
   (the file the user supplied in the hero round, 100%), v1-design, v1-life, and v1-blue,
   whose colour frame is SQUARE (1024x1024) and so does not have the tall-portrait problem
   that bit V11's swatches in EDIT-V94.

     v1-display  26 -> 46%   56svh. The crop kept the teardrop notch but lost both edges of
                             the handset, so the shape of the device was unreadable.
     v1-camera   26%         LEFT ALONE by the user's call. The module sits dead centre and
                             everything around it is near-black body with no information.
     v1-charge   23 -> 52%   40svh. THE WORST SINGLE IMAGE FOUND SO FAR on any model. It is
                             1400x690 (ratio 2.03, the most elongated on the site) showing a
                             handset on the diagonal with its charging cable — and the centre
                             crop cut the cable out completely. A "charging" section with no
                             cable in it.

   BOTH HIT THE CONTENT FLOOR, which is now a recurring limit worth naming: min-height is only
   a floor, so a section cannot go below the height of its own copy. v1-charge came out at
   exactly 371px with a 371px copy — 52% is the most this lever can give there. Recorded so the
   next person does not keep lowering the number expecting more.

   Mobile page height 10,189 -> 9,503px. No horizontal overflow at 390.
   Both files are used only by v1.html / -fa / -ar (checked).
   ========================================================= */
@media (max-width: 900px) {
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v1-display"]) { min-height: 56svh; }
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v1-charge"])  { min-height: 40svh; }
}

/* ===================== EDIT-V96 — V01: two full-bleed sections shortened =====
   MOBILE LAYER ONLY (max-width: 900px). Seventh model reviewed.

   V1 CORE (sixth) NEEDED NOTHING and no block was written for it: both of its full-bleed
   backdrops, v1core-cam and v1core-chip, put their subject dead centre and survive the crop
   intact, and its colour strip is a wide in-flow image at 100%.

   V01: ten content images at 390px, eight already fine — including its two colour swatches,
   which are 620x940 and so read at 82% in the 4/5 frame. That is worth contrasting with V11's
   swatches in EDIT-V94: those were 673x2100, far more elongated, and fell to 40%. The frame is
   the same; only the source aspect differs. Do not assume a colour swatch is safe — measure it.

     v01s-portrait  26 -> 46%   56svh.
     v01/selfie     31 -> 56%   56svh PLUS zeroing the copy's margins, and that second part is
                                the interesting bit.

   WHY min-height ALONE FAILED ON THE SELFIE SECTION. Setting 56svh (472.64px) left the section
   at 699px. The copy is only 362px, so the content floor should have been well under the gate.
   Measured cause: that copy carries the `m3t` class, which gives it margin-top 84.4px and
   margin-bottom 253.2px — a desktop composition device that drops the text into the lower
   third. 362 + 84 + 253 = 699. The margin, not the text, was the floor. Zeroing both margins
   for this one section on mobile takes it to 473px and the image from 31% to 56%.

   That trades the copy's lower-third placement for centring, on mobile only, on one section.
   Flagged to the user as going beyond "shorten the section" and approved explicitly.
   **Check for margin-based floors before concluding min-height has run out.**

   Mobile page height 12,357 -> 12,130px. No horizontal overflow at 390.
   Both files are used only by v01.html / -fa / -ar (checked).
   ========================================================= */
@media (max-width: 900px) {
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v01s-portrait"]) { min-height: 56svh; }
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v01/selfie"])    { min-height: 56svh; }
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v01/selfie"]) .v2x__copy {
    margin-top: 0; margin-bottom: 0;
  }
}

/* ==========================================================================
   EDIT-V97 — V0 Core: per-image mobile framing (mobile layer only)
   v0core-config : the internals line-drawing is symmetric (edge-energy
     centroid 49.0%), so the centre crop is right; it was only too tight.
     844px section -> content floor 491px lifts the visible band 31% -> 53%.
   v0core-design : the handset sits at natural x 1040-1450 of 1600. Centred,
     the mobile band was 592-1008 — the phone was entirely OUTSIDE the frame
     and the section rendered as a bare grey wall. Height cap widens the band
     to 679 natural px; the admissible object-position range is then
     83.7%-100%, and 92% centres the subject without pulling the empty right
     wall in. Band becomes 847-1526: the whole phone, with breathing room.
   Both sections are now floored by their own copy (491 / 517), so the
   min-height lever is spent. Desktop untouched — gated at 900px.
   ========================================================================== */
@media (max-width: 900px) {
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v0core-config"]) { min-height: 56svh; }
  html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v0core-design"]) { min-height: 56svh; }
  html body img.v2x__bg[src*="v0core-design"] { object-position: 92% center; }
}

/* ==========================================================================
   EDIT-V98 — F1: mobile framing for the "always on" photo (mobile layer only)
   f1-hand is 1600x900. Everything left of natural x 800 is a flat grey wall
   (per-column edge energy 0.0); the hand and handset occupy 845-1225. The
   mobile band is 416 natural px wide, and centred it ran 592-1008 — half
   empty wall, and the frame's right edge cut straight down the middle of the
   handset. Band width 416 vs subject width 380 means the crop is very nearly
   a snug fit, so the admissible range is narrow: left must satisfy
   [809 ... 845] to hold the subject, and 70% puts it at 829-1245 — the whole
   phone plus the holding hand, minimal dead wall.
   No min-height cap here: shortening only widens the band into more grey.
   Verified at 360/390/430/899 (subject inside at every one) and at 901 the
   gate releases and desktop reads 50% as before.
   ========================================================================== */
@media (max-width: 900px) {
  html body img.v2x__bg[src*="f1-hand"] { object-position: 70% center; }
}

/* ==========================================================================
   EDIT-V99 — index: clear the "packaging" eyebrow from the rotating box
   (mobile layer, Persian + Arabic only)
   .unf__stage is 320px tall but .box3d is a 3D box that TURNS, so its border
   box breathes between 329px and 354px across a revolution — sampled over 48
   frames. At its widest it spills 24px below the stage, while the eyebrow sat
   only 14px below it: at those angles the box crossed the pill by 10px.
   34px of extra lead puts the pill 48px below the stage, i.e. 24px clear of
   the worst rotation. The bottom margin drops 22 -> 6 so the title follows by
   only 18px instead of 34 (the user chose the compact variant over moving the
   whole copy block).
   Scoped to [dir="rtl"] because English is a later round — the same overlap
   exists there and this rule is ready to widen when it is.
   ========================================================================== */
@media (max-width: 900px) {
  html[dir="rtl"] .unforgettable .unf__copy .eyebrow {
    margin-top: 34px;
    margin-bottom: 6px;
  }
}

/* ==========================================================================
   EDIT-V100 — V2 Pro: per-section mobile alignment (Persian + Arabic only)
   Reviewed all 15 sections at 390x844 with the user; nine keep the alignment
   they had. The six below were decided one at a time:

     cam-macro  eyebrow to the right edge, copy 92px lower
     selfie     eyebrow AND the big "50MP" to the right, copy 129px lower
     chip       copy 123px lower, and the spec chips right-aligned - their row
                was centred, which left the lone "5G" chip stranded mid-line
     battery    eyebrow only; the copy already fills its 523px section
     network    stays centred but 145px HIGHER: at the old centre the copy sat
                on the glowing city lines, and this lifts it onto plain sky
     life       eyebrow to the right, copy 141px lower

   TWO TRAPS worth remembering.
   (1) margin-inline is LOGICAL: in RTL `auto 0` puts the free space on the
       right and shoves the box LEFT - the opposite of the intent. The value
       that right-aligns a fit-content block here is `0 auto`.
   (2) An existing rule pins these eyebrows with !important, so the logical
       property alone loses; the declarations below need !important too.

   SCOPE. Each rule is tied to its own section's background image via :has().
   The generic form `.v2x--right .v2x__copy.m2l.flush-l` also matches sections
   on v0-core, v01, v1-core and v2 - pages the user has not reviewed yet.
   ========================================================================== */
@media (max-width: 900px) {
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v2pro-cam-macro"]) .v2x__copy .eyebrow,
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="v2pro-selfie"]) .v2x__copy .eyebrow,
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="v2pro-selfie"]) .v2x__copy .v2x__big,
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="v2/battery"]) .v2x__copy .eyebrow,
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="v2pro-life"]) .v2x__copy .eyebrow {
    margin-inline: 0 auto !important;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v2pro-cam-macro"]) .v2x__copy,
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="v2pro-selfie"]) .v2x__copy,
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="v2pro-life"]) .v2x__copy {
    align-self: flex-end;
    margin-bottom: 100px;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v2pro-chip"]) .v2x__copy.perf-c {
    align-self: flex-end;
    margin-bottom: 40px;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v2pro-chip"]) .v2x__copy.perf-c .v2x__chips {
    justify-content: flex-start;
  }
  html[dir="rtl"] section.v2x--center:has(> img.v2x__bg[src*="v2pro-network"]) .v2x__copy--mid {
    align-self: flex-start;
    margin-top: 120px;
  }
}

/* ==========================================================================
   EDIT-V101 — V2: per-section mobile alignment (Persian + Arabic only)
   All 14 sections reviewed with the user at 390x844; ten keep what they had.
   Four changed, each decided on its own:

     v2-camera   stays centred; artwork 30px up, copy 50px down (its `top`
                 was -50px, a rule that had pulled the copy off the section)
     v2-gyro     centred; the "performance" eyebrow centred with it, the four
                 spec chips turned from a 4-row column into ONE right-aligned
                 row, copy 56px down, artwork 55px up
     v2-slim     right-aligned, copy dropped 140px INTO the section and the
                 artwork 38px up. Its copy sat at top:-140px, which pushed the
                 "8.5mm" figure and the eyebrow off the top of the phone
                 screen entirely - on mobile they were simply not visible
     v2-leather  eyebrow right, three chips into one right-aligned row, copy
                 160px down

   HOW FAR "as far as it goes" ACTUALLY GOES. The artwork can only travel by
   the parallax overhang: `scale(1.12)` leaves ~31px above and below on a
   523px section, more on a taller one (58px here). Past that a gap opens at
   the section's bottom edge. Downward copy travel stops at 48px, not 20px:
   the fixed "back to top" button sits 16px from the left, 46px tall, and at
   20px it covered the third chip by 28px.

   CHIP ROWS AND THE FONT. Turning a stacked chip column into one row is not
   free. In v2-gyro the four chips fit at the normal 12.5px in BOTH languages
   (fa 337px, ar 326px, against a 343px column). In v2-leather they do not:
   at 12.5px each chip's own text wraps to two lines, and single-line needs
   11px for Persian but 10px for Arabic - the Arabic strings are longer there.
   fa and ar must match, so both take 10px. Verified per language, per chip.

   Two overrides needed !important because existing rules win otherwise:
   `justify-content` on .v2x__chips (the sheet pins it to flex-end, which is
   LEFT in RTL) and the flex direction.

   Scoped by background image; all four files are unique to this page.
   ========================================================================== */
@media (max-width: 900px) {
  /* --- camera ------------------------------------------------------- */
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v2-camera"]) img.v2x__bg { margin-top: -30px; }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v2-camera"]) .v2x__copy { top: 0; }

  /* --- chip / gyro -------------------------------------------------- */
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v2-gyro"]) .v2x__copy {
    text-align: center !important;
    padding-top: 132px;
    padding-bottom: 20px;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v2-gyro"]) .v2x__copy .eyebrow {
    margin-inline: auto !important;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v2-gyro"]) .v2x__copy .v2x__chips {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: center;
    justify-content: flex-start !important;
    gap: 6px;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v2-gyro"]) .v2x__copy .v2x__chips > * {
    padding-left: 10px;
    padding-right: 10px;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v2-gyro"]) img.v2x__bg { margin-top: -55px; }

  /* --- slim --------------------------------------------------------- */
  html[dir="rtl"] section.v2x--center:has(> img.v2x__bg[src*="v2-slim"]) .v2x__copy--mid {
    text-align: right !important;
    top: 0;
  }
  html[dir="rtl"] section.v2x--center:has(> img.v2x__bg[src*="v2-slim"]) img.v2x__bg { margin-top: -38px; }

  /* --- leather ------------------------------------------------------ */
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="v2-leather"]) .v2x__copy .eyebrow {
    margin-inline: 0 auto !important;
  }
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="v2-leather"]) .v2x__copy .v2x__chips {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: center;
    justify-content: flex-start !important;
    gap: 5px;
  }
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="v2-leather"]) .v2x__copy .v2x__chips > * {
    padding-left: 8px;
    padding-right: 8px;
    font-size: 10px;
    white-space: nowrap;
  }
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="v2-leather"]) .v2x__copy {
    align-self: flex-end;
    margin-bottom: 48px;
  }
}

/* ==========================================================================
   EDIT-V102 — V2 Lite: per-section mobile alignment (Persian + Arabic only)
   All 14 sections reviewed; twelve already matched the decisions taken on
   v2-pro and v2, so only two changed:

     v2lite-10 (battery)  everything was already right-aligned except the
                          eyebrow, which sat centred at 146px. Same fix as the
                          v2-pro battery block.
     v2lite-07 (slim)     copy dropped 140px into the section. It carries the
                          same top:-140px anchor as v2's slim block, which put
                          the "8.5mm" figure and the eyebrow above the section
                          and therefore off a phone screen entirely. Unlike v2
                          the user kept this one CENTRED and left the artwork
                          alone - only the vertical move.

   Verified per language: in Arabic the battery eyebrow lands on the same 23px
   column, and the slim copy measures the same 359px in the same 371px section
   (6px clear top and bottom), so both rules behave identically in fa and ar.

   Scoped by background image; both files appear only on this page.
   ========================================================================== */
@media (max-width: 900px) {
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="v2lite-10"]) .v2x__copy .eyebrow {
    margin-inline: 0 auto !important;
  }
  html[dir="rtl"] section.v2x--center:has(> img.v2x__bg[src*="v2lite-07"]) .v2x__copy--mid {
    top: 0;
  }
}

/* ==========================================================================
   EDIT-V103 — V11: per-section mobile alignment (Persian + Arabic only)
   Horizontal alignment on this page already matched every decision taken on
   v2-pro, v2 and v2-lite: eleven centred heads and a centred hero, and the
   two photo sections already right-aligned with their eyebrow on the 23px
   column. Nothing to do there.

   What DID need work was vertical. Both photo blocks carry .m3t, which sets
   margin-top 84.4px / margin-bottom 253.2px - the copy clings to the top of
   the section and a quarter of the section sits empty underneath, with the
   text landing on the camera lens (v11-4) and on the chip die (v11-chip).
   Swapping the margins to 290/48 drops the copy clear of both subjects.

   v11-chip's three chips were centred and broke 2+1. Unlike the v2 leather
   block, one row needed NO font change here: 336px of chips plus 2x10px gaps
   came to 356 against a 343 column, only 13px over, and trimming the chip
   padding 14->10 with the gap 10->6 brought it to 324 with 19px to spare.
   All three were already single-line at 12.5px.

   Verified in Arabic: identical 290/48 placement, chips in one row at
   23/105/229, zero overflow. (Its section measures 844 against Persian's 854
   - a copy-height difference, not a layout one.)
   ========================================================================== */
@media (max-width: 900px) {
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v11-4"]) .v2x__copy,
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v11-chip"]) .v2x__copy {
    margin-top: 290px;
    margin-bottom: 48px;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v11-chip"]) .v2x__copy .v2x__chips {
    flex-wrap: nowrap !important;
    justify-content: flex-start !important;
    gap: 6px;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v11-chip"]) .v2x__copy .v2x__chips > * {
    padding-left: 10px;
    padding-right: 10px;
  }
}

/* ==========================================================================
   EDIT-V104 — V1: per-section mobile alignment (Persian + Arabic only)
   Eleven sections; nine already matched the earlier decisions. Two changed:

     v1-display  its four spec chips were centred rather than right-aligned.
                 They already filled ONE row - 312px of chips plus 3x10px gaps
                 is 342 against a 343px column - so centring only displaced
                 them by 2px. The user asked for it anyway, so the row now
                 starts on the same 23px column as everything else. No padding
                 or font change was needed.
     v1-camera   copy sat dead centre of an 844px section with 199px empty
                 above and below, and landed squarely on the camera lens.
                 Dropped to 48px off the bottom, which clears the lens.

   Verified in Arabic: the display chips measure 310px (slightly narrower than
   Persian) and still hold one row with zero overflow, and the camera copy
   lands on the same 48px bottom gap (it starts at 305 rather than 351 only
   because the Arabic copy block is taller).

   v1-charge was left alone: its copy is exactly as tall as its 371px section,
   so there is no vertical room, and .v2x--center stays centred by precedent.
   ========================================================================== */
@media (max-width: 900px) {
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v1-display"]) .v2x__copy .v2x__chips {
    justify-content: flex-start !important;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v1-camera"]) .v2x__copy {
    align-self: flex-end;
    margin-bottom: 48px;
  }
}

/* ==========================================================================
   EDIT-V105 — V1 Core: per-section mobile alignment (Persian + Arabic only)
   Nine of eleven sections already matched the earlier decisions. Two changed:

     v1core-cam   the eyebrow was pinned to the LEFT edge by .flush-l while
                  the title, copy and its three spec chips were all already on
                  the 23px right column. Only the eyebrow moved.
     v1core-chip  three chips broke 2+1. One row needs 44px saved: chip
                  padding 14->8 and the gap 10->5 gives exactly that.

   THE CHIP ROW HERE IS TIGHT. Persian lands on 341px against a 343px column -
   two pixels of slack, the narrowest margin in this whole pass. Arabic is
   easier at 336. The font is deliberately untouched (the user chose that over
   the safer 11.5px, which would have left 24px). If these three strings are
   ever re-worded, or the font stack changes, this row is the first to break.
   ========================================================================== */
@media (max-width: 900px) {
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v1core-cam"]) .v2x__copy .eyebrow {
    margin-inline: 0 auto !important;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v1core-chip"]) .v2x__copy .v2x__chips {
    flex-wrap: nowrap !important;
    gap: 5px;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v1core-chip"]) .v2x__copy .v2x__chips > * {
    padding-left: 8px;
    padding-right: 8px;
    white-space: nowrap;
  }
}

/* ==========================================================================
   EDIT-V106 — V01: per-section mobile alignment (Persian + Arabic only)
   Eleven of fourteen sections already matched the earlier decisions.

     v01s-portrait  the eyebrow was pinned left by .flush-l while the title,
                    copy and its three chips were all on the 23px column.
                    Eyebrow only - the copy is exactly as tall as its section.
     v01/selfie     copy dropped to 48px off the bottom (it had 111px of dead
                    space under it).

   THE !important ON THAT MARGIN IS NOT DECORATION. EDIT-V96, from the earlier
   image-crop pass, zeroes this very block's margins:
     html body section.v2x[class*="v2x--"]:has(> img.v2x__bg[src*="v01/selfie"])
       .v2x__copy { margin-top: 0; margin-bottom: 0 }
   That is (0,5,3) against this rule's (0,5,2) - three type selectors beat two
   - so without !important the copy slid to a 0px bottom gap instead of 48.
   The section does NOT grow back: copy 362 + 48 margin = 410, still under the
   473px min-height EDIT-V96 gave it, so that block's image framing is intact.

   Left alone deliberately: the "smooth and efficient" chips (Unisoc SC9863A1 /
   octa-core / IMG GE8322) need 399px in a 343px column and trimming padding
   and gaps only recovers 46 of the 56 needed - one row would cost a font drop,
   and their section head is centred anyway, so centred chips read correctly.
   ========================================================================== */
@media (max-width: 900px) {
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v01s-portrait"]) .v2x__copy .eyebrow {
    margin-inline: 0 auto !important;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v01/selfie"]) .v2x__copy {
    align-self: flex-end;
    margin-bottom: 48px !important;
  }
}

/* ==========================================================================
   EDIT-V107 — V0: single-line chip rows (Persian + Arabic only)
   Every one of V0's fourteen sections is a centred head, a centred hero or
   the CTA - the page has no photo-backed .v2x section at all - so its
   horizontal alignment already matched every earlier decision and nothing
   there changed. Two chip rows broke 2+1:
     "UNISOC SC9863A1 / octa-core / IMG GE8322"  needs 363px of a 343 column
     "5000mAh Li-Po / 10W / 24h"                 needs 348px
   Trimming chip padding 14->8 and the gap 10->5 recovers 46px, so both fit on
   one line with the font untouched.

   WHY A NEW CLASS INSTEAD OF A SELECTOR. These rows sit as a direct child of
   their section with only .v2x__chips--center to identify them, and that class
   is used 18 times across EIGHT pages (v01 4, v0 3, v0-core 3, f1/f2/f4 2 each,
   v1-core 1, v2-lite 1). A rule on the class alone would silently restyle four
   pages the user has not reviewed and three already signed off. So the two V0
   sections carry a .chips-1line hook instead, added to all three language
   files so their markup stays identical; the rule below is gated to RTL and to
   mobile, so the English page and every desktop width are untouched.
   ========================================================================== */
@media (max-width: 900px) {
  html[dir="rtl"] .chips-1line .v2x__chips--center {
    flex-wrap: nowrap !important;
    gap: 5px;
  }
  html[dir="rtl"] .chips-1line .v2x__chips--center > * {
    padding-left: 8px;
    padding-right: 8px;
    white-space: nowrap;
  }
}

/* ==========================================================================
   EDIT-V108 — V0 Core: single-line chip rows + one eyebrow
   (Persian + Arabic only)
   Eight of twelve sections already matched the earlier decisions. Four chip
   rows broke 2+1, and they did NOT all cost the same:

     v0core-design  needed 3px  -> padding 14->8, gap 10->5, font untouched.
                    Its eyebrow was also pinned left by .flush-l; moved to the
                    23px column like every other photo section.
     v2-game (§3)   needed 30px -> same trim, font untouched. Reuses the
                    .chips-1line hook introduced by EDIT-V107.
     v0core-config  needed 66px -> the trim only recovers 46, so this one also
                    takes font-size 11.5px.
     v2x-display(§5) needed 64px -> same, 11.5px. New .chips-1line-sm hook.

   WHY 11.5px AND NOT 12. Measured, not guessed: at 12.5px these two rows
   overflow by 10 and 9px, at 12px by 4 and 3px, and at 11.5px they land on
   339 and 337 against a 343px column. 11.5 is the smallest step that fits -
   one pixel down from the site default.

   The two class hooks go in all three language files so the markup stays
   identical; both rules are gated to RTL and to mobile, so English and every
   desktop width are untouched.
   ========================================================================== */
@media (max-width: 900px) {
  html[dir="rtl"] .chips-1line-sm .v2x__chips--center {
    flex-wrap: nowrap !important;
    gap: 5px;
  }
  html[dir="rtl"] .chips-1line-sm .v2x__chips--center > * {
    padding-left: 8px;
    padding-right: 8px;
    font-size: 11.5px;
    white-space: nowrap;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v0core-config"]) .v2x__chips {
    flex-wrap: nowrap !important;
    gap: 5px;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v0core-config"]) .v2x__chips > * {
    padding-left: 8px;
    padding-right: 8px;
    font-size: 11.5px;
    white-space: nowrap;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v0core-design"]) .v2x__copy .eyebrow {
    margin-inline: 0 auto !important;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v0core-design"]) .v2x__chips {
    flex-wrap: nowrap !important;
    gap: 5px;
  }
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="v0core-design"]) .v2x__chips > * {
    padding-left: 8px;
    padding-right: 8px;
    white-space: nowrap;
  }
}

/* ==========================================================================
   EDIT-V109 — F1: per-section mobile alignment (Persian + Arabic only)
   Seven of eleven sections already matched the earlier decisions. Four moved:

     f1-flatlay  eyebrow was CENTRED at 152px while the title and copy were on
                 the 23px column; copy also sat dead centre of an 844px section
                 with 228px empty above and below, landing on the handset and
                 the glasses. Eyebrow to 23, copy 181px down.
     f1-hand     eyebrow was pinned LEFT by .flush-l; copy 193px down, which
                 also clears the text off the screen and keypad that EDIT-V98's
                 70% crop had brought into frame.
     v2x-display three chips broke 2+1, 23px over a 343 column
     v2-game     four chips broke 2+2, 21px over
   Both chip rows fit on one line with the font untouched - the padding 14->8
   and gap 10->5 trim recovers 46 and 63px respectively. They reuse the
   .chips-1line hook from EDIT-V107, added here to both sections in all three
   language files.
   ========================================================================== */
@media (max-width: 900px) {
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="f1-flatlay"]) .v2x__copy .eyebrow,
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="f1-hand"]) .v2x__copy .eyebrow {
    margin-inline: 0 auto !important;
  }
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="f1-flatlay"]) .v2x__copy,
  html[dir="rtl"] section.v2x--right:has(> img.v2x__bg[src*="f1-hand"]) .v2x__copy {
    align-self: flex-end;
    margin-bottom: 48px;
  }
}

/* ---------------------------------------------------------------------------
   EDIT-V110 - f2 - mobile text alignment (RTL only, <=900px)
   Section 1 ("beautiful front, confident back"): the eyebrow pill sat centred
   at 162px from the right and the copy sat dead-centre vertically (228/228).
   Approved: pill onto the 23px right column, copy down to the 48px floor -
   the same treatment as v2-pro s1, v11 camera and f1. 48px is the practical
   floor because the fixed back-to-top button covers anything lower.
   Scoped by background image, not by class: .v2x--left is shared across
   pages, "f2-dark" appears only on the three f2 documents.
   Section 5's six-chip row is deliberately left at two rows - one line needs
   554px against a 343px container, i.e. an ~8px font.
   Desktop and English are untouched: gated on max-width and dir="rtl".
   --------------------------------------------------------------------------- */
@media (max-width: 900px) {
  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="f2-dark"]) .v2x__copy .eyebrow {
    margin-inline: 0 auto !important;
  }

  html[dir="rtl"] section.v2x--left:has(> img.v2x__bg[src*="f2-dark"]) .v2x__copy {
    align-self: flex-end;
    margin-bottom: 48px;
  }
}

/* ---------------------------------------------------------------------------
   EDIT-V111 - f4 - mobile chip row (RTL only, <=900px)
   Section 4 (1200mAh battery): three chips wrapped onto two rows - 396px
   needed against a 343px container in Persian, 360px in Arabic. Approved:
   one row at the native 12.5px font, bought with padding 14->6 and gap
   10->4. That lands Persian at 336 of 343 (7px of slack, the binding case)
   and Arabic at 300 of 343.
   The shipped .chips-1line hook (padding 8, gap 5) is NOT enough here - it
   reaches 350 of 343 and the chips get squeezed - so this is scoped to the
   f4 battery section by its own image. "f4-battery-img" appears only on the
   three f4 documents, so no unreviewed page is touched.
   The row stays centred: its section head is centred, matching every other
   f4 section. Section 5's six-chip row is deliberately left at two rows -
   one line needs 545px against 343px, i.e. an ~8px font.
   Desktop and English are untouched: gated on max-width and dir="rtl".
   --------------------------------------------------------------------------- */
@media (max-width: 900px) {
  html[dir="rtl"] section.v2x-display:has(img[src*="f4-battery-img"]) .v2x__chips--center {
    flex-wrap: nowrap !important;
    column-gap: 4px !important;
  }

  html[dir="rtl"] section.v2x-display:has(img[src*="f4-battery-img"]) .v2x__chips--center > * {
    padding-left: 6px;
    padding-right: 6px;
    white-space: nowrap;
  }
}

/* ---------------------------------------------------------------------------
   EDIT-V112 - ENGLISH (LTR) mobile layer: the approved mirror of V99..V111
   Written as a NEW block gated on html[dir="ltr"] rather than by removing the
   rtl gate from the thirteen Persian blocks. Three reasons: the fa/ar rules
   stay literally untouched so there is no regression path; styles.css keeps
   the append-only property that every upload this session has proved with
   cmp; and vertical placement is direction-agnostic, so the numbers carry
   over unchanged.
   Remember that dir is set at RUNTIME - the language switcher has no hrefs
   and rewrites the page in place - so [dir="ltr"] is the English RENDERING,
   not the English file names. index.html viewed in Persian is dir="rtl" and
   correctly gets the V99..V111 rules instead.

   WHAT IS HERE (34 Persian decisions -> 26 rules):
   - all 18 vertical placements, same numbers as the RTL rules
   - one horizontal fix: the v2lite-10 eyebrow. In LTR it computed
     margin-left: 162.25px / margin-right: 0, i.e. pinned to the RIGHT of a
     left-aligned copy. `margin-inline: 0 auto` is correct in BOTH
     directions, so this is the same declaration as the RTL rule.
   - seven of the fifteen two-line chip rows. English strings are longer
     than Persian, so only these seven reach one line with the font
     untouched (padding 14->6, gap 10->4):
       v2-pro performance 392->332   v11 chip        382->322
       v1 display         390->308   v0-core design  393->333
       v0 display         376->316   v0 game         395->335
       f1 game            374->292
     The other eight need a font drop and the user chose to leave them at
     two rows: v1-core chip 406->346 (3px over), v2 performance 447->365,
     v0-core game 420->360, v0-core display 430->370, v2 leather 463->403,
     f1 display 446->386, f4 battery 454->394.

   WHAT IS DELIBERATELY NOT HERE:
   - the two horizontal moves the RTL blocks make on the v2 gyro and slim
     sections (centre / right-align). The user reviewed those as a separate
     question and kept English as it is, so only the VERTICAL half of those
     two rules is mirrored here.
   - .chips-1line / .chips-1line-sm are NOT reused for the English rows.
     Those hooks sit on five sections across three pages and two of them
     (v0-core game, f1 display) do not fit one line in English - nowrap
     there would squeeze the chips, which is worse than two rows. So the
     three head-centred rows are scoped some other way instead.
     CAREFUL: the two `.v2-game` sections contain NO image of their own, so
     `:has(img[...])` on the section can never match them - a first attempt
     did exactly that and measured as a silent no-op (padding stayed 14px,
     the row stayed at two lines). They are reached by identifying the PAGE
     instead, with `main:has(img[src*=...])` on an image that is unique to
     that page: v0-chip for v0 and f1-battery-img for f1. Verified that each
     appears only in its own three language files and that no page carries
     both, so v0-core's `.v2-game.chips-1line` - which does NOT fit one line
     in English - is left alone.
   --------------------------------------------------------------------------- */
@media (max-width: 900px) {
  /* -- vertical placement -------------------------------------------------- */
  html[dir="ltr"] .unforgettable .unf__copy .eyebrow {
    margin-top: 34px;
    margin-bottom: 6px;
  }

  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v2pro-cam-macro"]) .v2x__copy,
  html[dir="ltr"] section.v2x--left:has(> img.v2x__bg[src*="v2pro-selfie"]) .v2x__copy,
  html[dir="ltr"] section.v2x--left:has(> img.v2x__bg[src*="v2pro-life"]) .v2x__copy {
    align-self: flex-end;
    margin-bottom: 100px;
  }

  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v2pro-chip"]) .v2x__copy.perf-c {
    align-self: flex-end;
    margin-bottom: 40px;
  }

  html[dir="ltr"] section.v2x--center:has(> img.v2x__bg[src*="v2pro-network"]) .v2x__copy--mid {
    align-self: flex-start;
    margin-top: 120px;
  }

  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v2-camera"]) img.v2x__bg { margin-top: -30px; }
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v2-camera"]) .v2x__copy { top: 0; }

  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v2-gyro"]) .v2x__copy {
    padding-top: 132px;
    padding-bottom: 20px;
  }
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v2-gyro"]) img.v2x__bg { margin-top: -55px; }

  html[dir="ltr"] section.v2x--center:has(> img.v2x__bg[src*="v2-slim"]) .v2x__copy--mid { top: 0; }
  html[dir="ltr"] section.v2x--center:has(> img.v2x__bg[src*="v2-slim"]) img.v2x__bg { margin-top: -38px; }

  html[dir="ltr"] section.v2x--center:has(> img.v2x__bg[src*="v2lite-07"]) .v2x__copy--mid { top: 0; }

  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v11-4"]) .v2x__copy,
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v11-chip"]) .v2x__copy {
    margin-top: 290px;
    margin-bottom: 48px;
  }

  html[dir="ltr"] section.v2x--left:has(> img.v2x__bg[src*="v2-leather"]) .v2x__copy,
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v1-camera"]) .v2x__copy,
  html[dir="ltr"] section.v2x--left:has(> img.v2x__bg[src*="f1-flatlay"]) .v2x__copy,
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="f1-hand"]) .v2x__copy,
  html[dir="ltr"] section.v2x--left:has(> img.v2x__bg[src*="f2-dark"]) .v2x__copy {
    align-self: flex-end;
    margin-bottom: 48px;
  }

  /* EDIT-V96 zeroes the margins on this block at higher specificity, the same
     way it does in the RTL rule, so the bottom gap needs !important here. */
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v01/selfie"]) .v2x__copy {
    align-self: flex-end;
    margin-bottom: 48px !important;
  }

  /* -- the one horizontal fix ---------------------------------------------- */
  html[dir="ltr"] section.v2x--left:has(> img.v2x__bg[src*="v2lite-10"]) .v2x__copy .eyebrow {
    margin-inline: 0 auto !important;
  }

  /* -- chip rows: the seven that reach one line at the native 12.5px ------- */
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v2pro-chip"]) .v2x__copy.perf-c .v2x__chips,
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v11-chip"]) .v2x__copy .v2x__chips,
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v1-display"]) .v2x__copy .v2x__chips,
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v0core-design"]) .v2x__chips,
  html[dir="ltr"] section.v2x-display:has(img[src*="v0-chip"]) .v2x__chips--center,
  html[dir="ltr"] main:has(img[src*="v0-chip"]) section.v2-game.chips-1line .v2x__chips--center,
  html[dir="ltr"] main:has(img[src*="f1-battery-img"]) section.v2-game.chips-1line .v2x__chips--center {
    flex-wrap: nowrap !important;
    column-gap: 4px !important;
  }

  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v2pro-chip"]) .v2x__copy.perf-c .v2x__chips > *,
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v11-chip"]) .v2x__copy .v2x__chips > *,
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v1-display"]) .v2x__copy .v2x__chips > *,
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v0core-design"]) .v2x__chips > *,
  html[dir="ltr"] section.v2x-display:has(img[src*="v0-chip"]) .v2x__chips--center > *,
  html[dir="ltr"] main:has(img[src*="v0-chip"]) section.v2-game.chips-1line .v2x__chips--center > *,
  html[dir="ltr"] main:has(img[src*="f1-battery-img"]) section.v2-game.chips-1line .v2x__chips--center > * {
    padding-left: 6px;
    padding-right: 6px;
    white-space: nowrap;
  }

  /* The three left-aligned rows start on the 23px column, matching their own
     copy; the four head-centred rows stay centred, as in the RTL blocks. */
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v2pro-chip"]) .v2x__copy.perf-c .v2x__chips,
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v11-chip"]) .v2x__copy .v2x__chips,
  html[dir="ltr"] section.v2x--right:has(> img.v2x__bg[src*="v1-display"]) .v2x__copy .v2x__chips {
    justify-content: flex-start !important;
  }
}
