/* ============================================================
   CASE STUDY TEMPLATE
   Loaded after type.css.

   A strict set of content components. Each has one job, one style, and no
   overlap with the others. If a piece of content does not fit one of these it
   needs a new component, not a variant of an existing one.

   HEAD      eyebrow (company, years) · title · standfirst · hero image
             (editorial two-column on desktop)
   CONTENT   prose · statement · callout · quote · bullets · table ·
             metrics · cards · figure
   NAV       sticky table of contents
   ============================================================ */

/* ---------- head ----------
   No breadcrumb: the header's Projects link is the way back, and a
   "Work / Case name" trail repeated it. Company and years sit above the
   title as an eyebrow. */
.cs-summary{padding:clamp(48px,6vw,96px) 0 0;}

/* A page title, not the one statement on the site, so it steps down from the
   homepage hero. */
.cs-summary .cs-title{
  font-size:clamp(1.75rem, 1.35rem + 2vw, 3.25rem);      /* 28 -> 52 */
  line-height:1.1;letter-spacing:-0.02em;margin:0;max-width:13.88em;
}
/* The standfirst is large body: it is read, not scanned, so it stays in the
   text face rather than the display one. */
.cs-summary .cs-lede{
  font-family:var(--body);font-weight:400;
  font-size:clamp(1.0625rem, 1rem + 0.5vw, 1.4375rem);   /* 17 -> 23 */
  line-height:1.5;letter-spacing:normal;color:var(--ink-2);
  margin:clamp(20px,2.4vw,30px) 0 0;max-width:58ch;
}

/* company and years above the title. No role: the case is about the product,
   and a job title undersells older work (and is on the resume anyway) */
.cs-summary .cs-eyebrow{
  font-family:var(--body);font-weight:500;font-size:var(--t-label-size);line-height:1.4;
  letter-spacing:var(--t-label-ls);text-transform:uppercase;color:var(--muted);
  margin:0 0 clamp(14px,1.6vw,20px);
}

/* the hero runs full width under the head, and carries no caption: it is the
   opening image, not a figure being referred to */
.cs-hero{margin:clamp(36px,4.5vw,64px) 0 0;}
.cs-hero .case-media{border-radius:14px;}

/* ---------- editorial head (desktop, every content page) ----------
   Title on the left at full page-title size, standfirst on the right, the
   hero image (case studies) full width beneath. From 1100px, the same point the body becomes
   contents rail + flow; below that the head stays stacked.
   Top-aligned: titles run two to three lines and standfirsts four to seven,
   so bottom alignment left short titles floating mid-block. The standfirst's
   first line is nudged down to sit near the title's cap height. It drops to
   body size: beside the title it needs no extra size to read as the intro. */
@media (min-width:1100px){
  .cs-summary.is-editorial{
    display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);
    column-gap:clamp(40px,5vw,80px);align-items:start;
  }
  .cs-summary.is-editorial .cs-eyebrow{grid-column:1 / -1;}
  .cs-summary.is-editorial .cs-title{grid-column:1;max-width:none;}
  .cs-summary.is-editorial .cs-lede{
    grid-column:2;margin:0.35em 0 0;max-width:none;
    font-size:var(--t-body-size);
  }
  .cs-summary.is-editorial .cs-hero{grid-column:1 / -1;}
}

/* ---------- gallery hero (How I work pages) ----------
   Three pages side by side in one field, the case study hero's colour, radius
   and padding. Each page is cropped tall (4:5) from its top-left corner, so
   the row reads as pages rather than thumbnails of whole screens.
   Phones: one page at a time in a sideways swipe, the next one peeking in. */
