/* ============================================================
   SITE.CSS — all the styling for the site lives here.
   The only part you'll likely want to touch is "BRAND TOKENS"
   directly below. Change a value there and it updates everywhere.
   ============================================================ */

/* ---------- BRAND TOKENS ---------------------------------- */
:root {
  /* THREE faces, by job:

       --font-title    Komu. EVERY title and heading, including the
                       wordmark and the objective/process/result labels.
       --font-display  Inter Tight. The few bits of UI that are neither
                       heading nor body: arrow links, the contact email.
       --font-body     Inter. All body copy.

     Komu ships each cut (komu-new-c / d / e / f) as its own family at
     a single weight, so anything set in it uses font-weight 400 and
     hierarchy comes from size alone. Swap the letter below to change
     cut: c, d, e or f.

     A weight the CSS asks for but the font request omits fails
     silently — font-synthesis-weight is none, so the browser just
     substitutes the nearest weight it has. */
  --font-title: "komu-new-f", "Inter Tight", sans-serif;
  --font-display: "Inter Tight", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;
  /* Colour. Pale cream paper, near-black ink, green for the graphic
     mats behind cards and images, red for titles and accents.

     Two reds, split by SIZE not by use. #D95555 measures 3.45:1 on
     this cream: fine for display type (needs 3:1), short of the 4.5:1
     that small text needs. So the given red carries the big titles,
     and a deeper one carries labels and links. */
  --bg: #ffffff;
  --bg-sunk: #f4f4f4;
  --fg: #000000;
  --muted: #6b6b6b;       /* 5.33:1 on white */
  --line: #dcdcdc;

  /* The site is black and white on purpose. All the colour on the
     page comes from the work — the illustrations, the certificates,
     the project covers — so the chrome stays out of the way. If you ever want an
     accent back, change --accent (fills, mats, rules) and
     --accent-ink (accent text) and nothing else needs touching. */
  --accent: #000000;      /* mats, borders, rules */
  --accent-fg: #ffffff;   /* sits on top of --accent */
  --title: #000000;       /* display headings */
  --accent-ink: #000000;  /* accent text at body sizes */

  /* The one deliberate exception to the black-and-white rule. A
     status light that isn't green isn't a status light. 3.3:1 on
     white, which clears the 3:1 a meaningful indicator needs. */
  --status: #16a34a;

  /* Section labels - Brief Description / Process / Result, the
     certificate names, and the Contact heading all read as one style.
     Defined once here so they can't drift apart.

     Tracking is POSITIVE. Komu is condensed, and these are set in
     caps: negative tracking jams the strokes together and the words
     turn to mush at label size. */
  --label-size: 1.25rem;
  --label-tracking: 0.03em;

  /* Rhythm */
  --measure: 62ch;
  --gutter: clamp(1.25rem, 5vw, 4.5rem);
  --section: clamp(4.5rem, 11vw, 9rem);
  --radius: 4px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* No dark mode. The site is always black on white, so the
   palette above is the whole story. Adding one back means a
   @media (prefers-color-scheme: dark) block here plus a way to
   switch — see git history for the version that had it. */

/* ---------- RESET ----------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  font-synthesis-weight: none;
  overflow-x: hidden;
}

img, video, svg { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
button { font: inherit; color: inherit; }

::selection { background: var(--accent); color: var(--accent-fg); }

:focus-visible {
  outline: 2px solid var(--accent-ink);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--fg);
  color: var(--bg);
  padding: 0.75rem 1.25rem;
  z-index: 100;
}
.skip:focus { left: 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;
}

/* ---------- LAYOUT ---------------------------------------- */
.wrap {
  width: 100%;
  max-width: 1440px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--narrow { max-width: 900px; }

.section { padding-block: var(--section); }
.stack > * + * { margin-top: 1rem; }

/* ---------- TYPE ------------------------------------------ */
h1, h2, h3, h4 {
  font-family: var(--font-title);
  /* Komu has one weight. Asking for anything else finds nothing. */
  font-weight: 400;
  line-height: 1.04;
  /* Loosened from -0.032em: tuned for Inter Tight, too tight for Komu. */
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.display {
  font-size: clamp(2.75rem, 1.2rem + 7vw, 7rem);
  letter-spacing: -0.015em;
}
.h2 { font-size: clamp(1.85rem, 1.1rem + 3vw, 3.4rem); }
.h3 { font-size: clamp(1.3rem, 1rem + 1.2vw, 1.9rem); letter-spacing: -0.005em; }

.lede {
  font-size: clamp(1.15rem, 1rem + 0.75vw, 1.6rem);
  line-height: 1.42;
  letter-spacing: -0.014em;
  max-width: 34ch;
  text-wrap: pretty;
}

.prose { max-width: var(--measure); }
.prose p + p { margin-top: 1.15em; }
.prose p { text-wrap: pretty; }

.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.muted { color: var(--muted); }

/* Section headings with a rule across the top */

/* ---------- LINKS ----------------------------------------- */
.link {
  color: inherit;
  text-decoration: none;
  background-image: linear-gradient(var(--fg), var(--fg));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  transition: background-size 0.4s var(--ease);
  padding-bottom: 1px;
}
.link:hover { background-size: 0% 1px; background-position: 100% 100%; }

.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  text-decoration: none;
  font-family: var(--font-display);
  letter-spacing: -0.01em;
}
.arrow-link span:last-child { transition: transform 0.35s var(--ease); }
.arrow-link:hover span:last-child { transform: translateX(0.3em); }

/* ---------- HEADER ---------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(1.6) blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease);
}
.site-header[data-scrolled="true"] { border-bottom-color: var(--line); }

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  height: 4.5rem;
}

.wordmark {
  font-family: var(--font-title);
  font-weight: 400;
  font-size: 1.0625rem;
  letter-spacing: -0.03em;
  text-decoration: none;
  white-space: nowrap;
}

.nav { display: flex; align-items: center; gap: clamp(1rem, 3vw, 2.25rem); }
.nav a {
  text-decoration: none;
  font-size: 0.9375rem;
  color: var(--muted);
  transition: color 0.2s var(--ease);
}
.nav a:hover, .nav a[aria-current="page"] { color: var(--fg); }

/* ---------- HERO ------------------------------------------ */
.hero { padding-block: clamp(3.5rem, 9vw, 8rem) clamp(3rem, 7vw, 6rem); }
.hero__meta {
  display: flex; flex-wrap: wrap; gap: 0.75rem 1.5rem;
  align-items: center;
  margin-bottom: clamp(1.75rem, 4vw, 3rem);
}

.status {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--font-mono); font-size: 0.72rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
}
.status::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--status);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--status) 70%, transparent);
  animation: pulse 2.4s infinite;
}
@keyframes pulse {
  70% { box-shadow: 0 0 0 7px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* Hero: the copy on one side, an illustration on the other. Keeps
   the positioning statement visible while the drawing carries the
   personality — and fills the empty right-hand column the hero
   used to have. */
.hero-split {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3.5rem);
  grid-template-columns: 1fr;
  align-items: center;
}
.hero-split .display { font-size: clamp(2.2rem, 1rem + 5vw, 5rem); }
/* Text-only hero, so the intro gets a proper reading measure rather than
   the narrow column it had when an image sat beside it. */
.hero-split .lede { margin-top: 1.75rem; max-width: 58ch; }
.hero-split__offers { margin-top: 1.5rem; color: var(--muted); }
.hero-split__cta { margin-top: 1rem; }

/* ---------- ABOUT: TEXT BESIDE THE DRAWING ----------------
   Same shape as .hero-split, but the illustration takes less of
   the row: this section is text first, picture second.
   ---------------------------------------------------------- */
.about-split {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3.5rem);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 900px) {
  .about-split { grid-template-columns: 1fr 0.72fr; }
}
.about-split figure { margin: 0; }
.about-split img { width: 100%; border-radius: var(--radius); }

