/* ⚠️ MEASURED, not guessed: the sticky header renders 89px tall on a
   desktop and 75px on a phone. If the header's padding or type size ever
   changes, THIS IS THE NUMBER THAT HAS TO CHANGE WITH IT — the hero's top
   padding is built on it. */
:root{ --hdr-h:89px; }
@media (max-width:900px){ :root{ --hdr-h:75px; } }

/* =========================================================
   Cinema Skin FX — step 1, the RDR feature hero
   Its own file for the same reason titlecard.css is: it is a
   full composition, not a handful of component rules. Loads
   after atmosphere.css so the hero's own ground wins.
   ========================================================= */

.hero{
  position:relative;
  /* ⚠️ THE TOP PADDING HAS A FLOOR, AND THE FLOOR IS THE HEADER. The header
     is sticky and floats OVER this section rather than pushing it down, so a
     purely viewport-relative padding does not clear it — measured, the
     "Recommended by Boss RDR" badge sat 10 to 28px behind the header at six
     of the eight sizes tested, phones included. --hdr-h is the header's real
     measured height; +16px is the breathing room.

     ⚠️ THE BOTTOM VALUE CARRIES --lift-rise, AND IT IS NOT SPARE SPACE. It
     is what #about takes back: #about sets margin-top:-var(--lift-rise) and
     climbs over whatever precedes it. Adding the same number here means the
     clearance actually left is this section's plain padding-bottom — 30px on
     a phone, 48 at 1440 — rather than a difference between two tuned numbers.

     This reservation used to be spent as the bottom margin of .hero-facts,
     the fact bar that closed the hero. The bar was removed on request. With
     nothing holding the room open the clearance measured -16px at 1440 and
     0px at 390: #about sat on the hero's own content. --lift-rise is declared
     on :root in styles.css — change it there. */
  padding:max(clamp(40px,5vw,72px), calc(var(--hdr-h) + 16px)) 0
          calc(clamp(30px,3.6vw,48px) + var(--lift-rise));
  overflow:hidden;
  /* Backstop under the silk, in the same key. Only shows if .hero-silk is
     ever removed — the silk covers it. */
  background:linear-gradient(158deg, #FBFCFC 0%, #EEF3F4 46%, #FCFCFB 100%);
}

/* ---- THE HERO AS ITS OWN SCREEN ----
   Asked for as "make this part as a page": land on it and it fills the
   window, rather than stopping short with the next section already showing.

   ⚠️ min-height, NOT height, and the difference is the whole rule. Measured,
     the content needs:

       1900x1080   864px in 1080   216 spare
       1440x 900   862px in  900    38 spare
       1366x 768   851px in  768    83 SHORT
       1280x 720   835px in  720   115 SHORT
        390x 664  1459px in  664   2.3 screens

     A fixed height on a 1366x768 laptop does not make a page, it hides the
     bottom of one. A minimum can only grow the section into room that is
     already going spare.

   ⚠️ AND THE CENTRING IS GATED, because that is the half that can lose
     content. justify-content:center shares out the spare room — and when
     the room is negative it shares out the deficit too, lifting the headline
     up under the sticky header and off the top of the screen. 940px is taken
     from the table above: the content never needs more than ~864px at any
     desktop width, so inside the gate there is always something to share and
     never anything to lose. Below it, nothing here applies and the hero is
     exactly what it was.

   ⚠️ 104px OF TOP PADDING, because the site header is 89px, sticky, and
     floats over this section rather than pushing it down. Centred content on
     a 940px screen would otherwise sit 38px from the top — underneath it. */
@media (min-width:1100px) and (min-height:940px){
  .hero{
    min-height:100svh;
    display:flex;
    flex-direction:column;
    justify-content:center;
    padding-top:max(clamp(40px,5vw,72px), 104px);
  }
}

/* =========================================================
   The scene — silk, the same idea as the interview section

   `.story-silk` and this are built the same way: light pooling into two
   corners, with folds running across. What differs is the key. The
   interview is warm ivory; the hero is a cool pearl, so the two sections
   read as a pair rather than as the same picture twice.

   The folds are two repeating gradients at different angles AND different
   periods (238px against 356px), so they beat against each other instead of
   falling into a visible stripe. Matching periods would turn it into
   wallpaper.
   ========================================================= */
.hero-scene{
  position:absolute;inset:0;
  z-index:0;
  pointer-events:none;
  overflow:hidden;
}
.hero-silk{
  position:absolute;inset:0;
  background:
    radial-gradient(52% 46% at 14% 8%,  rgba(255,254,250,.96) 0%, rgba(255,254,250,0) 62%),
    radial-gradient(46% 44% at 88% 82%, rgba(246,250,251,.92) 0%, rgba(246,250,251,0) 66%),
    repeating-linear-gradient(107deg,
      rgba(176,197,206,0)   0px,
      rgba(176,197,206,.09) 70px,
      rgba(255,255,255,.44) 142px,
      rgba(176,197,206,0)   238px),
    repeating-linear-gradient(66deg,
      rgba(176,197,206,0)   0px,
      rgba(176,197,206,.05) 116px,
      rgba(255,255,255,.22) 206px,
      rgba(176,197,206,0)   356px),
    linear-gradient(158deg, #FDFDFC 0%, #F1F6F6 46%, #FDFCFA 100%);
}

/* Seafoam bloom trailing the pointer.

   The champagne spotlight on [data-spotlight]::before is already eased in
   main.js; this one reads the same --mx/--my through its own --ax/--ay,
   which are @property-registered and therefore transitionable. Two glows
   arriving a beat apart give the light depth — one hue leading, a cooler
   one catching up. Registered as <length-percentage> so a browser without
   the transition still tracks the pointer, just without the lag. */
@property --ax{ syntax:"<length-percentage>"; inherits:false; initial-value:50%; }
@property --ay{ syntax:"<length-percentage>"; inherits:false; initial-value:50%; }
.hs-aura{
  position:absolute;inset:0;
  --ax:var(--mx,50%);
  --ay:var(--my,50%);
  opacity:0;
  background:
    radial-gradient(26vw 26vw at var(--ax) var(--ay), rgba(250,238,200,.34) 0%, rgba(250,238,200,0) 68%),
    radial-gradient(11vw 11vw at var(--ax) var(--ay), rgba(198,164,85,.14) 0%, rgba(198,164,85,0) 72%);
  transition:
    --ax .85s var(--ease-soft),
    --ay .85s var(--ease-soft),
    opacity .7s var(--ease-soft);
}
.hero.is-lit .hs-aura{opacity:1;}

/* =========================================================
   Layout
   ========================================================= */
.hero-grid{
  position:relative;
  z-index:1;
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.06fr);
  gap:clamp(26px,3.6vw,60px);
  align-items:center;
}

/* Badge */
.hero-badge{
  display:inline-flex;align-items:center;gap:10px;
  padding:8px 20px 8px 9px;
  margin-bottom:24px;
  border-radius:var(--r-pill);
  background:rgba(255,253,247,.72);
  border:1.5px solid var(--gold);
  font-size:11px;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;
  color:var(--gold-ink);
}
.hero-badge strong{font-weight:800;color:#6E5514;}
.hb-star{
  display:grid;place-items:center;
  width:24px;height:24px;flex:none;
  border-radius:50%;
  background:linear-gradient(135deg,#DCC486,var(--gold));
  box-shadow:0 4px 10px -4px rgba(160,124,40,.8);
}
.hb-star svg{width:13px;height:13px;fill:#fff;}

.hero-title{
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(34px,4.4vw,58px);
  line-height:1.08;
  letter-spacing:-.02em;
  margin-bottom:16px;
}
.hero-rule{
  display:block;
  width:110px;height:4px;
  margin:0 0 22px;
  border-radius:2px;
  background:linear-gradient(90deg, var(--gold) 0%, var(--gold-soft) 62%, rgba(233,220,180,0) 100%);
}
.hero-sub{
  font-size:clamp(14px,1.05vw,15.5px);
  font-weight:400;
  line-height:1.75;
  color:var(--ink-2);
  max-width:46ch;
  margin-bottom:26px;
}

/* Three claim cards */
.hero-stats{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:12px;
  margin-bottom:28px;
}
.hstat{
  position:relative;
  padding:16px 14px 15px;
  border-radius:var(--r-md);
  background:rgba(255,253,248,.82);
  border:1px solid rgba(233,220,180,.9);
  box-shadow:0 10px 26px -20px rgba(120,96,44,.5);
  overflow:hidden;
  /* ⚠️ SAME FAULT AS .vidcard, TWO ELEMENTS AWAY — see the long note there.
     This shorthand was replacing the reveal's transition on every claim card,
     so the cards arrived opaque and sharp on frame one and their 3/4/5 stagger
     was reset to 0s. It was found by the same reading: computed
     transition-property said "transform, box-shadow, border-color" where the
     headline beside it said "opacity, transform, filter".
     Delays are paired per property so :hover stays immediate. */
  transition:
    transform .4s var(--ease),
    box-shadow .4s var(--ease),
    border-color .4s var(--ease),
    opacity .95s var(--ease-out),
    filter .8s var(--ease-out);
  transition-delay:0s, 0s, 0s,
    calc(var(--d,0) * 95ms), calc(var(--d,0) * 95ms);
}
.hstat::after{           /* gold sheen that wipes across on hover */
  content:"";
  position:absolute;inset:0;
  background:linear-gradient(104deg, rgba(255,255,255,0) 36%, rgba(255,255,255,.85) 50%, rgba(255,255,255,0) 64%);
  background-size:260% 100%;
  background-position:180% 0;
  opacity:0;
  transition:background-position .7s var(--ease), opacity .3s var(--ease);
}
.hstat:hover{
  transform:translateY(-5px);
  border-color:var(--gold);
  box-shadow:0 20px 38px -22px rgba(120,96,44,.62);
}
.hstat:hover::after{opacity:1;background-position:-80% 0;}
.hstat-ico{display:block;margin-bottom:11px;}
.hstat-ico svg{
  width:22px;height:22px;
  fill:none;stroke:var(--gold-accent);stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;
  transition:transform .45s var(--ease-back), stroke .3s var(--ease);
}
.hstat:hover .hstat-ico svg{transform:translateY(-2px) scale(1.12);stroke:var(--gold-ink);}
.hstat-val{
  font-size:12px;font-weight:700;
  letter-spacing:.05em;text-transform:uppercase;
  line-height:1.35;
  color:var(--gold-ink);
  margin-bottom:5px;
}
.hstat-cap{
  font-size:11.5px;font-weight:400;line-height:1.45;
  color:var(--ink-3);
}

.hero-cta{display:flex;flex-wrap:wrap;gap:12px;}
/* Asked to come down a little. Was 16px/30px at 14.5px, which rendered a
   57.9px button — the pair of them were the heaviest thing left in the hero's
   column once the fact bar came out from under them.
   ⚠️ The floor is the touch target, not the look. 44px is what every touch
   guideline asks for, and the phone override further down is the one that can
   breach it, so both were measured rather than eyeballed. */
.hero-cta .btn{padding:13px 26px;font-size:13.5px;font-weight:600;}
/* The outlined twin of .btn-gold */
.btn-outline-gold{
  background:rgba(255,253,247,.6);
  border:1.5px solid var(--gold);
  color:var(--gold-ink);
}
.btn-outline-gold:hover{background:var(--gold-tint);border-color:var(--gold-accent);}

/* =========================================================
   The vlog card
   ========================================================= */
.hero-right{display:flex;flex-direction:column;gap:14px;}
.vidcard{
  position:relative;
  /* ⚠️ The card owns its own 16:9, not whichever child happens to be in it.
     It used to take its height from .vid-link, which main.js REPLACES with the
     iframe — so the box was defined by one element before the swap and a
     different one after, and any disagreement between the two showed as a
     sliver of card background along an edge. One box, set once, either way. */
  aspect-ratio:16/9;
  border-radius:var(--r-lg);
  overflow:hidden;
  background:#EFE6D6;
  box-shadow:
    0 44px 80px -40px rgba(120,96,44,.55),
    0 4px 14px -8px rgba(120,96,44,.3);
  /* ⚠️ opacity AND filter ARE IN THIS LIST BECAUSE THE REVEAL OWNS THEM, AND
     THEY WERE MISSING. This is the third time this exact trap has been paid
     for on this page, and interactive.css documents the first two at length:
     `transition` is a shorthand, it resets every longhand it covers, and this
     file loads AFTER interactive.css at the same (0,1,0) specificity. So this
     one line was silently replacing the reveal's entire transition —
     [data-reveal] sets opacity:0 and filter:blur(6px), .is-in sets them back,
     and on this element NEITHER was being animated. The card slid up over
     .5s while arriving already opaque and already sharp on frame one. Its
     190ms stagger was reset to 0s in the same stroke.

     Found by reading the COMPUTED transition-property, which said
     "transform, box-shadow" where every sibling said "opacity, transform,
     filter". The rule looked right in isolation; only the element disagreed.

     ⚠️ FOUR PROPERTIES, FOUR DELAYS, AND THE PAIRING MATTERS. A single
       transition-delay would apply to all four and make the hover lift wait
       out the entrance stagger every time the pointer arrives. Only the two
       the reveal owns are delayed; transform and box-shadow stay immediate
       because they belong to :hover. transform is genuinely shared, and it is
       left on the hover's timing deliberately — a hover repeats, an entrance
       happens once.

     ⚠️ AND IT STAYS BELOW THE SHORTHAND. Same reason as the note in
       interactive.css: if the list above is ever edited, this line moves with
       it, never above it. */
  transition:
    transform .5s var(--ease),
    box-shadow .5s var(--ease),
    opacity .95s var(--ease-out),
    filter .8s var(--ease-out);
  transition-delay:0s, 0s,
    calc(var(--d,0) * 95ms), calc(var(--d,0) * 95ms);
}
.vidcard:hover{
  transform:translateY(-4px);
  box-shadow:
    0 56px 96px -40px rgba(120,96,44,.62),
    0 6px 18px -8px rgba(120,96,44,.34);
}
.vid-link{
  position:relative;
  display:block;
  aspect-ratio:16/9;
  overflow:hidden;
}

/* The stand-in poster: a flat-lay built from the product symbols.
   Hidden the moment a real assets/img/rdr-vlog.jpg loads. */
.vid-stage{position:absolute;inset:0;overflow:hidden;}
.vs-ground{
  position:absolute;inset:0;
  background:
    radial-gradient(52% 60% at 34% 26%, rgba(255,250,240,.95) 0%, rgba(255,250,240,0) 64%),
    linear-gradient(168deg, #E8D9C2 0%, #D8C4A6 52%, #C9B291 100%);
}
.vs-mirror{
  position:absolute;top:6%;left:6%;
  width:26%;aspect-ratio:1;border-radius:50%;
  background:radial-gradient(circle at 38% 32%, rgba(255,255,255,.9) 0%, rgba(228,214,190,.6) 58%, rgba(198,176,142,.5) 100%);
  box-shadow:inset 0 0 0 4px rgba(214,186,132,.7), 0 14px 26px -14px rgba(90,70,36,.6);
}
.vs-p{
  position:absolute;bottom:12%;
  filter:drop-shadow(0 18px 22px rgba(90,70,36,.42));
}
.vs-p1{left:9%;  width:14%; bottom:16%;}
.vs-p3{left:35%; width:17%; bottom:9%;  z-index:2;}
.vs-puff{
  position:absolute;right:5%;bottom:10%;
  width:15%;aspect-ratio:1;border-radius:50%;
  background:radial-gradient(circle at 36% 30%, #FFFDF8 0%, #F0E4D0 62%, #DDCBB0 100%);
  box-shadow:0 16px 24px -14px rgba(90,70,36,.6);
}
/* A real poster covers the stand-in entirely */
.vid-poster{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;
}
.vid-poster.is-missing{display:none;}
.vid-poster:not(.is-missing) ~ .vid-stage,
.vid-stage:has(+ .vid-poster:not(.is-missing)){display:none;}

/* Sized for a real thumbnail, which can be bright and busy behind the
   caption — the vector stand-in would need far less. */
.vid-scrim{
  position:absolute;inset:0;
  background:
    linear-gradient(180deg, rgba(28,20,8,.72) 0%, rgba(28,20,8,.34) 22%, rgba(28,20,8,0) 42%),
    linear-gradient(0deg, rgba(28,20,8,.66) 0%, rgba(28,20,8,0) 30%);
}

/* Play button */
.vid-btn{
  position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%);
  display:grid;place-items:center;
  width:clamp(64px,6.4vw,96px);aspect-ratio:1;
  border-radius:50%;
  background:rgba(255,253,248,.94);
  box-shadow:0 18px 40px -14px rgba(60,44,16,.7);
  transition:transform .45s var(--ease-back), background-color .3s var(--ease);
}
.vid-btn svg{width:34%;height:34%;fill:var(--gold-accent);margin-left:8%;}
.vid-btn::before{
  content:"";
  position:absolute;inset:-12px;
  border-radius:50%;
  border:1.5px solid rgba(255,253,248,.7);
  animation:vidPulse 2.8s var(--ease-soft) infinite;
}
@keyframes vidPulse{
  0%  {transform:scale(.88);opacity:.85;}
  70% {transform:scale(1.26);opacity:0;}
  100%{transform:scale(1.26);opacity:0;}
}
.vid-link:hover .vid-btn,
.vid-link:focus-visible .vid-btn{transform:translate(-50%,-50%) scale(1.1);background:#fff;}

/* The still and its play button are the fallback — reduced motion, or no
   JavaScript. The moment the player lands they go. */
.vidcard.is-playing .vid-scrim,
.vidcard.is-playing .vid-btn{display:none;}

/* =========================================================
   THE CARD ONCE IT IS PLAYING

   main.js no longer replaces the link with the player; it inserts the player
   BEHIND the link. Everything here is what turns the leftover facade into
   the card's own interactive surface.

   ⚠️ THIS IS WHAT KEEPS YOUTUBE'S CHROME AWAY, NOT THE URL PARAMETERS.
     controls=0 removes the transport, but the title strip and channel line
     have no flag — they appear on pause and on pointer contact. A surface
     over the player means the player never receives either, so they have
     nothing to appear for. The parameters and this rule are two halves of
     one answer; removing either brings the furniture back.
   ========================================================= */
.vidcard.is-playing .vid-stage,
.vidcard.is-playing .vid-poster{display:none;}

.vidcard.is-playing .vid-link{
  position:absolute;
  inset:0;
  z-index:2;
  /* ⚠️ the facade sized ITSELF 16:9; stretched over a card that already is
     16:9, a second ratio can only disagree with the first */
  aspect-ratio:auto;
  /* ⚠️ display:grid, align-content:end, justify-items:end and a padding sat
     here to place the cue pill in the bottom-right corner. The pill is gone,
     so they are too — an empty grid parked at the bottom of a box with
     nothing in it is a layout waiting to surprise whoever adds the next
     child. The link is a bare cover now, which is all it has to be. */
  /* a gold ring that closes as a pointer arrives — the card answering, rather
     than the player answering for it */
  box-shadow:inset 0 0 0 0 rgba(198,164,85,0);
  transition:box-shadow .38s var(--ease);
}
.vidcard.is-playing .vid-link:hover,
.vidcard.is-playing .vid-link:focus-visible{
  box-shadow:inset 0 0 0 2px rgba(198,164,85,.85);
}

/* ⚠️ THE "WATCH ON YOUTUBE" CUE WAS HERE AND WAS REMOVED ON REQUEST.
   It was a pill in the bottom-right corner naming what the surface does.
   Taken out, the surface itself is unchanged: the link still covers the
   player, so YouTube's chrome is still unreachable and the card still opens
   the video. What is gone is the only VISIBLE sign that it does — the ring
   and the press below answer a pointer, and a phone has neither hover nor
   focus-visible, so on touch the card now looks inert until it is tapped.
   That is the trade, and it was asked for knowingly.

   If it ever comes back, it belongs here rather than in the markup: the
   link carries aria-label already, so a generated label adds nothing to the
   accessibility tree and removing it takes nothing away either. */
/* pressed — the card dips under the finger and returns */
.vidcard.is-playing .vid-link:active{translate:0 1px;}

@media (prefers-reduced-motion:reduce){
  .vidcard.is-playing .vid-link{transition:none;}
}
/* ⚠️ inset:-1px, and the reason is sub-pixel. The card is a fraction of a
   pixel wide at most widths (581.00 x 326.81 at 1440), and an iframe laid out
   to exactly 100% of a fractional box can round a hair short — which paints a
   one-pixel line of whatever is behind it down an edge. A pixel of overhang
   costs nothing (overflow:hidden clips it) and makes that impossible.

   The iframe is absolutely positioned so it fills the card's own box rather
   than deriving a second one from its own aspect-ratio. Two independent 16:9
   boxes that must agree is one box too many. */
.vidcard iframe{
  position:absolute;
  inset:-1px;
  display:block;
  width:calc(100% + 2px);
  height:calc(100% + 2px);
  border:0;
}

/* Endorsement strip */
/* ⚠️ IT WAS A FULL-WIDTH PILL AND THAT IS WHY IT READ AS TOO BIG.
   As a <p> in a one-column .hero-right it stretched the whole width, and
   its own content is nowhere near that wide — so on a phone it was a large
   near-white lozenge with two short lines of type floating in it and
   13px/22px of padding holding the rest open. Three things were wrong and
   only one of them was the padding:

     width      block-level by default; now it shrinks to its content, so
                the strip is the length of what it says
     wrapping   flex-wrap:wrap let "Recommended by Boss RDR." drop to a
                second line, which doubled the height of the lozenge. It is
                one line or it is nothing.
     colour     rgba(255,253,248,.86) on the hero's own pearl is very nearly
                the ground it sits on, so all the size was doing no work.
                Asked for colour: a gold wash entering from the star side,
                a gold rule down the left, and a real gold border.

   ⚠️ THE GOLD IS A WASH UNDER THE TYPE, NOT THE TYPE ITSELF. BRAND.md is
     explicit that small gold type on white is out, and --gold-accent tops
     out at 2.95:1 page-wide. The label stays --ink on a tinted ground; the
     gold carries the border, the rule and the star only. Measured after. */
.hero-endorse{
  position:relative;
  display:flex;align-items:center;flex-wrap:nowrap;gap:8px;
  width:fit-content;
  max-width:100%;
  /* ⚠️ the right padding clears the end rule, it is not symmetry. At 16px the
     rule sat ~5px from the last letter and read as a stray pipe character
     rather than as a terminator — visible only once the phone copy shortened
     to "FEATURED IN RDR VLOG". Rule at 9px, text stopping at 22px, 13px of
     air between them. */
  padding:8px 22px 8px 8px;
  border-radius:var(--r-pill);
  background:linear-gradient(100deg,
    rgba(198,164,85,.20) 0%,
    rgba(244,232,203,.55) 34%,
    rgba(255,253,248,.92) 74%);
  border:1px solid rgba(198,164,85,.46);
  box-shadow:0 8px 20px -18px rgba(120,96,44,.55);
  font-size:11.5px;color:var(--ink-2);
}
/* a gold rule closing the open end, so the wash reads as deliberate rather
   than as a gradient that ran out */
.hero-endorse::after{
  content:"";
  position:absolute;
  right:9px;top:26%;bottom:26%;
  width:2px;border-radius:2px;
  background:linear-gradient(180deg, rgba(198,164,85,0), var(--gold), rgba(198,164,85,0));
}
.hero-endorse strong{
  font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  font-size:10.5px;color:var(--ink);white-space:nowrap;
}
.hero-endorse em{font-style:normal;color:var(--ink-2);}
.he-dash{color:var(--taupe);}
.hero-endorse em{white-space:nowrap;}
.he-star{
  display:grid;place-items:center;
  width:22px;height:22px;flex:none;
  border-radius:50%;
  background:linear-gradient(135deg,#DCC486,var(--gold));
  box-shadow:0 4px 10px -5px rgba(160,124,40,.8);
}
.he-star svg{width:13px;height:13px;fill:#fff;}


/* =========================================================
   Responsive
   ========================================================= */
@media (max-width:1024px){
  .hero-grid{grid-template-columns:1fr;}
  .hero-copy{max-width:640px;}
  /* ⚠️ min-width:0 OR A nowrap CHILD SETS THIS COLUMN'S WIDTH. Stacked, the
     column is `1fr`, which is minmax(AUTO,1fr) — and an auto minimum is
     min-content, so it cannot shrink below the widest unbreakable thing
     inside it. The endorsement strip is white-space:nowrap, and it pushed
     this column to 343.1px inside a 280px shell at 320. Nothing scrolled
     sideways, because .hero is overflow:hidden — it was simply CLIPPED, which
     is the worse failure of the two because it leaves no trace. */
  .hero-right{width:100%;max-width:640px;min-width:0;}

  /* ⚠️ THE VIDEO LEADS THE MOMENT THE GRID STACKS, AND ONLY THEN.
     Asked for: the player first, the "Featured in RDR Vlog" line with it, and
     both above the "Recommended by Boss RDR" badge. Both already live together
     in .hero-right, so this is one declaration rather than a markup move — and
     a markup move would have been wrong, because side by side at 1025px and up
     the copy still has to lead the video. The condition is not "a phone", it
     is "there is only one column", which is exactly this breakpoint. */
  .hero-right{order:-1;}

  /* ⚠️ THE SECOND HALF OF THE STRIP IS DROPPED HERE, AND IT IS A DUPLICATE,
     NOT A CASUALTY. The strip reads "Featured in RDR Vlog — Recommended by
     Boss RDR." and .hero-badge, which in this layout sits about 100px
     directly beneath it, reads "Recommended by Boss RDR". The same seven
     words twice, one under the other.

     The em earns its place at 1025px and up, where the badge is in the other
     column and nowhere near it — which is why this is here and not in the
     base rule. The condition is the same one that reordered the halves:
     one column means the two are adjacent.

     It is also what makes the strip fit. nowrap + fit-content leaves a phone
     no way to escape a too-long line except to be clipped; 343.1px of
     content does not go into 280px of shell at 320, and no amount of type
     shrinking makes it while the sentence is doubled. */
  .hero-endorse em,
  .hero-endorse .he-dash{display:none;}

  /* ⚠️ ORDER MOVES THE BOXES, NOT THE STAGGER — AND THE STAGGER IS THE POINT.
     Every [data-reveal] waits `--d * 95ms`, and --d comes from a
     data-reveal-delay attribute written for the DESKTOP order: the badge is 0
     and the player is 2. Reversed on screen and not in time, the hero lands
     backwards — the badge appears, then the title, and only then the largest
     object on screen, sitting above both. Measured 190ms late.

     The attributes cannot be re-written, because at 1025px and up they are
     correct. So the two halves are re-based here instead, which is two
     declarations rather than eight overrides: the player's half counts from
     two earlier, the copy's half from two later, and every existing rhythm
     inside each half survives untouched.

     ⚠️ SPECIFICITY, NOT SOURCE ORDER, IS WHY THESE LAND. interactive.css sets
       the delay on [data-reveal] at (0,1,0) and .hstat re-declares the
       `transition` SHORTHAND at (0,1,0) in this very file — which resets
       transition-delay to 0s, the trap interactive.css documents at length.
       These selectors are (0,2,0) and beat both. */
  .hero-right [data-reveal]{transition-delay:calc((var(--d,0) - 2) * 95ms);}
  /* ⚠️ .vidcard carries FOUR transitions, so it needs four delays here too —
     a single value would re-delay the hover lift that the base rule just took
     care to keep immediate. */
  .hero-right .vidcard{
    transition-delay:0s, 0s,
      calc((var(--d,0) - 2) * 95ms), calc((var(--d,0) - 2) * 95ms);
  }
  .hero-copy  [data-reveal]{transition-delay:calc((var(--d,0) + 2) * 95ms);}
  /* ⚠️ and .hstat carries FIVE, for the same reason .vidcard carries four */
  .hero-copy .hstat{
    transition-delay:0s, 0s, 0s,
      calc((var(--d,0) + 2) * 95ms), calc((var(--d,0) + 2) * 95ms);
  }
  .hero-copy[data-reveal],
  .hero-badge{transition-delay:calc((var(--d,0) + 2) * 95ms);}
}
@media (max-width:720px){
  .hero-title{font-size:clamp(30px,8vw,40px);}
  .hero-cta .btn{flex:1 1 auto;justify-content:center;padding:12px 18px;}
  .hero-stats{gap:10px;}
  /* ⚠️ nowrap plus fit-content means a phone can only shrink the TYPE — the
     strip has no second line to escape into. Measured at 430/390/375/360/320
     to confirm it still fits the shell without clipping its own end. */
  .hero-endorse{font-size:10.5px;padding:7px 20px 7px 7px;gap:7px;}
  .hero-endorse strong{font-size:9.5px;letter-spacing:.07em;}
  .he-star{width:19px;height:19px;}
  .he-star svg{width:11px;height:11px;}
}
@media (max-width:560px){
  /* ⚠️ TWO ACROSS, NOT ONE, AND THE THIRD SPANS. Asked for against a reference
     whose claim cards are a GRID on a phone rather than a stack. Ours is three
     cards where the reference has four, so the question is not only "two
     columns" but what the odd one does. Three answers were possible:

       three across   at 320 that is a 87px column carrying "100% Recommended"
                      in 12px uppercase with .05em tracking — the trust band
                      can do three across because its type is display-sized and
                      centred; these are boxed labels with 14px of padding
                      either side, and they are not the same problem
       2 + a hole     the third card in column 1 and nothing beside it reads as
                      a missing fourth card, not as a deliberate three
       2 + a full one what is here: the odd card takes the whole width, so the
                      block ends on a line instead of on a gap

     Stacked, the three cards were 331.6px of hero on every phone width. Two
     across costs one row instead of three. */
  .hero-stats{
    grid-template-columns:repeat(3,minmax(0,1fr));
    gap:clamp(5px,1.8vw,10px);
  }
  /* ⚠️ THREE ACROSS MEANS THE TYPE HAS TO CHANGE, NOT JUST THE GRID.
     The blocker was never the column count, it was 12px UPPERCASE with .05em
     tracking inside a box with padding either side. "100% RECOMMENDED" is the
     widest string on the page per available pixel, and "RECOMMENDED" alone is
     11 characters that cannot be broken. At 320 a third of the block minus the
     gaps minus the padding is about 73px of usable width, and 11 uppercase
     characters at 12px with tracking want roughly 90px — so at the old size
     the word does not wrap, it OVERFLOWS, which is the one failure mode a
     narrower column cannot fix by itself.

     So the card is restyled to the same logic as the trust band it now
     matches: centred, tighter padding, smaller mark, and a value that scales
     with the viewport instead of sitting at a fixed 12px. The tracking drops
     from .05em to .02em, which is worth about 5px on that word on its own.

     ⚠️ THE SIZES ARE FLOORS, NOT GUESSES. The lower end of each clamp is the
       size at which the longest unbreakable word still fits the narrowest
       column, measured rather than chosen — see the README table. Raising any
       of them without re-measuring at 320 will overflow "RECOMMENDED". */
  .hstat{
    padding:clamp(10px,3vw,14px) clamp(5px,1.7vw,10px) clamp(9px,2.6vw,12px);
    text-align:center;
  }
  /* ⚠️ the svg is display:block, so text-align:center does not reach it —
     it needs a centring container of its own */
  .hstat-ico{display:grid;justify-items:center;margin-bottom:clamp(6px,1.8vw,8px);}
  .hstat-ico svg{width:clamp(17px,5vw,20px);height:clamp(17px,5vw,20px);}
  .hstat-val{
    font-size:clamp(9px,2.75vw,11.5px);
    letter-spacing:.02em;
    line-height:1.3;
    margin-bottom:3px;
  }
  .hstat-cap{font-size:clamp(9.5px,2.6vw,11px);line-height:1.35;}

}

/* Motion off — the ground stays, it just stops moving */
@media (prefers-reduced-motion:reduce){
  .vid-btn::before{animation:none !important;}
  .hstat::after{display:none;}
}

/* Badge: a slow catch-light travelling across the pill */
.hero-badge{position:relative;overflow:hidden;}
.hero-badge::after{
  content:"";
  position:absolute;inset:0;
  background:linear-gradient(104deg,
    rgba(255,255,255,0) 38%, rgba(255,255,255,.75) 50%, rgba(255,255,255,0) 62%);
  background-size:250% 100%;
  animation:hsBadge 7s linear infinite;
  pointer-events:none;
}
@keyframes hsBadge{ 0%{background-position:180% 0;} 55%,100%{background-position:-90% 0;} }

/* The card tilts under the pointer via the shared [data-tilt] handler, which
   writes an inline transform — so the lift lives on the shadow only, or the
   two would fight over the same property. */
.vidcard:hover{transform:none;}
.vidcard[data-tilt]{transform-style:preserve-3d;}

/* A light runs the card's rim while it waits to be played */
.vidcard::after{
  content:"";
  position:absolute;inset:0;
  z-index:3;
  pointer-events:none;
  border-radius:inherit;
  padding:1.5px;
  background:linear-gradient(var(--rim-angle,0deg),
    rgba(250,238,200,0) 30%, rgba(250,238,200,.95) 50%, rgba(250,238,200,0) 70%);
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
          mask-composite:exclude;
  animation:hsRim 6s linear infinite;
}
@property --rim-angle{ syntax:"<angle>"; inherits:false; initial-value:0deg; }
@keyframes hsRim{ to{ --rim-angle:360deg; } }
.vidcard.is-playing::after{display:none;}

@media (prefers-reduced-motion:reduce){
  .hero-badge::after,
  .vidcard::after{display:none;}
}

/* The field. Canvas, drawn in main.js — motes that drift on the silk and
   bond to each other only where the pointer is. Last child of .hero-scene.
   Its box is what main.js measures, so it has to fill the scene exactly. */
.hero-field{
  position:absolute;inset:0;
  display:block;
  width:100%;height:100%;
}
