/* ============================================================
   SECTIONS
   Built up phase by phase per CLAUDE.md §40. Header/Nav (Phase 2),
   Hero + Video Showcase (Phase 3) implemented so far.
   ============================================================ */

/* ---- Header / Navigation ----
   Fixed (not sticky) so header.js can drive it with a GSAP
   transform/opacity tween independent of document flow — see
   header.js for the scroll show/hide behavior. main gets a
   matching padding-top (global.css) since fixed removes the
   header from flow and would otherwise leave hero content
   underneath it. */
.header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: var(--z-header);
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--header-h);
  padding-inline: var(--section-px);
  background: var(--color-surface);
  transition: box-shadow var(--dur-base) var(--ease-standard);
}

.header--scrolled {
  box-shadow: 0 2px 16px rgba(31, 39, 58, 0.06);
}

.header__logo {
  position: relative;
  width: 75px;
  height: 40px;
  display: block;
}

.header__logo-grid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.header__logo-mark {
  position: absolute;
  left: 20px;
  top: 7px;
  width: 27px;
  height: 27px;
}

.header__logo-dot {
  position: absolute;
  left: 49px;
  top: 28px;
  width: 5.33px;
  height: 5.33px;
  border-radius: 1.33px;
  background: var(--color-ink);
}

.header__nav {
  display: none;
  align-items: center;
  gap: 40px;
}

.header__link {
  transition: color var(--dur-fast) var(--ease-standard);
}

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

/* Ghost pill — icon + text, no fill (Figma: node 1:70, no bg on the button itself) */
.header__contact {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 8px 16px;
  border-radius: var(--radius-pill);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  text-transform: uppercase;
  color: var(--color-black);
  transition: background-color var(--dur-fast) var(--ease-standard);
}

.header__contact:hover {
  background: var(--color-bg);
}

.header__contact-icon {
  width: 8px;
  height: 8px;
  flex-shrink: 0;
  background: var(--color-accent);
}

/* ---- Mobile nav toggle ---- */
.header__hamburger {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  width: 40px;
  height: 40px;
}

.header__hamburger span {
  display: block;
  width: 20px;
  height: 2px;
  background: var(--color-ink);
  transition: transform var(--dur-base) var(--ease-standard),
              opacity var(--dur-base) var(--ease-standard);
}

.header__hamburger[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.header__hamburger[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}
.header__hamburger[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

.header__drawer {
  position: fixed;
  inset: var(--header-h) 0 0 0;
  z-index: calc(var(--z-header) - 1);
  background: var(--color-surface);
  padding: 32px var(--section-px-mobile);
  transform: translateY(-8px);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-standard),
              transform var(--dur-base) var(--ease-standard);
}

.header__drawer[aria-hidden="false"] {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.header__drawer-nav {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.header__drawer-link {
  font-size: var(--fs-xl);
}

.header__drawer-cta {
  margin-top: 8px;
  width: 100%;
}

/* ---- Hero ---- */
.hero {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 48px;
}

.hero__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 24px;
  width: 100%;
}

.hero__intro {
  display: flex;
  flex-direction: column;
  gap: 14px;
  color: var(--color-ink);
  max-width: 640px;
}

.hero__eyebrow {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: var(--fs-xl);
  text-transform: uppercase;
}

.hero__eyebrow strong {
  font-weight: 700;
}

.hero__role {
  font-family: var(--font-body);
  font-size: var(--fs-md);
}

.hero__meta {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding-top: 4px;
}

.hero__meta-group {
  display: flex;
  align-items: center;
  gap: 8px;
}

.hero__meta-value {
  color: var(--color-ink);
}

.hero__meta-sep {
  color: var(--color-muted);
}

.hero__headline {
  color: var(--color-ink);
  width: 100%;
  /* Reserves height for the tallest any statement wraps to at each
     breakpoint (measured empirically — "Meaningful Impact." is the
     long pole) so the typewriter reveal growing the string never
     shifts .hero__description/.hero__cta below it. Base/desktop: 2
     lines is enough headroom; responsive.css tightens or loosens
     this per breakpoint where measured wrap counts differ. */
  min-height: calc(2 * var(--fs-display-lg));
}

.hero__headline-typed {
  display: block;
}

/* Always its own block row — the line break between "I <word>" and
   the rest of the statement must never depend on natural text wrap
   (a wide/narrow viewport could otherwise collapse them onto one
   line, or wrap either line unpredictably). */
.hero__headline-line {
  display: block;
}

.hero__typed-cursor {
  display: inline-block;
  margin-left: 0.02em;
  color: var(--color-accent);
  animation: hero-cursor-blink 1s steps(1, end) infinite;
}

@keyframes hero-cursor-blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .hero__typed-cursor {
    animation: none;
    opacity: 0;
  }
}

.hero__description {
  display: flex;
  flex-wrap: wrap;
  gap: 68px;
  width: 100%;
}

.hero__tagline {
  color: var(--color-ink);
  max-width: 630px;
}

.hero__bio {
  color: var(--color-ink);
  max-width: 582px;
  line-height: 1.75;
}

.hero__bio a {
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color var(--dur-fast) var(--ease-standard);
}

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

/* ---- Video Showcase ---- */
.showreel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 26px;
}

