/* ============================================================
   MEMORIAL BAND, Jen Weber                          2026-09-01
   Loaded only when $wb_memorial is set (see inc/topscripts.php),
   so this file costs every other page on the site nothing.
   Markup + editable copy: inc/memorial.php
   Behaviour (the endless pile): js/memorial.js

   Palette is sampled from the background art itself, so the photo
   borders read as white stock lying on warm paper rather than as
   two different whites fighting.

   CONTRAST. Text here sits on a PHOTOGRAPH, so a flat token-vs-token
   sum proves nothing. Every figure below was measured instead: render
   the band with the copy set to transparent, take the tight per-line
   box of each text run (a Range, not the element box, which spans the
   whole column and would sample gutters no glyph ever touches), and
   take the darkest pixel in it. Worst case over 27 widths from 320
   to 1920px, against the real rendered background:
     kicker  4.91:1 @ 900px      name  5.03:1 @ 960px
     line    6.43:1 @ 861px      obituary button  6.68:1 @ 1024px
   All clear 4.5:1 as normal text, so none of them leans on the
   large-text exemption. Re-measure if the art or the wash changes.

   Two traps if you re-measure. Kill transitions first: the button
   animates colour over 200ms, so hiding the copy and sampling
   straight away reads the button's own glyphs and reports a false
   failure at nearly every width. And park the pile (drop
   .is-falling/.is-out) before any geometry check: a print that has
   not fallen yet sits 190px above its resting place at opacity 0,
   so its box overlaps things nothing is visible over.
   ============================================================ */

.wb-mem{
  --mem-paper:  #EBE7E0;   /* the ground, sampled from memorial-bg */
  --mem-paper-2:#F2EFE9;   /* the lighter wash the copy sits on */
  --mem-frame:  #FAF8F3;   /* photo stock, a shade above the paper */
  --mem-ink:    #22262b;
  /* Darker than the site's #5c636c muted token on purpose. That token was
     verified against the flat #e8ebef canvas, but the secondary text here
     lands on mottled background ART, where the darkest measured pixel under
     the kicker is #D5D1C9. #5c636c on that is 3.99:1, a plain AA failure at
     the widths where the kicker is under 24px and so not large text.
     #4e555e on the same pixel is 4.95:1 and clears AA at every width. */
  --mem-muted:  #4e555e;
  --mem-red:    #b81e24;
  --mem-hair:   rgba(34,38,43,.16);

  /* Frame widths. Landscape prints run wider than portrait ones, the
     way real 4x6s do, so a mixed pile still looks like one shoebox. */
  --mem-fw-land: clamp(216px, 24vw, 330px);
  --mem-fw-port: clamp(172px, 18.5vw, 250px);

  background-color:var(--mem-paper);
  background-image:url('../images/jen/memorial-bg.webp');
  background-size:cover;
  background-position:left center;
  background-repeat:no-repeat;
  color:var(--mem-ink);

  /* Owns the first screen so the hero's "WE GET / DONE." and the search
     start below the fold for the run of the tribute. */
  min-height:clamp(560px, 82vh, 800px);
  display:flex;
  align-items:center;

  /* Clears the fixed glass nav (top:14px + ~66px tall) at every width;
     the band's default var(--wb-pad) bottoms out at 56px and would tuck
     the kicker under the pill on short screens. */
  padding-top:clamp(6.5rem, 13vh, 9rem);
  padding-bottom:clamp(3.5rem, 7vh, 6rem);
}

/* The wash. Leaves the cross and flowers alone on the left and lifts the
   right into calm paper.
   It deliberately does NOT try to protect the copy. The gradient is a
   percentage of the BAND, while the copy is positioned by the centred
   1180px grid, so the two drift apart as the window changes: measured, the
   copy column starts at 31% of the band at 1440px but 20% at 1280px and 16%
   at 1081px. A single set of stops that covers the copy at every width has
   to start washing at ~14%, which is straight over the cross. So the copy
   carries its own paper instead (see .wb-mem__copy), and this is free to
   stay light and let the art through. */
