/* ============================================================
   VERNIAS - Glass design system: token layer
   Dark ground - green/teal/blue spectrum - frosted glass surfaces
   Load this FIRST, before any component CSS.
   Full specification and live specimens: docs/design-system.html
   ============================================================ */

:root{

  /* ---------- 1. GROUND ------------------------------------
     The page base. Never pure black: it kills the depth the
     glass depends on. All four carry a blue-green cast so the
     mesh gradient sits on them without a hue seam.          */
  --ink-975:#020508;   /* deepest ground, for a section that needs
                          to sit back from the rest of the page      */
  --ink-950:#04090C;   /* page base                          */
  --ink-900:#070F14;   /* section base                       */
  --ink-850:#0A151C;   /* the notional ground behind glass   */
  --ink-800:#0E1D26;   /* solid fallback fill for glass      */

  /* ---------- 2. SPECTRUM (atmosphere only) ----------------
     Sampled from the reference art. These are for gradients,
     meshes and glows. Never use them for text, borders,
     buttons or focus rings: the mid-blues measure below 3.5:1
     on the ground and fail WCAG AA outright.                */
  --spec-mint:#45C98B;
  --spec-emerald:#1E9B6B;
  --spec-pine:#0E5A41;   /* carried over from the current brand */
  --spec-teal:#12808F;
  --spec-blue:#1C6FB8;
  --spec-indigo:#1B2A63;
  --spec-abyss:#050D14;

  /* ---------- 2b. WARM SPECTRUM (atmosphere only) ----------
     A second, warm arm of the spectrum, for ember-lit grounds.
     Same rule as the cool one and more strictly: these are for
     glows and gradients, never for text, borders, buttons or
     focus rings. The accent stays green everywhere, so warmth
     can never be mistaken for something interactive.        */
  --spec-ember:#C4472A;   /* deep, burnt - the base of a flame */
  --spec-flame:#E8703A;   /* the body                          */
  --spec-gold:#E8A33C;    /* the tip                           */

  /* ---------- 3. ACCENT (the only interactive colour) ------
     One accent for the whole site: every CTA, link, active
     state and focus ring. 10.76:1 on --ink-950.             */
  --accent:#3ED69B;
  --accent-hover:#5FE3B0;
  --accent-press:#2BB37F;
  --accent-ink:#04120C;  /* text ON an accent fill: 10.3:1.
                            White on accent is 1.86:1. Never. */
  --accent-soft:rgba(62,214,155,.14);
  --accent-line:rgba(62,214,155,.32);

  /* ---------- 4. TEXT --------------------------------------
     Ratios quoted against --ink-950 and against the weakest
     glass tier (glass-3, effective #202A30).                */
  --text-hi:#EAF2F0;   /* headings.        17.6:1 / 12.9:1   */
  --text:#B6C4C6;      /* body.            11.2:1 /  8.2:1   */
  --text-lo:#8A9B9F;   /* meta, captions.   6.9:1 /  5.1:1   */
  --text-on-glass:var(--text-hi);

  /* Non-text only. 2.7:1 on glass, so hairlines and disabled
     chrome, never a character of copy.                      */
  --hairline:#5C6C71;

  /* ---------- 5. GLASS -------------------------------------
     Three tiers. Tier is chosen by elevation, not by taste,
     and a page should not use more than three at once.      */

  /* tier 1 - chrome: nav bar, chips, inline tags */
  --g1-fill:rgba(255,255,255,.045);
  --g1-border:rgba(255,255,255,.09);
  --g1-blur:blur(18px) saturate(150%);
  --g1-inset:inset 0 1px 0 rgba(255,255,255,.10);
  --g1-shadow:0 4px 16px rgba(2,8,12,.30);

  /* Nav fill. Dark, not white-on-glass: the bar has to stay readable
     over a photographic hero, and a white translucent fill disappears
     against a bright frame.

     One value, constant. It used to lighten at scroll zero and deepen
     once the page moved, which meant the bar visibly changed the moment
     you touched the wheel - a state change with nothing behind it. */
  --nav-fill:rgba(4,9,12,.74);

  /* tier 2 - content: cards, panels, the default */
  --g2-fill:rgba(255,255,255,.06);
  --g2-border:rgba(255,255,255,.12);
  --g2-blur:blur(24px) saturate(160%);
  --g2-inset:inset 0 1px 0 rgba(255,255,255,.14);
  --g2-shadow:0 20px 50px rgba(2,8,12,.55);

  /* tier 3 - raised: hero panel, dialogs, dropdowns */
  --g3-fill:rgba(255,255,255,.09);
  /* A menu cannot be tinted glass. Every other glass surface sits on a
     ground this system controls, so a white wash at 9% is predictable.
     A dropdown floats over WHATEVER has scrolled under the nav - on the
     platform page that is a white panel and a bright photograph, where
     a 9% white fill resolved to a near-white panel carrying light text
     at 1.2:1. Ink at 92% instead: the backdrop can still be felt, but
     it can no longer decide whether the menu is readable. Measured, the
     worst case across dark, card, photo and white is 7.7:1. */
  --menu-fill:rgba(14,29,38,.92);
  --menu-border:rgba(255,255,255,.14);
  --g3-border:rgba(255,255,255,.16);
  --g3-blur:blur(40px) saturate(180%);
  --g3-inset:inset 0 1px 0 rgba(255,255,255,.20);
  --g3-shadow:0 32px 80px rgba(2,8,12,.65);

  /* ---------- 6. TYPE --------------------------------------
     Two families. General Sans carries everything; Geist Mono
     carries figures, code and small labels. No serif.       */
  --font-sans:"General Sans",system-ui,-apple-system,"Segoe UI",sans-serif;
  --font-mono:"Geist Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  /* Figures do NOT use --font-mono. Geist Mono draws a slashed zero as
     its default glyph, and it is not an optional feature - "zero" 0,
     "ss01" 0 and font-variant-numeric all leave it slashed, so it can
     only be avoided by leaving the family. General Sans is already
     loaded, has a plain zero, and its lining tabular figures keep
     stacked numerals in a column the way the mono did. */
  --font-num:"General Sans",system-ui,-apple-system,"Segoe UI",sans-serif;

  --t-display:clamp(2.125rem,1.35rem + 3.1vw,3.5rem);
  --t-h1:clamp(2rem,1.3rem + 2.8vw,3.25rem);
  --t-h2:clamp(1.875rem,1.28rem + 2.4vw,3rem);
  --t-h3:clamp(1.25rem,1.08rem + 0.7vw,1.625rem);
  --t-lead:clamp(1.0625rem,0.98rem + 0.5vw,1.375rem);
  --t-body:1rem;
  --t-sm:0.9375rem;
  --t-xs:0.8125rem;
  --t-label:0.75rem;   /* mono, uppercase, tracked */

  /* One heading treatment for the whole site, set here rather than per
     section: a regular weight at a restrained size with tight tracking.
     Headings were semibold at a much larger display scale; this is the
     hero treatment promoted to the default so nothing has to opt in. */
  --w-heading:400;

  --lh-display:1.08;
  --lh-heading:1.10;
  --lh-lead:1.5;
  --lh-body:1.62;

  --tr-display:-0.028em;
  --tr-heading:-0.026em;
  --tr-body:-0.006em;
  --tr-label:0.16em;

  /* ---------- 7. SPACE (4px base) -------------------------- */
  --s-1:4px;   --s-2:8px;   --s-3:12px;  --s-4:16px;
  --s-5:24px;  --s-6:32px;  --s-7:48px;  --s-8:64px;
  --s-9:96px;  --s-10:128px; --s-11:160px;

  --section-y:clamp(72px,9vw,144px);
  --maxw:1220px;
  --gutter:clamp(20px,4vw,40px);

  /* ---------- 8. RADIUS ------------------------------------
     One rule, applied everywhere:
       interactive pills  -> --r-pill  (buttons, chips, tabs)
       containers         -> --r-lg    (cards, panels, media)
       raised containers  -> --r-xl    (hero panel, dialogs)
       inputs             -> --r-md
     Anything outside this list is a mistake, not a variant.  */
  --r-md:14px;
  --r-lg:22px;
  --r-xl:28px;
  --r-pill:999px;

  /* ---------- 9. MOTION ------------------------------------ */
  --ease:cubic-bezier(.16,1,.3,1);
  --d-fast:160ms;
  --d-base:240ms;
  --d-slow:420ms;
  --d-reveal:700ms;

  /* ---------- 10. LAYERS ----------------------------------- */
  --z-mesh:0;
  --z-content:1;
  --z-nav:60;
  --z-dialog:80;
  --z-grain:90;

  /* ---------- 12. GROUND ----------------------------------
     The atmosphere, as a reusable background-image. Applied to a
     SECTION rather than to one fixed layer behind the document:
     a fixed layer does not move with the page, so scrolling walks
     the content across it and the ground appears to change colour
     under you. Attached to a section it scrolls with that section,
     so within a section the colour is simply the colour.        */
  --ground-mesh:
    radial-gradient(90% 70% at 82% 8%,  rgba(69,201,139,.42), transparent 62%),
    radial-gradient(80% 62% at 58% 34%, rgba(28,111,184,.40), transparent 66%),
    radial-gradient(70% 66% at 16% 62%, rgba(18,128,143,.30), transparent 68%),
    radial-gradient(94% 80% at 24% 108%,rgba(27,42,99,.46),  transparent 70%);

  /* Same field, roughly half strength. For sections whose content is
     doing the work and only want the ground to be tinted, not lit. */
  --ground-mesh-soft:
    radial-gradient(90% 70% at 82% 8%,  rgba(69,201,139,.18), transparent 62%),
    radial-gradient(80% 62% at 58% 34%, rgba(28,111,184,.17), transparent 66%),
    radial-gradient(70% 66% at 16% 62%, rgba(18,128,143,.13), transparent 68%),
    radial-gradient(94% 80% at 24% 108%,rgba(27,42,99,.20),  transparent 70%);

  /* ---------- 11. IMAGERY ----------------------------------
     Photography is graded, never dropped in raw. Two lanes,
     and they are not interchangeable:

       .media-photo   abstract / architectural / texture.
                      Desaturated, then re-tinted into the
                      spectrum. Grade hard: a recognisably
                      stock frame is worse than no frame.
       .media-product real product UI. NEVER graded - the
                      screenshot's own colour is the evidence.
                      It gets a frame and a scrim, nothing more.

     Ambient art is decorative raster placed at a corner. It
     does what a radial-gradient cannot: art-directed shape.  */

  --grade-mix:color;              /* blend mode for the tint pass   */
  --grade-wash:linear-gradient(115deg,var(--spec-emerald),var(--spec-teal) 44%,var(--spec-indigo));
  --grade-prep:grayscale(.88) contrast(1.06) brightness(.78);

  /* Scrim. Sits above the grade and guarantees the contrast
     floor for any text laid over the frame. Photography has no
     contrast contract of its own; this is what supplies one.  */
  --scrim-bottom:linear-gradient(180deg,transparent 34%,rgba(4,9,12,.82));
  --scrim-side:linear-gradient(90deg,rgba(4,9,12,.88),rgba(4,9,12,.20) 58%,transparent);
  --scrim-flat:rgba(4,9,12,.55);

  /* For a frame whose bright region is in one corner. Solved against the
     agents backdrop, whose sunset sits top-right under the agent grid: a
     flat scrim strong enough to clear it (.55) drops the whole image to
     mean L 24, while this reaches the same zero-failure result at L 28
     because it only darkens where the glow actually is. */
  --scrim-glow-tr:radial-gradient(120% 105% at 100% 0%,
                    rgba(4,9,12,.86),rgba(4,9,12,.30) 55%,transparent 100%);

  /* Copy overlaid on the right of a frame whose subject is on the left.
     Solved against the platform desk shot: it stays fully clear until
     42%, which is where that laptop still is, then reaches .95 by 70%.
     Measured at 0.18% of the copy area below AA while leaving the
     product screen at luminance 109 of an unscrimmed 113. */
  --scrim-right:linear-gradient(90deg,
                  transparent 42%,rgba(4,9,12,.95) 70%,rgba(4,9,12,.95));

  /* A section-wide backing that content sits on top of. Heavy, because
     everything in the section - heading, paragraph, a screenshot - has
     to read against it. Solved on the ocean backdrop: at .68 no part of
     the frame fails AA for body text, at .58 about 1% still does. */
  --scrim-deep:rgba(4,9,12,.72);

  /* For a backdrop that carries no text of its own - everything on top
     of it is an opaque card or a panel with its own ground. Only enough
     to stop the picture competing with what is laid over it. */
  --scrim-soft:rgba(4,9,12,.34);

  /* Centred copy over a full-bleed frame. Two layers: a flat floor that
     guarantees the contrast contract wherever the photograph happens to
     be bright, and a soft pool under the text block itself. Sized for a
     headline and a short paragraph at the optical centre. */
  --scrim-hero:radial-gradient(72% 62% at 50% 46%,rgba(4,9,12,.80),rgba(4,9,12,.52) 72%,rgba(4,9,12,.66)),
               linear-gradient(rgba(4,9,12,.30),rgba(4,9,12,.30));

  /* Product screenshots get luminance held down so the frame
     sits in the page, without touching hue or saturation.     */
  --product-prep:brightness(.94) contrast(1.02);

  /* A third treatment, for photography that already sits in the palette.
     The full grade exists to rescue a generic frame; run it on an image
     that is already deep blue-teal with warm practical lights and it
     flattens the lights and throws away the thing that made the frame
     worth using. This unifies gently and leaves the colour alone. */
  --grade-prep-light:saturate(.94) contrast(1.03) brightness(.90);
  --grade-wash-opacity:.30;

  --art-opacity:.40;      /* corner ambient art, matched to blueflame's */
  --art-opacity-lo:.24;   /* when it lands near body copy               */
  --parallax-shift:12%;   /* total travel; beyond ~15% it reads as slip */
}

