/* ==========================================================================
   case.css — per-block type and layout for the Help Me Choose case

   Forked from av-restricted-content/case.css, which is the closer of the two
   Apple pages structurally: same section rhythm, same components. The block
   system in styles/ does the layout; this file only names the per-block type
   scale and the components both Apple cases need that Banco Inter didn't
   (option cards, metric grid, process map, prototype frame).

   Kept wholesale rather than trimmed to what this page uses today. The case is
   text-first while the writing settles and the asset slots fill in, and every
   component here has a slot waiting for it in index.html.

   Font sizes are in `em` against the 10px root — see base.css.
   ========================================================================== */

.page.project {
  --page-background: #000;
  --nav-height: 124px;

  /*
   * Same blue as the Restricted Content case, on purpose: both are Apple, and
   * two different accents across two Apple pages would read as two different
   * clients.
   */
  /* Sampled off the upper third of 00-cover.jpg, which is what the cover
     actually shows: a lit store ceiling and wall. Warm, very light, so the band
     before the photo decodes reads as the same room rather than as a hole. */
  --s-cover: #f2eeec;
  /* Apple's marketing blue. White on it measures 4.70:1, which clears AA for
     body text as well as for the headline. #0a84ff, the iOS system blue this
     case uses for links, only reaches 3.65:1 and would be large-text-only. */
  --s-accent: #0071e3;
  --case-accent: #0a84ff;
}

/*
 * The prev/next nav and the footer sit below the last block, on the black page
 * background, so they take a light ink.
 */
.page.project .project-nav,
.page.project footer {
  --color: #e2e2e2;
  --nav-link-color: #e2e2e2;
}

/*
 * Dark ink over this cover, the same as the Restricted Content case.
 *
 * The photograph is anchored `bottom`, which keeps the hands and the phone in
 * frame and gives up the lit ceiling that used to sit behind the nav for free.
 * What the nav band lands on now moves with viewport height — 13% down the
 * frame on a tall window, 57% on a short one — and anywhere under about 1000px
 * tall that band catches the blond head and the navy shirt. Averaged it still
 * looks fine, 19.2:1 at best and 5.3:1 at worst; per pixel it collapses to
 * 1.15:1, and a nav link crossing a strand of dark hair is unreadable at
 * exactly that strand.
 *
 * So the scrim below does the work instead, and the ink stays black.
 */
.page.project > .navigation {
  --color: #000;
  --nav-link-color: #000;
}

/* --- cover scrim -------------------------------------------------------- */
/*
 * A white wash over the top of the hero, sitting above the photograph and below
 * the nav. It exists solely so the anchor can be `bottom`.
 *
 * The alphas are measured, not guessed. Black text needs a background near
 * L 0.175 to clear 4.5:1, which is about sRGB 116; the darkest hair that rises
 * into the nav band is very nearly sRGB 0, so white has to be laid over it at
 * about 0.46 to get there. Sweeping the whole nav band at every viewport height
 * from 1000px down to 480px, 0.62 falling to 0.50 across the band is the first
 * pair that clears AA everywhere, at a worst case of 5.32:1. The pair that was
 * here first, 0.55 to 0.35, reached only 3.04:1.
 *
 * It is invisible in practice. The top of this frame is a pale wall whichever
 * way the crop falls, and white over near-white changes nothing; the wash only
 * declares itself where something dark rises into the band, which is the only
 * place it is wanted.
 *
 * 320px, not 124px. Ending it exactly at the foot of the nav would draw a hard
 * horizontal edge across the photograph; running it well past and easing out
 * makes it read as light in the room.
 */
.page.project .block.cover .cover-scrim {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  z-index: 1;
  height: 320px;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.62) 0,
    rgba(255, 255, 255, 0.5) 124px,
    rgba(255, 255, 255, 0.22) 210px,
    rgba(255, 255, 255, 0) 100%
  );
}

/* --- cover height ------------------------------------------------------ */
/*
 * Short of the viewport on purpose. A cover that fills the screen exactly
 * gives a reader no reason to believe there is anything under it; leaving the
 * next band's edge showing is the affordance.
 */

.page.project {
  --cover-height: 86vh;
}

/* --- scroll reveal ------------------------------------------------------ */
/*
 * base.css reveals every `.block > .content` as one object: 50px of lift over
 * 500ms. Right for the Banco Inter port, which has to match the original, but
 * on this page it reads as a section switching on all at once.
 *
 * Here the block stops moving and its ROWS move instead, one after another, in
 * document order: the headline, then each subsection title, then each
 * paragraph, then each list item or figure. scripts/reveal-rows.js numbers
 * them into `--row`; everything below is the timing.
 *
 * `cubic-bezier(.16,1,.3,1)` is the near-exponential ease-out — most of the
 * distance is covered immediately and the last pixels settle slowly, which is
 * what lets a 24px move read as deliberate rather than twitchy.
 *
 * All of it is scoped under `html.reveal-rows`, a class the script adds only
 * once it has indexed something. Without the script none of this applies and
 * base.css's block-level reveal is what runs.
 */

