/* The results section: case cards, KPI tiles, metric tabs and the charts
   js/results.js draws into them.

   Chart colour lives here, not in the script. The brand red is the only data
   colour: every chart is a single series, so there is one identity to carry
   and nothing for a second hue to do. It was run through the dataviz
   palette validator against both surfaces below — lightness band, chroma
   floor and >= 3:1 contrast all pass. */

.results {
  --chart-accent: var(--primary);
  /* The card's own colour — .case's --black-300 wash composited over
     --black. The dots' 2px ring is drawn in this, so it has to match what
     is actually behind the chart or the ring reads as a halo. */
  --chart-surface: #151515;
  --chart-grid: rgba(255, 255, 255, .08);
  --chart-ink: var(--text-muted);
}

.results__lead { max-width: 52ch; margin-top: 24px; }

/* ---------- the carousel ----------
   One case on screen at a time. The track is a scroll-snap container first
   and a scripted carousel second: touch, trackpad and a keyboard tabbing
   into a slide all move it natively, so the arrows are an addition rather
   than the mechanism. */

.results__carousel { margin-top: clamp(40px, 5vw, 72px); }

.results__cases {
  display: grid;
  grid-auto-flow: column;
  /* Each slide is the full track width, so one case fills the view and the
     next begins exactly at the edge. */
  grid-auto-columns: 100%;
  gap: clamp(20px, 3vw, 32px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* The cards carry their own rounded corners and the track has no padding,
     so nothing needs clipping — and a scrollbar under six cards would be
     chrome the arrows already replace. */
  scrollbar-width: none;
  /* Every card is as tall as the tallest, so stepping never jumps the page. */
  align-items: stretch;
}

.results__cases::-webkit-scrollbar { display: none; }

.case { scroll-snap-align: start; }

.results__nav {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: clamp(20px, 2vw, 28px);
}

.results__arrow {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--white-100);
  border-radius: 50%;
  background: none;
  color: var(--white-800);
  cursor: pointer;
  transition: border-color .25s, background-color .25s, color .25s, opacity .25s;
}

.results__arrow:hover:not(:disabled) {
  border-color: var(--border-1);
  background: var(--white-100);
  color: var(--white);
}

/* Disabled at the ends rather than wrapping around: a results reel that
   silently loops back to the first case makes it impossible to tell you have
   seen them all. */
.results__arrow:disabled { opacity: .3; cursor: default; }

