/* ============================================================
   BASE — v4.7 "GROUND TRUTH"
   Complete rewrite of the app shell and ambient layers.

   ROOT CAUSE OF ANDROID HORIZONTAL DRIFT (confirmed):
   The previous architecture had three compounding factors that,
   together, cause the Chrome Android compositor thread to mis-place
   the app column during the URL-bar viewport transition:

   1. `isolation: isolate` on #app — creates a new stacking context,
      which forces the browser to re-evaluate ALL stacking/z-index
      relationships on every composited-layer update. On Android, the
      compositor thread runs this re-evaluation asynchronously from
      the URL-bar height change, producing a frame where #app's
      position is computed relative to the OLD visual viewport width
      before settling. This is the primary cause of horizontal drift.

   2. `will-change: transform` on #app::before — promotes that layer
      to its own GPU compositor texture. On Android Chrome, compositor
      textures are positioned relative to the visual viewport at the
      moment they are composited, NOT at the moment the CSS is parsed.
      During URL-bar transition, the visual viewport width transiently
      differs from the layout viewport width, so any fixed/promoted
      layer repositions by the difference — which is exactly the
      observed horizontal offset.

   3. Multiple `backdrop-filter` declarations — each one forces the
      browser to create an intermediate compositing surface. On Android,
      multiple intermediate surfaces across a stacking-context boundary
      (the isolation: isolate on #app) require synchronization between
      the main thread and compositor thread, and that synchronization
      does not happen frame-perfectly during the URL-bar transition.

   THE FIX (architecture, not patching):
   — Remove isolation: isolate from #app entirely.
   — Remove will-change from all ambient/decorative layers. Only use
     will-change: opacity (not transform) where absolutely needed, and
     only on elements that are NOT full-viewport in size.
   — Replace backdrop-filter on mobile with solid semi-transparent
     backgrounds (same visual effect, zero compositor surface overhead).
   — Add touch-action: pan-y to #app to explicitly tell the Chrome
     Android touch pipeline that only vertical pan is allowed here,
     which prevents horizontal gesture disambiguation from running.
   — Add contain: layout style paint to the hero screen so Chrome's
     layout engine skips re-running layout on the hero subtree when
     ancestors change during scroll (per Chromium RenderingNG docs).
   ============================================================ */

/* ============================================================ RESET */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  font-family: var(--ff-body);
  background: #15130F;
  color: var(--snow);
  min-height: 100vh; min-height: 100svh;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
::selection { background: var(--gold-soft); color: var(--gold-bright); }
button { cursor: pointer; border: none; background: none; font-family: var(--ff-body); }
input, select { font-family: var(--ff-body); }

html[lang="en"] { --ff-body: 'Manrope', sans-serif; --ff-display: 'Bricolage Grotesque', sans-serif; }
html[dir="ltr"] body { direction: ltr; }

/* ============================================================ APP SHELL */
#app {
  position: relative; min-height: 100vh; min-height: 100svh;
  max-width: 480px; margin: 0 auto;
  background: var(--obsidian);
  box-shadow: 0 0 0 1px rgba(247,242,230,0.03), 0 0 80px 10px rgba(8,7,5,0.55);
  /* CRITICAL (v4.7): NO isolation:isolate here. That property forces
     a new stacking context which the Chrome Android compositor
     re-evaluates asynchronously from the URL-bar transition, causing
     the column to shift horizontally. Removed entirely. */
  overscroll-behavior-y: contain;
  /* Tell Chrome's touch pipeline explicitly: only vertical pan allowed.
     This prevents horizontal gesture-disambiguation from running on
     touch events that land inside the app column. */
  touch-action: pan-y;
}

/* AMBIENT LIVING LIGHT
   v4.7: The ambient layer is now position:absolute (already correct),
   but critically: NO will-change, NO filter on the layer itself.
   We use opacity-only animation (ambientPulse) on all tiers.
   The desktop camera-drift (scale+translateY) is preserved as a
   CSS animation but WITHOUT will-change, so the browser is NOT forced
   to promote it to an independent compositor layer — it paints with
   its parent (#app) and never needs cross-thread synchronization.
   Result: the ambient layer cannot independently shift relative to
   the page on any platform. */
