/* ==========================================================================
   Steiner Intro — the overlay stylesheet
   --------------------------------------------------------------------------
   Enqueued by the plugin, on the front page only. Every selector in this file
   lives inside the plugin's own namespace. The only document-level rules are
   the scroll lock at the very bottom and its cleanup counterpart, both of
   which are removed at teardown.

   Two numbers in here are measured, not chosen. Do not "tidy" them:

   --steiner-intro-bg: #F7F5F0
       The exact background colour of the supplied emblem PNG — a property of
       the asset, not a brand colour. The emblem is opaque, so against any
       other backdrop it shows as a faint pale rectangle. Matching the file
       exactly makes that rectangle mathematically invisible, with no image
       editing. Replace the emblem and this must change with it, which is why
       the plugin exposes it as a setting rather than fixing it here.

   --steiner-intro-nudge: -6.805%
       The emblem circle sits 23px right of centre inside its own 338px-wide
       canvas (circle spans columns 85-298). 23/338 = 6.805%. A percentage
       translate resolves against the element's own width, so this correction
       holds at every rendered size. Without it the composition is visibly
       off-centre.

   The z-index is a very high generic default rather than a number tuned to
   one theme: a plugin cannot know what the host site stacks above what. Sites
   with an unusual stacking context override it through the
   steiner_intro_z_index filter.
   ========================================================================== */

.steiner-intro {
  /* ---- tunables (all production defaults) ---- */
  --steiner-intro-bg: #F7F5F0;
  --steiner-intro-emblem-w: 168px;
  --steiner-intro-nudge: -6.805%;
  --steiner-intro-gap: 30px;
  --steiner-intro-slogan-color: #6d675f; /* approved Steiner slogan grey */
  --steiner-intro-fade-in: 750ms;        /* composition fade-in */
  --steiner-intro-cross: 250ms;          /* composition -> veil crossfade */
  --steiner-intro-fade-out: 350ms;       /* final transition to the homepage */

  /* ---- default state: INERT ----
     The intro is invisible and non-blocking until JavaScript activates it.
     If the script fails to load, errors, or is disabled, the visitor gets the
     plain homepage rather than a blank wall. This is the single most
     important declaration in the file. */
  display: none;

  position: fixed;
  top: 0;
  left: 0;

  /* Set by the plugin as an inline custom property; this is the fallback if
     that ever fails to arrive. Deliberately extreme — an intro overlay has to
     sit above whatever the host theme treats as its topmost layer, including
     a focused skip link, and a plugin cannot enumerate that in advance. */
  z-index: var(--steiner-intro-z, 2147483000);

  width: 100%;
  height: 100vh;
  height: 100dvh; /* avoids the iOS Safari address-bar height jump */
  margin: 0;
  padding: 0;
  background-color: var(--steiner-intro-bg);
  opacity: 1;
  transition: opacity var(--steiner-intro-fade-out) ease;
  -webkit-tap-highlight-color: transparent;
}

.steiner-intro.is-on {
  display: block;
}

.steiner-intro.is-out {
  opacity: 0;
}

/* --------------------------------------------------------------------------
   The veil video
   -------------------------------------------------------------------------- */

.steiner-intro__veil {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border: 0;
  opacity: 0;
  transition: opacity var(--steiner-intro-cross) ease;

  /* An unpainted video element renders black (or transparent) depending on
     the browser. Painting it the intro colour removes the black-flash class
     of bug entirely, including the first frame on iOS. */
  background-color: var(--steiner-intro-bg);
  z-index: 2;
}

.steiner-intro.is-veil .steiner-intro__veil {
  /* The source MP4 is intentionally opaque. Its pale field is composited
     above the fixed homepage still so the still is already perceptible through
     the light fabric while the cloth itself remains the only moving layer. */
  opacity: .84;
  mix-blend-mode: multiply;
}

/* --------------------------------------------------------------------------
   The homepage under the cloth

   The supplied H.264 veil is intentionally kept byte-for-byte and has no
   alpha channel. This layer therefore stays fixed underneath the footage for
   the entire approved 2.0–3.4s window. The footage's light field is blended
   above it so the homepage is softly visible through the cloth from the first
   reveal frame. Only the cloth moves; the still never translates, clips, or
   scales during the reveal.
   -------------------------------------------------------------------------- */

