/* ————— Palette from the printed pieces ————— */
:root{
  --paper:#e8e5df;
  --card:#faf8f4;
  --graphite:#14161a;
  --champagne:#a8926b;
  --tagnum:#c9b389;
  --cream:#efe9dd;
}

*{box-sizing:border-box}
html,body{height:100%;height:100dvh}
body{
  margin:0;
  background:#dedbd4;
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  color:var(--graphite);
  overflow:hidden;
  overscroll-behavior:none;
  -webkit-tap-highlight-color:transparent;
  user-select:none;
  -webkit-user-select:none;
  transition:background 1200ms ease;
}
body.dark{background:#0b0c0f}

/* ————— Ambient keyframes (motion doc) ————— */
@keyframes v2rake{0%{transform:translateX(-70%) rotate(14deg)}100%{transform:translateX(190%) rotate(14deg)}}
@keyframes v2breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.006)}}
@keyframes v2caret{0%,70%,100%{transform:translateX(0);opacity:.6}82%{transform:translateX(5px);opacity:1}}
@keyframes v2swing{0%{transform:rotate(0)}22%{transform:rotate(3.4deg)}52%{transform:rotate(-1.6deg)}78%{transform:rotate(.7deg)}100%{transform:rotate(0)}}
@keyframes v2mote{0%{transform:translate(0,0);opacity:0}12%{opacity:.5}88%{opacity:.4}100%{transform:translate(14px,-190px);opacity:0}}
@keyframes v2shake{0%,100%{transform:translate(0,0)}20%{transform:translate(-3px,2px)}45%{transform:translate(3px,-2px)}70%{transform:translate(-2px,-1px)}}
@keyframes v2hair{0%{transform:translateX(-100%)}100%{transform:translateX(260%)}}
@keyframes v2emboss{0%{transform:translateX(-170%) skewX(-16deg)}100%{transform:translateX(350%) skewX(-16deg)}}
@keyframes v2lamp{0%,100%{opacity:1}17%{opacity:.962}34%{opacity:1}56%{opacity:.978}73%{opacity:.949}88%{opacity:.994}}
@keyframes v2jolt{0%,100%{transform:translate(0,0) rotate(0)}16%{transform:translate(-1.7px,1.2px) rotate(-.28deg)}40%{transform:translate(1.5px,-.9px) rotate(.2deg)}68%{transform:translate(-.7px,.4px) rotate(-.09deg)}86%{transform:translate(.3px,-.2px) rotate(.04deg)}}
@keyframes v2pool{0%,100%{opacity:.84;transform:translateX(-50%) scaleX(1)}50%{opacity:1;transform:translateX(-50%) scaleX(1.04)}}
/* light-rig keyframes: shafts drift, glints fire, grain jitters */
@keyframes v2ray{0%,100%{opacity:.42;transform:translateX(0) skewX(var(--sk,0deg)) scaleY(1)}50%{opacity:.9;transform:translateX(5px) skewX(var(--sk,0deg)) scaleY(1.05)}}
@keyframes v2glint{
  0%,66%,100%{transform:translate(-50%,-50%) scale(0) rotate(0deg);opacity:0}
  7%{transform:translate(-50%,-50%) scale(1) rotate(24deg);opacity:1}
  20%{transform:translate(-50%,-50%) scale(.5) rotate(42deg);opacity:.45}
  36%{transform:translate(-50%,-50%) scale(.92) rotate(58deg);opacity:.9}
  54%{transform:translate(-50%,-50%) scale(0) rotate(74deg);opacity:0}
}
@keyframes v2spin{0%{transform:translate(-50%,-50%) rotate(0deg)}100%{transform:translate(-50%,-50%) rotate(360deg)}}
/* the highlight travels, then rests off the metal for most of the cycle */
@keyframes v2sheen{
  0%{transform:translateX(-170%) skewX(-13deg)}
  52%,100%{transform:translateX(320%) skewX(-13deg)}
}
@keyframes v2grain{
  0%{transform:translate(0,0)}
  20%{transform:translate(-13px,8px)}
  40%{transform:translate(10px,-11px)}
  60%{transform:translate(-7px,-14px)}
  80%{transform:translate(12px,6px)}
  100%{transform:translate(0,0)}
}

