/* =========================================================
   Portfolio Styles
   Plain CSS, no framework. Custom properties drive theming.
   ========================================================= */

:root {
  /* Type */
  --font-body:
    "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
    sans-serif;
  --font-display: "Source Serif 4", Georgia, "Times New Roman", serif;

  /* Brand palette — fixed, does not adapt to OS light/dark setting */
  --bg: #1f051c; /* darkest plum — page background */
  --bg-elevated: #2e0a29; /* card / header background */
  --text: #f7ece3; /* primary text — soft warm ivory */
  --text-muted: #f7ece3; /* secondary text — soft warm ivory */
  --text-subtle: #be9ca8; /* subtlest*/
  --border: #2e0a29; /* borders / dividers */
  --accent: #ffbe5c; /* links, highlights, hover states — ~4.8:1 on bg */
  --highlight: #ffbe5c52;
  --accent-text: #090608; /* text placed on top of an accent-colored fill */
  --illustration: #ffbe5c; /* hero illustration line color — warm gold. Was #441c3c for the low-contrast flower doodle; now drives the waving-Natalie hero sketch, which wants to be seen. */
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.35), 0 8px 28px rgba(0, 0, 0, 0.45);

  /* Spacing scale */
  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.5rem;
  --space-4: 2.5rem;
  --space-5: 4rem;
  --space-6: 6rem;
  --space-7: 9rem;

  --radius: 14px;
  --max-width: 1024px;
  /* Container side padding — fluid so it never collapses on narrow screens
     (a fixed --space-3 doesn't shrink, but it also doesn't grow, and looked
     like it "vanished" once content near the edge had nothing else framing
     it) and gains a little extra air on wide viewports. */
  --container-pad: clamp(1.25rem, 4vw, 2rem);

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

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-weight: 300;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  margin: 0;
}

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

a {
  color: inherit;
}

.wrap {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--container-pad);
}

/* ---------- Link underline (shared) ----------
   One hover-reveal underline mechanic, reused by every link on the site:
   nav links, "← Return", work-row "Learn more", footer links, and inline
   prose links (.link). A ::after grows from 0 to 100% width under the text
   on hover. Each context below only adds its own color/size/layout — the
   underline behavior itself is defined once, here. */

.nav-links a,
.back-link,
.work-row-link,
.footer-links a,
.link {
  position: relative;
}

.nav-links a::after,
.back-link::after,
.work-row-link::after,
.footer-links a::after,
.link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 0%;
  height: 1px;
  background: currentColor;
  transition: width 0.25s var(--ease);
}

.nav-links a:hover::after,
.back-link:hover::after,
/* the whole card is the link, so hovering anywhere on .work-row reveals it */
.work-row:hover .work-row-link::after,
.footer-links a:hover::after,
.link:hover::after {
  width: 100%;
}

/* Generic inline link (e.g. a link inside a paragraph) — same underline
   mechanic as the rest of the site instead of a hand-rolled <u>. */
.link {
  text-decoration: none;
  color: inherit;
  transition: color 0.2s var(--ease);
}

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

/* ---------- Header / Nav ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 85%, transparent);
  backdrop-filter: blur(10px);
  transition: box-shadow 0.3s var(--ease);
}

.site-header.is-scrolled {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.12),
    0 4px 14px rgba(0, 0, 0, 0.16);
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2) var(--container-pad);
  max-width: var(--max-width);
  margin: 0 auto;
}

.nav-logo {
  display: flex;
  align-items: center;
  gap: var(--space-1, 0.5rem);
  font-family: var(--font-display);
  font-size: 1.05rem;
  text-decoration: none;
  letter-spacing: -0.01em;
}

.nav-logo-icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
}

.nav-links {
  display: flex;
  gap: var(--space-4);
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-links a {
  text-decoration: none;
  font-size: 0.95rem;
  color: var(--text-muted);
  transition: color 0.2s var(--ease);
}

.nav-links a:hover {
  color: var(--text);
}

/* Scroll-spy: the underline "lights up" and stays lit for whichever
   section is currently in view, in the brand accent color. */