/* ============================================================
   THE MESH
   One fixed layer for the whole document. Glass has nothing to
   refract if each section paints its own background, and a
   per-section gradient also forces a repaint on every scroll
   frame behind every blurred panel.
   ============================================================ */
/* Flat, on purpose.

   This layer used to carry four large radial gradients. Because it is
   fixed, the page scrolls ACROSS them rather than them scrolling with
   it, so every section sat over a different part of the field and the
   ground appeared to change colour as you moved down the page. The
   colour was never changing; the page was moving over it.

   The mesh existed to give backdrop-filter something varied to refract.
   Since then the sections that carry real weight - hero, agents - all
   have their own photographic grounds, and the remaining glass (the nav,
   the dropdown) blurs the CONTENT behind it rather than the ground. So
   the mesh was earning very little and costing consistency.

   Restore variation here only if a section needs it, and give it to that
   section rather than to the whole document. */
/* The document base. Flat: the atmosphere lives on the sections now,
   via .has-ground, so that it scrolls with them. */
.mesh{
  position:fixed;inset:0;z-index:var(--z-mesh);pointer-events:none;
  background:var(--ink-950);
}

/* A section's own atmosphere. Scrolls with the section, so the colour
   is fixed relative to the content sitting on it. */
.has-ground{
  background-color:var(--ink-950);
  background-image:var(--ground-mesh);
}
.has-ground.is-quiet{background-image:var(--ground-mesh-soft)}
/* Deeper still: the soft field over the darkest ground. For a section
   that should recede rather than glow. */
