/* ==========================================================
   Sebastián Saavedra — one-page portfolio
   Dark mode only. Cinematic / editorial / minimal.
   ========================================================== */

:root {
  --bg: #0a0a09;
  --bg-raise: #121210;
  --bg-soft: #0f0e0c;
  --ink: #e8e4dc;
  --ink-dim: #9a958a;
  --ink-faint: #5c584f;
  --line: rgba(232, 228, 220, 0.13);
  --line-soft: rgba(232, 228, 220, 0.075);
  --accent: #cfc9bc;
  --band-bg: #d6d2c8;
  --band-ink: #17150f;
  --band-ink-dim: #4a463c;
  --sans: "Helvetica Neue", Helvetica, Arial, "Segoe UI", sans-serif;
  --mono: "SF Mono", "Cascadia Code", "IBM Plex Mono", Menlo, Consolas, monospace;
  --pad: clamp(1.25rem, 4vw, 4rem);
  --ease-premium: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 180ms;
  --dur-med: 420ms;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

section,
footer {
  scroll-margin-top: 5.75rem;
}

body {
  background:
    radial-gradient(circle at 84% 8%, rgba(207, 201, 188, 0.055), transparent 28rem),
    linear-gradient(180deg, #0d0c0b 0%, var(--bg) 28rem);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; height: auto; }
picture { display: block; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; }
em { font-style: italic; }

:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 0.35rem;
}

@supports selector(:focus-visible) {
  :focus:not(:focus-visible) { outline: none; }
}

/* subtle film-grain texture */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 999;
  opacity: 0.042;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.6'/%3E%3C/svg%3E");
}

/* halftone-gradient texture, sits at the top of the page and scrolls away
   with it (unlike the fixed grain above). A generated (not tiled) dot field:
   size/density fade from top to bottom, with dots blurred+rethresholded so
   dense areas fuse into organic blobs instead of reading as a uniform
   repeating grid. See BUILD_NOTES.md. */
body::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  aspect-ratio: 1400 / 820;
  pointer-events: none;
  z-index: 998;
  opacity: 0.055;
  background-image: url("../img/bg-halftone.webp");
  background-repeat: no-repeat;
  background-position: top center;
  background-size: 100% auto;
  mix-blend-mode: screen;
}

/* ---------- header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.15rem var(--pad);
  background: rgba(10, 10, 9, 0.82);
  backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--line);
}

@supports not (backdrop-filter: blur(1px)) {
  .site-header { background: rgba(10, 10, 9, 0.96); }
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  color: var(--ink);
}

.brand-mark {
  width: 2.6rem;
  height: 1.56rem;
  flex-shrink: 0;
  color: var(--accent);
}

.brand-name {
  display: flex;
  flex-direction: column;
  font-family: var(--mono);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  line-height: 1.5;
}

.main-nav {
  display: flex;
  gap: clamp(1.2rem, 3vw, 2.8rem);
}

.main-nav a,
.lang-switch button {
  position: relative;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-dim);
  transition: color var(--dur-fast) var(--ease-premium), letter-spacing var(--dur-med) var(--ease-premium);
}

.main-nav a::after,
.footer-links a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.42rem;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  opacity: 0.7;
  transition: transform var(--dur-med) var(--ease-premium);
}

.main-nav a:hover,
.main-nav a:focus-visible {
  color: var(--ink);
  letter-spacing: 0.25em;
}

.main-nav a:hover::after,
.main-nav a:focus-visible::after,
.footer-links a:hover::after,
.footer-links a:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left center;
}

.header-right { display: flex; align-items: center; gap: 1.4rem; }

.lang-switch {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: 0.72rem;
}

.lang-switch button {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.2rem 0.1rem;
  transition: color var(--dur-fast) var(--ease-premium), border-color var(--dur-fast) var(--ease-premium);
}

.lang-switch button:hover,
.lang-switch button:focus-visible { color: var(--ink); }

.lang-switch button.is-active {
  color: var(--ink);
  border-bottom: 1px solid var(--ink);
}

.nav-toggle {
  display: none;
  background: none;
  border: none;
  cursor: pointer;
  width: 28px;
  height: 20px;
  position: relative;
}
.nav-toggle span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: var(--ink);
  transition: transform var(--dur-med) var(--ease-premium), top var(--dur-med) var(--ease-premium), opacity var(--dur-fast) var(--ease-premium);
}
.nav-toggle span:first-child { top: 5px; }
.nav-toggle span:last-child { top: 13px; }
.nav-toggle[aria-expanded="true"] span:first-child { top: 9px; transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:last-child { top: 9px; transform: rotate(-45deg); }

/* ---------- hero ---------- */
.hero {
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  position: relative;
  padding: 0 var(--pad);
  overflow: clip;
  border-bottom: 1px solid var(--line-soft);
}