.showreel__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 26px;
  width: 100%;
  max-width: 768px;
}

.showreel__player {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 768 / 428;
  overflow: hidden;
  background: #111111;
}

.showreel__poster {
  position: absolute;
  inset: 0;
}

.showreel__poster-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Figma's default render shows neither this nor .showreel__close — both
   are a hover/open affordance, revealed on hover, keyboard focus, or
   once the player is toggled open. */
.showreel__play-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 90px;
  height: 90px;
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-standard),
              transform var(--dur-base) var(--ease-standard);
}

.showreel__player:hover .showreel__play-icon,
.showreel__player:focus-visible .showreel__play-icon {
  opacity: 1;
}

.showreel__player:hover .showreel__play-icon {
  transform: translate(-50%, -50%) scale(1.05);
}

.showreel__close {
  position: absolute;
  top: 22px;
  right: 24px;
  font-family: var(--font-body);
  font-size: var(--fs-xl);
  color: var(--color-surface);
  text-transform: uppercase;
  padding-bottom: 4px;
  border-bottom: 2px solid var(--color-surface);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-standard);
}

.showreel__player[aria-expanded="true"] .showreel__close {
  opacity: 1;
}

.showreel__player[aria-expanded="true"] .showreel__play-icon {
  opacity: 0;
}

.showreel__title {
  font-family: var(--font-body);
  font-size: var(--fs-2xl);
  color: var(--color-ink);
}

/* ---- Featured Works ---- */
.works {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 40px;
  padding-block: var(--section-py);
  overflow: clip; /* belt-and-suspenders: track never causes page-level horizontal overflow */
}

.works__header {
  display: flex;
  flex-direction: column;
  gap: 9px;
  width: 100%;
}

.works__title,
.works__subtitle {
  color: var(--color-ink);
}

.works__subtitle {
  max-width: 521px;
}

/* ---- Horizontal scroll track ----
   Mobile-first base: plain vertical stack, identical to the section's
   original single-project layout — this is also the reduced-motion and
   no-overflow-desktop fallback (see responsive.css and featuredWorks.js).
   The min-width:1024px + no-preference-motion override turns this into
   the horizontal pinned track.

   .works__viewport and .works__track are deliberately UNPADDED at every
   breakpoint — featuredWorks.js measures track.scrollWidth against
   viewport.clientWidth to compute scroll distance, and clientWidth
   includes an element's own padding, so padding on either of them would
   throw that measurement off. The visual inset lives on .works__track
   (mobile) or on each .project-card (desktop track) instead — see below
   and responsive.css. */
.works__viewport {
  width: 100%;
}

.works__track {
  display: flex;
  flex-direction: column;
  gap: 40px;
  width: 100%;
  padding-inline: var(--section-px);
}

.project-card {
  display: flex;
  align-items: center;
  gap: 36px;
  width: 100%;
  flex-wrap: wrap;
}

.project-card__content {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 40px;
  flex: 1 1 420px;
  max-width: 476px;
  align-self: stretch;
}

