:root {
  /* Landing/about exception palette — design-system.md §9.2 */
  --bg: #fdf8f0;
  --ink: #16181d;
  --gray: #6b7280;
  --gray-dark: #4b4f58;
  --yellow: #ee964b;
  --black: #111214;
  --white: #ffffff;
  --nav-h: 48px;

  /* Typography — design-system.md §3 (applies site-wide, no exception) */
  --font-display: "Sofia Sans", "Helvetica Neue", Arial, sans-serif;
  --font-accent: "Sofia Sans", "Helvetica Neue", Arial, sans-serif;
  --font-body: "Geist", -apple-system, "Segoe UI", sans-serif;

  --text-display: clamp(2.75rem, 1.5rem + 5.2vw, 5rem);
  --text-h1: clamp(2.25rem, 1.5rem + 3.0vw, 3.5rem);
  --text-h2: clamp(1.75rem, 1.35rem + 1.7vw, 2.375rem);
  --text-h3: clamp(1.375rem, 1.18rem + 0.8vw, 1.6875rem);
  --text-h4: 1.0625rem;
  --text-lead: clamp(1.125rem, 1.05rem + 0.4vw, 1.375rem);
  --text-body: 1.0625rem;
  --text-body-sm: 0.9375rem;
  --text-caption: 0.875rem;
  --text-eyebrow: 0.8125rem;
  --text-micro: 0.6875rem; /* interview-insight card labels */
  --text-metric: clamp(2.5rem, 1.8rem + 3.0vw, 3.75rem);
  --text-num-lg: clamp(1.75rem, 1.4rem + 1.2vw, 2.25rem); /* case-study row numbering */

  /* Sized to the sentence, not to a step on the scale — both headlines below
     are fixed copy that has to land on a set number of lines.
     --text-hero keeps "I make complex systems learnable." on ONE line from
     ~736px up (measured: the string is 16.21x its font-size, against the
     832px --measure column), and lets it fall to two lines on phones.
     --text-statement keeps the about page's title on TWO lines, with ~40px
     of slack on the longer line so it can't tip to three. */
  --text-hero: clamp(1.5rem, 0.73rem + 3.85vw, 3rem);
  --text-statement: clamp(1.75rem, 1.1rem + 1.9vw, 2.25rem);

  --leading-display: 1.0;
  --leading-tight: 1.10;
  --leading-snug: 1.35;
  --leading-relaxed: 1.5;
  --leading-body: 1.72;

  --tracking-display: -0.022em;
  --tracking-tight: -0.014em;
  --tracking-normal: 0em;
  --tracking-accent: 0.09em;

  /* Layout — design-system.md §4 (applies site-wide, no exception) */
  --measure: 52rem;
  --measure-wide: 72rem; /* docs/landing-structure-update.md §0b — card grids only */
  --page-gutter: clamp(1.25rem, 5vw, 3rem);
  --rail-width: 8rem; /* design-system.md §4.1 — case-study side nav rail */
  --rail-gap: 2.5rem;

  /* Elevation — docs/landing-structure-update.md §0a */
  --shadow-card: 0 1px 2px rgb(26 23 20 / .05),
                 0 6px 20px rgb(26 23 20 / .07);
  --shadow-card-hover: 0 2px 4px rgb(26 23 20 / .06),
                       0 14px 32px rgb(26 23 20 / .11);

  /* design-system.md §9.2 names, aliased to the tokens above (no value change) */
  --landing-bg: var(--bg);
  --landing-ink: var(--ink);
  --landing-gray: var(--gray);
  --landing-gray-dark: var(--gray-dark);
  --landing-accent: var(--yellow);
  --landing-black: var(--black);
  --landing-white: var(--white);

  /* Color — design-system.md §2.1 (applies site-wide, no exception) */
  --color-paper: #ffffff;
  --color-paper-sunken: #faf8f6;
  --color-line: #e9e5e0;
  --color-line-strong: #d5cfc7;
  --color-ink: #1a1714;
  --color-ink-secondary: #4a443d;
  --color-ink-muted: #7c7469;
  --color-brand: #ee964b;
  --color-brand-ink: #b25a14;
  --color-brand-soft: #fdf1e6;
  --color-teal: #1f6f63;
  --color-teal-soft: #e7f1ef;
  --color-focus: #b25a14;
}

.measure {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--page-gutter);
}

.measure-wide {
  width: 100%;
  max-width: var(--measure-wide);
  margin-inline: auto;
  padding-inline: var(--page-gutter);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body), "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}

/* About page only — the top (.about-hero-wrap) carries its own cream-to-
   white gradient, so the body base just needs to be the white it fades
   into for the sections below. */
body.about-page {
  background: var(--color-paper);
}

/* Matches where "Case Studies" lands when Work is clicked from the landing
   page (.work-white's own top padding), so the two pages' headings sit at
   the same height. */
body.about-page .page-intro {
  padding-top: 7.75rem;
}

a { text-decoration: none; color: inherit; }
button { font: inherit; border: none; background: none; cursor: pointer; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  text-wrap: balance;
  margin: 0;
}

/* ---------- Navbar ---------- */

.navbar {
  position: absolute;
  inset-inline: 0;
  top: 0;
  z-index: 6;
  padding: 18px var(--page-gutter);
}

.nav-inner {
  /* spans the full navbar (inset only by its page-gutter padding) so the
     logo and icon sit toward the viewport edges instead of --measure's
     narrower reading width */
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
}

/* explicit column placement: .nav-pill is position:fixed and out of grid
   flow, so auto-placement would otherwise slide .nav-actions into the
   middle column instead of the right one */
.nav-brand { grid-column: 1; justify-self: start; }
.nav-actions { grid-column: 3; justify-self: end; }

.nav-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

.nav-logo {
  width: var(--nav-h);
  height: var(--nav-h);
  border-radius: 50%;
  box-shadow: 0 4px 16px rgba(17, 18, 20, 0.06);
  object-fit: cover;
  flex-shrink: 0;
}

.brand-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 17px;
  color: var(--gray-dark);
}

