/* ── Opiniones ─────────────────────────────────────────────────────────────
   The Framer file had a flat screenshot of this component pasted where the
   component belonged. This is the component, brought over from the doctor's
   own site and re-toned for the cream — the panel it sits in is the darker
   rectangle that screenshot was showing.

   One opinion at a time inside a panel that never changes height. The rule
   across the top is the position and the clock at once: a segment an eighth
   of the track wide travels to whichever opinion is showing, and fills as
   that opinion's turn runs out. Under it, at the left, the two buttons — and
   every slide sits in the same grid cell, so moving between them cannot move
   anything else on the page.
   ────────────────────────────────────────────────────────────────────────── */

.ops {
  position: relative;
  background: var(--ground);
  overflow-x: clip;
}

.ops__defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ── Heading ───────────────────────────────────────────────────────────── */

.ops__head {
  max-width: 44rem;
  margin: 0 auto clamp(2.5rem, 5vw, 4rem);
  text-align: center;
}

.ops__head .h-eyebrow { margin-bottom: clamp(1rem, 2vw, 1.4rem); }

.ops__title { margin-bottom: clamp(0.85rem, 1.8vw, 1.15rem); }

/* The word the sentence turns on, picked out in the accent — the one
   emphasis device the Framer page uses in a heading. */
.ops__title em {
  font-style: normal;
  color: var(--indigo);
}

.ops__lede { margin-inline: auto; max-width: 42ch; }

/* ── The panel ─────────────────────────────────────────────────────────── */

.ops__panel {
  padding: clamp(1.25rem, 2.6vw, 2.25rem);
  border-radius: var(--r-card);
  background: var(--ground-alt);
}

/* Two decks, side by side where there is room for two. Each is its own
   carousel: its own four opinions, its own clock, its own buttons. */
.ops__decks {
  display: grid;
  gap: clamp(1.25rem, 2.4vw, 2rem);
}

.ops__deck {
  display: grid;
  gap: clamp(1.125rem, 2.2vw, 1.75rem);
  padding: clamp(1.25rem, 2.2vw, 1.75rem);
  border-radius: 14px;
  background: var(--white);
}

/* ── The rule ──────────────────────────────────────────────────────────── */

.ops__track {
  position: relative;
  height: 2px;
  background: var(--ink-12);
  transform-origin: 0 50%;      /* it draws itself from the left on arrival */
}

.ops__lit {
  position: absolute;
  inset: 0 auto 0 0;
  width: calc(100% / 8);        /* one eighth: one opinion */
  background: rgba(42, 43, 47, 0.2);
  will-change: transform;
}

.ops__fill {
  position: absolute;
  inset: 0;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: 0 50%;
  will-change: transform;
}

/* ── The two buttons ───────────────────────────────────────────────────────
   Round, which nothing else on this site is: the rest of the page's controls
   are pills carrying words, and these carry a direction.
   ────────────────────────────────────────────────────────────────────────── */

.ops__nav { display: flex; gap: 0.625rem; }

.ops__step {
  --out:  140%;                 /* where the leaving arrow goes */
  --in:  -140%;                 /* and where its copy waits */
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  padding: 0;
  background: none;
  border: 1px solid var(--ink-12);
  border-radius: var(--r-pill);
  color: var(--ink);
  cursor: pointer;
  transition: background-color 240ms var(--ease),
              border-color 240ms var(--ease),
              transform 240ms var(--ease);
}

.ops__step[data-dir="-1"] { --out: -140%; --in: 140%; }

.ops__step:hover  { background: var(--ink-08); border-color: rgba(42, 43, 47, 0.2); }
.ops__step:active { transform: scale(0.94); }

/* The arrow leaves and its own copy takes its place, so the button answers
   before the slide does. */
.ops__step-ico {
  display: grid;
  width: 1.125rem;
  height: 1.125rem;
  overflow: hidden;
}

.ops__step-ico svg {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  transition: transform 260ms var(--ease);
}

.ops__step[data-dir="-1"] .ops__step-ico svg { transform: scaleX(-1); }

.ops__step-ico svg:last-child { transform: translateX(var(--in)); }
.ops__step[data-dir="-1"] .ops__step-ico svg:last-child {
  transform: translateX(var(--in)) scaleX(-1);
}

.ops__step:hover .ops__step-ico svg:first-child { transform: translateX(var(--out)); }
.ops__step[data-dir="-1"]:hover .ops__step-ico svg:first-child {
  transform: translateX(var(--out)) scaleX(-1);
}

.ops__step:hover .ops__step-ico svg:last-child { transform: translateX(0); }
.ops__step[data-dir="-1"]:hover .ops__step-ico svg:last-child {
  transform: translateX(0) scaleX(-1);
}