.cs-gallery{
  background:var(--case-field);border-radius:14px;
  padding:clamp(16px,3vw,40px);overflow:hidden;
}
.cs-gallery ul{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(12px,2vw,28px);margin:0;padding:0;list-style:none;
}
.cs-gallery li{margin:0;min-width:0;}
.cs-gallery img{
  display:block;width:100%;height:auto;aspect-ratio:4 / 5;
  object-fit:cover;object-position:left top;
  border-radius:5px;background:var(--paper);
  box-shadow:0 10px 26px rgba(8,14,26,.14), 0 1px 3px rgba(8,14,26,.10);
}
@media (max-width:699px){
  .cs-gallery{padding-inline:0;}
  .cs-gallery ul{
    grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:80%;
    gap:12px;overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;scroll-padding-inline:16px;padding-inline:16px;
    scrollbar-width:none;
  }
  .cs-gallery ul::-webkit-scrollbar{display:none;}
  .cs-gallery li{scroll-snap-align:start;}
  .cs-gallery ul::after{content:"";width:4px;}   /* lets the last page snap flush */
}

/* captions sit centred under their image */
.cs-flow figcaption,.cs-hero figcaption{text-align:center;}

/* ---------- body layout ---------- */
.cs-body{margin-top:clamp(56px,7vw,104px);}
@media (min-width:1100px){
  .cs-body{
    display:grid;grid-template-columns:200px minmax(0,1fr);
    gap:clamp(40px,5vw,80px);align-items:start;
  }
}
/* ---------- TWO WIDTHS, AND ONLY TWO ----------
   The flow itself is no longer measure-capped, so components declare which of
   the two widths they take. Anything added later must join one of these lists.

   READING WIDTH (68ch) - anything you read as sentences, including the boxes
   that contain sentences. A callout and a card grid are both prose in a box,
   so they align with the paragraphs around them.

   FULL COLUMN (~896px) - figures and data, which need the width and read as
   set pieces rather than as part of the sentence flow: images, tables, the
   metrics band, and code (long lines should not wrap at 68ch). */
.cs-flow{max-width:none;}
.cs-flow .body > p,
.cs-flow .body > ul,
.cs-flow .body > blockquote,
.cs-flow .body > .callout,
.cs-flow .body > .code-note,
.cs-flow .body > .cards,
.cs-section > h2{max-width:68ch;}

.cs-section{margin:0 0 clamp(56px,7vw,96px);}
.cs-section:last-child{margin-bottom:0;}
.cs-section > h2{
  font-family:var(--body);font-weight:500;
  font-size:var(--t-2-size);line-height:1.2;letter-spacing:-0.014em;
  color:var(--ink);margin:0 0 clamp(18px,2vw,26px);
  scroll-margin-top:24px;
}
/* the reset that used to undo the grid cell is gone: .cs-flow is no longer
   capped, so the per-component 68ch caps above are what constrain the text */
.cs-section .body{max-width:none;}
/* The template uses .cs-section, so type.css's `.section .body p` body role
   does not reach it and the paragraphs were inheriting ink. State it here. */
.cs-flow .body > p{
  font-family:var(--body);font-weight:400;
  font-size:var(--t-body-size);line-height:var(--t-body-lh);
  letter-spacing:normal;color:var(--ink-2);margin:0;
}
/* bold inside prose steps up to ink, which is the only emphasis mechanism now
   that the statement component is gone */
.cs-flow .body b,.cs-flow .body strong{font-weight:600;color:var(--ink);}

/* ============ CONTENT COMPONENTS ============ */

/* ---------- sub-heading ----------
   A second level inside a long section (an Outcome with adoption and
   rollout parts). Body face, one step under the section title. */
.cs-flow .body > h3{
  font-family:var(--body);font-weight:500;
  font-size:var(--t-3-size);line-height:1.3;letter-spacing:-0.01em;
  color:var(--ink);margin:0;max-width:68ch;
}
.cs-flow .body > * + h3{margin-top:clamp(40px,4.4vw,56px);}
.cs-flow .body > h3 + p{margin-top:14px;}

/* ---------- callout ----------
   A boxed aside: true, but tangential to the argument. Outlined rather than
   filled so it reads as a note and not a warning. */
