/* ==========================================================================
   casestudy.css — Guardian Layer (and future case studies)
   Reuses all tokens from styles.css. Layout: a pinned gray panel on the
   left whose copy swaps per section, and scrolling paper content on the
   right, with a progress rail (dots on a filling line).
   ========================================================================== */

:root {
  --cs-panel-w: 42%;
  /* Same value as --cs-panel-w, in viewport units. Needed for the
     .cs-section--merged full-bleed breakout below: that rule lives on an
     element nested inside .cs-content, so a plain "%" there would resolve
     against .cs-content's own (already-offset) width instead of the full
     viewport, and the math would come up short of true edge-to-edge. */
  --cs-panel-vw: 42vw;
  --cs-accent: var(--accent-guardian);
  --cs-accent-text: var(--accent-guardian-text);
}

/* Per-project accent themes */
.cs[data-accent="shortlist"] {
  --cs-accent: var(--accent-shortlist);
  --cs-accent-text: var(--accent-shortlist-text);
}
.cs[data-accent="copilot"] {
  --cs-accent: var(--accent-copilot);
  --cs-accent-text: var(--accent-copilot-text);
}
.cs[data-accent="copilot"] .cs-caption {
  color: var(--cs-accent-text); /* blue captions, scoped to this project only */
}
/* Progress rail intentionally left on the shared rule below (same as Guardian
   Layer and Shortlist) — labels stay ink/black, only the dot squares and fill
   pick up the project's --cs-accent-text. No copilot-specific override. */

/* --- Minimal top nav --- */
.cs-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 32px;
  padding: 16px var(--margin) 0;
}
.cs-nav-right {
  display: flex;
  gap: 32px;
}
.cs-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.cs-back-arrow {
  transition: transform var(--dur-ui) var(--ease);
}
.cs-back:hover .cs-back-arrow {
  transform: translateX(-4px);
}

/* --- Layout shell --- */
.cs {
  display: block;
  padding-top: 0;
}

/* --- Pinned left panel --- */
.cs-panel {
  position: fixed;
  top: 0;
  left: 0;
  width: var(--cs-panel-w);
  height: 100vh;
  background: var(--work-gray);
  z-index: 10;
  display: flex;
  align-items: flex-start;         /* fixed top anchor, not centered */
  overflow: hidden;                /* clip content when the panel height is cut */
}
.cs-panel-inner {
  padding: 22vh 40px 0 190px;      /* consistent higher start for every section */
  max-width: 100%;
  width: 100%;
}

.cs-eyebrow {
  margin: 0 0 20px;
  color: var(--cs-accent-text);
}

.cs-heading {
  margin: 0 0 20px;
  transition: opacity 300ms var(--ease), transform 300ms var(--ease);
}

.cs-sub {
  margin: 0 0 24px;
  color: var(--ink);
}
.cs-sub:empty { display: none; margin: 0; }

.cs-body {
  margin: 0;
  color: var(--ink-60);
}

/* Panel copy cross-fades on section change (JS toggles .is-swapping) */
.cs-panel.is-swapping .cs-heading,
.cs-panel.is-swapping .cs-sub,
.cs-panel.is-swapping .cs-body,
.cs-panel.is-swapping .cs-eyebrow,
.cs-panel.is-swapping .cs-meta-card,
.cs-panel.is-swapping .cs-panel-card,
.cs-panel.is-swapping .cs-panel-status,
.cs-panel.is-swapping .cs-panel-how {
  opacity: 0;              /* fade OUT is opacity-only, so no jump on scroll-up */
}
.cs-heading, .cs-sub, .cs-body, .cs-eyebrow, .cs-meta-card, .cs-panel-card, .cs-panel-status, .cs-panel-how {
  transition: opacity 250ms var(--ease);
}

/* Rise-in on section change: text drifts up 8px as it fades in, matching
   the homepage reveal. Staggered slightly for a soft cascade. */
.cs-panel.is-entering .cs-eyebrow { animation: cs-rise 360ms var(--ease) both; }
.cs-panel.is-entering .cs-heading { animation: cs-rise 360ms var(--ease) 40ms both; }
.cs-panel.is-entering .cs-sub     { animation: cs-rise 360ms var(--ease) 80ms both; }
.cs-panel.is-entering .cs-body    { animation: cs-rise 360ms var(--ease) 80ms both; }
.cs-panel.is-entering .cs-panel-card,
.cs-panel.is-entering .cs-panel-status,
.cs-panel.is-entering .cs-panel-how { animation: cs-rise 360ms var(--ease) 120ms both; }


@keyframes cs-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .cs-panel.is-entering .cs-eyebrow,
  .cs-panel.is-entering .cs-heading,
  .cs-panel.is-entering .cs-sub,
  .cs-panel.is-entering .cs-body { animation: none; }
}