.hero::before {
  content: "";
  position: absolute;
  top: 5.5rem;
  right: max(-10vw, -8rem);
  width: clamp(18rem, 38vw, 40rem);
  height: clamp(18rem, 38vw, 40rem);
  background: radial-gradient(circle, rgba(207, 201, 188, 0.12), rgba(207, 201, 188, 0) 68%);
  pointer-events: none;
}

.hero-inner {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(18rem, 0.88fr);
  gap: clamp(2.25rem, 6vw, 7rem);
  align-items: start;
  min-height: min(760px, calc(100svh - 5rem));
  padding: clamp(3.1rem, 7vw, 6.6rem) 0 clamp(2.75rem, 5.5vw, 5rem);
}

.hero-title {
  font-family: var(--mono);
  font-weight: 500;
  font-size: clamp(2.15rem, 5.35vw, 5.6rem);
  line-height: 0.98;
  letter-spacing: 0.025em;
  text-transform: uppercase;
  color: var(--accent);
}
.hero-title span {
  display: block;
  max-width: 10ch;
}

.hero-title span:nth-child(2) {
  color: var(--ink);
  text-indent: clamp(1rem, 5vw, 5rem);
}

.hero-title span:nth-child(3) {
  color: var(--ink-dim);
}

.hero-bio {
  max-width: 31rem;
  margin-top: clamp(1.6rem, 3vw, 2.6rem);
  color: var(--ink-dim);
  font-size: clamp(0.95rem, 1.4vw, 1.05rem);
  line-height: 1.68;
}

.hero-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.9rem;
  margin-top: clamp(1.9rem, 3.5vw, 3rem);
  padding: 0.85rem 1.6rem;
  border: 1px solid var(--ink-faint);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  transition: border-color 0.22s var(--ease-out), background 0.22s var(--ease-out), color 0.22s var(--ease-out), transform 0.22s var(--ease-out);
}
.hero-cta:hover {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--bg);
  transform: translateY(-1px);
}
.hero-cta .arrow {
  font-size: 1rem;
  transition: transform 0.22s var(--ease-out);
}
.hero-cta:hover .arrow { transform: translate(3px, -3px); }

.hero-photo {
  position: relative;
  justify-self: end;
  width: 100%;
  max-width: min(560px, 42vw);
  overflow: hidden;
  border: 1px solid rgba(232, 228, 220, 0.12);
  background: var(--bg-raise);
  isolation: isolate;
}
.hero-photo img {
  width: 100%;
  aspect-ratio: 0.82;
  object-fit: cover;
  transform: scale(1.015);
  filter: grayscale(14%) contrast(1.08) brightness(0.88) saturate(0.9);
  transition: transform 0.7s var(--ease-out), filter 0.7s var(--ease-out);
}
.hero-photo:hover img {
  transform: scale(1.035);
  filter: grayscale(8%) contrast(1.1) brightness(0.92) saturate(0.95);
}
.hero-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background:
    linear-gradient(200deg, transparent 46%, rgba(10, 10, 9, 0.62)),
    linear-gradient(0deg, rgba(10, 10, 9, 0.16), rgba(10, 10, 9, 0));
  pointer-events: none;
}

.hero-side {
  position: absolute;
  right: -1.4rem;
  top: 50%;
  transform: rotate(90deg) translateX(-50%);
  transform-origin: right center;
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}

/* ---------- pillars ---------- */
.pillars {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1.25rem, 2.8vw, 3rem);
  padding: clamp(2.2rem, 4.5vw, 3.8rem) 0 clamp(3.25rem, 6vw, 5.25rem);
  border-top: 1px solid var(--line-soft);
}

.pillar-mark {
  width: 2.5rem;
  height: 2rem;
  color: var(--ink-faint);
  transition: color var(--dur-med) var(--ease-premium);
}
.pillar:hover .pillar-mark,
.pillar:focus-within .pillar-mark {
  color: var(--accent);
}

.pillar h2 {
  margin-top: 0.7rem;
  padding-bottom: 0.7rem;
  min-height: 2.6em;
  border-bottom: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  line-height: 1.3;
}

.pillar p {
  margin-top: 0.85rem;
  font-size: 0.85rem;
  color: var(--ink-dim);
  line-height: 1.62;
}

/* ---------- statement band ---------- */
.band {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 0.6fr);
  align-items: center;
  gap: clamp(2rem, 6vw, 6rem);
  padding: clamp(3rem, 6vw, 5rem) var(--pad);
  background: var(--band-bg);
  color: var(--band-ink);
}