.nav-links a.is-active {
  color: var(--text);
}

.nav-links a.is-active::after {
  width: 100%;
  background: var(--text-subtle);
  box-shadow: 0 0 8px color-mix(in srgb, var(--text-subtle) 65%, transparent);
}

@media (max-width: 720px) {
  .nav {
    gap: var(--space-2);
  }

  .nav-logo {
    font-size: 0.95rem;
  }

  .nav-links {
    gap: var(--space-2);
    flex-wrap: nowrap;
    flex-shrink: 0;
  }
}

@media (max-width: 420px) {
  .nav-logo {
    font-size: 0.85rem;
  }

  .nav-links {
    gap: var(--space-1, 0.5rem);
  }

  .nav-links a {
    font-size: 0.85rem;
  }
}

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

.hero {
  /* padding-top/bottom only (not the shorthand) so this doesn't clobber
     .wrap's left/right padding — same specificity, later in the cascade,
     and a shorthand here would reset the sides to 0. */
  /* Fluid instead of a flat --space-7/--space-6: on a short mobile
     viewport, 144px of top padding alone pushes "Howdy!" almost to the
     middle of the screen before anything else has happened. Scales down
     to a much tighter clamp floor on small screens, back up to the
     original spacing on desktop. */
  padding-top: clamp(3rem, 8vw + 2rem, var(--space-7));
  padding-bottom: clamp(2.5rem, 6vw + 1rem, var(--space-6));
}

.hero-eyebrow {
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-subtle);
  font-weight: 600;
  margin: 0 0 var(--space-2);
}

.hero h1 {
  font-size: clamp(2.2rem, 5vw, 3.75rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin: 0 0 var(--space-3);
  max-width: 18ch;
}

.hero p {
  font-size: 1.4rem;
  color: var(--text-muted);
  max-width: 52ch;
  margin: 0 0 var(--space-4);
}

.hero-traits {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5em;
  list-style: none;
  margin: 0;
  padding: 0;
}

.hero-traits li {
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--text-subtle);
  padding: 0;
  line-height: 1.4;
}

.hero-traits li:not(:last-child)::after {
  content: "\00b7";
  margin-left: 0.9em;
  color: var(--text-subtle);
}