.cs-flow .callout{
  display:grid;grid-template-columns:20px minmax(0,1fr);
  gap:4px 12px;align-items:start;
  border:1px solid var(--rule);border-radius:12px;
  padding:clamp(16px,1.8vw,20px) clamp(16px,2vw,22px);
  margin:0;
}
.cs-flow .callout svg{
  width:18px;height:18px;margin-top:3px;
  fill:none;stroke:var(--ink);stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;
}
.cs-flow .callout .callout-title{
  font-family:var(--body);font-weight:500;
  font-size:var(--t-body-size);line-height:1.45;color:var(--ink);margin:0;
}
.cs-flow .callout .callout-body{
  grid-column:2;
  font-family:var(--body);font-weight:400;
  font-size:var(--t-body-size);line-height:1.5;color:var(--ink-2);margin:0;
}

/* ---------- quote ----------
   An attributed quotation. Rule on the left, italic, body size — the words
   carry it rather than the type size. */
.cs-flow blockquote.quote{
  border-left:3px solid var(--rule);
  padding:0 0 0 clamp(16px,2vw,22px);
  margin:0;
}
.cs-flow blockquote.quote p.q{
  font-family:var(--body);font-weight:500;font-style:italic;
  font-size:var(--t-body-size);line-height:1.55;color:var(--ink);margin:0;
}
.cs-flow blockquote.quote cite{
  display:block;font-style:normal;
  font-family:var(--body);font-weight:400;
  font-size:var(--t-sm-size);line-height:1.4;color:var(--muted);margin-top:12px;
}

/* ---------- bullets ----------
   Small muted marker, hanging indent, roomy leading. */
.cs-flow ul.bullets{list-style:none;margin:0;padding:0;}
.cs-flow ul.bullets li{
  position:relative;padding-left:26px;
  font-family:var(--body);font-weight:400;
  font-size:var(--t-body-size);line-height:1.55;color:var(--ink-2);
}
.cs-flow ul.bullets li + li{margin-top:14px;}
.cs-flow ul.bullets li::before{
  content:"";position:absolute;left:6px;top:calc(0.775em - 3px);
  width:6px;height:6px;border-radius:50%;background:var(--muted);opacity:.55;
}

/* ---------- table ----------
   Header underlined, rows filled on hover. No vertical rules and no zebra —
   the hover is the affordance. */