.band::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(90deg, rgba(23, 21, 15, 0.06), transparent 36%),
    radial-gradient(circle at 85% 18%, rgba(23, 21, 15, 0.1), transparent 18rem);
}

.band-statement {
  position: relative;
  max-width: 36rem;
  font-size: clamp(1.12rem, 2vw, 1.55rem);
  line-height: 1.48;
  letter-spacing: -0.015em;
}

.band-label {
  position: relative;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--band-ink-dim);
  margin-bottom: 1.1rem;
}

.band-audience ul li {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-family: var(--mono);
  font-size: 0.82rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.52rem 0;
  border-bottom: 1px solid rgba(23, 21, 15, 0.15);
  transition: border-color var(--dur-med) var(--ease-premium);
}
.band-audience ul li:hover { border-color: rgba(23, 21, 15, 0.32); }

/* one of the 5 motion studies from 01_Preproduccion/Motion Design, inlined
   — quiet by default, only discovered on hover (see README there for the
   "sparse signal, near-imperceptible" intent behind these). */
.band-motion {
  width: 2.5rem;
  height: 2.5rem;
  flex-shrink: 0;
  color: var(--band-ink);
  opacity: 0;
  transform: scale(0.86);
  transition: opacity var(--dur-med) var(--ease-premium), transform var(--dur-med) var(--ease-premium);
}
.band-audience ul li:hover .band-motion {
  opacity: 1;
  transform: scale(1);
}

/* ---------- sections ---------- */
.section {
  position: relative;
  padding: clamp(4.5rem, 8vw, 7.5rem) var(--pad);
}

.section-head {
  display: flex;
  align-items: baseline;
  gap: clamp(1.25rem, 3vw, 2.4rem);
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}
.section-head::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, var(--line), transparent);
}

.section-title {
  font-family: var(--mono);
  font-weight: 500;
  font-size: clamp(1.35rem, 2.65vw, 2.15rem);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}

/* ---------- projects ---------- */
.projects-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1.35rem, 2.6vw, 2.35rem);
}

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

/* Carousel controls: hidden entirely on tablet/desktop, where the grid
   already shows all 4 projects at once (see BUILD_NOTES.md rationale). */
.projects-carousel-controls { display: none; }

.project-thumb {
  position: relative;
  aspect-ratio: 4 / 3;
  margin-bottom: 1.35rem;
  overflow: hidden;
  border: 1px solid var(--line-soft);
  background-color: var(--bg-soft);
  transition: border-color var(--dur-med) var(--ease-premium), filter var(--dur-med) var(--ease-premium), transform var(--dur-med) var(--ease-premium);
}
/* real project stills (as opposed to the plain gradient placeholders):
   fills the 4:3 box completely (cover) instead of letterboxing, to match
   the other cards. For a portrait poster like Últimos días that means
   cropping — object-position is shifted up so the title + face survive
   the crop and it's the credits line at the bottom that gets cut instead. */
/* one shared grade across every poster still + preview clip, regardless of
   how each source was originally shot/lit — this is what makes four very
   different materials (a poster scan, a client color-grade sample, an
   AI-generated image, a raw studio broadcast frame) read as one consistent
   set instead of four unrelated thumbnails. */
.project-thumb.has-poster img,
.thumb-preview-video {
  filter: grayscale(15%) contrast(1.08) brightness(0.88) saturate(0.85);
}
/* Últimos días' clip is a dusk shot that's already mostly silhouette —
   the shared grade on top of that reads too dark, so it gets a touch
   more brightness back. Attribute selector so it only kicks in while
   this specific clip is loaded into the shared preview <video>, not
   Pastora (the other work-link sharing the same element). */
.thumb-preview-video[src*="ultimos-dias-preview"] {
  filter: grayscale(10%) contrast(0.95) brightness(1.3) saturate(0.88);
}
/* Video Production's source material (bright studio lighting, saturated
   brand colors) reads noticeably lighter than the other three even after
   the shared grade above — pull it down further so it stops standing out. */
.thumb-2.has-poster img {
  filter: grayscale(30%) contrast(1.12) brightness(0.6) saturate(0.55);
}
/* the still poster can carry the full grade, but once the clip is actually
   playing that much darkening/desaturation reads muddy — ease off ~30%
   toward the shared site-wide grade while it's active. */
.thumb-2 .thumb-preview-video {
  filter: grayscale(21%) contrast(1.08) brightness(0.86) saturate(0.68);
}
.project-thumb.has-poster img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 20%;
}
/* hovering/focusing a work-link with data-preview swaps this in over the
   poster (see work-preview.js) — poster stays as the instant-paint fallback */