.results__count {
  margin: 0;
  font-family: var(--font-secondary);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

.results__now { color: var(--white); }

/* No script: no arrows to press, but the track still scrolls and swipes. */
.results__carousel:not(.is-ready) .results__nav { display: none; }

.results__note {
  margin-top: 20px;
  font-family: var(--font-secondary);
  font-size: 13px;
  color: var(--text-muted);
}

/* ---------- the case card ---------- */

.case {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(28px, 4vw, 56px);
  padding: clamp(20px, 3vw, 40px);
  /* Same card as .step on the work process: a visitor who has scrolled past
     it already knows the shape. */
  border: 1px solid var(--white-100);
  border-radius: var(--radius-lg);
  background: var(--black-300);
}

.case__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin: 0;
  font-family: var(--font-secondary);
  font-size: 13px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.case__channel { color: var(--white); }

/* ---------- the one-line result ----------
   The whole case in one line, above the headline, so stepping through the
   carousel does not mean reading six paragraphs before you can compare two
   of them. Sized and worded (content/results.php) to stay on one line down
   to 375px; nowrap is deliberately NOT set — if a translation or a longer
   figure ever overflows, two lines is the right failure, a clipped number
   is not. */

.case__line {
  margin: 18px 0 0;
  font-family: var(--font-secondary);
  font-size: 15px;
  line-height: 1.4;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* The outcome half in white: the eye lands on what the money bought, and the
   spend beside it stays legible without competing. */
.case__line .hl {
  color: var(--white);
  font-style: normal;
  font-weight: var(--w-medium);
}

.case__title {
  margin: 12px 0 0;
  font-family: var(--font-body);
  font-size: clamp(24px, 1rem + 1.3vw, 38px);
  font-weight: var(--w-medium);
  line-height: 1.08;
  /* Keeps a two-line headline from ending on one orphaned word. */
  text-wrap: balance;
}

.case__text {
  margin: 14px 0 0;
  max-width: 46ch;
  font-family: var(--font-secondary);
  font-size: var(--p2);
  line-height: var(--lh-xl);
  color: var(--text-muted);
}

/* .hl is the site's emphasis mark. In muted body copy it lifts to white. */
.case__title .hl { color: var(--primary-text); font-style: normal; }
.case__text .hl { color: var(--white); font-style: normal; }

/* ---------- KPI tiles ----------
   A 1px gap over a hairline-coloured background draws the dividers: the
   tiles never carry a border of their own, so the lines never double up
   where two tiles meet. */

.case__kpis {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  margin: 28px 0 0;
  overflow: hidden;
  border: 1px solid var(--white-100);
  border-radius: var(--radius-md);
  background: var(--white-100);
}

.kpi {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 18px 18px;
  background: var(--chart-surface);
}

.kpi__label {
  font-family: var(--font-secondary);
  font-size: 13px;
  color: var(--text-muted);
}

/* Proportional figures, deliberately: tabular-nums gives every digit the
   width of a 0, and at this size "1,310" would read loose. */
.kpi__value {
  margin: 0;
  font-family: var(--font-body);
  font-size: clamp(24px, 1rem + 1.2vw, 34px);
  font-weight: var(--w-medium);
  line-height: 1;
  color: var(--white);
  white-space: nowrap;
}

/* ---------- metric tabs ---------- */

/* A flex column so the one control on the card can be pinned to the bottom
   of it — see .case__proof. Everything above it stacks as it always did. */
.case__viz {
  display: flex;
  flex-direction: column;
  /* The gap does the spacing between every block in this column, so the
     button's margin-top:auto can take the slack without collapsing against
     whatever sits above it when a card happens to have none. */
  gap: 18px;
  min-width: 0;
}

.case__tabs {
  display: inline-flex;
  /* Its own width, not the column's: .case__viz is a flex column, and a
     stretched tab row turns a control into a band across the card. */
  align-self: flex-start;
  gap: 4px;
  max-width: 100%;
  padding: 4px;
  border: 1px solid var(--white-100);
  border-radius: var(--radius-pill);
  /* Four labels fit a 320px phone; this is the fallback if copy ever
     makes one longer — scroll inside the pill, never widen the page. */
  overflow-x: auto;
  scrollbar-width: none;
}

.case__tabs::-webkit-scrollbar { display: none; }

.case__tab {
  flex-shrink: 0;
  min-height: 36px;
  padding: 0 16px;
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  font: var(--w-medium) 14px/1 var(--font-secondary);
  color: var(--text-muted);
  cursor: pointer;
  transition: background-color .2s, color .2s;
}

.case__tab:hover { color: var(--white); }

.case__tab[aria-selected="true"] {
  background: var(--white);
  color: var(--black);
}

/* ---------- the chart ---------- */

.chart {
  position: relative;
  /* The height includes the x-axis band: the script draws into exactly this
     box, so the labels are inside it rather than spilling into a nested
     scroll. */
  height: 300px;
  border-radius: var(--radius-sm);
}

.chart:focus-visible { outline-offset: 6px; }

.chart svg { display: block; overflow: visible; }

.chart__grid { stroke: var(--chart-grid); stroke-width: 1; shape-rendering: crispEdges; }

.chart__tick {
  font-family: var(--font-secondary);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  fill: var(--chart-ink);
}

.chart__col {
  fill: var(--chart-accent);
  transform-box: fill-box;
  transform-origin: 50% 100%;
  transition: opacity .15s;
}

/* Emphasis on hover: the bar under the pointer keeps full strength and the
   rest step back, so the one being read is unmistakable. */
.chart.is-hovering .chart__col:not(.is-active) { opacity: .35; }

.chart__line {
  fill: none;
  stroke: var(--chart-accent);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* Fill set per chart by the script (a url() to that chart's own gradient). */
.chart__area { stroke: none; }

.chart__dot {
  fill: var(--chart-accent);
  stroke: var(--chart-surface);
  stroke-width: 2;
}

.chart__cross {
  stroke: rgba(255, 255, 255, .28);
  stroke-width: 1;
  shape-rendering: crispEdges;
}

/* Text never wears the series colour: values and labels stay in ink, and
   the red mark beside them carries the identity. */
.chart__endlabel {
  font-family: var(--font-secondary);
  font-size: 13px;
  font-weight: 600;
  fill: var(--white);
}

.chart__tip {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  padding: 9px 12px 10px;
  border: 1px solid var(--white-100);
  border-radius: 10px;
  background: #1d1d1d;
  box-shadow: 0 12px 28px -12px rgba(0, 0, 0, .9);
  font-family: var(--font-secondary);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity .12s;
}

.chart__tip.is-on { opacity: 1; }

/* Value leads, label follows — the reader already knows the series. */
.chart__tipvalue {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 15px;
  font-weight: 600;
  color: var(--white);
}

/* A short stroke, not a box: at tooltip size a filled square is data-weight
   ink doing a label's job. */
.chart__tipkey {
  width: 12px;
  height: 2px;
  border-radius: 1px;
  background: var(--chart-accent);
}

.chart__tiplabel {
  margin-top: 3px;
  font-size: 12px;
  color: var(--text-muted);
}

.chart__live {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Without the script there is nothing behind the tabs and nothing to draw
   into, so neither is shown. What survives is the KPI tiles and the link to
   the dashboard — the headline figures and the proof, just not the series. */
.case:not(.is-ready) .case__tabs,
.case:not(.is-ready) .case__panel { display: none; }

.case__footnote {
  margin: 0;
  font-family: var(--font-secondary);
  font-size: 12px;
  color: var(--text-muted);
}

@media (max-width: 991px) {
  /* Stacked, the card is two rows in a box sized by the tallest slide in
     the track, and left to themselves both rows grow — which opens a gap in
     the middle of the card, under the copy. Naming the rows instead hands
     every spare pixel to the second one: the copy stays the height it needs
     and the chart column absorbs the rest, which is also what lets the
     button inside it reach the bottom edge the way it does on a wide card. */
  .case { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
}

@media (max-width: 560px) {
  .chart { height: 240px; }
  .case__line { font-size: 14px; }
  .case__tab { padding: 0 11px; font-size: 13px; }
  .kpi { padding: 14px 14px 16px; }
}

@media (prefers-reduced-motion: reduce) {
  .case__tab,
  .chart__col,
  .chart__tip { transition: none; }
}

/* ---------- the evidence ----------
   Anyone can draw a chart. The screenshot is what makes the chart beside it
   worth believing, so the link to it is a real control, not fine print. */

.case__proof {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  /* The card's one action, in the corner a card's action belongs in.
     margin-top:auto takes whatever height the column has left over, so the
     button sits on the bottom edge whether the chart above it is 300px or
     the screenshot is 200px; align-self keeps it its own width at the right
     rather than stretching into a band. In flow, never absolute — an
     absolute corner would ride over the content on a card that fills. */
  align-self: flex-end;
  margin-top: auto;
  min-height: 40px;
  padding: 0 16px;
  border: 1px solid var(--white-100);
  border-radius: var(--radius-pill);
  font-family: var(--font-secondary);
  font-size: 13px;
  color: var(--white-800);
  transition: border-color .25s, color .25s, background-color .25s;
}

.case__proof:hover,
.case__proof:focus-visible {
  border-color: var(--border-1);
  background: var(--white-100);
  color: var(--white);
}

.case__proof svg { flex-shrink: 0; opacity: .75; }

/* ---------- a case with no series to chart ----------
   The dashboard IS the visual here, rather than something tucked behind a
   link, and it gets the same framed panel the charts sit in so the slide has
   the same shape as its neighbours.

   Every card in the track is as tall as the tallest, so this one has height
   to spend. It is spent as air between the panel and the button pinned under
   it, never inside the frame: a frame stretched to 420px around a 175px
   screenshot is a visibly empty box, which reads worse than the thin strip
   it replaced. The frame hugs the image. */

/* Centred in whatever height the column has, not parked at the top: the
   figure takes the free space itself and centres the image and its caption
   inside it, so the button below still reaches the bottom edge. Doing it
   with the figure rather than the column matters — auto margins on both
   would split the slack three ways and land the image a third of the way
   down instead of halfway. */
.case__shotfig {
  display: flex;
  flex: 1;
  flex-direction: column;
  justify-content: center;
  margin: 0;
}

/* Less frame, more picture — at every width. */
.case--shot .case__shotlink { padding: clamp(8px, 1vw, 12px); }

/* Wider than the 5/7 every other card uses: a screenshot IS the evidence on
   these two, and at 7 columns it was filling under a third of the height it
   had. The copy column pays for it, so two guards.

   It waits for 1200px: at 1024 the narrower column pushed "$5,680" and
   "$43.00" past the edge of their tiles, which are nowrap and so clip rather
   than wrap.

   And it never drops under 330px. Past about 1500 the card stops widening
   with the container while the tile type keeps growing to its 34px cap, so a
   pure fraction breaks those same two values at the other end of the range.
   330px is what the wider of them needs at that cap, plus the tile padding. */
@media (min-width: 1200px) {
  .case--shot {
    grid-template-columns: minmax(330px, 4fr) minmax(0, 8fr);
    gap: clamp(24px, 3vw, 40px);
  }
}

.case__shotlink {
  display: block;
  overflow: hidden;
  padding: clamp(10px, 1.6vw, 16px);
  border: 1px solid var(--white-100);
  border-radius: var(--radius-md);
  /* The same wash the KPI tiles sit on, so the two blocks on this card read
     as one family rather than a panel and a photo. */
  background: var(--chart-surface);
  transition: border-color .3s, background-color .3s, transform .4s var(--ease);
}

.case__shotlink:hover,
.case__shotlink:focus-visible {
  border-color: var(--border-1);
  transform: translateY(-3px);
}

/* The shots are light-UI screenshots on a dark page. Held back a little at
   rest so they sit in the page instead of glaring out of it, full strength
   on hover — which also signals they are worth clicking. */
.case__shotlink img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-sm);
  opacity: .82;
  transition: opacity .3s;
}

.case__shotlink:hover img,
.case__shotlink:focus-visible img { opacity: 1; }

.case__shotfig figcaption {
  margin-top: 12px;
  font-family: var(--font-secondary);
  font-size: 12px;
  line-height: var(--lh-xl);
  color: var(--text-muted);
}

/* ---------- the overlay ----------
   A native <dialog>: the focus trap, Escape, and the inert background behind
   it come from the browser, not from code we would have to keep correct. */

.shots {
  width: min(1180px, 94vw);
  max-height: 92vh;
  /* iOS Safari resolves vh against the LARGE viewport — the one with the
     URL bar retracted — so with the bars showing a 92vh box runs under
     them. dvh tracks the viewport that is actually visible. The vh line
     above stays as the fallback for engines without dvh. */
  max-height: 92dvh;
  padding: 0;
  border: 1px solid var(--white-100);
  border-radius: var(--radius-lg);
  background: var(--black);
  color: var(--white);
  overflow: hidden;
}

.shots::backdrop {
  background: rgba(0, 0, 0, .8);
  backdrop-filter: blur(6px);
}

.shots__body {
  max-height: 92vh;
  /* iOS Safari resolves vh against the LARGE viewport — the one with the
     URL bar retracted — so with the bars showing a 92vh box runs under
     them. dvh tracks the viewport that is actually visible. The vh line
     above stays as the fallback for engines without dvh. */
  max-height: 92dvh;
  padding: clamp(20px, 3vw, 36px);
  /* The close button floats over this box, so the content has to start below
     it or the first screenshot wears a × through its top-right corner. That
     corner is where a dashboard puts its date range and totals, and on a wide,
     short screenshot the 40px button covers a third of the image's height. */
  padding-top: 62px;
  overflow-y: auto;
  display: grid;
  gap: clamp(24px, 3vw, 40px);
}

.shots__fig { margin: 0; }

.shots__fig img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--white-100);
  border-radius: var(--radius-md);
}

.shots__fig figcaption {
  margin-top: 12px;
  font-family: var(--font-secondary);
  font-size: 13px;
  line-height: var(--lh-xl);
  color: var(--text-muted);
}

.shots__full {
  display: inline-block;
  margin-top: 8px;
  font-family: var(--font-secondary);
  font-size: 13px;
  color: var(--white);
  text-decoration: underline;
  text-decoration-color: var(--white-400);
  text-underline-offset: 4px;
  transition: text-decoration-color .25s;
}

.shots__full:hover,
.shots__full:focus-visible { text-decoration-color: currentColor; }

.shots__close {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 1;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--white-100);
  border-radius: 50%;
  background: rgba(13, 13, 13, .82);
  backdrop-filter: blur(8px);
  color: var(--white);
  font: 400 22px/1 var(--font-secondary);
  cursor: pointer;
  transition: background-color .2s, border-color .2s;
}

.shots__close:hover { background: var(--black); border-color: var(--border-1); }

/* On a phone every pixel of width is a pixel of a 1600px-wide dashboard, so
   the overlay hands the screenshot as much of the viewport as it can get. The
   preview is still only an index of what the shot says — "Open full size" is
   the way to actually read it — but it should not be smaller than it has to be. */
@media (max-width: 767px) {
  /* The UA stylesheet caps a dialog at calc(100% - 6px - 2em), which on a
     375px phone is 337px however wide we ask for. Override it or the width
     above does nothing. */
  .shots { width: 96vw; max-width: 96vw; }
  .shots__body {
    padding-left: 14px;
    padding-right: 14px;
    padding-bottom: 20px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .case__proof,
  .case__shotlink,
  .case__shotlink img,
  .shots__close,
  .shots__full { transition: none; }
  .case__shotlink:hover { transform: none; }
}