.reveal-rows .page.project .block.animated > .content {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: none;
}

.reveal-rows .page.project .block.animated [data-row] {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity 720ms cubic-bezier(0.16, 1, 0.3, 1),
    transform 900ms cubic-bezier(0.16, 1, 0.3, 1);
}

/*
 * 130ms a row. Below about 100 the rows blur into one event; above about 160
 * the reader catches up with the animation and waits for it. The 90ms lead-in
 * keeps the first row from firing on the same frame the block is triggered,
 * which is what made the old version feel abrupt.
 */
.reveal-rows .page.project .block.animated.is-revealed [data-row] {
  opacity: 1;
  transform: none;
  transition-delay: calc(90ms + var(--row, 0) * 130ms);
}

/*
 * Decoration, all of it. Without this the page would sit at opacity 0 for
 * anyone who asked for less movement, since the rows never get the class that
 * brings them back.
 */
@media (prefers-reduced-motion: reduce) {
  .reveal-rows .page.project .block.animated [data-row] {
    opacity: 1;
    transform: none;
    transition: none;
    transition-delay: 0s;
  }
}

/* --- inline code ------------------------------------------------------- */
/*
 * The case leans on literal strings — opaque IDs, `001.mov`. Sized in `em`
 * against the surrounding copy and nudged up, because browsers otherwise apply
 * their own smaller default size to any monospace family and the numerals fall
 * out of the line.
 */

code {
  padding: 0.12em 0.32em;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.05);
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 0.92em;
  /* Overrides `.block`'s `word-break: break-word`: these literals are short
     and a broken `001.mov` reads as two things. */
  word-break: normal;
  white-space: nowrap;
}

/* --- client mark -------------------------------------------------------- */
/*
 * `.media > img` in blocks.css positions and sizes the image inside the
 * aspect-ratio well; the rule does not reach an inline `<svg>`, so the mark
 * needs the same treatment stated here or it collapses to nothing.
 */
.block.logo-block .logo-grid .media > svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/*
 * Two things the shared `logo-grid` does that are right for a wordmark and
 * wrong for a glyph.
 *
 * It centres each mark in its column (`.media` carries `margin: 0 auto`), which
 * for a 480px-wide logo in a 1100px grid is barely a shift and for a 39px mark
 * puts it adrift in the middle of nothing. Flush left instead, on the same edge
 * as the ROLES column directly beneath it.
 *
 * And it forces a 1:1 well. The Apple mark is 19.55 x 24, so a square well
 * letterboxes it and the left edge of the glyph lands inside the left edge of
 * the box — which is exactly the alignment being asked for here. The well takes
 * the mark's own ratio instead, and the two edges become one.
 */
.block.logo-block .logo-grid .client-mark {
  margin-left: 0;
  aspect-ratio: 1955 / 2400;
  max-width: 39px;
}

/* --- project meta + summary -------------------------------------------- */

.block.meta {
  --label-size: 1.7em;
  --label-leading: 1.51;
  --label-weight: 400;
  --body-size: 2.3em;
  --body-leading: 1.49;
}

.block.meta .meta-list dt {
  color: var(--label-color);
  font-weight: 600;
}

.block.meta .meta-list dd {
  margin: 0;
}

.block.meta .meta-list dd + dt {
  margin-top: 1.51em;
}

/*
 * The summary runs to two paragraphs here (Banco Inter's is one), and this
 * column is not `.rich`, so it has no paragraph rhythm of its own. One blank
 * line box, which at this block's leading is 1.49em.
 */
.block.meta .col-body p + p {
  margin-top: 1.49em;
}

/* --- try it yourself ---------------------------------------------------- */
/*
 * The one link in body copy anywhere on the site, so it gets a rule rather
 * than inheriting one. It points at the live tool, which is the strongest
 * evidence this case has and the only piece of it a reader can verify without
 * taking anyone's word.
 *
 * Set in the case accent rather than underlined: at this block's size an
 * underline under a 2.3em line reads as a correction. `--case-accent` is the
 * iOS system blue, which is large-text-only against white at 3.65:1 — fine
 * here, where the link is one 2.3em line and never body-sized prose.
 *
 * A full blank line above it, plus a little, so it reads as a separate
 * gesture rather than a fourth paragraph.
 */
.block.meta .col-body .try-it {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4em;
  margin-top: 1.9em;
  color: var(--case-accent);
  font-weight: 600;
  text-decoration: none;
}

/* The arrow travels on hover, the same gesture the reading bar's CTA makes.
   `inline-block` because `transform` does nothing to an inline box. */
.block.meta .col-body .try-it .arrow {
  display: inline-block;
  transition: transform 0.24s cubic-bezier(0.4, 0, 0.2, 1);
}

.block.meta .col-body .try-it:hover .arrow {
  transform: translateX(0.22em);
}

@media (prefers-reduced-motion: reduce) {
  .block.meta .col-body .try-it .arrow {
    transition: none;
  }
}