.nav-pill {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 4px;
  height: var(--nav-h);
  background: rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(14px) saturate(180%);
  -webkit-backdrop-filter: blur(14px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: 999px;
  padding: 4px 6px;
  box-shadow: 0 4px 16px rgba(17, 18, 20, 0.06);
}

.nav-link {
  height: 100%;
  display: flex;
  align-items: center;
  padding: 0 18px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 14px;
  color: #4b4f58;
  transition: background 0.2s, color 0.2s;
  white-space: nowrap;
}

.nav-link:hover { color: var(--ink); }

.nav-link.active {
  background: var(--yellow);
  color: var(--black);
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.btn-linkedin {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--nav-h);
  height: var(--nav-h);
  background: var(--yellow);
  color: var(--white);
  border-radius: 50%;
  box-shadow: 0 4px 16px rgba(17, 18, 20, 0.06);
  transition: transform 0.15s ease;
}

.btn-linkedin:hover { transform: translateY(-2px); }

.nav-burger {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: var(--nav-h);
  height: var(--nav-h);
  background: var(--white);
  border-radius: 12px;
  box-shadow: 0 4px 16px rgba(17, 18, 20, 0.06);
}

.nav-burger span {
  width: 20px;
  height: 2px;
  background: var(--black);
  border-radius: 2px;
  transition: transform 0.2s ease, opacity 0.2s ease;
}

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

.mobile-menu {
  display: none;
  flex-direction: column;
  width: 200px;
  padding: 0 8px;
  max-height: 0;
  overflow: hidden;
  background: var(--white);
  border-radius: 16px;
  box-shadow: 0 4px 16px rgba(17, 18, 20, 0.06);
  box-sizing: border-box;
  transition: max-height 0.25s ease, padding 0.25s ease;
}

/* Padding only applies once open — at max-height:0 it left a persistent
   sliver visible even "closed", since Chrome doesn't collapse padding
   along with a max-height clamp the way it does ordinary content. */
.mobile-menu.open { padding: 4px 8px; }

.mobile-menu.open {
  max-height: 240px;
}

.mobile-link {
  position: relative;
  padding: 14px 6px;
  font-weight: 600;
  font-size: 15px;
  color: var(--ink);
}

/* Inset from the link's own padding edges (shorter than full-bleed) and
   skipped on the last item — no divider needed below "About". */
.mobile-link:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 6px;
  right: 6px;
  bottom: 0;
  border-bottom: 1px solid rgba(17, 18, 20, 0.05);
}

.mobile-link.active { color: var(--black); font-weight: 700; }

/* ---------- Hero ---------- */

.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  place-items: center;
  align-content: center; /* without this, the two auto rows stretch to fill
    the hero and each child centers inside its own oversized row instead of
    the headline+copy centering together as one compact block */
  /* Top padding only has to clear the absolutely-positioned navbar now that
     the icon arch is gone — 7.75rem is the same clearance .cs-hero and the
     about page's .page-intro use, so the headline lands at a consistent
     height across the site. */
  padding: 7.75rem 0 5.75rem;
  overflow: hidden;
  color: var(--landing-ink);

  background: linear-gradient(
    to bottom,
    var(--landing-bg) 0%,
    var(--landing-bg) 72%,
    var(--color-paper) 100%
  );
}

.hero-content {
  position: relative;
  z-index: 5;
  /* text column stays exactly --measure wide, as before — the page-gutter
     padding here is only a narrow-viewport safety margin, not a width cut */
  max-width: calc(var(--measure) + 2 * var(--page-gutter));
  margin-inline: auto;
  padding-inline: var(--page-gutter);
  text-align: center;
}

.hero h1 {
  /* --text-h1 topped out at 56px, where this headline needs 908px against an
     832px column and so always broke to two lines. --text-hero is the same
     shape of token, capped where the line actually fits. */
  font-size: var(--text-hero);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

/* ---------- Generic page intro (non-hero pages, e.g. about.html) ---------- */
/* Top padding matches .hero's so content clears the absolutely-positioned navbar. */

.page-intro {
  /* padding-block only — the inline gutter comes from the .measure/.measure-wide
     class alongside it. The old `padding: 6.5rem 0 4rem` shorthand won on source
     order and zeroed that gutter, which left the heading hanging a full gutter
     to the left of the content it sits above. */
  padding-block: 6.5rem 4rem;
  text-align: center;
}

.page-intro h1 {
  font-size: var(--text-h1);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

/* The about page's h1 is a full sentence rather than a label, so it needs the
   size that lets it sit on two lines (see --text-statement). */
/* Broken at the comma rather than left to text-wrap: balance — balancing put
   the break inside "now designing", and a punctuation break reads better than
   an even one. The <br> is dropped below the mobile breakpoint, where the
   second line no longer fits on its own and natural wrapping is tidier. */
body.about-page .page-intro h1 { font-size: var(--text-statement); }

/* ---------- About page: hero gradient (mirrors .hero's cream-to-white fade) ---------- */

.about-hero-wrap {
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--bg) 55%, white) 0%,
    color-mix(in srgb, var(--bg) 55%, white) 65%,
    var(--color-paper) 100%
  );
}

/* ---------- About page: photo stack + intro (side by side) ---------- */

.about-top {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 6fr);
  align-items: center;
  gap: clamp(2rem, 5vw, 4rem);
  padding-block: 0.5rem 3rem;
}

.photo-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 19rem;
  margin-inline: auto;
}

.photo-stack-item {
  position: relative;
  width: 92%;
  aspect-ratio: 4 / 3;
  padding: 0;
  border: 4px solid var(--color-paper);
  border-radius: 0.875rem;
  overflow: hidden;
  background: var(--color-brand-soft);
  box-shadow: var(--shadow-card);
  color: var(--color-ink-muted);
  display: grid;
  place-items: center;
  rotate: var(--rot);
  translate: var(--shift, 0) 0;
  cursor: pointer;
  margin-top: -2.75rem;
  transition: rotate 220ms cubic-bezier(.22,.61,.36,1),
              translate 220ms cubic-bezier(.22,.61,.36,1),
              scale 220ms cubic-bezier(.22,.61,.36,1),
              box-shadow 220ms ease;
}

.photo-stack-item:first-child { margin-top: 0; }

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

.photo-stack-item.is-front {
  rotate: 0deg;
  scale: 1.06;
  translate: 0 -0.625rem;
  box-shadow: var(--shadow-card-hover);
}

/* ---------- About page: intro card ---------- */

.intro-card {
  background: var(--color-paper);
  border: 1px solid var(--color-line);
  border-radius: 1.5rem;
  padding: clamp(1.75rem, 4vw, 3rem);
  box-shadow: var(--shadow-card);
}

.intro-card-dot {
  display: block;
  width: 2.25rem;
  height: 4px;
  border-radius: 999px;
  background: var(--yellow);
  margin-bottom: 1.25rem;
}

.intro-card p {
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--color-ink-secondary);
  margin: 0 0 1rem;
}

.intro-card p:last-child { margin-bottom: 0; }

/* ---------- About page: education + career ---------- */

.education-wrap { padding-block: 1rem 7rem; }
.timeline-wrap { padding-block: 1rem 5.5rem; }

.section-head { margin-bottom: clamp(1.5rem, 4vw, 2.25rem); }

.section-head h2 {
  font-size: var(--text-h2);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
}

.education-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
}

.education-item {
  background: var(--color-paper);
  border: 1px solid var(--color-line);
  border-radius: 1.25rem;
  padding: clamp(1.5rem, 3vw, 2rem);
  box-shadow: var(--shadow-card);
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
}

.education-item h3 {
  font-size: var(--text-h4);
  font-weight: 600;
  color: var(--color-ink);
}

.education-major {
  margin: 0;
  font-size: var(--text-body-sm);
  color: var(--color-ink-secondary);
}