/* ————— Frame: fluid design space, scaled to viewport (sized by JS) ————— */
#frame-scaler{
  position:fixed;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
}
#frame{
  position:relative;
  flex:none;
  width:390px;
  height:844px;
  overflow:hidden;
  background:var(--paper);
  box-shadow:0 14px 50px rgba(20,22,26,.24);
  transition:background 1200ms cubic-bezier(.4,0,.25,1);
  transform-origin:center center;
}
#frame.dark{background:var(--graphite)}
/* full-bleed on phones: no drop shadow to give away the letterbox */
#frame.bleed{box-shadow:none}

/* ————— Filmstrip ————— */
#film{
  position:absolute;
  inset:0;
  transform:translateX(0%);
  will-change:transform;
}
.stage{
  position:absolute;
  left:0;top:0;
  width:100%;height:100%;
  overflow:hidden;
  clip-path:inset(0px);
}
.cam{
  position:absolute;
  inset:0;
  will-change:transform;
}

/* ————— Stage 0: fluid vertical rhythm —————
   The envelope block keeps its designed 344×242 proportions; the four gaps
   above/between/below it grow and shrink in the ratio the 844-tall design used
   (74 : 32 : 46 : 200 : 52), so the same composition survives any frame height. */
#st0-stack{
  position:absolute;
  inset:0;
  display:flex;
  flex-direction:column;
  align-items:center;
  padding:0 23px;
}
#st0-stack .sp{display:block;width:1px;min-height:0}
#head0{
  flex:none;
  width:100%;
  text-align:center;
  opacity:1;
  transition:opacity 600ms ease;
}
#env-wrap{
  position:relative;
  flex:none;
  width:min(344px,100%);
  aspect-ratio:344/242;
  perspective:1150px;
  perspective-origin:50% 26%;
  animation:v2breathe 7s ease-in-out infinite;
}
#hero{
  flex:none;
  width:100%;
  display:flex;
  flex-direction:column;
  align-items:center;
  opacity:1;
  transition:opacity 500ms ease;
}
#foot0{
  flex:none;
  text-align:center;
  font:400 8.5px/1.8 'IBM Plex Mono',monospace;
  letter-spacing:.3em;
  color:rgba(20,22,26,.45);
}

/* ————— Captions: the two lines rise on a stagger, not as one block ————— */
#caption{transition:opacity 520ms ease}
.cap-line{
  opacity:0;
  transform:translateY(9px);
  transition:opacity 760ms ease,transform 900ms cubic-bezier(.16,1,.3,1);
}
#caption.up .cap-line{opacity:1;transform:translateY(0)}
#caption.up #cap-title{transition-delay:130ms}

/* ————— Specular travel on the ring —————
   A band of light sliding over a flat rectangle reads as a grey slab the
   moment the animation is anywhere but mid-sweep — which is what a stalled
   or finished animation leaves on screen. Masking the layer with the ring
   artwork means the highlight can only ever land on the metal, and the band
   itself is a blurred gradient, so there is no edge to catch. */
#sheen{
  position:absolute;
  inset:0;
  overflow:hidden;
  opacity:0;
  pointer-events:none;
  mix-blend-mode:screen;
  -webkit-mask-image:url(../assets/ring.png);
  mask-image:url(../assets/ring.png);
  -webkit-mask-size:100% 100%;
  mask-size:100% 100%;
  -webkit-mask-repeat:no-repeat;
  mask-repeat:no-repeat;
  transition:opacity 1400ms ease;
}
#sheen i{
  position:absolute;
  top:-30%;
  left:0;
  width:34%;
  height:160%;
  background:linear-gradient(90deg,transparent,rgba(255,247,230,.8) 48%,transparent);
  filter:blur(7px);
  transform:translateX(-170%) skewX(-13deg);
}
#sheen.on i{animation:v2sheen 5.6s cubic-bezier(.42,0,.58,1) infinite}

