/* ==========================================================================
   Font

   Google Sans Flex, SIL Open Font License, self-hosted.

   The download from Google ships six variable axes (opsz, wdth, wght, GRAD,
   ROND, slnt) and weighs 1.9 MB. This copy is instanced down to the optical
   size axis alone — 86 KB — because the design uses a single weight at the
   default width. Regenerate from the original with fontTools if another axis
   is ever needed:
     instantiateVariableFont(font, {"wght":400,"wdth":100,"GRAD":0,
                                    "ROND":0,"slnt":0})
   ========================================================================== */

@font-face {
  font-family: "Google Sans Flex";
  src: url("../fonts/google-sans-flex.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ==========================================================================
   Design tokens — mirrors the Figma colour styles and text styles
   ========================================================================== */

:root {
  --green-dark: #044953;
  --green-neon: #d3f782;
  --orange-deep: #d24621;
  --purple-light: #dad2ff;
  --white-dirty: #f4f4f4;
  --white: #ffffff;
  --placeholder: #d9d9d9;

  /* Google Sans Flex replaces the Figma file's "Haas Grot Text Trial", whose
     trial licence cannot be served on the web. */
  --font-sans: "Google Sans Flex", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-detail: "Google Sans Flex", "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* Type scale — mirrors the Figma text styles, which are SINGLE-VALUED.
     These never change at a breakpoint. When text is smaller on a narrower
     screen it is because a component asked for a different style (the mobile
     card/case study uses B2 where desktop uses B1), exactly as the Figma
     component variants do. Do not reintroduce breakpoint overrides here.

     The one exception is `.page-provisional` — see the note further down. */
  --h1: 96px;
  --h2: 80px;
  --h3: 60px;
  --h4: 40px;
  --b1: 36px;
  --b2: 24px;
  --b3: 18px;
  --subtitle-1: 16px;
  --subtitle-2: 14px;
  --subtitle-3: 12px;

  --page-gutter: 128px;
  --section-gap: 36px;
}

/* ==========================================================================
   Reset
   ========================================================================== */

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

body {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: 400;
  line-height: normal;
  color: var(--green-dark);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
}

img {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

p {
  margin: 0;
}

/* ==========================================================================
   Type roles
   ========================================================================== */

.h1 { font-size: var(--h1); }
.h2 { font-size: var(--h2); }
.h3 { font-size: var(--h3); }
.h4 { font-size: var(--h4); }
.b1 { font-size: var(--b1); }
.b2 { font-size: var(--b2); }
.b3 { font-size: var(--b3); }
.subtitle-1 { font-size: var(--subtitle-1); }
.subtitle-2 { font-size: var(--subtitle-2); }
.subtitle-3 { font-size: var(--subtitle-3); }

.h1, .h2, .h3, .h4 {
  font-weight: 400;
  margin: 0;
}

/* Stacked paragraphs inside a rich-text block */
.prose > p + p {
  margin-top: 18px;
}

/* ==========================================================================
   Page header (used on work / about / case study)
   ========================================================================== */

.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 8px 16px;
  overflow: hidden;
}

.page-header--purple { background: var(--purple-light); }
.page-header--green {
  background: var(--green-dark);
  color: var(--white);
}

.page-header__title {
  padding: 16px;
  white-space: nowrap;
}

.page-header__close {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

/* button icon ladder: XL 100, L 80, M 60, S 44.
   The header uses L. It has no fixed height — it hugs the title and icon.
   The tablet/mobile steps below are chosen from this ladder rather than
   specified in the design. */
.page-header__close img {
  width: 80px; /* L */
  height: 80px;
}

/* ==========================================================================
   Text button (label + arrow)
   ========================================================================== */

.button-text {
  display: inline-flex;
  align-items: center;
}

/* Size ladder. The icon is 40px at every size — not specified in the design,
   carried over from the original frame. */
.button-text--xs {
  gap: 12px;
  padding: 8px 16px;
  font-size: var(--b2);
}

.button-text--s {
  gap: 12px;
  padding: 16px;
  font-size: var(--b1);
}

.button-text--m {
  gap: 12px;
  padding: 16px;
  font-size: var(--h4);
}

.button-text--l {
  gap: 16px;
  padding: 16px;
  font-size: var(--h3);
}

.button-text img {
  width: 40px;
  height: 40px;
  flex: none;
}

.button-text--back img {
  transform: rotate(180deg);
}

/* ==========================================================================
   Tag
   ========================================================================== */

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  width: 100%;
}

.tag {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 60px;
  padding: 8px;
  background: var(--green-neon);
  color: #000;
  font-size: var(--subtitle-2);
  white-space: nowrap;
  overflow: hidden;
}

/* Size M. No height set, so it hugs its content. */
.tag--lg {
  min-width: 70px;
  font-size: var(--subtitle-1);
}

/* Size XS. No height set, so it hugs its content. */
.tag--xs {
  min-width: 50px;
  padding: 6px 12px;
  font-size: var(--subtitle-3);
}

/* Status tag for a case study that has no page yet */
.tag--soon {
  background: var(--orange-deep);
  color: var(--white);
}

/* ==========================================================================
   Home
   ========================================================================== */

/* The home page is a single screen — it must never scroll. `dvh` keeps that
   true on mobile browsers whose toolbars change the visible height. */
.home {
  display: flex;
  align-items: stretch;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.home__column {
  display: flex;
  flex-direction: column;
  flex: 1 1 50%;
  min-width: 0;
}

.card-home {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  padding: 26px;
  min-height: 0;
  min-width: 0;
}

/* Shares the row 50/50 with .home__column at every width — the Figma frame's
   720px is exactly half of its 1440px artboard, so this generalises it. */
.card-home--about {
  flex: 1 1 50%;
  min-width: 0;
  background: var(--white-dirty);
}

.card-home--work {
  flex: 1 0 0;
  background: var(--purple-light);
}

.card-home--contacts {
  flex: 1 0 0;
  background: var(--green-neon);
}

.card-home__text {
  display: flex;
  flex-direction: column;
  gap: 36px;
  width: 100%;
}

.card-home__title,
.card-home__subtitle {
  padding: 16px;
}

/* Wraps rather than nowrap: at 1280/1366 the 96px name needs more width than
   half the screen offers, and clipping it would be worse than two lines. */
.card-home__title { width: 100%; }
.card-home__subtitle { width: 100%; }

.card-home__media {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-height: 0;
}

/* Reproduces the Figma crop: the photo is scaled up and offset inside a
   fixed square window rather than simply object-fit: cover. */
.photo-crop {
  position: relative;
  overflow: hidden;
  flex: none;
}

.photo-crop img {
  position: absolute;
  width: 148.21%;
  height: 197.01%;
  left: -19.15%;
  top: -85.56%;
  max-width: none;
}

.card-home__photo {
  padding: 16px;
}

/* Square, but capped against viewport height so a short screen shrinks the
   photo rather than pushing the card past the fold. */
.card-home__photo .photo-crop {
  width: min(200px, 22vh);
  height: min(200px, 22vh);
}

/* Sub-links only exist in the mobile design */
.card-home__link {
  display: none;
  padding: 16px 0;
  font-size: var(--subtitle-1);
}

/* --- Card reveals ---------------------------------------------------------
   Hovering OR keyboard-focusing a card recolours it and reveals a line of
   invitation copy at the bottom. Hover and focus share one rule block so the
   two can never drift apart (WCAG 2.1.1 — keyboard parity). The text stays
   in the DOM and is only faded, so assistive tech can always reach it rather
   than it appearing conditionally.

   The reveal and the mobile sub-link are never both in the accessibility
   tree: the sub-link is display:none above 768px, the reveal below it. */

.card-home--contacts,
.card-home--work,
.card-home--about {
  transition: background-color 200ms ease, color 200ms ease;
}

.card-home__reveal {
  margin-top: auto;
  opacity: 0;
  text-decoration: underline;
  text-underline-position: from-font;
  transition: opacity 200ms ease;
}

/* Sits directly under the photo rather than being pushed to the card floor —
   the About card's media block already sits at the bottom. */
.card-home--about .card-home__reveal {
  margin-top: 0;
}

/* A touch device has no hover, so the recolour would only ever fire as a
   sticky side effect of tapping through to the next page. `hover: hover`
   gates on the pointer's actual capability; the width bound keeps it off a
   narrow desktop window, where the reveal copy is hidden anyway. Focus is
   gated alongside hover so the two stay in lockstep — the focus ring itself
   is global and still appears for keyboard users everywhere. */
@media (hover: hover) and (min-width: 769px) {
  .card-home--contacts:hover,
  .card-home--contacts:focus,
  .card-home--contacts:focus-visible {
    background: var(--white);
  }

  .card-home--work:hover,
  .card-home--work:focus,
  .card-home--work:focus-visible {
    background: var(--orange-deep);
    color: var(--white);
  }

  .card-home--about:hover,
  .card-home--about:focus,
  .card-home--about:focus-visible {
    background: var(--green-dark);
    color: var(--white);
  }

  /* The default dark-green focus ring only reaches 2.2:1 on the deep orange
     and is invisible on the dark green, short of the 3:1 WCAG 2.4.11 wants
     for a focus indicator. White clears both. */
  .card-home--work:focus-visible,
  .card-home--about:focus-visible {
    outline-color: var(--white);
  }

  .card-home--contacts:hover .card-home__reveal,
  .card-home--contacts:focus .card-home__reveal,
  .card-home--contacts:focus-visible .card-home__reveal,
  .card-home--work:hover .card-home__reveal,
  .card-home--work:focus .card-home__reveal,
  .card-home--work:focus-visible .card-home__reveal,
  .card-home--about:hover .card-home__reveal,
  .card-home--about:focus .card-home__reveal,
  .card-home--about:focus-visible .card-home__reveal {
    opacity: 1;
  }
}

/* On a touch device the reveal can never be shown, so stop it reserving
   layout space — this matters on tablets at 769px and wider, where the
   mobile display:none below does not reach. */
@media (hover: none) {
  .card-home__reveal {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .card-home--contacts,
  .card-home--work,
  .card-home--about,
  .card-home__reveal {
    transition: none;
  }
}

/* ==========================================================================
   Work
   ========================================================================== */

.work {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 100vh;
  background: var(--white-dirty);
}

.work__body {
  width: 100%;
  padding: 48px var(--page-gutter);
}

.case-study-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 40px;
  width: 100%;
}

.card-case-study {
  display: flex;
  flex-direction: column;
  gap: 16px;
  align-items: flex-start;
}

.card-case-study__media {
  width: 100%;
  height: 356px;
  background: var(--placeholder);
  overflow: hidden;
}

.card-case-study__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card-case-study__client {
  width: 100%;
  font-size: var(--subtitle-1);
}

.card-case-study__title {
  width: 100%;
}

/* ==========================================================================
   About
   ========================================================================== */

.about__intro {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 36px 46px;
  background: var(--green-dark);
}

.about__intro-text {
  flex: 1 0 0;
  min-width: 0;
  color: var(--white-dirty);
  font-size: var(--b1);
}

.about__intro-media {
  display: flex;
  flex: 1 0 0;
  min-width: 0;
  align-items: center;
  justify-content: flex-end;
}

.about__intro-media .photo-crop {
  width: 455px;
  height: 455px;
  margin: 16px;
}

.about__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: stretch;
}

.about__column {
  display: flex;
  flex-direction: column;
}

.about-block {
  display: flex;
  flex-direction: column;
  gap: 16px;
  align-items: flex-start;
  padding: 36px 46px;
}

.about-block--purple { background: var(--purple-light); }
.about-block--neon { background: var(--green-neon); }
.about-block--dirty {
  flex: 1 0 0;
  justify-content: space-between;
  background: var(--white-dirty);
}

.about-block__body {
  display: flex;
  flex-direction: column;
  gap: 32px;
  width: 100%;
}

.entry {
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 100%;
}

.entry__role {
  font-size: var(--h4);
}

.entry__meta,
.entry__detail {
  font-size: var(--subtitle-1);
}

.entry__meta > p + p {
  margin-top: 8px;
}

.entry__detail > p + p {
  margin-top: 8px;
}

.skills-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px 40px;
  width: 100%;
}

.skills-grid p {
  font-size: var(--b2);
}

.languages {
  display: flex;
  gap: 40px;
  align-items: flex-start;
}

.language__name { font-size: var(--b1); }
.language__level { font-size: var(--subtitle-1); }

.contacts__list {
  display: flex;
  flex-direction: column;
  gap: 24px;
  width: 100%;
  font-size: var(--b1);
}

.contacts__list a {
  text-decoration: underline;
  text-underline-position: from-font;
  word-break: break-word;
}

.about__cta {
  display: flex;
  width: 100%;
  padding: 16px 46px 16px 36px;
}

/* ==========================================================================
   Case study
   ========================================================================== */

.case-study__back {
  padding: 8px 0;
}

/* Icon size S. Scoped to the back button rather than to .button-text--s,
   because only this button was specified — the CV button on about is also
   size S but still carries the 40px icon. */
.case-study__back .button-text img {
  width: 24px;
  height: 24px;
}

.case-study__content {
  display: flex;
  flex-direction: column;
  gap: var(--section-gap);
  padding: 0 var(--page-gutter);
}

.cs-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 40px;
  padding: 0;
}

