/* Daljit Singh — portfolio
   Plain CSS. No build step. Edit freely.
   ---------------------------------------------------------------- */

/* Self-hosted. No third-party font request, no flash of fallback type. */
@font-face {
  font-family: "Geist";
  src: url("../fonts/geist-var.woff2") format("woff2-variations"),
       url("../fonts/geist-var.woff2") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Newsreader";
  src: url("../fonts/newsreader-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Newsreader";
  src: url("../fonts/newsreader-500.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Newsreader";
  src: url("../fonts/newsreader-400-italic.woff2") format("woff2");
  font-weight: 400; font-style: italic; font-display: swap;
}

:root {
  /* Warm off-white ground, near-black headings, cobalt accent. */
  --paper: #F8F6F1;   /* page background            */
  --panel: #EFECE4;   /* tinted blocks, callouts    */
  --card:  #FCFBF7;   /* figures, cards             */

  --ink:   #171717;   /* headings and primary text  */
  --prose: #33312D;   /* body copy                  */
  --muted: #5E5B55;   /* secondary text. Nudged darker: 6.3:1.        */
  --faint: #6F6B63;   /* small uppercase labels. Letterspaced caps need
                         more contrast than they look like they do. 4.9:1. */
  --ghost: #928D81;   /* index numbers. 3.07:1, which 30px type needs.  */
  --line:  #D9D5CD;   /* borders and rules          */

  --accent:      #3F4FB8;   /* 6.4:1 on paper. Deliberately short of
                               default-hyperlink blue.              */
  --accent-dark: #333F96;

  --sans: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --serif: "Newsreader", Georgia, "Times New Roman", serif;

  --ease: cubic-bezier(.22, .68, .16, 1);
  /* Symmetric in and out. Hover should feel the same arriving and leaving. */
  --hover-ease: cubic-bezier(.44, 0, .56, 1);

  --pad: 88px;
  --maxw: 1440px;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16.5px;
  line-height: 1.62;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img, svg { max-width: 100%; height: auto; display: block; }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-dark); }
a:focus-visible,
button:focus-visible,
input:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }

h1, h2, h3, h4 { margin: 0; font-weight: 700; letter-spacing: -0.035em; line-height: 1.06; }
p { margin: 0; }

.wrap { max-width: var(--maxw); margin: 0 auto; padding-left: var(--pad); padding-right: var(--pad); }
.serif-italic { font-family: var(--serif); font-style: italic; font-weight: 400; letter-spacing: -0.02em; }

/* The one word in the headline that is also a control. Styled to be
   invisible as a button: it inherits the h1 completely and only the
   pointer and the hover tint give it away. With JS off it is an inert
   button reading "complexity", so nothing is lost. */
.word {
  /* Inherit only what the h1 owns. Family, italic, weight and tracking
     stay with .serif-italic, which is also on this element. */
  font-size: inherit; line-height: inherit; color: inherit;
  background: none; border: 0; padding: 0; margin: 0;
  -webkit-appearance: none; appearance: none; cursor: pointer;
  transition: color 200ms var(--hover-ease);
}
.word:hover { color: var(--accent); }
.word [data-word-text] {
  display: inline-block;
  transition: clip-path 190ms var(--ease), opacity 190ms var(--ease);
  clip-path: inset(-0.25em 0 -0.25em 0);
}
.word [data-word-text].out { clip-path: inset(0 0 105% 0); opacity: 0; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- header ---------- */

.site-header {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px; padding-top: 22px; padding-bottom: 22px;
}
.wordmark { font-size: 16px; font-weight: 700; letter-spacing: -0.025em; color: var(--ink); }
.site-nav { display: flex; align-items: center; gap: 28px; font-size: 14.5px; font-weight: 500; }
.site-nav a { color: var(--muted); transition: color 150ms ease; }
.site-nav a:hover, .site-nav a[aria-current="page"] { color: var(--ink); }
.site-nav a[aria-current="page"] { font-weight: 500; }

/* ---------- hero ---------- */

.hero { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 64px; align-items: end; padding: 24px 0 34px; }
.eyebrow {
  font-size: 12px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--faint); margin-bottom: 26px;
}
.hero h1 {
  font-size: clamp(46px, 7.6vw, 112px); font-weight: 800;
  line-height: 0.90; letter-spacing: -0.058em;
  max-width: 14em;
}
/* The break is explicit rather than natural. The second word is swappable
   and the shorter words would otherwise pull it up onto line one, moving
   the whole page under it. */
.hero h1 .h1-line { display: block; }
.hero__lede { font-size: 17.5px; line-height: 1.58; color: var(--prose); max-width: 33em; margin: 32px 0 20px; text-wrap: pretty; }
.trustline {
  font-size: 12px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--faint); margin-bottom: 30px;
}
.hero-note { font-size: 14.5px; color: var(--muted); margin-top: 12px; }
.hero-actions { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; }
.hero-actions .note { font-size: 15px; color: var(--muted); }
.textlink {
  color: var(--ink); font-size: 15px; font-weight: 500; position: relative;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat; background-position: 0 100%; background-size: 0 1px;
  box-shadow: inset 0 -1px 0 var(--ghost);
  transition: background-size 380ms var(--ease), color 200ms ease;
}
.textlink:hover { color: var(--accent); background-size: 100% 1px; }