#app::before {
  content: '';
  position: absolute; inset: 0;
  z-index: 0; pointer-events: none;
  background:
    radial-gradient(58% 42% at 30% 16%, var(--ambient-warm) 0%, transparent 62%),
    radial-gradient(64% 50% at 82% 78%, var(--ambient-deep) 0%, transparent 66%),
    radial-gradient(40% 30% at 70% 30%, var(--ambient-cool) 0%, transparent 70%);
  animation: ambientPulse 6s ease-in-out infinite;
  /* NO will-change. NO filter. */
}
@keyframes ambientPulse {
  0%,100% { opacity: .82; }
  50%     { opacity: 1; }
}
/* Desktop only: gentle scale breathing, still no will-change */
html[data-quality="high"] #app::before {
  animation: ambientBreathe 14s ease-in-out infinite;
}
@keyframes ambientBreathe {
  0%,100% { opacity: .88; transform: scale(1); }
  50%     { opacity: 1;   transform: scale(1.05); }
}

/* Grain layer — static, no animation */
#app::after {
  content: '';
  position: absolute; inset: 0;
  z-index: 0; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  opacity: .022; mix-blend-mode: overlay;
}

/* SCREEN LAYOUT */
.screen {
  display: none;
  position: relative; z-index: 1;
  min-height: 100vh; min-height: 100svh;
  flex-direction: column;
  background: transparent;
  animation: screenIn .5s cubic-bezier(.16,1,.3,1) both;
}
.screen.active { display: flex; }

/* Hero screen gets CSS containment so the layout engine skips
   re-running layout on this subtree during ancestor scroll events.
   Prevents the hero section from participating in viewport-resize
   layout recalculations triggered by the URL-bar transition. */
/* v4.9 — #s0 containment REMOVED. The proven-stable loader screen (#s7)
   carries no containment at all; the hero now matches it. Screen-level
   `contain` was one of the architectural differences between the two. */
#s0 { }

@keyframes screenIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

/* REVEAL CHOREOGRAPHY */
.screen.active .q-category,
.screen.active .q-title,
.screen.active .q-insight,
.screen.active .multi-badge,
.screen.active .options-list,
.screen.active .gender-grid,
.screen.active .hero-visual,
.screen.active .specimen-tag,
.screen.active .hero-headline,
.screen.active .hero-sub,
.screen.active .hero-trust,
.screen.active .hero-cta-group,
.screen.active .r-section,
.screen.active .summary-pills,
.screen.active .protocol-preview,
.screen.active .form-fields {
  animation: riseIn .55s cubic-bezier(.16,1,.3,1) both;
}
.screen.active .q-title,        .screen.active .specimen-tag   { animation-delay: .05s; }
.screen.active .q-insight,      .screen.active .hero-headline  { animation-delay: .10s; }
.screen.active .multi-badge,    .screen.active .hero-sub       { animation-delay: .15s; }
.screen.active .options-list,   .screen.active .gender-grid,
.screen.active .hero-trust                                      { animation-delay: .20s; }
.screen.active .hero-cta-group                                  { animation-delay: .25s; }
.screen.active .r-section:nth-child(2)  { animation-delay: .05s; }
.screen.active .r-section:nth-child(3)  { animation-delay: .10s; }
.screen.active .r-section:nth-child(4)  { animation-delay: .15s; }
.screen.active .r-section:nth-child(5)  { animation-delay: .20s; }
.screen.active .r-section:nth-child(6)  { animation-delay: .25s; }
@keyframes riseIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

/* Custom scrollbar */
* { scrollbar-width: thin; scrollbar-color: var(--hairline-strong) transparent; }
*::-webkit-scrollbar { width: 7px; height: 7px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--hairline-strong); border-radius: 999px; border: 2px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--gold-soft); background-clip: content-box; }

/* PREFERS-REDUCED-MOTION */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration:.001s !important; animation-iteration-count:1 !important; transition-duration:.001s !important; }
  #app::before { animation: none; opacity: .88; }
}

/* ============================================================ INTERACTION STATES */
@media (pointer: fine) {
  .opt:hover { background: var(--ink-raised); }
  .opt.selected:hover { background: var(--gold-soft); }
  .sub-opt:hover { background: var(--ink-raised); }
  .sub-opt.selected:hover { background: var(--gold-soft); }
}
.opt:focus-visible, .sub-opt:focus-visible, .btn-start:focus-visible, .btn-next:focus-visible,
.btn-get-protocol:focus-visible, .btn-submit:focus-visible, .btn-wa:focus-visible, .q-back:focus-visible,
.lang-toggle:focus-visible, .fa-dropzone:focus-visible, .field-input:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--gold-soft), 0 0 0 1px var(--gold); }
[dir="ltr"] .opt, [dir="ltr"] .sub-opt { text-align: left; }

