/* ==========================================================================
   /work — THE PORTFOLIO PAGE

   Standalone stylesheet. It borrows the landing page's tokens (redeclared
   here, not imported — this page must not pull in style.css, which is built
   entirely around a pinned GSAP scene that doesn't exist here), and nothing
   else. If a token changes in css/style.css, change it here too.

   THE IDEA
   This is the working document behind the desert: a contact sheet, not a
   second experience. Display type for names, monospace for the facts
   (client · role · year). That one type pairing is what makes the page read
   as authored rather than templated — and it earns the word "receipts"
   without ever printing it.

   LAYOUT
   A real grid: one case study (full-width, `grid-column: 1/-1`), then a
   row of 3 uniform gallery cards, repeating — see interleaveCaseStudies()
   in work.js. Gallery cards are all the same 3:4 frame (object-fit:cover),
   traded up from an earlier natural-aspect-ratio masonry: a uniform grid
   reads faster for someone skimming a stack of portfolios, which is this
   page's whole job. No click-to-expand anywhere — gallery cards use a
   cursor look-around (scale + shift toward the pointer) instead, plus a
   next-image arrow for rows with a second photo.
   ========================================================================== */

:root {
  --ink:        #0d0d0c;
  --ink-raised: #161613;
  --cream:      #f1ece1;
  --cream-dim:  #a8a297;
  --gold:       #f6ba02;
  --line:       rgba(241, 236, 225, 0.14);
  --line-soft:  rgba(241, 236, 225, 0.07);

  --font-display: 'Bricolage Grotesque', sans-serif;
  --font-body:    'Plus Jakarta Sans', sans-serif;
  /* Same font as --font-body, different name — matches css/style.css's
     token split, kept in sync here so "the eyebrow font" means the same
     thing on both pages: font-nav, 12px, 0.12em tracking, uppercase. */
  --font-nav:     'Plus Jakarta Sans', sans-serif;
  /* System stack on purpose: the metadata voice costs zero network. */
  --font-mono:    ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  --gutter: clamp(20px, 5vw, 64px);
  --radius: 14px;
  --maxw: 1560px;
  /* .nav-right sits at top:18px and its tallest child (.nav-menu-trigger)
     is 40px, so its bottom edge lands at 58px — this needs to be 18px
     past that (76px) for the .is-scrolled background band to give it the
     same breathing room below as it has above, not crowd the bottom
     edge. See the 68px mobile override for the same math at top:14px. */
  --nav-h: 76px;
}

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

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
body.is-locked { overflow: hidden; }

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

::selection { background: var(--gold); color: var(--ink); }

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

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

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--gold); color: var(--ink); padding: 10px 16px;
  font-family: var(--font-mono); font-size: 12px; text-decoration: none;
}
.skip-link:focus { left: 8px; top: 8px; }

/* ---------- Nav -----------------------------------------------------------
   Same component as the landing page's .site-nav (css/style.css) —
   duplicated here rather than shared, same reasoning as the sheet-fetch
   helpers in js/work.js: this page stays dependency-free of main.js. Any
   change to the shared nav look/behavior needs both copies updated. */

/* Transparent over the hero strip photo at the very top; turns solid ink
   once that image has scrolled past (.is-scrolled, toggled by
   wireStripNavBg() in work.js) so the nav text isn't fighting whatever
   content is now underneath it. */
.site-nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: var(--nav-h);
  z-index: 100;
  pointer-events: none;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color 0.3s ease, border-color 0.3s ease;
}
.site-nav.is-scrolled {
  background: var(--ink);
  border-bottom-color: var(--line);
}

.nav-right {
  position: fixed;
  top: 18px;
  right: var(--gutter);
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 16px;
  pointer-events: auto;
}

.nav-contact-trigger {
  appearance: none;
  background: none;
  border: none;
  border-bottom: 1px solid transparent;
  padding: 0;
  padding-bottom: 4px;
  margin: 0;
  font: inherit;
  cursor: pointer;
}
.nav-callout-link.nav-contact-trigger { border-bottom-color: var(--gold); padding-bottom: 0; }

/* ---------- Contact dropdown (same markup/behavior as index.html) --------- */
.contact-dropdown {
  position: fixed;
  top: calc(var(--nav-h) + 10px);
  right: var(--gutter);
  z-index: 105;
  width: min(340px, calc(100vw - 2 * var(--gutter)));
  background: var(--ink-raised);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.6);
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
  max-height: calc(100dvh - var(--nav-h) - 24px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.contact-dropdown.is-open { opacity: 1; transform: translateY(0); pointer-events: auto; }
.contact-dropdown-inner { position: relative; padding: 20px; display: flex; flex-direction: column; gap: 14px; }

.contact-close {
  position: absolute;
  top: 10px; right: 10px;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border: none; background: transparent;
  color: var(--cream-dim);
  font-size: 20px; line-height: 1;
  cursor: pointer;
  transition: color 0.2s ease;
}
.contact-close:hover { color: var(--gold); }

.nav-contact-trigger.is-active { color: var(--gold); }
.nav-callout-link.nav-contact-trigger.is-active { border-bottom-color: var(--gold); }

.contact-book {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 16px;
  border-radius: 12px;
  background: var(--gold);
  color: var(--ink);
  position: relative;
  transition: transform 0.2s ease, filter 0.2s ease;
}
.contact-book:hover { filter: brightness(1.08); transform: translateY(-1px); }
.contact-book-label { font-family: var(--font-display); font-weight: 700; font-size: 15px; }
.contact-book-sub { font-size: 11.5px; opacity: 0.75; line-height: 1.4; }
.contact-book-arrow { position: absolute; right: 16px; top: 50%; transform: translateY(-50%); font-size: 16px; }
.contact-book.is-unset { display: none; }

.contact-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--cream-dim);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.contact-divider::before, .contact-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--line);
}