/* --- Progress rail --- */
.cs-rail {
  position: fixed;
  left: 20px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 30;
  width: 150px;
}
.cs-rail-track {
  position: absolute;
  left: 5px;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: var(--ink-12);
}
.cs-rail-fill {
  position: absolute;
  left: 0;
  top: 0;
  width: 1px;
  height: 0;
  background: var(--cs-accent-text);
  transition: height 120ms linear;
}
.cs-rail-dots {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 48px;
}
.cs-rail-dots li {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 12px;
}
.cs-dot {
  width: 11px;
  height: 11px;
  border: 1px solid var(--ink-40);
  background: var(--work-gray);
  flex: none;
  transition: background-color 200ms var(--ease), border-color 200ms var(--ease);
}
.cs-dot-label {
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-40);
  white-space: nowrap;
  transition: color 200ms var(--ease);
}
.cs-rail-dots li.is-past .cs-dot,
.cs-rail-dots li.is-active .cs-dot {
  background: var(--cs-accent-text);
  border-color: var(--cs-accent-text);
}
.cs-rail-dots li.is-active .cs-dot-label {
  color: var(--ink);
  font-weight: 500;
}
.cs-rail-dots li.is-past .cs-dot-label {
  color: var(--ink-60);
}

/* --- Scrolling paper content on the right --- */
.cs-content {
  margin-left: var(--cs-panel-w);
  background: var(--paper);
  min-height: 100vh;
}
.cs-section {
  min-height: 100vh;
  padding: 120px 80px 120px 80px;
  padding-right: max(var(--margin), 80px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 32px;
  border-bottom: 1px solid var(--ink-12);
}
.cs-section:last-child { border-bottom: 0; }


/* Meta card (Project type / Problem / Impact) — homepage card style */
.cs-meta-card {
  margin: 32px 0 0;
  padding: 24px 28px;
  background: var(--paper);
  border: 1px solid var(--ink-40);
  box-shadow: 0 4px 4px rgba(10, 9, 13, 0.10);
  display: grid;
  gap: 16px;
  width: 100%;          /* align to the heading/text width above it */
  transition: opacity 200ms var(--ease);
}
/* Meta card belongs to the intro; hide it once past the first section */
.cs-panel.past-start .cs-meta-card {
  display: none; /* intro-only; fully gone past the first section */
}
.cs-meta-row {
  display: grid;
  gap: 4px;
}
.cs-meta-label {
  color: var(--cs-accent-text);
}
.cs-meta-value {
  margin: 0;
  font-size: 15px;
  line-height: 22px;
  color: var(--ink);
}

/* Short-viewport headroom: the meta card now holds the same three entries
   (project type, problem, impact) as the homepage card, which run longer
   than the old Role/Timeline/Type values and can wrap to more lines in the
   narrower panel widths. Rather than shrink the card's own padding, gap, or
   text (same reasoning as the homepage card), free up room by tightening
   the surrounding stack — the panel's top offset and the gaps between
   heading/sub/card — and only on short viewports where it's actually
   needed. Taller screens are untouched. */
@media (max-height: 820px) {
  .cs-panel-inner { padding-top: 15vh; }
  .cs-heading { margin-bottom: 12px; }
  .cs-sub { margin-bottom: 16px; }
  .cs-meta-card { margin-top: 20px; }
}
@media (max-height: 700px) {
  .cs-panel-inner { padding-top: 8vh; }
  .cs-heading { margin-bottom: 6px; }
  .cs-sub { margin-bottom: 8px; }
  .cs-meta-card { margin-top: 10px; }
}
@media (max-height: 620px) {
  .cs-panel-inner { padding-top: 1vh; }
  .cs-heading { margin-bottom: 2px; }
  .cs-sub { margin-bottom: 4px; }
  .cs-meta-card { margin-top: 4px; }
}


/* --- Problem diagram: magnet-hovering boxes with tracking lines --- */
.cs-problem-diagram {
  position: relative;
  width: 100%;
  max-width: 760px;
  aspect-ratio: 3 / 2;
  margin: 0 auto;
}

.cs-problem-diagram-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
}

.cs-problem-node {
  position: absolute;
  transform: translate(-50%, -50%); /* position by center for even rectangle */
  z-index: 2;
  width: 200px;
  max-width: 40%;
}

.cs-problem-node-inner {
  display: block;
  padding: 14px 10px;
  background: var(--paper);
  border: 1px solid var(--ink-40);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 21px;
  color: var(--ink);
  text-align: center;
  box-shadow: 0 4px 4px rgba(10, 9, 13, 0.10);
  transition: transform 0.5s ease-in-out;
  will-change: transform;
}

.cs-problem-node.is-magnet-active .cs-problem-node-inner {
  transition: transform 0.3s ease-out;
}

#problem-estimation    { left: 30%; top: 22%; }  /* top-left */
#problem-overcommitment { left: 70%; top: 22%; }  /* top-right */
#problem-urgent         { left: 70%; top: 78%; }  /* bottom-right */
#problem-freezing       { left: 30%; top: 78%; }  /* bottom-left */

/* Keep the existing-tools explanation centered beneath the connected boxes. */
.cs-problem-tools {
  display: flex;
  justify-content: center;
  width: 100%;
}

.cs-problem-tools .cs-card {
  width: min(100%, 760px);
  max-width: 760px;
}