.hero-actions {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* Flex rather than a fr-based grid: fr columns stretch to fill the
   container's full width even though neither the text nor the sketch is
   that wide, which was leaving a huge dead-air gap between them on wide
   viewports. Sizing each item to its content and centering the pair as a
   group keeps them visually paired at any width, with a fluid gap that
   scales down on small screens and up on large ones instead of one fixed
   value.
   flex-wrap is intentionally NOT set here: wrapping decisions in the flex
   spec are based on items' unshrunk flex-basis, not their post-shrink
   size, so "wrap" would drop to a stacked layout well before the two
   items actually ran out of room to shrink into. The row/column switch is
   handled explicitly by the media query below instead. */
.hero-grid {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: center;
  gap: clamp(var(--space-4), 6vw, var(--space-6));
}

.hero-content {
  /* flex-grow: 0 — content-sized, not stretched to fill the row, so it
     doesn't push .hero-me away from it (that was the old fr-grid problem). */
  flex: 0 1 420px;
  max-width: 480px;
}

/* Retired along with the flower markup in index.html — see the comment there.
.hero-flowers {
  color: var(--illustration);
  width: 100%;
  max-width: 320px;
  margin: 0 auto;
}

.hero-flower-variant {
  opacity: 0;
}

.hero-flower-variant.is-active {
  opacity: 1;
}

@media (max-width: 800px) {
  .hero-flowers {
    max-width: 220px;
    margin-top: var(--space-3);
  }
}
*/

/* ---------- Hero: waving sketch ---------- */

.hero-me {
  --fill: var(
    --bg
  ); /* dress fill — hides the lines behind it without becoming a white blob */
  color: var(--illustration);
  width: 100%;
  max-width: 320px;
  flex: 0 1 280px;
  /* No auto margin: as a flex item, .hero-grid's justify-content: center
     already centers the text+sketch pair as a group. An auto margin here
     would instead center .hero-me alone within its own leftover flex
     space, prying it away from .hero-content. align-items: center on the
     parent still centers it when the layout stacks on narrow screens. */
}

.hero-me-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.hero-me-svg .occlude {
  fill: var(--fill);
}

.hero-me-svg g[class] {
  transform-box: view-box;
}

/* whole figure: slow weight shift, pivot at the feet */
.hero-me-fig {
  transform-origin: 140px 326px;
  animation: heroMeSway 7s ease-in-out infinite;
}

/* head: gentle tilt, pivot at the neck — runs on its own cycle so it never
   lines up with the arm and reads as one repeating loop */
.hero-me-head {
  transform-origin: 140px 132px;
  animation: heroMeHeadSway 5.4s ease-in-out infinite;
}

/* raised arm: waves, lowers to her side, holds, raises again */
.hero-me-arm {
  transform-origin: 101px 150px;
  animation: heroMeArmCycle 9s linear infinite;
}

/* hand: flicks at the wrist, phase-matched to the arm cycle */
.hero-me-hand {
  transform-origin: 32px 97px;
  animation: heroMeHandCycle 9s linear infinite;
}

@keyframes heroMeSway {
  0% {
    transform: rotate(-0.9deg);
  }
  50% {
    transform: rotate(0.9deg);
  }
  100% {
    transform: rotate(-0.9deg);
  }
}

@keyframes heroMeHeadSway {
  0% {
    transform: rotate(-2.6deg) translateY(0);
  }
  50% {
    transform: rotate(2.3deg) translateY(-1.5px);
  }
  100% {
    transform: rotate(-2.6deg) translateY(0);
  }
}

/* shoulder angle: 0deg = raised as drawn, -104deg = hanging at her side */
@keyframes heroMeArmCycle {
  0% {
    transform: rotate(0deg);
  }
  3% {
    transform: rotate(-2deg);
  }
  6% {
    transform: rotate(3deg);
  }
  10% {
    transform: rotate(-2deg);
  }
  14% {
    transform: rotate(3deg);
  }
  18% {
    transform: rotate(-2deg);
  }
  22% {
    transform: rotate(2deg);
  }
  26% {
    transform: rotate(0deg);
  }
  28% {
    transform: rotate(3deg); /* tiny lift before dropping */
  }
  36% {
    transform: rotate(-100deg);
  }
  39% {
    transform: rotate(-106.5deg); /* overshoot */
  }
  42% {
    transform: rotate(-104deg); /* settle by her side */
  }
  50% {
    transform: rotate(-102.5deg); /* idle micro-swing */
  }
  58% {
    transform: rotate(-104.5deg);
  }
  66% {
    transform: rotate(-102.5deg);
  }
  70% {
    transform: rotate(-104deg);
  }
  78% {
    transform: rotate(-6deg); /* back up */
  }
  81% {
    transform: rotate(2.5deg);
  }
  85% {
    transform: rotate(-1deg);
  }
  89% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

/* wrist angle, phase-matched to heroMeArmCycle */
@keyframes heroMeHandCycle {
  0% {
    transform: rotate(0deg);
  }
  3% {
    transform: rotate(22deg);
  }
  6% {
    transform: rotate(-20deg);
  }
  10% {
    transform: rotate(22deg);
  }
  14% {
    transform: rotate(-20deg);
  }
  18% {
    transform: rotate(22deg);
  }
  22% {
    transform: rotate(-14deg);
  }
  26% {
    transform: rotate(4deg);
  }
  30% {
    transform: rotate(0deg);
  }
  36% {
    transform: rotate(-9deg); /* hand trails as the arm drops */
  }
  42% {
    transform: rotate(6deg);
  }
  46% {
    transform: rotate(0deg);
  }
  50% {
    transform: rotate(2deg);
  }
  58% {
    transform: rotate(-2deg);
  }
  66% {
    transform: rotate(2deg);
  }
  70% {
    transform: rotate(0deg);
  }
  74% {
    transform: rotate(11deg); /* trails on the way up */
  }
  78% {
    transform: rotate(-9deg);
  }
  82% {
    transform: rotate(6deg);
  }
  86% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-me-fig,
  .hero-me-head,
  .hero-me-arm,
  .hero-me-hand {
    animation: none !important;
  }
}

/* Tablet: text and sketch stay side by side (just tighter) — only phone
   widths below this stack them. */
@media (max-width: 640px) {
  .hero-grid {
    flex-direction: column;
    /* Tighter than the row gap, and stacking's only job now — .hero-me no
       longer adds its own margin-top on top of this (see below), so this
       single value is the whole gap between text and sketch. */
    gap: var(--space-3);
  }

  .hero-content {
    /* flex-direction is column here, so the main axis is vertical — a
       420px flex-basis (meant as a row width) would otherwise force the
       text block to be 420px *tall*, blowing the gap to .hero-me open. */
    flex-basis: auto;
    max-width: none;
  }

  .hero-me {
    max-width: 220px;
  }
}

/* ---------- Section scaffolding ---------- */

section {
  padding: var(--space-1) 0;
}

/* .wrap's own padding rule (padding: 0 var(--space-3)) has equal specificity
   and would otherwise cancel the vertical padding above, so #work/#about
   need to set top/bottom explicitly. */
#work,
#about {
  padding-top: var(--space-4);
}

.section-header {
  margin-bottom: var(--space-1);
  max-width: 60ch;
}

.section-header h2 {
  font-size: clamp(2rem, 4vw, 2.75rem);
  margin: 0;
}

/* ---------- About ---------- */

.about-layout {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: space-between;
  gap: clamp(var(--space-4), 6vw, var(--space-6));
}

.about-bio {
  flex: 1 1 480px;
  max-width: 68ch;
}

.about-bio p {
  color: var(--text-muted);
  font-size: 1.05rem;
}

.highlight {
  background: var(--highlight);
  color: var(--text);
  padding: 0.03em 0.2em;
  border-radius: 4px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

/* ---------- About: surfing sketch ---------- */
/* Same animated-line-drawing approach as .hero-me — see that section for
   the pattern this mirrors (transform-box: view-box + per-group pivots). */

.about-surf {
  color: var(--illustration);
  width: 100%;
  max-width: 260px;
  flex: 0 0 240px;
}

.about-surf-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.about-surf-svg g[class] {
  transform-box: view-box;
}

/* whole figure + board: gentle rise and fall over the wave, pivot at the
   board's center so the rock reads as riding, not floating */
.about-surf-fig {
  transform-origin: 150px 320px;
  animation: surfRock 3.6s ease-in-out infinite;
}

/* head: small independent tilt, phase-offset so it never lines up 1:1
   with the body rock */
.about-surf-head {
  transform-origin: 145px 168px;
  animation: surfHeadTilt 3.6s ease-in-out infinite;
  animation-delay: -0.4s;
}

/* paddling arm: light trailing swing, pivot at the shoulder */
.about-surf-arm {
  transform-origin: 186px 148px;
  animation: surfArmPaddle 3.6s ease-in-out infinite;
  animation-delay: -0.9s;
}

/* wave crest: slow horizontal flow with a touch of swell */
.about-surf-wave {
  transform-origin: 330px 260px;
  animation: surfWaveFlow 4.2s ease-in-out infinite;
}

/* sea spray: quick upward flicks, staggered off the wave cycle */
.about-surf-spray {
  transform-origin: 300px 258px;
  animation: surfSpray 2.4s ease-in-out infinite;
}

@keyframes surfRock {
  0%,
  100% {
    transform: rotate(-1.8deg) translateY(0);
  }
  50% {
    transform: rotate(1.8deg) translateY(-4px);
  }
}

@keyframes surfHeadTilt {
  0%,
  100% {
    transform: rotate(-2.2deg);
  }
  50% {
    transform: rotate(1.6deg);
  }
}

@keyframes surfArmPaddle {
  0%,
  100% {
    transform: rotate(-2deg);
  }
  50% {
    transform: rotate(3deg);
  }
}

@keyframes surfWaveFlow {
  0%,
  100% {
    transform: translateX(0) scaleY(1);
  }
  50% {
    transform: translateX(4px) scaleY(1.03);
  }
}

@keyframes surfSpray {
  0%,
  100% {
    transform: translateY(0);
    opacity: 0.85;
  }
  50% {
    transform: translateY(-5px);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .about-surf-fig,
  .about-surf-head,
  .about-surf-arm,
  .about-surf-wave,
  .about-surf-spray {
    animation: none !important;
  }
}

@media (max-width: 640px) {
  .about-layout {
    flex-direction: column;
    gap: var(--space-3);
  }

  .about-bio {
    flex-basis: auto;
  }

  .about-surf {
    max-width: 190px;
  }
}

/* ---------- Work list ---------- */

.work-list {
  display: flex;
  flex-direction: column;
}

.work-row {
  display: grid;
  grid-template-columns: minmax(160px, 240px) 1fr;
  gap: var(--space-4);
  padding: var(--space-4) 0;
  text-decoration: none;
  color: inherit;
}

.work-row:not(:first-child) {
  border-top: 1px dashed color-mix(in srgb, var(--text) 15%, transparent);
}

.work-row-title {
  font-size: 1.3rem;
  margin: 0;
  transition: color 0.25s var(--ease);
}

.work-row-content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  max-width: 640px;
}

.work-row-media {
  width: 100%;
  overflow: hidden;
}

.work-row-media img {
  transition: transform 0.5s var(--ease);
}

.work-row:hover .work-row-media img {
  transform: scale(1.03);
}

.project-tags {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}

.tag {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
  color: var(--text-subtle);
}

.tag:not(:last-child)::after {
  content: "\00b7";
  margin-left: 0.5em;
  color: var(--text-subtle);
}

/* Skills-used variant: same layout/spacing/dot-separator as .tag, but reads
   as a normal-case list of phrases rather than short uppercase category
   chips. Case-study "Skills used" entries are prose-length ("Design system
   creation & management"), and running that through .tag's uppercase +
   letter-spacing treatment reads as a wall of caps instead of scannable
   chips — this keeps the mechanic, drops the chip typography. */
.tag--skill {
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
  font-size: 0.95rem;
  color: var(--text-muted);
}

.work-row-content p {
  color: var(--text-muted);
  font-size: 0.98rem;
  margin: 0;
}

.work-row-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text);
}