/* ── The slides ────────────────────────────────────────────────────────────
   All four in one cell. The cell is as tall as the longest of them, which is
   what makes changing slides cost nothing: no reflow, no shift, and the
   panel is the same height on every one.
   ────────────────────────────────────────────────────────────────────────── */

.ops__slides {
  display: grid;
  align-items: center;
  min-height: 1px;
  touch-action: pan-y;          /* the page keeps the vertical scroll */
}

.op {
  grid-area: 1 / 1;
  margin: 0;
  will-change: transform;
}

/* ── The opinion ───────────────────────────────────────────────────────── */

.op__quote { margin: 0; padding: 0; }

.op__quote p {
  margin: 0;
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: var(--track-body);
  color: var(--ink);
  text-wrap: pretty;
}

/* A word in its own mask, so the opinion arrives a word at a time rather
   than fading in as a block. Same primitive as .oh, per word: the padding
   and the negative margin below give the descenders room inside it. */
.op__w {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding: 0 0.12em 0.2em 0;
  margin: 0 -0.12em -0.2em 0;
}
.op__w > span { display: inline-block; will-change: transform; }

.op__by { margin: clamp(1rem, 2vw, 1.5rem) 0 0; }

.op__rating { display: flex; gap: 0.1875rem; margin-bottom: 0.75rem; }

.op__star {
  width: 0.9375rem;
  height: 0.9375rem;
  fill: var(--star);
  flex: none;
  will-change: transform;
}

.op__name {
  display: block;
  font-size: var(--fs-ui);
  font-weight: 600;
  letter-spacing: var(--track-body);
  color: var(--ink);
}

.op__date {
  display: block;
  margin-top: 0.1875rem;
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-mute);
}

/* Each letter of the name in its own mask, so the name arrives sideways
   through it rather than fading. Same idea as .oh, turned on its side. */
/* Vertical room only. The letters arrive by travelling in from the right, so
   widening this box would leave a sliver of each one showing before it moves. */
.op__char {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding-bottom: 0.2em;
  margin-bottom: -0.2em;
}
.op__char > span {
  display: inline-block;
  transform: translateX(100%);
  will-change: transform;
}

/* ── From 64rem: the buttons beside the opinion ────────────────────────── */