.education-location {
  margin: 0;
  font-size: var(--text-body-sm);
  color: var(--color-ink-muted);
}

.timeline {
  list-style: none;
  margin: 0;
  padding: 0;
}

.timeline-item {
  display: grid;
  /* fixed first-column width, not minmax() — each <li> is its own grid
     container, so a content-sized track resolves to a different width per
     row (short "2026" vs. "May – Aug 2022"), throwing the dot/rail out of
     alignment between rows and making the connecting line look broken */
  grid-template-columns: 6.5rem 2rem 1fr;
  padding-block: clamp(1.75rem, 3.5vw, 2.5rem);
}

.timeline-item:first-child { padding-top: 0; }
.timeline-item:last-child { padding-bottom: 0; }

.timeline-date-col { padding-top: 0.1875rem; }

.timeline-date {
  font-size: var(--text-body-sm);
  font-weight: 500;
  color: var(--color-brand-ink);
}

.timeline-rail {
  position: relative;
  display: flex;
  justify-content: center;
}

.timeline-rail::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2px;
  translate: -50% 0;
  background: var(--color-line);
}

.timeline-item:first-child .timeline-rail::before { top: 0.5625rem; }
.timeline-item:last-child .timeline-rail::before { bottom: calc(100% - 0.5625rem); }

.timeline-dot {
  position: relative;
  z-index: 1;
  margin-top: 0.1875rem;
  width: 0.6875rem;
  height: 0.6875rem;
  border-radius: 50%;
  background: var(--color-paper);
  border: 2px solid var(--color-line-strong);
  transition: background 240ms ease, border-color 240ms ease, box-shadow 240ms ease;
}

.timeline-body h3 {
  margin: 0 0 0.25rem;
  font-size: var(--text-h4);
  font-weight: 600;
  color: var(--color-ink-muted);
  transition: color 240ms ease;
}

.timeline-org {
  margin: 0 0 0.5rem;
  font-size: var(--text-body-sm);
  color: var(--color-ink-muted);
}

.timeline-body p:last-child {
  margin: 0;
  font-size: var(--text-body-sm);
  line-height: var(--leading-body);
  color: var(--color-ink-muted);
  transition: color 240ms ease;
}

.timeline-item.is-active .timeline-dot {
  background: var(--color-brand);
  border-color: var(--color-brand);
  box-shadow: 0 0 0 4px var(--color-brand-soft);
}

.timeline-item.is-active .timeline-body h3 { color: var(--color-ink); }

.timeline-item.is-active .timeline-org,
.timeline-item.is-active .timeline-body p:last-child {
  color: var(--color-ink-secondary);
}

.hero-copy {
  position: relative;
  z-index: 5;
  max-width: calc(var(--measure) + 2 * var(--page-gutter));
  margin-inline: auto;
  padding-inline: var(--page-gutter);
  text-align: center;
  margin-block: 44px 64px;
}

/* Hero headline: the knot under "learnable" pulls itself straight.
   Every animated value is written frame-by-frame by script.js, so there is no
   transition or keyframe to declare here — which is also why the resting state
   below is the *finished* state. If the script never runs, the word still
   reads correctly with its clean underline already in place. */

.untangle {
  position: relative;
  display: inline-block;
  color: var(--yellow);
  white-space: nowrap;
}

/* The .ch spans are plain inline text and carry no styling of their own: they
   exist only as handles for the colour resolve, which script.js writes inline.
   Leaving them unstyled means the resting state is the finished one — the word
   inherits the accent colour from .untangle whether or not the script runs. */

.untangle-knot {
  position: absolute;
  left: 0;
  bottom: -0.52em;
  width: 100%;
  height: 0.62em;
  overflow: visible;
}

.untangle-knot path {
  fill: none;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* the tangled state is gray and starts hidden; the resolved line is the accent */
.untangle-knot .knot-messy { stroke: var(--gray); opacity: 0; }
.untangle-knot .knot-tidy  { stroke: var(--yellow); }

.subtitle {
  color: var(--gray-dark);
  font-weight: 400;
  font-size: var(--text-lead);
  line-height: var(--leading-snug);
  margin: 0 0 44px;
}

.subtitle-break { display: inline; }
.statement-break { display: inline; }

.hero-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
}

.btn-primary, .btn-secondary {
  padding: 14px 26px;
  border-radius: 10px;
  font-weight: 400;
  font-size: 14px;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.btn-primary {
  background: var(--yellow);
  color: var(--black);
}

.btn-secondary {
  background: var(--white);
  color: var(--black);
  box-shadow: 0 4px 16px rgba(17, 18, 20, 0.06);
}

.btn-primary:hover, .btn-secondary:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(17, 18, 20, 0.1);
}

/* ---------- Scroll cue ---------- */

.scroll-cue {
  position: absolute;
  bottom: 1.75rem;
  left: 50%;
  translate: -50% 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4375rem;

  font-family: var(--font-accent);
  font-size: var(--text-eyebrow);
  font-weight: 600;
  letter-spacing: var(--tracking-accent);
  text-transform: uppercase;
  color: var(--color-ink-muted);
  text-decoration: none;
}

.scroll-cue svg { animation: nudge 2.2s ease-in-out infinite; }

@keyframes nudge {
  0%, 100% { transform: translateY(0);        opacity: .4; }
  50%      { transform: translateY(.375rem);  opacity: 1; }
}

/* ---------- Work (Case Studies + Contact) ---------- */

.work {
  --w-panel: #ffffff;
  --w-border: #ece2d2;
  --w-ink: #1a1714;
  --w-body: #4a443d;
  --w-muted: #7c7469;
  --w-accent: #b25a14;
  --w-orange: #ee964b;
  --w-orange-hover: #e5842f;
  --w-green: #1f6f63;
  --w-red: #b3432f;
  --w-sub-bg: #fbf6ec;

  color: var(--w-body);
  scroll-margin-top: 24px;
}

.work h2, .work h3 {
  color: var(--w-ink);
}

.work-white {
  background: var(--color-paper);
  padding: clamp(3rem, 6vw, 5rem) 0 clamp(5rem, 12vw, 8.75rem);
}

.work-head {
  text-align: center;
  margin-bottom: clamp(2.5rem, 5vw, 3.75rem);
}

.work-head h1,
.work-head h2 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-h1);          /* not --text-h2 — outweighs the scroll cue above it */
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.75rem;
}

.case {
  display: block;
  background: var(--color-paper);
  border-radius: 1rem;
  padding: 0.875rem 0.875rem 1.5rem;
  box-shadow: var(--shadow-card);
  text-decoration: none;
  color: inherit;
  transition: box-shadow 180ms cubic-bezier(.22,.61,.36,1),
              transform  180ms cubic-bezier(.22,.61,.36,1);
}

.case:hover {
  box-shadow: var(--shadow-card-hover);
  transform: translateY(-3px);
}

