/* The customer story (2026-09-15; docs/superpowers/specs/2026-09-15-case-study-page-design.md): one editorial
   article drawn on the marketing grid. An overage sheet because the shared sheet is at its budget. The article
   is the grid container; its direct children keep the contract's order and CSS places them: the header as a
   split hero, the facts and metrics as ruled rows, the TL;DR under its tabs, then the aside beside the body
   from 1000px. The rails run from the header's rule to the foot once the joints island has written the
   header's height (--joint-1, islands/SplitJoints.astro). */

/* ——— the breadcrumb: inside main, outside the article ——— */
/* nav.case-crumb outranks the editorial sheet's .breadcrumb width, which is bundled after this sheet */
nav.case-crumb { width: min(100% - 2 * var(--gutter), var(--container)); margin: 0 auto; padding: var(--s-8) 0 0; font-size: var(--fs-small); background: none; }  /* on the rail, as the bar's mark and the hero (Robert) */
nav.case-crumb::before { content: none; }  /* the editorial sheet's breadcrumb band; the page keeps the standard ground (Robert) */
.case-crumb ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); color: var(--muted); }
.case-crumb li { display: inline-flex; align-items: center; gap: var(--s-2); min-width: 0; }
.case-crumb li + li::before { content: '/'; color: var(--border-strong); }
.case-crumb a { color: var(--muted); text-decoration: none; }
.case-crumb a:hover { color: var(--ink); }
.case-crumb [aria-current] { color: var(--ink); max-width: 56ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ——— the article: the grid container, rail to rail; two columns from 1000px (the body, the aside's 20rem) ——— */
.case-study { position: relative; width: min(100% - 2 * var(--gutter), var(--container)); margin-inline: auto; padding: 0 var(--grid-text-inset) var(--section-pad); display: grid; grid-template-columns: minmax(0, 1fr); column-gap: var(--s-8);
  --rail: linear-gradient(var(--page-grid-ink), var(--page-grid-ink)); --dot: radial-gradient(circle, var(--grid-dot) 1px, transparent 1.5px); --hd: radial-gradient(circle, var(--grid-dot) 1px, var(--bg) 1.5px 9.5px, transparent 10px); }
.case-study > * { grid-column: 1 / -1; min-width: 0; margin: 0; }
/* the rails, 2px past each rail as the sections' own box, from 9px under the header's dot to 11px above the foot */
.case-study::after { content: ''; position: absolute; inset: -2px calc(-1 * var(--grid-rail-inset) - 2px); pointer-events: none; }
.case-study[style*="--joint-1"]::after { --j1: calc(var(--joint-1) + 2px);
  background: var(--dot) left 0 top calc(var(--j1) - 2.5px) / 5px 5px no-repeat, var(--dot) right 0 top calc(var(--j1) - 2.5px) / 5px 5px no-repeat,
    var(--rail) left 2px top calc(var(--j1) + 9px) / 1px calc(100% - var(--j1) - 20px) no-repeat, var(--rail) right 2px top calc(var(--j1) + 9px) / 1px calc(100% - var(--j1) - 20px) no-repeat; }

/* ——— the header: a split hero rail to rail, the copy on the column as the home's hero; its rule edge to edge
   beneath, breaking 9px either side of each rail dot ——— */
.case-header { position: relative; isolation: isolate; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); margin-inline: calc(-1 * var(--grid-text-inset)); padding-block: var(--s-5) var(--s-8); }
/* the breadcrumb, tag and title spaced as on a resource page (Robert, 2026-09-30, "mirror the resources breadcrumb, pill,
   hero spacing"): the breadcrumb 64px under the bar, the tag 24px under it, 16px between the header's rows. It replaces
   the same afternoon's 80px more under the breadcrumb, and the breadcrumb's earlier 24px under the bar. */
.case-category { margin: 0; font-size: var(--fs-eyebrow); letter-spacing: var(--track-eyebrow); text-transform: uppercase; color: var(--muted); }
/* The header's wash (Robert, 2026-09-16: "the background gradient like we have on the homepage in the
   solutions page"). Same hue family as the home's aurora and the split hero's panel — pink, purple, a
   warm foot — but static and as a pseudo-element: the home builds its bloom from a <div class="s2-aurora">
   inside the hero, and the article header may hold only the category, H1, dates and hero figure
   (ART-004), so no element is added here. Full bleed by the CSS-004 formula, masked so it fades in
   under the bar and out before the header's rule, the way the home's does (V4 §12). */
.case-header::before { content: ''; position: absolute; z-index: -1; pointer-events: none;
  left: calc(50% - 50vw); width: 100vw; top: 0; bottom: 0;
  background: radial-gradient(58% 68% at 76% 10%, rgba(255, 154, 194, .20), transparent 70%),
    radial-gradient(52% 62% at 97% 42%, rgba(195, 139, 255, .20), transparent 72%),
    radial-gradient(48% 58% at 62% 96%, rgba(255, 176, 138, .16), transparent 74%);
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 22%, #000 66%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0%, #000 22%, #000 66%, transparent 100%); }
.case-header h1 { margin: 0; font-size: var(--fs-display); line-height: var(--lh-display); letter-spacing: var(--track-tight); max-width: 22ch; }
.case-dates { display: flex; gap: var(--s-2); margin: 0; font-size: var(--fs-small); color: var(--muted); }
.case-dates dt, .case-dates dd { margin: 0; }
.case-hero { margin: 0; }
.case-hero img { display: block; width: 100%; height: auto; border-radius: var(--r-card); border: 1px solid var(--border); }
.case-header::after { content: ''; position: absolute; left: calc(50% - 50vw); width: 100vw; bottom: -2.5px; height: 5px; pointer-events: none;
  --span: calc(min(100vw - 2 * var(--gutter), var(--container)) + 2 * var(--grid-rail-inset)); --edge: calc((100vw - var(--span)) / 2);
  background: var(--rail) left 0 top 2px / calc(var(--edge) - 9px) 1px no-repeat, var(--rail) center top 2px / calc(var(--span) - 18px) 1px no-repeat, var(--rail) right 0 top 2px / calc(var(--edge) - 9px) 1px no-repeat; }
@media (min-width: 900px) {
  /* top-aligned (2026-09-30): the tag and the image start 24px under the breadcrumb as a resource page's tag does; the
     image's extra height falls below the dates rather than spreading the copy or centring it */
  .case-header { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); grid-template-rows: auto auto 1fr; column-gap: var(--s-8); align-items: start; }
  .case-header > .case-hero { grid-column: 2; grid-row: 1 / span 3; }
}

/* ——— the joints: a halo dot on each rail where a ruled row opens on its rule, the halo of the ground so the lines
   stop short of the dot (the cells' own device) ——— */
.case-joints::before { content: ''; position: absolute; inset: -10px; z-index: 1; pointer-events: none;
  background: var(--hd) left .5px top .5px / 20px 20px no-repeat, var(--hd) right .5px top .5px / 20px 20px no-repeat; }

/* ——— the metrics: a ruled row of four cells with the cells idiom's dividers, their joints dotted top and bottom
   (the cells--4 drawing) ——— */
.case-metrics.case-joints::before { background:
    var(--hd) left .5px top .5px / 20px 20px no-repeat, var(--hd) left calc(100% / 3 + .5px) top .5px / 20px 20px no-repeat, var(--hd) left calc(100% * 2 / 3 + .5px) top .5px / 20px 20px no-repeat, var(--hd) right .5px top .5px / 20px 20px no-repeat,
    var(--hd) left .5px bottom -.5px / 20px 20px no-repeat, var(--hd) left calc(100% / 3 + .5px) bottom -.5px / 20px 20px no-repeat, var(--hd) left calc(100% * 2 / 3 + .5px) bottom -.5px / 20px 20px no-repeat, var(--hd) right .5px bottom -.5px / 20px 20px no-repeat; }
.case-metrics { position: relative; list-style: none; margin: 0 calc(-1 * var(--grid-text-inset)); padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 1px solid var(--page-grid-ink); }
.case-metrics > li { min-width: 0; display: grid; gap: var(--s-3); align-content: start; padding: var(--s-6) var(--grid-text-inset); }
.case-metrics > li + li { background: var(--rail) left top 11px / 1px calc(100% - 22px) no-repeat; }
.case-metric-value { font-size: clamp(var(--fs-subhead), 2.2vw, var(--fs-display)); white-space: nowrap; line-height: var(--lh-flat); letter-spacing: var(--track-tight); color: var(--ink); }  /* a figure that is words (~1 day/week) fits its cell */
.case-study--legacy .case-metric-value { white-space: normal; overflow-wrap: normal; }
.case-metrics > li > span { font-size: var(--fs-small); color: var(--muted); }
@media (max-width: 900px) {
  .case-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* the row's own joints: three dots on the top rule (the rails and the divider that starts there), two on the
     foot — the third metric spans both columns, so no divider reaches the foot and a dot there would mark
     nothing */
  .case-metrics.case-joints::before { background: var(--hd) left .5px top .5px / 20px 20px no-repeat, var(--hd) left calc(50% + .5px) top .5px / 20px 20px no-repeat, var(--hd) right .5px top .5px / 20px 20px no-repeat, var(--hd) left .5px bottom -.5px / 20px 20px no-repeat, var(--hd) right .5px bottom -.5px / 20px 20px no-repeat; }
  /* the third metric takes the whole second row, so its rule runs rail to rail instead of stopping under the
     first cell, and it carries its own halo dots — the rails either side and the joint where the divider above
     ends on it. Robert, 2026-09-16: "connect the dots on mobile". The dots ride the cell rather than the row's
     ::before because only the cell knows where that rule falls. */
  .case-metrics > li:nth-child(3) { grid-column: 1 / -1; position: relative; border-top: 1px solid var(--page-grid-ink); background: none; }
  .case-metrics > li:nth-child(3)::before { content: ''; position: absolute; z-index: 1; left: -10px; right: -10px; top: -10px; height: 20px; pointer-events: none;
    background: var(--hd) left .5px top .5px / 20px 20px no-repeat, var(--hd) center top .5px / 20px 20px no-repeat, var(--hd) right .5px top .5px / 20px 20px no-repeat; }
  .case-metrics > li:nth-child(n + 4) { border-top: 1px solid var(--page-grid-ink); }
}

/* The second column's content is desktop's (Robert, 2026-09-16: "we don't need to show those on case study
   mobile"). Below the breakpoint where that column exists, the facts card and the aside are hidden — the
   story itself, its metrics and its TL;DR carry the page on a phone. Both stay in the built HTML, so the
   facts and the contents list remain extractable (OUT-005); only their presentation is dropped. */
@media (max-width: 999px) {
  .case-study > .case-facts, .case-study > .case-aside { display: none; }
  /* the mini menu trial (2026-09-30): with the script, the phone takes the aside back as the small widget below */
  .case-study > .case-aside[data-mini] { display: grid; }
}

/* ——— the TL;DR: a ruled row; the intro, the capsule strip, the three parts (all in the HTML; the island shows
   one). From 1000px it keeps the first column and its rule stops at the divider; the column's frame carries that
   rule on across the second, where the facts card opens the run of right-hand cards ——— */
.case-tldr { position: relative; margin: 0 calc(-1 * var(--grid-text-inset)); padding: var(--s-8) var(--grid-text-inset) var(--s-8); border-top: 1px solid var(--page-grid-ink); display: grid; gap: var(--s-5); }
.case-tldr > h2 { margin: 0; }
.case-tldr-intro { margin: 0; max-width: 66ch; font-size: var(--fs-lead-sm); line-height: var(--lh-sub); color: var(--body); }
.case-tldr-nav { margin-top: var(--s-2); }
/* each part is a card on the light wash (Robert, 2026-09-16), its glyph in the small frame at the head of the
   heading: the problem staked out, the path taken, where it came out */
.case-tldr-part { display: grid; gap: var(--s-4); padding: var(--s-6); border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--tile-wash); }
.case-tldr-part > h3 { display: flex; align-items: center; gap: var(--s-3); margin: 0; font-size: var(--fs-card-sm); line-height: var(--lh-tight); }
.case-tldr-part > h3 > .icon-tile { background: transparent; }  /* the frame on the wash, not a white chip cut out of it */
.case-tldr-part > ul { margin: 0; padding-left: 1.2em; display: grid; gap: var(--s-3); max-width: 72ch; color: var(--body); }
.case-tldr-part[hidden] { display: none; }
@media print { .case-tldr-part[hidden] { display: grid; } }