/* Outbound marker. Sized down and set slightly above the baseline so it
   reads as a sign rather than a character in the word. */
.ext { font-size: 0.82em; line-height: 1; vertical-align: 0.08em; opacity: .75; margin-left: 1px; }

.btn {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 14px 26px; border-radius: 999px;
  background: var(--accent); color: #fff;
  font-size: 15px; font-weight: 600; letter-spacing: -0.01em; border: 0; cursor: pointer;
  transition: transform 140ms ease, background 200ms ease;
}
.btn:hover { transform: translateY(-2px); background: var(--accent-dark); color: #fff; }
.btn--accent { background: var(--accent); }      /* same as .btn now, kept so old markup still works */
.btn--accent:hover { background: var(--accent-dark); }
.btn--ghost { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--line); }
.btn--ghost:hover { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink); }

/* The file is cropped to the drawing, with no blank margin baked in, so
   the image box and the ink are the same thing. That lets the right edge
   land on the same 88px content edge as the nav above it. Earlier the file
   carried ~45px of its own whitespace, which put the drawing 20px shy of
   every other edge on the page and read as misaligned.

   The paper-coloured ground matters separately: the reveal animation
   creates a stacking context, and multiply needs something to multiply
   against. */
.portrait { margin: 0 auto; align-self: center; position: relative; max-width: 300px; background: var(--paper); }
/* Her head sits high in the frame and the hair falls past it, so the mass
   is low. Nudge up so it reads centred rather than measuring centred. */
.hero .portrait { margin-right: 0; transform: translateY(-6px); }
/* Same on About. Its right column is wider than the drawing, so centring
   there left it floating with nothing to line up against. */
.about-hero .portrait { margin-right: 0; }
.portrait img {
  width: 100%; mix-blend-mode: multiply;
  /* The lag is the whole effect. The cursor leads, the drawing follows
     a beat later and settles. Set from js/motion.js, fine pointers only. */
  transition: transform 520ms var(--ease);
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .portrait img { transition: none; transform: none !important; }
}
/* The halftone portrait is a real bitmap: one dot per CSS pixel, generated
   at each breakpoint's exact width so it is never resampled down. The
   picture element picks the right file; pixelated keeps a retina screen
   from smoothing the dots into grey. The ink is baked in and the paper
   shows through the transparent gaps, so no blend mode is needed. */
.portrait--bmp img { mix-blend-mode: normal; image-rendering: pixelated; }
.portrait--bmp picture { display: block; }
.portrait figcaption { font-size: 12px; color: var(--faint); text-align: center; margin-top: 10px; }

/* ---------- clients ---------- */

.clients { display: flex; align-items: center; gap: 34px; padding-top: 18px; border-top: 1px solid var(--line); flex-wrap: wrap; }
.clients h2 {
  font-size: 12.5px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--faint); flex-shrink: 0;
}
.clients ul { display: flex; gap: 32px; list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }
.clients li { font-size: 19px; font-weight: 600; letter-spacing: -0.02em; color: var(--prose); }

/* ---------- section heads ---------- */

/* No rule underneath. The card borders already do the structuring, and
   the two together read as over-ruled. */
.section-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 20px;
  padding-bottom: 16px; margin-top: 40px;
}
.section-head h2 { font-size: 12px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); }
.section-head .aside { font-size: 12.5px; letter-spacing: 0.02em; color: var(--faint); }

/* ---------- work: cards ---------- */