@media (min-width: 64rem) {
  .ops__decks { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .ops__deck {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "track  track"
      "nav    slides";
    column-gap: clamp(1.25rem, 2.4vw, 2.25rem);
    row-gap: clamp(1.25rem, 2.4vw, 2rem);
  }

  .ops__track  { grid-area: track; }
  .ops__nav    { grid-area: nav; flex-direction: row; align-self: start; }
  .ops__slides { grid-area: slides; }
}

/* ── The same opinions, said out loud ─────────────────────────────────────
   Three videos inside the panel, under the two decks. Deliberately part of
   the panel and not a section of their own: the heading above already says
   these are opinions, and a second heading would make the page argue the
   point twice.

   Three across where there is room. On a phone, one at a time behind two
   arrows — buttons, not a sideways swipe, so it never competes with the
   page's own scroll. See "One at a time, on a phone" below.
   ────────────────────────────────────────────────────────────────────────── */

/* Heading beside the films where there is room for it, above them where
   there is not. The row was centred in the panel with a good deal of empty
   either side of it; this is what that space is for. */
.ops__films {
  display: grid;
  gap: clamp(1rem, 2.4vw, 1.75rem);
  margin-top: clamp(1.25rem, 2.4vw, 2rem);
}

@media (min-width: 62rem) {
  .ops__films {
    grid-template-columns: minmax(0, 13rem) minmax(0, 1fr);
    align-items: center;
    column-gap: clamp(1.5rem, 3vw, 2.75rem);
  }
}

.films__title {
  margin: 0 0 0.5rem;
  font-size: var(--fs-lead);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: var(--track-display);
  color: var(--ink);
  text-wrap: balance;
}

.films__note {
  margin: 0;
  font-size: var(--fs-meta);
  letter-spacing: var(--track-body);
  color: var(--ink-mute);
}

.films {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(0.75rem, 1.6vw, 1.125rem);
}

/* justify-self, not auto margins.

   An auto inline margin on a grid item suppresses stretch — the item falls
   back to fit-content. And fit-content here is zero: .film__frame carries its
   height from aspect-ratio, and its only child is absolutely positioned, so
   it has no intrinsic width to be fitted to. The row measured 0px wide and
   the three players collapsed to nothing.

   This was fine while .films sat in the panel's block flow, where auto
   margins just centre. It stopped being fine the moment the heading turned
   the parent into a grid. */
.films {
  width: 100%;
  /* A quarter larger than they were. Written as the multiplication so the
     relationship stays visible: 15rem was the stacked cap, 44rem the row's. */
  max-width: calc(15rem * 1.25);
  justify-self: center;
}

@media (min-width: 46rem) {
  /* Held to a measure of their own: three 3:4 players stretched across the
     whole panel would be taller than the opinions they belong to. */
  .films {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    max-width: calc(44rem * 1.25);
  }
}

.film { margin: 0; }

/* The frame owns the ratio, so a video and a placeholder occupy the same box
   and dropping the real file in moves nothing. 4:5 — the shape a phone shoots
   a person in, which is what these will be. */
.film__frame {
  position: relative;
  /* 3:4 — the shape of the picture, not of the file. The sources are 9:16
     with 160px of black at each end; object-fit: cover on a 3:4 box trims
     0.2222 of the width from each end, and a 160px bar of a 1280px source is
     0.2222 of the width. The letterbox is removed exactly, with nothing
     re-encoded and nothing else lost. */
  aspect-ratio: 3 / 4;
  border-radius: 14px;
  overflow: hidden;
  /* White, like the decks above it — the panel these all sit on is the tinted
     one, so a frame in the panel's own tone would have vanished into it. And
     --ground-alt does not exist in the blue edition at all. */
  background: var(--white);
}

.film__vid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.film__vid { object-fit: cover; display: block; }

/* ── One at a time, on a phone ─────────────────────────────────────────────
   Stacked, the three players ran to three screens of video before the page
   got anywhere. Below 46rem js/films.js marks the stage as paged and only
   the current one is shown, between two arrows, with a count under it.
   No script, or wider than that, and the arrows and the count never appear:
   a control that cannot control is worse than no control.
   ────────────────────────────────────────────────────────────────────────── */

.films__stage {
  display: grid;
  min-width: 0;
}

.films__step,
.films__count { display: none; }

@media (max-width: 45.99rem) {
  .films__stage--paged {
    grid-template-columns: auto minmax(0, calc(15rem * 1.25)) auto;
    justify-content: center;
    align-items: center;
    column-gap: 0.5rem;
    row-gap: 0.75rem;
  }

  .films__stage--paged .films       { grid-area: 1 / 2; }
  .films__stage--paged .films__step { display: grid; flex: none; }
  .films__stage--paged .films__step[data-dir="-1"] { grid-area: 1 / 1; }
  .films__stage--paged .films__step[data-dir="1"]  { grid-area: 1 / 3; }

  .films__stage--paged .film:not(.is-current) { display: none; }

  .films__stage--paged .films__count {
    display: block;
    grid-area: 2 / 2;
    margin: 0;
    text-align: center;
    font-size: var(--fs-meta);
    font-variant-numeric: tabular-nums;
    letter-spacing: var(--track-body);
    color: var(--ink-mute);
  }
}


/* ── Foot ──────────────────────────────────────────────────────────────── */

.ops__foot {
  display: grid;
  gap: clamp(1.25rem, 2.4vw, 1.75rem);
  margin: clamp(1.5rem, 3vw, 2.25rem) 0 0;
}

.ops__note {
  margin: 0;
  max-width: 52ch;
  font-size: var(--fs-meta);
  line-height: 1.6;
  letter-spacing: var(--track-body);
  color: var(--ink-mute);
}

.dr-badge { justify-self: start; }

@media (min-width: 48rem) {
  .ops__foot {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: clamp(2rem, 5vw, 5rem);
  }
  .dr-badge { justify-self: end; }
}

.dr-badge:focus-visible { outline-color: var(--doctoralia); }

/* ── Resting state ─────────────────────────────────────────────────────────
   No script, no GSAP, or reduced motion: there is no carousel to drive, so
   the eight opinions are simply a column of eight opinions. The rule and the
   buttons go with it — neither does anything without a script behind it, and
   a control that cannot control is worse than no control.
   ────────────────────────────────────────────────────────────────────────── */

.no-js .ops__track,
.no-js .ops__nav,
.ops--static .ops__track,
.ops--static .ops__nav { display: none; }

.no-js .ops__deck,
.ops--static .ops__deck { grid-template-columns: minmax(0, 1fr); }

.no-js .ops__slides,
.ops--static .ops__slides {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
  max-width: 48ch;
}

.no-js .op,
.ops--static .op { grid-area: auto; visibility: visible; opacity: 1; }

.no-js .op__w > span,
.no-js .op__char > span,
.ops--static .op__w > span,
.ops--static .op__char > span { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .ops__step-ico svg,
  .ops__step { transition-duration: 1ms; }
  .op__w > span, .op__char > span { transform: none; }
}

/* ── Mobile ────────────────────────────────────────────────────────────────
   One deck, not two. Stacked on a phone the second is another four opinions
   below four the reader has already been shown, and the panel runs to twice
   the height it needs to say the same thing.
   ────────────────────────────────────────────────────────────────────────── */

@media (max-width: 47.99rem) {
  .ops__decks .ops__deck:last-child { display: none; }
}
