/* ═══════════════════════════════════════════════════════════════════
   Client reviews — one reel, two shapes.

   Above 1280px the script adds .is-floating and this becomes a fixed
   rail beside the hero, rolling upward. Below that it stays in the
   document as a band under the hero, rolling sideways. There is only
   one of these on the page now; the "What clients said" section is gone.

   Depends on hp-tokens.css for every colour and step.
   ═══════════════════════════════════════════════════════════════════ */


/* The angle the running light is drawn at. Registering it as a typed
   custom property is what makes it animatable — a plain --angle is a
   string and jumps from 0 to 360 in one frame. Unsupported browsers
   simply never animate it and get the static border below. */
@property --hp-tst-angle{
  syntax: '<angle>';
  initial-value: 0deg;
  /* inherits, so ONE animation on the tile drives both the sharp ring
     and the blurred glow behind it. Two separately-animated pseudos
     drift out of phase and the highlight tears in half. */
  inherits: true;
}


/* ── Stars ────────────────────────────────────────────────────────── */
.hp-tst-stars{ display:inline-flex; gap:2px; line-height:0; color:var(--h-gold); }
.hp-tst-stars svg{ display:block; }
.hp-tst-stars .is-off{ opacity:.28; }


/* ── The tile ─────────────────────────────────────────────────────── */
.hp-tst-tile{
  position:relative;
  margin:0;
  display:flex; flex-direction:column; gap:9px;
  padding:14px 16px;
  border-radius:12px;
  background:var(--h-white);

  /* NO BORDER. This is why the light was almost invisible in r45: a 1px
     solid grey border is painted on the element itself, which is ABOVE
     the pseudo-element behind it, so the running highlight was a 1.5px
     sliver peeking out from under a grey line. The ring below is the
     border now.

     The animation lives here rather than on the pseudos so both of them
     read the same angle. */
  border:0;
  animation:hp-tst-light 3.4s linear infinite;
}

/* ── The running light ────────────────────────────────────────────
   A conic gradient rotated behind the tile, showing only in the 1.5px
   the card does not cover. Brand colours in sequence — gold into
   orange into purple — so it reads as one travelling highlight rather
   than a rainbow.

   z-index:-1 puts it behind the tile's own white background but in
   front of the reel, which has none. */
.hp-tst-tile::before{
  content:'';
  position:absolute; inset:-2.5px;
  border-radius:14px;
  z-index:-1;
  /* A tighter, brighter comet than r45's. The band is narrower so it
     reads as one travelling head of light rather than a smear, and it
     runs up to white at the centre — the brand hues alone, at 75%
     opacity, on a white card, were the other half of why this did not
     register. */
  background:conic-gradient(from var(--hp-tst-angle),
      transparent 0 62%,
      var(--h-gold)   71%,
      var(--h-orange) 77%,
      #fff8ee        80%,
      var(--h-orange) 83%,
      var(--h-purple) 88%,
      transparent 95%);
  opacity:1;
}

/* The glow. Same gradient, pushed out and blurred, so the light spills
   onto the navy around the card instead of stopping at its edge. This is
   what makes it read as a light rather than a coloured border. */
.hp-tst-tile::after{
  content:'';
  position:absolute; inset:-9px;
  border-radius:20px;
  z-index:-2;
  background:conic-gradient(from var(--hp-tst-angle),
      transparent 0 62%,
      var(--h-gold)   72%,
      var(--h-orange) 80%,
      var(--h-purple) 88%,
      transparent 95%);
  filter:blur(11px);
  opacity:.62;
  transition:opacity .25s ease;
}
/* Fully lit under the cursor, which is also the tile the reel has
   paused on — so the highlight doubles as "this is the one you stopped". */
.hp-tst-tile:hover::after{ opacity:1; }

@keyframes hp-tst-light{ to{ --hp-tst-angle:360deg; } }

.hp-tst-tile blockquote{
  margin:0;
  font-family:var(--h-font-editorial);
  font-style:italic;
  font-size:.875rem;
  line-height:1.5;
  color:var(--h-ink);
  text-wrap:pretty;
}
.hp-tst-tile figcaption{ display:flex; flex-direction:column; gap:1px; }
.hp-tst-tile figcaption strong{
  font-size:var(--h-step--1); font-weight:600; color:var(--h-navy);
}
.hp-tst-tile figcaption span{ font-size:.6875rem; color:var(--h-muted); }


/* ── The reel ─────────────────────────────────────────────────────
   Two identical sets end to end, translated by exactly one set's
   length. At the end of the cycle the second set sits precisely where
   the first began, so the restart is invisible and the roll is
   continuous rather than a slideshow that steps.

   --reel-shift and --reel-dur are measured and set by the script:
   duration is derived from length so the SPEED is constant whatever
   the reviews happen to measure. */
.hp-tst-reel{
  display:flex;
  gap:12px;
  animation:hp-tst-roll-x var(--reel-dur, 60s) linear infinite;
  will-change:transform;
}
.hp-tst-set{ display:flex; gap:12px; flex-shrink:0; }

@keyframes hp-tst-roll-x{ to{ transform:translate3d(calc(-1 * var(--reel-shift, 2000px)), 0, 0); } }
@keyframes hp-tst-roll-y{ to{ transform:translate3d(0, calc(-1 * var(--reel-shift, 1400px)), 0); } }

