/* build 62 */
/* ===========================================================================
   Matar Cohen - portfolio v2
   Aimed at one reader: a Google UX hiring manager, ~3 minutes, deciding whether
   this person operates as a manager across an ecosystem or as a craft IC.

   The structural idea: this work is about two audiences with opposing
   incentives sharing one workflow. So the two accents are not decoration -
   blue is always the resident, amber is always the property manager, in the
   diagram, the tags and the metrics.
=========================================================================== */

:root {
  --ink:        #131a22;
  --ink-soft:   #2b3742;
  --muted:      #6b7684;
  --line:       #d9dee4;   /* structural dividers */
  --line-soft:  rgba(196, 178, 150, 0.42);   /* inner dividers: warm, and translucent so they sit under the type rather than beside it */
  --paper:      #f4f6f8;
  --white:      #ffffff;

  /* the two tracks */
  --accent:     #e6694a;
  --resident:   #1f4fd8;
  --manager:    #e4572e;

  /* Display and body match the live site so this reads as the same person's
     work. The mono is kept for every number and label: it is what makes the
     record section read as measured rather than decorative. */
  --display: 'Poppins', system-ui, sans-serif;
  --body:    'Poppins', system-ui, sans-serif;
  --mono:    'IBM Plex Mono', ui-monospace, monospace;

  --gutter: clamp(20px, 5vw, 72px);
  --measure: 62ch;
  --rail: clamp(56px, 6vw, 88px);
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

img, video { display: block; max-width: 100%; }
a { color: inherit; }

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

/* Horizontal only: the `padding` shorthand here was silently zeroing the
   vertical padding that `section` sets, because .wrap outranks the element
   selector. Every section had 0 top/bottom padding as a result. */
.wrap { max-width: 1180px; margin: 0 auto; padding-left: var(--gutter); padding-right: var(--gutter); }
.measure { max-width: var(--measure); }

/* ---------- top rail ---------- */
.rail {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px clamp(18px, 2.2vw, 30px);
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: saturate(1.6) blur(10px);
  -webkit-backdrop-filter: saturate(1.6) blur(10px);
}

.rail-name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: -0.01em;
  text-decoration: none;
}

/* Wider gaps and vertical padding so each is a comfortable tap target rather
   than a 14px-apart text run. */
.rail-links { display: flex; gap: clamp(20px, 3vw, 28px); margin-right: -10px; }

.rail-links a {
  font-family: var(--mono);
  font-size: 12px;
  padding: 10px;
  margin: -10px 0;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  transition: color 160ms ease;
}

.rail-links a:hover { color: var(--ink); }

/* ---------- shared type ---------- */
.eyebrow {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 20px;
}

.display {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(39px, 6.2vw, 68px);
  line-height: 1.04;
  letter-spacing: -0.028em;
  margin: 0;
  text-wrap: balance;
}

.h2 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(24px, 3.4vw, 36px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin: 0 0 8px;
}

.lede {
  font-size: clamp(18px, 2vw, 21px);
  line-height: 1.55;
  color: var(--ink-soft);
}

p { margin: 0 0 18px; }

/* 116px top AND bottom stacked to 232px between sections, which hid the fact
   that anything followed. Half that, and the rhythm still reads. */
section { padding: clamp(34px, 4vw, 54px) 0; }
/* Inset to the content column: a border on the section itself spans the
   padding too, so it ran 144px wider than every other rule on the page. */
section + section { border-top: 0; position: relative; }

section + section::before {
  content: "";
  position: absolute;
  top: 0;
  left: var(--gutter);
  right: var(--gutter);
  height: 1px;
  background: var(--line);
}

#leading::before, .case-section.no-rule::before { content: none; }

/* Case-study sections are already inside .case-page-content's gutter, so the
   inset that aligns homepage rules would apply twice and pull them 72px short
   on each side. */
.case-section + .case-section::before { left: 0; right: 0; }
#leading { border-top: 0; }
.case-section.no-rule { border-top: 0 !important; }

/* The record already separates the hero from the work list, so the two section
   paddings were stacking to 124px and pushing the list out of view. */
/* The rule at the top of #work sat flush against the stats, so it read as
   underlining the data instead of opening the work section. Space on both
   sides makes it a divider between the two. */
.hero { padding-bottom: clamp(34px, 3.8vw, 54px); }
#work { padding-top: clamp(30px, 3.4vw, 48px); }

/* ---------- hero ---------- */
/* The page was pure black on white and read as rigid. A very soft warm wash
   behind the hero and the accent on the figures gives it temperature without
   adding any new element to look at. */
.hero {
  padding-top: clamp(48px, 8vw, 96px);
  position: relative;
}

/* A soft sphere behind the headline. The stops are eased rather than a single
   hard falloff, so there is no visible edge where the wash ends. */
.hero::before {
  content: "";
  position: absolute;
  inset: 6% 0 -14% 0;
  background: radial-gradient(closest-side circle at 30% 46%,
    rgba(230, 105, 74, 0.16) 0%,
    rgba(230, 105, 74, 0.10) 38%,
    rgba(230, 105, 74, 0.045) 62%,
    rgba(230, 105, 74, 0.014) 80%,
    rgba(230, 105, 74, 0) 100%);
  filter: blur(26px);
  pointer-events: none;
  z-index: -1;
}

.hero .eyebrow { color: var(--accent); }

.record-num { color: var(--accent); letter-spacing: -0.035em; }
.hero .display { max-width: 17ch; }
.hero .lede { margin-top: 28px; max-width: 54ch; }

/* ---------- operating record ---------- */
/* A rule over each figure, and the block held to the same measure as the
   paragraph above it so the hero reads as one column rather than a narrow
   text block sitting on a page-wide table. */
.record {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0 clamp(20px, 2.4vw, 36px);
  margin-top: clamp(28px, 4.4vw, 52px);
  /* Same measure as the lede above. font-size here is only ever used to resolve
     the ch unit - every child sets its own size - so the two track together as
     the lede type scales. */
  font-size: clamp(18px, 2vw, 21px);
  max-width: 54ch;
}

.record-cell {
  background: none;
  padding: 0;
}

.record-num { color: var(--accent); letter-spacing: -0.035em; }
.hero .display { max-width: 17ch; }
.hero .lede { margin-top: 28px; max-width: 54ch; }


.record-num {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(28px, 3.6vw, 42px);
  line-height: 1;
  letter-spacing: -0.03em;
  display: block;
}

.record-label {
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.5;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 10px;
  display: block;
}

/* ---------- work: image-led rows, still directly comparable ----------
   Every project exposes the same three facts in the same slots, so a hiring
   manager can compare five projects in one scan. The image carries the
   appeal; the mono facts carry the argument. */
/* The first row already carries 46px of its own top padding. */
.work-list { margin-top: clamp(18px, 1.8vw, 26px); }

.work-row {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 1fr);
  gap: clamp(24px, 4vw, 60px);
  align-items: center;
  padding: clamp(26px, 3.2vw, 40px) 0;
  border-top: 1px solid var(--line);
  text-decoration: none;
  color: inherit;
}

.work-row:first-of-type { border-top: 0; }
.work-row:last-of-type { border-bottom: 1px solid var(--line); }

.work-figure {
  position: relative;
  overflow: hidden;
  border-radius: 14px;
  background: var(--paper);
  aspect-ratio: 984 / 668;
}

.work-figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  display: block;
  transition: transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
}

.work-row:hover .work-figure img { transform: scale(1.035); }

.work-client {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 12px;
  display: flex;
  gap: 12px;
  align-items: baseline;
}

.work-client b { color: var(--accent); font-weight: 500; }

.work-title {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(21px, 2.3vw, 30px);
  line-height: 1.2;
  letter-spacing: -0.02em;
  margin: 0 0 22px;
  text-wrap: balance;
}

.work-facts { display: grid; gap: 12px; margin: 0; }

.work-fact {
  display: grid;
  grid-template-columns: 82px 1fr;
  gap: 12px;
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.65;
}

.work-fact dt { color: var(--ink); letter-spacing: 0.05em; text-transform: uppercase; font-weight: 500; }
.work-fact dd { margin: 0; color: var(--muted); }

.work-go {
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 22px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent);
}