/* ————— Light rig: glints and grain ————— */
/* the prismatic wheel is a blurred, rotating layer — only spin it once the
   stage is actually lit, never behind an invisible opacity:0 */
#prism.on{animation:v2spin 26s linear infinite}
.glint{
  position:absolute;
  display:block;
  background:#fff7e6;
  box-shadow:0 0 15px 4px rgba(255,238,205,.85);
  clip-path:polygon(50% 0,59% 41%,100% 50%,59% 59%,50% 100%,41% 59%,0 50%,41% 41%);
  transform:translate(-50%,-50%) scale(0);
  opacity:0;
  animation-name:v2glint;
  animation-timing-function:ease-in-out;
  animation-iteration-count:infinite;
}
/* fine film grain — kills the banding that dark radial gradients show on OLED
   phones, and gives the dark stages a photographic surface */
#grain{
  position:absolute;
  inset:-70px;
  z-index:23;
  pointer-events:none;
  opacity:0;
  mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='170' height='170'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='170' height='170' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
  background-size:170px 170px;
  animation:v2grain 1.1s steps(1,end) infinite;
  transition:opacity 1400ms ease;
}

/* ————— Lot tag hero ————— */
#tag-btn:active{filter:brightness(1.05)}
#tag-btn.swing{animation:v2swing 620ms cubic-bezier(.33,1,.68,1)}
#env-tilt.jolt{animation:v2jolt 250ms cubic-bezier(.36,.07,.19,.97) 1}
#st6.shake{animation:v2shake 280ms cubic-bezier(.36,.07,.19,.97) 1}

/* ————— Finale band + ghost buttons (Hammer Rule) ————— */
.band-btn{
  position:relative;
  display:block;
  width:100%;
  height:58px;
  border:none;
  background:none;
  padding:0;
  cursor:pointer;
  overflow:hidden;
  border-top:1px solid rgba(20,22,26,.55);
  border-bottom:1px solid rgba(20,22,26,.55);
  transition:background 260ms ease;
}
.band-btn:hover{background:rgba(20,22,26,.045)}
.band-btn:active{background:rgba(20,22,26,.09)}
.band-inner{
  position:absolute;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:space-between;
  padding:0 18px;
}
.band-label{
  font:400 11px/1 'IBM Plex Mono',monospace;
  letter-spacing:.36em;
  color:var(--graphite);
  padding-left:.36em;
}
.band-caret{
  font:400 12px/1 'IBM Plex Mono',monospace;
  color:var(--champagne);
  animation:v2caret 3s ease-in-out infinite;
}
.band-hair{
  position:absolute;
  left:0;right:0;bottom:0;
  height:1px;
  overflow:hidden;
}
.band-hair div{
  width:40%;height:100%;
  background:linear-gradient(90deg,transparent,var(--champagne),transparent);
  animation:v2hair 4.5s linear infinite;
}
/* ————— Buttons —————
   From the project's own Button System sheet, which was specified and never
   used. The rule that matters: anything pressable has an edge, anything that
   is only a hint does not. Bare letterspaced text in a row reads as a caption,
   which is exactly how the finale controls were being missed.
   Square always — a rounded corner is the one plastic thing on a paper table. */
