/* ============================================================
   CLIENT FLAGS
   ------------------------------------------------------------
   The flag beside a client's name, and the wave on it.

   Not emoji. Windows has no colour glyphs for the regional
   indicator pairs, so U+1F1EE U+1F1F9 renders as the letters
   "IT" on most Windows browsers — which is where this site is
   being reviewed. Inline SVG draws the same shapes everywhere
   with no font dependency.

   The wave is three things at once, because any one of them
   alone reads as static at this size. The first attempt was a
   1.6deg shear and a soft travelling gradient: about 0.4px of
   movement at the trailing edge, which looked painted on.

   1. An feDisplacementMap driven by animated feTurbulence
      (#flag-wave in index.html), so the bands themselves deform
      rather than the rectangle shearing as one rigid piece.
   2. A CSS shear and bob, which is what carries the motion if
      SMIL is ever unavailable - the filter would then hold a
      static displacement, still cloth-like.
   3. Travelling fold shading, now at contrast you can see.

   Only the visible review animates. .sc-review:not(.is-active)
   is visibility:hidden, and an animation under a hidden element
   still burns frames, so the keyframes are scoped to the active
   card.
   ============================================================ */

.client-flag {
  position: relative;
  display: inline-block;
  width: 22px;
  height: 15px;
  flex: 0 0 auto;
  border-radius: 2px;
  /* No overflow:hidden and no hard 1px ring. The displacement map moves the
     silhouette by up to ~1.6px, so a clip and an outline would hold a crisp
     rectangle around cloth that is visibly moving inside it - the flag would
     read as coming loose from its own frame. The 7px gap before the name gives
     the crests room to spill. */
  /* Sits on the cap height of the name beside it rather than the
     baseline, which is what stops it reading as a dropped box. */
  vertical-align: -2px;
  filter: drop-shadow(0 1px 1px rgb(8 14 26 / .5));
  transform-origin: 0% 50%;
}

/* The flag is a <span> wrapping an <svg>, not a bare <svg>. Pseudo-elements do
   not render on SVG elements, so with the class on the svg the fold overlay on
   ::after painted nothing and this rule matched nothing either - which left the
   shear as the only live layer, at 0.4px. */
.client-flag svg {
  display: block;
  width: 100%;
  height: 100%;
  filter: url(#flag-wave);
}

/* The folds: two soft light bands and two shadows, twice the width of the
   flag so the pattern can travel a full period without repeating visibly. */
.client-flag::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(
    100deg,
    rgb(255 255 255 / 0) 0%,
    rgb(255 255 255 / .58) 13%,
    rgb(6 12 24 / .42) 29%,
    rgb(255 255 255 / 0) 45%,
    rgb(255 255 255 / .5) 61%,
    rgb(6 12 24 / .44) 77%,
    rgb(255 255 255 / 0) 100%
  );
  background-size: 220% 100%;
  background-position: 0% 0;
  pointer-events: none;
}

/* Pinned at the hoist and free at the fly, which is why transform-origin is on
   the left edge: the shear, the squeeze and the bob all grow toward the right.
   4.5deg over 22px is about 1.7px at the trailing edge, four times the first
   attempt, and the phases are offset so it never passes through a flat frame
   with everything at rest. */
/* One continuous cycle, sampled every eighth of the period so linear
   interpolation traces a sine rather than a zig-zag.

   The timing function below is linear, and that is the whole point. A CSS
   timing function applies between *every pair of keyframes*, not once across
   the animation — so `ease-in-out` on six keyframes was five separate
   ease-in-outs per lap, decelerating the cloth to a standstill five times a
   cycle. That reads exactly as a flag that stops and starts again instead of
   one that is being blown.

   The samples are also symmetric now. The previous set went -4.5, -1, +4.5,
   +1, which leaned the wave to one side and made the return stroke faster
   than the outbound one. */
@keyframes client-flag-wave {
  0%    { transform: skewY(0deg)    scaleY(1)    translateY(0); }
  12.5% { transform: skewY(-3.2deg) scaleY(.958) translateY(-.35px); }
  25%   { transform: skewY(-4.5deg) scaleY(.94)  translateY(-.5px); }
  37.5% { transform: skewY(-3.2deg) scaleY(.958) translateY(-.35px); }
  50%   { transform: skewY(0deg)    scaleY(1)    translateY(0); }
  62.5% { transform: skewY(3.2deg)  scaleY(.958) translateY(.35px); }
  75%   { transform: skewY(4.5deg)  scaleY(.94)  translateY(.5px); }
  87.5% { transform: skewY(3.2deg)  scaleY(.958) translateY(.35px); }
  100%  { transform: skewY(0deg)    scaleY(1)    translateY(0); }
}
@keyframes client-flag-folds {
  from { background-position: 0% 0; }
  to   { background-position: -120% 0; }
}

.sc-review.is-active .client-flag {
  animation: client-flag-wave 3.2s linear infinite;
}
/* Deliberately not the same duration as the shear: equal periods make the
   highlight arrive on the same frame as the fold every cycle, which the eye
   reads as a loop rather than as wind. */
.sc-review.is-active .client-flag::after {
  animation: client-flag-folds 2.6s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .sc-review.is-active .client-flag,
  .sc-review.is-active .client-flag::after { animation: none; }
  .client-flag svg { filter: none; }
}

/* ---- the name row ---- */

/* .sc-author strong is display:block in studio-console.css, which would put
   the flag on its own line under the name. */
#studio-console .sc-author strong {
  display: flex;
  align-items: center;
  gap: 7px;
}

/* ---- monogram avatars ----
   Placeholder until the client photographs go in. Deliberately a letter and
   not a stock portrait: a photograph of someone who is not the client, beside
   that client's words, is the one thing in a testimonial that must not be
   invented. Swap the <img> back in when the real faces arrive. */
#studio-console .sc-avatar--monogram {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: 0 0 auto;
  border: 1px solid rgb(164 184 207 / .4);
  border-radius: 50%;
  background: linear-gradient(150deg, rgb(120 150 196 / .38), rgb(30 46 72 / .55));
  color: #e8eff8;
  font-family: var(--body, "DM Sans", sans-serif);
  font-size: .92rem;
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1;
  text-transform: uppercase;
}

@media (max-width: 860px) {
  .client-flag { width: 20px; height: 14px; }
}

/* ---- mobile quote fit ----
   Three of the six ran to three lines at 375px, because the mobile rule caps
   the quote at 22ch and `ch` in the display serif resolves narrower than the
   text needs — so the block jumped between two and three lines as the carousel
   advanced. A rem cap does not depend on the font metric, so the box is the
   same width whatever the face resolves to, and a slightly smaller size brings
   the longest quote back to two lines. */
@media (max-width: 860px) {
  #studio-console .sc-panel--testimonials .sc-quote,
  #studio-console .sc-quote {
    max-width: none;
    font-size: 0.95rem;
    line-height: 1.32;
  }
  #studio-console .sc-visual,
  #studio-console .sc-visual img {
    display: none !important;
  }
}