.work-go span { transition: transform 400ms cubic-bezier(0.22, 1, 0.36, 1); }
.work-row:hover .work-go span { transform: translateX(6px); }

/* ---------- how I lead ---------- */
.lead-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(20px, 3vw, 44px);
  margin-top: 36px;
}

.lead-card { border-top: 2px solid var(--ink); padding-top: 18px; }

.lead-card h3 {
  font-family: var(--display);
  font-weight: 600;
  font-size: 19px;
  letter-spacing: -0.01em;
  margin: 0 0 10px;
}

.lead-card p { font-size: 15.5px; line-height: 1.6; color: var(--ink-soft); margin: 0; }

/* ---------- contact ---------- */
.contact-line {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 40px;
  margin-top: 28px;
  font-family: var(--mono);
  font-size: 14px;
}

.contact-line a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 4px; }


/* ---------------------------------------------------------------------------
   Metric-matched fallback
   ---------------------------------------------------------------------------
   With font-display:swap, text paints immediately in a fallback and the real
   face swaps in - which normally causes a reflow "jump". These faces pre-scale
   the fallback so its metrics match Poppins and the swap is invisible.
   size-adjust values were measured per weight against Poppins in-browser;
   ascent/descent are Poppins' own (1050/-350 per 1000 em) divided by that
   scale. Regular and semibold differ enough (110.3% vs 106.3%) to need
   separate faces - one shared value shifts long body copy by a whole line.
--------------------------------------------------------------------------- */
@font-face {
  font-family: 'Poppins Fallback';
  font-weight: 400;
  src: local('Arial'), local('Helvetica'), local('Liberation Sans');
  size-adjust: 113.5%;
  ascent-override: 92.5%;
  descent-override: 30.8%;
  line-gap-override: 0%;
}

@font-face {
  font-family: 'Poppins Fallback';
  font-weight: 500;
  src: local('Arial'), local('Helvetica'), local('Liberation Sans');
  size-adjust: 111.52%;
  ascent-override: 94.2%;
  descent-override: 31.4%;
  line-gap-override: 0%;
}

@font-face {
  font-family: 'Poppins Fallback';
  font-weight: 600 700;
  src: local('Arial Bold'), local('Arial'), local('Liberation Sans');
  size-adjust: 106.25%;
  ascent-override: 98.8%;
  descent-override: 32.9%;
  line-gap-override: 0%;
}

:root {
  /* Layout system --------------------------------------------------------
     The Figma frames are 1728px wide: a 347px sidebar, then a gutter, then
     the content column. Below 1728 the sidebar and gutters contract fluidly
     (no jumps) until the tablet tier, where the sidebar moves to the top.
       sidebar  347px @1728  ->  260px @1025
       case     203px @1728  ->   60px @1025   (project pages, x=550)
       page     171px @1728  ->   60px @1025   (about/contact, x=518)  */
  --design-w: 1728px;
  --sidebar-w: clamp(260px, calc(45.2px + 20.96vw), 347px);
  --gutter-case: clamp(60px, calc(-148.5px + 20.34vw), 203px);
  /* Figma's frame closes with a 202px right margin (347+203+976+202=1728).
     It needs to be a real gutter, not just leftover space: above 1526 the
     column's max-width happens to leave the gap, but below that the element
     fills the viewport and the text would run to the edge. */
  --gutter-case-right: clamp(60px, calc(-147px + 20.199vw), 202px);
  --gutter-page: clamp(60px, calc(-101.8px + 15.79vw), 171px);
  --content-w: 976px;

  --charcoal: #3d3d3d;
  --charcoal-dark: #3e3a37;
  --light-grey: #999999;
  --primary: #e6694a;
  --accent: #e6694a;
  --sidebar-bg: #f9f9f9;
  --card-cream: #f8f7f4;
  --border-light: #f1f1f1;
}

html {
  scroll-behavior: auto;
  overflow-y: scroll;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: 'Poppins', 'Poppins Fallback', sans-serif;
  color: var(--charcoal);
  background: #ffffff;
}

.page {
  position: relative;
  min-height: 100vh;
  width: 100%;
  max-width: var(--design-w);
  margin: 0 auto;
  /* clip, not hidden: `hidden` would make .page a scroll container, which
     breaks position:sticky on the mobile bar and hijacks window scrolling.
     `clip` contains the intentional Figma overflows without that side effect. */
  overflow-x: clip;
  --page-inset: max(0px, calc((100vw - var(--design-w)) / 2));
}

/* ---------- Sidebar ---------- */
.sidebar {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: calc(var(--page-inset) + var(--sidebar-w));
  background: var(--sidebar-bg);
  z-index: 10;
}

.brand {
  position: fixed;
  left: 50px;
  top: 42px;
  z-index: 11;
}

.brand .name {
  font-weight: 500;
  font-size: 24px;
  margin: 0;
}

.brand .title {
  font-weight: 400;
  font-size: 15px;
  /* Figma puts the name box at y=42 and this at y=82; a 10px margin pushed it
     to 87. */
  margin: 5px 0 0;
  color: var(--charcoal);
}

.nav {
  position: fixed;
  left: 4px;
  top: 281px;
  width: 343px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  z-index: 11;
  max-height: calc(100vh - 281px - 40px);
  overflow-y: auto;
}

.nav-item {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 40px;
  height: 40px;
  width: 100%;
  padding-left: 0;
  cursor: pointer;
  text-decoration: none;
}

/* ---------------------------------------------------------------------------
   Navigation motion
   ---------------------------------------------------------------------------
   One coordinated gesture, three beats:
     0ms    press      the pressed item acknowledges instantly
     0ms    marker     leads, travelling to its new home (300ms)
     60ms   content    follows and settles (260ms, 8px rise)
   The sidebar itself never animates. Holding the furniture perfectly still is
   what sells the change as "one region updated" rather than "a new document
   appeared" - and it means nothing around the type can shift.
   Only opacity/transform are animated, so nothing here can reflow the page.
--------------------------------------------------------------------------- */
:root {
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --marker-duration: 600ms;
}

.nav-item .marker {
  width: 6px;
  height: 40px;
  background: var(--primary);
  border-radius: 3px;
  flex-shrink: 0;
  opacity: 0;
  will-change: transform;
  transition: opacity 180ms ease;
}

.nav-item.active .marker { opacity: 1; }

/* Hover tints the label itself. The marker stays exclusively with the active
   item, so it reads as one object that only ever moves on navigation - never
   as a per-item hover decoration. */
@media (hover: hover) {
  .nav-item:hover .label,
  .projects-list a:hover { opacity: 0.8; }
}

/* Press carries the same tint - no colour change, so type never shifts hue
   underneath the cursor mid-click. */
.nav-item:active .label,
.projects-list a:active { opacity: 0.8; }

/* Labels transition opacity only - never colour, size or position - so type
   can never shift or reflow while the marker moves. */
.nav-item .label,
.projects-list a,
.projects-list .current { transition: opacity 160ms ease; }

@keyframes page-enter {
  from { opacity: 0; transform: translate3d(0, 8px, 0); }
  to   { opacity: 1; transform: none; }
}

@keyframes page-enter-soft {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.case-page-content,
.about-content,
.contact-content,
.home-content {
  animation: page-enter 260ms var(--ease-out) 60ms backwards;
}

@media (prefers-reduced-motion: reduce) {
  .nav-item .marker { transition: none !important; }
  .case-page-content,
  .about-content,
  .contact-content,
  .home-content { animation: page-enter-soft 120ms linear both; }
}

.nav-item .label {
  font-weight: 600;
  font-size: 15px;
  color: var(--charcoal);
  width: 77px;
  margin: 0;
}

.projects-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  /* 6px marker + 40px gap = the main labels' text edge, so every nav item
     shares one left alignment instead of the sub-list sitting proud. */
  padding-left: 46px;
  width: 100%;
}

.projects-list a {
  font-weight: 400;
  font-size: 14px;
  color: var(--light-grey);
  text-decoration: none;
  cursor: pointer;
}

.projects-list .current {
  font-weight: 500;
  font-size: 14px;
  color: var(--charcoal);
}

/* ---------- About page ---------- */
.about-content {
  margin-left: var(--sidebar-w);
  padding: 160px var(--gutter-page) 60px var(--gutter-page);
  max-width: none;
  display: flex;
  flex-direction: column;
  gap: 60px;
}