/* ——— the right-hand blocks. The aside is a card on the tile ground (the no-script view; with scripts it is the mini
   menu). The facts are the washed column (Robert, 2026-09-30, the first of three options on the canvas: "lets go with
   the washed column"): no card and no hairlines; from 1000px the second column itself, divider to rail and from the
   TL;DR's rule to the story's, takes the product hero panel's wash. The head is the industry's glyph alone at the top
   left — the place a branded story's logo takes — named for assistive technology only; then Segment, Products used
   and Integrations, each value led by a purple check in a small round frame. The frame and the check are the <dd>'s
   own pseudo-elements, so the list is the same <dl> (OUT-004) and no path data is repeated (NAV-006) ——— */
.case-aside { margin: var(--s-6) 0 0; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--tile); }
.case-facts { display: grid; align-content: start; gap: var(--s-6); margin: var(--s-6) 0 0; padding: var(--sp-40) var(--s-6); background: var(--tile-wash); }
.case-fact--head dd { display: grid; justify-items: start; margin: 0; }
.case-facts-mark { background: var(--bg); }
.case-fact dt { margin: 0 0 var(--s-3); font-size: var(--fs-small); color: var(--muted); }
.case-fact dd { margin: 0; font-size: var(--fs-ui); line-height: var(--lh-body); color: var(--ink); }
.case-fact dd + dd { margin-top: var(--s-2); }
.case-fact:not(.case-fact--head) > dd { position: relative; padding-left: var(--s-6); }
.case-fact:not(.case-fact--head) > dd::before { content: ''; position: absolute; left: 0; top: 2px; width: 20px; height: 20px; box-sizing: border-box; border: 1px solid var(--border); border-radius: 50%; background: var(--bg); }
.case-fact:not(.case-fact--head) > dd::after { content: ''; position: absolute; left: 7px; top: 6px; width: 4.5px; height: 8.5px; border-right: 2px solid var(--purple); border-bottom: 2px solid var(--purple); transform: rotate(45deg); }