/* How-it-works panel block: body + Hook Model lines */
.cs-panel-how { margin-top: 0; }
.cs-panel-how[hidden] { display: none; }
.cs-panel-how .type-body { margin: 0 0 24px; color: var(--ink-60); }
.cs-hook { display: grid; gap: 12px; }
.cs-hook-line {
  margin: 0;
  font-size: 15px;
  line-height: 22px;
  color: var(--ink-60);
}
.cs-hook-line .cs-hl { color: var(--cs-accent-text); font-weight: 500; }

/* Bigger flow image, centered, fills the column */
.cs-figure--flow {
  max-width: none;
  width: 100%;
  margin-inline: 0;
  margin-right: -80px; /* extend into the right breathing space for a bigger image */
}
.cs-section--imgonly .cs-figure.cs-figure--flow {
  max-width: none;       /* beat the 560px imgonly cap */
  width: auto;
  align-self: stretch;
  margin: 0 -80px 0 0;
}
@media (max-width: 1279px) {
  .cs-figure--flow, .cs-section--imgonly .cs-figure--flow { margin-right: 0; }
}


/* Impact stats */
.cs-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 40px;
  margin-bottom: 8px;
}
.cs-stat .type-body { margin: 8px 0 0; }
.cs-stat-num {
  margin: 0;
  font-size: 44px;
  line-height: 1;
  font-weight: 500;
  color: var(--cs-accent-text);
}
@media (max-width: 1023px) { .cs-stats { grid-template-columns: 1fr; gap: 24px; } }

/* Pull quote in a card */
.cs-quote { margin: 0; font-size: 18px; line-height: 28px; }
.cs-quote-attr { margin: 12px 0 0; color: var(--ink-60); }



/* Exploration grid image, centered in the column */
.cs-figure--explorations {
  max-width: 720px;
  margin-inline: auto;
}

/* --- Insight V-diagram: every node is a box, connected like the skills --- */
.cs-diagram {
  position: relative;
  width: 100%;
  aspect-ratio: 3 / 2;
  max-width: 760px;
  margin: 0 auto;
}
.cs-diagram-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
}
.cs-node {
  position: absolute;
  transform: translate(-50%, -50%);
  z-index: 2;
  width: 220px;
  max-width: 44%;
}
.cs-node-inner {
  display: block;
  padding: 14px 18px;
  background: var(--paper);
  border: 1px solid var(--ink-40);
  box-shadow: 0 4px 4px rgba(10, 9, 13, 0.10);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 21px;
  color: var(--ink);
  text-align: center;
  transition: transform 0.5s ease-in-out;
  will-change: transform;
}
.cs-node.is-magnet-active .cs-node-inner {
  transition: transform 0.3s ease-out;
}
.cs-node--text strong { font-weight: 500; }

/* Top pills keep an accent-tinted fill; still bordered boxes */
.cs-node--protect .cs-node-inner {
  background: var(--cs-accent); /* project accent */
  border: 0;                          /* no stroke */
  color: var(--ink);                  /* dark text */
  font-weight: 500;
}
.cs-node--install .cs-node-inner {
  background: var(--ink);             /* black box */
  border: 0;                          /* no stroke */
  color: var(--cs-accent);      /* project accent type */
  font-weight: 500;
}
.cs-node--sum .cs-node-inner {
  background: var(--paper);
  border-color: var(--ink-40);
  font-weight: 500;
}

/* --- Interview quote chain: same magnet + tracking-line system as the
   V-diagram above, but the three nodes stay in normal vertical flow (not
   absolute-positioned by percentage) so boxes of different quote lengths
   never overlap — the connector lines are still drawn by JS between each
   pair's bottom/top edges, so they track correctly either way. --- */
.cs-chain {
  position: relative;
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 56px;
}
.cs-chain-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
}
.cs-chain-node {
  position: relative;
  z-index: 2;
  width: 100%;
}
.cs-chain-node-inner {
  display: block;
  padding: 20px 24px;
  background: var(--paper);
  border: 1px solid var(--ink-40);
  box-shadow: 0 4px 4px rgba(10, 9, 13, 0.10);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 22px;
  color: var(--ink);
  text-align: center;
  transition: transform 0.5s ease-in-out;
  will-change: transform;
}
.cs-chain-node.is-magnet-active .cs-chain-node-inner {
  transition: transform 0.3s ease-out;
}





/* Now section status, shown in the left panel as plain text */
.cs-panel-status {
  margin: 32px 0 0;
  display: grid;
  gap: 28px;
}
.cs-panel-status[hidden] { display: none; }
.cs-status-head {
  display: block;
  margin: 0 0 4px;
  color: var(--cs-accent-text);
  font-weight: 500;
  font-size: 16px;
  line-height: 22px;
}
.cs-panel-status-item .type-body { margin: 0; color: var(--ink-60); }

/* Section cards shown inside the left panel (Exploration, Final design) */
.cs-panel-card {
  margin: 32px 0 0;
  padding: 24px;
  width: 100%;
  background: var(--paper);
  border: 1px solid var(--ink-40);
  box-shadow: 0 4px 4px rgba(10, 9, 13, 0.10);
}