.project-card__text {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.project-card__header {
  display: flex;
  flex-direction: column;
  color: var(--color-ink);
  font-family: var(--font-display);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.project-card__index {
  font-size: var(--fs-lg);
}

.project-card__name,
.project-card__subname {
  line-height: 1;
}

.project-card__desc {
  color: var(--color-ink);
  max-width: 433px;
}

.project-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.project-card__cta {
  align-self: flex-start;
}

.project-card__media {
  flex: 1 1 480px;
  max-width: 768px;
  aspect-ratio: 768 / 440;
  overflow: hidden;
}

.project-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---- Side Projects ---- */
.side-projects {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 34px;
}

.side-projects__header {
  display: flex;
  flex-direction: column;
  color: var(--color-ink);
}

.side-projects__title {
  margin: 0;
}

.side-projects__subtitle {
  margin: 0;
  margin-top: -0.08em;
}

.side-project {
  display: flex;
  align-items: center;
  gap: 56px;
  width: 100%;
  flex-wrap: wrap;
}

.side-project__media {
  flex: 1 1 480px;
  max-width: 768px;
  aspect-ratio: 768 / 432;
  overflow: hidden;
}

.side-project__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.side-project__content {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 40px;
  flex: 1 1 380px;
  align-self: stretch;
}

.side-project__text {
  display: flex;
  flex-direction: column;
  gap: 16px;
  color: var(--color-ink);
}

.side-project__name {
  margin: 0;
}

.side-project__desc {
  max-width: 458px;
}

.side-project__cta {
  align-self: flex-start;
}

/* ---- Why Choose Me ----
   Deliberately not display:flex on the section itself —
   .why-choose__pin-wrap (a direct child) is a GSAP ScrollTrigger
   pin:true target at desktop, and GSAP's pin-spacer height
   calculation does not correctly reserve the pin's scroll distance
   when the pinned element's parent is a flex container (reproduced
   this in isolation previously). Plain block flow + margin-based
   spacing between the two top-level children avoids it entirely. */
.why-choose-me {
  padding-block: var(--section-py);
}

.why-choose-me > * + * {
  margin-top: 80px;
}

.why-choose__pin-wrap {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 40px;
  width: 100%;
}

.why-choose-me__title {
  color: var(--color-ink);
  width: 100%;
}

.why-choose-me__intro {
  display: flex;
  flex-direction: column;
  width: 100%;
  /* Figma specifies this intro block as pure black, distinct from the
     --color-ink navy used on every other section in this design */
  color: #000000;
}

.why-choose-me__statement {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--fs-xl);
  line-height: 1.3;
}

/* Mobile-first: single column. responsive.css adds 2 cols at tablet,
   3 at desktop, matching Figma's grid-cols-3 exactly at that width. */
.principle-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 40px;
  width: 100%;
  color: var(--color-ink);
}

.principle-card {
  display: flex;
  flex-direction: column;
  gap: 16px;
  background: var(--color-surface);
  padding: 32px;
}

.principle-card__number {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  letter-spacing: 0.02em;
}

.principle-card__title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-xl);
}

.principle-card__desc {
  font-size: var(--fs-md);
  line-height: 1.5;
}

/* ---- Marquee ("longscroll text" in Figma) ----
   Two identical copies back to back, each with its own trailing
   margin baked in as the repeat gap — that makes the two copies
   exactly equal width, so translateX(-50%) always loops seamlessly
   regardless of the text's actual rendered width (no JS measurement
   needed). Second copy is aria-hidden (decorative repeat); the first
   carries the real, screen-reader-visible text. */
.why-choose-me__marquee {
  width: 100%;
  overflow: hidden;
}

.why-choose-me__marquee-track {
  display: flex;
  width: max-content;
  animation: why-choose-marquee 24s linear infinite;
}

.why-choose-me__marquee-text {
  color: var(--color-ink);
  white-space: nowrap;
  flex-shrink: 0;
  margin-right: 80px;
}

@keyframes why-choose-marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .why-choose-me__marquee-track {
    animation: none;
  }

  .why-choose-me__marquee-text[aria-hidden="true"] {
    display: none;
  }
}

/* ---- My Expertise ---- */
.expertise {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 48px;
}

.expertise__title {
  color: var(--color-ink);
  width: 100%;
}

.expertise__body {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 48px;
  width: 100%;
}

.expertise__main {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 13px;
  flex: 1 1 500px;
  max-width: 629px;
}