/* Not a link — just previews an upcoming case study. */
.case.is-soon { cursor: default; }
.case.is-soon:hover { box-shadow: var(--shadow-card); transform: none; }

.thumb-badge {
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--text-eyebrow);
  letter-spacing: var(--tracking-accent);
  text-transform: uppercase;
  color: var(--color-ink);
  background: color-mix(in srgb, var(--color-paper) 85%, transparent);
  padding: 0.5rem 1rem;
  border-radius: 999px;
  box-shadow: var(--shadow-card);
  white-space: nowrap;
}

.thumb {
  position: relative;
  aspect-ratio: 3 / 2;
  border-radius: 0.625rem;
  background: var(--color-brand-soft);
  margin-bottom: 1.25rem;
  display: grid;
  place-items: center;
  overflow: hidden;
}

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

/* Full-bleed screenshot thumbs (e.g. hero-image reuse) crop badly at 3:2 —
   show the whole image centered instead of covering and cutting off the
   edges. Plain paper bg, not the shared brand-soft one: two case cards
   sitting side by side on the same orange tint read as near-duplicates. */
.thumb.is-contain {
  background: var(--color-paper);
}

.thumb.is-contain img {
  object-fit: contain;
  object-position: center;
  transform: scale(var(--thumb-zoom, 1));
}

.case-body { padding-inline: 0.625rem; }

.tags { display: flex; gap: 0.4375rem; flex-wrap: wrap; margin-bottom: 0.9375rem; }

.tag {
  padding: 0.3125rem 0.6875rem;
  border-radius: 999px;
  background: var(--color-brand-soft);
  font-family: var(--font-body);
  font-size: var(--text-caption);
  font-weight: 500;
  color: var(--color-ink-muted);
  line-height: 1;
}

.case h3 {
  margin: 0 0 0.625rem;
  padding-left: 0.6875rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-lead);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
}

.case p {
  margin: 0;
  padding-left: 0.6875rem;
  font-size: var(--text-body-sm);
  line-height: var(--leading-body);
  color: var(--color-ink-secondary);
}

/* ---------- Contact ---------- */

.contact {
  border-top: 1px solid var(--w-border);
  background: var(--w-sub-bg);
  padding: 80px var(--page-gutter) 88px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 36px;
  scroll-margin-top: 24px;
}

.contact-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  text-align: center;
  max-width: var(--measure);
}

.contact-status {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-display);
  font-size: var(--text-eyebrow);
  font-weight: 600;
  letter-spacing: var(--tracking-accent);
  text-transform: uppercase;
  color: var(--w-muted);
}

.contact-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--w-green);
}

.contact-head h2 {
  font-size: var(--text-h2);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.contact-head p {
  font-size: var(--text-body);
  line-height: var(--leading-body);
  margin: 0;
}

.contact-form {
  width: 100%;
  max-width: var(--measure);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.field span {
  font-family: var(--font-display);
  font-size: var(--text-eyebrow);
  font-weight: 600;
  letter-spacing: var(--tracking-accent);
  text-transform: uppercase;
  color: var(--w-muted);
}

.field input,
.field textarea {
  padding: 13px 16px;
  border: 1px solid var(--w-border);
  border-radius: 10px;
  background: var(--w-panel);
  font-size: var(--text-body);
  font-family: inherit;
  color: var(--w-ink);
  outline: none;
  transition: border-color 0.15s ease;
}

.field input::placeholder,
.field textarea::placeholder {
  color: var(--w-muted);
}

.field textarea { resize: vertical; line-height: 1.6; }

.field input:focus,
.field textarea:focus {
  border-color: var(--w-accent);
}

.field-full { grid-column: 1 / -1; }

.contact-submit-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.contact-submit {
  font-family: var(--font-display);
  font-size: var(--text-body-sm);
  font-weight: 600;
  padding: 13px 30px;
  border-radius: 999px;
  border: 1px solid transparent;
  background: var(--w-orange);
  color: #1a1714;
  cursor: pointer;
  transition: background 0.18s cubic-bezier(.2,0,0,1);
}

.contact-submit:hover {
  background: var(--w-orange-hover);
}

.contact-submit:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.contact-honeypot {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

.contact-form-message {
  margin: 0;
  font-size: var(--text-body-sm);
  font-weight: 600;
  min-height: 1.2em;
}

.contact-form-message.is-success { color: var(--w-green); }
.contact-form-message.is-error { color: var(--w-red); }

/* ---------- Footer ---------- */

.site-footer {
  border-top: 1px solid var(--color-line);
  background: var(--color-paper);
  padding: 40px var(--page-gutter);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
}

.footer-mark {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
}

.footer-tagline {
  margin: 0;
  font-size: var(--text-body-sm);
  color: var(--color-ink-secondary);
}

.footer-links {
  display: flex;
  align-items: center;
  gap: 16px;
}

.footer-links a {
  display: flex;
  color: var(--color-ink-muted);
  transition: color 0.15s ease;
}

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

.footer-copyright {
  margin: 0;
  font-size: var(--text-caption);
  color: var(--color-ink-muted);
}

/* ---------- Case study pages (e.g. urcareer.html) ---------- */
/* design-system.md §9.1 — case studies follow §2–5 with no exception, so
   these components use the standard sitewide palette (orange brand, used
   sparingly, plus neutral ink) rather than a bespoke per-project accent —
   every case study should read as one system, not each with its own hue. */

body.case-page {
  background: var(--color-paper);
  color: var(--color-ink-secondary);
}

.cs-casenav {
  display: none;
  position: fixed;
  top: 22vh;
  z-index: 40;
  width: var(--rail-width);
  right: calc(50% + (var(--measure) + 2 * var(--page-gutter)) / 2 + var(--rail-gap));
}

@media (min-width: 1300px) {
  .cs-casenav { display: block; }
}

.cs-casenav ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.cs-casenav a {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  text-decoration: none;
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-ink-muted);
  transition: color 260ms cubic-bezier(.65,0,.35,1);
}

.cs-casenav a::before {
  content: "";
  width: 12px;
  height: 2px;
  background: var(--color-line-strong);
  flex: none;
  transition: all 260ms cubic-bezier(.65,0,.35,1);
}

.cs-casenav a:hover { color: var(--color-ink); }
.cs-casenav a.is-active { color: var(--color-brand-ink); }
.cs-casenav a.is-active::before { width: 26px; background: var(--color-brand); }

.cs-hero { padding-top: 7.75rem; padding-bottom: 2.5rem; }

.cs-hero .tags { margin-bottom: 1.5rem; }

.cs-hero-title {
  font-size: var(--text-h1);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
}

.cs-lead {
  margin-top: 1.5rem;
  font-size: var(--text-lead);
  line-height: var(--leading-snug);
  color: var(--color-ink-secondary);
}

.cs-figure { margin: 0; }

.cs-frame {
  border: 1px solid var(--color-line);
  border-radius: 1.125rem;
  overflow: hidden;
  background: var(--color-paper-sunken);
  position: relative;
}

.cs-frame img { display: block; width: 100%; height: auto; }

.cs-hero-img { display: block; width: 100%; height: auto; }

/* Stand-in for a figure whose real asset isn't ready yet — same frame,
   a plain label instead of an image. */
.cs-ph {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  text-align: center;
  font-family: var(--font-accent);
  font-size: var(--text-caption);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-accent);
  color: var(--color-ink-muted);
}

.cs-frame-embed { padding: 0; }
.cs-frame-embed iframe { display: block; width: 100%; height: min(70vh, 640px); border: 0; }

.cs-video { position: relative; overflow: hidden; box-shadow: var(--shadow-card); }

/* Source export has a hairline dark column baked into its right edge —
   scale past the frame by a hair and let the wrapper's overflow clip it,
   rather than re-encoding. */
.cs-video-el { display: block; width: 101%; height: auto; }

.cs-video-pp {
  position: absolute;
  right: 0.5rem;
  top: 0.5rem;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  border: 1px solid var(--color-line-strong);
  background: color-mix(in srgb, var(--color-paper) 88%, transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: var(--color-ink);
  display: grid;
  place-items: center;
  cursor: pointer;
  box-shadow: var(--shadow-card);
  transition: transform 180ms cubic-bezier(.22,.61,.36,1),
              background 180ms cubic-bezier(.22,.61,.36,1);
}

.cs-video-pp:hover { background: var(--color-paper); transform: scale(1.06); }
.cs-video-pp svg { display: block; width: 14px; height: 14px; }

.cs-figure figcaption {
  margin-top: 0.75rem;
  font-family: var(--font-accent);
  font-size: var(--text-caption);
  line-height: var(--leading-snug);
  color: var(--color-ink-muted);
}

.cs-meta-strip {
  margin: 2.5rem 0 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.5rem;
  padding-block: 1.5rem;
  border-top: 1px solid var(--color-line);
  border-bottom: 1px solid var(--color-line);
}

.cs-meta-strip.is-tri { grid-template-columns: 1.4fr 1.1fr 0.8fr; }
@media (max-width: 640px) { .cs-meta-strip.is-tri { grid-template-columns: 1fr; } }

.cs-meta-strip dt {
  margin-bottom: 0.5rem;
  font-family: var(--font-accent);
  font-size: var(--text-eyebrow);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-accent);
  color: var(--color-ink-muted);
}

.cs-meta-strip dd {
  margin: 0;
  font-size: var(--text-body-sm);
  line-height: var(--leading-relaxed);
  color: var(--color-ink);
}

.cs-block {
  padding-bottom: clamp(4.5rem, 8vw, 8rem);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  scroll-margin-top: 6rem;
}

/* Reset first — the browser default UA margin-bottom on <p> was never
   overridden, so it stacked on top of each box's own bottom padding and
   made the space under the text look bigger than the space above it.
   Placed here (same specificity as the more specific rules below) so
   source order lets those still set their own margin-top afterward. */
.cs-block p { margin: 0; }

.cs-block:first-of-type { padding-top: clamp(4.5rem, 8vw, 8rem); }

.cs-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--font-accent);
  font-size: var(--text-eyebrow);
  font-weight: 600;
  letter-spacing: var(--tracking-accent);
  text-transform: uppercase;
  color: var(--color-ink-muted);
}