.cs-panel-card[hidden] { display: none; }
.cs-panel-card .type-body { margin: 0; }
.cs-panel-card .cs-livelink { margin-top: 20px; }
.cs-panel-card .cs-livelink:first-child { margin-top: 0; }

/* Trust principles rendered inside the left panel body — and the same
   data-body HTML gets reused verbatim in the mobile .cs-inline-body (see
   buildInlineHeadings in casestudy.js), so it needs the same treatment
   there too, or the principles run together as one paragraph with no
   green bold on mobile. */
#cs-body .cs-principle,
.cs-inline-body .cs-principle {
  display: block;
  margin-top: 20px;
  font-size: 15px;
  line-height: 22px;
  color: var(--ink-60);
}
#cs-body .cs-principle:first-child,
.cs-inline-body .cs-principle:first-child { margin-top: 0; }
#cs-body .cs-principle strong,
.cs-inline-body .cs-principle strong {
  display: block;
  margin-bottom: 2px;
  color: var(--cs-accent-text);
  font-weight: 500;
}

/* Trust principles (legacy, right-side) — plain text with green subheadings */
.cs-principles {
  display: grid;
  gap: 32px;
  max-width: 640px;
}
.cs-principle-head {
  margin: 0 0 8px;
  color: var(--cs-accent-text);
}
.cs-principle .type-body {
  margin: 0;
}

/* Figures */
.cs-figure {
  margin: 0;
}
.cs-figure img,
.cs-figure video {
  display: block;
  width: 100%;
  height: auto;
}

.cs-caption {
  margin: 12px 0 0;
}
.cs-caption--above {
  margin: 0 0 12px;
}

/* Guardian Layer start-section video: same resting shadow as the site's
   cards (hero tiles, work cards), so it lifts off the paper background
   instead of a hard-edged stroke. A box-shadow paints outside the box
   rather than over it, so — unlike the border this replaced — it isn't
   affected by the video's own hardware-composited layer rounding up a
   sub-pixel at the two-column desktop width. */
main[data-accent="guardian"] #sec-start .cs-figure {
  box-shadow: 0 4px 4px rgba(10, 9, 13, 0.10);
}

/* Final design — the warning + onboarding section merged into one full-page,
   full-bleed block. The paper fill sits on the section itself (not a
   separate overlay), is never part of the reveal-on-scroll transition, and
   so is always solid — only .cs-merged-eyebrow and .cs-merged-heading fade
   in on scroll (see the reveal-on-scroll rules further down). On desktop it
   also breaks out of the two-column layout, the same way .cs-footer does:
   full viewport width, sitting above the fixed side panel (z-index 10), with
   its own left padding (190px) matching .cs-panel-inner's so the heading
   lines up with "Guardian Layer has two users..." above it. */