/* ==========================================================================
   A note on units, because it bites

   `.block.intro .col-body` sets `font-size: 1.7em` — 17px against the 10px
   root. Everything below lives inside that column, so its `em`s are relative
   to 17px, NOT to the root. A component written as `1.7em` in here renders at
   28.9px, not 17px.

   So: components that should read as body copy declare no font-size at all and
   inherit the column's, and anything that needs a different size is expressed
   as a multiple of 17px (0.94em = 16px, 2.6em = 44px).

   The exceptions are `.asset-caption` and the slot wells, which sit in
   `.block.fluid > .content` where no font-size is set — there an `em` is a root
   `em` and reads as "× 10px", like the rest of the site.
   ========================================================================== */

/* --- section headline column ------------------------------------------- */
/*
 * blocks.css splits `.intro` into four equal columns and gives the headline
 * one of them: 255px at this grid, minus the 20px gutter, so 235px of measure.
 * "The Process" and "The Problem" needed a hard <br> to fit that, which is a
 * markup workaround for a column 40px too narrow.
 *
 * 290px removes the need for the break and costs the body column 35px, which
 * is well inside the measure it wants. `:not(.stacked)` because the stacked
 * blocks run their headline across the whole grid and must keep one column.
 */

.block.intro:not(.stacked) > .content {
  grid-template-columns: 290px repeat(3, 1fr);
}

/* --- the problem ------------------------------------------------------- */
/*
 * One sentence, at the largest body size on the page. It is set a step above
 * Design Challenge because it is the shorter of the two and lands first: the
 * problem is the claim the case rests on, so it gets the whole column and
 * nothing else.
 *
 * Everything that explains it — what the system is, how the old process ran,
 * what hurt — belongs in Context, above. If this block grows past three lines,
 * the copy has drifted back into background and should move up.
 */

.block.problem .col-body {
  --body-size: 2.6em;
  --body-leading: 1.5;
}

/*
 * On a phone, blocks.css clamps every `.col-body` to `4vw` — 15.6px at 390px,
 * which is the same size as ordinary body copy. Banco Inter's Design Challenge
 * renders that way and stays that way, because that page is a faithful port.
 * Here it defeats the point: a one-sentence display statement that reads at
 * body size is just a short paragraph. So the Problem gets its own ceiling,
 * still fluid, just a larger fraction of the viewport.
 */
@media (max-width: 768px) {
  .block.problem .col-body {
    font-size: clamp(1em, 2.6em, 6.4vw);
  }
}

/* --- the process ------------------------------------------------------- */
/*
 * The design challenge lives inside this section now, as its first `h4`, so
 * this block is ordinary rich text rather than the display statement it used
 * to be. 1.8em is a shade above the 1.7em body default, which is what the
 * section carried before and what keeps it distinct from Context above it.
 */

.block.process .col-body {
  --body-size: 1.8em;
}

/* --- stacked intro ----------------------------------------------------- */
/*
 * Headline across the full grid with its paragraph beneath, instead of the
 * label-column / body-column split every other `.intro` block uses. For a
 * section whose title is a statement in its own right rather than a filing
 * label.
 *
 * Built as a modifier on `.intro` rather than a plain block so the headline
 * keeps `--label-size` and the paragraph keeps `--body-size`; dropping `intro`
 * would mean restating both. The mobile rules in blocks.css already collapse
 * `.intro` to one column, so nothing here needs a breakpoint.
 */

.block.intro.stacked > .content {
  grid-template-columns: 1fr;
}

.block.intro.stacked .col-label,
.block.intro.stacked .col-body {
  grid-column: 1;
  padding-right: 0;
}

.block.intro.stacked .col-label {
  margin-bottom: 24px;
}

/*
 * No measure cap: when the headline runs the full grid the paragraph does too,
 * so the two share one left and right edge. That does mean a long line, so keep
 * the copy in these blocks to two or three sentences.
 */

/* --- process roadmap --------------------------------------------------- */
/*
 * The three-phase diagram under The Process, standing in for the exported
 * roadmap image the Banco Inter case uses. Built in markup rather than as an
 * <svg> on purpose: SVG <text> does not wrap, so a three-up diagram of
 * sentences cannot reflow to one column on a phone without shipping a second
 * copy of itself — and its copy would be invisible to the in-page editor.
 *
 * It sits in a plain `.block`, not an `.intro` one, so `.content` is the full
 * 1100px grid and an `em` here is a root em (× 10px) like the rest of the site.
 *
 * The 2px top rule per stage is the diagram: three equal bars reading left to
 * right as a timeline.
 */

.process-map {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 48px 34px;
}

.process-map .stage {
  border-top: 2px solid var(--color);
  padding-top: 16px;
}

.process-map .stage-num {
  display: block;
  font-size: 1.2em;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--numeral-color);
}

.process-map .stage-title {
  margin-top: 8px;
  font-size: 1.9em;
  line-height: 1.25;
  font-weight: 600;
}

.process-map .stage-desc {
  margin-top: 12px;
  font-size: 1.5em;
  line-height: 1.5;
}