.cards { list-style: none; margin: 0; padding: 0; display: grid; gap: 24px; }
.cards--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 24px; }
.cards--mini { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.card {
  position: relative;
  background: #FBFAF7;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 28px;
  cursor: pointer;
}


/* One real link per card, stretched over it. Single tab stop, no nested
   interactive elements. */
.card__title a::after { content: ""; position: absolute; inset: 0; z-index: 2; }

/* --- company mark, top left of the three featured cards --- */
/* No box, no pill. Heights are set per mark so the cap heights match
   optically rather than the bounding boxes matching numerically, and the
   bottom margin is reduced on marks that carry a descender. */
.card__logo img { display: block; width: auto; }
.card__logo--onetrust { margin-bottom: 24px; }
.card__logo--onetrust img { height: 21px; }
.card__logo--wayfair { margin-bottom: 14px; }
.card__logo--wayfair img { height: 26px; }
.card__logo--verizon { margin-bottom: 20px; }
.card__logo--verizon img { height: 22px; }

/* The year, quiet, under the title. Not an eyebrow: no caps, no tracking,
   no weight. It is a credit line, and it should read like one. */
.card__meta {
  font-size: 14px; font-weight: 400; line-height: 1.5;
  letter-spacing: -0.005em; color: var(--faint);
  margin-top: 9px;
}
.card__title {
  font-size: clamp(22px, 2.1vw, 30px); font-weight: 700;
  line-height: 1.04; letter-spacing: -0.04em;
  text-wrap: pretty;
}
.card__title a { color: var(--ink); transition: color 200ms var(--hover-ease); }
.card:hover .card__title a { color: var(--accent); }
.card__desc { font-size: 15.5px; line-height: 1.62; color: var(--prose); margin-top: 20px; max-width: 36em; }

.card__foot { margin-top: 20px; }
.impact { display: block; line-height: 1.25; text-wrap: pretty; }
.impact__num {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(30px, 2.8vw, 38px); line-height: 1.05;
  letter-spacing: -0.025em; color: var(--accent);
}
.impact__word { font-size: 15px; font-weight: 600; letter-spacing: -0.012em; color: var(--ink); margin-left: 2px; }
.impact__sub { font-size: 14px; line-height: 1.5; color: var(--muted); margin-top: 6px; max-width: 26em; }
.card__link {
  margin-top: 16px; font-size: 14.5px; font-weight: 600; letter-spacing: -0.01em;
  color: var(--ink); transition: color 200ms var(--hover-ease);
}
.card__link .arrow { display: inline-block; }
/* The title and the read link change together, as one object. Nothing
   lifts, slides, scales or changes background. */
.card:hover .card__link { color: var(--accent); }

/* --- the product screen --- */
/* Wayfair and Verizon share this exactly: same ratio, same frame, same
   inset. The pair should read as one decision, not two. */
.card__shot { margin: 0; overflow: hidden; border-radius: 6px; border: 1px solid var(--line); background: #fff; }
.card__shot img { width: 100%; display: block; }


/* --- 01, the flagship. Screen takes a little under 60% of the card. --- */
.card--lead {
  display: grid;
  grid-template-columns: minmax(0, 37fr) minmax(0, 61fr);
  grid-template-areas:
    "body shot"
    "foot shot"
    "link shot";
  grid-template-rows: auto 1fr auto;
  column-gap: 36px; padding: 30px;
}
.card--lead .card__body { grid-area: body; }
.card--lead .card__foot { grid-area: foot; padding-top: 24px; }
.card--lead .card__link { grid-area: link; margin-top: 18px; }
/* Shown whole rather than cover-cropped. The rationale block is the point
   of the screenshot, and cover was cutting it off. */
.card--lead .card__shot { grid-area: shot; align-self: center; }
.card--lead .card__title { font-size: clamp(26px, 2.6vw, 38px); }
.card--lead .card__desc { font-size: 16.5px; }
.card--lead .impact__num { font-size: clamp(36px, 3.4vw, 46px); }

/* --- 02 and 03 --- */
.cards--pair .card { display: flex; flex-direction: column; }
.cards--pair .card__shot { margin-bottom: 22px; }
/* 2:1, the same ratio as the flagship. Left-anchored so any overflow is
   trimmed from the right rather than from both sides. */
.cards--pair .card__shot img { aspect-ratio: 2 / 1; object-fit: cover; object-position: left top; }
.cards--pair .card__foot { margin-top: auto; padding-top: 20px; }

/* --- 04 and 05, compact horizontal cards, no screenshot --- */
.section-head--more { margin-top: 56px; }
.card--mini {
  display: grid; grid-template-columns: minmax(0, 1fr) 180px;
  gap: 24px; align-items: start; padding: 24px;
}
.card--mini .card__title { font-size: clamp(19px, 1.8vw, 23px); }
.card--mini .card__desc { font-size: 14.5px; margin-top: 14px; }
.card--mini .card__meta { font-size: 13px; margin-top: 8px; }
.card--mini .impact__num { font-size: clamp(22px, 2vw, 27px); }
.card--mini .card__foot { margin-top: 0; padding-top: 2px; }
.card--mini .card__link { margin-top: 12px; font-size: 13.5px; }

.card__tag {
  display: inline-block; margin-left: 8px;
  font-size: 10px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--accent); border: 1px solid currentColor; border-radius: 999px;
  padding: 2px 9px; white-space: nowrap;
}

/* ---------- live demo ---------- */

.demo { padding: 30px 0 42px 98px; }
.demo__label {
  font-size: 13px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--faint); margin-bottom: 14px;
}
/* A rebuild of the shipped review step: same columns, same confidence
   treatment, same expanded panel. Every string in it is from the Figma
   export, so nothing here is invented product copy. The one control whose
   detail the export captures is the only one that expands; the rest show a
   flat chevron. */
.reco {
  max-width: 880px; background: #fff; border: 1px solid var(--line);
  border-radius: 8px; overflow: hidden;
  box-shadow: 0 20px 40px -30px rgba(23,23,23,.4);
}
.reco__head { padding: 18px 20px 14px; }
.reco__title { font-size: 15.5px; font-weight: 600; letter-spacing: -0.012em; }
.reco__sub { font-size: 12px; line-height: 1.5; color: var(--muted); margin-top: 4px; }
.reco__risk { font-size: 12px; line-height: 1.5; color: var(--prose); margin-top: 12px; }