.btn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-height:44px;
  box-sizing:border-box;
  padding:13px 18px 13px 22px;
  border:1px solid rgba(168,146,107,.55);
  border-radius:0;
  background:transparent;
  font:400 10px/1 'IBM Plex Mono',monospace;
  letter-spacing:.28em;
  color:var(--champagne);
  text-decoration:none;
  cursor:pointer;
  transition:background 160ms cubic-bezier(.22,.68,.16,1),
             color 160ms cubic-bezier(.22,.68,.16,1),
             border-color 160ms ease,
             transform 90ms cubic-bezier(.22,.68,.16,1);
}
.btn:hover{background:rgba(168,146,107,.1);border-color:var(--champagne)}
.btn:active{transform:translateY(1px);background:rgba(168,146,107,.18)}
.btn--primary{
  background:var(--champagne);
  border-color:var(--champagne);
  color:var(--graphite);
}
.btn--primary:hover{background:#c4ad83;border-color:#c4ad83}
.btn--primary:active{background:#8a7550;transform:translateY(1px)}
.btn--quiet{
  border-color:rgba(20,22,26,.28);
  color:rgba(20,22,26,.55);
}
.btn--quiet:hover{background:rgba(20,22,26,.05);border-color:rgba(20,22,26,.5);color:var(--graphite)}

/* a hint is NOT a button — no edge, lower contrast, and it says so.
   It also needs air above it, or it crowds the row and reads as attached. */
.hint{
  font:italic 400 11px/1.4 'Newsreader',Georgia,serif;
  letter-spacing:.02em;
  color:rgba(20,22,26,.42);
  text-align:center;
  margin-top:20px;
}

/* finale control rows */
.ctrl-row{
  display:flex;
  justify-content:center;
  align-items:center;
  gap:10px;
  flex-wrap:wrap;
  padding-top:12px;
}

/* ————— Music utility button (round, dark, pause bars) ————— */
#music-btn{
  position:absolute;
  top:18px;
  left:18px;
  z-index:28;
  width:44px;height:44px;
  border-radius:50%;
  background:rgba(20,22,26,.85);
  border:1px solid rgba(201,179,137,.35);
  cursor:pointer;
  display:flex;
  align-items:center;
  justify-content:center;
  gap:2.5px;
  transition:transform 200ms cubic-bezier(.34,1.4,.64,1),opacity 600ms ease;
}
#music-btn[hidden]{display:none}

/* ————— A private view · the souvenir —————
   A dark gallery ground is what makes the cream artwork glow; the note sits
   under it as a plate's dedication, in the same Newsreader italic the film
   speaks in. It scrolls internally because body is overflow:hidden for the film. */
#souvenir{
  position:absolute;
  inset:0;
  z-index:32;
  background:var(--stage,#0d0f12);
  opacity:0;
  transition:opacity 620ms cubic-bezier(.22,.68,.16,1);
}
#souvenir[hidden]{display:none}
#souvenir.on{opacity:1}
#souvenir-scroll{
  position:absolute;
  inset:0;
  overflow-y:auto;
  overflow-x:hidden;
  -webkit-overflow-scrolling:touch;
  overscroll-behavior:contain;
  padding:0 0 64px;
  text-align:center;
}
/* ————— The frame —————
   Sized by HEIGHT, not width, so the whole plate is on screen at rest and
   nothing has to be scrolled to see it. The stage is a share of the frame's
   own height, the mount fills the stage, and the artwork fills the mount —
   its width follows from its 941:1672 proportion, so the frame shrinks to it. */
.sv-stage{
  /* tall enough that the frame is width-bound on a phone — it hangs as large
     as the screen allows while still landing whole, with the plate line just
     below it to show there is more */
  height:88%;
  display:flex;
  align-items:center;
  justify-content:center;
  /* the top pad clears the CLOSE control, so the frame hangs below it rather
     than having a chip sitting on the mount */
  padding:60px 12px 0;
  box-sizing:border-box;
}
/* The gilt frame is a real PNG with a transparent window, so the artwork is
   positioned INTO that window rather than the frame being drawn in CSS. The
   numbers below are measured from the file's alpha channel, not estimated:
   window = 289,207 → 751,1278 of a 1024×1536 image. Its aspect is 0.431 while
   the artwork is 0.563, so the art is centre-cropped to fill — the bride is
   dead centre, which is what makes that crop read as deliberate. */