.contact-form { display: flex; flex-direction: column; gap: 8px; }
.contact-input {
  width: 100%;
  background: rgba(241, 236, 225, 0.06);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 10px 12px;
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 13px;
}
.contact-input::placeholder { color: var(--cream-dim); }
.contact-input:focus { outline: none; border-color: var(--gold); }

.contact-send {
  align-self: flex-start;
  background: transparent;
  border: 1px solid var(--gold);
  color: var(--gold);
  border-radius: 9px;
  padding: 8px 18px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease;
}
.contact-send:hover { background: var(--gold); color: var(--ink); }
.contact-send:disabled { opacity: 0.5; cursor: default; }

.contact-status { margin: 0; font-size: 11.5px; color: var(--cream-dim); }
.contact-status.is-success { color: var(--gold); }
.contact-status.is-error { color: #e0836a; }

.contact-email-fallback {
  font-size: 11.5px;
  color: var(--cream-dim);
  text-align: center;
  border-top: 1px solid var(--line);
  padding-top: 12px;
  transition: color 0.2s ease;
}
.contact-email-fallback:hover { color: var(--gold); }

@media (max-width: 700px) {
  .contact-dropdown { right: var(--gutter); left: var(--gutter); width: auto; }
}

/* ---------- Circle trigger, logo, dropdown panel, back-to-desert link ---- */
.nav-menu-trigger {
  display: flex;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: rgba(13, 13, 12, 0.4);
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 5px;
  cursor: pointer;
  flex: 0 0 auto;
  transition: background 0.3s ease;
}
.nav-menu-trigger:hover { background: rgba(13, 13, 12, 0.7); }
.nav-menu-trigger-bar {
  display: block;
  width: 16px;
  height: 1px;
  background: var(--cream);
  transition: transform 0.3s ease, opacity 0.3s ease, background 0.3s ease;
}
.site-nav.is-menu-open .nav-menu-trigger-bar:first-child { transform: translateY(3px) rotate(45deg); }
.site-nav.is-menu-open .nav-menu-trigger-bar:last-child { transform: translateY(-3px) rotate(-45deg); }

.nav-callout {
  /* The eyebrow font (--font-nav), not the header/mono voice — was
     font-mono. */
  font-family: var(--font-nav);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.6;
  color: var(--cream); /* solid white always, matching the landing page */
  white-space: nowrap;
  text-align: right;
  margin: 0;
}
.nav-callout-link {
  /* Header/mono voice, distinct from .nav-callout's eyebrow font above
     it — two fonts, deliberately. */
  display: inline-block;
  font-family: var(--font-mono);
  color: var(--cream);
  border-bottom: 1px solid var(--gold);
  text-transform: none;
  letter-spacing: 0.02em;
}
.nav-callout-link:hover { color: var(--gold); }

.nav-mark { display: block; }
.nav-logo-img { height: 30px; width: auto; display: block; }

.nav-menu-panel {
  position: fixed;
  top: 70px;
  right: var(--gutter);
  z-index: 101;
  width: max-content;
  max-width: calc(100vw - 2 * var(--gutter));
  padding: 12px 16px;
  background: var(--ink-raised);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.6);
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.site-nav.is-menu-open .nav-menu-panel {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* One row: Work/About grouped left, Contact centered (its own grid
   column stays centered regardless of how wide the left group or "Get
   lost" on the right are), "Get lost" right. */
.nav-links {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 18px;
}
.nav-links-left { display: flex; align-items: center; gap: 18px; justify-self: start; }

/* Plain text, no native/underline decoration — just a gray line sitting
   under it, not hugging the letters like a default link underline. The
   clean eyebrow font (--font-nav), not the header/mono voice. Turns gold
   (text AND the line under it) on hover/click. */
.nav-link {
  font-family: var(--font-nav);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--cream); /* solid white, matching the rest of the header */
  padding: 8px 2px;
  border-bottom: 1px solid rgba(168, 162, 151, 0.45); /* true gray, not a faint white */
  transition: color 0.2s ease, border-color 0.2s ease;
}
.nav-link:hover, .nav-link.is-active { color: var(--gold); border-color: var(--gold); }

/* Contact — centered in the row, same plain-text/gray-line treatment as
   Work/About (no more pill — that moved to "Get lost"), just with the
   plus-circle icon (matching "A closer look", .tile__more-plus) after
   the word. The icon stays gold always and rotates into an "x" while
   the dropdown is open. */
.nav-contact-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  justify-self: center;
}
.nav-contact-plus {
  display: grid;
  place-items: center;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--gold);
  color: var(--ink);
  font-size: 13px;
  line-height: 1;
  font-weight: 700;
  transition: transform 0.3s cubic-bezier(0.2, 0.7, 0.3, 1);
}
.nav-contact-btn.is-active .nav-contact-plus { transform: rotate(45deg); }

/* "Get lost" — the pill treatment Contact used to carry: gray stroke,
   white text at rest, fills solid gold on hover. Its own grid column on
   the right marks it as the one exit in a row of sections. */