/* ============================================================
   GOLD TEXT GRADIENT — applied to key display elements */
.goldtext, .hero-headline .line-truth, .loader-title {
  background: var(--text-gold-grad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}

/* LUXURY PANEL MATERIAL */
.r-block, .dr-card, .summary-pills, .formulation-card, .gender-card {
  background-image: var(--panel) !important;
  border-color: var(--panel-border-soft) !important;
  box-shadow: var(--panel-glow) !important;
}
.gender-card.selected {
  background-image: var(--panel-raised) !important;
  border-color: var(--gold) !important;
  box-shadow: var(--panel-glow-active) !important;
}

/* Gold kicker-rules */
.q-title::after, .report-title::after, .form-title::after, .success-title::after, .fa-reco-heading::after {
  content: ''; display: block; width: 38px; height: 2px; margin-top: 12px;
  background: var(--text-gold-grad); border-radius: 2px;
}
[dir="rtl"] .q-title::after, [dir="rtl"] .report-title::after, [dir="rtl"] .form-title::after { margin-left: auto; }
.success-title::after { margin-left: auto; margin-right: auto; }

/* ============================================================
   QUALITY-RESPONSIVE COMPOSITING
   v4.7: backdrop-filter is replaced with solid semi-transparent
   backgrounds on LOW and MEDIUM. This eliminates intermediate
   compositor surfaces on mobile entirely. */

/* HIGH (desktop): keep full glass effects */
html[data-quality="high"] .app-header,
html[data-quality="high"] .sudegy-sig,
html[data-quality="high"] .q-progress,
html[data-quality="high"] .q-footer {
  -webkit-backdrop-filter: blur(20px) saturate(150%);
  backdrop-filter: blur(20px) saturate(150%);
}

/* MEDIUM: lighter glass */
html[data-quality="medium"] .app-header,
html[data-quality="medium"] .sudegy-sig,
html[data-quality="medium"] .q-progress,
html[data-quality="medium"] .q-footer {
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}

/* LOW (mobile): NO backdrop-filter. Solid opaque backgrounds.
   Eliminates all intermediate compositor surfaces on Android Chrome. */
html[data-quality="low"] .app-header {
  background: rgba(24,21,16,.97) !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
}
html[data-quality="low"] .sudegy-sig {
  background: rgba(21,19,15,.98) !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
}
html[data-quality="low"] .q-progress {
  background: rgba(21,19,15,.97) !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
}
html[data-quality="low"] .q-footer {
  background: rgba(21,19,15,.98) !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
}
html[data-quality="low"] #app::after { display: none; }
html[data-quality="low"] #app > .screen.active::after { display: none; }
html[data-quality="low"] .hv-frame::after,
html[data-quality="low"] .btn-start::after,
html[data-quality="low"] .btn-get-protocol::after,
html[data-quality="low"] .btn-submit::after,
html[data-quality="low"] .btn-next.on::after { animation: none; display: none; }
html[data-quality="low"] .r-block,
html[data-quality="low"] .dr-card,
html[data-quality="low"] .summary-pills,
html[data-quality="low"] .formulation-card,
html[data-quality="low"] .gender-card { box-shadow: 0 8px 24px rgba(8,7,5,0.5) !important; }

/* MOBILE MOTION PROFILE — hard CSS gate (belt AND suspenders with JS) */
html[data-quality="medium"] .hero-visual,
html[data-quality="low"] .hero-visual,
html[data-quality="medium"] .hv-frame,
html[data-quality="low"] .hv-frame { transform: none !important; transition: none !important; }

/* Suppress filters that force intermediate surfaces on mobile */
html[data-quality="low"] .hv-scanline,
html[data-quality="low"] .fa-scan-beam { mix-blend-mode: normal; filter: none; }
html[data-quality="low"] .fa-mesh-line,
html[data-quality="low"] .fa-mesh-dot,
html[data-quality="low"] .hv-mesh-line,
html[data-quality="low"] .hv-mesh-dot,
html[data-quality="low"] .fa-gauge-fill,
html[data-quality="low"] .hero-visual::after { filter: none; }

/* Screen vignette — absolute, animates only opacity */
#app > .screen.active::after {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(130% 100% at 50% 38%, transparent 52%, rgba(8,7,5,0.5) 100%);
}

@media (min-width: 540px) {
  .fa-scan-frame-wrap, .fa-scan-frame { width: 260px; height: 260px; }
}