.sv-frame{
  position:relative;
  height:100%;
  aspect-ratio:1024/1536;
  filter:drop-shadow(0 22px 40px rgba(0,0,0,.62));
}
#souvenir-art{
  position:absolute;
  left:28.223%;
  top:13.477%;
  width:45.117%;
  height:69.727%;
  object-fit:cover;
  object-position:center;
  display:block;
}
#souvenir-frame{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  display:block;
  pointer-events:none;
}
.sv-plate{padding:26px 28px 0}
.sv-lot{
  font:400 9px/1 'IBM Plex Mono',monospace;
  letter-spacing:.42em;
  color:var(--champagne);
  padding-left:.42em;
}
.sv-rule{
  width:34px;height:1px;
  background:rgba(201,179,137,.5);
  margin:18px auto 0;
}
.sv-note{
  padding:26px 34px 0;
  text-align:left;
  max-width:330px;
  margin:0 auto;
}
.sv-note p{
  font:italic 400 16px/1.75 'Newsreader',Georgia,serif;
  color:rgba(239,233,221,.9);
  margin:0 0 15px;
  text-wrap:pretty;
}
.sv-sign{
  font:italic 400 20px/1.4 'Newsreader',Georgia,serif;
  color:var(--champagne);
  text-align:right;
  max-width:330px;
  margin:6px auto 0;
  padding:0 34px;
}
.sv-foot{
  font:400 8.5px/1 'IBM Plex Mono',monospace;
  letter-spacing:.34em;
  color:rgba(239,233,221,.35);
  padding:40px 28px 0;
}
#souvenir-close{
  position:absolute;
  top:16px;right:16px;
  z-index:34;
  border-color:rgba(201,179,137,.45);
  color:rgba(239,233,221,.75);
  background:rgba(13,15,18,.72);
}
#souvenir-close:hover{background:rgba(201,179,137,.16);color:#faf8f4}

/* ————— Skip —————
   Present from the landing screen on, because the guest most likely to want it
   is the one re-opening the link the night before to check the time. It hides
   at the finale, which is where it sends them. */
#skip-btn{
  position:absolute;
  top:26px;right:18px;
  z-index:28;
  background:none;
  border:none;
  padding:10px 2px 10px 8px;
  font:400 9px/1 'IBM Plex Mono',monospace;
  letter-spacing:.3em;
  color:rgba(20,22,26,.45);
  cursor:pointer;
  transition:color 260ms ease,opacity 500ms ease;
}
#skip-btn:hover{color:var(--graphite)}
body.dark #skip-btn{color:rgba(239,233,221,.5)}
body.dark #skip-btn:hover{color:rgba(239,233,221,.9)}
#skip-btn[hidden]{display:none}
#music-btn:hover{transform:scale(1.06)}
#music-btn:active{transform:scale(.94)}
#music-btn .bar{
  width:2px;height:11px;
  background:var(--tagnum);
  transition:height 200ms ease,transform 200ms ease;
}
/* paused → the two bars become a play wedge-ish pair */
#music-btn.paused .bar:first-child{transform:translateX(1px) rotate(0deg)}
#music-btn.paused .bar:last-child{height:7px;opacity:.5}
#yt-player{position:fixed;left:-9999px;top:0;width:1px;height:1px;opacity:0;pointer-events:none}

/* ————— Finale card (design unchanged from the printed piece) ————— */
.mono-label{
  font:400 10px/1.8 'IBM Plex Mono',monospace;
  letter-spacing:.32em;
  color:var(--graphite);
}
.mono-label.dim{color:rgba(20,22,26,.55)}
.mono-label.gold{color:var(--champagne)}

.card-scaler{
  position:relative;
  width:min(344px,88%);
  aspect-ratio:1123/794;
  perspective:2000px;
  cursor:zoom-in;
  box-shadow:0 18px 46px rgba(20,22,26,.24);
}