.cs-section--merged {
  background: var(--paper);
  border-top: 1px solid var(--ink-12);
  border-bottom: 1px solid var(--ink-12);
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
@media (min-width: 1024px) {
  .cs-section--merged {
    position: relative;
    z-index: 20;                                  /* above .cs-panel (10), below .cs-rail (30) */
    margin-left: calc(-1 * var(--cs-panel-vw));    /* cancel .cs-content's offset, reach x:0 */
    width: 100vw;                                  /* true edge-to-edge, not just the column */
  }
}
.cs-merged-inner {
  width: 100%;
  max-width: 980px;
  margin: 0 auto;
  padding: 120px 56px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;   /* heading + button flush left, like every other heading */
  gap: 32px;
  text-align: left;
}
/* 190px matches .cs-panel-inner's own left padding, so the heading here
   lines up exactly under "Guardian Layer has two users..." as you scroll
   from the panel into this full-bleed section — no more centering. Placed
   after the base .cs-merged-inner rule above so it wins the cascade. */
@media (min-width: 1024px) {
  .cs-merged-inner {
    max-width: none;
    margin: 0;
    padding: 120px 80px 120px 190px;
  }
}
.cs-merged-eyebrow {
  margin: 0;
  color: var(--cs-accent-text);
}
.cs-merged-heading {
  margin: 0;
  white-space: nowrap; /* always one horizontal line, per the brief */
}
.cs-merged-link {
  margin-top: 8px;
  margin-bottom: 16px;
}
.cs-merged-figures {
  display: flex;
  flex-direction: column;   /* stacked vertically, like the two images were before the merge */
  align-items: center;
  gap: 64px;
  width: 100%;
  margin-top: 16px;
}

/* Each image's <figure> sizes to its own content (the callout grid, or —
   below 1280px — the plain centered image), and .cs-merged-figures' own
   align-items:center keeps it centered in the column either way. */
.cs-callout-figure {
  margin: 0;
}
.cs-callout-figure .cs-caption {
  text-align: center;
}

/* Below 1280px there's no room for side-column callout text next to the
   image, so the grid collapses to just the image column at its old fixed
   width — same look as before the callouts existed. The callout text and
   its connector lines only appear at 1280px+ (below). */
.cs-callouts {
  display: block;
}
.cs-callout-col {
  display: none;
}
.cs-callout-img {
  margin-inline: auto;
}
.cs-callout-img img {
  display: block;
  width: 100%;
  height: auto;
  box-shadow: 0 4px 4px rgba(10, 9, 13, 0.10);
}
.cs-callouts--warning .cs-callout-img {
  max-width: 420px;
}
.cs-callouts--onboarding .cs-callout-img {
  max-width: 480px;
}

/* --- Annotated callouts: 3-column grid (text | image | text), shown only
   at 1280px+ where there's enough width for side text plus the image at a
   readable size. Side columns use align-items:stretch so they're exactly
   as tall as the image, which is what makes the --top percentages below
   line up with specific rows in the image. Each .cs-callout is positioned
   by a --top custom property (set inline per callout, as a % of the image's
   own height) rather than by hand-tuned pixel values, so the same markup
   stays correct if the image is ever resized. The connector line + arrowhead
   are plain pseudo-elements (no SVG): a thin bar plus a CSS border-triangle,
   both drawn past the callout's own box so they cross the gap and run a
   little way over the image itself, matching the reference slides' arrows
   that land on the exact detail being called out. */
@media (min-width: 1280px) {
  .cs-callouts {
    display: grid;
    align-items: stretch;
    column-gap: 28px;
  }
  .cs-callouts--warning {
    grid-template-columns: minmax(150px, 230px) 420px minmax(150px, 230px);
  }
  .cs-callouts--onboarding {
    grid-template-columns: minmax(150px, 230px) 480px minmax(150px, 230px);
  }
  .cs-callout-col {
    display: block;
    position: relative;
    z-index: 2;    /* above .cs-callout-img, so BOTH sides' lines/arrowheads
                      stay visible even where they cross over the image —
                      without this, the left column (which comes before the
                      image in the markup) paints underneath it instead. */
  }
  .cs-callout-img {
    position: relative;
    z-index: 1;
    max-width: none;
    margin-inline: 0;
  }
  .cs-callout {
    position: absolute;
    left: 0;
    right: 0;
    top: var(--top, 50%);
    transform: translateY(-50%);
    margin: 0;
    font-size: 14px;
    line-height: 20px;
    color: var(--ink-60);
  }
  .cs-callout strong {
    color: var(--ink);
    font-weight: 500;
  }
  /* Text sits nearest the edge it points across, same as the reference
     slides — with extra padding on that side so the text has room to
     breathe before the connector line starts (the line itself still
     anchors to the column's outer edge, since absolutely positioned
     ::before/::after measure from the border box, ignoring padding). */
  .cs-callout-col--left .cs-callout {
    text-align: right;
    padding-right: 20px;
  }
  .cs-callout-col--right .cs-callout {
    text-align: left;
    padding-left: 20px;
  }
  /* Line + arrowhead, left column → pointing right, across the gap and
     ~48px into the image. */
  .cs-callout-col--left .cs-callout::before {
    content: "";
    position: absolute;
    top: 50%;
    right: -76px;
    width: 76px;
    height: 1px;
    background: var(--cs-accent-text);
  }
  .cs-callout-col--left .cs-callout::after {
    content: "";
    position: absolute;
    top: 50%;
    right: -83px;
    transform: translateY(-50%);
    width: 0;
    height: 0;
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    border-left: 7px solid var(--cs-accent-text);
  }
  /* Same idea, mirrored, for the right column → pointing left. */
  .cs-callout-col--right .cs-callout::before {
    content: "";
    position: absolute;
    top: 50%;
    left: -76px;
    width: 76px;
    height: 1px;
    background: var(--cs-accent-text);
  }
  .cs-callout-col--right .cs-callout::after {
    content: "";
    position: absolute;
    top: 50%;
    left: -83px;
    transform: translateY(-50%);
    width: 0;
    height: 0;
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    border-right: 7px solid var(--cs-accent-text);
  }
}


/* Exploration image: centered above the card */
.cs-figure--explore {
  max-width: 640px;
  margin-inline: auto;
}
.cs-figure--explore img {
}

/* Testing-import video: portrait clip, kept narrower so it doesn't tower over the page, and centered.
   The max-height on the video itself is what actually forces the size down — a plain max-width on
   the figure gets beaten by the more specific .cs-section--imgonly .cs-figure rule below (560px). */
.cs-figure--centered {
  max-width: 380px;
  margin-inline: auto;
  text-align: center;
}
.cs-figure--centered video {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 90vh;
  margin: 0 auto;
}

/* Flow-complete video: same idea as above but sized down further so a tall
   portrait clip still fits comfortably within the viewport height. */
.cs-figure--sm {
  max-width: 360px;
  margin-inline: auto;
  text-align: center;
}
.cs-figure--sm video {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 90vh;
  margin: 0 auto;
}


/* Card pairs (pivot, insight) */
.cs-cardpair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
}
.cs-card {
  align-self: flex-start;   /* sit on the left */
  width: 405px;             /* match the start section's meta card width */
  max-width: 100%;
  padding: 24px;
  background: var(--paper);
  border: 1px solid var(--ink-40);
  box-shadow: 0 4px 4px rgba(10, 9, 13, 0.10);
}

