/* ═══════════════════════════════════════════════════════════════
   CASE STUDY VIEWER — see render.js's caseStudy()/frameVideo()

   Structure: tabselect() in tileMode, in one of two selector styles:
     .case--pills  — VSLs. Numbered text pills, tray ABOVE the case
                     study (tabs-before-panels is both the correct
                     ARIA order and the wanted layout — no reorder
                     trick needed).
     .case--thumbs — Organic, Landing Pages. Image thumbnails, no
                     numbering, tray BELOW (column-reverse — DOM
                     order stays tabs-before-panels for a11y, only
                     the visual position flips).
   ═══════════════════════════════════════════════════════════════ */

.case { margin-top: var(--sp-5); }

.case .tabselect { display: flex; flex-direction: column; gap: var(--sp-5); }
.case--thumbs .tabselect { flex-direction: column-reverse; }
.case .tabselect__panels { margin: 0; }

.case .tabselect__tray {
  position: relative;   /* anchors the sliding highlight bar */
  display: flex;
  gap: var(--sp-2);
  background: var(--surface-sunken);
  box-shadow: var(--e-sunken);
  border-radius: var(--radius-lg);
  padding: var(--sp-2);
  margin-bottom: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.case .tabselect__tray::-webkit-scrollbar { display: none; }

/* Pills tray spans the full width, tiles split it evenly. Thumbs
   tray sizes to its fixed-width thumbnail children and scrolls. */
.case--pills .tabselect__tray { flex-wrap: nowrap; width: 100%; }
.case--thumbs .tabselect__tray { flex-wrap: nowrap; width: auto; }

/* wireTraySlider() in render.js measures the active tile and
   translates this bar to it on load and on every switch. */
.tabselect__slider {
  position: absolute;
  top: var(--sp-2);
  bottom: var(--sp-2);
  left: 0;
  border-radius: var(--radius);
  transition: transform var(--dur-slow) var(--ease),
              width var(--dur-slow) var(--ease),
              background-color var(--dur-base) var(--ease),
              border-color var(--dur-base) var(--ease);
  z-index: 0;
  pointer-events: none;
}
/* Slider colour follows the selected tile's own variant — see the
   winner/mini-winner/lost treatment below. wireTraySlider() swaps
   this modifier class to match. */
.tabselect__slider--brand {
  background: var(--surface-brand-tint);
  border: 1px solid var(--border-brand);
  box-shadow: var(--e2), var(--highlight-top);
}
.tabselect__slider--outline {
  background: var(--surface);
  border: 1px solid var(--brand-sky);
  box-shadow: var(--e1), var(--highlight-top);
}
.tabselect__slider--neutral {
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--e1), var(--highlight-top);
}

/* -- STAGE + PANEL, side by side on desktop -----------------------
   Frame takes less width than the panel (40/60). On desktop the row
   stretches both columns to the same height — the frame's own 9:16
   ratio at that narrower width is normally the taller of the two, so
   in practice it's the panel column that grows to match the video,
   not the other way round. */

.case__body {
  display: grid;
  gap: var(--sp-5);
}

@media (min-width: 1024px) {
  .case__body {
    grid-template-columns: 40fr 60fr;
    align-items: stretch;
  }
}

/* -- FRAME — minimal unbranded phone -------------------------------- */

.frame {
  background: var(--surface-sunken);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--e-sunken);
  padding: var(--sp-2);
  /* Stays at its own natural (video-ratio) height — it's what the
     panel column stretches to match, not the other way round. */
  align-self: start;
}

.frame__inner {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--e1);
}

.case__video, .frame__inner .ph-graphic { display: block; width: 100%; }

/* Big opaque play pill, centered over the poster. Nothing plays
   until this is pressed — see wireCaseVideos() in render.js. */
.case__play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 72px;
  height: 72px;
  border: none;
  border-radius: var(--radius-pill);
  background: var(--grad-brand-solid);
  box-shadow: var(--e-brand);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform var(--dur-base) var(--ease),
              box-shadow var(--dur-base) var(--ease);
}
.case__play:hover {
  transform: translate(-50%, -50%) scale(1.06);
  box-shadow: var(--e-brand-hover);
}
.case__play[hidden] { display: none; }
.case__play svg {
  width: 26px;
  height: 26px;
  fill: var(--text-on-brand);
  margin-left: 3px; /* optically centers the play triangle */
}