.about-group {
  display: flex;
  flex-direction: column;
  gap: 30px;
}

.about-heading {
  font-weight: 600;
  font-size: clamp(48px, 1.836px + 4.508vw, 70px);
  line-height: 1.214;
  letter-spacing: -0.03em;
  color: var(--accent);
  margin: 0;
  max-width: 895px;
}

.about-row {
  display: flex;
  align-items: center;
  gap: 40px;
}

/* portrait enlarged 50% over the Figma 130px */
.about-photo {
  width: 195px;
  height: 195px;
  border-radius: 20px;
  overflow: hidden;
  flex-shrink: 0;
}

.about-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.about-passions {
  font-weight: 400;
  font-size: clamp(24px, 9.311px + 1.434vw, 31px);
  line-height: 1.516;
  letter-spacing: -0.016em;
  color: var(--charcoal);
  margin: 0;
  max-width: 594px;
}

.about-bio {
  font-weight: 400;
  font-size: 20px;
  line-height: 40px;
  color: var(--charcoal);
  margin: 0;
  max-width: 895px;
}

.view-work-btn {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  width: 234px;
  height: 50px;
  padding: 0 9px 0 33px;
  background: #ffffff;
  border: 2px solid var(--accent);
  border-radius: 25px;
  color: var(--accent);
  font-weight: 600;
  font-size: 20px;
  line-height: normal;
  text-decoration: none;
  flex: none;
}

.view-work-btn:hover { background: var(--accent); color: #ffffff; }
.view-work-btn:hover .vw-arrow img { filter: brightness(0) invert(1); }

.vw-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 14px;
  flex: none;
}

.vw-arrow img {
  /* source is 16x20 */
  width: 14.4px;
  height: 18px;
  display: block;
  transform: rotate(90deg);
  transition: filter 0.2s ease;
}

/* ---------- Contact page ---------- */
.contact-content {
  margin-left: var(--sidebar-w);
  padding: 160px var(--gutter-page) 60px var(--gutter-page);
  max-width: none;
  display: flex;
  flex-direction: column;
  gap: 100px;
}

.contact-heading {
  font-weight: 600;
  font-size: clamp(48px, 1.836px + 4.508vw, 70px);
  line-height: 1.214;
  letter-spacing: -0.03em;
  color: var(--accent);
  margin: 0;
  max-width: 707px;
}

.contact-list {
  display: flex;
  flex-direction: column;
  gap: 60px;
  width: 262px;
}

.contact-label {
  font-weight: 600;
  font-size: 25px;
  line-height: 30px;
  height: 40px;
  margin: 0;
  color: var(--charcoal);
}

.contact-value {
  font-weight: 400;
  font-size: 20px;
  line-height: 40px;
  margin: 0;
  color: var(--charcoal);
  display: block;
}

.contact-link {
  text-decoration: underline;
  cursor: pointer;
}

/* ---------- iPad tier: shrink sidebar/padding smoothly, no stacking yet ---------- */
@media (max-width: 1300px) and (min-width: 1025px) {
  .brand { left: 50px; }
  .nav { left: 4px; width: calc(var(--sidebar-w) - 4px); }
}

/* ---------- Case study pages ---------- */
.case-page-content {
  position: relative;
  margin-left: var(--sidebar-w);
  padding: 40px var(--gutter-case-right) 160px var(--gutter-case);
  max-width: calc(var(--gutter-case) + var(--content-w) + var(--gutter-case-right));
}

/* Header rhythm scales with the viewport. Figma's fixed 100px/60px gaps were
   drawn for a tall canvas and pushed the first image off the fold on laptops;
   these track the screen instead, topping out just below the Figma values. */
.case-breadcrumb {
  font-weight: 400;
  font-size: 18px;
  line-height: 30px;
  color: var(--light-grey);
  margin: 0 0 clamp(32px, 4.6vw, 56px);
}

.case-hero-logo {
  margin: 0 0 clamp(32px, 4.6vw, 56px);
}

.case-hero-logo img {
  display: block;
  height: auto;
}
.case-hero-logo.text {
  font-weight: 600;
  font-size: 28px;
  color: var(--charcoal);
}

.case-h1 {
  font-weight: 600;
  font-size: clamp(40px, 9.574px + 2.971vw, 54.5px);
  line-height: 1.17;
  letter-spacing: -0.03em;
  color: var(--charcoal);
  margin: 0 0 clamp(28px, 3.6vw, 44px);
  max-width: 910px;
}

.case-visual {
  width: 100%;
  height: auto;
  border-radius: 20px;
  display: block;
  margin: 0 0 100px;
}

/* Padding is zeroed here: .case-section is a <section>, so it was picking up
   the generic vertical padding as well as its own margin. */
.case-section { padding: 40px 0 0; margin-bottom: 40px; }

/* Per-frame rhythm: Figma uses 101px stacks on Project 3, 100px on Project 2. */
.p3 .case-section { margin-bottom: 40px; }
/* The hero visual closes the "Titles" group on P2 (100px) but sits inside a
   60px stack on P3. */
.p3 .case-visual { margin-bottom: 60px; }
.p2 /* Same treatment as the footer link, but sits inline inside a section. */
.case-more-link {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  margin-top: 26px;
  font-weight: 600;
  font-size: 20px;
  color: var(--accent);
  text-decoration: none;
}

.case-more-link:hover { opacity: 0.8; }

.next-project-link { margin-top: 100.3px; }

.case-h2 {
  font-weight: 600;
  font-size: clamp(32px, 15.213px + 1.639vw, 40px);
  line-height: 0.75;
  color: var(--charcoal);
  margin: 0 0 30px;
}

.case-subhead {
  font-weight: 600;
  font-size: clamp(20px, 9.508px + 1.025vw, 25px);
  line-height: 1.2;
  color: var(--charcoal);
  margin: 0 0 20px;
}

.case-highlight {
  font-weight: 400;
  font-size: clamp(24px, 9.311px + 1.434vw, 31px);
  line-height: 1.516;
  letter-spacing: -0.01em;
  color: var(--charcoal);
  margin: 0 0 24px;
}

.case-body {
  font-weight: 400;
  font-size: 16px;
  line-height: 30px;
  color: var(--charcoal);
  margin: 0 0 20px;
}

/* Context blocks set their body copy one step larger. */
.case-body.lg { font-size: 18px; }

/* Figma measures: full column vs the narrower 826px reading measure. */
.m826 { max-width: 826px; }
.m976 { max-width: 976px; }

/* "Context" heads sit further above their block than ordinary section heads. */
.case-h2.gap60 { margin-bottom: 60px; }
.case-h2.gap40 { margin-bottom: 40px; }
.p5 .flow-heading { margin-bottom: 70px; }

/* My Role is a 3-column layout filled column-major, not a wrapping grid. */
.role-cols { display: flex; gap: 8px; align-items: flex-start; margin-top: 20px; }
.role-col { display: flex; flex-direction: column; gap: 8px; flex: 1 1 0; min-width: 0; }

.role-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-top: 20px;
}

/* Compact, bulleted role cards. The 24px/18px block read as heavy and made the
   section a long scroll; the bullet carries the "these are items in a list"
   signal that the padding used to do. */
.role-card {
  background: var(--card-cream, #f8f7f4);
  border-radius: 14px;
  padding: 14px 18px;
  font-weight: 500;
  font-size: 16px;
  line-height: 24px;
  color: var(--charcoal);
  position: relative;
}

/* Bullet is a phone-only affordance: stacked full-width cards need the list
   cue, the three-column desktop grid already reads as a set. */
.role-card::before {
  content: none;
  position: absolute;
  left: 18px;
  top: 21px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--primary);
}

.research-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 30px 60px;
  margin-top: 20px;
}

.research-card { display: flex; flex-direction: column; gap: 16px; }

.research-dot {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--primary);
  flex-shrink: 0;
}

.research-card-head {
  display: flex;
  align-items: center;
  gap: 16px;
}

.research-card-head p {
  font-weight: 600;
  font-size: 18px;
  line-height: 26px;
  color: var(--charcoal);
  margin: 0;
}

.research-card-body {
  font-weight: 400;
  font-size: 16px;
  line-height: 26px;
  color: var(--charcoal);
  margin: 0;
}