/* ---------- WORK MARQUEE ----------------------------------
   A band of work that drifts left forever. Full-bleed, so it
   deliberately ignores .wrap.

   Spacing is margin-right on each figure rather than gap on the
   flex container. With gap, one set plus its trailing gap is not
   exactly a third of the track, and the loop visibly jumps.
   ---------------------------------------------------------- */
/* With no images in it the band would be two rules around a gap,
   so it takes itself off the page until there is something to show. */
.marquee:not(:has(img)) { display: none; }

/* The label belongs to the band, so it takes the section's top margin
   and the band tucks up underneath it. */
.marquee-label { margin-top: clamp(2.5rem, 6vw, 4.5rem); }
.marquee-label p { margin: 0; }
.marquee-label + .marquee { margin-top: 0.85rem; }
/* Empty band, no label either. */
.marquee-label:has(+ .marquee:not(:has(img))) { display: none; }

.marquee {
  overflow: hidden;
  margin-block: clamp(2.5rem, 6vw, 4.5rem);
  padding-block: clamp(1.25rem, 3vw, 2rem);
  border-block: 1px solid var(--line);
  /* Fades both ends into the page instead of cutting the images
     off against a hard edge. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}

.marquee__track {
  display: flex;
  width: max-content;
  animation: marquee-drift 45s linear infinite;
}
.marquee figure { margin: 0 clamp(0.75rem, 2vw, 1.5rem) 0 0; }
.marquee img {
  display: block;
  height: clamp(140px, 21vw, 260px);
  width: auto;
  border-radius: var(--radius);
  background: var(--bg-sunk);
}

@keyframes marquee-drift {
  to { transform: translateX(-33.3333%); }
}

/* Motion off: becomes a plain strip you can swipe or scroll. */
@media (prefers-reduced-motion: reduce) {
  .marquee { overflow-x: auto; }
  .marquee__track { animation: none; }
}

/* ---------- WORK GRID ------------------------------------- */
/* One project per row, full width. With a small number of strong
   projects this reads better than a grid — each gets its own moment.
   Once you're past about four projects, uncomment the two-column
   rule below for a denser layout. */
.work-grid {
  display: grid;
  gap: clamp(2.5rem, 6vw, 5rem);
  grid-template-columns: 1fr;
}
/*
@media (min-width: 720px) {
  .work-grid { grid-template-columns: repeat(2, 1fr); }
}
*/

.work-card { position: relative; }

/* Image beside the description rather than above it, so a whole
   project fits on screen at once. Stacks on narrow screens. */
.work-card a {
  text-decoration: none;
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.25rem, 3vw, 3rem);
  align-items: center;
}
@media (min-width: 820px) {
  .work-card a { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
}

.work-card__media {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--bg-sunk);
  aspect-ratio: 16 / 9;
}