/*
 * A stage that runs to two paragraphs — only Validation, which is two separate
 * rounds and reads wrong as one block. A full blank line box, against the 12px
 * that separates the first paragraph from the title above it, so the break
 * inside the card is bigger than the break at its head.
 */
.process-map .stage-desc + .stage-desc {
  margin-top: 1.5em;
}

/*
 * Phase four is a full-width row beneath the three columns: eyebrow and title
 * on one line, then the paragraph running the whole grid. It was a 1fr/2fr
 * split first, which put the paragraph's left edge under phase 02 and made it
 * read as belonging to phases 2 and 3 rather than following all three.
 *
 * It stays secondary through the dashed rule, the "THEN" eyebrow and a smaller
 * title — NOT through colour. The first version set the whole row in
 * `--label-color`, which is #999 and measures 2.85:1 on white; that is under
 * the 4.5:1 floor for body text, and it is why the paragraph read as absent
 * rather than as de-emphasised.
 */
.process-map .stage-aside {
  grid-column: 1 / -1;
  display: block;
  border-top: 1px dashed rgba(0, 0, 0, 0.24);
}

/* The eyebrow stacks above the title, same as the three phases; only the
   title's size marks this one as secondary. */
.process-map .stage-aside .stage-title {
  font-size: 1.7em;
}

/*
 * Validation on this page borrows the aside's full-width row but NOT its
 * demotion. It is step 06 of six, not a coda: the dashed rule and the smaller
 * title were there to say "this follows the phases", and here they would say
 * "this matters less", which is the opposite of true. The 18% comes out of
 * this step.
 *
 * So: same solid 2px rule and same title size as the five cards above it, and
 * only the full-width row is inherited.
 */
.process-map .stage-aside.stage-step {
  border-top: 2px solid var(--color);
  padding-top: 16px;
}

.process-map .stage-aside.stage-step .stage-title {
  font-size: 1.9em;
}

/* Held to a readable measure rather than the full 1100px. */
.process-map .stage-aside .stage-desc {
  max-width: 84ch;
}

@media (max-width: 768px) {
  .process-map {
    grid-template-columns: 1fr;
    gap: 32px 0;
  }
}

/* --- a section's opening line ------------------------------------------ */
/*
 * One sentence that introduces the section under its own label, a step down
 * from Problem and Challenge. Used on Explorations.
 */

.block.lead .col-body {
  --body-size: 2.5em;
  --body-leading: 1.66;
}

/* --- option cards: the alternatives considered ------------------------- */
/*
 * Four candidate answers to the same question, three of them rejected. Laid
 * out as a rule-separated list rather than as boxes: they're read in sequence
 * and compared, and boxes would imply they're browsable in any order.
 */

/* Body size is inherited from `.col-body` — see the note on units above. */
.options {
  line-height: 1.61;
}

.options > li {
  padding: 32px 0;
  border-top: 1px solid rgba(0, 0, 0, 0.1);
}

.options > li:last-child {
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}

.options .option-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}

.options .option-id {
  font-size: 0.71em;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--label-color);
}

.options .option-title {
  font-size: 1.24em;
  line-height: 1.3;
  font-weight: 600;
  margin-bottom: 0.5em;
}

.options p + p {
  margin-top: 0.8em;
}

/* "Why not —" / "Why this —": the sentence a reviewer is actually looking for,
   so the lead-in is set in the label grey and the rest reads as body. */
.options .option-why strong {
  color: var(--label-color);
  font-weight: 600;
}

/* --- messy-parts highlight cards --------------------------------------- */
/*
 * `.block.columns` already gives the two-up grid, the image well and the
 * kicker/caption rhythm (blocks.css). These cards add a second and sometimes
 * third caption under the first, so the 1.5em `padding-top` that separates a
 * caption from its image would triple-space them.
 */

/*
 * The highlight cards carry no title: the image is the subject, and each half
 * of the caption is introduced by a small eyebrow instead. Problem, then a gap,
 * then Solution.
 *
 * The eyebrow is the label grey, which is fine here in a way it was not for a
 * card title — it labels the paragraph rather than carrying its meaning, and
 * the paragraph itself is body ink.
 */
/*
 * Half the gap blocks.css puts between the image and its caption: 20px of
 * margin plus 1.5em of padding read as a break between two things, and these
 * two are one card. 10px + 0.75em lands at about 23px.
 */
.block.columns .caption-group {
  margin-top: 10px;
}

.block.columns .caption {
  padding-top: 0.75em;
}

.block.columns .caption .eyebrow {
  display: block;
  margin-bottom: 0.35em;
  font-size: 0.71em;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--label-color);
}

/* The gap between the problem and the solution: one blank line box plus a
   little, so the two read as a pair rather than as one run of text. */
.block.columns .caption + .caption {
  padding-top: 1.7em;
}

/* --- verdict chips ----------------------------------------------------- */

.verdict {
  padding: 4px 9px;
  border-radius: 100px;
  font-size: 0.65em;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}

.verdict.rejected {
  border: 1px solid rgba(0, 0, 0, 0.16);
  color: var(--label-color);
}

.verdict.shipped {
  background: #1d1d1f;
  color: #fff;
}

