/* ==========================================================================
   TOKENS
   Design tokens extracted from the Figma frame
   "TMOBILE - SWITCHING - PRODUCTION" (node 688:11159).

   Values here come from get_variable_defs + the frame's design context.
   Nothing in the other stylesheets should hardcode a hex value or a raw
   type size — reach for a token instead.
   ========================================================================== */

:root {
  /* ---------------------------------------------------------------------
     COLOR
     Figma variable names are noted where one exists.
     --------------------------------------------------------------------- */

  /* Surfaces */
  --color-bg: #fafafa;              /* page background */
  --color-surface-grey: #efeeef;    /* Approach + Final Designs panels */
  --color-header: #323237;          /* top header bar */

  /* Brand / accent */
  --color-brand: #b82967;           /* hero headline magenta */
  --color-brand-75: rgba(184, 41, 103, 0.75);  /* hero eyebrow */
  --color-brand-88: rgba(184, 41, 103, 0.88);  /* hero body copy */
  --color-rose: #cf2c73;            /* color/rose/49 — Key Insights banner */

  /* Ink (dark → light) */
  --color-ink: #242427;             /* section + column headings */
  --color-ink-strong: #32302d;      /* emphasised run of Situation copy */
  --color-grey-15: #282626;         /* color/grey/15 — vertical rules */
  --color-grey-18: #2f2e2e;         /* color/grey/18 — Exploration body */
  --color-grey-25: #414141;         /* color/grey/25 — image caption */
  --color-body: #686765;            /* Approach body copy */
  --color-muted: #8a857f;           /* rail labels + secondary body copy */
  --color-nav-inactive: #454545;    /* case-study sub-nav, resting state */

  /* Ink on dark surfaces */
  --color-on-dark: #ededea;         /* nav tabs, Key Insights text */
  --color-grey-93: #ececec;         /* color/grey/93 — banner + impact body */
  --color-on-dark-strong: #fafafa;  /* impact headline */
  --color-white: #ffffff;

  /* ---------------------------------------------------------------------
     TYPOGRAPHY
     font family/Font 1 = Inter, font family/Font 2 = Poppins
     --------------------------------------------------------------------- */
  --font-primary: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
    Helvetica, Arial, sans-serif;
  --font-secondary: "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI",
    Helvetica, Arial, sans-serif;

  /* Weights */
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --fw-extrabold: 800;

  /* Static sizes (used where the design does not need to scale) */
  --fs-12: 0.75rem;    /* 12px — rail sub-labels */
  --fs-13: 0.8125rem;  /* 13px — hero eyebrow */
  --fs-14: 0.875rem;   /* 14px — nav, bullet lists, captions */
  --fs-15: 0.9375rem;  /* 15px — rail values */

  /* Fluid sizes. The upper bound is the value measured in the 1920 frame;
     the lower bound is the 375px-viewport value. */
  --fs-body: clamp(1rem, 0.86rem + 0.6vw, 1.25rem);        /* 16 → 20 */
  --fs-section-label: clamp(1.125rem, 1.05rem + 0.31vw, 1.5rem); /* 18 → 24 */
  --fs-column-heading: clamp(1.125rem, 1.03rem + 0.4vw, 1.25rem); /* 18 → 20 */
  --fs-wordmark: clamp(1.25rem, 1rem + 1.07vw, 2rem);      /* 20 → 32 */
  --fs-hero-title: clamp(2rem, 1.14rem + 3.66vw, 2.875rem); /* 32 → 46 */
  --fs-hero-lede: clamp(1rem, 0.86rem + 0.6vw, 1.25rem);   /* 16 → 20 */
  --fs-situation: clamp(1.375rem, 0.73rem + 2.74vw, 2.5rem); /* 22 → 40 */
  --fs-insight: clamp(1.25rem, 0.66rem + 2.5vw, 2.125rem); /* 20 → 34 */
  --fs-impact-title: clamp(1.875rem, 0.55rem + 5.63vw, 4rem); /* 30 → 64 */
  --fs-impact-body: clamp(1rem, 0.86rem + 0.6vw, 1.5rem);  /* 16 → 24 */

  /* Line heights — unitless so they scale with the fluid sizes above */
  --lh-tight: 1.08;    /* 49.68 / 46 — hero title */
  --lh-heading: 1.09;  /* 70 / 64 — impact headline */
  --lh-snug: 1.18;     /* 40 / 34 — key-insight lines */
  --lh-title: 1.4;     /* 56 / 40 — situation copy */
  --lh-label: 1.5;     /* 36 / 24 — section labels, column headings */
  --lh-body: 1.5;      /* 30 / 20 — body copy */
  --lh-impact-body: 1.58; /* 38 / 24 */
  --lh-rail: 1.4;      /* 21 / 15 — rail values */
  --lh-caption: 1.4;   /* 19.6 / 14 — Poppins caption */
  --lh-normal: normal;

  /* Letter spacing */
  --ls-tight-1: -1px;
  --ls-tight-92: -0.92px;
  --ls-tight-44: -0.44px;
  --ls-0: 0;
  --ls-10: 0.1px;
  --ls-12: 0.12px;
  --ls-15: 0.15px;
  --ls-wide: 1.82px;   /* hero eyebrow */

  /* ---------------------------------------------------------------------
     SPACE
     --------------------------------------------------------------------- */
  --space-xs: 8px;     /* item spacing/xs */
  --space-sm: 14px;
  --space-md: 24px;
  --space-lg: 40px;
  --space-xl: 64px;
  --space-2xl: 80px;

  /* Section rhythm — vertical gaps between the page's major blocks */
  --section-gap: clamp(48px, 3.5vw, 80px);
  --section-gap-lg: clamp(64px, 5vw, 110px);

  /* ---------------------------------------------------------------------
     LAYOUT
     The frame is 1920 wide with 80px gutters. Content sits in two columns:
     a label rail starting at x=80 and a main column starting at x=401.
     --------------------------------------------------------------------- */
  --layout-max: 1920px;
  --gutter: clamp(20px, 4.17vw, 80px);
  --rail-width: 321px;   /* 401 - 80 */
  --content-max: 1440px; /* main column at the 1920 reference width */

  /* Final-designs flow strips. All three are scaled by the SAME factor so a
     phone screen is the same size in every group: each strip's width is a
     percentage of the widest strip's native width (the reference), so they
     share one scale instead of each stretching to fill the panel. Below a
     common minimum scale they scroll sideways to stay legible. */
  --screenflow-ref: 1345px;   /* widest strip's native width */
  --screenflow-min-scale: 0.6;

  /* Shared-system values, copied from the portfolio's tokens.css so the
     case-study sub-nav on this page matches the other case studies exactly. */
  --cs-page-gutter:  clamp(1.25rem, 0.33981rem + 3.88350vw, 5rem);   /* 20 -> 80 */
  --cs-subnav-gap:   clamp(1.5rem, 1.13594rem + 1.55340vw, 3rem);    /* 24 -> 48 */

  /* Sticky chrome. Both the dark header and the light case-study strip pin to
     the top; the strip's offset is the header's height, so it stays correct as
     the header changes height across breakpoints (64px base, 90px desktop —
     overridden in the desktop media block below). */
  --header-height: 64px;
  --case-nav-height: 51px;


  /* ---------------------------------------------------------------------
     BORDERS, RADII, SHADOWS
     --------------------------------------------------------------------- */
  --stroke-1: 1px;
  --stroke-3: 3px;
  --radius-screen: 16px;
  --shadow-screen: 0 0 5.7px 0 rgba(0, 0, 0, 0.57);
  --shadow-page: 0 20px 60px 0 rgba(0, 0, 0, 0.12);

  /* Minimum touch target (WCAG 2.5.5 / mobile guidance) */
  --touch-target: 44px;

  /* ---------------------------------------------------------------------
     BREAKPOINTS
     Single source of truth. CSS cannot evaluate custom properties inside
     a media query, so the literals below are repeated in @media rules —
     but only these five values are ever used, and JS reads them from here
     via getComputedStyle so the two stay in step.

       Mobile        base styles      →  480px
       Large mobile  481px            →  767px
       Tablet        768px            → 1023px
       Desktop       1024px           → 1439px
       Large desktop 1440px and up  (1920 Figma frame is the reference)
     --------------------------------------------------------------------- */
  --bp-mobile-max: 480px;
  --bp-large-mobile: 481px;
  --bp-tablet: 768px;
  --bp-desktop: 1024px;
  --bp-large-desktop: 1440px;
}