.has-ground.is-deep{
  background-color:var(--ink-975);
  background-image:var(--ground-mesh-soft);
}

/* Grain. Dark wide-area gradients band badly on 8-bit panels;
   this hides it. Fixed and non-interactive so it never repaints
   with scroll. */
.grain{
  position:fixed;inset:0;z-index:var(--z-grain);pointer-events:none;
  opacity:.035;mix-blend-mode:overlay;
  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='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ============================================================
   GLASS SURFACES
   ============================================================ */
.glass,.glass-1,.glass-2,.glass-3{
  position:relative;isolation:isolate;
  border-style:solid;border-width:1px;
  border-radius:var(--r-lg);
  color:var(--text);
}
.glass-1{
  background:var(--g1-fill);border-color:var(--g1-border);
  -webkit-backdrop-filter:var(--g1-blur);backdrop-filter:var(--g1-blur);
  box-shadow:var(--g1-inset),var(--g1-shadow);
}
.glass-2{
  background:linear-gradient(158deg,rgba(255,255,255,.07),rgba(255,255,255,.02) 46%),var(--g2-fill);
  border-color:var(--g2-border);
  -webkit-backdrop-filter:var(--g2-blur);backdrop-filter:var(--g2-blur);
  box-shadow:var(--g2-inset),var(--g2-shadow);
}
.glass-3{
  background:linear-gradient(158deg,rgba(255,255,255,.11),rgba(255,255,255,.03) 46%),var(--g3-fill);
  border-color:var(--g3-border);border-radius:var(--r-xl);
  -webkit-backdrop-filter:var(--g3-blur);backdrop-filter:var(--g3-blur);
  box-shadow:var(--g3-inset),var(--g3-shadow);
}

/* Specular top edge. This is what separates a real glass panel
   from a translucent div: light catches the upper rim only. */
.glass-2::before,.glass-3::before{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:linear-gradient(180deg,rgba(255,255,255,.16),transparent 22%);
  -webkit-mask:linear-gradient(#000,#000) content-box,linear-gradient(#000,#000);
  -webkit-mask-composite:xor;mask-composite:exclude;
  padding:1px;
}

/* Accent bloom. Use on at most one panel per viewport. */
.glass-bloom::after{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:-1;
  background:radial-gradient(60% 80% at 88% 0%,rgba(62,214,155,.20),transparent 60%);
}

/* ---------- required fallbacks ---------- */

/* Firefox with backdrop-filter disabled, and older engines.
   Without this the panels render as flat washes of white and
   the text contrast collapses. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .glass-1,.glass-2,.glass-3{
    background:var(--ink-800);
    box-shadow:0 20px 50px rgba(2,8,12,.55);
  }
}

/* Accessibility setting, not a nice-to-have: users who ask for
   reduced transparency get opaque surfaces. */
@media (prefers-reduced-transparency:reduce){
  .glass-1,.glass-2,.glass-3{
    background:var(--ink-800);
    -webkit-backdrop-filter:none;backdrop-filter:none;
    border-color:rgba(255,255,255,.16);
  }
  .glass-2::before,.glass-3::before,.glass-bloom::after,.grain{display:none}
}

/* ============================================================
   INTERACTIVE
   ============================================================ */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
  font-family:var(--font-sans);font-size:var(--t-sm);font-weight:600;line-height:1;
  letter-spacing:-.01em;white-space:nowrap;
  padding:.875rem 1.5rem;border-radius:var(--r-pill);
  border:1px solid transparent;cursor:pointer;
  transition:background var(--d-base) var(--ease),
             border-color var(--d-base) var(--ease),
             transform var(--d-fast) var(--ease),
             box-shadow var(--d-base) var(--ease);
}
.btn-primary{background:var(--accent);color:var(--accent-ink);box-shadow:0 8px 24px rgba(62,214,155,.22)}
.btn-primary:hover{background:var(--accent-hover);box-shadow:0 12px 32px rgba(62,214,155,.30)}
.btn-primary:active{background:var(--accent-press);transform:scale(.98);box-shadow:0 4px 12px rgba(62,214,155,.20)}

/* Ghost buttons need their own frosted backing. A transparent
   button over the mesh has no guaranteed contrast floor. */
.btn-ghost{
  background:var(--g1-fill);border-color:var(--g1-border);color:var(--text-hi);
  -webkit-backdrop-filter:var(--g1-blur);backdrop-filter:var(--g1-blur);
}
.btn-ghost:hover{background:rgba(255,255,255,.09);border-color:rgba(255,255,255,.20)}
.btn-ghost:active{transform:scale(.98)}

a{color:var(--accent);text-decoration-color:var(--accent-line);text-underline-offset:3px}
a:hover{color:var(--accent-hover)}

:where(a,button,input,select,textarea,[tabindex]):focus-visible{
  outline:2px solid var(--accent);outline-offset:3px;border-radius:var(--r-md);
}

.label{
  font-family:var(--font-mono);font-size:var(--t-label);font-weight:500;
  letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--text-lo);
}

