/* ==========================================================================
   Media + image motion layer.

   WIREFRAME STAGE: every photographic asset is a placeholder. No third-party
   imagery is hotlinked. Each slot carries a caption describing the shot the
   final asset should be, so the client can approve art direction before
   anything is commissioned.

   Motion vocabulary measured off forhers.com computed styles:
     reveal   opacity + transform   600ms  cubic-bezier(.72, 0, .45, 1)
     settle   670ms cubic-bezier(.71, 0, .18, 1), 8% overshoot then -2%
     drift    transform 3s ease, slow ambient movement
     float    translateY 0 -> -15px -> 0, slow, infinite
   ========================================================================== */

/* ---------------------------------------------------------------- slots -- */
.media {
  position: relative;
  border-radius: var(--r-card, 24px);
  overflow: hidden;
  background: linear-gradient(140deg, #2b3320 0%, #1e3944 48%, #3a4a2a 100%);
  isolation: isolate;
}
.media.ratio-16x9 { aspect-ratio: 16/9; }
.media.ratio-4x3  { aspect-ratio: 4/3; }
.media.ratio-1x1  { aspect-ratio: 1/1; }
.media.ratio-3x4  { aspect-ratio: 3/4; }
.media.light { background: linear-gradient(140deg, #eef5e4 0%, #dfeef0 52%, #e8f0dd 100%); }

/* slow drifting colour field, the "photograph" stand-in */
.media::before {
  content: ""; position: absolute; inset: -18%; z-index: 0; pointer-events: none;
  background:
    radial-gradient(38% 42% at 24% 26%, rgba(197,237,130,.55), transparent 66%),
    radial-gradient(34% 38% at 78% 34%, rgba(163,181,141,.42), transparent 68%),
    radial-gradient(44% 48% at 56% 84%, rgba(17,131,160,.38), transparent 70%);
  filter: blur(28px);
  animation: media-drift 22s cubic-bezier(.4,0,.2,1) infinite alternate;
}
.media.light::before { opacity: .8; }

@keyframes media-drift {
  0%   { transform: translate3d(0,0,0) scale(1); }
  50%  { transform: translate3d(-3%, 2.5%, 0) scale(1.08); }
  100% { transform: translate3d(2.5%, -3%, 0) scale(1.04); }
}

/* fine grain so the placeholder does not read as a flat swatch */
.media::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none; opacity: .16;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)' opacity='.55'/></svg>");
}

/* real imagery inside a media slot: fills the frame, sits under grain + play */
.media > img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0; display: block;
}
.media:has(> img)::before { display: none; }   /* drop the drift field once a real image exists */
.media:has(> img) .slot { display: none; }     /* and the placeholder caption */

/* the caption that tells the client what the real shot is */
.media .slot {
  position: absolute; inset: 0; z-index: 2; display: grid; place-content: center;
  text-align: center; padding: var(--s-5); gap: var(--s-2);
}
/* when a play control sits in the centre, drop the caption to the base so the
   two do not overlap */