.cs-eyebrow::before {
  content: "";
  width: 22px;
  height: 2px;
  background: var(--color-line-strong);
  flex: none;
}

/* Sub-item numbering (e.g. "1-1") reads better as a bare label —
   the leading rule is sized for section-level eyebrows. */
.cs-eyebrow.is-plain::before { content: none; }

h2.cs-sec {
  margin-top: 1rem;
  font-size: var(--text-h2);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
}

.cs-block > p { margin-top: 1.5rem; }

.cs-insightbox-standalone { margin-top: 1.5rem; }
.cs-insightbox-standalone p { font-weight: 600; }

.cs-sub { margin-top: clamp(2.25rem, 4vw, 3.5rem); }

.cs-sublabel {
  font-family: var(--font-accent);
  font-size: var(--text-eyebrow);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-accent);
  color: var(--color-ink-secondary);
}

.cs-sub h3 {
  margin-top: 0.75rem;
  font-size: var(--text-h3);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
}

.cs-sub h3 + p { margin-top: 1rem; }
.cs-sub .cs-figure { margin-top: 1.5rem; }
.cs-sub .cs-pull:first-of-type { margin-top: 2rem; }

.cs-insightgrid {
  margin-top: 2rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.25rem;
}

/* Grouped interview-insight cards: a sunken well (.cs-well) containing one
   heading + card-grid per theme. Cards default to plain paper/bordered;
   .is-brand marks the one insight per theme worth calling out. */
.cs-note-group + .cs-note-group { margin-top: 2rem; }

.cs-note-heading {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-lead);
  letter-spacing: var(--tracking-tight);
  color: var(--color-brand-ink);
}

.cs-note-grid {
  margin-top: 1.25rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}

@media (max-width: 820px) { .cs-note-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .cs-note-grid { grid-template-columns: 1fr; } }

.cs-note {
  background: var(--color-paper);
  border: 1px solid var(--color-line);
  border-radius: 0.875rem;
  padding: 1.25rem;
}

.cs-note.is-brand {
  background: var(--color-brand-soft);
  border-color: transparent;
}

.cs-note-label {
  display: block;
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--text-micro);
  text-transform: uppercase;
  letter-spacing: var(--tracking-accent);
  color: var(--color-ink-muted);
  margin-bottom: 0.75rem;
}

.cs-note p {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-body-sm);
  color: var(--color-ink);
  margin: 0;
}

.cs-insightbox {
  padding: 1.5rem;
  background: var(--color-brand-soft);
  border-left: 3px solid var(--color-brand);
  border-radius: 0.875rem;
}

.cs-insightbox-n {
  display: block;
  font-family: var(--font-accent);
  font-size: var(--text-eyebrow);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-accent);
  color: var(--color-brand-ink);
}

.cs-insightbox p { margin-top: 0.75rem; color: var(--color-ink); }
.cs-insightbox p:first-child { margin-top: 0; }

.cs-insightbox cite {
  display: block;
  margin-top: 1rem;
  font-style: normal;
  font-family: var(--font-accent);
  font-size: var(--text-caption);
  color: var(--color-ink-muted);
}

.cs-pull {
  margin: 2.5rem 0 0;
  padding-left: 1.5rem;
  border-left: 2px solid var(--color-line-strong);
}

.cs-pull p {
  font-family: var(--font-display);
  font-size: var(--text-lead);
  line-height: var(--leading-snug);
  color: var(--color-brand-ink);
  margin: 0;
}

.cs-pull cite {
  display: block;
  margin-top: 0.75rem;
  font-style: normal;
  font-family: var(--font-accent);
  font-size: var(--text-caption);
  color: var(--color-ink-muted);
}

