/* ============================================================
   Carousel slide layouts. Every family here is built only from the
   tokens in base.css / themes.css, so a layout works on any ground.
   ============================================================ */

/* Full-bleed photo cover: photo, scrim, content stacked above it. */
.lay-full { padding: 0; }
.lay-full .overlay { position: absolute; inset: 0; z-index: 2; padding: 88px; display: flex; flex-direction: column; }

/* Split: photo on one side, copy on the other. */
.lay-split { padding: 0; flex-direction: row; }
.lay-split .half-img { width: 46%; position: relative; }
.lay-split .half-img .img { position: absolute; inset: 0; border-radius: 0; }
.lay-split .half-txt { flex: 1; padding: 88px 72px; display: flex; flex-direction: column; }
.lay-split.rev { flex-direction: row-reverse; }

/* Photo band across the top or bottom. */
.band-img { position: relative; height: 46%; margin: -88px -88px 56px; }
.band-img .img { position: absolute; inset: 0; border-radius: 0; }
.band-img.bottom { margin: 56px -88px -88px; }

/* Giant statistic. */
.stat-hero { font-size: 260px; font-weight: 500; line-height: 0.84; letter-spacing: -0.05em; color: var(--accent); }
.stat-hero.ink { color: var(--ink-1); }
.stat-sub { font-size: 30px; color: var(--ink-2); line-height: 1.4; }

/* Numbered rows. */
.num-row { display: flex; gap: 32px; align-items: flex-start; padding: 30px 0; border-bottom: 1px solid var(--line); }
.num-row:last-child { border-bottom: 0; }
.num-row .n { font-size: 46px; font-weight: 500; letter-spacing: -0.03em; color: var(--accent); min-width: 92px; line-height: 1; }
.num-row .t { font-size: 32px; font-weight: 500; letter-spacing: -0.02em; color: var(--ink-1); line-height: 1.2; }
.num-row .b { font-size: 24px; color: var(--ink-2); line-height: 1.45; margin-top: 10px; }

/* Ticked list. */
.tick-list { display: flex; flex-direction: column; gap: 26px; }
.tick-row { display: flex; gap: 22px; align-items: flex-start; font-size: 29px; line-height: 1.35; color: var(--ink-2); }
.tick-row::before {
  content: ""; flex: 0 0 auto; width: 30px; height: 30px; margin-top: 6px;
  border-radius: var(--radius-circle); background: var(--accent);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/22px no-repeat, linear-gradient(#000,#000);
  -webkit-mask-composite: destination-out; mask-composite: exclude;
}

/* Timeline / phases. */
.tl-row { display: flex; gap: 36px; padding: 28px 0; border-bottom: 1px solid var(--line); }
.tl-row:last-child { border-bottom: 0; }
.tl-row .day { font-size: 21px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-text); min-width: 190px; padding-top: 8px; }
.tl-row .t { font-size: 31px; font-weight: 500; letter-spacing: -0.02em; color: var(--ink-1); }
.tl-row .b { font-size: 23px; color: var(--ink-2); line-height: 1.45; margin-top: 8px; }

/* Spec table. Carries the case-study facts: scope, stack, timeline. */
.spec-row { display: flex; justify-content: space-between; align-items: baseline; gap: 28px; padding: 24px 0; border-bottom: 1px solid var(--line); }
.spec-row:last-child { border-bottom: 0; }
.spec-row .k { font-size: 20px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); }
.spec-row .v { font-size: 28px; font-weight: 500; letter-spacing: -0.015em; color: var(--ink-1); text-align: right; }

/* Quote. */
.quote-c { font-size: 56px; font-weight: 500; line-height: 1.16; letter-spacing: -0.03em; color: var(--ink-1); text-wrap: balance; }
.quote-mark { font-size: 150px; line-height: 0.6; color: var(--accent); font-weight: 500; }
.quote-by { font-size: 23px; color: var(--ink-3); letter-spacing: 0.06em; text-transform: uppercase; }

/* Card grids. */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 28px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.grid-2-3 { display: grid; grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(3, 1fr); gap: 22px; }
.mini { display: flex; flex-direction: column; gap: 12px; }
.mini .t { font-size: 30px; font-weight: 500; letter-spacing: -0.02em; color: var(--ink-1); }
.mini .b { font-size: 22px; color: var(--ink-2); line-height: 1.4; }
.mini .n { font-size: 21px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-text); }

/* Before / after. */
.cmp { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; flex: 1; }
.cmp .side { display: flex; flex-direction: column; gap: 20px; padding: 40px; border-radius: var(--wx8-r-card); border: 1px solid var(--line); }
.cmp .side.was { background: transparent; }
.cmp .side.now { background: var(--card-bg); }
.cmp .side .lbl { font-size: 20px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); }
.cmp .side.now .lbl { color: var(--accent-text); }
.cmp .side .li { font-size: 25px; line-height: 1.4; color: var(--ink-2); padding: 14px 0; border-bottom: 1px solid var(--line); }
.cmp .side .li:last-child { border-bottom: 0; }