/* ————— Enlarged card —————
   An A4 landscape sheet only reads on a portrait phone if it is turned. The
   transform itself is written inline from JS, because the finale timeline
   writes this element's transform inline too and a stylesheet rule loses. */
#st7.zoomed .card-scaler{
  position:absolute;
  left:50%;top:50%;
  margin:0;
  cursor:zoom-out;
  z-index:4;
}
#st7.zoomed #card-head,
#st7.zoomed #card-ctrl{opacity:0 !important;pointer-events:none}
#card-close{
  position:absolute;
  top:16px;right:16px;
  z-index:6;
  letter-spacing:.3em;
}
#card-close[hidden]{display:none}

/* ————— The sheet —————
   The card is laid out at its true printed size, 1123 x 794, and the whole
   sheet is then scaled down by --sheet (set in JS from the slot width).
   That matters: sized down directly, the smallest type lands near 4px, and
   WebKit quietly inflates text that small at paint time, so the columns wrap
   far more than the layout allows and side B runs past the trim. Scaling a
   full-size layout has no such floor, and it makes the card an exact
   reduction of the printed sheet instead of an approximation of it. */
.sheet{
  position:absolute;
  left:0;top:0;
  width:1123px;
  height:794px;
  transform-origin:0 0;
  transform:scale(var(--sheet,.306));
  /* The perspective has to live HERE, not on .card-scaler. CSS perspective
     applies only to an element's direct children, and .flip is a grandchild
     once this wrapper exists — with it on the scaler the card turned flat and
     orthographic, which is what read as "not smooth". In sheet coordinates
     the card is 1123px wide, so this is roughly 2.3x its width. */
  perspective:2600px;
  -webkit-perspective:2600px;
}
.flip{
  position:relative;
  width:100%;height:100%;
  transform-style:preserve-3d;
  -webkit-transform-style:preserve-3d;
  transition:transform 900ms cubic-bezier(.4,0,.2,1);
  will-change:transform;
}
.flip.flipped{transform:rotateY(180deg)}
.face{
  position:absolute;
  inset:0;
  background:var(--card);
  backface-visibility:hidden;
  -webkit-backface-visibility:hidden;
}
/* Face switch at the halfway point. It is needed because the clip-path on
   .stage flattens the 3D context on WebKit and defeats backface-visibility.
   A hard 0ms switch popped, so it is a short crossfade centred on the midpoint
   of the 900ms turn (390ms delay, 120ms fade) — brief enough that the two faces
   are never both legible, long enough that the change is not a snap. */
.face-front{transform:rotateY(0deg);opacity:1;transition:opacity 120ms linear 390ms}
.face-back{transform:rotateY(180deg);opacity:0;transition:opacity 120ms linear 390ms}
.flip.flipped .face-front{opacity:0}
.flip.flipped .face-back{opacity:1}
.face-cq{position:absolute;inset:0;overflow:hidden}

/* --emb-standard from the digital kit, at the 50% the component sheet sets */
.emboss{
  filter:drop-shadow(2.5px 2.5px 1px rgba(20,22,26,.28)) drop-shadow(-2px -2px 1px rgba(255,255,255,.95));
  opacity:.5;
}
.card-tiger{position:absolute;left:-70px;bottom:-70px;width:560px;height:570px;z-index:0}
.card-shark{position:absolute;right:-26px;bottom:-46px;width:376px;height:550px;z-index:0}

.card-inner{
  position:absolute;
  left:72px;top:64px;right:72px;bottom:64px;
  display:flex;
  flex-direction:column;
  z-index:1;
}
.face .mono-label{font:400 11px/1.9 'IBM Plex Mono',monospace;letter-spacing:.36em}
.face .mono-label.dim{color:rgba(20,22,26,.5)}
.face .mono-label.gold{color:var(--champagne);letter-spacing:.32em}
.card-toprow,.card-foot{display:flex;justify-content:space-between}
.card-rule{height:1px;background:rgba(20,22,26,.16);margin-top:14px}