.cs-header__main {
  display: flex;
  flex-direction: column;
  gap: 24px;
  align-items: flex-start;
}

.cs-header__logo {
  width: 142px;
  height: 89px;
  object-fit: contain;
  object-position: left center;
}

.cs-header__details {
  display: flex;
  flex-direction: column;
  gap: 24px;
  flex: none;
  font-family: var(--font-detail);
  color: var(--green-dark);
}

.cs-detail__label {
  font-size: var(--b3);
  margin-bottom: 6px;
}

.cs-detail__value {
  font-size: var(--subtitle-1);
}

.cs-tools__icons {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 6px 0;
}

.cs-tools__icons img {
  height: 34px;
  width: auto;
}

.cs-tools__caption {
  font-size: var(--subtitle-1);
}

.cs-image img,
.cs-image-grid img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 8px;
}

.cs-image {
  width: 100%;
  aspect-ratio: 1184 / 775.57;
  overflow: hidden;
  border-radius: 8px;
}

.cs-image-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
  width: 100%;
}

.cs-image-grid > div {
  aspect-ratio: 580 / 731.86;
  overflow: hidden;
  border-radius: 8px;
}

.cs-quote {
  width: 100%;
  font-size: var(--b1);
}

.cs-title {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 8px;
  background: var(--purple-light);
  font-size: var(--h4);
  white-space: nowrap;
}