/* Inputs: label above, never placeholder-as-label. Placeholder
   sits at --text-lo so it still clears AA. */
.field{display:flex;flex-direction:column;gap:var(--s-2)}
.input{
  width:100%;padding:.8125rem 1rem;border-radius:var(--r-md);
  background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.12);
  color:var(--text-hi);font-family:var(--font-sans);font-size:var(--t-body);
  transition:border-color var(--d-base) var(--ease),background var(--d-base) var(--ease);
}
.input::placeholder{color:var(--text-lo)}
.input:hover{border-color:rgba(255,255,255,.20)}
.input:focus{outline:none;border-color:var(--accent);background:rgba(255,255,255,.07)}

/* ============================================================
   MOTION
   ============================================================ */
[data-reveal]{opacity:0;translate:0 20px;transition:opacity var(--d-reveal) var(--ease),translate var(--d-reveal) var(--ease)}
[data-reveal].in{opacity:1;translate:0 0}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important;
  }
  [data-reveal]{opacity:1;translate:none}
}


/* ============================================================
   IMAGERY
   Taken from the reference site's strongest move: full-bleed
   photography graded into the palette and drifting on scroll,
   with decorative raster art pinned to section corners. Adapted
   to a dark ground and this spectrum.
   ============================================================ */

/* The frame. Everything visual sits in one of these. */
.media{
  position:relative;isolation:isolate;overflow:hidden;
  border-radius:var(--r-lg);
}
.media>img,.media>video{
  display:block;width:100%;height:100%;object-fit:cover;
}