.work-card__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--ease), filter 0.5s var(--ease);
}
.work-card a:hover .work-card__media img { transform: scale(1.035); }

.work-card__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.9rem;
}
.work-card__title {
  font-family: var(--font-title);
  font-size: clamp(1.15rem, 1rem + 0.7vw, 1.55rem);
  font-weight: 400;
  letter-spacing: -0.025em;
  line-height: 1.15;
}

/* The one-line descriptor under a project title. */
.work-card__year {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--muted);
  white-space: nowrap;
}

/* ---------- CAPABILITIES ---------------------------------- */
.cap-grid {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3rem);
  grid-template-columns: 1fr;
}
@media (min-width: 700px) { .cap-grid { grid-template-columns: repeat(3, 1fr); } }

.cap h3 { margin-bottom: 0.6rem; }
.cap ul { list-style: none; padding: 0; }
.cap li {
  padding: 0.45rem 0;
  border-bottom: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.9375rem;
}

/* ---------- CASE STUDY ------------------------------------ */
.case-hero { padding-block: clamp(2.5rem, 6vw, 5rem) clamp(2rem, 4vw, 3rem); }

.case-meta {
  display: grid;
  gap: 1.5rem 2rem;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  padding-block: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-block: clamp(2.5rem, 6vw, 4rem);
}
.case-meta dt {
  font-family: var(--font-mono);
  font-size: 0.7rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--muted);
  margin-bottom: 0.4rem;
}
.case-meta dd { margin: 0; font-size: 0.9375rem; }