.thumb-preview-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 20%;
  opacity: 0;
  transition: opacity var(--dur-med) var(--ease-premium);
  pointer-events: none;
}
.thumb-preview-video.is-active {
  opacity: 1;
}

/* quiet centered "there's something to explore here" cue, on all 4
   category thumbnails regardless of whether their videos are wired up
   yet — a magnifying glass rather than a play icon since it doesn't
   promise video specifically. Purely visual: pointer-events:none lets
   clicks fall through to whatever the thumb itself already does (the
   tap-to-cycle preview on Film/Creative Direction today, nothing yet on
   the other three). Hides while a preview is actually playing so it
   doesn't sit on top of the moving video. */
.thumb-explore-hint {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  transition: opacity var(--dur-med) var(--ease-premium);
}
.thumb-explore-hint svg {
  width: 2.6rem;
  height: 2.6rem;
  color: var(--ink);
  opacity: 0.55;
  filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.6));
}
.project-thumb:has(.thumb-preview-video.is-active) .thumb-explore-hint {
  opacity: 0;
}

/* bottom-center pagination dots — generated by work-preview.js, one per
   data-preview work-link. Same visual language as .carousel-dots (see
   the mobile projects carousel) so "tap again to see the next one" reads
   as a familiar pattern rather than a new one. */
.thumb-dots {
  position: absolute;
  left: 50%;
  bottom: 0.9rem;
  z-index: 3;
  display: flex;
  gap: 0.5rem;
  transform: translateX(-50%);
}
.thumb-dot {
  appearance: none;
  -webkit-appearance: none;
  width: 7px;
  height: 7px;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: rgba(232, 228, 220, 0.45);
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.6));
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-premium), transform var(--dur-fast) var(--ease-premium);
}
.thumb-dot:hover,
.thumb-dot:focus-visible {
  background: var(--ink);
}
.thumb-dot.is-active {
  background: var(--accent);
  transform: scale(1.3);
}
.project-thumb::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(120deg, rgba(232, 228, 220, 0.16), transparent 36%),
    radial-gradient(circle at 75% 20%, rgba(232, 228, 220, 0.12), transparent 34%);
  opacity: 0;
  transition: opacity var(--dur-med) var(--ease-premium);
}
/* always-on shortcut in the corner — the tap-to-cycle preview is nice but
   still needs an explicit "open the real thing" action, especially on
   touch where there's no hover to discover the work-links below. */
.thumb-open {
  appearance: none;
  -webkit-appearance: none;
  position: absolute;
  right: 0.9rem;
  bottom: 0.9rem;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  padding: 0.6rem 0.9rem;
  background: rgba(10, 10, 9, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid transparent;
  border-radius: 0.5rem;
  text-align: center;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-premium), background var(--dur-fast) var(--ease-premium), opacity 0.5s var(--ease-premium) 0.15s, transform 0.5s var(--ease-premium) 0.15s;
}
.thumb-open:hover,
.thumb-open:focus-visible {
  border-color: var(--accent);
  background: rgba(10, 10, 9, 0.78);
}
/* small staggered pop-in after the card itself reveals on scroll (see
   body.reveal-enabled rules in main.js's IntersectionObserver system) —
   falls back to fully visible if that system never engages (no-JS). */
body.reveal-enabled .thumb-open {
  opacity: 0;
  transform: scale(0.9);
}
body.reveal-enabled .project.is-revealed .thumb-open {
  opacity: 1;
  transform: scale(1);
}
.thumb-open-title {
  font-family: var(--sans);
  font-size: 0.72rem;
  color: var(--ink-dim);
}
@keyframes thumb-open-title-in {
  from { opacity: 0; transform: translateY(3px); }
  to { opacity: 1; transform: translateY(0); }
}
/* replayed via JS (class removed + re-added) every time the label swaps,
   whether from the tap-to-cycle or from hovering a different work-link. */
.thumb-open-title.is-updating {
  animation: thumb-open-title-in 0.35s var(--ease-premium);
}
.thumb-open-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}
.thumb-open-cta .arrow {
  font-size: 0.85rem;
  transition: transform 0.22s var(--ease-out);
}
.thumb-open:hover .arrow { transform: translate(2px, -2px); }