/* -- RIGHT PANEL — one shared grey container, zones inside ---------- */

/* Grid item on desktop (case__body's column 2) — wraps the panel
   itself plus the winner CTA below it, so the button sits "underneath
   the analysis container" as its own box, in the panel's column, not
   spanning the frame too. Stretched to the frame's height by the
   parent grid; case__panel is the one that grows to absorb it — the
   CTA (flex:none, see below) keeps its own compact size, so the two
   together sum to exactly the frame's height, on every card. */
.case__panel-col {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}

.case__panel {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  background: var(--surface-sunken);
  border-radius: var(--radius-lg);
  padding: var(--sp-5);
  box-shadow: var(--e-sunken);
}

/* Pins "What it changed" to the bottom of the panel when it's
   stretched taller than its own content needs — reads as anchored,
   not stranded with dead space underneath it. */
.case__next { margin-top: auto; }

/* Winner only. Left-aligned and padded to match case__panel's own
   inset exactly, so the label sits flush under the diagnosis copy
   above it instead of floating centered — that's the "not aligned"
   fix. Compact height (sp-3 vertical, not sp-4) and a tighter radius
   than the old pill-ish sp-radius-lg reads less basic, more like a
   refined in-context link than a generic marketing button. */
.case__winner-cta {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-5);
  border-radius: var(--radius);
  background: var(--grad-brand-solid);
  color: var(--text-on-brand);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.01em;
  box-shadow: var(--e-brand);
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
}
.case__winner-cta:hover {
  transform: translateY(var(--lift));
  box-shadow: var(--e-brand-hover);
}
.case__winner-cta__arrow {
  flex: none;
  width: 16px;
  height: 16px;
  transition: transform var(--dur-base) var(--ease);
}
.case__winner-cta:hover .case__winner-cta__arrow { transform: translateX(3px); }

.case__format {
  align-self: flex-start;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* VSL-only wrapper (compactMetrics) — gives the accented metrics row
   its own "Performance" heading so the Hypothesis → Performance →
   Review → Next Steps zones read as four named sections, matching
   the labelled dl fields above and below it. */
.case__performance {
  display: grid;
  gap: var(--sp-2);
}

/* Zones sit raised on the panel's sunken backdrop — same
   sunken-container / raised-block layering as the rest of the site,
   just applied one level up so the whole panel reads as one unit.
   This is the Organic / Landing Pages metrics treatment. */
.case__metrics {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface);
  border-radius: var(--radius-sm);
  box-shadow: var(--e1);
}

.case__metric { display: flex; flex-direction: column; gap: 2px; }
.case__metric-value {
  font-family: var(--font-mono);
  font-size: var(--fs-lead);
  font-weight: 600;
  color: var(--text-primary);
}
.case__metric-label {
  font-size: var(--fs-micro);
  color: var(--text-muted);
}

/* VSL-only compact row: Spend / ROAS / Engagement / a Screenshot
   button, compressed into one accented strip instead of a boxed grid
   plus a separate proof expandable. 1px gap + a coloured parent
   background is the divider — cheaper than four individual borders
   and it stays crisp at the shared corner radius. Lighter fill
   (surface-brand-tint) than the plain-white Organic/Landing grid
   above — "not so opaque" was the note. */
.case__metrics--row {
  display: flex;
  gap: 1px;
  padding: 0;
  background: var(--border-brand);
  border: 1px solid var(--border-brand);
  border-radius: var(--radius-sm);
  overflow: hidden;
  box-shadow: none;
}
.case__metrics--row .case__metric {
  flex: 1 1 0;
  min-width: 0;
  padding: var(--sp-2) var(--sp-3);
  background: var(--surface-brand-tint);
  gap: 1px;
}
.case__metrics--row .case__metric-value { font-size: var(--fs-small); color: var(--brand-deep); }
.case__metrics--row .case__metric-label { font-size: 0.65rem; }