.wb-mem__scrim{
  position:absolute; inset:0; z-index:1; pointer-events:none;
  background:
    linear-gradient(96deg,
      rgba(235,231,224,0)    0%,
      rgba(235,231,224,.10) 17%,
      rgba(235,231,224,.40) 33%,
      rgba(242,239,233,.62) 50%,
      rgba(242,239,233,.70) 100%),
    /* a soft vignette top and bottom so the band reads as its own sheet */
    linear-gradient(180deg, rgba(255,255,255,.34) 0%, rgba(255,255,255,0) 22%, rgba(255,255,255,0) 78%, rgba(210,204,194,.22) 100%);
}

/* ---- Layout: empty art gutter | tribute | pile ---- */
.wb-mem__inner{
  display:grid;
  /* The copy column carries a 300px floor rather than a bare fraction. When
     the site's "On this page" rail docks at about 1300px it collapses
     .wb-inner from 1180px to (viewport - 560), so the copy column bottoms out
     around 265px there and the tribute broke to three lines between 1300 and
     1335. The floor only binds inside that squeezed range; above and below it
     the fraction is already wider than 300px and nothing moves. The art
     gutter can afford to give the room back, because once the rail narrows
     .wb-inner there is a wide page margin on the left where the cross sits
     anyway. */
  grid-template-columns:minmax(0,.42fr) minmax(300px,1fr) minmax(0,1.18fr);
  align-items:center;
  gap:clamp(1rem,2vw,2.5rem);
  width:100%;
}
/* Column 1 holds no content. It is the room the cross and the flowers
   need in the background photo; without it the copy lands on the cross. */
.wb-mem__art{ min-height:1px; }

/* The paper under the tribute and the pile. Sits in the same grid row as
   the copy and the stack and spans their columns, so its left edge tracks
   the copy column at every width instead of drifting away from it the way a
   band-wide percentage gradient does.
   No visible edge anywhere:
     left   a long soft feather in absolute px, so the fade is the same
            distance at every window size
     right  bleeds 60vw past the grid and is clipped by the band
     top/bottom  bleed 5rem and are masked out
   This replaces the ellipse panel that used to ride on .wb-mem__copy, which
   read as a pale rectangle laid on the photograph at 1024px and 1440px
   because its own radii kept it opaque right up to its edges. */
/* Every item in this grid is placed EXPLICITLY. The wash shares row 1 with
   the copy and the stack, and auto-placement refuses to put an item into a
   cell an explicitly placed one already occupies: leave the others on auto
   and the copy gets pushed down into row 2. */
.wb-mem__wash { grid-area:1 / 2 / 2 / -1; }
.wb-mem__art  { grid-area:1 / 1 / 2 / 2; }
.wb-mem__copy { grid-area:1 / 2 / 2 / 3; }
.wb-mem__stack{ grid-area:1 / 3 / 2 / 4; }

/* DOM order is not enough to keep the wash underneath. Its mask-image makes
   it a stacking context, and a non-positioned element that forms one paints
   with the positioned z-index:0 group, which is LATER than the plain inline
   content of its siblings. Left alone it lies on top of the tribute and
   greys the words out. Positioning the two real items above it fixes the
   order without touching the markup. */
.wb-mem__wash{ z-index:0; }
.wb-mem__copy,
.wb-mem__stack{ position:relative; z-index:1; }