/* The header grows from 64px to 90px at the desktop breakpoint, so the sticky
   sub-nav's top offset has to grow with it. Kept here beside the other
   breakpoint-driven values. */
@media (min-width: 1024px) {
  :root {
    --header-height: 90px;
  }
}


/* ==========================================================================
   MAIN
   Reset, element defaults, and the layout primitives shared by every page.
   Load order: tokens.css → main.css → components.css → case-study.css
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. RESET
   -------------------------------------------------------------------------- */

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

html {
  /* Anchor links land below the whole sticky chrome (header + sub-nav) rather
     than under it. Tracks both heights so it stays correct across breakpoints. */
  scroll-padding-top: calc(5.625rem + 3.1875rem + 1rem);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background-color: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-primary);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  /* The header is fixed and carries both bars, so replace the space it no
     longer occupies in the flow — same offset the other case studies use. */
  padding-top: calc(5.625rem + 3.1875rem);   /* header 90 + sub-nav 51 */
  /* Nothing in this design bleeds sideways; this is a backstop so a stray
     wide child can never produce a horizontal scrollbar on mobile. */
  overflow-x: hidden;
}

h1,
h2,
h3,
h4,
p,
figure,
blockquote {
  margin: 0;
}

ul,
ol {
  margin: 0;
  padding: 0;
}