.case__screenshot-btn {
  flex: 1 1 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-2) var(--sp-3);
  background: var(--surface-brand-tint);
  border: none;
  color: var(--brand-indigo);
  font-size: var(--fs-small);
  font-weight: 700;
  cursor: pointer;
  transition: background var(--dur-base) var(--ease), color var(--dur-base) var(--ease);
}
.case__screenshot-btn:hover { background: var(--brand-indigo-a20); color: var(--brand-deep); }

.case__proof { display: grid; gap: var(--sp-2); }
.case__proof img, .case__proof .ph-graphic { width: 100%; border-radius: var(--radius-xs); }
.case__proof-caption { font-size: var(--fs-small); color: var(--text-secondary); }

.case__field {
  margin: 0;
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface);
  border-radius: var(--radius-sm);
  box-shadow: var(--e1);
}
.case__field dt {
  font-size: var(--fs-micro);
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.case__field dd { margin: 0; font-size: var(--fs-small); margin-top: var(--sp-2); }

/* ── FIELD SHAPES — paragraph, bullets, or sub-labelled groups ───
   caseFieldValue() in render.js picks one of three by inspecting the
   data. A VSL's Concept is four labelled groups (Segment, Narrative,
   Format, Belief shift) and its Review is a short list of numbered
   observations, so the field has to hold more than one paragraph.

   Bullets are marker-less with a hanging em dash: a real disc marker
   plus the field's own uppercase label plus the panel's own border is
   three levels of decoration on a box that's already small. */

.case__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--sp-2);
}

.case__list li {
  position: relative;
  padding-left: var(--sp-4);
  line-height: var(--lh-snug);
}

.case__list li::before {
  content: "—";
  position: absolute;
  left: 0;
  color: var(--text-faint);
}

/* Sub-labelled group (Segment / Narrative / Format / Belief shift).
   The label is mono micro rather than another uppercase run, so it
   reads as a level BELOW the field's own <dt> instead of competing
   with it. */
.case__subfield + .case__subfield { margin-top: var(--sp-3); }

.case__subfield-label {
  margin: 0 0 var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: 0.02em;
}

.case__subfield > p:not(.case__subfield-label) {
  margin: 0;
  line-height: var(--lh-snug);
}

/* Diagnosis is the load-bearing field on every case study — same
   emphasis idea as .teardown dd.is-hypothesis in components.css. */
.case__field.is-diagnosis {
  border-left: 3px solid var(--brand-indigo);
}
.case__field.is-diagnosis dd {
  color: var(--text-primary);
  font-weight: 500;
}

.case__next {
  padding-top: var(--sp-2);
  display: grid;
  gap: var(--sp-2);
}
.case__next p { margin: 0; font-size: var(--fs-small); }

.case__gotobtn {
  justify-self: start;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--brand-indigo);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}
.case__gotobtn:hover { color: var(--brand-deep); }

/* -- SELECTOR TILE — shared base, both styles -----------------------
   The sliding bar above (.tabselect__slider) IS the selected state —
   tiles themselves stay transparent so it shows through. Each status
   keeps its own on-brand accent whether selected or not. */

.case__tile {
  position: relative;
  z-index: 1;
  display: flex;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius);
  border: 1.5px solid transparent;
  background: transparent;
  text-align: left;
  overflow: hidden;   /* clips the ::before accent bar to this radius —
                          see the note in components.css above .card */
  transition: border-color var(--dur-base) var(--ease);
}
.case__tile:hover { border-color: var(--border-strong); }

.case__tile-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.case__tile-status {
  font-size: var(--fs-small);
  font-weight: 700;
}
.case__tile-metrics {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  color: var(--text-faint);
}

/* Pills — VSLs: numbered, fills the row evenly. */
.case__tile--pills {
  flex: 1 1 0;
  min-width: 120px;
  flex-direction: row;
  align-items: center;
  gap: var(--sp-3);
}
.case__tile-num {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-pill);
  background: var(--grad-brand-solid);
  color: var(--text-on-brand);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 700;
  transition: transform var(--dur-base) var(--ease);
}

/* Mini poster thumbnail — sits in the spare space at the tile's right
   edge, pushed there by margin-left:auto since num + text don't fill
   a pill's full flex-1 width. Just enough to recognize the ad by
   sight; the frame does the real preview work. */