/* --- lane 1: graded photography ---------------------------- */
.media-photo>img,.media-photo>video,
.media-photo>picture>img{filter:var(--grade-prep)}

/* the tint pass */
.media-photo::before{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  mix-blend-mode:var(--grade-mix);
  background:var(--grade-wash);
}
/* the scrim, painted after the tint so it always wins */
.media-photo::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:2;
  background:var(--scrim-bottom);
}
.media-photo.scrim-side::after{background:var(--scrim-side)}
.media-photo.scrim-flat::after{background:var(--scrim-flat)}
.media-photo.scrim-hero::after{background:var(--scrim-hero)}
.media-photo.scrim-glow-tr::after{background:var(--scrim-glow-tr)}
.media-photo.scrim-right::after{background:var(--scrim-right)}
.media-photo.scrim-deep::after{background:var(--scrim-deep)}
.media-photo.scrim-soft::after{background:var(--scrim-soft)}
.media-photo.scrim-none::after{display:none}

/* Light-touch variant: see --grade-prep-light. */
.media-photo.grade-light>img,.media-photo.grade-light>video,
.media-photo.grade-light>picture>img{filter:var(--grade-prep-light)}
.media-photo.grade-light::before{opacity:var(--grade-wash-opacity)}

/* --- lane 2: product UI ------------------------------------
   No grade and no tint: the screenshot's own colour is the
   product claim. Raised glass frame, per the migration map.  */