.cs-columns {
  display: flex;
  gap: 0;
  align-items: flex-start;
  width: 100%;
}

.cs-columns > * {
  flex: 1 0 0;
  min-width: 0;
}

.cs-column {
  display: flex;
  flex-direction: column;
  gap: 0;
  align-items: flex-start;
}

.cs-section {
  display: flex;
  flex-direction: column;
  gap: 0;
  align-items: flex-start;
  width: 100%;
}

.cs-body {
  font-size: var(--b2);
  width: 100%;
}

.cs-values {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
  width: 100%;
}

.cs-value__number {
  font-size: var(--h2);
  margin-bottom: 16px;
}

.cs-value__label {
  font-size: var(--b2);
}

.cs-split {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0;
  width: 100%;
}

.cs-split__aside {
  width: 544px;
  flex: none;
}

.related {
  display: flex;
  flex-direction: column;
  gap: 24px;
  width: 100%;
}

/* A grid rather than a flex row so a lone related card keeps its column
   width instead of stretching across the full content measure. */
.related__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 40px;
  width: 100%;
}

/* ==========================================================================
   PROVISIONAL type scale

   `about.html` and `case-study-via-verde.html` carry `class="page-provisional"`
   on <body> because they have no mobile design in Figma yet. These pages fall
   back to an interpolated scale so 96px headings do not appear on a phone.

   This is a stopgap, NOT a design decision — the sizes were invented here.
   As soon as a mobile frame exists for one of these pages, drop the class from
   that page and express the sizes as component-level style choices, the way
   home, work and card/case study already do.
   ========================================================================== */