/* ——— the story: the heading opens the first column on a rule; the aside is the second card in the column, the
   contents over the demo call, the two divided by the same hairline as the facts card's rows; sticky within the
   column from 1000px. The aside pads through its children, so no wrapper is added to hold a card row ——— */
.case-story-heading { position: relative; margin: 0 calc(-1 * var(--grid-text-inset)); padding: var(--s-8) var(--grid-text-inset) 0; border-top: 1px solid var(--page-grid-ink); font-size: var(--fs-subhead); line-height: var(--lh-tight); }
/* "The full story" is a display heading in the headline face (Robert, 2026-09-30): still the <h2> that opens the story
   (a .display class would make it a <p>), set at the display rung in the flyers' title cut, as the section displays are */
.case-study > .case-story-heading { font-family: var(--font-headline); font-weight: var(--fw-headline); font-variation-settings: 'opsz' var(--opsz-display); font-size: var(--fs-display); line-height: var(--lh-headline-display); letter-spacing: var(--track-headline-display); }
.case-aside { display: grid; gap: var(--s-3); align-content: start; justify-items: start; padding: 0; }
.case-aside > :not(.case-toc) { margin-inline: var(--s-5); }
.case-aside > .case-aside-cta-heading { margin-top: var(--s-2); }
.case-aside > :last-child { margin-bottom: var(--s-5); }
.case-aside-label { margin: 0 0 var(--s-3); font-size: var(--fs-nano); letter-spacing: var(--track-widest); text-transform: uppercase; color: var(--muted); }
.case-toc { justify-self: stretch; margin: 0; padding: var(--s-5); border-bottom: 1px solid var(--border); }
.case-toc ol { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
.case-toc a { display: block; padding-left: var(--s-3); border-left: 2px solid var(--border); color: var(--body); font-size: var(--fs-ui-small); text-decoration: none; }
.case-toc a:hover, .case-toc a.is-hot { color: var(--ink); border-color: var(--ink); }  /* is-hot: the section under the pointer (islands/StoryHover.astro) */
.case-aside-cta-heading { margin: 0; font-size: var(--fs-card-sm); line-height: var(--lh-tight); }
.case-aside-cta-body { margin: 0; font-size: var(--fs-small); color: var(--muted); }
.case-aside-link { margin: 0; font-size: var(--fs-ui-small); }
/* The story's body is set by the blog's own body rules in src/styles/editorial.css (one rich text, Robert,
   2026-09-30: "when we make changes to Richard's, it will be reflected"), so it keeps no type or rhythm of its own
   here. Only its reading width is the story's: 68ch below 1000px, the centred 720px column above it (desktop block). */
.case-study > aside ~ * { max-width: 68ch; }
/* strong in the story's prose and in the TL;DR cards, the same opt-in the editorial article makes.
   .data is excluded: the metric figures are <strong class="data"> inside their <li> and must stay 400 (V4 §1). */
.case-study :is(p, li, dd, blockquote, figcaption) :is(strong, b):not(.data) { font-weight: var(--fw-bold); color: var(--ink); }
@media (min-width: 1000px) {
  .case-study { grid-template-columns: minmax(0, 1fr) 20rem; column-gap: 0; }
  /* the metrics row takes the page's own columns, so its last divider is the column divider below and the rule
     between them carries one dot at that joint rather than two a hair apart (2026-09-16). The row bleeds one text
     inset past the content box either side, so the third track carries that inset and the dots are placed off the
     halo box's own edges. A percentage in a background position is of the box less the image, and the halo box is
     the row grown 10px either side for a 20px image, so 100% there is the row's own width: the first divider's dot
     is half of the two flexible tracks, with nothing taken off (the -20px it once had put the dot 10px left of its
     divider; Robert, 2026-09-30) */
  .case-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)) calc(20rem + var(--grid-text-inset)); }
  .case-metrics.case-joints::before { --m2: calc((100% - 20rem - var(--grid-text-inset)) / 2 + .5px); background:
      var(--hd) left .5px top .5px / 20px 20px no-repeat, var(--hd) left var(--m2) top .5px / 20px 20px no-repeat,
      var(--hd) right calc(20rem + var(--grid-text-inset)) top .5px / 20px 20px no-repeat, var(--hd) right .5px top .5px / 20px 20px no-repeat,
      var(--hd) left .5px bottom -.5px / 20px 20px no-repeat, var(--hd) left var(--m2) bottom -.5px / 20px 20px no-repeat,
      var(--hd) right calc(20rem + var(--grid-text-inset)) bottom -.5px / 20px 20px no-repeat, var(--hd) right .5px bottom -.5px / 20px 20px no-repeat; }
  .case-study > .case-tldr { grid-column: 1; margin-right: 0; padding-right: var(--grid-text-inset); }
  /* From "The full story" down the story is one centred column at the reading measure (Robert, 2026-09-30, the mini
     menu trial): the heading's rule still runs rail to rail, its words start where the body's do. A padding percentage
     is of the grid area, the article's width, which is what the body's measure is centred in. */
  .case-study { --story-measure: 720px; }
  .case-study > .case-story-heading { grid-column: 1 / -1; padding-inline: calc(var(--grid-text-inset) + (100% - min(100%, var(--story-measure))) / 2); }
  /* the facts fill the second column's cell (2026-09-30, the washed column): the TL;DR's row, from the divider to the
     rail, a pixel inside the lines that bound it. The grid's dots carry a disc in the page's white that breaks the lines
     near a joint; over the wash it would bite a white quarter out of each corner, so the wash lies above the frame (its
     z-index 1) and, stopping short of the lines, covers only the discs' inner quarters */
  .case-study > .case-facts { grid-column: 2; align-self: stretch; position: relative; z-index: 2; margin: 1px calc(1px - var(--grid-text-inset) - var(--grid-rail-inset)) 0 1px; }
  /* the aside left the second column (2026-09-30): without the script it sits in the story's column, before the body;
     with it, it is the mini menu (below) */
  .case-study > aside { grid-column: 1 / -1; justify-self: center; width: min(100%, var(--story-measure)); margin: var(--s-6) 0 0; }
  /* the body fills its column to the same 48px from the divider as from the rail (Robert: "equal to the padding on
     the left side"); the quote cards with it */
  .case-study > aside ~ * { grid-column: 1 / -1; justify-self: center; width: min(100%, var(--story-measure)); max-width: none; margin-right: 0; }
  /* the second column's frame (Robert, 2026-09-16: the cards sit inside it, not instead of it): from the TL;DR's
     rule (--joint-2) to the article's foot — the divider on its left, the TL;DR's rule carried across its top, and
     a halo dot at each corner. islands/SplitJoints.astro writes the offsets. */
  .case-study[style*="--joint-2"]::before { content: ''; position: absolute; z-index: 1; pointer-events: none; top: calc(var(--joint-2) - 10px); bottom: -10px; right: calc(-1 * var(--grid-rail-inset) - 10px); width: calc(20rem + var(--grid-text-inset) + 20px);
    background: var(--hd) left 0 top 0 / 20px 20px no-repeat, var(--hd) right 0 top 0 / 20px 20px no-repeat,
      var(--hd) left 0 bottom 0 / 20px 20px no-repeat, var(--hd) right 0 bottom 0 / 20px 20px no-repeat,
      var(--rail) left 10px top 10px / 1px calc(100% - 20px) no-repeat, var(--rail) left 10px top 10px / calc(100% - 20px) 1px no-repeat; }
  /* the story's rule (--joint-3) crosses the column on its way to the rail, the way the TL;DR's does at the frame's
     top: the rule carried across, a dot where it meets the divider and another where it meets the rail, both
     placed from the frame's own top. Robert, 2026-09-16: "connect the dots" — the rule stopped at the divider and
     the joint read as a dead end. */
  /* With the aside gone from the column (2026-09-30), the frame closes at the story's rule: its divider runs from the
     TL;DR's rule down to it and a dot sits at each of its four corners. */
  .case-study[style*="--joint-3"]::before { --j3: calc(var(--joint-3) - var(--joint-2)); bottom: auto; height: calc(var(--j3) + 20px);
    background: var(--hd) left 0 top 0 / 20px 20px no-repeat, var(--hd) right 0 top 0 / 20px 20px no-repeat,
      var(--hd) left 0 top var(--j3) / 20px 20px no-repeat, var(--hd) right 0 top var(--j3) / 20px 20px no-repeat,
      var(--rail) left 10px top calc(var(--j3) + 10px) / calc(100% - 20px) 1px no-repeat,
      var(--rail) left 10px top 10px / 1px calc(100% - 20px) no-repeat, var(--rail) left 10px top 10px / calc(100% - 20px) 1px no-repeat; }
  /* a story with no TL;DR has no second column to frame: its story heading is the second joint and the body below it is
     the centred column */
  .case-study[style*="--joint-2"]:not([style*="--joint-3"])::before { content: none; }
}