.media-product{
  border-radius:var(--r-xl);
  border:1px solid var(--g3-border);
  box-shadow:var(--g3-inset),var(--g3-shadow);
}
.media-product>img,.media-product>video{filter:var(--product-prep)}

/* --- full-bleed section backing ---------------------------- */
.media-bleed{
  position:absolute;inset:0;z-index:-1;
  border-radius:0;pointer-events:none;
}

/* --- corner ambient art ------------------------------------
   Plain <img>, absolutely positioned, decorative. Always
   alt="" and pointer-events:none: it is not content.        */
.art{
  position:absolute;z-index:-1;pointer-events:none;user-select:none;
  max-width:none;opacity:var(--art-opacity);
}
.art-tr{inset:0 0 auto auto}
.art-tl{inset:0 auto auto 0}
.art-br{inset:auto 0 0 auto}
.art-bl{inset:auto auto 0 0}
.art-quiet{opacity:var(--art-opacity-lo)}

/* Sections carrying bleed or art need a stacking context, or the art
   paints over the content instead of behind it. The art sits at z-index
   -1 rather than the content being pushed to +1: a blanket rule on the
   children would also overwrite the positioning of any child that sets
   its own, such as an absolutely placed scroll cue. */
.has-art{position:relative;isolation:isolate;overflow:hidden}

/* --- parallax ----------------------------------------------
   GSAP writes the transform; this only declares intent.

   HARD RULE: never on a glass panel or any ancestor of one. A
   backdrop-filter under a scroll-driven transform re-rasterises
   everything behind it on every frame. Parallax belongs to
   .media-bleed and .art, which carry no blur.               */
[data-parallax]{will-change:transform}

@media (prefers-reduced-transparency:reduce){
  .media-photo::before{display:none}
  .media-photo>img,.media-photo>video{filter:none}
}
@media (prefers-reduced-motion:reduce){
  [data-parallax]{will-change:auto;transform:none!important}
}