img,
picture,
svg,
video {
  display: block;
  max-width: 100%;
}

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

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

/* --------------------------------------------------------------------------
   2. ACCESSIBILITY HELPERS
   -------------------------------------------------------------------------- */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Skip link — visible only once it takes focus. */
.skip-link {
  position: absolute;
  top: -100px;
  left: var(--space-xs);
  z-index: 100;
  padding: 12px 20px;
  background-color: var(--color-header);
  color: var(--color-white);
  font-size: var(--fs-14);
  font-weight: var(--fw-semibold);
  border-radius: 0 0 6px 6px;
  transition: top 0.15s ease;
}

.skip-link:focus {
  top: 0;
}

/* A single, consistent focus treatment across the site. */
:focus-visible {
  outline: 2px solid var(--color-rose);
  outline-offset: 3px;
  border-radius: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------------------------
   3. LAYOUT PRIMITIVES

   The frame is a two-column page: an 80px-inset label rail and a main
   content column that begins at x=401. Below the desktop breakpoint the
   rail label stacks above its content instead.
   -------------------------------------------------------------------------- */

/* Horizontal container — caps the content and applies the page gutters. */
.container {
  width: 100%;
  max-width: var(--layout-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* A page section built on the rail + content grid. */
.section {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
}

/* The small uppercase label that sits in the left rail
   (RESPONSIBILITY, SITUATION, APPROACH, FINAL DESIGNS, IMPACT). */
.section__label {
  font-size: var(--fs-section-label);
  font-weight: var(--fw-medium);
  line-height: var(--lh-label);
  letter-spacing: var(--ls-tight-44);
  color: var(--color-muted);
  text-transform: uppercase;
}

/* Content that pairs with a rail label. */
.section__content {
  min-width: 0; /* lets grid children shrink instead of forcing overflow */
}

/* Full-bleed band that escapes the container to span the viewport. */
.band {
  width: 100%;
}

/* Desktop and up: restore the true two-column rail layout. */
@media (min-width: 1024px) {
  .section {
    grid-template-columns: var(--rail-width) minmax(0, 1fr);
    gap: 0;
  }

  .section__label {
    grid-column: 1;
  }

  .section__content {
    grid-column: 2;
  }
}


/* ==========================================================================
   COMPONENTS
   Reusable pieces that will be shared by every case study in the portfolio.
   Page-specific composition lives in case-study.css.
   ========================================================================== */

/* --------------------------------------------------------------------------
   SITE HEADER
   Dark bar (#323237, 90px tall in the frame) carrying the wordmark, the
   primary nav, and the LinkedIn link.
   -------------------------------------------------------------------------- */

/* Values copied verbatim from the shared system (tokens.css / components.css)
   so this header renders pixel-identically to the other case studies.
   Keep in step if the shared system changes. */
.site-header {
  /* Fixed, carrying BOTH bars (dark header + case-study strip) as one unit,
     exactly as the other case studies do. body carries a matching padding-top
     to replace the space it no longer occupies in the flow. */
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 20;
  background-color: #323237;          /* --color-surface-header */
}

/* Shared page shell: 1760 content + gutters, centred. */
.site-header .shell {
  width: 100%;
  max-width: calc(1760px + var(--cs-page-gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--cs-page-gutter);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: 1rem;                          /* --space-16 */
  min-height: 5.625rem;               /* --header-height, 90 flat */
}

.site-header__wordmark {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  min-height: 44px;                   /* --tap-target */
  color: #fafafa;                     /* frame 715:8183 */
  /* Both header frames set this at a flat 32 — the desktop header (728:9841)
     and the mobile one (742:15539) — so it reaches 32 by the nav breakpoint
     and holds there rather than growing on to 1920. */
  font-size: clamp(1.375rem, 1.09056rem + 1.21359vw, 2rem);  /* 22 -> 32 at 1199 */
  font-weight: 500;
  line-height: 1.125;
  letter-spacing: -0.44px;            /* --ls-eyebrow */
  white-space: nowrap;
}

/* Hamburger toggle — mobile and tablet only. */
/* Drawn to match the frame's menu icon (742:15548): three 22.5 rules, 2.5
   thick with round caps, 7.5 apart. Kept as CSS bars rather than the exported
   SVG so they can still cross into an X when the panel opens. Sizing and
   placement come from the .site-header__actions group above. */
.nav-toggle__box {
  display: block;
  position: relative;
  width: 22.5px;
  height: 17.5px;
}

.nav-toggle__bar,
.nav-toggle__bar::before,
.nav-toggle__bar::after {
  position: absolute;
  left: 0;
  width: 22.5px;
  height: 2.5px;
  border-radius: 1.25px;              /* the frame's round line caps */
  background-color: currentColor;
  transition: transform 0.2s ease, opacity 0.2s ease;
}

.nav-toggle__bar {
  top: 7.5px;
}

.nav-toggle__bar::before,
.nav-toggle__bar::after {
  content: "";
}

.nav-toggle__bar::before {
  top: -7.5px;
}

.nav-toggle__bar::after {
  top: 7.5px;
}

/* Open state — the bars cross into an X.
   TODO (interactions phase): js/main.js toggles aria-expanded on
   .nav-toggle and the `is-open` class on .primary-nav. */
.nav-toggle[aria-expanded="true"] .nav-toggle__bar {
  background-color: transparent;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar::before {
  transform: translateY(7.5px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar::after {
  transform: translateY(-7.5px) rotate(-45deg);
}

/* Primary nav — a collapsible panel below the header bar on small screens. */
.primary-nav {
  display: none;
  position: absolute;
  inset-inline: 0;
  /* The header is the containing block and carries both bars, so 100% drops
     the panel clear of the sub-nav — same as the other case studies. */
  top: 100%;
  padding: var(--space-xs) var(--gutter) var(--space-md);
  background-color: var(--color-header);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.24);
}

.primary-nav.is-open {
  display: block;
}

.primary-nav__list {
  display: flex;
  flex-direction: column;
  list-style: none;
}

.primary-nav__link {
  display: flex;
  align-items: center;
  min-height: var(--touch-target);
  font-size: var(--fs-14);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-normal);
  color: var(--color-on-dark);
  text-transform: uppercase;
}

.primary-nav__link:hover {
  color: var(--color-white);
}

/* LinkedIn mark. Aligned to the end, not centred: the frame sets the mark's
   right edge on the page margin. The 44px touch target grows inward. */
/* --- Header actions: mail · LinkedIn · menu ------------------------------
   Figma 742:15540. The frame sets 40 between the icon boxes and puts the
   group's right edge on the page margin. Each control is a 44 touch target
   with its glyph centred, so the gap between BOXES is the frame's 40 less
   the padding those targets add either side.
   ------------------------------------------------------------------------ */
.site-header__actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: clamp(0.0625rem, -0.57752rem + 2.73058vw, 1.46875rem);
  margin-inline-start: auto;
  /* The frame puts the LAST glyph's right edge on the page margin, but a 44
     target centred on a 22.5 menu icon holds it ~11 short of that. Pulling
     the group out by that padding lands the glyph on the margin without
     shrinking the target or disturbing the gaps between the icons. */
  margin-inline-end: -10.75px;
}

.site-header__mail,
.site-header__social,
.nav-toggle {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 44px;                        /* --tap-target */
  height: 44px;
  color: var(--color-on-dark);
}

.site-header__mail-icon {
  width: 25px;
  height: 20px;
}

.site-header__mail:hover { color: var(--color-white); }

.site-header__social img {
  width: 2rem;                        /* 32 */
  height: 2rem;
  max-width: none;
}

/* From the shared nav breakpoint (1200) the row sits inline and right-aligned
   and the toggle disappears — same breakpoint and metrics as the other pages. */
@media (min-width: 1200px) {
  /* Only the menu goes. The mail icon has replaced the row's "Get in touch"
     item (frame 715:8183), so it is shown at every width now. */
  .nav-toggle { display: none; }

  /* Frame 715:8183 across the 1760 content box: the wordmark sits left and
     the cluster is hard against the right margin -
       nav row (658 at its natural width) | 41 | mail 30 | 38 | LinkedIn 32
     The icon anchors stay 44px touch targets with their glyphs centred, so
     the gaps between BOXES are the frame's gaps less the padding those
     targets add: 41 - 9.5 = 34 before the group, 40.5 - 9.5 - 6 = 25 inside
     it, and the trailing target overhangs the margin by 6. */
  .site-header__inner {
    display: flex;
    align-items: center;
    gap: 34px;
  }
  .site-header__wordmark { flex: 0 0 auto; }
  .primary-nav { flex: 0 0 auto; margin-inline-start: auto; }
  .primary-nav__list { max-width: none; margin-inline: 0; }
  .site-header__actions {
    flex: 0 0 auto;
    margin-inline-start: 0;
    gap: 25px;
    margin-inline-end: -6px;
  }

  .primary-nav {
    display: block;
    position: static;
    flex: 1 1 auto;
    min-width: 0;
    padding: 0;
    background: none;
    box-shadow: none;
  }

  .primary-nav__list {
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    gap: clamp(1.5rem, -1rem + 3.33333vw, 3rem);   /* 24 -> 48 */
    /* No cap: frame 715:8183 lets the six items sit at their natural 658
       and pins the row to the right margin. */
    max-width: none;
    min-width: 0;
    margin-inline: 0;
  }

  .primary-nav__link {
    min-height: 66px;
    white-space: nowrap;
    text-align: center;
  }




  .primary-nav__list {
    margin-inline: 0;
  }
}

/* --------------------------------------------------------------------------
   CASE-STUDY SUB-NAV
   Light 51px strip listing the six case studies, with an underline marking
   the current one. Scrolls horizontally when it cannot fit.
   -------------------------------------------------------------------------- */

/* These values are copied verbatim from the shared system (tokens.css,
   base.css, components.css) that the other case studies use, so this bar
   renders pixel-identically to the ones on Boarding App and WayFinder News.
   Keep them in step if the shared system changes. */
.case-nav {
  /* Sits inside the fixed .site-header, so the two bars pin together as one
     unit — the same arrangement the other case studies use. */
  background-color: #fafafa;          /* --cs-subnav-bg */
}

/* Shared page shell: 1760 content + gutters, centred. */
.case-nav .shell {
  width: 100%;
  max-width: calc(1760px + var(--cs-page-gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--cs-page-gutter);
}

.case-nav__inner {
  display: flex;
  align-items: center;
  min-height: 3.1875rem;              /* --cs-subnav-h, 51 flat */
  /* Below the nav breakpoint the labels are wider than the bar, so it scrolls
     sideways rather than wrapping or shrinking the type. */
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.case-nav__inner::-webkit-scrollbar {
  display: none;
}

.case-nav__list {
  display: flex;
  align-items: center;
  gap: var(--cs-subnav-gap);
  min-width: max-content;             /* keeps the labels on one line */
  list-style: none;
}

.case-nav__link {
  display: flex;
  align-items: center;
  min-height: 44px;                   /* --tap-target */
  color: #454545;                     /* --cs-subnav-ink */
  font-size: 0.875rem;                /* --fs-nav, 14 fixed */
  font-weight: 600;
  line-height: normal;
  text-transform: uppercase;
  white-space: nowrap;
  text-decoration-thickness: 1px;     /* --cs-subnav-underline */
  text-decoration-color: #1d1d1b;     /* --cs-subnav-underline-ink */
  text-underline-offset: 7px;     /* frame: 7px under the baseline */
}

a.case-nav__link:hover {
  color: #2f2e2e;                     /* --cs-ink */
  text-decoration-line: underline;
}

/* The project this page is. A <span>, not a link — there is nowhere for it to
   go — carrying the underline that marks it as selected. The frame keeps every
   label at --cs-subnav-ink; only the rule marks the current one. */
.case-nav__link--current {
  text-decoration-line: underline;
}

/* At the frame's own width the row sits where the frame puts it. Below the
   nav breakpoint the bar scrolls, so it starts from the left instead. */
@media (min-width: 1200px) {
  .case-nav__list {
    margin-inline-start: auto;
    margin-inline-end: 6.25%;         /* --cs-subnav-inset-end */
  }
}

/* --------------------------------------------------------------------------
   META RAIL
   The ROLE / TEAM / SHIPPED block in the left rail beside the hero.
   -------------------------------------------------------------------------- */

.meta-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md) var(--space-lg);
  list-style: none;
}

.meta-list__term {
  margin: 0;
  font-size: var(--fs-14);
  font-weight: var(--fw-bold);
  line-height: var(--lh-normal);
  letter-spacing: var(--ls-tight-44);
  color: var(--color-ink);
  text-transform: uppercase;
}

/* TEAM and SHIPPED are a step smaller than ROLE in the frame. */
.meta-list__item--sm .meta-list__term {
  font-size: var(--fs-12);
  letter-spacing: var(--ls-12);
}

.meta-list__value {
  margin: var(--space-xs) 0 0;
  font-size: var(--fs-15);
  font-weight: var(--fw-regular);
  line-height: var(--lh-rail);
  letter-spacing: var(--ls-15);
  color: var(--color-muted);
}

.meta-list__value--medium {
  font-weight: var(--fw-medium);
}

.meta-list__value ul {
  list-style: none;
}

/* Sitting underneath the hero image, the meta reads as a horizontal row of
   Role / Team / Shipped. It stays a row on wider screens with more air between
   the items, and wraps naturally when space runs out. */
@media (min-width: 768px) {
  .meta-list {
    gap: var(--space-lg) clamp(var(--space-xl), 6vw, 120px);
  }
}

/* --------------------------------------------------------------------------
   RULED BLOCK
   Copy introduced by a vertical rule on its left edge. Used at 3px for the
   Responsibility and Exploration paragraphs, 1px for the Approach columns.
   -------------------------------------------------------------------------- */

.ruled {
  padding-inline-start: var(--space-md);
  border-inline-start: var(--stroke-3) solid var(--color-grey-15);
}

.ruled--hairline {
  padding-inline-start: var(--space-sm);
  border-inline-start-width: var(--stroke-1);
}

/* --------------------------------------------------------------------------
   BULLET LIST
   Small 14px bulleted lists in the rail and in the Key Insights banner.
   -------------------------------------------------------------------------- */

.bullets {
  margin-top: var(--space-xs);
  padding-inline-start: 21px;
  list-style: disc;
  font-size: var(--fs-14);
  font-weight: var(--fw-medium);
  line-height: 1.45;
  letter-spacing: var(--ls-tight-44);
  color: var(--color-muted);
}

.bullets--on-dark {
  color: var(--color-on-dark);
}

/* --------------------------------------------------------------------------
   SCREENFLOW STRIP
   A wide exported contact-sheet of design screens in the Final Designs
   section. All three strips share ONE scale so a phone screen is the same
   size in every group: each image's width is its native width as a percentage
   of the reference (widest) strip — set inline as --sf-pct — measured against
   the shared .screenflows box, which is capped at the reference width. So a
   narrower strip renders proportionally narrower rather than being stretched
   up to fill the panel.

   Per strip, set --sf-w (native width) and --sf-pct (--sf-w ÷ reference) inline.
   -------------------------------------------------------------------------- */

.screenflow {
  margin: 0;
}

.screenflow img {
  display: block;
  width: var(--sf-pct);
  max-width: var(--sf-w); /* never upscale past native */
  /* Scroll rather than shrink below the shared minimum scale, so the screens
     stay readable — the floor is proportional, keeping the scale equal. */
  min-width: calc(var(--sf-w) * var(--screenflow-min-scale));
  height: auto;
}

/* --------------------------------------------------------------------------
   SCROLL HINT
   Marks a block that scrolls sideways on narrow viewports (the journey map).
   -------------------------------------------------------------------------- */

.scroller {
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  -webkit-overflow-scrolling: touch;
}

.scroller__hint {
  margin-top: var(--space-xs);
  font-size: var(--fs-14);
  font-style: italic;
  color: var(--color-muted);
}

@media (min-width: 1440px) {
  .scroller__hint {
    display: none;
  }
}


/* ==========================================================================
   CASE STUDY — T-MOBILE EASY SWITCH
   Page-specific composition. Reusable pieces live in components.css.
   Section order follows the Figma frame top to bottom.
   ========================================================================== */

/* --------------------------------------------------------------------------
   INTRO — the hero title-and-image artboard, with the project meta beside it
   The hero is a single exported image from Figma (node 696:12580) that already
   contains the eyebrow, title, lede, gradient and phone. It scales as one unit
   and never splits. The matching copy lives as visually-hidden text in the
   markup for assistive tech.

   Frame 688:11159 places the two like every other section on the page: the
   ROLE / TEAM / SHIPPED rail at x=80 (Group 40779) and the hero artboard at
   x=402, 1518 wide, running off the right edge to x=1920. So this reuses the
   same --rail-width grid .section already uses, and the hero bleeds right.

   Below the desktop breakpoint it collapses to one column. The meta stays
   after the hero in the DOM, so the small-screen order — hero, then meta —
   is exactly what it was.
   -------------------------------------------------------------------------- */

.intro {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.hero {
  padding-inline: 0;
  background-color: rgb(233, 224, 250); /* gradient tone while the image loads */
}

/* One image; keeps the artboard's 1518:761 ratio and scales to the width. */
.hero__image {
  display: block;
  width: 100%;
  height: auto;
}

/* Project meta. Wrapped under the hero on small screens; the left rail from
   the desktop breakpoint up. */
.intro__meta {
  padding: var(--space-lg) var(--gutter) 0;
}

@media (min-width: 1024px) {
  .intro {
    grid-template-columns: var(--rail-width) minmax(0, 1fr);
    align-items: start;
    /* Left gutter only: the hero runs to the right edge, as the frame draws
       it (x=402 → 1920). */
    padding-inline-start: var(--gutter);
  }

  /* Explicit placement so the hero can lead in the DOM while the rail still
     sits in column 1. */
  .intro__meta {
    grid-column: 1;
    grid-row: 1;
    padding: 0 var(--space-lg) 0 0;
  }

  /* In the rail the three items stack rather than sitting in a row. The
     frame's gaps are 24px: Role ends 186 → Team 210, Team ends 360 →
     SHIPPED 384. */
  .intro__meta .meta-list {
    flex-direction: column;
    flex-wrap: nowrap;
    gap: var(--space-md);
    /* <dl> carries a 1em UA margin. Cleared here only, so the rail's first
       item starts at y=141 with the hero; the small-screen spacing below the
       hero, which has always included it, is left alone. */
    margin: 0;
  }

  /* The frame's text boxes inside Group 40779: Role 264 wide, Team and
     SHIPPED 222. The narrower box is what wraps "4 Software & Network
     Engineers" onto a second line, which is what puts SHIPPED at y=384. */
  .intro__meta .meta-list__value {
    max-width: 264px;
  }

  .intro__meta .meta-list__item--sm .meta-list__value {
    max-width: 222px;
  }

  .intro .hero {
    grid-column: 2;
    grid-row: 1;
  }
}

/* --------------------------------------------------------------------------
   RESPONSIBILITY
   -------------------------------------------------------------------------- */

.responsibility {
  margin-top: var(--section-gap);
}

.responsibility__body {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--color-muted);
}

/* --------------------------------------------------------------------------
   SITUATION — square photo beside a large two-tone paragraph
   -------------------------------------------------------------------------- */

.situation {
  margin-top: var(--section-gap-lg);
}

.situation__layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
  align-items: start;
}

.situation__figure {
  position: relative;
  margin: 0;
  aspect-ratio: 1 / 1;
  max-width: 434px;
  overflow: hidden;
}

.situation__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 100% center;
}

.situation__body {
  font-size: var(--fs-situation);
  font-weight: var(--fw-regular);
  line-height: var(--lh-title);
  letter-spacing: var(--ls-tight-1);
  color: var(--color-muted);
}

/* The second half of the sentence steps up in weight and contrast. */
.situation__body strong {
  font-weight: var(--fw-medium);
  color: var(--color-ink-strong);
}

@media (min-width: 768px) {
  .situation__layout {
    grid-template-columns: minmax(200px, 434px) minmax(0, 1fr);
    gap: var(--space-lg);
  }
}

/* --------------------------------------------------------------------------
   APPROACH — grey band holding three ruled columns and the journey map
   -------------------------------------------------------------------------- */

.approach {
  margin-top: var(--section-gap-lg);
  padding-block: var(--section-gap);
  background-color: var(--color-surface-grey);
}

.approach__columns {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-lg);
  margin-bottom: var(--section-gap);
}

.approach__heading {
  margin-bottom: var(--space-xs);
  font-size: var(--fs-column-heading);
  font-weight: var(--fw-medium);
  line-height: var(--lh-label);
  letter-spacing: var(--ls-10);
  color: var(--color-ink);
}

.approach__body {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--color-body);
}