/* ——— The mini menu (Robert, 2026-09-30, a trial; V4 §53). With the script (islands/StoryMiniMenu.astro) the aside is
   a small widget fixed at the bottom right, on every width. Collapsed it is its "Contents menu" control and the one
   contents link marked aria-current="location", the section in view, a long name ending in an ellipsis at the card's
   padding (the heading itself is untouched and reads in full). Open (toggled, a link with keyboard focus, or hovered
   where a pointer can hover) it grows upward into the whole list, the call and the product link, and folds back the
   same way. It shows only while the reader is inside the story, or when focus reaches it. Its HTML is the aside's own.
   One switch drives it: the state sets --mini-open (0 or 1) and a few keywords, and every part derives its height,
   opacity and spacing from them, so the card animates through its real heights; a folded part turns hidden only once
   it has folded, which takes it out of the tab order and the accessibility tree. */
.case-study > .case-aside[data-mini] {
  --t-mini: 300ms; --mini-open: 0; --mini-vis: hidden; --mini-delay: var(--t-mini); --mini-cover: block; --mini-ws: nowrap;
  position: fixed; z-index: 70; right: var(--sp-24); bottom: var(--sp-24); width: min(320px, 100vw - 2 * var(--sp-16));
  max-height: calc(100vh - 120px); overflow: hidden auto; overscroll-behavior: contain; margin: 0; justify-self: auto; gap: 0;
  background: var(--bg); box-shadow: var(--menu-shadow);
  transition: opacity var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
/* open: toggled, or a link has keyboard focus; below, hovered where a pointer can really hover (on a touch screen a tap
   is also a hover, which opened the card under the finger and sent the tap to a link inside it) */
.case-study > .case-aside[data-mini]:is([data-open], :has(a:focus-visible)) { --mini-open: 1; --mini-vis: visible; --mini-delay: 0s; --mini-cover: none; --mini-ws: normal; }
@media (hover: hover) { .case-study > .case-aside[data-mini]:hover { --mini-open: 1; --mini-vis: visible; --mini-delay: 0s; --mini-cover: none; --mini-ws: normal; } }
.case-study > .case-aside[data-mini]:not([data-visible]):not(:focus-within) { opacity: 0; transform: translateY(8px); pointer-events: none; }
/* the "In this story" label is the no-script view's; the widget's control names it instead */
.case-study > .case-aside[data-mini] .case-aside-label { display: none; }
.case-study > .case-aside[data-mini] .case-toc {
  position: static; padding: calc(var(--s-4) + var(--mini-open) * (var(--s-5) - var(--s-4))) var(--s-5);
  border-bottom: 1px solid color-mix(in srgb, var(--border) calc(var(--mini-open) * 100%), transparent);
  transition: padding var(--t-mini) var(--ease), border-color var(--t-mini) var(--ease);
}
.case-study > .case-aside[data-mini] .case-toc ol { grid-template-columns: minmax(0, 1fr); gap: 0; margin-top: var(--s-3); }  /* a long name must not widen the track */
.case-study > .case-aside[data-mini] .case-toc li { padding-block: 3px; }
.case-study > .case-aside[data-mini] .case-toc a[aria-current] { color: var(--ink); border-color: var(--orange); white-space: var(--mini-ws); overflow: hidden; text-overflow: ellipsis; }
/* the parts that fold: every other section, the call and the product link */
.case-study > .case-aside[data-mini] .case-toc li:not(:has(> a[aria-current])),
.case-study > .case-aside[data-mini] > :not(.case-toc) {
  max-height: calc(var(--mini-open) * 8em); opacity: var(--mini-open); visibility: var(--mini-vis); overflow: hidden;
  transition: max-height var(--t-mini) var(--ease), opacity var(--t-mini) var(--ease), margin var(--t-mini) var(--ease), padding var(--t-mini) var(--ease), min-height var(--t-mini) var(--ease), border-width var(--t-mini) var(--ease), visibility 0s linear var(--mini-delay);
}
.case-study > .case-aside[data-mini] .case-toc li:not(:has(> a[aria-current])) { padding-block: calc(var(--mini-open) * 3px); }
.case-study > .case-aside[data-mini] > :not(.case-toc) { margin-top: calc(var(--mini-open) * var(--s-3)); margin-bottom: 0; }
.case-study > .case-aside[data-mini] > .case-aside-cta-heading { margin-top: calc(var(--mini-open) * var(--s-5)); }
.case-study > .case-aside[data-mini] > :last-child { margin-bottom: calc(var(--mini-open) * var(--s-5)); }
.case-study > .case-aside[data-mini] > .btn { min-height: calc(var(--mini-open) * var(--button-small-min-height)); padding-block: calc(var(--mini-open) * var(--sp-10)); border-width: calc(var(--mini-open) * 1px); }
/* the control: "Contents menu" in the label's voice, a caret at its right that turns from up to down as it opens;
   folded, its hit area covers the card so a tap anywhere opens it */
.case-mini-toggle { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); width: 100%; margin: 0; padding: 0; border: 0; background: none; font: inherit; font-size: var(--fs-nano); letter-spacing: var(--track-widest); text-transform: uppercase; color: var(--muted); text-align: left; cursor: pointer; }
.case-mini-toggle:hover { color: var(--ink); }
.case-mini-toggle::after { content: ''; flex: none; width: 7px; height: 7px; margin-right: 3px; border-top: 1.6px solid currentColor; border-left: 1.6px solid currentColor; transform: translateY(calc(2px - var(--mini-open) * 4px)) rotate(calc(45deg + var(--mini-open) * 180deg)); transition: transform var(--t-mini) var(--ease); }
.case-mini-toggle::before { content: ''; position: absolute; inset: 0; display: var(--mini-cover); }
@media (max-width: 640px) { .case-study > .case-aside[data-mini] { right: var(--sp-16); bottom: var(--sp-16); } }
/* reduced motion: the one duration token goes to zero, and with it every fold, fade, turn and the hidden-after delay */
@media (prefers-reduced-motion: reduce) { .case-study > .case-aside[data-mini] { --t-mini: 0ms; } }