.quote-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin: 30px 0;
}

.quote-card {
  background: var(--sidebar-bg);
  border-radius: 16px;
  padding: 30px 24px;
}

.quote-mark {
  font-size: 40px;
  color: var(--primary);
  line-height: 1;
  margin: 0 0 10px;
  font-weight: 700;
}

.quote-text {
  font-size: 18px;
  line-height: 28px;
  color: var(--charcoal);
  margin: 0;
  font-weight: 500;
}

.next-project-link {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  font-weight: 600;
  font-size: 20px;
  color: var(--accent);
  text-decoration: none;
  margin-top: 40px;
}

.next-project-link:hover { opacity: 0.8; }

.features-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 976 / 3402;
  border-radius: 20px;
  overflow: hidden;
}

.features-fg {
  position: absolute;
  height: auto;
  display: block;
}

.features-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }

.features-video {
  position: absolute;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 16px;
  box-shadow: 0 16px 32px -4px rgba(12,12,13,0.1), 0 4px 4px -4px rgba(12,12,13,0.05);
}

.numbered-list {
  list-style: none;
  counter-reset: case-num;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.numbered-list li {
  counter-increment: case-num;
  position: relative;
  padding-left: 34px;
  font-weight: 400;
  font-size: 16px;
  line-height: 30px;
  color: var(--charcoal);
}

.numbered-list li::before {
  content: counter(case-num) ".";
  position: absolute;
  left: 0;
  top: 0;
  font-weight: 600;
}

.numbered-list-label { font-weight: 600; }

.plain-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}

.plain-list li {
  position: relative;
  padding-left: 20px;
  font-weight: 400;
  font-size: 16px;
  line-height: 30px;
  color: var(--charcoal);
}

.plain-list.list-18 li { font-size: 18px; }

.plain-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 13px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--charcoal);
}

.research-note {
  width: 39.75%;
  margin-left: 60.25%;
  margin-top: 30px;
}

.research-arrow {
  display: block;
  width: 22.64%;
  height: auto;
  margin-left: 65.5%;
  margin-top: -6px;
}

.visual-wrap { position: relative; }

.tooltip-bubble {
  position: absolute;
  background: #12121f;
  color: #ffffff;
  border-radius: 12px;
  padding: 12px;
  font-size: 12px;
  font-weight: 500;
  line-height: 20px;
  text-align: center;
  z-index: 3;
}

.tooltip-bubble::after {
  content: "";
  position: absolute;
  top: -6px;
  left: 50%;
  transform: translateX(-50%);
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 6px solid #12121f;
}

.tooltip-bubble.tip-down::after {
  top: auto;
  bottom: -6px;
  border-bottom: none;
  border-top: 6px solid #12121f;
}

.phone-slideshow {
  position: absolute;
  aspect-ratio: 461 / 540;
  z-index: 2;
}

/* Project 4 lays the two "app hand" components out in normal flow, side by side. */
.phone-slideshow.c-static { position: relative; flex: none; }

.phone-slideshow .slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  transition: opacity 0.6s ease-in-out;
  border-radius: 0;
}

.phone-slideshow .slide.active { opacity: 1; }

.brand-scroll {
  display: block;
  width: 100%;
}

.brand-scroll img {
  display: block;
  width: 100%;
  height: auto;
  margin: 0;
}

.ms-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 976 / 3344;
  container-type: inline-size;
}

.ms-screen {
  position: absolute;
  height: auto;
  display: block;
}

.ms-cap {
  position: absolute;
  margin: 0;
  font-size: 1.639cqw;
  line-height: 3.074cqw;
  color: var(--charcoal);
  font-weight: 400;
}

.ms-cap b { font-weight: 600; }

/* Project 4 is built to the Figma frame's 976px content column
   (frame 1728 = 347px sidebar + 203px gutter + 976px content).
   Scoped to this page so the other case studies are untouched. */
/* Header metrics pinned to the Figma frame: breadcrumb sits in a 50px box,
   h1 is 54.494px/64px in an 838px measure, 100px gaps throughout. */
@media (min-width: 1301px) {
  .case-page-content .case-breadcrumb {
    display: flex;
    align-items: center;
    height: 50px;
    text-indent: 4.5px;
    margin-bottom: clamp(32px, 4.6vw, 56px);
  }

  /* Figma's box is 838px, but Google Fonts' Poppins renders line 1
     ("Helped top brands engage their") at 842px. 846px reproduces
     Figma's exact four line breaks. */
  .p4 .case-h1 {
    font-size: 54.494px;
    line-height: 64px;
    letter-spacing: -0.03em;
    max-width: 846px;
    margin: 0 0 clamp(44px, 5.9vw, 72px);
  }

  .p4 .c-sec:last-of-type { margin-bottom: 0; }

  /* Figma pins the footer link to the right edge of the column. */
  .case-page-content .next-project-link {
    display: flex;
    width: fit-content;
    margin: 90.74px 4px 0 auto;
  }
}

/* ---------------------------------------------------------------------------
   Short-viewport header tightening
   ---------------------------------------------------------------------------
   Figma's header stack (50 breadcrumb / 100 gap / logo / 60 / h1 / 60) is
   drawn for a tall canvas. On laptop-height screens it pushes the first image
   almost entirely below the fold. The 100px gap is the outlier - twice the
   others, and sitting between the two smallest elements on the page - so it
   takes most of the reduction. Type size is untouched.
   Above 1100px tall the Figma values stand exactly as drawn.
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   Project 5 hero: three device frames, the centre one playing the sign in
   Built in HTML rather than a flat export so the middle screen can hold video.
   Same card, radius and proportions as every other project hero.
--------------------------------------------------------------------------- */
.p5-hero {
  position: relative;
  container-type: inline-size;
  width: 100%;
  aspect-ratio: 976 / 513;
  border-radius: 20px;
  overflow: hidden;
  margin: 0 0 68px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #0d1116 url("images/p5-hero-bg.jpg") center / cover no-repeat;
}

/* A slight scrim so the device reads cleanly against the photograph without
   dulling it. */
.p5-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(8, 12, 18, 0.18), rgba(8, 12, 18, 0.34));
  pointer-events: none;
}

.p5-phone {
  position: relative;
  z-index: 1;
  flex: none;
  aspect-ratio: 760 / 1578;
  height: 86%;
  width: auto;
  border-radius: clamp(12px, 2.4cqw, 26px);
  overflow: hidden;
  background: #0b0d10;
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.16),
    0 30px 60px -12px rgba(0, 0, 0, 0.55),
    0 10px 22px -8px rgba(0, 0, 0, 0.4);
}

.p5-phone > * {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

@media (max-width: 640px) {
  .p5-hero { border-radius: 12px; margin-bottom: 56px; }
  .p5-phone { height: 84%; }
}

/* Project 5 states its role as a wrapping row of chips rather than a column
   grid: the lines are short, so chips read faster and waste less height. */
.p5 .role-cols { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-start; }
.p5 .role-col { display: contents; }

.p5 .role-card {
  padding: 10px 16px;
  font-size: 14px;
  line-height: 20px;
  border-radius: 20px;
  width: auto;
}

/* The Kinect screens lost a lot of height when the crop came off, so the row
   gives them the full column width instead of the designed thirds. */
.p4 [data-mobile-slideshow="kinect"] { width: 100% !important; gap: 40px; }
.p4 [data-mobile-slideshow="kinect"] > .c-cell { width: calc((100% - 80px) / 3) !important; }

/* ---------- Project 4 collection page ---------- */
/* Geometry mirrors the Figma frame "Project 4" (2186:14465), a 976px content
   column. All widths are expressed as a proportion of that column so the
   layout holds at any container width. */

.c-sec {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 60px;            /* Figma: section -> media gap */
  margin: 0 0 100px;    /* Figma: 100px between top-level blocks */
}

.c-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;            /* Figma: "my role" stack gap */
  width: 100%;
}

.c-stack { display: flex; flex-direction: column; align-items: flex-start; width: 100%; }
.c-row   { display: flex; align-items: center; width: 100%; }
.c-abs   { position: relative; }

/* An image frame: outer box keeps the designed aspect ratio, the leaf fills it. */
.c-cell {
  display: block;
  position: relative;
  overflow: hidden;
  flex: none;
}