.reco__cols,
.reco__main {
  display: grid;
  grid-template-columns: 20px 18px minmax(0, 1fr) 150px 96px 116px;
  gap: 12px; align-items: center;
}
.reco__cols {
  padding: 9px 20px; background: #F7F7F7; border-top: 1px solid #ECECEC; border-bottom: 1px solid #ECECEC;
  font-size: 11px; font-weight: 600; letter-spacing: 0.01em; color: #3C3C3C;
}
.reco__cols span:first-child { grid-column: span 2; }

.reco__row { border-bottom: 1px solid #ECECEC; transition: background 160ms ease; }
.reco__row:last-of-type { border-bottom: 0; }
.reco__row:hover { background: #FAFAFA; }
.reco__main { padding: 11px 20px; }
.reco__check { width: 15px; height: 15px; margin: 0; accent-color: #12805C; cursor: pointer; }

/* The disclosure control. A button where there is detail to show, a flat
   mark where the export does not capture any. */
.reco__chev {
  width: 18px; height: 18px; padding: 0; border: 0; background: none; cursor: pointer;
  position: relative;
}
.reco__chev::after {
  content: ""; position: absolute; left: 4px; top: 5px;
  width: 7px; height: 7px; border-right: 1.5px solid #5A5A5A; border-bottom: 1.5px solid #5A5A5A;
  transform: rotate(45deg); transition: transform 200ms var(--ease);
}
.reco__row[data-open="true"] .reco__chev::after { transform: rotate(225deg); top: 7px; }
.reco__chev--off { display: block; }
.reco__chev--off::after { border-color: #C9C9C9; }

.reco__name { font-size: 12.5px; color: #1A1A1A; cursor: pointer; }
.reco__code { display: block; font-size: 10.5px; color: #767676; margin-top: 1px; }
.reco__cell { font-size: 12px; color: #4A4A4A; }
.reco__conf { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #1A1A1A; }
.reco__dot { width: 6px; height: 6px; border-radius: 50%; background: #12805C; flex-shrink: 0; }

.reco__reason { padding: 4px 20px 18px 70px; }
.reco__detail { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 40px; }
.reco__detail h4 { font-size: 12px; font-weight: 600; color: #3C3C3C; margin-bottom: 4px; letter-spacing: 0; }
.reco__detail h4 + p { margin-bottom: 14px; }
.reco__detail p { font-size: 11.5px; line-height: 1.5; color: #5A5A5A; }
.reco__detail > div > p:last-child { margin-bottom: 0; }
.reco__dismiss { margin-top: 10px; font-size: 11.5px; color: #1B63C4; }

.reco__foot {
  display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  padding: 12px 20px; border-top: 1px solid #ECECEC; background: #FAFAFA;
}
.reco__note { font-size: 11px; color: #5A5A5A; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.reco__ai {
  background: #4B3FCF; color: #fff; border-radius: 3px; padding: 1px 4px;
  font-size: 8.5px; font-weight: 700; letter-spacing: 0.04em;
}
.reco__shown { color: #8A8A8A; }
.reco__actions { display: flex; align-items: center; gap: 10px; }
.reco__count { font-size: 11.5px; color: var(--muted); }
.reco__btn, .reco__apply {
  padding: 6px 13px; border-radius: 4px; font-family: inherit;
  font-size: 12px; font-weight: 600; cursor: pointer;
}
.reco__btn { background: #fff; border: 1px solid #C9C9C9; color: #1A1A1A; }
.reco__apply { background: #12805C; border: 1px solid #12805C; color: #fff; }
.reco__apply[disabled] { background: #DCDCDC; border-color: #DCDCDC; color: #8A8A8A; cursor: default; }

/* ---------- fun ---------- */

.fun { display: grid; grid-template-columns: repeat(3, 1fr); gap: 40px; padding: 32px 0 80px; }
.fun__kicker { font-size: 12.5px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent); margin-bottom: 12px; }
.fun__item h3 { font-size: 22px; letter-spacing: -0.028em; margin-bottom: 10px; }
.fun__item p { font-size: 15.5px; color: var(--prose); margin-bottom: 14px; }
.fun__item--empty .fun__kicker, .fun__item--empty h3 { color: var(--ghost); }
.fun__item--empty p { color: var(--muted); }

/* ---------- beliefs ---------- */

.beliefs { background: var(--panel); padding: 76px 0; margin-top: 0; }
.beliefs__grid { display: grid; grid-template-columns: 4fr 8fr; gap: 40px; align-items: start; }
.beliefs__intro h2 { font-size: 15px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; }
.beliefs__intro p { font-size: 15px; color: var(--muted); margin-top: 14px; }
.beliefs__list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 30px 44px; list-style: none; margin: 0; padding: 0; }
.beliefs__list h3 { font-size: 20px; letter-spacing: -0.026em; margin-bottom: 8px; }
.beliefs__list p { font-size: 15.5px; color: var(--prose); }

/* ---------- contact ---------- */

.contact { padding: 84px 0; }
.contact h2 { font-size: clamp(38px, 5.4vw, 78px); font-weight: 800; line-height: 0.92; letter-spacing: -0.058em; margin-bottom: 26px; }
.contact p { font-size: 18px; color: var(--prose); max-width: 40em; margin-bottom: 32px; }
.contact__row { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.contact__links { display: flex; gap: 22px; font-size: 15px; flex-wrap: wrap; }
.contact__links a { color: var(--muted); }
.contact__links a:hover { color: var(--ink); }

.site-footer { padding: 0 0 48px; font-size: 13px; letter-spacing: 0.01em; color: var(--faint); }
.site-footer p + p { margin-top: 6px; }

/* ---------- case study ---------- */

.cs-hero { padding: 40px 0 44px; }
/* Same mark as the homepage card, one step larger because it is carrying a
   page rather than a row. The h1 no longer says the company name; the mark
   and the <title> do that. */
.cs-logo img { display: block; width: auto; }
.cs-logo--onetrust { margin-bottom: 22px; }
.cs-logo--onetrust img { height: 26px; }
.cs-logo--wayfair { margin-bottom: 16px; }
.cs-logo--wayfair img { height: 32px; }
.cs-logo--verizon { margin-bottom: 22px; }
.cs-logo--verizon img { height: 27px; }
.cs-hero h1 { font-size: clamp(38px, 5.2vw, 78px); font-weight: 800; line-height: 0.94; letter-spacing: -0.052em; margin-bottom: 26px; max-width: 15em; }
.cs-hero .standfirst { font-family: var(--serif); font-style: italic; font-size: clamp(20px, 2.1vw, 26px); line-height: 1.42; letter-spacing: -0.015em; color: var(--prose); max-width: 30em; }

.cs-meta { border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink); }
.cs-meta dl { display: grid; grid-template-columns: repeat(4, 1fr); gap: 32px; margin: 0; padding: 20px 0; }
.cs-meta dt { font-size: 10px; font-weight: 600; letter-spacing: 0.17em; text-transform: uppercase; color: var(--faint); margin-bottom: 7px; }
.cs-meta dd { margin: 0; font-size: 14px; line-height: 1.45; }

.cs-section { display: grid; grid-template-columns: 3fr 9fr; gap: 40px; padding: 56px 0 0; align-items: start; }
.cs-section > * { min-width: 0; }
.cs-section > .cs-label { font-size: 10.5px; font-weight: 600; letter-spacing: 0.17em; text-transform: uppercase; color: var(--accent); }
.cs-section h2 { font-size: clamp(26px, 2.9vw, 42px); font-weight: 700; line-height: 1.0; letter-spacing: -0.042em; margin-bottom: 22px; max-width: 19em; }
/* Scoped to direct prose paragraphs only. As a bare `.cs-section p` this
   leaked serif, 18.5px and a 38em measure into the live demo. */
.cs-section > div > p { font-family: var(--serif); font-size: 18.5px; line-height: 1.64; color: var(--prose); max-width: 38em; margin-bottom: 17px; }
.cs-section > div > p:last-child { margin-bottom: 0; }

.cs-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-top: 24px; }
.cs-cards h3 { font-size: 16.5px; font-weight: 700; letter-spacing: -0.025em; margin-bottom: 9px; }
.cs-cards p { font-family: var(--sans); font-size: 14px; line-height: 1.6; color: var(--prose); }
.cs-cards li { border-top: 1px solid var(--ink); padding-top: 16px; list-style: none; }

.cs-figure { background: var(--card); border: 1px solid var(--line); border-radius: 8px; padding: 32px; margin-top: 24px; }
.cs-stat { display: grid; grid-template-columns: 260px 1fr; gap: 32px; align-items: center; }
.cs-stat .big { font-family: var(--serif); font-weight: 400; font-size: 72px; line-height: 0.92; letter-spacing: -0.03em; color: var(--accent); }
.cs-stat .cap { font-size: 11px; font-weight: 600; letter-spacing: 0.15em; text-transform: uppercase; color: var(--muted); margin-top: 12px; }
.cs-stat__lede { font-family: var(--serif); font-size: 18px; line-height: 1.6; margin-bottom: 14px; }
.cs-stat__note { font-family: var(--sans); font-size: 14px; line-height: 1.6; color: var(--prose); margin: 0; }
.cs-cards--spaced { margin-top: 28px; }
.cs-aside { margin-top: 22px; font-style: italic; }
.cs-section--last { padding-bottom: 72px; }
.option:not(.option--chosen) h3 { color: var(--muted); }
.option:not(.option--chosen) .for h4 { color: var(--faint); }
.option:not(.option--chosen) .for ul { color: var(--muted); }
.demo--flush { padding-left: 0; }
.reco__actions { display: flex; align-items: center; gap: 9px; }

.options { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin-top: 24px; }
.option { background: var(--card); border: 1px solid var(--line); border-radius: 8px; padding: 26px; }
.option--chosen { border-color: var(--accent); }
.option__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 16px; }
.option__tag { font-size: 10px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--faint); }
.badge { font-size: 10px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; background: var(--accent); color: var(--paper); padding: 4px 9px; border-radius: 3px; }
.option h3 { font-size: 19px; font-weight: 700; letter-spacing: -0.03em; margin-bottom: 18px; }
.option__cols { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
.option__cols h4 { font-size: 9.5px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; margin-bottom: 9px; }
.option__cols ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; font-size: 13.5px; line-height: 1.5; }
.for h4 { color: var(--accent); }
.against h4, .against ul { color: var(--muted); }

.measure { border-top: 1px solid var(--ink); margin-top: 24px; }
.measure__row > * { min-width: 0; }
.measure__row { display: grid; grid-template-columns: 220px 1fr 300px; gap: 28px; padding: 20px 0; border-bottom: 1px solid var(--line); }
.measure__row:last-child { border-bottom: 1px solid var(--ink); }
.measure__row h3 { font-size: 16.5px; font-weight: 700; letter-spacing: -0.025em; }
.measure__row p { font-family: var(--sans); font-size: 14.5px; line-height: 1.55; color: var(--prose); margin: 0; }
.measure__row ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; line-height: 1.5; color: var(--muted); }

/* The demo is a UI component, not prose. Stop the case study's serif and
   its 38em measure from leaking into it. */
.cs-section .reco,
.cs-section .reco p,
.cs-section .reco h4,
.cs-section .reco label,
.cs-section .reco button { font-family: var(--sans); }
.cs-section .reco p { max-width: none; margin-bottom: 0; }
/* Re-assert the detail panel's own rhythm. The line above zeroes every
   margin inside the demo, and at equal specificity it would win. */
.cs-section .reco__detail h4 { margin-top: 16px; }
.cs-section .reco__detail > div > h4:first-child { margin-top: 0; }

/* ---------- 404 ---------- */

/* Borrows the case study hero so the page is unmistakably part of the
   site rather than a server default. Vercel serves this automatically
   for any unmatched path on a static deploy. */
/* Its own hero rather than the case study one, so motion.js does not
   mistake a 404 for a case study and staple a reading progress bar to it. */
.nf-hero { padding: 40px 0 20px; }
.nf-hero h1 { font-size: clamp(38px, 5.2vw, 78px); font-weight: 800; line-height: 0.94; letter-spacing: -0.052em; margin-bottom: 26px; max-width: 15em; }
.nf-hero .standfirst { font-family: var(--serif); font-style: italic; font-size: clamp(20px, 2.1vw, 26px); line-height: 1.42; letter-spacing: -0.015em; color: var(--prose); max-width: 30em; }
.nf-list { list-style: none; margin: 0; padding: 0 0 40px; border-top: 1px solid var(--ink); }
.nf-list li { border-bottom: 1px solid var(--line); }
.nf-list a {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 24px; flex-wrap: wrap; padding: 20px 2px;
  color: var(--ink); transition: color 200ms var(--hover-ease);
}
.nf-list a:hover { color: var(--accent); }
.nf-list__title { font-size: clamp(20px, 2.2vw, 27px); font-weight: 700; letter-spacing: -0.035em; }
.nf-list__meta { font-size: 14px; color: var(--faint); }

/* ---------- case study figures ---------- */

.cs-shot { margin: 28px 0 0; }
.cs-shot img { width: 100%; border-radius: 4px; }
.cs-shot > img,
.cs-shot .frame > img { box-shadow: 0 0 0 1px var(--line), 0 32px 54px -48px rgba(23,23,23,.8); border-radius: 4px; }
/* The caption is a label for the image, so it runs to the same edges as
   the image rather than to a reading measure. No max-width: whatever the
   figure is, the caption matches. */
.cs-shot figcaption {
  font-family: var(--sans); font-size: 13px; line-height: 1.5;
  color: var(--faint); margin-top: 12px; text-wrap: pretty;
}
.cs-shot .frame { overflow: hidden; border-radius: 4px; }
/* A detail shot rather than a second hero. Narrower so it reads as an
   aside next to the full-width image above it. */
.cs-shot--half { max-width: 50%; }

.cs-ph {
  display: flex; align-items: center; justify-content: center; text-align: center;
  aspect-ratio: 16 / 9; padding: 28px;
  border: 1px dashed var(--ghost); border-radius: 4px; background: var(--panel);
}
.cs-ph p { font-family: var(--sans) !important; font-size: 13.5px !important; line-height: 1.55; color: var(--muted); max-width: 30em; margin: 0 !important; }
.cs-ph strong { display: block; font-size: 11px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); margin-bottom: 8px; }

/* ---------- case study footer nav ---------- */

.cs-next {
  display: flex; align-items: baseline; justify-content: space-between; gap: 24px; flex-wrap: wrap;
  border-top: 1px solid var(--ink); padding-top: 26px; margin-top: 72px;
}
.cs-next__label { font-size: 10.5px; font-weight: 600; letter-spacing: 0.17em; text-transform: uppercase; color: var(--faint); }
.cs-next__title { font-size: clamp(21px, 2.4vw, 34px); font-weight: 700; letter-spacing: -0.042em; margin-top: 10px; }
.cs-next__title a { color: var(--ink); }
.cs-next__title a:hover { color: var(--accent); }
.cs-next .arrow { display: inline-block; transition: transform 200ms cubic-bezier(.2,.8,.2,1); }
.cs-next:hover .arrow { transform: translateX(4px); }

.callout { display: flex; gap: 12px; margin-top: 22px; padding: 18px 20px; background: var(--panel); border-left: 2px solid var(--accent); }
.callout p { font-family: var(--sans); font-size: 14.5px; line-height: 1.6; color: var(--prose); margin: 0; }

.pullquote { font-family: var(--serif); font-style: italic; font-size: clamp(24px, 2.9vw, 40px); line-height: 1.2; letter-spacing: -0.028em; max-width: 20em; margin-bottom: 30px; }

/* ---------- about ---------- */

.about-hero { display: grid; grid-template-columns: 7fr 5fr; gap: 56px; align-items: start; padding: 36px 0 56px; }
/* The opening line is her own sentence rather than a slogan, so it is set
   at statement size rather than poster size. */
.about-hero h1 { font-size: clamp(26px, 2.9vw, 40px); font-weight: 700; line-height: 1.16; letter-spacing: -0.032em; margin-bottom: 26px; max-width: 18em; }
.about-hero > div > p { font-family: var(--serif); font-size: 18.5px; line-height: 1.64; color: var(--prose); margin-bottom: 17px; max-width: 34em; }
.about-cta { margin-top: 26px; }

/* Features and talks. A plain two-part row: what it was, then where. */
.press { list-style: none; margin: 0; padding: 0 0 8px; border-top: 1px solid var(--ink); }
.press li {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; padding: 16px 2px; border-bottom: 1px solid var(--line);
}
.press li > a, .press li > span:first-child {
  font-size: 16.5px; font-weight: 600; letter-spacing: -0.02em; color: var(--ink);
  transition: color 200ms var(--hover-ease);
}
.press li > a:hover { color: var(--accent); }
.press__meta { font-size: 13.5px; color: var(--faint); }

/* The photos. Square, six across, cropped by the cell rather than letterboxed. */
.life { list-style: none; margin: 0; padding: 0 0 8px; display: grid; grid-template-columns: repeat(6, 1fr); gap: 10px; }
.life img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 4px; display: block; }
/* The only hover on the site that is not type. An image cannot change
   colour, so it lightens instead. Same 200ms, same curve. */
.life a { display: block; transition: opacity 200ms var(--hover-ease); }
.life a:hover { opacity: 0.82; }
.about-hero .standfirst { font-family: var(--serif); font-style: italic; font-size: 22px; line-height: 1.48; letter-spacing: -0.015em; color: var(--prose); max-width: 26em; }
.about-cols { display: grid; grid-template-columns: repeat(2, 1fr); gap: 44px; }
.about-cols p { font-family: var(--serif); font-size: 18.5px; line-height: 1.64; color: var(--prose); margin-bottom: 17px; }

.path { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; list-style: none; margin: 0 0 44px; padding: 0; }
.path--design { grid-template-columns: repeat(5, 1fr); margin-bottom: 0; }
.path li { border-top: 2px solid var(--ghost); padding-top: 14px; }
.path--design li { border-top-color: var(--ink); }
.path .years { font-size: 12px; color: var(--faint); margin-bottom: 8px; }
.path h3 { font-size: 16.5px; font-weight: 700; letter-spacing: -0.025em; margin-bottom: 7px; }
.path p { font-size: 13.5px; line-height: 1.55; color: var(--prose); }
.band-label { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
.band-label span { font-size: 10.5px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--faint); }
.band-label .rule { flex-grow: 1; height: 1px; background: var(--line); }
.band-label--design span { color: var(--accent); }
.band-label--design .rule { background: var(--accent); }

/* ---------- responsive ---------- */

@media (max-width: 1120px) {
  :root { --pad: 48px; }
  .about-hero { grid-template-columns: 1fr; gap: 40px; }
  .life { grid-template-columns: repeat(3, 1fr); }
  .hero { grid-template-columns: minmax(0, 1fr) 240px; gap: 44px; }
  .portrait { max-width: 240px; }
  .card--lead { grid-template-columns: minmax(0, 38fr) minmax(0, 60fr); column-gap: 28px; }
  .card--mini { grid-template-columns: minmax(0, 1fr) 150px; gap: 20px; }
  .demo { padding-left: 0; }
  .cs-section { grid-template-columns: 1fr; gap: 16px; }
  .measure__row { grid-template-columns: 1fr; gap: 10px; }
  .beliefs__grid { grid-template-columns: 1fr; }
  .path, .path--design { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 820px) {
  :root { --pad: 24px; }
  body { font-size: 16px; }
  .site-header { flex-wrap: wrap; gap: 14px; }
  .site-nav { gap: 20px; font-size: 14px; }
  .fun, .cs-cards, .options, .about-cols, .beliefs__list, .cs-meta dl { grid-template-columns: 1fr; }
  .hero { grid-template-columns: 1fr; gap: 30px; align-items: start; }
  .portrait { max-width: 200px; margin: 0; }
  /* Dense product screens scroll sideways at a readable height on a phone. */
  .cs-shot .frame { overflow-x: auto; overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch; }
  .cs-shot .frame > img { width: auto; max-width: none; height: 320px; }
  /* A photograph is not a dense UI screen, so it should fit rather than
     scroll sideways like the product shots do. */
  .cs-shot--half { max-width: none; }
  .cs-shot--photo .frame { overflow-x: visible; }
  .cs-shot--photo .frame > img, .cs-shot--half .frame > img { width: 100%; height: auto; }
  /* Cards stack. The screen sits above the copy in every card, including
     the lead one, and is scaled up so it stays legible on a phone. */
  .cards--pair, .cards--mini { grid-template-columns: 1fr; }
  .card, .card--mini { display: block; padding: 22px; }
  /* The flagship stacks logo, title, year, description, impact, image,
     link. Built from grid areas rather than by shrinking the desktop
     columns. */
  .card--lead {
    grid-template-columns: 1fr;
    grid-template-areas: "body" "foot" "shot" "link";
    grid-template-rows: auto auto auto auto;
    padding: 22px;
  }
  .card--lead .card__shot { align-self: stretch; margin-top: 22px; }
  .card--lead .card__foot { padding-top: 18px; }
  .card--lead .card__link { margin-top: 18px; }
  /* All three screens get the same 185% enlargement and are cropped by
     their frame, so the pair and the flagship read as one treatment. */
  .card--lead .card__shot img { width: 185%; max-width: none; }
  .cards--pair .card__shot img { aspect-ratio: auto; width: 185%; max-width: none; }
  .cards--pair .card__foot, .card--mini .card__foot { margin-top: 18px; padding-top: 0; }
  .card--mini .card__foot { margin-top: 16px; }
  .section-head--more { margin-top: 40px; }
  .section-head { flex-direction: column; gap: 6px; align-items: flex-start; }
  .cs-meta dl { gap: 18px; }
  .cs-stat { grid-template-columns: 1fr; gap: 16px; }
  .reco__cols { display: none; }
  .reco__main { grid-template-columns: 20px 18px minmax(0, 1fr); row-gap: 8px; }
  .reco__cell, .reco__conf { grid-column: 3; font-size: 11.5px; }
  .reco__reason { padding-left: 20px; }
  .reco__detail { grid-template-columns: 1fr; gap: 0; }
  /* Stacked, the second column's first heading needs the same rhythm as
     the rest. Side by side it sits at the top and does not. */
  .cs-section .reco__detail > div + div > h4:first-child { margin-top: 16px; }
  .clients ul { gap: 20px; }
  .clients li { font-size: 17px; }
}

@media (max-width: 560px) {
  .path, .path--design { grid-template-columns: 1fr; }
  .life { grid-template-columns: repeat(2, 1fr); }
}

/* ================================================================
   MOTION
   Everything here is progressive enhancement. The .js class is set
   by motion.js, so with JavaScript off nothing is ever hidden.
   ================================================================ */

/* --- scroll reveal --- */
.js [data-reveal] { opacity: 0; transform: translateY(20px); }
.js [data-reveal].in {
  opacity: 1; transform: none;
  transition: opacity 760ms var(--ease), transform 860ms var(--ease);
  transition-delay: var(--d, 0ms);
}

/* --- hero entrance --- */
.js .hero [data-lift] { opacity: 0; transform: translateY(16px); }
.js .hero h1[data-lift] { clip-path: inset(0 0 105% 0); transform: translateY(0); }
.js .hero.ready [data-lift] {
  opacity: 1; transform: none;
  transition: opacity 720ms var(--ease), transform 900ms var(--ease), clip-path 1050ms var(--ease);
  transition-delay: var(--d, 0ms);
}
.js .hero.ready h1[data-lift] { clip-path: inset(-0.25em 0 -0.25em 0); }

/* --- work index rows --- */



/* --- the metric wipes up from its own baseline --- */
.js [data-reveal] .impact__num,
.js [data-reveal] .cs-stat .big { clip-path: inset(0 0 105% 0); }
.js [data-reveal].in .impact__num,
.js [data-reveal].in .cs-stat .big {
  clip-path: inset(-0.2em 0 -0.2em 0);
  transition: clip-path 900ms var(--ease) 180ms;
}

/* --- reading progress, case studies only --- */
.progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 40;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  will-change: transform;
}

/* --- header hides going down, returns coming up --- */
.site-header {
  position: sticky; top: 0; z-index: 30; background: var(--paper);
  transition: transform 420ms var(--ease);
}
.nav-up .site-header { transform: translateY(-101%); }

/* --- arrows and buttons --- */
.cs-next__title a, .band__link a { transition: color 200ms var(--hover-ease); }

@media (prefers-reduced-motion: reduce) {
  .js [data-reveal],
  .js .hero [data-lift],
  .js .hero h1[data-lift] { opacity: 1 !important; transform: none !important; clip-path: none !important; }
  .js [data-reveal] .impact__num,
  .js [data-reveal] .cs-stat .big { clip-path: none !important; }
  .card__title a, .card__link, .textlink, .site-header { transition: none !important; }
  .word [data-word-text] { transition: none !important; clip-path: none !important; opacity: 1 !important; }
  .progress { display: none; }
}