.media:has(.play) .slot { align-content: end; padding-bottom: var(--s-4); }
.media:has(.play) .slot .desc { font-size: var(--t-xs); max-width: 40ch; line-height: 1.4; }
.media .slot .tag {
  font-size: 10px; font-weight: 600; letter-spacing: .18em; text-transform: uppercase;
  color: rgba(255,255,255,.72);
}
.media.light .slot .tag { color: rgba(36,36,36,.55); }
.media .slot .desc {
  font-size: var(--t-sm); color: #fff; max-width: 34ch; margin: 0 auto; line-height: 1.45;
}
.media.light .slot .desc { color: #242424; }

/* ---------------------------------------------------- image motion ------- */

/* ken burns: a very slow scale + pan, the Hers ambient-drift register */
.media.kenburns > img,
.media.kenburns .slot { animation: kenburns 26s ease-in-out infinite alternate; }
@keyframes kenburns {
  from { transform: scale(1)    translate3d(0,0,0); }
  to   { transform: scale(1.07) translate3d(-1.5%, -1%, 0); }
}

/* float: for cut-out product shots and small cards */
.floats { animation: media-float 7s ease-in-out infinite; }
@keyframes media-float {
  0%,100% { transform: translateY(0); }
  50%     { transform: translateY(-15px); }
}

/* reveal-with-scale, on the Hers curve, for media entering the viewport */
.js-motion [data-reveal="media"] { opacity: 0; transform: translate3d(0,26px,0) scale(.97); }
.js-motion [data-reveal="media"].in {
  opacity: 1; transform: none;
  transition: opacity .6s cubic-bezier(.72,0,.45,1), transform .6s cubic-bezier(.72,0,.45,1);
}

/* hover: glass-aware, matches the .3s ease Hers uses on colour + backdrop */
.media.interactive { cursor: pointer; transition: transform .2s ease-in-out, box-shadow .3s cubic-bezier(.4,0,.2,1); }
.media.interactive:hover { transform: translateY(-3px); box-shadow: var(--e-3); }

/* play control sitting over media */
.media .play {
  position: absolute; inset: 0; margin: auto; z-index: 3;
  width: 60px; height: 60px; border-radius: 50%; display: grid; place-items: center;
  background: rgba(255,255,255,.34);
  -webkit-backdrop-filter: saturate(150%) blur(24px); backdrop-filter: saturate(150%) blur(24px);
  border: 1px solid rgba(255,255,255,.62); color: #fff; cursor: pointer;
  box-shadow: 0 8px 26px rgba(0,0,0,.3), inset 0 1px 0 rgba(255,255,255,.7);
  transition: transform .2s ease-in-out, background .3s cubic-bezier(.4,0,.2,1);
}
.media:hover .play { transform: scale(1.07); background: rgba(255,255,255,.44); }
.media .play:active { transform: scale(.96); }

/* ------------------------------------------------------ product stack ---- */
/* The bundle mockup is a transparent cut-out, so it sits directly on the page
   with no frame, no background and no crop. Never wrap it in .media. */
.stack-shot {
  display: block; width: 100%; height: auto; max-width: 780px;
  margin-inline: auto; background: none; border: 0;
}
.stack-shot.sm { max-width: 420px; }
.stack-shot.lg { max-width: 980px; }
/* a very soft ground shadow so the cut-out sits on the page rather than floats */
.stack-wrap { position: relative; }
.stack-wrap::after {
  content: ""; position: absolute; left: 12%; right: 12%; bottom: 4%; height: 26px; z-index: -1;
  background: radial-gradient(50% 50% at 50% 50%, rgba(35,40,23,.18), transparent 72%);
  filter: blur(10px);
}

/* portrait avatars used in testimonials and expert cards */
.avatar {
  width: 64px; height: 64px; border-radius: 50%; flex: none; position: relative; overflow: hidden;
  background: linear-gradient(140deg, #3a4a2a, #1e3944);
  display: grid; place-items: center; color: #fff; font-weight: 600; font-size: var(--t-md);
}
.avatar.lg { width: 88px; height: 88px; font-size: var(--t-lg); }
.avatar::after {
  content: ""; position: absolute; inset: -20%;
  background: radial-gradient(40% 44% at 30% 28%, rgba(197,237,130,.5), transparent 68%);
  animation: media-drift 20s cubic-bezier(.4,0,.2,1) infinite alternate;
}
.avatar span { position: relative; z-index: 1; }

/* real portrait inside an avatar: fills the circle, replaces the drift + initials */
.avatar > img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 1; display: block;
}
.avatar:has(> img)::after { display: none; }
.avatar:has(> img) span { display: none; }

/* ------------------------------------------------------ accessibility ---- */
@media (prefers-reduced-motion: reduce) {
  .media::before, .media.kenburns > img, .media.kenburns .slot,
  .floats, .avatar::after { animation: none !important; }
  .js-motion [data-reveal="media"] { opacity: 1 !important; transform: none !important; }
  .media.interactive:hover, .media:hover .play { transform: none !important; }
}
@media (prefers-reduced-transparency: reduce) {
  .media .play { background: #fff !important; color: var(--moss) !important;
                 -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
}
@media (forced-colors: active) {
  .media { border: 1px solid CanvasText; }
  .media::before, .media::after { display: none; }
}