.nav-link--cta {
  justify-self: end;
  display: inline-flex;
  align-items: center;
  border: 1px solid rgba(168, 162, 151, 0.45);
  border-radius: 999px;
  padding: 9px 15px;
  color: var(--cream);
  background: transparent;
}
.nav-link--cta:hover {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--ink);
}

/* Top-left, where the old "Sheri Cola" wordmark brand used to sit — the
   real logo lives top-right now (with everything else, matching the
   landing page), so this spot becomes the one thing that's actually
   different between the two pages: a way back. Solid gold, same as
   .btn--solid ("Book a call"), with an occasional glow pulse layered on
   top (cta-pulse-glow, defined below) so it isn't fully static. */
.nav-home-link {
  position: fixed;
  top: 18px;
  left: var(--gutter);
  z-index: 101; /* above .site-nav's own background fill (.is-scrolled) */
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 20px;
  border-radius: 999px;
  border: 1.5px solid var(--gold);
  background: var(--gold);
  color: var(--ink);
  /* Same font as "A closer look" (.tile__more) — was font-nav. */
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  animation: cta-pulse-glow 5s ease-in-out infinite;
  transition: transform 0.25s ease, box-shadow 0.25s ease, background 0.25s ease, color 0.25s ease;
}
.nav-home-link:hover {
  background: var(--cream);
  border-color: var(--cream);
  color: var(--ink);
  transform: translateY(-2px);
}

@keyframes cta-pulse-glow {
  0%, 85%, 100% { box-shadow: 0 0 0 0 rgba(246, 186, 2, 0); }
  92% { box-shadow: 0 0 20px 2px rgba(246, 186, 2, 0.5); }
}

@media (max-width: 600px) {
  :root { --nav-h: 68px; } /* nav-right top:14px + 40px circle + matching 14px below */
  .nav-logo-img { height: 24px; }
  .nav-right { top: 14px; gap: 12px; }
  .nav-home-link { top: 14px; font-size: 10.5px; padding: 8px 16px; }
  .nav-menu-panel { top: 62px; width: min(78vw, 240px); }
  .nav-links { grid-template-columns: 1fr; justify-items: center; gap: 10px; }
  .nav-links-left { flex-direction: column; align-items: center; justify-self: center; }
  .nav-contact-btn, .nav-link--cta { justify-self: center; }
}

/* ---------- Header strip + masthead --------------------------------------- */

.strip {
  /* No negative margin anymore — the nav is position:fixed (floating,
     like the landing page's), not sticky/in-flow, so it never reserves
     doc space to pull the strip back up under. */
  position: relative;
  height: clamp(165px, 21vw, 280px);
  overflow: hidden;
}
.strip picture { display: block; width: 100%; height: 100%; }
.strip img { width: 100%; height: 100%; object-fit: cover; object-position: center 62%; }
/* Fades the sunset into the page ground so the masthead below starts on ink
   rather than butting against a hard photographic edge. */
.strip::after {
  content: ''; position: absolute; inset: 0;
  background:
    linear-gradient(to bottom, rgba(13,13,12,.55) 0%, rgba(13,13,12,0) 26%, rgba(13,13,12,.72) 74%, var(--ink) 100%);
}

.masthead { padding-block: clamp(24px, 3.6vw, 42px) clamp(20px, 3vw, 34px); }
/* The one "eyebrow" style, shared with the landing page's own (.hero-
   eyebrow/.deck-eyebrow/.about-eyebrow in css/style.css) — font-nav,
   12px, 0.12em tracking, uppercase. Every small label-over-a-heading on
   either page reads as the same system now. */
.masthead__eyebrow {
  font-family: var(--font-nav); font-size: 12px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--gold); margin: 0 0 clamp(14px, 2.4vw, 22px);
}
.masthead__eyebrow b { font-weight: 500; color: var(--gold); }
.masthead__eyebrow i { font-style: normal; color: var(--cream-dim); margin-inline: 8px; }

.masthead h1 {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(27px, 4.1vw, 46px); line-height: 1.06; letter-spacing: -.026em;
  margin: 0; max-width: 24ch; text-wrap: balance;
}

.masthead__band {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 14px clamp(20px, 3vw, 40px);
  margin-top: clamp(16px, 2.6vw, 26px);
}

.masthead__clients {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0;
  margin: 0;
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--cream-dim);
}
.masthead__clients i { font-style: normal; color: var(--gold); margin-inline: 10px; opacity: .8; }

.masthead__actions { display: flex; flex-wrap: wrap; gap: 10px; margin: 0; }

.btn {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 11px 18px; border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent; color: var(--cream);
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .06em;
  text-decoration: none; cursor: pointer;
  transition: border-color .22s ease, background .22s ease, color .22s ease, transform .22s ease;
}
.btn:hover { border-color: var(--gold); color: var(--gold); transform: translateY(-1px); }
.btn--solid { background: var(--gold); border-color: var(--gold); color: var(--ink); font-weight: 600; }
.btn--solid:hover { background: var(--cream); border-color: var(--cream); color: var(--ink); }

/* Copy email — gold outline at rest (not solid), fills solid gold on
   hover and on the "copied!" confirmation click. */
.btn--outline-gold { border-color: var(--gold); color: var(--gold); }
.btn--outline-gold:hover,
.btn--outline-gold.is-copied { background: var(--gold); border-color: var(--gold); color: var(--ink); }

/* WHAT I DO. Four flat statements, no counts and nothing clickable.
   Deliberately not filters: 18 projects split four ways leaves buckets of
   3-6, and a filter invites the reader to open each one and find it thin.
   Read straight across, the same four categories read as range. */