.cs-stats {
  margin-top: 2.5rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--color-line);
  border-radius: 0.875rem;
  overflow: hidden;
}

.cs-stat { padding: 1.5rem; border-right: 1px solid var(--color-line); }
.cs-stat:last-child { border-right: none; }

.cs-stat-label {
  display: block;
  margin-bottom: 1rem;
  font-family: var(--font-accent);
  font-size: var(--text-eyebrow);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-accent);
  color: var(--color-ink-muted);
}

.cs-stat-value {
  display: block;
  margin-bottom: 0.5rem;
  font-family: var(--font-display);
  font-weight: 600;
  /* smaller ceiling than --text-metric — at the full 3.75rem, "11-19%" (the
     widest value in this row) wraps to two lines in a 3-column stat box */
  font-size: clamp(1.75rem, 1.4rem + 1.6vw, 2.75rem);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
  color: var(--color-brand-ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.cs-stat-context {
  font-size: var(--text-caption);
  line-height: var(--leading-snug);
  color: var(--color-ink-muted);
}

.cs-tradeoffs {
  margin-top: 2.5rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
}

.cs-tocol {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--color-line);
  border-radius: 0.875rem;
  overflow: hidden;
  background: var(--color-paper);
}

.cs-tocard { padding: 1.25rem; }

.cs-tocard-lbl {
  display: block;
  margin-bottom: 0.75rem;
  font-family: var(--font-accent);
  font-size: var(--text-eyebrow);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-accent);
}

.cs-tocard-val {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-h4);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
}

.cs-tocard.is-drop { background: var(--color-paper-sunken); }
.cs-tocard.is-drop .cs-tocard-lbl,
.cs-tocard.is-drop .cs-tocard-val { color: var(--color-ink-muted); }

/* Some of the three "dropped"/"kept" values run to two lines while their
   siblings fit on one (varies by viewport width, not just which of the two
   this is) — reserve two lines' height on both so the row below always
   starts at the same point across all three columns. */
.cs-tocard-val {
  min-height: calc(2 * var(--text-h4) * var(--leading-snug));
}

.cs-tocard.is-keep {
  background: var(--color-brand-soft);
  border-top: 1px solid var(--color-line);
  box-shadow: inset 3px 0 0 var(--color-brand);
}

.cs-tocard.is-keep .cs-tocard-lbl { color: var(--color-brand-ink); }
.cs-tocard.is-keep .cs-tocard-val { color: var(--color-ink); font-weight: 600; }

.cs-tocol p {
  margin: 0;
  padding: 1.25rem;
  border-top: 1px solid var(--color-line);
  font-size: var(--text-body-sm);
  line-height: var(--leading-body);
  color: var(--color-ink-secondary);
}

.cs-solrow {
  display: grid;
  grid-template-columns: 17rem 1fr;
  gap: 2.75rem;
  align-items: start;
}

/* Video first (left, on the smaller track), text second (right) — flipped
   visually via order rather than DOM order, so reading/AT order still
   hits the description before the demo clip. */
.cs-solrow > .cs-figure { order: 1; }
.cs-solrow > div:first-child { order: 2; }

/* Cudagra only: text on the wide track (left), video on the narrow one
   (right) — natural DOM order, so no order flip needed here. */
.cs-solrow.is-reverse { grid-template-columns: 1fr 17rem; }
.cs-solrow.is-reverse > .cs-figure { order: 2; }
.cs-solrow.is-reverse > div:first-child { order: 1; }

.cs-solrow + .cs-solrow { margin-top: clamp(3rem, 6vw, 4.5rem); }

.cs-claim {
  margin-top: 1rem;
  font-size: var(--text-h3);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
}

/* Heading picks up the project accent here (scoped to solrow, not the
   shared .cs-claim used elsewhere); body gets a narrower measure so lines
   don't run the full (now-wider) text column, plus a bit more breathing
   room between eyebrow / heading / body. */
.cs-solrow .cs-claim { margin-top: 1.25rem; color: var(--color-brand-ink); }
.cs-solrow p { margin-top: 1.5rem; max-width: 32rem; }

.cs-grid-2 {
  margin-top: 1.25rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1rem;
}

/* These two are map thumbnails, not reading content — keep them side by
   side even on narrow screens so they read as a pair, not a repeat of the
   full map figures right below them. */
.cs-grid-2.is-maps { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 480px) {
  .cs-grid-2.is-maps { gap: 0.625rem; }
  .cs-grid-2.is-maps .cs-card { padding: 0.875rem; }
}

.cs-maps-hint {
  margin-top: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  font-family: var(--font-accent);
  font-size: var(--text-eyebrow);
  font-weight: 600;
  letter-spacing: var(--tracking-accent);
  text-transform: uppercase;
  color: var(--color-ink-muted);
}

.cs-maps-hint svg { animation: nudge 2.2s ease-in-out infinite; }

.cs-closing { margin-top: 1.25rem; }

.cs-footnote {
  margin-top: 4rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--color-line);
  font-size: var(--text-caption);
  line-height: var(--leading-snug);
  color: var(--color-ink-muted);
}

.cs-grid-3 {
  margin-top: 2.5rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 1rem;
}

.cs-card {
  background: var(--color-paper);
  border: 1px solid var(--color-line);
  border-radius: 0.875rem;
  padding: 1.5rem;
}

.cs-card-num {
  display: block;
  margin-bottom: 1.25rem;
  font-family: var(--font-accent);
  font-weight: 700;
  font-size: 1.375rem;
  line-height: 1;
  color: var(--color-brand-ink);
  letter-spacing: var(--tracking-accent);
}

.cs-card h4 {
  margin-bottom: 0.75rem;
  font-size: var(--text-h4);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
}

/* .cs-card-num used on an h4 (e.g. the map-picker cards) needs to win over
   the .cs-card h4 rule above, which otherwise outranks it (0,1,1 vs 0,1,0)
   and overwrites its color/font-size back to the plain heading look. */
.cs-card h4.cs-card-num {
  font-size: 1.375rem;
  color: var(--color-brand-ink);
}

/* Problems section only — its cards stand in for a missing image, so the
   heading also takes the accent and a bit more size (elsewhere just the
   card number is accented, at the shared, smaller .cs-card-num size). */
#problems .cs-card h4 { font-size: var(--text-lead); color: var(--color-brand-ink); }
#problems .cs-card-num { color: var(--color-ink-muted); }

.cs-card-thumb {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: 0.625rem;
  border: 1px solid var(--color-line);
  margin-bottom: 1rem;
}

.cs-card p { font-size: var(--text-body-sm); line-height: var(--leading-snug); }

.cs-more-grid {
  margin-top: 2rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 1.75rem;
}

/* ---------- Case study: image placeholder (asset not delivered yet) ---------- */

.cs-ph {
  aspect-ratio: 16 / 9;
  display: grid;
  place-items: center;
  gap: 0.5rem;
  border: 1px dashed var(--color-line-strong);
  border-radius: 1.125rem;
  background: var(--color-paper-sunken);
  color: var(--color-ink-muted);
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: 0.8125rem;
  text-align: center;
  padding: 1.5rem;
}