/* --- tight lists inside rich text -------------------------------------- */
/*
 * `.rich .tight` is base.css's one-line-per-item numbered list — Context's key
 * pain points, and the three platform constraints in My Role. It sits between
 * paragraphs there, so it needs the same blank line above and below that
 * `.rich > * + *` gives everything else; base.css only zeroes the gaps
 * *between* the items.
 */

.rich > .tight {
  margin-top: var(--rhythm);
}

/* --- metric grid ------------------------------------------------------- */

.metric-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 40px 34px;
  margin-bottom: 48px;
}

/* 2.6em / 0.94em / 0.82em of the column's 17px = 44 / 16 / 14px. */
.metric-value {
  display: block;
  font-size: 2.6em;
  line-height: 1.1;
  font-weight: var(--title-weight);
  letter-spacing: -0.02em;
}

.metric-label {
  display: block;
  margin-top: 12px;
  font-size: 0.94em;
  line-height: 1.45;
  font-weight: 600;
}

.metric-note {
  display: block;
  margin-top: 4px;
  font-size: 0.82em;
  line-height: 1.45;
  color: var(--label-color);
}

/*
 * The four-across variant, used for the research figures under The Process. It
 * sits in a plain `.block` where an `em` is a root em, so it restates the 17px
 * body size the Impact grid inherits from its column — otherwise `.metric-value`
 * at 2.6em would render at 26px instead of 44px.
 */
/*
 * The band under The Shape of the Decision. Bigger numerals than the Impact
 * grid, because these are the point of their own section rather than a summary
 * at the foot of one.
 *
 * FOUR across, not the inherited three. The four figures are one sentence read
 * left to right — seven chip variants, twenty-six configurations, nineteen
 * attributes, eight questions — and a wrap after the third breaks the sentence
 * at its weakest join. Four fit: at 1100px that is 233px a column, and the
 * widest numeral here is two digits.
 *
 * It restates a 17px base because `.metric-grid`'s children are sized in em
 * against a body column, and this grid sits in a plain block that has none.
 */
.metric-grid.stats {
  grid-template-columns: repeat(4, 1fr);
  gap: 64px 28px;
  font-size: 1.7em;
}

.metric-grid.stats .metric-value {
  font-size: 3.8em;
  letter-spacing: -0.03em;
}

/*
 * Two-up before the phone breakpoint. Four columns of body copy under 900px
 * put the labels on three and four lines each; two rows of two hold the
 * reading order without shrinking the numerals.
 */