.c-cell > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Figma image-fill crop transform: explicit offset + size on the leaf. */
.c-cell > img.crop,
.c-logo > img.crop {
  inset: auto;
  object-fit: cover;
}

.r10 { border-radius: 10px; }
.c-cell.r10 > img { border-radius: 10px; }

/* Logos keep their designed pixel frame, since the type around them is fixed too. */
.c-logo {
  display: block;
  position: relative;
  overflow: hidden;
  max-width: 100%;
  flex: none;
}

.c-logo > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.c-logo-pair {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 443px;
  max-width: 100%;
}

.c-x {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex: none;
}

.c-x img { width: 12px; height: 12px; display: block; }

.c-award { display: flex; align-items: center; gap: 20px; }

.c-play {
  position: absolute;
  display: block;
  aspect-ratio: 1;
  z-index: 3;
}

.c-play img { width: 100%; height: 100%; display: block; }

.parlament-title {
  font-family: 'Assistant', 'Poppins', sans-serif;
  font-weight: 700;
  font-size: 45.142px;
  line-height: normal;
  letter-spacing: 0.06em;
  color: #000;
  margin: 0;
}

.collection-note {
  font-style: italic;
  font-weight: 400;
  font-size: 16px;
  line-height: 30px;
  color: var(--charcoal);
  margin: 0;
  max-width: 78.381%;
}

.collection-desc {
  font-weight: 600;
  font-size: 25px;
  line-height: 30px;
  color: var(--charcoal);
  max-width: 50.717%;
  margin: 0;
}

.collection-tags { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

.collection-tag {
  background: var(--card-cream, #f8f7f4);
  border-radius: 20px;
  padding: 10px 14px;
  font-size: 14px;
  line-height: 20px;
  font-weight: 500;
  color: var(--charcoal);
  text-align: center;
}

/* Figma pinned two of these to 188px; with the compact chip they hug instead,
   which keeps the row rhythm even. */
.collection-tag.w188 { width: auto; }

.npl-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 12px;
  flex: none;
}

.npl-arrow img {
  /* source is 14x17; a 15x12 box squashed it */
  width: 12.35px;
  height: 15px;
  display: block;
  transform: rotate(90deg);
}

.flow-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 975 / 4755;
  border-radius: 20px;
  overflow: visible;
  container-type: inline-size;
}

.flow-notification {
  position: absolute;
  z-index: 2;
  background: rgba(248, 248, 248, 0.92);
  border-radius: 1.126cqw;
  padding: 1.386cqw;
  display: flex;
  flex-direction: column;
  gap: 0.26cqw;
  box-shadow: 0 1.64cqw 3.28cqw 0 rgba(12,12,13,0.1), 0 0.41cqw 0.41cqw 0 rgba(12,12,13,0.05);
}

.notif-header { display: flex; align-items: center; gap: 0.52cqw; }

.notif-appicon { width: 1.733cqw; height: 1.733cqw; flex-shrink: 0; display: block; }
.notif-appicon img { width: 100%; height: 100%; display: block; }

.notif-company {
  font-size: 1.126cqw;
  line-height: 1.559cqw;
  letter-spacing: -0.0068cqw;
  color: #8e8e93;
  font-weight: 600;
  text-transform: uppercase;
  flex: 1;
}

.notif-now {
  font-size: 1.126cqw;
  line-height: 1.559cqw;
  letter-spacing: -0.0068cqw;
  color: #8e8e93;
  font-weight: 300;
}

.notif-title {
  font-size: 1.3cqw;
  line-height: 1.733cqw;
  color: #000;
  font-weight: 700;
  margin: 0.52cqw 0 0;
}

.notif-sub {
  font-size: 1.3cqw;
  line-height: 1.733cqw;
  color: #000;
  font-weight: 300;
  margin: 0;
}

.flow-cap {
  position: absolute;
  margin: 0;
  z-index: 3;
  font-size: 1.641cqw;
  line-height: 3.077cqw;
  color: var(--charcoal);
  font-weight: 400;
}

.flow-fg {
  position: absolute;
  height: auto;
  display: block;
  z-index: 2;
}

.flow-arrow {
  position: absolute;
  height: auto;
  display: block;
  z-index: 1;
}

.flow-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }

.flow-video {
  position: absolute;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  box-shadow: 0 16px 32px -4px rgba(12,12,13,0.1), 0 4px 4px -4px rgba(12,12,13,0.05);
}

.web-design-video {
  width: 100%;
  height: auto;
  border-radius: 20px;
  display: block;
  margin-top: 30px;
}

/* ===========================================================================
   Responsive tiers
   ---------------------------------------------------------------------------
   >=1526   native Figma metrics (976px column, 203px gutter, 347px sidebar)
   1025+    sidebar and gutters contract fluidly via the :root clamps
   <=1024   sidebar is replaced by a top bar + modal menu
   <=640    single-column phone layout
=========================================================================== */

/* ---------- Mobile top bar (hidden on desktop) ---------- */
.mobile-bar { display: none; }

.mobile-toggle {
  width: 44px;               /* 44px minimum touch target */
  height: 44px;
  border: 0;
  background: transparent;
  padding: 10px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  border-radius: 8px;
}

.mobile-toggle span {
  display: block;
  height: 2px;
  width: 24px;
  background: var(--charcoal);
  border-radius: 2px;
  transition: transform 240ms cubic-bezier(0.32, 0.72, 0, 1), opacity 160ms ease;
}

.menu-open .mobile-toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-open .mobile-toggle span:nth-child(2) { opacity: 0; }
.menu-open .mobile-toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.mobile-panel {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--sidebar-bg);
  padding: 76px 24px 40px;
  overflow-y: auto;
  overscroll-behavior: contain;
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 220ms ease, transform 260ms cubic-bezier(0.32, 0.72, 0, 1);
  -webkit-overflow-scrolling: touch;
}

.mobile-panel.is-open { opacity: 1; transform: none; }

/* The panel clones .nav, which the tablet tier hides - re-show it here. */
.mobile-panel .nav {
  display: flex;
  position: static;
  width: 100%;
  max-height: none;
  gap: 4px;
  margin: 0;
  overflow: visible;
}

/* Comfortable phone targets, keeping the desktop marker language. */
.mobile-panel .nav-item {
  display: flex;
  height: 56px;
  gap: 20px;
  padding-left: 0;
  border-radius: 10px;
}

.mobile-panel .nav-item .marker { height: 28px; }
.mobile-panel .nav-item .label { font-size: 17px; width: auto; letter-spacing: 0.06em; }

.mobile-panel .projects-list { padding-left: 26px; gap: 2px; margin: 4px 0 12px; }

.mobile-panel .projects-list a,
.mobile-panel .projects-list .current {
  font-size: 16px;
  line-height: 1.35;
  min-height: 48px;
  display: flex;
  align-items: center;
  padding: 4px 0;
}

/* The active nav-item already carries the marker; a second bar on the current
   project reads as two competing indicators. Weight alone is enough. */
.mobile-panel .projects-list .current { font-weight: 500; color: var(--charcoal); }

@media (prefers-reduced-motion: reduce) {
  .mobile-panel { transition: opacity 120ms ease; transform: none; }
  .mobile-toggle span { transition: none; }
}

/* ---------- Tablet and below: swap the sidebar for the top bar ---------- */
@media (max-width: 1024px) {
  .page { max-width: 100%; }

  .sidebar, .brand, .nav { display: none; }

  .mobile-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: sticky;
    top: 0;
    z-index: 70;
    height: 60px;
    padding: 0 10px 0 24px;
    background: rgba(255, 255, 255, 0.88);
    backdrop-filter: saturate(1.8) blur(12px);
    -webkit-backdrop-filter: saturate(1.8) blur(12px);
    border-bottom: 1px solid var(--border-light);
  }

  .mobile-brand {
    font-weight: 500;
    font-size: 17px;
    color: var(--charcoal);
    text-decoration: none;
    letter-spacing: -0.01em;
  }

  .case-page-content,
  .about-content,
  .contact-content,
  .home-content {
    margin-left: 0;
    max-width: 100%;
    padding: 48px 40px 88px;
  }

  .role-grid { grid-template-columns: repeat(2, 1fr); }
  .role-cols { flex-wrap: wrap; }
  .role-col { flex: 1 1 45%; }
  .research-grid, .quote-grid { grid-template-columns: 1fr; }
  .about-row { flex-wrap: wrap; }
  .research-note { width: 100%; margin-left: 0; }
  .research-arrow { display: none; }
}