/* Photo gallery strip. */
.gal-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.gal-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.gal-hero { display: grid; grid-template-columns: 2fr 1fr; gap: 18px; }

/* Device mock: a browser chrome frame around a screenshot or photo. */
.device { border-radius: var(--wx8-r-card); overflow: hidden; border: 1px solid var(--line); background: var(--card-bg); display: flex; flex-direction: column; }
.device .bar { display: flex; align-items: center; gap: 10px; padding: 18px 22px; border-bottom: 1px solid var(--line); }
.device .bar i { width: 13px; height: 13px; border-radius: var(--radius-circle); background: var(--ink-3); opacity: 0.5; }
.device .bar .addr { flex: 1; height: 26px; border-radius: var(--wx8-r-pill); background: var(--line); margin-left: 12px; }
.device .screen { flex: 1; position: relative; }
.device .screen .img { position: absolute; inset: 0; border-radius: 0; }

/* Swatch strip for palette / logo work. */
.swatches { display: flex; gap: 0; border-radius: var(--wx8-r-card); overflow: hidden; }
.swatches .sw { flex: 1; height: 150px; display: flex; align-items: flex-end; padding: 16px; font-size: 17px; font-weight: 600; letter-spacing: 0.06em; }

/* ============================================================
   Vertical fill.

   A 1080x1350 slide is much taller than the copy that goes on it, so a list
   left to its natural height stacks against the header and leaves a third of
   the slide empty. These two helpers hand the leftover height back to the rows
   themselves: the block claims the space between header and footer, and each
   row takes an equal share of it and centres its content.
   ============================================================ */
.block { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.block > .head-copy { flex: 0 0 auto; }

.list-fill { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.list-fill > .num-row,
.list-fill > .tl-row,
.list-fill > .spec-row { flex: 1; align-items: center; }
/* The row divider is a bottom border, so the last row must not draw one even
   once the rows are stretched. */
.list-fill > *:last-child { border-bottom: 0; }

.tick-list.list-fill { justify-content: space-evenly; }
.tick-list.list-fill .tick-row { flex: 0 0 auto; }

/* Compare columns: label pinned, statements share what is left. */
.cmp .side { min-height: 0; }
.cmp .side .lbl { flex: 0 0 auto; }
.cmp .side .li { flex: 1; display: flex; align-items: center; }

.grid-2.fill, .grid-3.fill, .grid-2-3.fill { flex: 1; min-height: 0; }
.gal-2.fill, .gal-3.fill { flex: 1; min-height: 0; }
/* Same for a lone photo asked to take the remaining room. Without this the
   box has no flex and no intrinsic height, so it renders at zero. */
.img.fill { flex: 1; min-height: 0; }

/* The quote mark is decorative, so it is sized and nudged by eye rather than
   left to the font's own metrics. */
.quote-mark { display: block; height: 84px; font-size: 190px; }

/* The hero statistic is set at a size that suits "3 steps" or "16px". Word
   values like "One source" or "0 surprises" run past the slide edge at that
   size, so the renderer steps the size down by character count. */
.stat-hero          { word-break: normal; overflow-wrap: break-word; }
.stat-hero--md      { font-size: 176px; line-height: 0.9; letter-spacing: -0.045em; }
.stat-hero--sm      { font-size: 124px; line-height: 0.95; letter-spacing: -0.04em; }
.post .stat-hero    { font-size: 210px; }
.post .stat-hero--md { font-size: 148px; }
.post .stat-hero--sm { font-size: 104px; }

/* ============================================================
   Extended layout families.

   The first pass shipped sixteen families and rotated six slide sequences
   across forty-two case studies, so seven decks shared each composition. These
   exist so every deck can be assembled from a different set.
   ============================================================ */

/* Full-bleed: photo behind, chrome and copy above it. */
.lay-bleed { }
.lay-bleed--top { }

/* Photo held inside a margin, copy overlapping its lower edge. */
.inset-photo { position: relative; height: 58%; margin: 12px -24px 0; }
.inset-photo .img { position: absolute; inset: 0; border-radius: var(--wx8-r-panel); }
.inset-copy { background: var(--bg-page); padding: 34px 34px 0 0; margin-top: -70px; position: relative; z-index: 3; max-width: 88%; }

/* A diagonal slice of photography across the upper half. */
.diag { position: absolute; inset: 0 0 34% 0; overflow: hidden; clip-path: polygon(0 0, 100% 0, 100% 74%, 0 100%); }
.diag .img { position: absolute; inset: 0; border-radius: 0; }
.diag .img::after { background: rgba(11,11,11,0.22); }

.img.arch { border-radius: 999px 999px 0 0; width: 62%; height: 52%; }

/* A thick accent border doing the framing instead of a hairline. */
.acc-frame { position: relative; border: 14px solid var(--accent); min-height: 0; }
.acc-frame .img { position: absolute; inset: 0; border-radius: 0; }

.corner-photo { position: absolute; inset-block-end: 0; inset-inline-end: 0; width: 54%; height: 46%; }
.corner-photo .img { position: absolute; inset: 0; border-radius: var(--wx8-r-panel) 0 0 0; }

.mosaic-bg { position: absolute; inset: 0; display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
.mosaic-bg .img { border-radius: 0; }
.mosaic-scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(11,11,11,0.42) 0%, rgba(11,11,11,0.88) 74%); }

.photo-strip { position: relative; height: 26%; margin: 12px -88px 0; }
.photo-strip .img { position: absolute; inset: 0; border-radius: 0; }

/* Outlined display type, for slides where a solid fill would be too heavy. */
.outline-type {
  color: transparent; -webkit-text-stroke: 3px currentColor;
  /* text-stroke paints from `color`, which is transparent here, so the stroke
     colour has to come from the parent's ink instead. */
  -webkit-text-fill-color: transparent; -webkit-text-stroke-color: var(--ink-1);
}
.s--orange .outline-type { -webkit-text-stroke-color: #fff; }
.edge-type { font-size: 118px; line-height: 0.94; }
.bigtype { font-size: 132px; line-height: 0.94; }

.lay-split.third .half-img { width: 34%; }
.band-img.bottom { margin: 40px -88px -88px; }

/* ── List numerals ── */
.nm { font-size: 46px; font-weight: 500; letter-spacing: -0.03em; color: var(--accent); min-width: 96px; line-height: 1; flex: 0 0 auto; }
.nm.big { font-size: 78px; min-width: 128px; }
.nm.sm { font-size: 21px; font-weight: 600; letter-spacing: 0.14em; min-width: 0; color: var(--accent-text); }
.num-row.bignum .nm { font-size: 96px; min-width: 168px; opacity: 0.85; }
.nsm { font-size: 21px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-text); }

.stack-row { display: flex; flex-direction: column; gap: 10px; padding: 24px 0; border-bottom: 1px solid var(--line); justify-content: center; }
.stack-row:last-child { border-bottom: 0; }
.stack-row .t { font-size: 32px; font-weight: 500; letter-spacing: -0.02em; color: var(--ink-1); line-height: 1.15; }
.stack-row .b { font-size: 23px; color: var(--ink-2); line-height: 1.45; }
.stack-row .k { font-size: 20px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); }
.v-stack { font-size: 34px; font-weight: 500; letter-spacing: -0.02em; color: var(--ink-1); line-height: 1.1; }