.services {
  list-style: none; margin: clamp(24px, 3.6vw, 38px) 0 0; padding: 0;
  display: grid; gap: clamp(14px, 2vw, 26px);
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: 1px solid var(--line-soft); padding-top: clamp(18px, 2.4vw, 26px);
}
.services__eyebrow { display: none; }
.services-panel { display: contents; }
@media (max-width: 900px) { .services { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) {
  .services { gap: 17px; }
}

.services h2 {
  margin: 0 0 5px;
  font-family: var(--font-display); font-weight: 600; font-style: italic;
  font-size: clamp(14px, 1.35vw, 16px); letter-spacing: -.01em; color: var(--gold);
}
.services p {
  margin: 0; font-size: 13px; line-height: 1.5; color: var(--cream-dim); max-width: 34ch;
}

/* The Work introduction becomes a single editorial column on phones only.
   Desktop and tablet retain their existing strip, spacing, and band layout. */
@media (max-width: 699px) {
  .strip { height: auto; aspect-ratio: 1 / 1; }
  .strip img { object-position: center center; }

  .masthead { display: flex; flex-direction: column; }
  .masthead__eyebrow { order: 1; }
  .masthead h1 { order: 2; max-width: none; }
  .masthead__band { display: contents; }
  .masthead__clients { order: 3; margin-top: 18px; }
  .masthead__actions { order: 4; margin-top: 28px; }
  .services-panel {
    display: block;
    order: 5;
    margin-top: 42px;
    padding: 36px 0 42px;
    border-top: 1px solid rgba(168, 162, 151, .25);
    background: #12110f;
    box-shadow: 0 0 0 100vmax #12110f;
    clip-path: inset(0 -100vmax);
  }
  .services__eyebrow {
    display: block;
    margin: 0;
    font-family: var(--font-nav);
    font-size: 12px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--gold);
  }
  .services {
    grid-template-columns: 1fr;
    margin-top: 18px;
    padding-top: 0;
    border-top: 0;
  }
  .services h2 { font-size: 18px; }
  .services p { font-size: 15.5px; }
  .services h2::before {
    content: '\2192';
    display: inline-block;
    margin-right: .55em;
    color: var(--cream-dim);
    font-family: var(--font-mono);
    font-size: .62em;
    font-style: normal;
    transform: translateY(-.08em);
  }
  .masthead { padding-bottom: 0; }

  /* Mobile chapter breaks: generous space, a quiet rule, and the existing
     eyebrow language separate the content without turning sections into
     heavy cards. */
  .work.shell {
    padding-top: 18px;
    padding-bottom: 74px;
    background: linear-gradient(to bottom, #12110f 0 18px, var(--ink) 18px);
  }
  .work .factbar { padding-top: 18px; margin-bottom: 28px; border-top-color: rgba(168, 162, 151, .25); }
  .work .factbar__label { color: var(--gold); }

  .section.about {
    padding-top: 62px;
    padding-bottom: 68px;
    border-top-color: rgba(168, 162, 151, .25);
    background: #12110f;
    box-shadow: 0 0 0 100vmax #12110f;
    clip-path: inset(0 -100vmax);
  }
}

/* The facts rule: how much work is on this page, and over what years. */
.factbar {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  padding: 14px 0; border-top: 1px solid var(--line);
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--cream-dim);
}
.factbar__label { color: var(--cream); }

/* ---------- The grid ------------------------------------------------------ */

.work { padding-bottom: clamp(40px, 7vw, 90px); }

/* A real grid, not masonry: one case study, full-width, then a row of
   3 uniform gallery cards, repeating — see interleaveCaseStudies() in
   work.js, which builds the rows in exactly that order. A case tile's
   grid-column:1/-1 (below) forces a fresh row after it regardless of
   the current column count, so the "1 case, then 3" grouping holds at
   every breakpoint even where there are only 1 or 2 gallery columns to
   show it in. */
/* 3 columns at every width down to mobile — deliberately NOT stepping
   down to 2 at tablet widths first (that used to put a caption directly
   above the next row's image with barely more room than the caption has
   from its OWN image, which read as ambiguous — "whose text is this?").
   Row gap is now clearly bigger than column gap for the same reason: the
   vertical distance from a caption to the next row down has to read as
   obviously more than the distance from a caption up to its own image. */
.grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: clamp(14px, 1.8vw, 26px);
  row-gap: clamp(36px, 5vw, 64px);
}
@media (max-width: 700px) { .grid { grid-template-columns: 1fr; row-gap: clamp(30px, 8vw, 46px); } }

.tile {
  opacity: 0; transform: translateY(14px);
  transition: opacity .6s ease, transform .6s cubic-bezier(.2,.7,.3,1);
}
.tile.is-in { opacity: 1; transform: none; }

/* Case studies break the grid and lay out as an editorial split — image
   on one side, the facts on the other, spanning every column so the next
   3 gallery tiles always start a clean new row after it. A raised,
   bordered "card" background wraps the whole split so the image and its
   text read as one embossed unit — distinct from the plain gallery
   tiles, which have no container of their own beyond .tile__frame. */