.approach__body strong {
  font-weight: var(--fw-bold);
}

/* Journey map is a single wide export; it scrolls sideways until it fits. */
.journey-map {
  margin: 0;
}

.journey-map img {
  width: 100%;
  /* Below this the map's labels stop being legible, so it scrolls instead. */
  min-width: 1000px;
  max-width: none;
  height: auto;
  /* Multiply drops the export's white ground onto the grey band, as in the
     frame, so the map reads as printed on the panel rather than pasted over it. */
  mix-blend-mode: multiply;
}

@media (min-width: 768px) {
  .approach__columns {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-lg) var(--space-xl);
  }
}

@media (min-width: 1024px) {
  .approach__columns {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 65px;
  }
}

/* --------------------------------------------------------------------------
   KEY INSIGHTS — full-bleed magenta band
   -------------------------------------------------------------------------- */

.insights {
  padding-block: var(--section-gap);
  background-color: var(--color-rose);
  color: var(--color-on-dark);
}

.insights__layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
}

.insights__label {
  color: var(--color-on-dark);
}

.insights__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  list-style: none;
}

.insights__item {
  font-size: var(--fs-insight);
  font-weight: var(--fw-medium);
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-tight-1);
  color: var(--color-grey-93);
}

@media (min-width: 1024px) {
  .insights__layout {
    grid-template-columns: var(--rail-width) minmax(0, 1fr);
    gap: 0;
  }
}