/* ---------------------------------------------------------------------------
   Mobile slideshows and overlays
   ---------------------------------------------------------------------------
   Groups that read as a set side by side on desktop (three Kinect screens, a
   grid of social posts, two phones in hand) become unreadable thumbnails when
   stacked. On phones they collapse into one frame that cycles instead, so the
   content stays full width and legible.
--------------------------------------------------------------------------- */
.m-slideshow {
  position: relative;
  width: 100%;
  display: block;
  overflow: hidden;
}

.m-slideshow > * {
  position: absolute !important;
  inset: 0 !important;
  width: 100% !important;
  height: 100% !important;
  margin: 0 !important;
  opacity: 0;
  transition: opacity 700ms ease-in-out;
}

.m-slideshow > .is-on { opacity: 1; }

/* contain, not cover: the box now follows the artwork so nothing is cropped */
.m-slideshow .c-cell > img,
.m-slideshow > .c-cell > img { object-fit: contain !important; }

.m-overlay { display: block; width: 100%; }

/* Once a board stacks, the play link's designed % offsets refer to a container
   that no longer exists at that height, so it slid to the bottom. Moved inside
   the still it belongs to and centred there instead. */
.c-cell.m-has-play { position: relative; }

.c-cell.m-has-play > .c-play {
  left: 50% !important;
  top: 50% !important;
  width: 22% !important;
  transform: translate(-50%, -50%);
  z-index: 4;
}

/* The collage rule forces every direct child static; the overlay wrapper has to
   stay a containing block, so it needs to outrank it on specificity. */
.flow-wrap > .m-overlay,
.ms-wrap > .m-overlay,
.features-wrap > .m-overlay { position: relative !important; height: auto !important; }
.m-overlay > .m-overlay-base { position: static !important; width: 100% !important; height: auto !important; }

.m-overlay > .m-overlay-top {
  position: absolute !important;
  left: 50% !important;
  top: 50% !important;
  transform: translate(-50%, -50%) !important;
  width: 72% !important;
  height: auto !important;
  opacity: 0.7;
  z-index: 2;
}

@media (prefers-reduced-motion: reduce) {
  .m-slideshow > * { transition: none; }
}

/* ---------- Phone ---------- */
@media (max-width: 640px) {
  /* The hero logos are sized as a % of the column, so a 8% logo lands at 28px
     on a phone. Pin them to a readable height instead and let width follow the
     artwork, which also optically normalises logos of different proportions. */
  .case-hero-logo svg,
  .case-hero-logo img {
    width: auto !important;
    height: clamp(30px, 5.5vw, 40px) !important;
  }

  .case-page-content,
  .about-content,
  .contact-content,
  .home-content { padding: 36px 20px 72px; }

  .case-h1 { font-size: clamp(28px, 7.2vw, 34px); line-height: 1.18; }
  .case-breadcrumb { font-size: 14px; }
  .case-h2 { font-size: 26px; line-height: 1.1; margin-bottom: 24px; }
  .case-h2.gap60, .case-h2.gap40 { margin-bottom: 28px; }
  .case-subhead { font-size: 19px; }
  .case-highlight { font-size: 20px; line-height: 1.5; }
  .case-body, .case-body.lg { font-size: 16px; line-height: 27px; }
  .case-section { margin-bottom: 64px; }
  .p2 .case-section, .p3 .case-section { margin-bottom: 34px; }
  .case-visual, .p3 .case-visual { border-radius: 12px; margin-bottom: 56px; }
  .m826, .m976 { max-width: 100%; }

  /* Stacked full-size cards made this section a long scroll. Tighter padding,
     a smaller measure and a leading bullet make it scannable instead. */
  .role-grid, .role-cols { display: flex; flex-direction: column; gap: 6px; }
  .role-col { flex: 1 1 auto; width: 100%; display: flex; flex-direction: column; gap: 6px; }
  .role-card {
    padding: 12px 14px 12px 30px;
    font-size: 15px;
    line-height: 21px;
    border-radius: 12px;
  }
  .role-card::before { content: ""; left: 14px; top: 18px; width: 5px; height: 5px; }

  /* 48px broke to 6 lines on a phone, 34px (the home hero size) read as small
     for a page whose headline is the whole content. 42px at 390 holds 4 lines
     and ramps up to meet the desktop clamp's 48px floor without a jump. */
  .about-content h1,
  .contact-content h1 { font-size: clamp(40px, 10.8vw, 48px); line-height: 1.15; }
  .about-photo { width: 150px; height: 150px; }
  .about-bio { font-size: 17px; line-height: 30px; }
  .about-passions { line-height: 1.35; }
  .contact-label { height: auto; margin-bottom: 4px; }
  .view-work-btn { width: 100%; max-width: 260px; }

  .collection-desc { font-size: 20px; line-height: 28px; max-width: 100% !important; }
  .collection-note { font-size: 15px; line-height: 26px; max-width: 100% !important; }
  .collection-tag { padding: 14px 18px; font-size: 15px; line-height: 22px; }
  .collection-tag.w188 { width: auto; }
  .parlament-title { font-size: 32px; }

  /* Project 4 media rows stack rather than shrinking to thumbnails. */
  .c-sec { gap: 32px; margin-bottom: 64px; }
  .c-row { flex-direction: column; gap: 10px !important; align-items: stretch; }
  .c-row > .c-cell,
  .c-row > .phone-slideshow { width: 100% !important; }
  /* Lockup is 397px (213 + 24 + 118 + gaps) and the column is 350, so it is
     sized by percentage. Every mark keeps its own ratio. */
  .c-logo-pair { width: 100%; gap: 0; justify-content: space-between; }
  .c-logo-pair > .c-logo:first-child { width: 53.7% !important; }
  .c-logo-pair > .c-x { width: 6%; height: auto; aspect-ratio: 1; }
  .c-logo-pair > .c-x img { width: 50%; height: 50%; }
  .c-logo-pair > .c-logo:last-child { width: 29.7% !important; }


  .c-award { gap: 14px; }

  .tooltip-bubble { font-size: 9px; padding: 6px; border-radius: 8px; line-height: 14px; }
}

/* ---------------------------------------------------------------------------
   Shared elevation
   ---------------------------------------------------------------------------
   Some mockups carry a baked-in shadow and some don't, and the videos never
   did - so blocks sat on two different planes. One token, applied to every
   media block that isn't already shadowed by its artwork.
--------------------------------------------------------------------------- */
:root { --media-shadow: 0 16px 32px -4px rgba(12,12,13,0.1), 0 4px 4px -4px rgba(12,12,13,0.05); }

/* The mockups already carry a shadow in the artwork - several (p2-ms*.png) even
   have a soft transparent halo baked in, so a CSS box-shadow drew a hard
   rectangle around that halo and read as a white outline. Only the videos were
   genuinely flat, so only they get the token. */
.features-video,
.flow-video,
.web-design-video {
  box-shadow: var(--media-shadow);
}

/* ---------- Footer (mobile only, static) ---------- */
/* Desktop already closes each page with the "Next project" / "Contact me" link,
   so a footer there was a second, weaker ending. Kept for phones and tablets,
   where that link is the only thing at the bottom of a very long scroll. */
.site-footer { display: none; }

.site-footer-sep { opacity: 0.6; }

@media (max-width: 1024px) {
  .site-footer {
    display: flex;
    margin-left: 0;
    padding: 32px 40px 40px;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
    font-size: 14px;
    line-height: 22px;
    color: var(--light-grey);
    border-top: 1px solid var(--border-light);
  }
}

@media (max-width: 640px) {
  .site-footer { padding: 28px 20px 36px; font-size: 13px; }
}