.cs-flow .t-wrap{overflow-x:auto;}
.cs-flow table{width:100%;border-collapse:collapse;font-family:var(--body);}
.cs-flow thead th{
  text-align:left;font-weight:600;
  font-size:var(--t-body-size);line-height:1.4;color:var(--ink);
  padding:0 16px 12px 12px;
  border-bottom:1px solid var(--rule-2,#d8d2d0);
}
.cs-flow tbody td{
  font-weight:400;font-size:var(--t-body-size);line-height:1.5;color:var(--ink-2);
  padding:14px 16px 14px 12px;
  border-bottom:1px solid var(--rule);vertical-align:top;
}
.cs-flow tbody tr:last-child td{border-bottom:0;}
.cs-flow tbody tr{transition:background .15s;}
@media (hover:hover){.cs-flow tbody tr:hover{background:#f3f1f1;}}
.cs-flow tbody td:first-child{color:var(--ink);}
.cs-flow td code{white-space:nowrap;}

/* ---------- metrics ----------
   Headline numbers, in the content flow rather than beside the hero, so they
   sit where the claim they support is made. */
.cs-flow .metrics{
  display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(22px,2.6vw,32px);
  padding:clamp(22px,2.6vw,30px) 0;
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);
}
@media (min-width:640px){.cs-flow .metrics{grid-template-columns:repeat(4,1fr);}
  .cs-flow .metrics.three{grid-template-columns:repeat(3,1fr);}}
.cs-flow .metrics .stat{
  font-family:var(--body);font-weight:500;
  font-size:clamp(1.5rem, 1.25rem + 1.2vw, 2.125rem);    /* 24 -> 34 */
  line-height:1.05;letter-spacing:-0.03em;color:var(--ink);margin:0;
}
.cs-flow .metrics p:not(.stat){
  font-size:var(--t-sm-size);line-height:1.45;color:var(--ink-2);
  margin:8px 0 0;max-width:12.62em;
}

/* ---------- rhythm between components ----------
   type.css owns the .section pattern; the template flow needs its own, and the
   same specificity trap applies: name the element or `p{margin:0}` wins. */
.cs-flow .body > * + *{margin-top:clamp(30px,3.4vw,44px);}
.cs-flow .body > p + p{margin-top:20px;}
.cs-flow .body > * + p,
.cs-flow .body > * + ul,
.cs-flow .body > * + div,
.cs-flow .body > * + blockquote,
.cs-flow .body > * + pre,
.cs-flow .body > * + figure{margin-top:clamp(30px,3.4vw,44px);}
/* a note belongs to the block above it */
.cs-flow .body > pre + .code-note{margin-top:10px;}
.cs-flow .body > p + p{margin-top:20px;}

/* ---------- table of contents ----------
   A reading-progress rail rather than a marker that jumps: a faint track runs
   the length of the list and an ink line grows along it as the page is read,
   through each item in proportion to how far the reader is through that
   section (js/toc.js sizes it).

   Desktop: a sticky column, the line grows top to bottom.
   Below 1100px: a sticky bar under nothing but the viewport edge, the links
   scroll sideways, and the line grows left to right along its bottom edge.
   The bar is opaque and ruled, so text passes cleanly beneath it, and section
   jumps stop below it (--toc-h, measured). */
.toc{
  position:sticky;top:24px;z-index:5;
  margin-bottom:clamp(36px,4vw,56px);
}
/* four chapters fit any window, so the sticky column is not a scroll area:
   one would capture the wheel and stop the page scrolling under the pointer */
@media (min-width:1100px){.toc{margin-bottom:0;}}
.toc ol{list-style:none;margin:0;padding:0 0 0 14px;position:relative;}
.toc li + li{margin-top:2px;}
.toc a{
  display:block;padding:6px 0;
  font-family:var(--body);font-weight:400;
  font-size:var(--t-sm-size);line-height:1.35;
  color:var(--muted);text-decoration:none;
  transition:color var(--hover-t,.1s) ease;
}
.toc a.is-current{color:var(--ink);font-weight:500;}

.toc a.is-read{color:var(--ink);}

/* sub-headings are jump targets too */
.cs-flow .body > h3[id]{scroll-margin-top:24px;}

/* the rail: track and fill share one geometry */
/* position and length are set by js/toc.js */
.toc-track,.toc-fill{position:absolute;left:0;width:2px;border-radius:2px;pointer-events:none;}
.toc-track{background:var(--rule);}
.toc-fill{background:var(--ink);}

/* specific enough to beat redesign.css's main section[id] offset */
main section.cs-section[id]{scroll-margin-top:24px;}

@media (max-width:1099px){
  .toc{
    position:sticky;top:0;
    margin-inline:calc(-1 * var(--gutter));padding:0;
    background:var(--paper);border-top:0;border-bottom:1px solid var(--rule);
  }
  .toc ol{
    display:flex;gap:clamp(12px,3.1vw,26px);   /* five chapters fit a phone */
    /* sideways only: overflow-x:auto alone makes the list scrollable on both
       axes, and iOS let the bar be dragged up and down inside itself */
    overflow-x:auto;overflow-y:hidden;
    overscroll-behavior:none;   /* no rubber-band past either end (contain still bounced) */
    padding:0 var(--gutter);scrollbar-width:none;
  }
  .toc ol::-webkit-scrollbar{display:none;}
  .toc li + li{margin-top:0;}
  /* centred on the page; auto margins fall to zero when the links overflow,
     so the first one never ends up past the left edge */
  .toc li:first-child{margin-left:auto;}
  .toc li:last-of-type{margin-right:auto;}
  .toc a{white-space:nowrap;padding:15px 0;font-size:13.5px;}
  /* on the bar, not in the scrolling list: the line spans the screen and
     stays put while the links scroll sideways (js/toc.js moves it here) */
  .toc-track,.toc-fill{top:auto !important;bottom:0;height:2px !important;}
  .toc-track{background:transparent;}   /* the bar's own bottom rule is the track */
  main section.cs-section[id],.cs-flow .body > h3[id]{scroll-margin-top:calc(var(--toc-h,50px) + 20px);}
  .toc ol{padding-left:var(--gutter);}
}
@media (pointer:coarse), (max-width:768px){
  .toc a{min-height:44px;display:flex;align-items:center;}
}
@media (prefers-reduced-motion:no-preference){
  .toc-fill{transition:height .12s linear,width .12s linear;}
}

/* ---------- code ----------
   Inline code is a chip: monospace on a soft grey field, enough padding that
   it reads as a discrete token rather than tinted prose. Sized at 0.94em so it
   optically matches the surrounding text — mono runs large at the same nominal
   size. Overrides the tighter rule in site.css. */
code,
.cs-flow code,
.section .body code{
  font-family:'DM Mono',ui-monospace,'SF Mono',SFMono-Regular,Menlo,Consolas,monospace;
  font-size:0.94em;line-height:inherit;letter-spacing:normal;
  background:#eceae9;color:var(--ink);
  padding:3px 7px;border-radius:6px;
  white-space:nowrap;
}

/* A code block is a different component: multi-line, scrollable, no chip. */
.cs-flow pre{
  margin:0;padding:clamp(16px,1.8vw,22px);
  background:#f3f1f1;border:1px solid var(--rule);border-radius:12px;
  overflow-x:auto;
}
.cs-flow pre code{
  display:block;background:none;padding:0;border-radius:0;
  white-space:pre;font-size:var(--t-sm-size);line-height:1.65;color:var(--ink-2);
}
/* a caption directly under a block, for naming the file or the command */
.cs-flow pre + .code-note{
  font-size:var(--t-sm-size);line-height:1.4;color:var(--ink-2);
  margin-top:10px;
}


/* ============ IMAGE LAYOUTS ============
   Three arrangements, one rule each. Every image is cropped to the layout's
   ratio by the browser, so a supplied capture never breaks the grid — it is
   centre-cropped, which is why the capture spec asks for a central safe area.

     .media-1   one image, full column
     .media-2   two side by side, equal
     .media-3   two side by side, one wide beneath

   All three collapse to a single stacked column below 700px, where side-by-side
   would make each image too small to read. */

.media-set{
  display:grid;
  gap:clamp(12px,1.6vw,20px);
  margin:0;
}
.media-set figure{margin:0;min-width:0;}
.media-set img{
  width:100%;height:100%;display:block;
  object-fit:cover;object-position:center;
  border-radius:12px;background:var(--sink);
}
/* a figure may wrap its image in a coloured field, as the previews do */
.media-set .case-media{border-radius:12px;}

/* ---- 1 up ---- */
.media-1 img{aspect-ratio:16/10;}

/* ---- 2 up ---- */
@media (min-width:700px){
  .media-2{grid-template-columns:1fr 1fr;}
}
.media-2 img{aspect-ratio:4/3;}

/* ---- 3 up: two, then one wide ---- */
@media (min-width:700px){
  .media-3{grid-template-columns:1fr 1fr;}
  .media-3 > :nth-child(3){grid-column:1 / -1;}
}
.media-3 > :nth-child(1) img,
.media-3 > :nth-child(2) img{aspect-ratio:4/3;}
.media-3 > :nth-child(3) img{aspect-ratio:21/9;}

/* below the split point everything stacks and shares one ratio, so the rhythm
   does not lurch between 4:3 and 21:9 on a phone */
@media (max-width:699px){
  .media-set img,
  .media-3 > :nth-child(3) img{aspect-ratio:4/3;}
}

/* .is-natural: interface captures with text in them are shown whole, at
   their own ratio, instead of centre-cropped to the layout's ratio */
.media-set.is-natural img,
.media-set.is-natural > :nth-child(n) img{aspect-ratio:auto;height:auto;object-fit:contain;}
.media-set.is-natural{align-items:start;}

/* one caption under the set rather than one per image */
.media-set + .media-caption{
  font-family:var(--body);font-weight:400;
  font-size:var(--t-sm-size);line-height:1.45;color:var(--ink-2);
  text-align:center;margin-top:12px;max-width:none;
}
.cs-flow .body > * + .media-caption{margin-top:12px;}

/* ============ PICK YOUR NEXT READ ============
   The end of a case study or practice page, as a choice between two reads.
   Each option leads with what the reader gets and names the project under
   it, with a small preview beside it. Two cells in one hairline frame, side
   by side from 840px; hover selects a cell as on the homepage (Option A /
   Option B). Kept short, so it shares a screen with the footer. */
.next-read{margin-top:clamp(72px,9vw,132px);}
.next-read > h2{
  /* the display serif at title-1, like the footer's "Get in touch" */
  font-family:var(--display);font-weight:500;font-variation-settings:"opsz" 96;
  font-size:var(--t-1-size);line-height:var(--t-1-lh);letter-spacing:var(--t-1-ls);
  color:var(--ink);margin:0 0 clamp(20px,2.4vw,32px);
}
/* the frame: the grid's 1px gap shows the rule colour between the cells */
.next-read .cases-b{gap:1px;background:var(--rule);border:1px solid var(--rule);}
.next-read .cases-b > li{background:var(--paper);}   /* opaque, so the gap shows only between cells */
.next-read .card-b{
  display:grid;grid-template-columns:clamp(96px,10vw,144px) minmax(0,1fr);
  align-items:center;gap:clamp(14px,1.6vw,22px);
  padding:clamp(14px,1.6vw,20px);
}
.next-read .card-b .shot img{border-radius:6px;}
.next-read .card-b .meta{padding:0;}
.next-read .card-b h3{
  font-size:clamp(1rem,0.94rem + 0.3vw,1.1875rem);   /* 16 -> 19 */
  line-height:1.3;letter-spacing:-0.01em;margin:0;text-wrap:balance;
}
.next-read .card-b .kicker{font-size:var(--t-label-size);color:var(--ink-3);margin:6px 0 0;}
/* on the white page a white hover fill would not show: the ground grey instead
   (dark keeps --cell-hover, css/cards-b.css) */
:root:not([data-theme="dark"]) .next-read a.card-b:focus-visible{background:var(--ground);}
@media (hover:hover){:root:not([data-theme="dark"]) .next-read a.card-b:hover{background:var(--ground);}}

/* ============ ARTICLE (privacy, legal) ============
   Plain documents, deliberately not case studies: no contents rail, the head
   stays stacked, and the text starts under the title in one reading column.
   Case studies and How I work pages use the full layout above. */
.cs-body.is-article{display:block;}
.cs-body.is-article .cs-flow{max-width:52rem;}

/* ============ PROSE LINKS ============ */
/* a link line at the end of a section, to the case study the point comes from */
.cs-flow .body > p.seen-in{font-size:var(--t-sm-size);color:var(--muted);}
.cs-flow .body > p.seen-in a{color:var(--ink);text-decoration:underline;text-decoration-color:var(--rule-2);text-underline-offset:3px;}
@media (hover:hover){.cs-flow .body > p.seen-in a:hover{color:var(--accent-text);text-decoration-color:var(--accent-text);}}
.cs-flow .body > * + p.seen-in{margin-top:14px;}
/* links inside prose */
.cs-flow .body p a{color:var(--ink);text-decoration:underline;text-decoration-color:var(--rule-2);text-underline-offset:3px;transition:color var(--hover-t,.1s) ease,text-decoration-color var(--hover-t,.1s) ease;}
@media (hover:hover){.cs-flow .body p a:hover{color:var(--accent-text);text-decoration-color:var(--accent-text);}}