.tile--case {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: minmax(0, 1.32fr) minmax(0, 1fr);
  gap: clamp(18px, 2.6vw, 40px);
  align-items: center;
  padding: clamp(18px, 2.6vw, 34px);
  border-radius: var(--radius);
  background: linear-gradient(135deg, rgba(246, 186, 2, 0.06), rgba(22, 22, 19, 0.5) 55%, rgba(22, 22, 19, 0.65));
  border: 1px solid var(--line-soft);
  box-shadow: 0 30px 60px -35px rgba(0, 0, 0, 0.55);
}
.tile--case .cs-expand { grid-column: 1 / -1; }
@media (max-width: 860px) {
  .tile--case { grid-template-columns: 1fr; gap: 0; padding: clamp(14px, 4vw, 22px); }
}

.tile__frame {
  position: relative; overflow: hidden; border-radius: var(--radius);
  background: var(--ink-raised);
  border: 1px solid var(--line-soft);
}
/* Every gallery card is the same 3:4 frame regardless of the source
   image's own proportions — object-fit:cover crops to it. Deliberate
   departure from "nothing gets cropped": a uniform grid reads faster for
   someone skimming a stack of portfolios than natural-ratio masonry does,
   which was the whole point of building this page. */
.tile--gallery .tile__frame { aspect-ratio: 3 / 4; }
.tile--gallery .tile__media { width: 100%; height: 100%; object-fit: cover; }

.tile__frame--wide { aspect-ratio: 16 / 10; }
@media (max-width: 860px) { .tile__frame--wide { aspect-ratio: 16 / 9; } }

.tile__media { width: 100%; height: auto; }
.tile__frame--wide .tile__media { height: 100%; object-fit: cover; }

/* The second image is swapped in by the next-image arrow (see .tile__next
   below and wireTiles() in work.js), not by hover — hover instead drives
   the cursor look-around (LOOK_MAX_SCALE/SHIFT, bindLookAround() in
   work.js), so the two interactions never fight over the same gesture. */
.tile__media--b {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: 0;
  transition: opacity .35s ease;
}
.tile.show-img-2 .tile__media--a { opacity: 0; }
.tile.show-img-2 .tile__media--b { opacity: 1; }

/* Cursor look-around: --look-scale/--look-x/--look-y are set on
   .tile__frame itself by bindLookAround() in work.js, tracking the
   cursor's position within the frame. Cascades onto whichever media
   layer is currently visible, so it keeps working across a next-image
   swap with nothing to re-bind. Replaces click-to-expand entirely — this
   page never opens a lightbox/modal. */
.tile--gallery .tile__media {
  transform: scale(var(--look-scale, 1)) translate(var(--look-x, 0px), var(--look-y, 0px));
  transition: transform .5s cubic-bezier(.2,.7,.3,1);
}

.tile__tag {
  position: absolute; top: 12px; left: 12px; z-index: 2;
  padding: 5px 11px; border-radius: 999px;
  background: rgba(13,13,12,.74); backdrop-filter: blur(8px);
  border: 1px solid rgba(246,186,2,.35);
  color: var(--gold);
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .13em; text-transform: uppercase;
}

/* Next-image arrow — only rendered when a row has a second image (see
   galleryTileMarkup() in work.js). Sits above the look-around media layer
   (z-index) so it stays clickable no matter how far the cursor effect
   has scaled/shifted the image underneath it. */
.tile__next {
  position: absolute; right: 10px; bottom: 10px; z-index: 3;
  width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(13,13,12,.72); backdrop-filter: blur(8px);
  border: 1px solid var(--line);
  color: var(--cream);
  font-size: 17px; line-height: 1;
  opacity: 1; transform: none;
  animation: cta-pulse-glow 5s ease-in-out infinite;
  transition: opacity .25s ease, transform .25s ease, border-color .2s ease, color .2s ease;
  cursor: pointer;
}
.tile--gallery:hover .tile__next,
.tile--gallery:focus-within .tile__next { opacity: 1; transform: translateY(-1px); }
.tile__next:hover { border-color: var(--gold); color: var(--gold); }

.tile__body { padding: 14px 2px 0; }
.tile--case .tile__body { padding-top: 0; }
@media (max-width: 860px) { .tile--case .tile__body { padding-top: 14px; } }

.tile__headline { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px; }
.tile__name {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(16px, 1.5vw, 21px); line-height: 1.2; letter-spacing: -.015em;
  margin: 0; color: var(--cream);
}
.tile--case .tile__name { font-size: clamp(22px, 2.6vw, 34px); font-weight: 700; }
.tile__name em { font-style: italic; color: var(--gold); }

.tile__cat {
  margin: 0;
  /* Same eyebrow style as .masthead__eyebrow — see the note there. */
  font-family: var(--font-nav); font-size: 12px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--gold); opacity: .85;
}

.tile__meta {
  margin: 7px 0 0;
  font-family: var(--font-mono); font-size: 11px; line-height: 1.6; letter-spacing: .04em;
  color: var(--cream-dim);
}
.tile__meta i { font-style: normal; margin-inline: 7px; opacity: .5; }

.tile__desc {
  margin: 9px 0 0; max-width: 62ch;
  font-size: 14px; line-height: 1.6; color: var(--cream-dim);
}
.tile--case .tile__desc { font-size: 15.5px; color: rgba(241,236,225,.82); }

.tile__more {
  display: inline-flex; align-items: center; gap: 9px;
  margin-top: 16px; padding: 9px 15px 9px 12px;
  border: 1px solid var(--line); border-radius: 999px;
  background: transparent; color: var(--cream);
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .06em;
  cursor: pointer;
  transition: border-color .2s ease, color .2s ease;
}
.tile__more:hover { border-color: var(--gold); color: var(--gold); }
.tile__more-plus {
  display: grid; place-items: center; width: 17px; height: 17px;
  border-radius: 50%; background: var(--gold); color: var(--ink);
  font-size: 13px; line-height: 1; font-weight: 700;
  transition: transform .3s cubic-bezier(.2,.7,.3,1);
}
.tile__more[aria-expanded="true"] .tile__more-plus { transform: rotate(45deg); }