/* Horizontal step track with a rule running through the pips. */
.steps-track { display: flex; gap: 20px; align-items: stretch; min-height: 0; }
.steps-track .step { flex: 1; display: flex; flex-direction: column; gap: 14px; padding-top: 46px; position: relative; }
.steps-track .step::before { content: ""; position: absolute; top: 21px; left: 0; right: -20px; height: 1px; background: var(--line); }
.steps-track .step:last-child::before { right: 0; }
.steps-track .pip {
  position: absolute; top: 0; left: 0; width: 44px; height: 44px; border-radius: var(--radius-circle);
  background: var(--accent); color: var(--on-accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 17px; font-weight: 600; letter-spacing: 0.04em;
}
.steps-track .step .t { font-size: 27px; font-weight: 500; letter-spacing: -0.02em; color: var(--ink-1); line-height: 1.15; }
.steps-track .step .b { font-size: 20px; color: var(--ink-2); line-height: 1.45; }

/* Asymmetric photo mosaic: one tall frame plus two stacked. */
.gal-mosaic { display: grid; grid-template-columns: 1.5fr 1fr; grid-template-rows: 1fr 1fr; gap: 18px; }
.gal-mosaic .a { grid-row: span 2; }

/* Quote with a thick accent bar on the leading edge. */
.quote-bar { border-inline-start: 10px solid var(--accent); padding-inline-start: 44px; }

/* Compare, stacked variant: the statements run as a wrapped row. */
.side .li { }
.compare-stack .side { padding: 32px; }

/* ── Stacking ──
   Decorative layers (photo backdrops, diagonal slices, mosaics, corner blocks)
   are absolutely positioned, and an absolute element paints above its
   non-positioned siblings. Without this the mosaic cover buried its own
   headline. Content gets a positioned context above them; the decoration is
   pinned to the bottom of the slide's stack. */
/* The exclusion list matters. An earlier version used a bare `.s > *`, which
   at equal specificity landed after the layers' own rules and reset their
   `position: absolute` to relative, collapsing the mosaic and the diagonal to
   zero height. Only content is given a stacking context here.

   .ch-rail joined the list on 2026-08-27. It is `position: absolute` with
   `inset-block: 0` so the rail runs the full height of the surface, but this
   selector carries seven :not() classes and outranked it, forcing it back to
   relative. The rail then collapsed to the height of its own rotated counter
   and sat in the flex column, so the counter overlapped the content beneath
   it. The rail chrome had never rendered correctly. */
.s > *:not(.img-full):not(.streaks):not(.mosaic-bg):not(.mosaic-scrim):not(.diag):not(.corner-photo):not(.inset-photo):not(.ch-rail) {
  position: relative; z-index: 2;
}
.s > .img-full, .s > .streaks, .s > .mosaic-bg, .s > .diag,
.s > .corner-photo, .s > .inset-photo { z-index: 0; }
.s > .mosaic-scrim { z-index: 1; }