/* ——— the quote card: the loop behind, the quote, the role and the company; no loop under reduced motion ——— */
.quote-card { position: relative; isolation: isolate; overflow: hidden; padding: var(--s-6); border-radius: var(--r-card); color: #fff; background: linear-gradient(307deg, #1a1535, #2d1f55); }
.quote-card--navy { background: linear-gradient(307deg, #0e1a3a, #1a2d62); }
.case-study > aside ~ .quote-card { margin-top: var(--s-6); max-width: none; }
.case-study > aside ~ .quote-card + * { margin-top: var(--s-6); }
.quote-card-loop { position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%; object-fit: cover; opacity: .38; pointer-events: none; }
.quote-card::before { content: ''; position: absolute; inset: 0; z-index: -1; background: linear-gradient(180deg, rgba(8, 6, 18, .15), rgba(8, 6, 18, .55)); }
.quote-card blockquote { margin: 0; }
.quote-card blockquote p { margin: 0; font-size: var(--fs-lead-sm); line-height: var(--lh-sub); color: #fff; }
.quote-card blockquote p::before { content: '\201C'; }
.quote-card blockquote p::after { content: '\201D'; }
.quote-card figcaption { margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid rgba(255, 255, 255, .2); display: grid; gap: 2px; font-size: var(--fs-small); }
.quote-card-name { color: #fff; }
.quote-card-role { color: rgba(255, 255, 255, .7); }
.quote-card-video-link { justify-self: start; margin-top: var(--s-2); color: #fff; text-decoration: underline; text-underline-offset: 3px; }
.quote-card-video-link:hover, .quote-card-video-link:focus-visible { color: #fff; text-decoration-color: var(--orange); }
@media (prefers-reduced-motion: reduce) { .quote-card-loop { display: none; } }

/* ——— more customer stories ——— */
.case-more-heading { margin: 0 0 var(--s-6); font-size: var(--fs-subhead); line-height: var(--lh-tight); }
.case-more-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-4); }
.case-more-card { display: grid; gap: var(--s-3); align-content: start; padding: var(--s-4); }
.case-more-card img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--r-field); }
.case-more-industry { margin: 0; font-size: var(--fs-nano); letter-spacing: var(--track-widest); text-transform: uppercase; color: var(--muted); }
.case-more-list .case-more-card h3 { margin: 0; font-size: var(--fs-card-sm); line-height: var(--lh-tight); }  /* the library cards' title size (2026-09-30): the list class outranks the shared .tile h3, which loads after this sheet */
.case-more-card h3 a { color: inherit; text-decoration: none; }
@media (max-width: 900px) { .case-more-list { grid-template-columns: minmax(0, 1fr); } }