@media (max-width: 900px) {
  .metric-grid.stats {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* "6hrs" — the unit rides at the numeral's size class, not the numeral's. */
.metric-value .unit {
  margin-left: 0.06em;
  font-size: 0.44em;
  font-weight: 600;
  letter-spacing: 0;
}

@media (max-width: 768px) {
  .metric-grid {
    grid-template-columns: 1fr 1fr;
    gap: 32px 20px;
  }

  .metric-grid.stats {
    gap: 36px 20px;
  }

  .metric-grid.stats .metric-value {
    font-size: clamp(1em, 3.8em, 15vw);
  }

  .metric-value {
    font-size: clamp(1em, 2.6em, 11vw);
  }
}

/* --- the Details cards: stills that play on hover ----------------------- */
/*
 * Screen recordings of the live tool, one per card. They sit still until the
 * pointer arrives; scripts/hover-video.js drives playback and the dissolve at
 * the end of each run.
 *
 * `.media` already reserves the aspect ratio and positions its child absolutely
 * — that is what stops the grid reflowing while a poster decodes — but its rule
 * only reaches `> img`, so the video needs the same treatment stated here.
 *
 * `object-fit: cover`, not the `contain` that `.media > img` uses. These are
 * square recordings dropped into square wells, so there is nothing to letterbox
 * and cover guarantees no hairline of backdrop shows along an edge.
 */
.detail-video {
  overflow: hidden;
  border-radius: 18px;
  /* Under the video while it decodes, and the colour the veil fades to. */
  background: var(--dv-veil);
}

.detail-video > video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/*
 * The seam. A recording that cuts back to frame one reads as a glitch, so the
 * card dissolves into its own backdrop, resets behind that, and dissolves back
 * to the still.
 *
 * The grey is sampled off the recordings themselves (#f2f2f4 at their corners),
 * so what the card fades into is the colour it was already mostly made of.
 *
 * 380ms here has to stay in step with VEIL_FADE in scripts/hover-video.js.
 */
.detail-video {
  --dv-veil: #f2f2f4;
}

.detail-video-veil {
  position: absolute;
  inset: 0;
  background: var(--dv-veil);
  opacity: 0;
  pointer-events: none;
  transition: opacity 380ms cubic-bezier(0.33, 1, 0.68, 1);
}

.detail-video.is-veiled .detail-video-veil {
  opacity: 1;
}

/*
 * How far through a card is, as a hairline along its bottom edge.
 *
 * Drawn BEFORE the veil in the markup, so the dissolve at the end of a run
 * takes the bar with it. It resets to zero behind that grey and is already back
 * at the left when the still fades in, which is why the reset is never seen.
 *
 * A bar with no track. A track would draw a line across the bottom of a card
 * that is doing nothing, four times over, on a page where these are the only
 * moving things; the filled part alone says everything, and says nothing at all
 * when there is nothing to say.
 *
 * scaleX rather than width: it is a compositor-only property, so a bar that is
 * rewritten on every painted frame never touches layout.
 *
 * NO transition. An earlier version eased between `timeupdate` events, which
 * fire about four times a second, and the result stepped: 120ms of movement
 * then 130ms of nothing. scripts/hover-video.js now samples `currentTime` on
 * requestAnimationFrame instead, so the value arriving here is already correct
 * for this frame. Easing it again would only add lag.
 */
.detail-video-progress {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 3px;
  overflow: hidden;
  pointer-events: none;
}

.detail-video-progress > i {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--case-accent);
  transform: scaleX(var(--dv-progress, 0));
  transform-origin: left center;
}

/*
 * The cursor says "this does something" without claiming to be a link, which is
 * the same line the flowchart cards walk.
 */
@media (hover: hover) {
  .detail-video {
    cursor: default;
  }
}

@media (prefers-reduced-motion: reduce) {
  .detail-video-veil {
    transition: none;
  }
}

/* --- the question set diagram ------------------------------------------- */
/*
 * The eight questions as one picture: the gate at the top, four branches that
 * only one of which most people see all of, everything merging into the three
 * questions everybody answers, and the four result slots at the bottom.
 *
 * An <svg>, against this repo's usual preference for markup — see the note on
 * `.process-map`, which is deliberately NOT an svg so its copy stays editable
 * in the page. The tradeoff is taken knowingly here: a branch-and-merge shape
 * cannot be built from stacked divs without a pile of absolutely positioned
 * connectors, and the connectors ARE the content in this one. The cost is that
 * scripts/edit-mode.js cannot reach the labels; they are edited in the source.
 *
 * Colours are held in the variables below rather than written into the markup.
 * The svg carries seventy-odd fills and strokes; naming them once is the
 * difference between changing the diagram's palette in one place and changing
 * it in seventy.
 *
 * Apple's own drawing manners: hairline strokes, generous rounding, one accent,
 * and almost everything in greys so the single blue means something.
 */
.flowchart {
  /* Grey, not white. The band under the diagram is #f5f5f5, so a white card sat
     proud of it and every box read as a raised object; grey lets the cards
     belong to the surface and leaves the hairline border to do the separating.
     It also stops twelve rectangles competing with the one thing on this
     stretch of page that IS meant to look raised, the button underneath.

     Five points OVER the band, having come down from white through #ededef and
     #f2f2f4, both of which read as dull rather than quiet. Below the band the
     cards stop looking like paper on a surface and start looking switched off.
     This is the softest off-white that still holds light; there are only five
     points left between here and #fff. */
  --fc-card: #fafafa;
  --fc-chip: #f5f5f7;
  --fc-line: rgba(0, 0, 0, 0.14);
  /* Connectors are darker than card edges on purpose. A hairline is right for
     a box outline, which the eye reads as an edge; it is wrong for a line the
     eye has to FOLLOW, and in this diagram the connectors are the content. */
  --fc-wire: rgba(0, 0, 0, 0.32);
  /* Hover only. See the note on `.fc-node:hover`. */
  --fc-shadow: rgba(0, 0, 0, 0.06);
  --fc-ink: #1d1d1f;
  --fc-mute: #86868b;

  margin-top: 8px;
}

/*
 * The diagram has a floor below which the labels stop being readable, so on a
 * narrow screen it scrolls sideways rather than scaling into nothing. The
 * viewBox is 1800 wide; at a 1500px floor it never scales below 0.83, which
 * keeps the 13px notes above 10px. Under that it scrolls.
 */
.flowchart-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.flowchart svg {
  display: block;
  width: 100%;
  min-width: 1500px;
  height: auto;
}

/*
 * The block is `fluid`, so `.content` has no side padding and the svg would
 * otherwise run into the window edges. The viewBox carries 30 units of its own
 * margin; this adds the rest at large sizes and gives back the full width when
 * there is none to spare.
 */
.flowchart {
  padding-inline: clamp(0px, 4vw, 64px);
}

/* Type. Sizes are set per element in the markup; these carry weight and ink. */
.flowchart .fc-eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  fill: var(--fc-mute);
}

.flowchart .fc-title {
  font-weight: 600;
  fill: var(--fc-ink);
}

.flowchart .fc-note,
.flowchart .fc-hint {
  fill: var(--fc-mute);
}

.flowchart .fc-chip-text {
  font-size: 13px;
  font-weight: 600;
  fill: var(--fc-ink);
}

