/* ==========================================================================
   Identity — the gradient field
   --------------------------------------------------------------------------
   Built exactly the way the material deck describes it:

     step 1  three brand blobs (images/shapes/*) tinted with the ramp colours
     step 2  scaled up hard and pushed to the bottom of the frame, cropped
     step 3  ~400px Figma layer blur  ->  a 164px CSS gaussian on a 1440 stage
             (Figma's blur radius is the FWHM, i.e. 2.355 x sigma)

   Geometry below was reverse-fitted against the reference frames, so the
   still frames match the comps pixel-for-pixel. Percentages are relative to
   the 1440 x 750 reference stage, which is stretched to the viewport.
   ========================================================================== */

.gradient-field {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  contain: strict;
}

.gradient-field__stage {
  position: absolute;
  inset: 0;
  background: var(--bg);
  isolation: isolate;                 /* keep the grain blending inside */
  will-change: opacity;
}

/* The shape is masked on the inner element and blurred on the wrapper:
   CSS applies mask *after* filter, so a mask on the blurred element itself
   would clip the blur straight back to a hard edge. */

.blob {
  position: absolute;
  will-change: transform;
  filter: blur(var(--blob-blur, 11.3889vw));
}

.blob::before {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  background: var(--blob-color);
  -webkit-mask-image: var(--blob-shape);
          mask-image: var(--blob-shape);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
}

/* The three shapes are inlined rather than linked. An SVG used as a CSS mask
   is fetched under CORS, and every file:// document is an opaque origin — so
   opening index.html straight off disk rejected the masks and the whole
   gradient disappeared, hero and CTA alike. A data: URI is always same-origin,
   so the field now renders from disk, from a server, from anywhere. The three
   files are still in images/shapes/ as the editable source. -----------------*/

.blob--a { --blob-color: var(--grad-3); --blob-shape: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 1000' preserveAspectRatio='none'><path fill='%23fff' d='M655.65 865.71C204.1 1126.71 -14.21 1007.26 0.72 507.37C15.65 7.47 241.42 -123.03 678.04 115.87C1114.67 354.77 1107.2 604.72 655.65 865.71Z'/></svg>"); }
.blob--b { --blob-color: var(--grad-2); --blob-shape: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 1000' preserveAspectRatio='none'><path fill='%23fff' d='M548.25 131.36C977.67 -320.8 1188.96 514.12 781.56 830.98C374.17 1147.84 118.58 1019.19 14.81 445.04C-88.96 -129.1 380.54 307.95 548.25 131.36Z'/></svg>"); }
.blob--c { --blob-color: var(--grad-1); --blob-shape: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 1000' preserveAspectRatio='none'><path fill='%23fff' d='M239.29 795.24C126.12 763.93 50.63 681.89 12.81 549.1C-25.01 416.31 20.92 323.33 150.61 270.15C280.29 216.97 389.22 147.86 477.4 62.8C565.57 -22.26 649.94 -20.91 730.51 66.85C811.09 154.62 884.7 239.83 951.36 322.47C1018.01 405.11 1016.17 487.69 945.81 570.21C875.46 652.73 819.14 756.87 776.86 882.63C734.57 1008.39 662.7 1033.09 561.23 956.73C459.76 880.38 352.45 826.55 239.29 795.24Z'/></svg>"); }

/* ---- hero / default composition (movement step 1) ------------------------
   Sized in vw so the whole composition scales uniformly with the frame width
   and stays anchored to the top of the viewport, exactly like the comps
   (the 1440 x 822 hero board and the 1440 x 750 material boards share the
   same gradient geometry measured from the top edge).                      */

.gradient-field .blob { --blob-blur: 11.8056vw; }   /* 170px on a 1440 stage */
.gradient-field .blob--a { left: -11.8056vw; top: 34.0278vw; width:  60.6944vw; height: 92.5000vw; }
.gradient-field .blob--b { left:  16.2500vw; top: 30.6944vw; width:  42.3611vw; height: 79.4444vw; }
.gradient-field .blob--c { left:  29.7222vw; top: 25.9722vw; width: 102.5000vw; height: 96.1111vw; }


/* ---- CTA panel: the same effect, composed for the 1440 x 528 band -------- */

.cta__gradient {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--bg);
  isolation: isolate;
  pointer-events: none;
}

.cta__gradient .blob { --blob-blur: 15.2778vw; }   /* 220px on the 1440 x 528 band */
.cta__gradient .blob--a { left:   5.9722%; top:  49.6212%; width:  88.3333%; height: 184.6591%; }
.cta__gradient .blob--b { left:  19.4444%; top: -74.0530%; width:  98.4722%; height:  39.0152%; }
.cta__gradient .blob--c { left: -39.3750%; top:  17.4242%; width: 154.8611%; height:  44.3182%; }

/* Motion is applied by js/gradient.js as translate3d() on each .blob and
   opacity on .gradient-field__stage. Without JS the hero composition stays
   put, which is the designed default state. */

@media (prefers-reduced-motion: reduce) {
  .blob { transition: none !important; }
}