/* ==========================================================================
   Short viewports — the home page must fit one screen without scrolling, so
   on a shallow window the type and padding step down rather than the card
   getting clipped. Height-based, deliberately independent of the width
   breakpoints below.
   ========================================================================== */

@media (min-width: 769px) and (max-height: 760px),
       (min-width: 769px) and (max-width: 1400px) and (max-height: 920px) {
  .home {
    --h1: 64px;
    --h3: 40px;
  }

  .home .card-home {
    padding: 20px;
  }

  .home .card-home__text {
    gap: 20px;
  }

  .home .card-home__title,
  .home .card-home__subtitle,
  .home .card-home__photo {
    padding: 8px;
  }
}

/* Tier 1 — tighten spacing only, so the mobile frame's type sizes survive.
   Covers 375x812 / 390x844, which do not fit at the design's full padding. */
@media (max-width: 768px) and (max-height: 860px) {
  .home .card-home {
    padding: 20px;
  }

  .home .card-home--work,
  .home .card-home--contacts {
    gap: 8px;
  }

  .home .card-home__title,
  .home .card-home__subtitle,
  .home .card-home__photo,
  .home .card-home__link {
    padding-top: 10px;
    padding-bottom: 10px;
  }
}

/* Tier 2 — genuinely short phones (SE, 360x640). Spacing alone is no longer
   enough here, so the type steps down too. */