/* Case study detail — expands in flow. Deliberately not a modal: that pattern
   was removed from the landing page on purpose and shouldn't come back. */
.cs-expand { overflow: hidden; height: 0; transition: height .45s cubic-bezier(.2,.7,.3,1); }
.cs-expand__inner {
  padding: clamp(20px, 3vw, 34px) 0 4px;
  display: grid; gap: clamp(20px, 3vw, 34px);
  grid-template-columns: 1fr;
}
@media (min-width: 900px) { .cs-expand__inner { grid-template-columns: minmax(0, 34%) minmax(0, 1fr); } }

.cs-expand__text p {
  margin: 0 0 14px; max-width: 60ch;
  font-size: 15px; line-height: 1.68; color: rgba(241,236,225,.8);
}
.cs-expand__text p:last-child { margin-bottom: 0; }

.cs-expand__shots { display: grid; gap: clamp(10px, 1.4vw, 16px); grid-template-columns: repeat(2, 1fr); }
@media (max-width: 620px) { .cs-expand__shots { grid-template-columns: 1fr; } }
.cs-expand__shots img {
  width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4 / 3;
  border-radius: 10px; border: 1px solid var(--line-soft); background: var(--ink-raised);
}
.cs-expand__close { display: none; }
@media (max-width: 699px) {
  .cs-expand__shots img {
    height: auto;
    aspect-ratio: auto;
    object-fit: contain;
  }
  .cs-expand__close {
    display: inline-flex;
    justify-self: start;
    margin-top: 6px;
    padding: 0 0 5px;
    border: 0;
    border-bottom: 1px solid var(--line);
    background: transparent;
    color: var(--cream-dim);
    font-family: var(--font-mono);
    font-size: 11.5px;
    letter-spacing: .08em;
    text-transform: uppercase;
    cursor: pointer;
  }
}

.work-error {
  font-family: var(--font-mono); font-size: 13px; color: var(--cream-dim);
  padding: 40px 0; max-width: 52ch;
}
.work-error a { color: var(--gold); }

/* ---------- Sections ------------------------------------------------------ */

.section { padding-block: clamp(46px, 7vw, 96px); border-top: 1px solid var(--line); }
.section__label {
  font-family: var(--font-nav); font-size: 12px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--gold); margin: 0 0 18px;
}

/* photo+bio on the left (.about__copy), eyebrow/heading/email/actions
   stacked on the right (.about__contact) — same spec as index.html's
   .about-grid in css/style.css, see the note there. */
.about__grid {
  display: grid; gap: clamp(28px, 4.5vw, 70px); align-items: start;
  grid-template-columns: 1fr;
}
@media (min-width: 700px) {
  /* Right (contact) column widened — was 0.85fr, which left the heading
     so little room that narrowing the window past desktop wrapped it
     into an extra, short orphaned line. 1fr still leaves the left
     (photo/bio) column the larger share, just by less — same fix as
     index.html's .about-grid, see the note there. */
  .about__grid { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: clamp(28px, 4.5vw, 64px); align-items: start; }
}

/* Tablet keeps the mobile reading order, but uses its extra width to place
   the portrait beside the bio. Contact follows below as a full-width beat. */
@media (min-width: 700px) and (max-width: 1024px) {
  .about .about__grid { grid-template-columns: 1fr; gap: 42px; }
  .about .about__copy {
    display: grid;
    grid-template-columns: minmax(180px, 32%) minmax(0, 1fr);
    column-gap: 26px;
    align-items: start;
  }
  .about .about__copy::after { display: none; }
  .about .about__section-eyebrow {
    position: static;
    grid-column: 1 / -1;
    transform: none;
    margin: 0 0 16px;
  }
  .about .about__photo {
    float: none;
    width: 100%;
    margin: 0;
  }
  .about .about__bio { font-size: 15.5px; }

  .services h2 { font-size: 19px; }
  .services p { font-size: 15.5px; line-height: 1.55; }
}

/* Mobile: plain block, photo full-width above the bio text (see
   .about__photo below). At the row breakpoint this becomes a real CSS
   float — the photo floats top-right, the bio text starts in the
   narrower space to its left and wraps to the full column once it
   clears the photo's bottom — not a flex row, so the text can actually
   wrap under the photo instead of sitting in a fixed-height row beside
   it. position:relative anchors .about__section-eyebrow, which sits
   above this box without being part of its flow — see that rule below.
   Same mechanism as index.html's .about-copy, see the note there. */
.about__copy {
  position: relative;
}
@media (min-width: 700px) {
  /* Clearfix: a float doesn't contribute to its parent's height on its
     own, so a bio short enough to clear the photo well before its
     bottom would otherwise leave .about__copy's own box shorter than
     the photo. */
  .about__copy::after { content: ''; display: table; clear: both; }
}