.expertise__selector-wrap {
  position: relative;
  width: 100%;
  /* Establishes its own stacking context so the z-index:20 listbox
     inside it always paints above .expertise__content, even when
     that content has an active (or GSAP-residual, near-zero but
     non-"none") transform — a transform alone creates a stacking
     context too, and without this, later DOM order lets it win the
     paint order over the listbox despite the listbox's z-index. */
  z-index: 1;
}

.expertise__selector {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  border: 2px solid var(--color-ink);
  padding: 24px 28px;
  background: transparent;
  text-align: left;
}

.expertise__handle {
  position: absolute;
  width: 16px;
  height: 16px;
  background: var(--color-surface);
  border: 2px solid var(--color-ink);
}

.expertise__handle--tl { top: -9px; left: -9px; }
.expertise__handle--bl { bottom: -9px; left: -9px; }
.expertise__handle--tr { top: -9px; right: -9px; }
.expertise__handle--br { bottom: -9px; right: -9px; }

.expertise__selector-label {
  color: var(--color-accent);
}

.expertise__selector-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  margin-left: auto;
  flex-shrink: 0;
  transform: rotate(45deg);
  transition: transform var(--dur-base) var(--ease-standard);
}

.expertise__selector[aria-expanded="true"] .expertise__selector-icon {
  transform: rotate(225deg);
}

.expertise__listbox {
  position: absolute;
  top: calc(100% + 12px);
  left: 0;
  right: 0;
  z-index: 20;
  background: var(--color-surface);
  border: 2px solid var(--color-ink);
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-standard),
              transform var(--dur-base) var(--ease-standard);
}

.expertise__listbox.is-open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.expertise__option {
  padding: 16px 28px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: var(--fs-md);
  text-transform: uppercase;
  color: var(--color-ink);
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}

.expertise__option:hover,
.expertise__option:focus-visible,
.expertise__option[aria-selected="true"] {
  background: var(--color-bg);
  color: var(--color-accent);
  outline: none;
}

.expertise__content {
  display: flex;
  flex-direction: column;
  gap: 32px;
  width: 100%;
  color: var(--color-ink);
  transition: opacity var(--dur-base) var(--ease-standard),
              transform var(--dur-base) var(--ease-standard);
}

.expertise__content.is-swapping {
  opacity: 0;
  transform: translateY(-10px);
}

.expertise__group {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.expertise__statement {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--fs-lg);
}

.expertise__desc {
  line-height: 1.5;
}

.expertise__keywords {
  display: flex;
  flex-direction: column;
  gap: 24px;
  /* max-width: 400px; */
}

.expertise__keywords-intro {
  line-height: 1.6;
}

.expertise__keyword-list {
  padding-left: 24px;
  list-style: disc;
}

.expertise__keyword-list li {
  line-height: 32px;
}

.expertise__keyword-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.expertise__cta {
  margin-top: 48px;
}

.expertise__media {
  flex: 1 1 400px;
  max-width: 508px;
  aspect-ratio: 508 / 477;
  overflow: hidden;
  align-self: flex-end;
}

.expertise__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---- Worked With ---- */
.worked-with {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 80px;
}

.worked-with__title {
  color: var(--color-ink);
  width: 100%;
}

.worked-with__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 20px;
  width: 100%;
}

.worked-with__item {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 150px;
  padding: 32px;
  background: var(--color-surface);
}

.worked-with__mark {
  height: 100%;
  width: auto;
  object-fit: contain;
}

.worked-with__wordmark {
  height: 40%;
  width: auto;
  object-fit: contain;
}

/* ---- Footer ---- */
.footer {
  display: flex;
  flex-direction: column;
}

.footer__top {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 32px;
  padding-bottom: 40px;
}

.footer__intro {
  display: flex;
  flex-direction: column;
  gap: 29px;
  color: var(--color-ink);
}

.footer__social {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
}

.footer__social-link {
  height: auto;
  padding: 16px 40px;
}

.footer__bottom {
  display: flex;
  flex-direction: column;
  padding-top: 20px;
  border-top: 1px solid var(--color-border);
}

.footer__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  color: var(--color-ink-2);
}

.footer__credit {
  display: flex;
  align-items: center;
  gap: 8px;
}

.footer__credit-icon {
  width: 20px;
  height: 20px;
}

.footer__wordmark {
  color: var(--color-ink-2);
  width: 100%;
}