/* ---------- Case study: pan/zoom diagram viewer ---------- */

.cs-viewer {
  border: 1px solid var(--color-line);
  border-radius: 1.125rem;
  overflow: hidden;
  background: var(--color-paper-sunken);
}

.cs-vstage {
  position: relative;
  height: min(70vh, 620px);
  overflow: hidden;
  background: var(--color-paper-sunken);
  cursor: grab;
  /* Claims all single/multi-finger gestures for our own pan/pinch-zoom
     handlers — pan-y left vertical drags to the browser's native scroll,
     which hijacked one-finger panning and left pinch-zoom dead on touch. */
  touch-action: none;
}

.cs-vstage.is-dragging { cursor: grabbing; }

.cs-vstage img,
.cs-vstage svg.cs-vmedia {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  max-width: none;
  user-select: none;
  -webkit-user-drag: none;
}

.cs-viewer.is-sub .cs-vstage { height: min(58vh, 460px); background: var(--color-paper); }

/* Floating zoom control, bottom-right of the stage — matches the pan/zoom
   widget already shipped in urcareer-precedents-matrix.html (−/slider/+,
   percent readout, Fit), reused here so every diagram viewer feels the same. */
.cs-vctrl {
  position: absolute;
  right: 1rem;
  bottom: 1rem;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.375rem 0.5rem;
  background: color-mix(in srgb, var(--color-paper) 92%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--color-line);
  border-radius: 999px;
  box-shadow: var(--shadow-card);
}

.cs-vctrl-btn {
  all: unset;
  box-sizing: border-box;
  cursor: pointer;
  min-width: 2rem;
  height: 2rem;
  padding-inline: 0.5rem;
  border-radius: 0.625rem;
  display: grid;
  place-items: center;
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: 1rem;
  color: var(--color-ink-secondary);
  transition: background 180ms cubic-bezier(.20,0,0,1);
}

.cs-vctrl-btn:hover { background: var(--color-paper-sunken); }
.cs-vctrl-btn:active { background: var(--color-line); }

.cs-vctrl-fit {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-brand-ink);
}

.cs-vctrl-pct {
  min-width: 2.75rem;
  text-align: center;
  font-family: var(--font-accent);
  font-size: 0.75rem;
  color: var(--color-brand-ink);
  font-variant-numeric: tabular-nums;
}

.cs-vctrl-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 5.5rem;
  height: 2rem;
  margin: 0;
  background: transparent;
  cursor: pointer;
}

.cs-vctrl-slider::-webkit-slider-runnable-track { height: 4px; border-radius: 2px; background: var(--color-line-strong); }
.cs-vctrl-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--color-paper);
  border: 1px solid var(--color-line-strong);
  box-shadow: 0 1px 3px rgba(26,23,20,.2);
  margin-top: -5px;
}
.cs-vctrl-slider::-moz-range-track { height: 4px; border-radius: 2px; background: var(--color-line-strong); }
.cs-vctrl-slider::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border: 1px solid var(--color-line-strong);
  border-radius: 50%;
  background: var(--color-paper);
}

.cs-vhint {
  position: absolute;
  left: 1rem;
  bottom: 1rem;
  z-index: 4;
  padding: 0.25rem 0.625rem;
  background: color-mix(in srgb, var(--color-paper) 85%, transparent);
  border-radius: 999px;
  font-family: var(--font-accent);
  font-size: 0.6875rem;
  color: var(--color-brand-ink);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

@media (max-width: 700px) { .cs-vhint { display: none; } }
@media (max-width: 460px) { .cs-vctrl-slider { width: 3.5rem; } }

/* ---------- Case study: map + leverage-point overlay pairing ---------- */

.cs-mapset + .cs-mapset { margin-top: var(--space-section, clamp(4.5rem, 8vw, 8rem)); }

.cs-setnum {
  font-family: var(--font-accent);
  font-weight: 700;
  font-size: var(--text-eyebrow);
  letter-spacing: var(--tracking-accent);
  text-transform: uppercase;
  color: var(--color-brand-ink);
}

.cs-derived {
  margin-top: 2.5rem;
  position: relative;
  padding-top: 2.5rem;
}

.cs-derived::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 1px;
  height: 2rem;
  background: var(--color-line-strong);
}

.cs-derived::after {
  content: "Overlay";
  position: absolute;
  top: calc(2rem - 0.7rem);
  left: 50%;
  transform: translateX(-50%);
  background: var(--color-paper);
  padding-inline: 0.75rem;
  font-family: var(--font-accent);
  font-size: 0.6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-accent);
  color: var(--color-ink-muted);
}

.cs-well {
  background: var(--color-paper-sunken);
  border: 1px solid var(--color-line);
  border-radius: 1.125rem;
  padding: 2rem;
}

@media (max-width: 600px) { .cs-well { padding: 1.25rem; } }

.cs-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: 2rem;
  align-items: start;
}

@media (max-width: 860px) { .cs-split { grid-template-columns: 1fr; gap: 1.5rem; } }

.cs-hypo {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.75rem;
  align-content: start;
}

@media (max-width: 480px) { .cs-hypo { grid-template-columns: 1fr; } }

.cs-hypo-bubble {
  background: var(--color-paper-sunken);
  border: 1px solid var(--color-line);
  border-radius: 1.125rem;
  padding: 1rem 1.25rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-body-sm);
  line-height: var(--leading-snug);
  color: var(--color-ink);
}

.cs-hypo-bubble.is-brand {
  background: var(--color-brand-soft);
  border-color: transparent;
}

.cs-addlist {
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.cs-addlist li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.75rem;
  font-size: var(--text-body-sm);
  line-height: var(--leading-snug);
  color: var(--color-ink);
}

.cs-addlist li::before {
  content: "";
  width: 9px;
  height: 9px;
  border-radius: 50%;
  margin-top: 0.35em;
  background: var(--color-ink-muted);
}

/* ---------- Case study: positive/negative comparison grid ---------- */

.cs-compare {
  margin-top: 1.5rem;
  display: grid;
  grid-template-columns: minmax(0,.7fr) minmax(0,1fr) minmax(0,1fr);
  gap: 0.75rem;
  align-items: stretch;
}

/* Stays a 3-column table at every width — cells just shrink — rather than
   collapsing to one column, which loses the positive/negative pairing that
   is the whole point of this comparison. */
@media (max-width: 640px) {
  .cs-compare { gap: 0.4rem; }
  .cs-compare-head { font-size: 0.6875rem; }
  .cs-compare-row { font-size: var(--text-caption); }
  .cs-compare-cell { padding: 0.625rem; font-size: var(--text-caption); }
}

.cs-compare-head {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: var(--tracking-accent);
  text-align: center;
}

.cs-compare-head.is-positive { color: var(--color-teal); }
.cs-compare-head.is-negative { color: var(--color-brand-ink); }