.wb-mem__wash{
  align-self:stretch;
  margin:-5rem -60vw -5rem -2.5rem;
  background:linear-gradient(96deg,
    rgba(242,239,233,0)     0,
    rgba(242,239,233,.66)  95px,
    rgba(242,239,233,.94) 215px,
    rgba(242,239,233,.96) 100%);
  -webkit-mask-image:linear-gradient(180deg, transparent 0, #000 13%, #000 87%, transparent 100%);
          mask-image:linear-gradient(180deg, transparent 0, #000 13%, #000 87%, transparent 100%);
  pointer-events:none;
}

/* ============================================================
   THE TRIBUTE
   Playfair Display against the site's Montserrat/Inter, so the
   serif reads as chosen for this band and not as a loose font.
   fonts-modern.css pins `p,li{font-family:Inter !important}`, which
   is why the paragraph rules below carry !important too.
   ============================================================ */
/* The copy needs no background of its own from 861px up: .wb-mem__wash
   above carries the paper on desktop, and the tablet range calms the whole
   band. Phones bring back a feathered panel, because there the art is
   deliberately left at strength. */
.wb-mem__copy{
  text-align:center; min-width:0;
  padding:clamp(1.5rem,2.4vw,2.3rem) clamp(1rem,2vw,1.9rem) clamp(1.8rem,2.8vw,2.5rem);
}

.wb-mem .wb-mem__kicker{
  font-family:'Playfair Display', Georgia, serif !important;
  font-style:italic; font-weight:400;
  font-size:clamp(1.15rem, .95rem + .8vw, 1.7rem);
  color:var(--mem-muted);
  letter-spacing:.01em; line-height:1.2;
  margin:0 0 .35rem;
}
.wb-mem .wb-mem__name{
  font-family:'Playfair Display', Georgia, serif !important;
  font-weight:600;
  font-size:clamp(2.5rem, 1.5rem + 4vw, 5rem);
  line-height:1.02;
  letter-spacing:.012em;
  text-transform:uppercase;
  color:var(--mem-ink);
  margin:0;
  /* the faintest lift off the paper, not a drop shadow */
  text-shadow:0 1px 0 rgba(255,255,255,.7);
}
.wb-mem .wb-mem__dates{
  font-family:'Playfair Display', Georgia, serif !important;
  font-size:clamp(1rem, .9rem + .35vw, 1.25rem);
  color:var(--mem-muted);
  letter-spacing:.06em;
  margin:.55rem 0 0;
}
/* A hairline rule with a small diamond, the one piece of ornament. */
.wb-mem .wb-mem__rule{
  position:relative;
  height:1px; width:min(230px, 62%);
  margin:clamp(1.1rem,2vh,1.6rem) auto;
  background:linear-gradient(90deg, rgba(34,38,43,0), var(--mem-hair) 22%, var(--mem-hair) 78%, rgba(34,38,43,0));
}
.wb-mem .wb-mem__rule::after{
  content:""; position:absolute; left:50%; top:50%;
  width:6px; height:6px; margin:-3px 0 0 -3px;
  background:var(--mem-red); transform:rotate(45deg);
  opacity:.65;
}
/* Visually hidden, still announced. overhaul.css has no shared utility for
   this (every block defines its own local copy), so this follows the same
   pattern. Used for the "opens in a new tab" tail on the obituary link.
   NOT display:none, which would hide it from assistive tech too. */
.wb-mem .wb-mem__sr{
  position:absolute !important;
  width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%);
  white-space:nowrap; border:0;
}

/* Keeps a hyphenated word whole. A hyphen is a break opportunity, so
   "co-worker" otherwise splits to "co-" / "worker." at most widths. Applied
   by inc/memorial.php to any hyphenated word in the tribute line. */
.wb-mem .wb-mem__nb{ white-space:nowrap; }

.wb-mem .wb-mem__line{
  font-family:'Playfair Display', Georgia, serif !important;
  font-style:italic; font-weight:400;
  font-size:clamp(1.1rem, .98rem + .55vw, 1.5rem);
  line-height:1.45;
  color:var(--mem-ink);
  margin:0 auto;
  max-width:26ch;
}

/* ---- The obituary button. Quiet on purpose: a memorial does not want a
        red call-to-action pill, so it is a thin outline that fills on
        hover. Small, as asked. ---- */
.wb-mem .wb-mem__cta{ margin:clamp(1.4rem,2.6vh,2.1rem) 0 0 !important; }
.wb-mem .wb-mem__btn{
  display:inline-block;
  font-family:'Playfair Display', Georgia, serif !important;
  font-size:.94rem; font-weight:500; letter-spacing:.045em;
  line-height:1;
  padding:.72rem 1.5rem;
  border:1px solid rgba(34,38,43,.34);
  border-radius:2px;                       /* square-ish, the serif's register */
  color:var(--mem-ink);
  /* Nearly opaque, so the button is its own paper. It sits at the bottom of
     the copy block, the first place the feathered phone panel gives out and
     the flowers come through, and it is the only muted-ink text that is not
     large. Carrying its own background means its contrast does not depend on
     what the art happens to do underneath: measured worst case 5.67:1. */
  background:rgba(250,248,243,.88);
  text-decoration:none;
  transition:background .2s ease, border-color .2s ease, color .2s ease;
}
.wb-mem a.wb-mem__btn:hover,
.wb-mem a.wb-mem__btn:focus-visible{
  background:var(--mem-ink);
  border-color:var(--mem-ink);
  color:#fff;
  text-decoration:none;
}
.wb-mem a.wb-mem__btn:focus-visible{
  outline:3px solid var(--mem-red);
  outline-offset:3px;
}
/* The placeholder state, shown until an obituary URL exists. Reads as a
   note rather than a control, and holds the button's exact slot so
   publishing the link later moves nothing on the page. */
.wb-mem .wb-mem__btn--wait{
  color:var(--mem-muted);
  border-style:dashed;
  border-color:rgba(34,38,43,.24);
  background:rgba(250,248,243,.88);
  font-style:italic;
  cursor:default;
}

/* ============================================================
   THE PILE
   Every frame is in the HTML. CSS gives it the white stock, the
   near-monochrome grade and the fall; memorial.js only decides
   when each one drops. With JS off the whole pile is simply
   there, stacked and still, which is a perfectly good page.
   ============================================================ */
.wb-mem__stack{
  position:relative;
  min-height:clamp(330px, 38vw, 470px);
  display:flex; align-items:center; justify-content:center;
}
.wb-mem__pile{ position:relative; width:100%; height:100%; min-height:inherit; }

.wb-mem-photo{
  position:absolute; left:50%; top:50%;
  margin:0;
  z-index:1;
  background:var(--mem-frame);
  /* content-box so the white stock is added AROUND the photo instead of
     eating into it (owner, 2026-09-01: border on the outside). The design
     system sets border-box on everything in .wb-scope, so this has to say
     so explicitly. --mem-fw-* is therefore the width of the PICTURE, and
     each print ends up 2x the padding wider than that. */
  box-sizing:content-box;
  padding:13px;
  border-radius:2px;
  /* Two shadows: a tight contact shadow where the print meets the pile,
     and a wide soft one for the height it fell from. */
  box-shadow:
    0 1px 2px rgba(60,52,40,.28),
    0 14px 30px -8px rgba(60,52,40,.42);
  transform:
    translate(-50%,-50%)
    translate3d(var(--fx,0), var(--fy,0), 0)
    rotate(var(--r,0deg));
  will-change:transform, opacity;
}
/* The frame widths are sized from the viewport, but the column they sit in is
   sized by the grid, and those two part company when the site's "On this page"
   rail docks around 1300px and narrows .wb-inner. There the prints were
   reaching 25px past their own column and into the copy's. Capping against
   100% of the pile keeps a print inside its column at any width; the 44px
   allows for this frame's own border plus a little slack for the rotation.
   min() means the cap only bites in that squeezed range and changes nothing
   at ordinary desktop widths. */
.wb-mem-photo.is-land{ width:min(var(--mem-fw-land), calc(100% - 44px)); }
.wb-mem-photo.is-port{ width:min(var(--mem-fw-port), calc(100% - 44px)); }

/* The image window. Fixed aspect per orientation so mixed originals
   (a 1600x2844 phone shot next to a 2878x1372 group photo) still read
   as ordinary prints. */
.wb-mem-photo__shot{
  display:block; position:relative; overflow:hidden;
  background:#ded9d1;
  border-radius:1px;
}
.wb-mem-photo.is-land .wb-mem-photo__shot{ aspect-ratio:4/3; }
.wb-mem-photo.is-port .wb-mem-photo__shot{ aspect-ratio:3/4; }
.wb-mem-photo__shot img{
  width:100%; height:100%; display:block;
  object-fit:cover;
  /* Mostly desaturated, about 15% of the colour left, with a whisper of
     sepia so the prints sit in the warm paper instead of going cold. */
  filter:grayscale(.85) sepia(.08) contrast(1.04) brightness(1.02);
}

/* Captions are OFF by default (see $mem_show_captions in inc/memorial.php).
   The pile reads stronger as pure imagery, and the words stay with the
   tribute. When they are switched on the pile gets .has-caps, which opens
   up the deeper print-bottom the caption sits in. */
.wb-mem-photo__cap{ display:none; }
.wb-mem__pile.has-caps .wb-mem-photo{ padding:12px 12px 4px; }
.wb-mem .wb-mem__pile.has-caps .wb-mem-photo__cap{
  display:block;
  font-family:'Playfair Display', Georgia, serif !important;
  font-size:clamp(.72rem, .66rem + .18vw, .84rem);
  font-style:italic;
  line-height:1.25;
  color:#4a5058;                 /* 7.4:1 on the #FAF8F3 photo stock */
  text-align:center;
  padding:.5rem .25rem .34rem;
  margin:0;
}

/* ---- The fall ----------------------------------------------------
   Gravity, then a landing. The photo starts above the pile, larger
   (nearer the eye), over-rotated and motion-blurred; it accelerates
   down, lands at 58%, rebounds a few pixels, and settles. The
   timing functions are per-keyframe because one curve cannot both
   accelerate into the impact and ease out of it.
   ------------------------------------------------------------------ */
@keyframes wb-mem-fall{
  0%{
    opacity:0;
    transform:
      translate(-50%,-50%)
      translate3d(calc(var(--fx,0px) - 14px), calc(var(--fy,0px) - 190px), 0)
      rotate(calc(var(--r,0deg) + var(--rf,8deg)))
      scale(1.13);
    filter:blur(2.4px);
    animation-timing-function:cubic-bezier(.5,.02,.76,.36);   /* accelerate */
  }
  14%{ opacity:1; }
  58%{
    opacity:1;
    transform:
      translate(-50%,-50%)
      translate3d(var(--fx,0px), var(--fy,0px), 0)
      rotate(var(--r,0deg))
      scale(1);
    filter:blur(0);
    animation-timing-function:cubic-bezier(.2,.7,.35,1);      /* the bounce out */
  }
  72%{
    transform:
      translate(-50%,-50%)
      translate3d(var(--fx,0px), calc(var(--fy,0px) - 7px), 0)
      rotate(calc(var(--r,0deg) - .7deg))
      scale(1.011);
    animation-timing-function:cubic-bezier(.45,0,.3,1);
  }
  86%{
    transform:
      translate(-50%,-50%)
      translate3d(var(--fx,0px), calc(var(--fy,0px) + 1.5px), 0)
      rotate(calc(var(--r,0deg) + .35deg))
      scale(.999);
  }
  100%{
    opacity:1;
    transform:
      translate(-50%,-50%)
      translate3d(var(--fx,0px), var(--fy,0px), 0)
      rotate(var(--r,0deg))
      scale(1);
    filter:blur(0);
  }
}
/* The shadow tightens as the print comes down, so height reads as height. */
@keyframes wb-mem-fall-shadow{
  0%{   box-shadow:0 3px 6px rgba(60,52,40,.10), 0 46px 60px -14px rgba(60,52,40,.34); }
  58%{  box-shadow:0 1px 2px rgba(60,52,40,.28), 0 14px 30px -8px rgba(60,52,40,.42); }
  72%{  box-shadow:0 2px 4px rgba(60,52,40,.22), 0 20px 36px -10px rgba(60,52,40,.40); }
  100%{ box-shadow:0 1px 2px rgba(60,52,40,.28), 0 14px 30px -8px rgba(60,52,40,.42); }
}

/* JS is driving: hide the pile so the drops can be sequenced. The class
   is set by an inline one-liner in the band itself, before the browser
   paints, so there is no flash of the assembled pile first. */
.wb-mem-js .wb-mem-photo{ opacity:0; }
/* 1.5s: slowed from 1.25s (owner, 2026-09-01). Keep FALL_MS in
   js/memorial.js in step with this number. */
.wb-mem-js .wb-mem-photo.is-falling{
  animation:
    wb-mem-fall 1.5s both,
    wb-mem-fall-shadow 1.5s both;
}
/* Leaving the pile: the bottom print, already buried, fades out slowly
   while the eye is on the one coming down. */
.wb-mem-js .wb-mem-photo.is-out{
  animation:none;
  opacity:0;
  transition:opacity .9s ease;
}

/* ============================================================
   THE DOVE, crossing the seam into the dark hero below
   ============================================================ */
.wb-mem-dove{ z-index:44; }
.wb-mem-dove__glide{
  position:absolute;
  /* Sits mostly BELOW the seam, so the dove reads as having crossed into
     the dark hero rather than hovering in the flowers. That also keeps it
     off every piece of memorial content: the cross and flowers are on the
     left of the band above, the pile is on the right, and the top of the
     hero below is empty for the depth of its own padding. */
  left:30%;
  top:clamp(-56px, -3.2vw, -28px);
  width:clamp(112px, 13vw, 196px);
  display:block;
  /* The drift lives on this wrapper because overhaul.js writes transform
     onto the inner [data-drive] img; both on one element would fight. */
  animation:wb-mem-dove-drift 9s ease-in-out infinite;
}
.wb-mem-dove__img{
  position:static;
  width:100%; height:auto;
  bottom:auto; left:auto;
  filter:drop-shadow(0 10px 16px rgba(40,34,26,.28));
}
@keyframes wb-mem-dove-drift{
  0%,100%{ transform:translateY(0) rotate(0deg); }
  50%    { transform:translateY(-11px) rotate(-1.6deg); }
}
/* Phones: keep the dove small and well inside the viewport. The drive tops out
   at 13vw, so left:11% + 13vw + the sprite width still clears the right
   edge at 360px and cannot widen the document. */
@media (max-width:768px){
  .wb-mem-dove__glide{ left:11%; width:clamp(84px, 22vw, 120px); top:-38px; }
}

/* ============================================================
   RESPONSIVE
   ============================================================ */

/* Tablet, 861 to 1080. The art gutter is gone here, so the tribute sits
   directly over the busiest part of the photograph: the cross and the dark
   diagonal texture beside it. A feathered panel alone cannot win that, it
   just reads as a pale rectangle laid on the picture, and its top edge left
   the kicker at 3.1:1. So this range calms the whole field instead and lets
   the panel do nothing but top it up. Phones override this again below,
   where the art is wanted at strength. */
@media (max-width:1080px){
  .wb-mem__inner{ grid-template-columns:minmax(0,1fr) minmax(0,1.1fr); }
  .wb-mem__art{ display:none; }
  /* The wash is a desktop device: with the art gutter gone the copy runs to
     the left edge, so there is nothing for it to feather across. */
  .wb-mem__wash{ display:none; }
  .wb-mem__copy { grid-area:1 / 1 / 2 / 2; }
  .wb-mem__stack{ grid-area:1 / 2 / 2 / 3; }
  .wb-mem{ background-position:22% center; }
  .wb-mem__scrim{
    background:
      linear-gradient(96deg,
        rgba(238,235,228,.34)   0%,
        rgba(240,237,230,.66)  20%,
        rgba(242,239,233,.88)  42%,
        rgba(242,239,233,.92) 100%),
      linear-gradient(180deg, rgba(255,255,255,.30) 0%, rgba(255,255,255,0) 24%, rgba(255,255,255,0) 76%, rgba(210,204,194,.20) 100%);
  }
  /* More room around the words, so the panel's fade happens out in the
     padding rather than across the first line of type. */
  .wb-mem__copy{ padding:clamp(2rem,4vw,3rem) clamp(1.4rem,3vw,2.4rem); }
}

/* Phone: the tribute reads first, the pile sits under it. */
@media (max-width:860px){
  .wb-mem{
    /* 14%, pulled left from 30% (owner, 2026-09-01) so the cross and the top
       of the flowers are actually in frame on a phone. At cover on a portrait
       viewport the 2400px art is cropped hard, and 30% landed the window just
       PAST the flowers, on empty paper. */
    background-position:14% center;
    min-height:0;
    /* Extra head room so that art has a clear run above the kicker instead of
       sitting behind it. */
    padding-top:clamp(7.5rem, 19vh, 10rem);
  }
  .wb-mem__inner{
    grid-template-columns:1fr;
    gap:clamp(1.5rem,4vh,2.5rem);
  }
  /* A phone has no side margin to hide the art in, so a band-wide wash
     strong enough to protect the copy also washes the cross out to nothing.
     Instead the band keeps only a light overall wash, and the paper the text
     needs is carried on the copy block itself (below) as a soft feathered
     panel. Net: the cross and flowers read at close to full strength
     everywhere the tribute is not. */
  .wb-mem__scrim{
    background:
      linear-gradient(180deg,
        rgba(240,237,231,.22)   0%,
        rgba(240,237,231,.34)  30%,
        rgba(242,239,233,.46)  62%,
        rgba(242,239,233,.54) 100%);
  }
  /* Phones stack, and they are the one place the band scrim stays light so
     the cross and flowers read at strength. That means the tribute does need
     paper of its own here: a feathered ellipse, centred on centred text, so
     it fades out well before the band edges and passes as light falling on
     the sheet rather than a panel. */
  .wb-mem__copy {
    grid-area:1 / 1 / 2 / 2;
    padding:1.7rem 1.1rem 2rem;
    background:radial-gradient(ellipse 112% 78% at 50% 50%,
      rgba(243,240,234,.985) 0%,
      rgba(243,240,234,.965) 44%,
      rgba(243,240,234,.86)  66%,
      rgba(243,240,234,.40)  85%,
      rgba(243,240,234,0)   100%);
  }
  .wb-mem__stack{ grid-area:2 / 1 / 3 / 2; }
  .wb-mem__stack{ min-height:clamp(300px, 74vw, 400px); }
  .wb-mem{
    --mem-fw-land:clamp(200px, 54vw, 290px);
    --mem-fw-port:clamp(158px, 42vw, 220px);
  }
}

/* ============================================================
   REDUCED MOTION
   No falling, no loop, nothing that moves. The pile is laid out
   as a small still fan of the first six prints, which is the same
   picture the animation ends on, minus the motion.
   ============================================================ */
@media (prefers-reduced-motion:reduce){
  .wb-mem-js .wb-mem-photo,
  .wb-mem-photo{
    opacity:1 !important;
    animation:none !important;
    transition:none !important;
  }
  .wb-mem-photo:nth-child(n+7){ display:none; }
  .wb-mem-dove__glide{ animation:none; }
}