/* --------------------------------------------------------------------------
   FINAL DESIGNS — grey panel of exploration copy plus three screen rows
   -------------------------------------------------------------------------- */

.final-designs {
  margin-top: var(--section-gap-lg);
}

.final-designs__panel {
  padding: var(--section-gap) var(--gutter);
  background-color: var(--color-surface-grey);
}

.final-designs__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  max-width: 1268px;
  margin-bottom: var(--section-gap);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--color-grey-18);
}

/* Three exported flow strips, stacked with the section's vertical rhythm.
   Capped at the reference width so the strips share one scale and never
   upscale past native; left-aligned, as in the frame. */
.screenflows {
  display: flex;
  flex-direction: column;
  gap: var(--section-gap);
  max-width: var(--screenflow-ref);
}

/* --------------------------------------------------------------------------
   IMPACT — full-bleed photograph with the closing statement over it
   -------------------------------------------------------------------------- */

.impact {
  position: relative;
  margin-top: var(--section-gap-lg);
  padding-block: var(--section-gap-lg);
  background-color: var(--color-rose);
  background-image: url("../assets/switching/impact-background.jpg");
  background-size: cover;
  background-position: center;
  color: var(--color-grey-93);
}

.impact__label {
  color: var(--color-on-dark);
}

.impact__title {
  max-width: 929px;
  margin-top: var(--space-md);
  font-size: var(--fs-impact-title);
  font-weight: var(--fw-regular);
  line-height: var(--lh-heading);
  letter-spacing: var(--ls-tight-1);
  color: var(--color-on-dark-strong);
}