.work-row-link .arrow {
  transition: transform 0.25s var(--ease);
}

.work-row:hover .work-row-link .arrow {
  transform: translateX(4px);
}

.work-row-status {
  font-size: 0.9rem;
  font-style: italic;
  color: var(--text-muted);
}

@media (max-width: 700px) {
  .work-row {
    grid-template-columns: 1fr;
    gap: var(--space-2);
  }
}

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

.site-footer {
  /* padding-top/bottom only (not the shorthand) so this doesn't clobber
     .wrap's left/right padding — same specificity, later in the cascade,
     and a shorthand here would reset the sides to 0. See the .hero
     comment above for the same pitfall. */
  padding-top: var(--space-4);
  padding-bottom: var(--space-5);
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 0.85rem;
  display: flex;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.footer-links {
  display: flex;
  gap: var(--space-3);
  list-style: none;
  padding: 0;
  margin: 0;
}

.footer-links a {
  text-decoration: none;
  color: var(--text-muted);
  font-size: 0.85rem;
  transition: color 0.2s var(--ease);
}

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

/* ---------- Case study page ---------- */

.case-hero {
  /* padding-top/bottom only — see the same note on .hero above */
  padding-top: var(--space-6);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--border);
}

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  text-decoration: none;
  color: var(--text-muted);
  font-size: 0.9rem;
  margin-bottom: var(--space-3);
  transition:
    color 0.2s var(--ease),
    gap 0.2s var(--ease);
}