/* ---------------------------------------------------------------------------
   Wide editorial collages on small screens
   ---------------------------------------------------------------------------
   The flow / main-screens / feature boards are absolutely positioned against a
   976px design width. Scaled to a phone the pieces become thumbnails and the
   captions render at ~6px. A horizontal scroller preserved fidelity but forced
   sideways reading, so below the desktop tier the boards unstack completely:
   each piece becomes a full-width block in document order. Nothing is cropped
   and nothing scrolls sideways.
--------------------------------------------------------------------------- */
@media (max-width: 1024px) {
  .board-scroll { overflow: visible; margin: 0; padding: 0; }
  .features-wrap[style*="margin-top"] { margin-top: 24px !important; }
  .web-design-video { margin-top: 24px; }
  .board-scroll::after { content: none; }

  .flow-wrap,
  .ms-wrap,
  .features-wrap {
    display: flex;
    flex-direction: column;
    gap: 24px;              /* one fixed step between every stacked block */
    aspect-ratio: auto !important;
    height: auto !important;
    overflow: visible;
    container-type: normal;
    border-radius: 0;
  }

  .flow-wrap > *,
  .ms-wrap > *,
  .features-wrap > * {
    position: static !important;
    left: auto !important;
    top: auto !important;
    right: auto !important;
    bottom: auto !important;
    width: 100% !important;
    height: auto !important;
    max-width: 100%;
    transform: none !important;
  }

  /* No border-radius here: these mockups already have rounded corners and a
     soft shadow baked into the artwork, so a second radius only risks clipping
     it. Videos are flat rectangles and do get one. */
  .flow-wrap > img,
  .ms-wrap > img,
  .features-wrap > img { display: block; }

  .flow-wrap > video,
  .features-wrap > video { border-radius: 12px; display: block; }

  /* The designed box only reserves space so nothing jumps while media loads.
     It is NOT the media's real shape - Edit_growth_plan is 1.711 but its box is
     1.599 - so `cover` was cropping ~7% off the sides and making videos read as
     zoomed next to the uncropped images. `contain` guarantees every block shows
     its full frame at the same width; JS swaps in each video's true ratio once
     metadata arrives, after which contain letterboxes nothing. */
  .flow-wrap > [style*="--stack-aspect"],
  .ms-wrap > [style*="--stack-aspect"],
  .features-wrap > [style*="--stack-aspect"] {
    aspect-ratio: var(--stack-aspect);
    object-fit: contain;
  }

  /* captions were sized in cqw against the board; give them real type */
  .flow-cap,
  .ms-cap {
    font-size: 16px !important;
    line-height: 26px !important;
    letter-spacing: normal !important;
    color: var(--charcoal);
    padding: 0;
  }

  .notif-card { padding: 14px 16px !important; border-radius: 12px; }
  .notif-header { gap: 6px !important; }
  .notif-appicon { width: 18px !important; height: 18px !important; }
  .notif-company, .notif-now { font-size: 12px !important; line-height: 16px !important; }
  .notif-title { font-size: 15px !important; line-height: 20px !important; }
  .notif-sub { font-size: 13px !important; line-height: 18px !important; }

  .research-arrow, .p3-arrow, .flow-arrow { display: none !important; }
}

/* ---------------------------------------------------------------------------
   Project 5 - flow walkthrough
   ---------------------------------------------------------------------------
   The whole case study is a three-minute screen recording, so the layout has to
   make a long portrait video readable rather than just embedding it. The phone
   stays pinned while the annotation track scrolls alongside; each chapter seeks
   the video, and the active chapter follows playback. That gives the reader two
   ways in: scrub the flow, or read the argument and let the video follow.
--------------------------------------------------------------------------- */
.flow-lab {
  display: grid;
  /* The phone scales with the viewport instead of sitting at a fixed 360px:
     it is the subject of the page, so it should grow on a large display and
     shrink smoothly down to the tablet breakpoint rather than snapping. */
  grid-template-columns: clamp(330px, 26vw, 450px) minmax(0, 1fr);
  gap: clamp(28px, 4.5vw, 72px);
  align-items: start;
  margin-top: 40px;
}

/* Plain sticky: pinning it to the end of the column stopped it travelling
   with the reader, which was the point of the layout. */
.flow-stage { position: sticky; top: 110px; }

/* Sized by viewport HEIGHT so it always fits on screen, but the margin is kept
   tight: this phone is 0.462 aspect, so every pixel of height costs two of
   width. At 200px top and bottom a 900px window left it only 231px wide. */
.flow-phone {
  position: relative;
  height: clamp(360px, calc(100vh - 220px), 880px);
  width: auto;
  margin: 0 auto;
  aspect-ratio: 1284 / 2778;
  border-radius: 40px;
  overflow: hidden;
  background: #0b0d10;
  border: 9px solid #16181d;
  box-shadow: var(--media-shadow);
}

.flow-phone video { width: 100%; height: 100%; object-fit: cover; display: block; }

.flow-scrub {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 16px;
  font-size: 13px;
  color: var(--light-grey);
}

.flow-play {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--border-light);
  background: #fff;
  cursor: pointer;
  display: grid;
  place-items: center;
  flex: none;
  padding: 0;
  transition: border-color 160ms ease;
}

.flow-play:hover { border-color: var(--charcoal); }
.flow-play svg { width: 14px; height: 14px; fill: var(--charcoal); }

.flow-track {
  flex: 1;
  height: 3px;
  border-radius: 2px;
  background: var(--border-light);
  overflow: hidden;
}

.flow-track i { display: block; height: 100%; width: 0; background: var(--primary); }

.flow-chapters { display: flex; flex-direction: column; }

.flow-chapter {
  display: grid;
  grid-template-columns: 58px 1fr;
  gap: 18px;
  align-items: start;
  padding: 20px 0;
  background: none;
  border: 0;   /* buttons carry a 2px outset border by default */
  border-left: 0;
  border-right: 0;
  border-bottom: 0;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  width: 100%;
  /* negative inline margin so the hover tint can bleed past the text column
     without shifting anything */
  padding-left: 12px;
  padding-right: 12px;
  margin-left: -12px;
  margin-right: -12px;
  border-radius: 8px;
  transition: opacity 180ms ease;
}

.flow-chapter:hover { opacity: 0.8; }

@media (prefers-reduced-motion: reduce) {
  .flow-chapter { transition: none; }
}

.flow-chapter time {
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  font-weight: 500;
  color: var(--light-grey);
  padding-top: 3px;
  transition: color 200ms ease;
}

.flow-chapter h3 {
  font-size: 20px;
  font-weight: 600;
  line-height: 1.3;
  margin: 0 0 8px;
  color: var(--charcoal);
}

.flow-chapter p {
  margin: 0;
  font-size: 16px;
  line-height: 26px;
  color: var(--charcoal);
  opacity: 0.78;
  max-width: 54ch;
}

.flow-chapter.is-active time { color: var(--primary); }
.flow-chapter.is-active h3 { color: var(--primary); }

@media (max-width: 1024px) {
  .flow-lab { grid-template-columns: 1fr; gap: 24px; }
  .flow-stage {
    position: sticky;
    top: 68px;
    z-index: 5;
    background: #fff;
    padding-bottom: 12px;
    margin: 0 -20px;
    padding-left: 20px;
    padding-right: 20px;
  }
  /* On a phone the sticky-and-small approach put the recording at ~156px wide,
     which renders the app's own UI type at about 4px - unreadable, and the
     recording is the whole point of the page. So on small screens the phone
     stops being sticky and gets real size; tapping a chapter scrolls it back
     into view instead. */
  .flow-stage {
    position: static;
    margin: 0;
    padding-left: 0;
    padding-right: 0;
    background: none;
  }
  .flow-phone {
    height: auto;
    width: min(320px, 88%);
    margin: 0 auto;
    border-radius: 30px;
    border-width: 7px;
  }
  .flow-scrub { max-width: 320px; margin-left: auto; margin-right: auto; }
  .flow-chapter { grid-template-columns: 48px 1fr; gap: 12px; padding: 20px 0; }
  .flow-chapter h3 { font-size: 17px; }
  .flow-chapter p { font-size: 15px; line-height: 24px; }
}

/* scaffolding for the sections still to be written */
.p5-todo {
  border: 1px dashed #c08a1e;
  background: #fffbef;
  color: #7a5a06;
  padding: 18px 20px;
  font-size: 15px;
  line-height: 25px;
  margin: 16px 0 0;
  max-width: 72ch;
}

.p5-todo b {
  display: block;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 6px;
}


/* Mono shows up wherever something is a label, a caption or a measurement. */
.shipped figcaption,
.flow-cap,
.ms-cap,
.research-note,
.case-more-link,
.next-project-link { font-family: var(--mono); }