/* Pivot phone-app figure (the abandoned concept) */
.cs-figure--phoneapp {
  max-width: 560px;
  margin: 0 auto 8px;
  text-align: center;
}
.cs-figure--phoneapp img {
}
.cs-struck {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  color: var(--ink-60);
}


/* A single card that spans the full column width (like a pair) */
.cs-card--wide {
  width: 100%;
  max-width: none;
}

/* Cards inside a pair fill their grid cell instead of the fixed width */
.cs-cardpair .cs-card {
  width: auto;
  align-self: stretch;
}
.cs-card-label {
  margin: 0 0 8px;
  color: var(--cs-accent-text);
}
.cs-card .type-body {
  margin: 0;
}
.cs-card .cs-livelink {
  margin-top: 20px;
}

/* Testing section: the accent-colored research question sitting between a
   session's setup line and its finding, inside a .cs-card. */
.cs-testing-q {
  margin: 20px 0 10px;
  color: var(--cs-accent-text);
  font-size: 16px;
  line-height: 24px;
  font-weight: 500;
}

/* Notes / callouts — subtle accent-tinted */
.cs-note {
  padding: 24px;
  background: color-mix(in srgb, var(--cs-accent) 14%, var(--paper));
  border-left: 2px solid var(--cs-accent-text);
}
.cs-note .type-body { margin: 0; }

/* Pull quote */
.cs-pullquote {
  margin: 0;
  max-width: 22ch;
  color: var(--ink);
}

/* Status list (Now) */
.cs-status {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 2fr 3fr; /* the longer item gets more room */
  gap: 48px;
}
.cs-status-item {
  padding-top: 20px;
  border-top: 1px solid var(--ink-12);
}
.cs-status-item .type-body {
  margin: 0;
  max-width: none;
}
/* Let the status list use the free space to the right of the column */
.cs-status {
  margin-right: -60px; /* extend into the right breathing space, no overflow */
}
@media (max-width: 1023px) {
  .cs-status { grid-template-columns: 1fr; margin-right: 0; }
}

/* Live link + next */
.cs-livelink {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  min-height: 44px;
  padding: 0 24px;
  background: var(--cs-accent);
  color: var(--ink);
  font-size: 15px;
  line-height: 20px;
  transition: transform 200ms var(--ease); /* the established button nudge */
}
.cs-livelink:hover,
.cs-livelink:focus-visible { transform: translateX(4px); }
/* Shortlist's accent is dark enough for white type on the button */
.cs[data-accent="shortlist"] .cs-livelink { color: var(--paper); }



/* --- Reveal on scroll for content blocks --- */
.cs-figure, .cs-cardpair, .cs-note, .cs-pullquote, .cs-status, .cs-principles, .cs-diagram, .cs-problem-diagram, .cs-chain, .cs-merged-eyebrow, .cs-merged-heading {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-reveal) var(--ease), transform var(--dur-reveal) var(--ease);
}
.cs-section.is-in .cs-figure,
.cs-section.is-in .cs-cardpair,
.cs-section.is-in .cs-note,
.cs-section.is-in .cs-pullquote,
.cs-section.is-in .cs-status,
.cs-section.is-in .cs-principles,
.cs-section.is-in .cs-diagram,
.cs-section.is-in .cs-problem-diagram,
.cs-section.is-in .cs-chain,
.cs-section.is-in .cs-merged-eyebrow,
.cs-section.is-in .cs-merged-heading {
  opacity: 1;
  transform: none;
}