.impact__body {
  max-width: 633px;
  margin-top: var(--section-gap);
  font-size: var(--fs-impact-body);
  font-weight: var(--fw-regular);
  line-height: var(--lh-impact-body);
  letter-spacing: var(--ls-tight-1);
  color: var(--color-grey-93);
}

/* On narrow screens the photograph's subject is off-frame behind the copy,
   so a scrim keeps the text readable over whichever part shows through. */
.impact::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    100deg,
    rgba(207, 44, 115, 0.92) 0%,
    rgba(207, 44, 115, 0.72) 45%,
    rgba(207, 44, 115, 0.1) 78%,
    rgba(207, 44, 115, 0) 100%
  );
}

.impact > * {
  position: relative;
  z-index: 1;
}

@media (min-width: 1440px) {
  .impact {
    /* At the reference width the artwork already carries its own gradient. */
    background-position: right center;
  }

  .impact::before {
    background: linear-gradient(
      100deg,
      rgba(207, 44, 115, 0.35) 0%,
      rgba(207, 44, 115, 0) 45%
    );
  }
}


/* --- Below the nav breakpoint: the mobile header (Figma 742:15538) -------
   A taller bar — 114 against the desktop header's 90 — carrying the wordmark
   and the three icons and nothing else. This stylesheet writes the chrome
   offsets as literals rather than reading a token, so the bar height, the
   body offset that replaces it in the flow, and the anchor scroll-padding
   are all restated here.
   ------------------------------------------------------------------------ */
@media (max-width: 1199px) {
  html { scroll-padding-top: calc(7.125rem + 3.1875rem); }
  body { padding-top: calc(7.125rem + 3.1875rem); }   /* header 114 + sub-nav 51 */

  .site-header__inner { min-height: 7.125rem; }       /* 114 (742:15538) */

}