/* --- hover ---------------------------------------------------------------
 *
 * Every card is a `<g class="fc-node">` rather than a loose rect and some
 * text, so the whole card reacts rather than only the rectangle under the
 * cursor. The rect is first in each group and carries a fill, which is what
 * makes the gaps between the lines hoverable too.
 *
 * A small lift and a soft shadow, nothing else. No pointer cursor and no
 * colour change: these are not links, and a hover that promises a click the
 * diagram cannot honour is worse than no hover at all. What it is for is to
 * let a reader hold their place in a wide picture.
 *
 * Nothing about the card's colour moves either. Earlier versions darkened the
 * stroke, then lightened the fill; both pulled the eye to the card as an object
 * being restyled rather than to the card as a thing being pointed at. A lift is
 * the whole of it now.
 *
 * Slow on purpose, and slower than anything else on the page: 600ms on
 * easeOutCubic. A quick hover reads as twitch on a diagram this wide, because a
 * cursor on its way somewhere crosses four or five cards to get there. At this
 * speed a card that is only passed over never fully arrives.
 *
 * The connectors are drawn before the cards in document order, so a lifted card
 * passes cleanly over the wires instead of under them.
 */
.flowchart .fc-node {
  transition:
    transform 0.6s cubic-bezier(0.33, 1, 0.68, 1),
    filter 0.6s cubic-bezier(0.33, 1, 0.68, 1);
}

/* The shadow is the only thing that changes: 6% black under a near-white card,
   which is all a lift this small needs to register. */
.flowchart .fc-node:hover {
  transform: translateY(-3px);
  filter: drop-shadow(0 4px 14px var(--fc-shadow));
}

@media (prefers-reduced-motion: reduce) {
  .flowchart .fc-node {
    transition: none;
  }

  .flowchart .fc-node:hover {
    transform: none;
  }
}

/* Boxes and rules. */
.flowchart .fc-card {
  fill: var(--fc-card);
  stroke: var(--fc-line);
  stroke-width: 1;
}

.flowchart .fc-chip {
  fill: var(--fc-chip);
  stroke: none;
}

.flowchart .fc-line {
  stroke: var(--fc-wire);
  stroke-width: 1.5;
  fill: none;
  stroke-linecap: round;
}

/*
 * No card is outlined in the accent any more. Every box in the diagram is drawn
 * the same way, and the blue survives only as INK: the gate's answer chips, the
 * two notes that state a rule, and the over-budget card's title.
 *
 * That is the stronger version of the same idea. An outlined box says "this box
 * is special"; blue words say which words matter, and they say it inside boxes
 * the eye has already accepted as identical. It also means the one filled blue
 * object on the whole page is the button underneath, which is where the reader
 * is actually meant to go.
 */
.flowchart .fc-chip-accent {
  fill: color-mix(in srgb, var(--case-accent) 12%, transparent);
}

.flowchart .fc-accent-text {
  fill: var(--case-accent);
}

/* Junction dots on the two straight hops between Q6, Q7 and Q8. Wire colour,
   not accent: the accent is spent on the gate and the over-budget slot, and a
   blue dot on a connector would quietly take some of that meaning away. */
.flowchart .fc-dot {
  fill: var(--fc-wire);
}

/* The screen-reader copy of the question set. The svg carries a <title> and a
   <desc>, but neither can hold eight questions in reading order. */