.thumb-1 { background: radial-gradient(120% 90% at 20% 15%, #2b2418 0%, #14110b 55%, #0c0a07 100%); }
.thumb-2 { background: radial-gradient(110% 100% at 80% 20%, #1e2430 0%, #11141b 55%, #0a0b0f 100%); }
.thumb-3 { background: linear-gradient(160deg, #16201c 0%, #0c110f 60%, #090b0a 100%); }
.thumb-4 { background: radial-gradient(130% 100% at 50% 100%, #2a1a1c 0%, #150e10 55%, #0b0809 100%); }

.project h3 {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  font-family: var(--mono);
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.145em;
  text-transform: uppercase;
  transition: color var(--dur-fast) var(--ease-premium);
}

.badge {
  font-size: 0.58rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--ink-faint);
  border-radius: 999px;
  color: var(--ink-dim);
  white-space: nowrap;
}

.is-upcoming .project-thumb { opacity: 0.75; }

/* on the mobile carousel, JS crossfades this via inline opacity as slides
   pass the center — the transition just smooths between updates. Inert
   on desktop (no inline opacity ever gets set there). */
.project-info { transition: opacity 0.15s linear; }

.project-meta {
  margin-top: 0.65rem;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #6f695f;
}

.project-desc {
  margin-top: 0.9rem;
  font-size: 0.86rem;
  color: var(--ink-dim);
  line-height: 1.66;
}

/* each project card is now a category — this lists the individual
   pieces inside it. Clickable ones open the video modal (see
   hero-modal.js); pending ones are plain text with a badge. */
.project-works {
  margin-top: 1.1rem;
  display: flex;
  flex-direction: column;
}

.work-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  width: 100%;
  padding: 0.55rem 0;
  background: none;
  border: none;
  border-bottom: 1px solid var(--line-soft);
  font-family: var(--sans);
  font-size: 0.82rem;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-premium), color var(--dur-fast) var(--ease-premium);
}
.work-link:hover,
.work-link:focus-visible,
.work-link.is-selected {
  border-color: var(--accent);
  color: var(--accent);
}

.work-pending {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 0.82rem;
  color: var(--ink-faint);
}

.work-tag {
  font-family: var(--mono);
  font-size: 0.65rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}

.project:hover .project-thumb,
.project:focus-within .project-thumb {
  border-color: rgba(232, 228, 220, 0.34);
  filter: contrast(1.08) brightness(1.08);
  transform: translateY(-2px);
}

.project:hover .project-thumb::after,
.project:focus-within .project-thumb::after { opacity: 1; }

.project:hover h3,
.project:focus-within h3 { color: var(--accent); }

/* ---------- services ---------- */
/* a second, lower encounter with the halftone texture (reuses the same
   generated asset as the hero one) — the page "meets more grain" again
   around Services instead of it only living up near the hero. Flipped
   vertically so it fades in from nothing right at the section boundary
   (its own top edge) and builds up further down, instead of starting at
   full density immediately — that was reading as an abrupt cut coming
   from Projects, where the hero's texture had already faded to nothing. */
#services::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  aspect-ratio: 1400 / 820;
  pointer-events: none;
  z-index: 0;
  opacity: 0.055;
  background-image: url("../img/bg-halftone.webp");
  background-repeat: no-repeat;
  background-position: top center;
  background-size: 100% auto;
  transform: scaleY(-1);
  mix-blend-mode: screen;
  /* mask is in the element's own (pre-flip) coordinates, so "transparent
     at the top here" is what ends up fading out at the visual bottom
     after scaleY(-1) — otherwise the texture just stops dead at the
     element's lower edge instead of tapering off. */
  mask-image: linear-gradient(to bottom, transparent 0%, black 20%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 20%);
}

.services-list li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  gap: 1rem clamp(2rem, 5vw, 4rem);
  padding: clamp(1.5rem, 2.4vw, 2rem) 0;
  border-bottom: 1px solid var(--line);
  transition: border-color var(--dur-med) var(--ease-premium), color var(--dur-fast) var(--ease-premium);
}
.services-list li:first-child { border-top: 1px solid var(--line); }

.services-list h3 {
  display: flex;
  gap: 1.4rem;
  align-items: center;
  font-family: var(--mono);
  font-size: 0.84rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform var(--dur-med) var(--ease-premium), color var(--dur-fast) var(--ease-premium);
}
.services-list h3:focus-visible { outline: 1px solid var(--accent); outline-offset: 4px; }

/* "+" cross-fades into "×" on open — same idea as the mobile nav-toggle. */
.svc-toggle {
  margin-left: auto;
  font-size: 1.15rem;
  font-weight: 400;
  color: var(--ink-faint);
  transition: transform var(--dur-med) var(--ease-premium), color var(--dur-fast) var(--ease-premium);
}
.services-list li.is-open .svc-toggle {
  transform: rotate(45deg);
  color: var(--accent);
}

.svc-mark {
  width: 1.7rem;
  height: 1.35rem;
  flex-shrink: 0;
  color: var(--ink-faint);
  transition: color var(--dur-med) var(--ease-premium);
}
.services-list li:hover .svc-mark,
.services-list li:focus-within .svc-mark {
  color: var(--accent);
}

.services-list p {
  font-size: 0.92rem;
  color: var(--ink-dim);
  max-width: 42rem;
  line-height: 1.68;
  transition: color var(--dur-fast) var(--ease-premium);
}

.services-list li:hover,
.services-list li:focus-within { border-color: rgba(232, 228, 220, 0.28); }

.services-list li:hover h3,
.services-list li:focus-within h3 {
  color: var(--accent);
  transform: translateX(0.35rem);
}

.services-list li:hover p,
.services-list li:focus-within p { color: var(--ink); }

.service-cta {
  grid-column: 1 / -1;
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition: max-height var(--dur-med) var(--ease-premium), opacity var(--dur-med) var(--ease-premium), margin-top var(--dur-med) var(--ease-premium);
}
.services-list li.is-open .service-cta {
  max-height: 5rem;
  opacity: 1;
  margin-top: 0.4rem;
}

.service-cta-link {
  display: inline-flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.75rem 1.4rem;
  border: 1px solid var(--ink-faint);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  transition: border-color var(--dur-fast) var(--ease-premium), background var(--dur-fast) var(--ease-premium), color var(--dur-fast) var(--ease-premium), transform var(--dur-fast) var(--ease-premium);
}
.service-cta-link:hover,
.service-cta-link:focus-visible {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--bg);
  transform: translateY(-1px);
}
.service-cta-link .arrow {
  font-size: 0.95rem;
  transition: transform 0.22s var(--ease-out);
}
.service-cta-link:hover .arrow { transform: translate(3px, -3px); }

/* ---------- about ---------- */
.about-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.74fr) minmax(0, 1.26fr);
  gap: clamp(2.75rem, 6vw, 6.5rem);
  align-items: start;
}