.case-section { margin-block: clamp(3rem, 7vw, 5.5rem); }
.case-section > .h3 { margin-bottom: 1.25rem; }

.figure { margin-block: clamp(2.5rem, 6vw, 4.5rem); }
.figure img { border-radius: var(--radius); width: 100%; background: var(--bg-sunk); }
.figure figcaption {
  margin-top: 0.85rem;
  font-size: 0.85rem;
  color: var(--muted);
  max-width: 60ch;
}
.figure--wide { width: 100%; max-width: 1440px; }

.figure-pair {
  display: grid;
  gap: clamp(0.75rem, 2vw, 1.25rem);
  grid-template-columns: 1fr;
}
@media (min-width: 640px) { .figure-pair { grid-template-columns: 1fr 1fr; } }

.pullquote {
  font-family: var(--font-title);
  font-size: clamp(1.4rem, 1rem + 1.8vw, 2.4rem);
  line-height: 1.22;
  letter-spacing: -0.028em;
  max-width: 22ch;
  margin-block: clamp(2.5rem, 6vw, 4rem);
  padding-left: clamp(1rem, 3vw, 2rem);
  border-left: 2px solid var(--accent);
}

.results {
  display: grid;
  gap: 1.5rem 2rem;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  padding-block: clamp(2rem, 4vw, 3rem);
  border-block: 1px solid var(--line);
}
.results dt {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.4rem + 2.4vw, 3.5rem);
  font-weight: 500;
  letter-spacing: -0.04em;
  line-height: 1;
}
.results dd { margin: 0.5rem 0 0; color: var(--muted); font-size: 0.9rem; max-width: 24ch; }

.case-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  padding-block: clamp(2.5rem, 5vw, 4rem);
  border-top: 1px solid var(--line);
}

/* ---------- OVERSIZED SECTION HEADING ---------------------
   Bigger and louder than .h2. Used for the major page sections
   so a long scroll has some rhythm to it.
   ---------------------------------------------------------- */
.xl-head {
  font-family: var(--font-title);
  font-size: clamp(2.6rem, 1rem + 8.5vw, 8rem);
  /* 400, not 800: Komu ships each cut as its own family at a single
     weight. Asking for 800 here would find nothing and fall back. */
  font-weight: 400;
  text-transform: uppercase;
  line-height: 0.92;
  /* Looser than the Inter Tight setting was — Komu is already a
     tight, geometric face and -0.05em collided the letterforms. */
  letter-spacing: -0.015em;
  color: var(--title);
  text-align: center;
  text-wrap: balance;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

/* ---------- "WHAT I CAN DO" CARD GRID ---------------------
   Fixed track widths plus justify-content:center so the last
   row centres under the rows above rather than stretching.
   ---------------------------------------------------------- */
/* Flex rather than grid, deliberately: a grid leaves a short final
   row hanging on the left. Flex centres each row independently, so
   with six cards the last two sit centred under the middle of the
   row above. */
.cando {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  /* Wide enough that the orange mats (5px, 8px on hover) never
     touch the ones beside them. */
  gap: clamp(1.5rem, 2.5vw, 1.75rem);
  max-width: 960px;
  margin-inline: auto;
}
.cando__card {
  flex: 0 1 215px;
  text-decoration: none;
  padding: 1.6rem 1rem;
  text-align: center;
  border-radius: 2px;
  background: var(--bg);
  /* Even spread on all four sides rather than an offset drop, so it
     reads as a frame around the card. No separate border: in mono
     the two would merge into one chunky edge. */
  box-shadow: 0 0 0 5px var(--accent);
  transition: box-shadow 0.2s var(--ease);
}
.cando__card:hover {
  box-shadow: 0 0 0 8px var(--accent);
}
.cando__title {
  font-family: var(--font-title);
  font-weight: 400;
  text-transform: uppercase;
  font-size: 1rem;
  letter-spacing: -0.01em;
  line-height: 1.15;
  min-height: 2.3em;
  display: flex;
  align-items: center;
  justify-content: center;
}
.cando__go {
  margin-top: 1rem;
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-ink);
  border-bottom: 1px solid var(--accent-ink);
}