/* ————— Side A ————— */
.face-front .card-inner{align-items:flex-end;text-align:right}
.face-front .card-toprow,.face-front .card-rule{width:100%}
.card-names{
  margin-top:46px;
  font:400 32px/1 'Newsreader',Georgia,serif;
  letter-spacing:.13em;
  white-space:nowrap;
}
.amp{color:var(--champagne)}
.card-sub{margin-top:14px;letter-spacing:.26em}
.card-num{
  font:400 250px/.8 'Newsreader',Georgia,serif;
  letter-spacing:-.012em;
  margin-top:auto;
}
.card-numlab{margin-top:20px;letter-spacing:.42em}
.card-footrow{width:452px;margin-top:auto}
.card-foot{margin-top:20px;letter-spacing:.3em}
.card-foot span{white-space:nowrap}

/* ————— Side B ————— */
.card-lede{
  font:400 40px/1.28 'Newsreader',Georgia,serif;
  margin-top:34px;
  max-width:700px;
  text-wrap:pretty;
}
.card-cols{display:flex;gap:38px;margin-top:44px}
.card-col{flex:none;width:338px}
.card-col:last-child{width:285px}
.sale-list{margin-top:20px;border-top:1px solid rgba(20,22,26,.16)}
.sale-item{padding:18px 0;border-bottom:1px solid rgba(20,22,26,.16)}
.sale-time{font:400 17px/1.2 'IBM Plex Mono',monospace;color:var(--champagne)}
.sale-name{font:400 25px/1.25 'Newsreader',Georgia,serif;margin-top:9px}
.sale-where{margin-top:9px;letter-spacing:.24em}
.card-attire-lab{margin-top:26px}
.card-attire{font:400 14px/1.55 'Newsreader',Georgia,serif;color:rgba(20,22,26,.88);margin-top:11px}
.cond-row{display:flex;gap:14px;margin-top:20px}
.cond-key{
  flex:none;width:48px;
  font:400 10px/1.9 'IBM Plex Mono',monospace;
  letter-spacing:.18em;color:rgba(20,22,26,.5);
}
.cond-val{flex:1;font:400 15px/1.65 'Newsreader',Georgia,serif;color:rgba(20,22,26,.88);text-wrap:pretty}
.cond-rule{height:1px;background:rgba(20,22,26,.1);margin:16px 0}
.cond-para{font:400 15px/1.7 'Newsreader',Georgia,serif;color:rgba(20,22,26,.85);text-wrap:pretty}
.cond-noterow{margin-top:18px}
.cond-note{
  flex:1;
  font:400 9.5px/1.9 'IBM Plex Mono',monospace;
  letter-spacing:.13em;color:rgba(20,22,26,.5);white-space:nowrap;
}
.card-rsvp{
  font:italic 400 22px/1.45 'Newsreader',Georgia,serif;
  color:var(--champagne);
  margin-top:auto;
  max-width:660px;
}
.card-bidder{display:flex;align-items:baseline;gap:20px;width:660px;margin-top:28px}
.card-bidder .mono-label{flex:none;letter-spacing:.3em;color:rgba(20,22,26,.45)}
.bidder-rule{flex:1;height:1px;background:rgba(20,22,26,.3)}

/* ————— Reduced motion: structure kept, camera dropped (JS handles beats) ————— */
@media (prefers-reduced-motion: reduce){
  #film,.cam,#env-card,#flap,#leaf-l,#leaf-r,#bride,#bride-halo,#ring-rot,#card-drop{
    transition-duration:1ms !important;
  }
  .stage [style*="animation"],#tag-btn,#env-wrap,.glint,#grain,#prism.on,#sheen.on i{animation:none !important}
  .glint{opacity:.9;transform:translate(-50%,-50%) scale(.85)}
}