.steiner-intro__homepage {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0;
  pointer-events: none;
  transform: translateZ(0);
  will-change: opacity;
}

.steiner-intro__homepage img {
  display: block;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  max-width: none;
  object-fit: cover;
  object-position: center top;
  transform: none;
  user-select: none;
  -webkit-user-drag: none;
}

.steiner-intro.is-veil .steiner-intro__homepage {
  opacity: 1;
}

/* --------------------------------------------------------------------------
   The emblem + slogan composition
   -------------------------------------------------------------------------- */

.steiner-intro__stage {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 24px;
  box-sizing: border-box;

  opacity: 0;
  transition: opacity var(--steiner-intro-fade-in) ease;

  /* Force this wrapper onto its own GPU layer so BOTH children paint
     together during the opacity transition. Without this, .steiner-intro__emblem
     (which has its own transform below and therefore its own layer) and
     .steiner-intro__slogan (which has none, and would otherwise be composited
     ad hoc by the browser) can be promoted inconsistently. WebKit has a
     long-standing class of bug where an unpromoted sibling text node drops
     out of an opacity transition on a parent — reported on a real iPhone
     with Low Power Mode on, which also lowers the GPU clock and makes this
     more likely to surface. Promoting the whole stage as one layer removes
     the asymmetry instead of guessing at which child was affected. */
  transform: translateZ(0);
  -webkit-backface-visibility: hidden;
  will-change: opacity;
  z-index: 3;
}

/* Emblem and slogan share one wrapper and one transition, so they fade in
   together as a single unit. No staged animation. */
.steiner-intro.is-shown .steiner-intro__stage {
  opacity: 1;
}

.steiner-intro.is-veil .steiner-intro__stage {
  opacity: 0;
  transition-duration: var(--steiner-intro-cross);
}

.steiner-intro__emblem {
  display: block;
  width: var(--steiner-intro-emblem-w);
  height: auto;
  transform: translateX(var(--steiner-intro-nudge));
  user-select: none;
  -webkit-user-drag: none;
}

.steiner-intro__slogan {
  margin: var(--steiner-intro-gap) 0 0;
  padding: 0;
  font-family: Georgia, 'Times New Roman', Times, serif; /* approved serif stack */
  font-size: clamp(15px, 1.15vw, 18px);
  font-weight: 400;
  font-style: normal;
  line-height: 1.4;
  letter-spacing: 0.06em;
  color: var(--steiner-intro-slogan-color);
}

/* --------------------------------------------------------------------------
   Responsive sizing

   The supplied PNG is 338 x 266 with a 214px circle. At a 168px canvas the
   circle renders ~106px, which is 1:1 on a 2x display. These sizes are the
   largest this asset supports without visible softening; a bigger emblem
   needs a bigger export, not a bigger width value here.
   -------------------------------------------------------------------------- */

@media (max-width: 1024px) {
  .steiner-intro {
    --steiner-intro-emblem-w: 150px;
    --steiner-intro-gap: 27px;
  }
}

@media (max-width: 640px) {
  .steiner-intro {
    --steiner-intro-emblem-w: 128px;
    --steiner-intro-gap: 24px;
  }

  .steiner-intro__homepage img {
    object-position: 26% top;
  }
}

/* --------------------------------------------------------------------------
   Reduced motion — show the composition, skip the veil, no fades.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .steiner-intro,
  .steiner-intro__stage,
  .steiner-intro__veil,
  .steiner-intro__homepage {
    transition-duration: 1ms !important;
  }
}

/* The explicit override steiner-intro.js also honours. Kept in step with the media
   query above so a forced reduced-motion run cannot leave the CSS fading for
   600ms while the JS tears down after 1ms. Not emitted in production. */
.steiner-intro[data-steiner-intro-reduced='1'],
.steiner-intro[data-steiner-intro-reduced='1'] .steiner-intro__stage,
.steiner-intro[data-steiner-intro-reduced='1'] .steiner-intro__veil,
.steiner-intro[data-steiner-intro-reduced='1'] .steiner-intro__homepage {
  transition-duration: 1ms !important;
}

/* --------------------------------------------------------------------------
   Scroll lock while the intro is on screen. Applied to <html> by steiner-intro.js and
   removed when the intro is torn down.
   -------------------------------------------------------------------------- */

.steiner-intro-lock,
.steiner-intro-lock body {
  overflow: hidden !important;
}