/* ---------- OBJECTIVE / PROCESS / RESULT ------------------ */

/* Date line and title for one experience entry. Centred to match
   the section headings; the columns beneath stay left-aligned,
   because centred paragraphs are harder to read. */
.opr-head {
  text-align: center;
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}
.opr-head .eyebrow { display: block; margin-bottom: 0.5rem; }
.opr-head .h3 { text-wrap: balance; }

.opr { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); }
@media (min-width: 800px) { .opr { grid-template-columns: repeat(3, 1fr); } }

.opr__label {
  font-family: var(--font-title);
  font-weight: 400;
  font-size: var(--label-size);
  letter-spacing: var(--label-tracking);
  text-transform: uppercase;
  color: var(--accent-ink);
  margin-bottom: 0.7rem;
}
.opr p { font-size: 0.9rem; line-height: 1.55; text-wrap: pretty; }

/* ---------- CERTIFICATIONS, SHOWN ------------------------- */
.certs {
  display: grid;
  /* Extra room for the 5px orange mat on each side. */
  gap: clamp(1.75rem, 3.5vw, 2.5rem);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.certs figure { display: flex; flex-direction: column; }

/* Certificates arrive at whatever proportions the issuer used, so
   force one box and letterbox inside it. object-fit:contain rather
   than cover — cropping a certificate cuts off the thing that makes
   it worth showing. The white fill matches the certificates' own
   backgrounds, so the bars are invisible. */
.certs img {
  width: 100%;
  display: block;
  aspect-ratio: 4 / 3;
  object-fit: contain;
  height: auto;
  background: #fff;
  border-radius: 2px;
  box-shadow: 0 0 0 2px var(--accent);
}
.certs figcaption { margin-top: 1.1rem; }
.certs__name {
  font-family: var(--font-title);
  font-weight: 400;
  text-transform: uppercase;
  font-size: var(--label-size);
  letter-spacing: var(--label-tracking);
  line-height: 1.25;
  /* Two lines' worth, so a name that wraps doesn't push its
     issuer line out of step with the ones beside it. */
  min-height: 2.5em;
}
.certs__by { color: var(--muted); font-size: 0.875rem; margin-top: 0.25rem; }

/* ---------- CV LIST (experience / education) --------------
   A dated row: date on the left, entry on the right. Stacks on
   narrow screens.
   ---------------------------------------------------------- */

/* Marks a certification you're partway through. Honest and
   still worth listing — just never leave it unlabelled. */

/* ---------- CASE STUDY: STICKY RAIL ----------------------
   The rail sits beside the case study body and stays put while
   you scroll. Its contents are per-page, so each project shows
   its own metadata with no scripting involved.
   ---------------------------------------------------------- */
.case-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}
@media (min-width: 1000px) {
  .case-layout { grid-template-columns: 210px minmax(0, 1fr); }
  .case-rail { position: sticky; top: 6.5rem; }
}

.case-rail dl { margin: 0; }
.case-rail dt {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.3rem;
}
.case-rail dd {
  margin: 0 0 1.35rem;
  font-size: 0.9rem;
  line-height: 1.45;
  text-wrap: pretty;
}
.case-rail dd:last-child { margin-bottom: 0; }

/* On narrow screens the rail becomes a plain block above the body */
@media (max-width: 999px) {
  .case-rail {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 1.25rem 2rem;
    padding-bottom: 2rem;
    border-bottom: 1px solid var(--line);
  }
  .case-rail dl { display: contents; }
  .case-rail dd { margin-bottom: 0; }
}

/* A label that marks what kind of artifact this is */
.case-tag {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  padding: 0.4em 0.7em;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
}

/* Companion document at the end of a case study: the link carries the
   weight, the meta line sits quietly beside it so nobody clicks a 4 MB
   download blind. */