.about-photo {
  max-width: 420px;
  overflow: hidden;
  border: 1px solid var(--line-soft);
  background: var(--bg-soft);
  transition: border-color var(--dur-med) var(--ease-premium);
}
.about-photo img {
  aspect-ratio: 4 / 5;
  object-fit: cover;
  filter: grayscale(25%) contrast(1.03) brightness(0.9);
  transition: transform 0.7s var(--ease-premium), filter 0.7s var(--ease-premium);
}

.about-photo:hover { border-color: rgba(232, 228, 220, 0.18); }
.about-photo:hover img {
  transform: scale(1.025);
  filter: grayscale(16%) contrast(1.06) brightness(0.94);
}

.about-text .section-title { margin-bottom: 2rem; }
.about-text p {
  max-width: 40rem;
  color: var(--ink-dim);
  font-size: clamp(0.96rem, 1.15vw, 1.03rem);
  line-height: 1.76;
}
.about-text p + p { margin-top: 1.45rem; }

/* ---------- clients ---------- */
.clients {
  padding-top: clamp(1rem, 2vw, 1.8rem);
  border-top: none;
}
.clients .band-label { color: var(--ink-faint); }

.clients-list {
  display: flex;
  flex-wrap: wrap;
  gap: 1.15rem clamp(2rem, 5vw, 4.5rem);
  padding-top: 1.65rem;
  border-top: 1px solid var(--line-soft);
}
.clients-list li {
  font-family: var(--mono);
  font-size: clamp(0.9rem, 1.6vw, 1.15rem);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #aaa397;
}

/* keeps a single letter lowercase (e.g. the "c" in McFIT) against an
   ancestor's text-transform: uppercase */
.cap-lower { text-transform: lowercase; }

/* ---------- footer ---------- */
.site-footer {
  position: relative;
  padding: clamp(4.5rem, 8vw, 7.25rem) var(--pad) 2.5rem;
  border-top: 1px solid var(--line-soft);
  background:
    radial-gradient(circle at 12% 12%, rgba(207, 201, 188, 0.06), transparent 24rem),
    linear-gradient(180deg, rgba(18, 18, 16, 0.35), transparent);
}

.footer-title {
  font-family: var(--mono);
  font-weight: 500;
  font-size: clamp(1.55rem, 3.4vw, 2.8rem);
  letter-spacing: 0.105em;
  text-transform: uppercase;
  color: var(--accent);
}