.next-project-link,
.case-more-link {
  font-size: 13px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.demo-hint, .work-go { font-family: var(--mono); }

/* ===========================================================================
   Bridge: project pages adopt the homepage's system
   ---------------------------------------------------------------------------
   The homepage sets the voice now, so the case studies inherit its palette,
   its top rail and its use of mono for anything that is data or a label.
   Body copy stays Poppins so long reading is unaffected.
=========================================================================== */

body { color: var(--ink); }

/* No sidebar any more: the column centres like the homepage's .wrap. */
.case-page-content,
.about-content,
.contact-content,
.home-content {
  margin-left: auto;
  margin-right: auto;
  max-width: 1180px;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
  padding-top: clamp(32px, 3.6vw, 52px);
  padding-bottom: clamp(48px, 5vw, 72px);
}

.sidebar, .brand, .nav, .mobile-bar { display: none !important; }

/* Breadcrumbs, tags and captions become data, in mono. */
.case-breadcrumb {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  height: auto;
  text-indent: 0;
  margin-bottom: clamp(24px, 3vw, 34px);
}

.case-h1 {
  font-family: var(--display);
  letter-spacing: -0.028em;
  color: var(--ink);
  max-width: 900px;
  font-size: clamp(32px, 4.6vw, 54px);
  line-height: 1.08;
}

.case-h2 {
  font-family: var(--display);
  font-size: clamp(24px, 3.4vw, 36px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.case-subhead { font-family: var(--display); color: var(--ink); }
.case-highlight { color: var(--ink-soft); }
.case-body { color: var(--ink-soft); }
.collection-desc { color: var(--ink); }

.collection-tag {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  background: var(--paper);
  color: var(--muted);
  border-radius: 4px;
  padding: 8px 12px;
}

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


/* ---------------------------------------------------------------------------
   Project pager
   ---------------------------------------------------------------------------
   Reviewers do not read case studies in order, and a single "Next project"
   link only ever moves one way. Previous and next at the foot of every case
   study, with the destination named so the choice is informed.
--------------------------------------------------------------------------- */
.pager {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  margin: 8px auto 0;
  max-width: 1180px;
  padding: 26px clamp(20px, 5vw, 72px) clamp(56px, 6vw, 88px);
}

.pager-spacer { flex: 1; }

.pager a {
  display: flex;
  flex-direction: column;
  gap: 5px;
  text-decoration: none;
  max-width: 46%;
}

.pager-next { text-align: right; align-items: flex-end; }

.pager-dir {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.pager-name {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(17px, 1.9vw, 23px);
  letter-spacing: -0.018em;
  color: var(--ink);
  line-height: 1.2;
  transition: color 160ms ease;
}

.pager a:hover .pager-name { color: var(--accent); }

.pager-ico { display: inline-block; transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1); }
.pager-prev:hover .pager-ico { transform: translateX(-4px); }
.pager-next:hover .pager-ico { transform: translateX(4px); }

@media (max-width: 560px) {
  .pager { gap: 14px; padding-top: 20px; }
  .pager a { max-width: 48%; }
  .pager-name { font-size: 16px; }
}

/* ---- About / Contact, in the homepage's system ---- */
.about-content h1,
.contact-content h1 {
  font-family: var(--display);
  color: var(--ink);
  letter-spacing: -0.028em;
  max-width: 22ch;
}

.about-passions { color: var(--ink); }
.about-bio { color: var(--ink-soft); }

.contact-label {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 400;
  height: auto;
  margin-bottom: 6px;
}

.contact-value { font-size: 19px; color: var(--ink); }
.contact-value a { color: var(--accent); text-underline-offset: 4px; }
.contact-item { padding-bottom: 26px; border-bottom: 1px solid var(--line); }
.contact-list { gap: 26px; }
.about-photo { border-radius: 10px; }

/* ---------------------------------------------------------------------------
   My role
   ---------------------------------------------------------------------------
   Previous attempts read as either a tag cloud or a spreadsheet. Studio sites
   tend to set a role list as an indexed run of lines: a hairline per item, a
   mono index, and the responsibility at reading size. It scans top to bottom
   in one pass and holds long and short lines equally well.
--------------------------------------------------------------------------- */
/* Two columns and no rules: as a single ruled column this ran to seven lines
   and read like a form. Paired up it takes half the height and scans as one
   block. */
.role-list {
  margin-top: 20px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(24px, 4vw, 64px);
  row-gap: 2px;
}

.role-item {
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 12px;
  align-items: baseline;
  padding: 9px 0;
}

.role-item .n {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  color: var(--muted);
}

.role-item .t {
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(15px, 1.5vw, 18px);
  line-height: 1.45;
  color: var(--ink);
  letter-spacing: -0.005em;
}

@media (max-width: 700px) {
  .role-list { grid-template-columns: 1fr; }
  .role-item { grid-template-columns: 28px 1fr; gap: 10px; padding: 7px 0; }
  .role-item .t { font-size: 15px; }
}

/* ---- legacy role grid, superseded by .role-list ----
   Pills stretched badly once the lines got long. These cells hold a full
   sentence at a readable size and stay on one grid line. */
.role-grid,
.role-cols,
.p5 .role-cols {
  display: grid !important;
  grid-template-columns: repeat(3, 1fr);
  align-items: stretch !important;
  gap: 1px !important;
  background: var(--line);
  border: 1px solid var(--line);
  margin-top: 26px;
}

.role-col { display: contents; }

.role-card,
.p5 .role-card {
  background: var(--white);
  border-radius: 0;
  padding: 22px 20px;
  font-family: var(--body);
  font-weight: 400;
  font-size: 15px;
  line-height: 23px;
  color: var(--ink-soft);
  width: auto;
}

.role-card::before { content: none; }

.next-project-link,
.case-more-link {
  font-family: var(--display);
  color: var(--accent);
}

.site-footer { font-family: var(--mono); border-top: 1px solid var(--line); color: var(--muted); }

@media (max-width: 900px) {
  .role-grid, .role-cols, .p5 .role-cols { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 560px) {
  .role-grid, .role-cols, .p5 .role-cols { grid-template-columns: 1fr; }
  .role-card, .p5 .role-card { padding: 16px 16px; font-size: 14.5px; line-height: 22px; }
}


/* ---- restored from the homepage system: motion + its responsive tiers ---- */
/* ---------- motion ---------- */
@media (prefers-reduced-motion: no-preference) {
  .reveal { opacity: 0; transform: translateY(14px); }
  .reveal.in { opacity: 1; transform: none; transition: opacity 620ms ease, transform 620ms cubic-bezier(0.22, 1, 0.36, 1); }
}

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  .lead-grid { grid-template-columns: 1fr; gap: 24px; }

  /* Stacked, each project is a tall block; 26px between them read as one
     continuous column rather than five separate pieces of work. */
  /* Space sits below the rule so each project opens with air rather than
     trailing it. */
  .work-row { grid-template-columns: 1fr; gap: 18px; padding: 52px 0 18px; }
}

@media (max-width: 720px) {
  body { font-size: 16px; }
  .rail-links { gap: 22px; }

  /* the spine folds into a single track, keeping the colour coding */
  .spine-head { display: none; }
  .spine-row { grid-template-columns: 1fr; min-height: 0; }
  .spine-link { display: none; }
  .spine-cell { padding: 14px 0; border-left: 2px solid var(--line); padding-left: 16px; }
  .spine-cell.res { border-left-color: var(--resident); padding-right: 0; }
  .spine-cell.mgr { border-left-color: var(--manager); text-align: left; padding-left: 16px; }
  .spine-cell::before {
    content: attr(data-side);
    display: block;
    font-family: var(--mono);
    font-size: 10.5px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 4px;
  }
  .spine-friction { padding: 18px 18px; }

  .tradeoff { grid-template-columns: 1fr; }
  .tradeoff > div + div { border-left: 0; border-top: 1px solid var(--line); }
  .shipped-pair { grid-template-columns: 1fr; }
  .decision { grid-template-columns: 1fr; gap: 0; }
  .decision-idx { padding-top: 0; margin-bottom: 8px; }
}

@media (max-width: 420px) {
  .work-fact { grid-template-columns: 66px 1fr; font-size: 12px; }
}