.case__tile-mini {
  flex: none;
  margin-left: auto;
  width: 30px;
  height: 38px;
  border-radius: var(--radius-xs);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--e1);
  border: 1px solid transparent;
  transition: border-color var(--dur-base) var(--ease);
}
.case__tile-mini img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Selected state — the sliding bar behind the tile is the primary
   signal, but the number badge and mini thumbnail pick up their own
   accent too so the active ad # reads unambiguously at a glance,
   even mid-scroll before the slider has settled. */
.case__tile[aria-selected="true"] .case__tile-num {
  transform: scale(1.08);
  box-shadow: var(--e1);
}
.case__tile[aria-selected="true"] .case__tile-mini {
  border-color: var(--brand-indigo);
}
.case__tile[aria-selected="true"] .case__tile-status {
  color: var(--text-primary);
}

/* Thumbs — Organic, Landing Pages: fixed-width image card, no
   numbering, no fill-the-row stretch — the tray scrolls instead. */
.case__tile--thumbs {
  flex: none;
  width: 132px;
  flex-direction: column;
  align-items: stretch;
  gap: var(--sp-2);
  padding: var(--sp-2);
}
.case__tile-thumb {
  display: block;
  aspect-ratio: 3 / 4;
  border-radius: var(--radius-xs);
  overflow: hidden;
  background: var(--surface);
}
.case__tile-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.case__tile--thumbs .case__tile-text { padding: 0 var(--sp-1) var(--sp-1); }
.case__tile--thumbs .case__tile-title {
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--text-primary);
}

/* Winner — the strongest accent: brand gradient top edge, indigo text. */
.case__tile--brand { border-color: var(--border-brand); }
.case__tile--brand .case__tile-status { color: var(--brand-indigo); }
.case__tile--brand::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: var(--grad-brand-line);
}

/* Reusable for any future status mapped to PILL_VARIANT's 'outline'
   tier — nothing currently uses it ("Didn't scale" reads as Lost, not
   a middle tier — design-rules call). */
.case__tile--outline { border-color: var(--brand-sky); }
.case__tile--outline .case__tile-status { color: var(--brand-deep); }

/* Lost / Didn't scale — deliberately the quietest: muted text, no
   accent border. Same weight for both; a loss is a loss. */
.case__tile--neutral .case__tile-status { color: var(--text-muted); }

/* -- MOBILE — horizontal scroll, not wrap: the slider only tracks
   translateX, so tiles must stay on one row for its position math
   to stay correct. -------------------------------------------------- */

@media (max-width: 767px) {
  .case__tile--pills { min-width: 128px; }
  .case__tile--thumbs { width: 108px; }
}

/* ═══════════════════════════════════════════════════════════════
   SCREENSHOT POPUP — render.js's openScreenshotModal()

   One shared overlay, reused for every case study's Screenshot
   button. Fades + scales in on open; closes on a click anywhere
   (including itself) or after 10s, whichever comes first.
   ═══════════════════════════════════════════════════════════════ */

.screenshot-modal {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-6);
  background: rgba(13, 21, 38, 0.55);
  backdrop-filter: blur(6px);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-slow) var(--ease);
  z-index: 100;
  cursor: pointer;
}
.screenshot-modal.is-open { opacity: 1; pointer-events: auto; }

.screenshot-modal__card {
  max-width: min(720px, 90vw);
  max-height: 85vh;
  overflow: hidden;
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--e4);
  padding: var(--sp-3);
  transform: scale(0.96);
  transition: transform var(--dur-slow) var(--ease);
  cursor: default;
}
.screenshot-modal.is-open .screenshot-modal__card { transform: scale(1); }

/* Landscape product UI — the Taskanchor shots. 720px is sized for a
   portrait-ish Ads Manager crop; a 16:10 app screenshot at that width
   renders its labels below reading size. */
.screenshot-modal__card--wide { max-width: min(1180px, 94vw); }

.screenshot-modal__media img,
.screenshot-modal__media svg {
  display: block;
  width: 100%;
  border-radius: var(--radius-sm);
}
.screenshot-modal__caption {
  margin: var(--sp-3) var(--sp-2) 0;
  font-size: var(--fs-small);
  color: var(--text-secondary);
}