.footer-mail {
  display: inline-block;
  margin-top: 1.75rem;
  font-family: var(--mono);
  font-size: clamp(0.95rem, 2vw, 1.3rem);
  letter-spacing: 0.08em;
  color: var(--ink);
  border-bottom: 1px solid var(--ink-faint);
  padding-bottom: 0.25rem;
  transition: border-color var(--dur-fast) var(--ease-premium), color var(--dur-fast) var(--ease-premium);
}
.footer-mail:hover,
.footer-mail:focus-visible {
  border-color: var(--ink);
  color: var(--accent);
}

.footer-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: clamp(3rem, 6vw, 5rem);
  padding-top: 1.55rem;
  border-top: 1px solid var(--line-soft);
}

.footer-copy {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.footer-links { display: flex; gap: 2.2rem; }
.footer-links a {
  position: relative;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-dim);
  transition: color var(--dur-fast) var(--ease-premium), letter-spacing var(--dur-med) var(--ease-premium);
}
.footer-links a:hover,
.footer-links a:focus-visible {
  color: var(--ink);
  letter-spacing: 0.25em;
}

body.reveal-enabled .section,
body.reveal-enabled .band,
body.reveal-enabled .pillars,
body.reveal-enabled .project,
body.reveal-enabled .services-list li,
body.reveal-enabled .about-photo,
body.reveal-enabled .about-text,
body.reveal-enabled .clients-list li,
body.reveal-enabled .site-footer {
  transition:
    opacity 0.7s var(--ease-premium),
    transform 0.7s var(--ease-premium),
    border-color var(--dur-med) var(--ease-premium),
    color var(--dur-fast) var(--ease-premium);
}

/* :not(.is-revealed) here so this never has to out-specificity the
   .is-revealed rule below — .services-list li / .clients-list li match an
   extra element selector (li) that made the plain ".is-revealed" rule lose
   the cascade once revealed, leaving those two permanently invisible. */
body.reveal-enabled .section:not(.is-revealed),
body.reveal-enabled .band:not(.is-revealed),
body.reveal-enabled .pillars:not(.is-revealed),
body.reveal-enabled .project:not(.is-revealed),
body.reveal-enabled .services-list li:not(.is-revealed),
body.reveal-enabled .about-photo:not(.is-revealed),
body.reveal-enabled .about-text:not(.is-revealed),
body.reveal-enabled .clients-list li:not(.is-revealed),
body.reveal-enabled .site-footer:not(.is-revealed) {
  opacity: 0;
  transform: translateY(18px);
}

body.reveal-enabled .is-revealed {
  opacity: 1;
  transform: translateY(0);
}

/* ---------- video modal ---------- */
body.modal-open { overflow: hidden; }

.video-modal {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--pad);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-med) var(--ease-premium);
}
.video-modal.is-open {
  opacity: 1;
  pointer-events: auto;
}

.video-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(6, 6, 5, 0.88);
  backdrop-filter: blur(6px);
}

.video-modal-dialog {
  position: relative;
  width: min(1000px, 100%);
}

.video-modal-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--bg-soft);
  border: 1px solid var(--line-soft);
  overflow: hidden;
}
.video-modal-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* muted looping preview, dimmed well below the picker buttons so it reads
   as ambiance — the choice (Full film / Trailer / Press) stays the focus */
.video-modal-picker-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.16;
  z-index: 0;
  transition: opacity var(--dur-med) var(--ease-premium);
}
/* set right as a picker option is chosen, so the ambient loop reveals at
   full strength while the buttons fade — a beat of continuity before the
   real embed swaps in, instead of an abrupt cut. */
.video-modal-picker-bg.is-revealed {
  opacity: 1;
}

.video-modal-picker {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  background: linear-gradient(rgba(6, 6, 5, 0.35), rgba(6, 6, 5, 0.55));
  transition: opacity var(--dur-med) var(--ease-premium);
}
.video-modal-picker.is-choosing {
  opacity: 0;
  pointer-events: none;
}
.video-modal-picker-option {
  min-width: 12rem;
  padding: 0.9rem 1.8rem;
  background: none;
  border: 1px solid var(--ink-faint);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 0.82rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-premium), color var(--dur-fast) var(--ease-premium), background var(--dur-fast) var(--ease-premium);
}
.video-modal-picker-option:hover,
.video-modal-picker-option:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
}

.video-modal-password {
  margin-top: 0.9rem;
  font-family: var(--mono);
  font-size: 0.8rem;
  letter-spacing: 0.05em;
  color: var(--ink-dim);
  text-align: center;
}

.video-modal-close {
  position: absolute;
  top: -2.6rem;
  right: 0;
  width: 2.2rem;
  height: 2.2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid var(--ink-faint);
  border-radius: 999px;
  color: var(--ink);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-premium), color var(--dur-fast) var(--ease-premium);
}
.video-modal-close:hover,
.video-modal-close:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
}