/* --------------------------------------------------------------------------
   Case study page load-in — the nav fades in first, then the intro copy:
   the pinned panel on desktop, or the first section's inline heading on
   tablet/phone where the panel is hidden instead. Mirrors the homepage's
   load-in (styles.css 7.6): body.has-cs-intro starts things hidden at
   first paint (no flash of the fully-visible page first) and gated on
   .is-entered, which script.js adds after the window's `load` event (so
   it starts once the page's images are actually ready) plus two frames.
   Skipped entirely under reduced motion, and <noscript> in the HTML
   forces everything visible if JS never runs.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  /* No entrance fade on .nav-bar itself here either (see styles.css 7.6) —
     it just appears at full opacity once .is-entered lands. */

  body.has-cs-intro .cs-panel-inner {
    opacity: 0;
    transform: translateY(12px);
    transition: opacity 650ms var(--ease) 220ms, transform 650ms var(--ease) 220ms;
  }
  body.has-cs-intro.is-entered .cs-panel-inner {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: no-preference) and (max-width: 1023px) {
  /* .cs-panel is display:none here (see the breakpoint block below), so
     the first section's own inline heading — built by casestudy.js's
     buildInlineHeadings() before script.js's .is-entered flip — stands
     in as the page's intro copy instead. */
  body.has-cs-intro .cs-section:first-child .cs-inline {
    opacity: 0;
    transform: translateY(12px);
    transition: opacity 650ms var(--ease) 220ms, transform 650ms var(--ease) 220ms;
  }
  body.has-cs-intro.is-entered .cs-section:first-child .cs-inline {
    opacity: 1;
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   Tablet / phone: the panel stops being pinned; content stacks in flow.
   Each section shows its own heading inline instead of the swapping panel.
   -------------------------------------------------------------------------- */
@media (max-width: 1023px) {
  .cs-panel { display: none; }
  .cs-rail { display: none; }
  .cs-content { margin-left: 0; }
  .cs-section {
    min-height: 0;
    padding: 96px var(--margin);
    justify-content: flex-start;
  }
  /* The merged section's data-eyebrow/data-heading are left blank (so the
     pinned panel never shows them while this section scrolls by on desktop),
     so the inline-heading JS has nothing to build here on small screens —
     this section's own eyebrow + heading markup below is the only copy
     shown, on every breakpoint. */
  .cs-section--merged {
    padding: 96px var(--margin);
    display: block;
  }
  .cs-merged-inner {
    padding: 0;
    gap: 32px;
  }
  .cs-merged-figures {
    flex-direction: column;
  }
  /* Annotated callouts, scaled down for mobile/tablet. There's no room for
     text on both sides of the image here, so both of desktop's columns
     (.cs-callout-col--left and --right) are placed into the SAME grid
     cell, to the right of a smaller image — same merge technique desktop
     already uses to line text up with the image (align-items:stretch
     makes both column boxes exactly as tall as the image, since their
     children are position:absolute and so don't otherwise affect height).
     The image column is a PERCENTAGE of the available width (not a fixed
     px value) so it keeps shrinking in step with the text column on narrow
     phones instead of starving it of space. The block itself sits flush to
     the left edge of the content column (no auto centering) so the image
     reads as part of the left-aligned page rather than floating in the
     middle of extra tablet-width whitespace.
     The other thing that doesn't carry over from desktop is the --top
     values themselves: at desktop's size the image is tall enough that its
     own --top percentages leave room for multi-line text at each point,
     but shrunk down those same percentages would land callouts too close
     together for the (not equally shrunk) mobile text to fit without
     overlapping. --top-mobile is a second, evenly-spaced set of
     percentages — set alongside --top on each <p class="cs-callout"> in
     the HTML — chosen with enough room for this font size at this image
     size (checked against every callout's actual wrapped line count, not
     just a guess, across phone through tablet widths). Lines still point
     from the text into the image, just shorter. */
  .cs-callouts {
    display: grid;
    grid-template-columns: 36% 1fr;
    column-gap: 10px;
    align-items: stretch;
    max-width: 380px;
    margin-inline: 0;
  }
  .cs-callouts--onboarding {
    /* the onboarding screenshot is a full, very tall page, so even a
       larger image share here still leaves the text column enough room —
       and the extra height gives all 5 callouts plenty of space. */
    grid-template-columns: 40% 1fr;
  }
  .cs-callout-col {
    display: block;
    grid-column: 2;
    grid-row: 1;
    position: relative;
    z-index: 2;
  }
  .cs-callout-img {
    grid-column: 1;
    grid-row: 1;
    position: relative;
    z-index: 1;
    margin-inline: 0;
    max-width: none;
  }
  .cs-callout {
    position: absolute;
    left: 0;
    right: 0;
    top: var(--top-mobile, var(--top, 50%));
    transform: translateY(-50%);
    margin: 0;
    font-size: 11px;
    line-height: 14px;
    color: var(--ink-60);
    text-align: left;
    padding-left: 10px;
  }
  .cs-callout strong {
    color: var(--ink);
    font-weight: 500;
  }
  .cs-callout::before {
    content: "";
    position: absolute;
    top: 50%;
    left: -12px;
    width: 12px;
    height: 1px;
    background: var(--cs-accent-text);
  }
  .cs-callout::after {
    content: "";
    position: absolute;
    top: 50%;
    left: -16px;
    transform: translateY(-50%);
    width: 0;
    height: 0;
    border-top: 2.5px solid transparent;
    border-bottom: 2.5px solid transparent;
    border-right: 4px solid var(--cs-accent-text);
  }
  /* Inline heading rebuilt from data- attributes by JS on small screens */
  .cs-inline-head {
    margin: 0 0 8px;
    color: var(--cs-accent-text);
  }
  .cs-inline-title {
    margin: 0 0 16px;
  }
  .cs-inline-sub {
    margin: 0 0 12px;
    color: var(--ink);
  }
  .cs-inline-body {
    margin: 0 0 32px;
    color: var(--ink-60);
  }
  .cs-cardpair { grid-template-columns: 1fr; }
  .cs-problem-diagram { position: relative; aspect-ratio: auto; display: flex; flex-direction: column; gap: 20px; align-items: center; text-align: center; }
  /* Reorder into the causal reading order (estimation -> overcommitment ->
     urgent -> freezing) regardless of DOM order, so the chain below reads
     top to bottom the same way the desktop loop does. */
  #problem-estimation     { order: 1; }
  #problem-overcommitment { order: 2; }
  #problem-urgent         { order: 3; }
  #problem-freezing       { order: 4; }
  /* Lines stay visible and now draw a straight centered chain between the
     stacked boxes (see mobileConnections in casestudy.js) instead of the
     desktop rectangle's side-to-side edges. Needs position: relative (not
     static) so each box still out-stacks the lines svg's z-index, but that
     also reactivates the desktop left/top % offsets below, so those get
     cancelled per id right after. */
  .cs-problem-node { position: relative; transform: none; width: auto; max-width: 100%; }
  #problem-estimation, #problem-overcommitment, #problem-urgent, #problem-freezing {
    left: auto; top: auto;
  }
  /* Insight V-diagram keeps its absolute-positioned, converging layout on
     mobile too (unlike the problem cycle above, which restacks into a
     single column) — the left/top percentage coordinates already draw a
     V shape that still reads correctly at narrow widths; it just needs
     more vertical room for the wrapped text than the desktop 3:2 box, and
     a capped width so the V doesn't go sparse on wider "mobile" (tablet)
     viewports. Lines stay visible and track the nodes exactly as they do
     on desktop (see initDiagram in casestudy.js). */
  .cs-diagram { aspect-ratio: 3 / 5; max-width: 420px; }
  /* .cs-chain's nodes are already in normal vertical flow, full width,
     same as desktop — no override needed, so the connector lines (and
     touch press-and-hold, see initDiagram in casestudy.js) just work
     at any width. */
  .cs-nav { position: static; }
}

@media (prefers-reduced-motion: reduce) {
  .cs-heading, .cs-sub, .cs-body, .cs-eyebrow,
  .cs-rail-fill, .cs-dot, .cs-dot-label,
  .cs-figure, .cs-cardpair, .cs-note, .cs-pullquote, .cs-status,
  .cs-back-arrow {
    transition: none;
  }
  .cs-figure, .cs-cardpair, .cs-note, .cs-pullquote, .cs-status {
    opacity: 1;
    transform: none;
  }
}

/* Trust section: only the image on the right */
.cs-section--imgonly .cs-figure {
  align-self: center;
  max-width: 560px;
  margin: 0 auto;
}

/* Inline highlight: dark green bold (matches the accent-text tone) */
.cs-hl {
  color: var(--accent-guardian-text);
  font-weight: 500;
}

/* Next-project footer — full-width white band with a purple project button */
.cs-footer {
  position: relative;
  z-index: 20;              /* sits above the fixed left panel (z 10) */
  background: var(--paper);
  border-top: 1px solid var(--ink-12);
  padding: 80px var(--margin);
}
.cs-footer-inner {
  max-width: var(--container-max);
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: flex-end; /* content sits on the right */
  gap: 24px;
}
.cs-footer-label {
  font-size: 16px;
  line-height: 24px;
  color: var(--ink);
}
.cs-footer-btn {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 24px;
  background: var(--accent-shortlist); /* Shortlist purple */
  color: var(--paper);                 /* white type */
  font-size: 15px;
  line-height: 20px;
  font-weight: 500;
  transition: transform 200ms var(--ease);
}
.cs-footer-btn:hover,
.cs-footer-btn:focus-visible { transform: translateX(4px); }

@media (prefers-reduced-motion: reduce) {
  .cs-footer-btn { transition: none; }
  .cs-footer-btn:hover, .cs-footer-btn:focus-visible { transform: none; }
}

/* Full case study button — each page's own accent color (green on
   Guardian, purple on Shortlist), dark ink type by default. Purple is
   dark/saturated enough that ink type loses contrast, so Shortlist (and
   Copilot's blue, if it ever adds this button) flip to paper-white type
   below — same per-project text-contrast split already used by
   .work-cursor and .cs-footer-btn. */
.cs-fullcase {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  min-height: 44px;
  margin-top: 20px;
  padding: 0 24px;
  background: var(--cs-accent);
  color: var(--ink);
  font-size: 15px;
  line-height: 20px;
  font-weight: 500;
  transition: transform 200ms var(--ease);
}
.cs[data-accent="shortlist"] .cs-fullcase,
.cs[data-accent="copilot"] .cs-fullcase { color: var(--paper); }
.cs-fullcase:hover,
.cs-fullcase:focus-visible { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) {
  .cs-fullcase { transition: none; }
  .cs-fullcase:hover, .cs-fullcase:focus-visible { transform: none; }
}

/* Next-project footer button per target project */
.cs-footer-btn--guardian {
  background: var(--accent-guardian);
  color: var(--ink);
}
.cs-footer-btn--copilot {
  background: var(--accent-copilot);
  color: var(--paper); /* blue needs light text */
}
.cs-footer-btn--copilot:hover,
.cs-footer-btn--copilot:focus-visible {
  background: var(--accent-copilot-text); /* darker blue on hover */
}

/* Full-bleed sections break out to viewport width; prevent H-scroll */
html { overflow-x: hidden; }



/* Hide the rail while the panel is meeting the black task-flow band */