@media (max-width: 768px) and (max-height: 700px) {
  .home .card-home__title {
    font-size: 28px;
  }

  .home .card-home__subtitle {
    font-size: 19px;
  }

  .home .card-home__link {
    font-size: 13px;
  }

  .home .card-home {
    padding: 16px;
  }

  .home .card-home--work,
  .home .card-home--contacts {
    gap: 4px;
  }

  .home .card-home__title,
  .home .card-home__subtitle,
  .home .card-home__photo,
  .home .card-home__link {
    padding-top: 6px;
    padding-bottom: 6px;
  }
}

/* ==========================================================================
   Focus states
   ========================================================================== */

a:focus-visible {
  outline: 3px solid var(--green-dark);
  outline-offset: 4px;
}

.page-header--green a:focus-visible {
  outline-color: var(--white);
}

/* ==========================================================================
   Tablet
   ========================================================================== */

@media (max-width: 1024px) {
  :root {
    --page-gutter: 48px;
  }

  /* header/page is designed; hold it at H2 even on provisional pages. */
  .page-header__title {
    font-size: 80px; /* H2 */
  }

  /* Provisional type scale — see the note above `.page-provisional`. */
  .page-provisional {
    --h1: 64px;
    --h2: 56px;
    --h3: 44px;
    --h4: 32px;
    --b1: 28px;
    --b2: 20px;
  }

  .page-header__close img {
    width: 60px; /* M */
    height: 60px;
  }

  .about__intro-media .photo-crop {
    width: 320px;
    height: 320px;
  }

  .cs-split__aside {
    width: 50%;
  }

  /* Below desktop the case study meta and the research stats run across the
     full page width instead of stacking. The header stacks so the meta gets
     the whole width rather than being squeezed beside the title. */
  .cs-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 24px;
  }

  .cs-header__details {
    flex: 1 1 auto;
    flex-direction: row;
    flex-wrap: wrap;
    width: 100%;
    gap: 24px 40px;
  }

  .cs-header__details > div {
    flex: 1 1 140px;
  }

  /* 6 stats — 3 across keeps the desktop rhythm and avoids an orphan row. */
  .cs-values {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

}

/* ==========================================================================
   Mobile
   ========================================================================== */