/* ==========================================================
   Responsive
   ========================================================== */

@media (max-width: 960px) {
  .hero-inner { grid-template-columns: 1fr; }
  .hero-photo {
    justify-self: start;
    max-width: min(520px, 86vw);
    order: -1;
  }
  .hero-title span { max-width: 11ch; }
  .hero-side { display: none; }
  .pillars { grid-template-columns: repeat(2, 1fr); }
  .projects-grid { grid-template-columns: repeat(2, 1fr); }
  .band { grid-template-columns: 1fr; }
  .about-grid { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  section,
  footer {
    scroll-margin-top: 4.75rem;
  }

  .section { padding-block: clamp(3.6rem, 14vw, 5rem); }

  .nav-toggle { display: block; }

  .main-nav {
    position: fixed;
    inset: 0;
    z-index: 90;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 2.2rem;
    background: rgba(10, 10, 9, 0.97);
    transform: translateY(-100%);
    visibility: hidden;
    transition: transform 0.3s ease, visibility 0.3s;
  }
  .main-nav.is-open { transform: translateY(0); visibility: visible; }

  /* backdrop-filter on .site-header creates a containing block for its
     position:fixed descendants (the CSS spec quirk behind the menu bug) —
     dropping it while the mobile menu is open lets .main-nav's inset:0
     size against the real viewport instead of the header's own box. */
  .site-header.nav-open { backdrop-filter: none; }
  .main-nav a { font-size: 1rem; }

  .pillars { grid-template-columns: 1fr; }
  .services-list li { grid-template-columns: 1fr; }
  .brand-name { font-size: 0.8rem; letter-spacing: 0.3em; }
  .brand-mark { width: 2.15rem; height: 1.29rem; }
  .hero-inner {
    min-height: 0;
    padding-top: 2.5rem;
  }
  .hero-title {
    font-size: clamp(2rem, 12vw, 3.85rem);
    line-height: 1.02;
  }
  .hero-title span:nth-child(2) { text-indent: clamp(0.8rem, 10vw, 2.6rem); }
  .hero-photo { max-width: 100%; }

  /* ---- projects: swipeable one-at-a-time carousel on mobile only ----
     On desktop/tablet the 4 projects stay a scannable grid (see
     BUILD_NOTES.md for why we didn't carousel-ify the whole section).
     On mobile the grid already stacked to 1 column, so turning that
     single column into a swipe strip is a pure UX gain: same content,
     no extra scrolling, and clear "N of 4" navigation. */
  .projects-grid {
    display: flex;
    grid-template-columns: none;
    gap: 0;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .projects-grid::-webkit-scrollbar { display: none; }

  .projects-grid .project {
    flex: 0 0 100%;
    scroll-snap-align: center;
  }

  .projects-carousel-controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.4rem;
    margin-top: 1.6rem;
  }

  .carousel-btn {
    appearance: none;
    -webkit-appearance: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.4rem;
    height: 2.4rem;
    padding: 0;
    border: 1px solid var(--ink-faint);
    border-radius: 999px;
    background: none;
    color: var(--ink);
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
  }
  .carousel-btn svg {
    width: 0.8rem;
    height: 0.8rem;
    display: block;
  }
  .carousel-btn:hover,
  .carousel-btn:focus-visible { border-color: var(--ink); background: rgba(232, 228, 220, 0.08); }
  .carousel-btn:disabled { opacity: 0.3; cursor: default; }

  .carousel-dots {
    display: flex;
    gap: 0.55rem;
  }
  .carousel-dots button {
    width: 7px;
    height: 7px;
    padding: 0;
    border: none;
    border-radius: 999px;
    background: var(--ink-faint);
    cursor: pointer;
  }
  .carousel-dots button.is-active { background: var(--accent); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    transition-duration: 0.001ms !important;
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
  }

  .hero-cta,
  .hero-cta .arrow,
  .hero-photo img {
    transition: none;
  }

  .hero-photo:hover img {
    transform: scale(1.015);
  }

  .projects-grid { scroll-behavior: auto; }

  .project:hover .project-thumb,
  .project:focus-within .project-thumb,
  .services-list li:hover h3,
  .services-list li:focus-within h3,
  .about-photo:hover img {
    transform: none;
  }

  body.reveal-enabled .section,
  body.reveal-enabled .band,
  body.reveal-enabled .pillars,
  body.reveal-enabled .project,
  body.reveal-enabled .services-list li,
  body.reveal-enabled .about-photo,
  body.reveal-enabled .about-text,
  body.reveal-enabled .clients-list li,
  body.reveal-enabled .site-footer {
    opacity: 1;
    transform: none;
  }
}