.about__section-eyebrow {
  display: none;
}
@media (max-width: 699px) {
  .about__section-eyebrow {
    display: block;
    position: static;
    font-family: var(--font-nav);
    font-size: 12px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--gold);
    margin: 0 0 14px;
  }
}
@media (min-width: 700px) {
  .about__section-eyebrow {
    display: block;
    position: absolute;
    left: 0;
    top: 0;
    /* Own height + a fixed gap, both via one transform (not a negative
       margin) so it doesn't need updating if the eyebrow's font-size
       ever changes — -100% is relative to THIS element's own box,
       always. */
    transform: translateY(calc(-100% - 14px));
    font-family: var(--font-nav);
    font-size: 12px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--gold);
    margin: 0;
  }
}

.about__photo {
  width: 100%;
  margin: 0 0 16px; /* it's a <figure> — resets the browser default 1em/40px margin, which was pushing it off-center */
  aspect-ratio: 1 / 1;
  border-radius: 16px;
  overflow: hidden;
}
@media (min-width: 700px) {
  /* Bigger than the old flex-row version, but capped well under half
     the column's width even at its widest (an explicit "bigger, but
     not half-width" ask) — 280px against a left column that's normally
     400-600px+ wide. */
  .about__photo {
    float: right;
    width: clamp(160px, 21vw, 280px);
    margin: 0 0 18px 24px;
  }
}
.about__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Width alone does not make a mouse-driven desktop a phone. When a desktop
   window is narrowed below the phone breakpoint, retain the tablet-style
   portrait-and-bio row instead of stretching the portrait full width. */
@media (max-width: 699px) and (any-pointer: fine) {
  .about .about__grid { grid-template-columns: 1fr; gap: 42px; }
  .about .about__copy {
    display: grid;
    grid-template-columns: minmax(150px, 34%) minmax(0, 1fr);
    column-gap: 24px;
    align-items: start;
  }
  .about .about__copy::after { display: none; }
  .about .about__section-eyebrow { grid-column: 1 / -1; }
  .about .about__photo { width: 100%; margin: 0; }
}

/* Font size matches .tile--case .tile__desc (the case-study description
   preview) — same "preview paragraph" voice everywhere on the site.
   .about-lead (data-copy-mode="lead", applied by applyCopy() in work.js —
   see its own comment there) steps just the opening clause ("I'm Sheri")
   up to the project-title voice, same as .about-lead in css/style.css.
   .about-dash is the em dash after it, plain body color. */
.about__bio {
  margin: 0; text-align: left; line-height: 1.65;
  color: var(--cream-dim);
  /* Fluid at the row breakpoint, like index.html's .about-body — as the
     column narrows toward tablet the text shrinks with it instead of
     holding a fixed size and reading oddly large against the (also
     fluid, but proportionally smaller) photo. Fixed below that, same
     as before. */
  font-size: 15.5px;
}
@media (min-width: 700px) {
  .about__bio { font-size: clamp(14px, 1.4vw, 15.5px); }
}
.about-lead {
  font-family: var(--font-display); font-weight: 700;
  font-size: 19px; color: var(--gold);
}
@media (min-width: 700px) {
  .about-lead { font-size: clamp(16px, 1.6vw, 19px); }
}
.about-dash { color: var(--cream-dim); }

.about h2 {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(20px, 2.3vw, 29px); line-height: 1.2; letter-spacing: -.01em;
  margin: 0; max-width: 20ch; text-wrap: balance;
}

/* Eyebrow + email, moved down together — a deliberate gap from the
   heading marks them as their own beat. */
.contact-callout-group { margin-top: 32px; }

.about__callout {
  display: block;
  font-family: var(--font-nav); font-size: 12px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--gold); margin: 0 0 10px;
}
/* Size matches the project-title voice (.tile__name) — was its own much
   larger statement. Underline is permanently gold, no gray resting
   state, no hover color-change on the line — same reasoning as
   .contact-email in css/style.css. */
.about__email {
  display: inline-block;
  font-family: var(--font-display); font-weight: 700;
  font-size: 20px; letter-spacing: -.01em;
  color: var(--cream); word-break: break-all; text-decoration: none;
  border-bottom: 1px solid var(--gold); padding-bottom: 10px;
  transition: color .2s ease;
  cursor: pointer;
}
.about__email:hover { color: var(--gold); }
.about__actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; }

/* Match the landing page's cleaner desktop About composition without
   disturbing the phone's full-width portrait or the tablet row above. */
@media (min-width: 1025px) and (any-pointer: fine) {
  .section.about {
    background: #12110f;
  }

  .about__grid {
    grid-template-columns: minmax(0, 1.55fr) minmax(280px, 0.75fr);
    gap: clamp(40px, 5vw, 72px);
  }

  .about__copy {
    display: grid;
    grid-template-columns: clamp(210px, 18vw, 270px) minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    column-gap: clamp(28px, 3vw, 44px);
    row-gap: 26px;
    align-items: start;
  }

  .about__copy::after { display: none; }

  .about__section-eyebrow {
    position: static;
    grid-column: 1 / -1;
    transform: none;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--line);
  }

  .about__photo {
    float: none;
    width: 100%;
    margin: 0;
    border-radius: 12px;
  }

  .about__bio {
    font-size: 15.5px;
    line-height: 1.72;
    max-width: 46ch;
  }

  .about__contact {
    margin-top: 40px;
    padding: 28px 0 0 clamp(24px, 3vw, 42px);
    border-top: 1px solid var(--line);
    border-left: 1px solid var(--line-soft);
  }

  .about h2 {
    font-size: clamp(22px, 2vw, 28px);
    line-height: 1.25;
  }

  .contact-callout-group { margin-top: 26px; }
}

/* Personal strip — horizontal, slim, scroll-snapped. Hidden entirely until
   there are rows with Display Type = Personal. */