@media (max-width: 768px) {
  :root {
    --page-gutter: 24px;
    --section-gap: 24px;
  }

  /* Provisional type scale — see the note above `.page-provisional`. */
  .page-provisional {
    --h1: 36px;
    --h2: 36px;
    --h3: 28px;
    --h4: 24px;
    --b1: 24px;
    --b2: 18px;
    --subtitle-1: 14px;
  }

  /* --- Designed mobile styles -------------------------------------------
     Taken from the home_mobile and work_mobile frames. Each component names
     a different style from the fixed ladder; the ladder itself never moves. */

  /* home_mobile: title B1, subtitle B2, sub-links Subtitle 1 */
  .card-home__title {
    font-size: var(--b1);
  }

  .card-home__subtitle {
    font-size: var(--b2);
  }

  /* work_mobile: header title steps down from H2 to B1.
     Literal 36px rather than var(--b1): header/page is a designed component
     shared with the provisional pages, and must not be shrunk by their
     fallback ladder — otherwise the same header renders at two sizes. */
  .page-header__title {
    font-size: 40px; /* H4 */
  }

  /* Home stacks into the three cards of the mobile frame */
  .home {
    flex-direction: column;
  }

  .home__column {
    flex: none;
    width: 100%;
  }

  .card-home--about {
    flex: 1 1 auto;
    width: 100%;
    min-height: 0;
  }

  .card-home--work,
  .card-home--contacts {
    flex: none;
    gap: 16px;
    justify-content: center;
  }

  .card-home__text {
    gap: 0;
  }

  .card-home__title,
  .card-home__subtitle {
    padding: 16px 0;
  }

  .card-home__title {
    white-space: normal;
  }

  .card-home__photo {
    padding: 16px 0;
  }

  .card-home__photo .photo-crop {
    width: min(128px, 16vh);
    height: min(128px, 16vh);
  }

  .card-home__link {
    display: block;
  }

  /* The mobile design shows the email address directly, so the hover reveal
     has no role here — and there is no hover on touch. */
  .card-home__reveal {
    display: none;
  }

  /* Everything else collapses to a single column */
  .case-study-grid,
  .about__grid,
  .cs-image-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  /* cs-values and cs-header__details deliberately stay horizontal here —
     they inherit the wrapping row set at the 1024px breakpoint, just with
     tighter gaps and smaller minimums so they still fit a phone. */
  .cs-values,
  .skills-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 24px 16px;
  }

  .cs-header__details {
    gap: 20px 24px;
  }

  .cs-header__details > div {
    flex: 1 1 120px;
  }

  .about__intro,
  .cs-columns,
  .cs-split {
    flex-direction: column;
  }

  .related__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
  }

  .about__intro {
    padding: 24px;
  }

  .about__intro-media {
    justify-content: flex-start;
  }

  .about__intro-media .photo-crop {
    width: 240px;
    height: 240px;
    margin: 16px 0;
  }

  .about-block {
    padding: 24px;
  }

  .about__cta {
    padding: 16px 24px;
  }

  .cs-split__aside {
    width: 100%;
  }

  .languages {
    flex-wrap: wrap;
    gap: 24px;
  }

  /* Sticks to the top edge while the page scrolls. `sticky` rather than
     `fixed` so the header keeps its place in flow and the content below
     needs no compensating offset. No ancestor may set `overflow` other than
     visible, or this silently stops working. */
  .page-header {
    position: sticky;
    top: 0;
    z-index: 10;
    padding: 0 16px;
  }

  .page-header__close img {
    width: 60px; /* M */
    height: 60px;
  }

  /* The case study header tags step down to size XS — mirrors .tag--xs */
  .tag--lg {
    min-width: 50px;
    padding: 6px 12px;
    font-size: var(--subtitle-3);
  }

  /* Back button steps down to size XS. Literal 24px (B2) so the provisional
     ladder on this page cannot shrink a directly specified style. */
  .case-study__back .button-text {
    gap: 12px;
    padding: 8px 16px;
    font-size: 24px; /* B2 */
  }

  /* cs body, mobile. Literal values so the provisional ladder on this page
     cannot shrink styles that were specified directly. */
  .cs-quote {
    font-size: 24px; /* B2 */
  }

  .cs-title {
    font-size: 24px; /* B2 */
  }

  .cs-body {
    font-size: 16px; /* Subtitle 1 */
  }

  /* cs-header, mobile: title B1, detail labels B3, values Subtitle 2.
     Literal values, so the provisional ladder on this page cannot shrink
     styles that were specified directly. */
  .cs-header h1 {
    font-size: 36px; /* B1 */
  }

  .cs-detail__label {
    font-size: 18px; /* B3 */
  }

  .cs-detail__value,
  .cs-tools__caption {
    font-size: 14px; /* Subtitle 2 */
  }

  .cs-title {
    white-space: normal;
  }

  .work__body {
    padding: 24px var(--page-gutter);
  }

  /* card/case study — Mobile variant */
  .case-study-grid {
    gap: 24px;
  }

  .card-case-study {
    gap: 8px;
  }

  .card-case-study__media {
    height: 280px;
  }

  .card-case-study__title {
    font-size: var(--b2);
  }

  /* Tags step down to size XS on the cards — mirrors .tag--xs */
  .card-case-study .tag {
    min-width: 50px;
    padding: 6px 12px;
    font-size: var(--subtitle-3);
  }
}