.back-link:hover {
  color: var(--text);
  gap: 0.65em;
}

.case-hero h1 {
  font-size: clamp(2rem, 4.5vw, 3.2rem);
  letter-spacing: -0.02em;
  margin: 0 0 var(--space-2);
}

.case-hero .subtitle {
  font-size: 1.1rem;
  color: var(--text-muted);
  max-width: 60ch;
  margin: 0 0 var(--space-4);
}

/* Compact byline (when · context · tools) — replaces what used to be its own
   WHEN/WHERE/HOW grid. That grid sat directly on top of the At a Glance card
   below it, and two "row of three labeled things" components stacked back
   to back read as one duplicated pattern rather than two different kinds of
   content. This keeps the same info as a single muted caption instead,
   reusing the dot-separator already used by .tag and .hero-traits. */
.case-meta {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  margin: 0 0 var(--space-4);
  padding: 0;
  font-size: 0.9rem;
  color: var(--text-subtle);
}

.case-meta li:not(:last-child)::after {
  content: "\00b7";
  margin: 0 0.6em;
}

.case-image {
  width: 100%;
  margin: var(--space-4) 0;
  color: var(--text-muted);
}

.case-image img {
  width: 100%;
  height: auto;
  display: block;
}

.case-body {
  max-width: 72ch;
}