.strip-scroll {
  display: flex; gap: clamp(12px, 1.6vw, 20px);
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  padding-bottom: 14px;
  margin-inline: calc(var(--gutter) * -1); padding-inline: var(--gutter);
  scrollbar-width: thin; scrollbar-color: var(--line) transparent;
}
.strip-scroll::-webkit-scrollbar { height: 5px; }
.strip-scroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: 99px; }
.strip__item { margin: 0; flex: 0 0 auto; scroll-snap-align: start; max-width: 78vw; }
.strip__frame {
  height: clamp(180px, 24vw, 280px); border-radius: 10px; overflow: hidden;
  background: var(--ink-raised); border: 1px solid var(--line-soft);
}
.strip__frame .tile__media { height: 100%; width: auto; object-fit: cover; }
.strip__item figcaption {
  margin-top: 9px;
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--cream-dim);
}

/* The scenic route — the exit back into the desert. Quiet on purpose: this
   line only works if it doesn't shout. */
.scenic {
  display: flex; flex-wrap: wrap; align-items: center; gap: clamp(16px, 3vw, 30px);
  padding: clamp(20px, 3vw, 30px);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: linear-gradient(100deg, rgba(246,186,2,.05), rgba(22,22,19,0) 62%);
  text-decoration: none;
  transition: border-color .3s ease, background .3s ease, transform .3s cubic-bezier(.2,.7,.3,1);
}
.scenic:hover { border-color: rgba(246,186,2,.45); transform: translateY(-2px); }
.scenic__thumb {
  flex: 0 0 auto; width: clamp(108px, 15vw, 180px); aspect-ratio: 16 / 10;
  border-radius: 9px; overflow: hidden; border: 1px solid var(--line-soft);
}
.scenic__thumb img { width: 100%; height: 100%; object-fit: cover; object-position: 62% 60%; transition: transform .6s cubic-bezier(.2,.7,.3,1); }
.scenic__thumb picture { display: block; width: 100%; height: 100%; }
.scenic:hover .scenic__thumb img { transform: scale(1.06); }
.scenic__text { min-width: 0; }
.scenic__line {
  /* A <span> by default (see work.html), so it needs display:block to
     actually break onto its own line — without it, it was flowing
     inline right into .scenic__cta with no visible gap between them. */
  display: block;
  margin: 0; font-family: var(--font-display); font-weight: 600;
  font-size: clamp(17px, 2.1vw, 26px); line-height: 1.2; letter-spacing: -.018em; text-wrap: balance;
}
.scenic__cta {
  margin: 8px 0 0; display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .06em; color: var(--gold);
}
.scenic__cta svg { transition: transform .3s cubic-bezier(.2,.7,.3,1); }
.scenic:hover .scenic__cta svg { transform: translateX(4px); }

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

.wfoot { border-top: 1px solid var(--line); padding-block: 0 30px; }

/* Three-part row — nav left, LinkedIn centered and on its own (not
   grouped with the other links), copyright right. */
.wfoot__base {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 12px 26px;
  padding-top: 24px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .08em; color: var(--cream-dim);
}
.wfoot__base a { text-decoration: none; transition: color .2s ease; }
.wfoot__base a:hover { color: var(--gold); }
.wfoot__base nav { display: flex; flex-wrap: wrap; gap: 20px; justify-self: start; }
.wfoot__linkedin { justify-self: center; }
.wfoot__base > span { justify-self: end; }

@media (max-width: 700px) {
  .wfoot__base { grid-template-columns: 1fr; justify-items: center; text-align: center; }
  .wfoot__base nav, .wfoot__linkedin, .wfoot__base > span { justify-self: center; }
}

/* No lightbox on this page — gallery images never open a modal. The
   cursor look-around (.tile__frame / .tile__media above) is the whole
   "see it bigger" interaction, plus the next-image arrow. Matches the
   landing page's own rule against reintroducing popup patterns. */

/* ---------- Print — recruiters do save portfolios as PDFs ------------------ */
@media print {
  .site-nav, .nav-home-link, .strip, .scenic, .tile__more, .tile__next, .strip-scroll { display: none !important; }
  body { background: #fff; color: #111; }
  .tile { opacity: 1 !important; transform: none !important; }
  .grid { grid-template-columns: repeat(2, 1fr); }
  .tile__name, .about h2 { color: #111; }
  .tile__meta, .tile__desc, .about__bio { color: #444; }
  a { color: #111; text-decoration: underline; }
}

/* ==========================================================================
   IMAGE PROTECTION — deterrence, not security.

   Blocks the two casual gestures: dragging a picture off the page, and
   right-click > Save Image As. That is genuinely most people.

   It is NOT protection. Anyone can still screenshot, open devtools, or read
   the URL straight out of the page source — the file has to reach the
   browser to be displayed at all, so it can always be saved by someone who
   wants to. Treat this as a speed bump, not a lock. The real protections for
   published work are watermarking, posting at display resolution (already
   the case here: nothing is above 1800px), and copyright.
   ========================================================================== */
img, video {
  -webkit-user-drag: none;
  -khtml-user-drag: none;
  -moz-user-drag: none;
  -o-user-drag: none;
  user-drag: none;
  -webkit-touch-callout: none; /* stops iOS long-press "Save Image" */
}
img { user-select: none; -webkit-user-select: none; }

/* Preserve panning gestures while disabling browser pinch zoom. */
html, body { touch-action: pan-x pan-y; }