.doc-link {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem 1.1rem;
  margin-top: clamp(2.5rem, 6vw, 4rem);
  padding-top: clamp(1.25rem, 3vw, 2rem);
  border-top: 1px solid var(--line);
}
.doc-link .arrow-link { font-size: clamp(1.05rem, 0.95rem + 0.4vw, 1.3rem); }
.doc-link__meta {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---------- FOOTER / CONTACT ------------------------------ */
.contact { border-top: 1px solid var(--line); }
/* The email and LinkedIn read as a matched pair of contact routes,
   not a headline and a footnote: the address leads by about 1.3x
   rather than 3x, and they sit close enough to group. */
/* Same face, tracking and colour as the Brief Description / Process /
   Result labels, but sized on its own rather than off --label-size:
   this one heads a whole section, so it carries more than they do.
   Changing --label-size no longer moves it. */
.contact .eyebrow {
  font-family: var(--font-title);
  font-weight: 400;
  font-size: 1.55rem;
  letter-spacing: var(--label-tracking);
  color: var(--accent-ink);
}

.contact__email {
  font-family: var(--font-display);
  /* Sized for a long address - 22 characters. If you switch to a short
     one like hello@rorocha.com, the last value can go up to ~3.25rem
     without wrapping on a phone. */
  font-size: clamp(1.3rem, 0.8rem + 1.8vw, 2rem);
  /* Regular, not medium: at this size the scale carries the emphasis,
     and the lighter cut keeps the address from shouting. */
  font-weight: 400;
  letter-spacing: -0.04em;
  text-decoration: none;
  display: inline-block;
  line-height: 1.05;
  word-break: break-word;
}
.contact__email:hover { color: var(--title); }

.contact__social {
  margin-top: 1.1rem;
  font-size: clamp(1.05rem, 0.85rem + 0.75vw, 1.45rem);
}

.site-footer {
  border-top: 1px solid var(--line);
  padding-block: 2rem 2.5rem;
  font-size: 0.85rem;
  color: var(--muted);
}
.site-footer__inner {
  display: flex; justify-content: space-between;
  gap: 1rem 2rem; flex-wrap: wrap; align-items: center;
}
.social { display: flex; gap: 1.5rem; list-style: none; padding: 0; }
.social a { text-decoration: none; }
.social a:hover { color: var(--fg); }

/* ---------- SCROLL REVEAL --------------------------------- */
/* Elements fade up as they enter the viewport. Handled by site.js.
   If JS is off, everything is visible by default. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
.js [data-reveal].is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; }
}

/* ============================================================
   CASE STUDY — long-form layout with a sticky metadata rail.
   Used by work/clints-collective.html. Reusable for future
   case studies: same markup, different content.
   ============================================================ */

/* ---------- Full-bleed hero ------------------------------- */

/* ---------- Two-column body with sticky rail -------------- */

/* The rail. Its contents are hard-scoped to this page — each case
   study is its own document, so there's nothing to swap or reset. */

/* ---------- Prose ----------------------------------------- */

/* A lead paragraph, one step up in size */

/* ---------- Case study: text beside an image ---------------
   Same idea as the hero split, scoped to the case study body.
   Breakpoint is higher than the hero's because the sticky rail
   has already taken 210px off the available width.
   ---------------------------------------------------------- */
.case-split {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.5rem, 3vw, 2.75rem);
  align-items: center;
  margin-block: clamp(2.5rem, 6vw, 4.5rem);
}
@media (min-width: 1000px) {
  .case-split { grid-template-columns: 1fr 0.9fr; }
  /* Alternate which side the image falls on, so a long page
     doesn't read as the same slab repeated. */
  .case-split--flip figure { order: -1; }
}
.case-split .case-section { margin: 0; }
.case-split figure { margin: 0; }
.case-split img {
  width: 100%;
  border-radius: var(--radius);
  background: var(--bg-sunk);
}

/* Descriptor line on a work card — a sentence rather than a tag list. */
/* The one-line descriptor under a project title. */
.work-card__desc {
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--muted);
  margin-top: 0.5rem;
  max-width: 40ch;
  text-wrap: pretty;
}