/* Stop when someone is reading it — cursor over the panel, or a
   keyboard user tabbing into one of the links. */
.hp-tst-rail:hover .hp-tst-reel,
.hp-tst-rail:focus-within .hp-tst-reel{ animation-play-state:paused; }


/* ── Head: rating, and the two things that qualify it ─────────────── */
.hp-tst-rail-head{ display:flex; flex-direction:column; gap:3px; }
.hp-tst-rail-score{ display:flex; align-items:center; gap:8px; }
.hp-tst-score{
  font-family:var(--h-font-display);
  font-size:1.35rem; line-height:1;
  letter-spacing:var(--h-tracking-tight);
  font-variant-numeric:tabular-nums;
}
.hp-tst-count{ font-size:var(--h-step--1); }
.hp-tst-rail-src{
  align-self:flex-start;
  font-size:.6875rem; line-height:1.45;
  text-decoration:none;
  border-bottom:1px solid currentColor;
}


/* ═══════════════════════════════════════════════════════════════════
   SHAPE 1 — the band, under the hero. Every width by default.
   ═══════════════════════════════════════════════════════════════════ */

.hp-tst-rail{
  display:block;
  background:var(--h-navy);
  color:var(--h-cream);
  padding:18px 0 22px;
  overflow:hidden;
}
.hp-tst-rail .hp-tst-rail-head{
  max-width:1180px; margin:0 auto 14px; padding:0 24px;
}
.hp-tst-rail-src{ color:rgba(240,233,224,.8); }
.hp-tst-rail-src:hover{ color:var(--h-cream); }
.hp-tst-count{ color:rgba(240,233,224,.72); }

.hp-tst-rail-track{
  overflow:hidden;
  /* Fades the tiles out at both ends instead of cutting them, which is
     what makes a strip of cards read as one continuous wheel. */
  -webkit-mask-image:linear-gradient(to right, transparent, #000 4%, #000 96%, transparent);
          mask-image:linear-gradient(to right, transparent, #000 4%, #000 96%, transparent);
}
.hp-tst-rail-track .hp-tst-tile{ width:284px; flex-shrink:0; }


/* ═══════════════════════════════════════════════════════════════════
   SHAPE 2 — the floating rail. Added by the script above 1280px.
   ═══════════════════════════════════════════════════════════════════ */

@media (min-width:1280px){
  .hp-tst-rail.is-floating{
    position:fixed;
    right:clamp(16px, calc((100vw - 1180px) / 2), 40px);
    top:100px;
    width:272px;
    z-index:40;
    display:flex; flex-direction:column; gap:10px;
    background:none; padding:0; overflow:visible;

    opacity:1;
    transition:opacity .35s ease, transform .35s ease;
  }
  /* Off on scroll, as asked. */
  .hp-tst-rail.is-floating.is-gone{
    opacity:0;
    transform:translateX(28px);
    pointer-events:none;
  }

  .hp-tst-rail.is-floating .hp-tst-rail-head{
    max-width:none; margin:0; padding:0;
  }

  .hp-tst-rail.is-floating .hp-tst-rail-track{
    height:var(--tst-track, 344px);
    /* The glow reaches 9px past each tile. Without this the reel's own
       edges shear it off down both sides and the light looks like it is
       switching on and off. */
    padding:0 10px; margin:0 -10px;
    -webkit-mask-image:linear-gradient(to bottom, transparent, #000 9%, #000 91%, transparent);
            mask-image:linear-gradient(to bottom, transparent, #000 9%, #000 91%, transparent);
  }
  .hp-tst-rail.is-floating .hp-tst-rail-track .hp-tst-tile{
    width:auto; flex-shrink:0;
    background:rgba(255,255,255,.97);
    border-color:rgba(255,255,255,.5);
    box-shadow:0 8px 24px rgba(5,13,31,.22);
  }

  .hp-tst-rail.is-floating .hp-tst-reel,
  .hp-tst-rail.is-floating .hp-tst-set{ flex-direction:column; }
  .hp-tst-rail.is-floating .hp-tst-reel{ animation-name:hp-tst-roll-y; }
}

/* The rail stays pinned to the VIEWPORT edge at every width.
 *
 * There used to be a rule here moving it to calc(50% + 614px) past
 * 1800px, on the theory that the container was 1180px wide and its
 * margin could hold the panel. The container is 1460px. That rule put
 * the rail 116px INSIDE the portrait at 2560 and 10px inside it at
 * 1920 — measured, after the portrait grew to 430px.
 *
 * The hero reserves a lane computed from the real container width
 * instead (hp-start.css), which handles every width without the rail
 * needing to move at all. */


/* Nothing rolls, nothing glows, for someone who asked for stillness.
   The reviews are all still there — they just sit still. */
@media (prefers-reduced-motion:reduce){
  .hp-tst-reel{ animation:none; }
  .hp-tst-tile{ animation:none; border:1px solid var(--h-line); }
  .hp-tst-tile::before, .hp-tst-tile::after{ display:none; }
  .hp-tst-rail.is-floating{ transition:none; }
  .hp-tst-rail-track{
    overflow:auto;
    -webkit-mask-image:none; mask-image:none;
  }
}