.case-body h2 {
  font-size: 1.5rem;
  margin: var(--space-5) 0 var(--space-2);
}

/* Same typography as .tag (reused, not a new pattern) — the italic display
   font + accent color read as a headline here, which is too decorative for
   a small subsection label like "Ordering" / "Cart" / "Profile". */
.case-body h3 {
  font-family: var(--font-body);
  font-style: normal;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-subtle);
  margin: var(--space-4) 0 0.5em;
}

.case-body p {
  color: var(--text-muted);
  font-size: 1.05rem;
}

.case-body ul {
  color: var(--text-muted);
  font-size: 1.05rem;
  margin: 0.6em 0;
  padding-left: 1.2em;
}

.case-body li {
  margin: 0.3em 0;
}

.case-body li strong,
.case-body p strong {
  color: var(--text);
}

/* ---------- At-a-glance summary (scannable case study TL;DR) ---------- */

.at-a-glance {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-3) var(--space-4);
  margin-top: var(--space-4);
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent) 7%, var(--bg-elevated));
}

.at-a-glance-item .label {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-subtle);
  font-weight: 600;
  margin: 0 0 0.35em;
}

.at-a-glance-item p {
  margin: 0;
  font-size: 0.98rem;
  color: var(--text);
}

.image-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--space-2);
  max-width: none;
  margin: var(--space-3) 0;
}

/* A framed screenshot that keeps its natural aspect ratio (no forced crop) —
   used for tall/portrait screenshots where .case-image's 16:9 crop would cut
   off content. */
.shot img {
  width: 100%;
  display: block;
}

.shot-caption {
  text-align: center;
  color: var(--text-muted);
  font-size: 0.85rem;
  margin: 0 0 var(--space-1);
}

/* Confidentiality note on case studies without shareable visuals */
.confidential-note {
  font-style: italic;
  color: var(--text-muted);
}

.case-nav {
  display: flex;
  justify-content: space-between;
  padding: var(--space-4) 0;
  border-top: 1px solid var(--border);
  margin-top: var(--space-5);
}

/* ---------- Scroll reveal ---------- */

.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity 0.7s var(--ease),
    transform 0.7s var(--ease);
}

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

.reveal-stagger > * {
  transition-delay: calc(var(--stagger-index, 0) * 60ms);
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