.cs-compare-row {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--text-body-sm);
  text-transform: uppercase;
  letter-spacing: var(--tracking-accent);
  color: var(--color-ink);
  align-self: center;
  overflow-wrap: break-word;
  -webkit-hyphens: auto;
  hyphens: auto;
}

.cs-compare-cell {
  border-radius: 0.5rem;
  padding: 1rem;
  font-size: var(--text-body-sm);
  line-height: var(--leading-snug);
  color: var(--color-ink);
}

.cs-compare-cell.is-positive { background: var(--color-teal-soft); }
.cs-compare-cell.is-negative { background: var(--color-brand-soft); }

/* ---------- Responsive ---------- */

@media (max-width: 900px) {
  /* Full nav bar collapses to a burger menu; brand mark and pill nav hide. */
  .nav-brand,
  .nav-pill {
    display: none;
  }

  .nav-inner { grid-template-columns: 1fr; }

  /* Otherwise still renders in normal flow at the same top-right corner
     the now-fixed .nav-burger occupies, peeking out from behind it. */
  .btn-linkedin { display: none; }

  /* Fixed (not absolute, like the rest of .navbar) so the burger and its
     menu — unlike the LinkedIn button — stay on screen while scrolling,
     the same way .nav-pill does on desktop. Pinned to the right so it
     doesn't sit on top of the hero headline/icons underneath it. */
  .nav-burger {
    display: flex;
    position: fixed;
    top: 16px;
    right: var(--page-gutter);
    z-index: 50;
  }

  .mobile-menu {
    display: flex;
    position: fixed;
    top: calc(16px + var(--nav-h) + 8px);
    right: var(--page-gutter);
    z-index: 50;
  }

  .page-intro { padding: 96px var(--page-gutter) 40px; }

  /* Case study page (urcareer.html) — clear the burger nav. cs-stats,
     cs-tradeoffs and cs-solrow keep their desktop-width column counts through
     this whole tablet range on purpose (see the 46rem block below) — they
     only actually need to stack once the viewport gets phone-narrow. */
  .cs-hero { padding-top: 96px; padding-bottom: 40px; }
  .cs-meta-strip { grid-template-columns: repeat(2, 1fr); }

  /* photo stack stays on top, intro card below */
  .about-top { grid-template-columns: 1fr; }

  .photo-stack { max-width: 15rem; }

  .hero-content,
  .hero-copy {
    text-align: center;
  }

  .subtitle-break { display: none; }
  .statement-break { display: none; }

  .contact {
    padding: 48px var(--page-gutter) 56px;
    gap: 28px;
  }

  .contact-form {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 900px) and (min-width: 46.01rem) {
  /* Tablet only, above the 46rem mobile cutoff below. The vertical
     overlapping stack was built to sit narrow beside the intro text on
     desktop — once .about-top drops to one column here, that same stack
     reads as an oddly tall, disproportionate column with all that width
     going unused beside it. Lay the same three photos out as a row instead. */
  .photo-stack {
    flex-direction: row;
    max-width: 40rem;
  }

  /* .about-top's own 0.5rem top padding was tuned for sitting *beside* the
     heading's row on desktop, not stacked directly under it — give the
     now-wide photo row real breathing room from "About Me" above it. */
  .about-top {
    padding-block-start: 3rem;
  }

  .photo-stack-item {
    width: 34%;
    margin-top: 0;
    margin-left: -2rem;
    translate: 0 var(--shift, 0);
  }

  .photo-stack-item:first-child { margin-left: 0; }
}

@media (max-width: 46rem) {
  /* docs/landing-structure-update.md §5 — card grid's own breakpoint */
  .grid {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }

  /* text stacks above the screen instead of sitting beside it */
  .case-row {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }

  /* Case study page — cs-solrow's fixed 17rem video track holds its
     desktop-style side-by-side layout through tablet widths (see the 900px
     block) and only stacks once the viewport is genuinely phone-narrow. */
  .cs-solrow { grid-template-columns: 1fr; }
  .cs-solrow.is-reverse { grid-template-columns: 1fr; }

  /* Stacked, the screen must stay at its own native size instead of
     stretching to fill the now-full-width column, and sit centered. */
  .cs-solrow .cs-figure {
    max-width: 17rem;
    margin-inline: auto;
  }

  /* Text always reads before the screen once stacked — is-reverse (Cudagra)
     is already DOM-order text-first so this only changes the default
     (video-left) variant, but both are set explicitly here for clarity. */
  .cs-solrow > .cs-figure,
  .cs-solrow.is-reverse > .cs-figure {
    order: 2;
  }
  .cs-solrow > div:first-child,
  .cs-solrow.is-reverse > div:first-child {
    order: 1;
  }

  /* Education cards stay 3-across through tablet widths (stacking them
     there just leaves each short card floating in a lot of empty space) —
     only stack once truly cramped. */
  .education-grid { grid-template-columns: 1fr; }
}

/* Case study page — cs-tradeoffs' three dropped/kept columns get cramped
   below this width (measured: three-across still reads fine at 750px, but
   is tight by 650px) — switch to two-up (2 then 1) before it's forced to
   full single-column. */
@media (max-width: 43.75rem) {
  .cs-tradeoffs { grid-template-columns: repeat(2, 1fr); }
}

/* ...and two-up itself gets cramped below this width. */
@media (max-width: 30rem) {
  .cs-tradeoffs { grid-template-columns: 1fr; }
}

/* cs-stats' three EQUAL columns hold up until "11-19%" (the widest value) no
   longer fits without wrapping or spilling past the card's rounded corner —
   measured to happen right around 500px. Below that, give column 3 a bigger
   share (label/context text in columns 1-2 have their own unbreakable-word
   floor, so the ratio can't be pushed indefinitely) plus tighter padding —
   measured to hold three-up down to ~400px before the same overflow returns. */
@media (max-width: 32.5rem) {
  .cs-stats { grid-template-columns: 0.75fr 0.75fr 1.5fr; }
  .cs-stat { padding: 0.75rem 0.5rem; }
}

/* Below the narrowed-ratio floor above, stack for good. Measured floor for
   the ratio above was ~400px; a 10px margin is kept here for scrollbar-width
   and font-rendering variance across browsers/platforms. */
@media (max-width: 410px) {
  .cs-stats { grid-template-columns: 1fr; }
  .cs-stat { padding: 1.5rem; border-right: none; border-bottom: 1px solid var(--color-line); }
  .cs-stat:last-child { border-bottom: none; }
}

/* ---------- Reveal motion (docs/landing-structure-update.md §6) ---------- */

.reveal {
  opacity: 0;
  transform: translateY(1.25rem);
  transition: opacity 560ms cubic-bezier(.22,.61,.36,1),
              transform 560ms cubic-bezier(.22,.61,.36,1);
}

.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .scroll-cue svg { animation: none; }
  .cs-maps-hint svg { animation: none; }
}