.flowchart-alt {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- the pill button under the diagram ---------------------------------- */
/*
 * Out to the live tool. It was going to be an embed: apple.com serves
 * `x-frame-options: SAMEORIGIN` on /mac/best-mac/ and on the
 * /help-me-choose/mac/ app inside it, so an iframe paints a blank box here.
 *
 * The only filled button in the case, and the only solid blue object on the
 * page outside the closing band. It carries the same label as the text link in
 * the summary on purpose: same offer, said twice, at the two points where a
 * reader is most likely to want it. The weight differs because the position
 * does, not because the destination does.
 *
 * #0071e3 rather than the `--case-accent` #0a84ff used for blue INK. White on
 * #0071e3 measures 4.70:1 and clears AA; on #0a84ff it is 3.65:1 and would be
 * large-text-only. A button is not large text.
 *
 * No arrow. An arrow says "continue reading in this direction"; this leaves the
 * page, and the pill shape is already the affordance.
 */
.pill-cta {
  display: inline-block;
  padding: 0.72em 1.9em;
  border-radius: 100px;
  background: var(--s-accent);
  color: #fff;
  font-size: 1.8em;
  font-weight: 600;
  line-height: 1.4;
  text-decoration: none;
  transition:
    background 0.24s ease,
    transform 0.24s cubic-bezier(0.16, 1, 0.3, 1);
}

.pill-cta:hover {
  /* apple.com's own hover blue for this button. */
  background: #0077ed;
  transform: translateY(-1px);
}

.pill-cta:active {
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .pill-cta {
    transition: none;
  }

  .pill-cta:hover {
    transform: none;
  }
}

/* --- prototype frame ---------------------------------------------------- */
/*
 * The shipped prototype, framed to match the first-version image above it: a
 * 1020x800 plate with the app window sitting proud of it and running off the
 * bottom edge.
 *
 * The three offsets are MEASURED off 01-v1-review-tab.jpg, not guessed — the
 * window in that file starts 11.6% down, is inset 14.8% each side and is 70.4%
 * wide. Matching them is what makes the before and after read as one pair
 * rather than two unrelated pictures.
 *
 * `overflow: hidden` is what crops the video, and it clips the lower half of
 * the shadow with it, which is correct: a window running off the plate has no
 * bottom edge to cast one.
 */

.prototype-frame {
  position: relative;
  max-width: 1020px;
  margin: 0 auto;
  aspect-ratio: 51 / 40;
  overflow: hidden;
  background: #ebebeb;
}

/*
 * A wrapper carries the position, the radius and the shadow; the video just
 * fills it. Putting `border-radius` on the <video> itself is unreliable —
 * WebKit composites video on its own layer and does not always clip it to the
 * element's radius, which shows as square dark corners. `overflow: hidden`
 * here clips the video for certain, and does NOT clip this element's own
 * shadow (only an ancestor's overflow could).
 *
 * `line-height: 0` kills the inline descender gap a replaced element would
 * otherwise leave under itself.
 */
.prototype-window {
  position: absolute;
  top: 11.6%;
  left: 14.8%;
  width: 70.4%;
  border-radius: 14px;
  overflow: hidden;
  line-height: 0;
  box-shadow:
    0 1px 3px rgba(0, 0, 0, 0.07),
    0 16px 40px rgba(0, 0, 0, 0.11);
}

/* Portrait source in a landscape plate, so height comes from the intrinsic
   ratio and overshoots the bottom of the plate by design. */
.prototype-window video {
  display: block;
  width: 100%;
  height: auto;
  background: transparent;
}

@media (max-width: 768px) {
  .prototype-window {
    border-radius: 8px;
  }
}

/* --- impact statements -------------------------------------------------- */
/*
 * Six outcomes as big-type statements rather than number tiles. Tiles put the
 * figure first and the meaning second, which works when every row is a figure;
 * half of these are not, so the sentence leads and the figures inside it are
 * lifted to the title weight instead.
 *
 * Plain `.block`, so 3.2em is 32px against the 10px root.
 */

.impact-list {
  border-top: 1px solid rgba(0, 0, 0, 0.1);
}

/*
 * The indent is padding on the item, not margin on the list, so the hairlines
 * still run the full grid width while the statements sit inset from them. As a
 * percentage it resolves against the list's width, so it stays a fifth of the
 * measure at any viewport.
 */
.impact-list > li {
  padding: 14px 0 14px 20%;
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
  font-size: 3.2em;
  line-height: 1.25;
  letter-spacing: -0.01em;
  font-weight: var(--title-weight);
  color: #6e6e73;
}

/*
 * With the whole statement bold, weight can no longer separate the figure from
 * the sentence — 700 is the heaviest face loaded. So the figure holds the full
 * black while the sentence sits back in dark grey.
 */
.impact-list .fig {
  color: var(--color);
}

@media (max-width: 768px) {
  .impact-list > li {
    padding: 10px 0 10px 16px;
    font-size: clamp(1em, 3.2em, 7vw);
  }
  /* A fifth of a 350px measure is 70px, which is most of the line. */
}

/* --- fill markers ------------------------------------------------------ */
/*
 * Every number on this page that only Airton can supply. Marked rather than
 * guessed: a placeholder that looks like a placeholder can't be shipped by
 * accident, and an invented metric is worse than a missing one.
 *
 * Delete the `fill` class (and its contents) as each real figure lands.
 */

.fill {
  border-bottom: 2px dashed rgba(178, 94, 0, 0.5);
  background: rgba(255, 176, 46, 0.14);
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-weight: 400;
  color: #a75800;
}

.metric-value .fill {
  font-size: 0.62em;
  letter-spacing: 0;
}

/* --- editorial callout ------------------------------------------------- */
/*
 * A note to the author, not to the reader. Styled so it is impossible to
 * mistake for case copy and impossible to miss when proofing.
 */

.callout {
  padding: 20px 24px;
  border: 1px solid rgba(178, 94, 0, 0.28);
  border-radius: 10px;
  background: #fff8ef;
  /*
   * `rem` against the 10px root, not `em`, so the note is 15px wherever it is
   * placed. As an `em` it inherited its container: 15px inside Impact's 17px
   * body column, but 8.8px in the plain block under The Process.
   */
  font-size: 1.5rem;
  line-height: 1.55;
  color: #6b4405;
}

.callout .callout-label {
  display: block;
  margin-bottom: 8px;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 0.78em;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #a75800;
}

.callout ul {
  margin-top: 0.7em;
  padding-left: 1.2em;
  list-style: disc;
}

.callout li {
  display: list-item;
  margin-top: 0.35em;
}

/* --- hindsight --------------------------------------------------------- */
/* One blank line between sections rather than two, as in Learnings. */

.block.learnings .col-body {
  --section-gap: 1;
}

/* --- call to action ---------------------------------------------------- */

/* Both white: the band is blue now, so the accent that used to carry the link
   would be invisible on it. */
.block.header .headline,
.block.header .subheadline a {
  color: #fff;
}
