/* =========================================================
   components.css — nav, cards, footer, buttons, carousel,
   and other shared UI
   ========================================================= */

/* =========================================================
   Header / Nav (§2, §7, §6.9)
   ========================================================= */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  height: var(--header-h);
  display: flex;
  align-items: center;
  background: transparent;
  transition: background var(--dur-med) var(--ease-out),
    border-color var(--dur-med) var(--ease-out);
  border-bottom: 1px solid transparent;
}

/* Solidifies (cream) after scroll threshold — toggled by nav.js.
   NOTE: intentionally no backdrop-filter here. A filter on the header would
   make it the containing block for the fixed mobile menu, clipping it to the
   header height. A near-opaque background gives the same effect without that. */
.site-header.is-scrolled {
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  border-bottom-color: var(--line);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  max-width: var(--bp-xl);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.brand {
  font-family: var(--font-display);
  font-weight: var(--fw-title);
  font-size: 1rem;
  letter-spacing: -0.01em;
}

.nav {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.nav__link {
  position: relative;
  font-size: var(--fs-nav);
  font-weight: var(--fw-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  padding-block: var(--space-1);
}

/* Nav underline grows 0 -> 100% (§6.5) */
.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-fast) var(--ease-out);
}

.nav__link:hover::after,
.nav__link:focus-visible::after,
.nav__link[aria-current="page"]::after {
  transform: scaleX(1);
}

/* Mobile menu toggle */
.nav-toggle {
  display: none;
  width: 2.5rem;
  height: 2.5rem;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 120;
}

.nav-toggle__bar,
.nav-toggle__bar::before,
.nav-toggle__bar::after {
  content: "";
  display: block;
  width: 22px;
  height: 2px;
  background: var(--text);
  transition: transform var(--dur-fast) var(--ease-out),
    opacity var(--dur-fast) var(--ease-out);
}

.nav-toggle__bar::before {
  position: absolute;
  transform: translateY(-7px);
}

.nav-toggle__bar::after {
  position: absolute;
  transform: translateY(7px);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar {
  background: transparent;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar::before {
  transform: translateY(0) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar::after {
  transform: translateY(0) rotate(-45deg);
}

/* Mobile nav (under --bp-md) */
@media (max-width: 767.98px) {
  .nav-toggle {
    display: flex;
  }

  .nav {
    position: fixed;
    inset: 0;
    flex-direction: column;
    justify-content: center;
    gap: var(--space-4);
    background: color-mix(in srgb, var(--bg) 96%, transparent);
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
    transform: translateY(-100%);
    opacity: 0;
    visibility: hidden;
    transition: transform var(--dur-med) var(--ease-out),
      opacity var(--dur-med) var(--ease-out),
      visibility var(--dur-med) var(--ease-out);
  }

  .nav.is-open {
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
  }

  .nav__link {
    font-size: var(--fs-h3);
  }
}

/* =========================================================
   Footer (§7)
   ========================================================= */
.site-footer {
  flex-shrink: 0;
  border-top: 1px solid var(--line);
  padding-block: var(--space-4);
  margin-top: var(--space-6);
}

.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  align-items: center;
  justify-content: space-between;
}

.site-footer .label {
  color: var(--text-mute);
}

.back-to-top {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--fs-nav);
  font-weight: var(--fw-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.back-to-top:hover {
  color: var(--text);
}

/* =========================================================
   Buttons / link buttons (§7 detail pages)
   ========================================================= */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--fs-nav);
  font-weight: var(--fw-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  padding: 0.75rem 1.25rem;
  border: 1px solid var(--text);
  border-radius: var(--radius);
  transition: background var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out);
}

.btn:hover,
.btn:focus-visible {
  background: var(--text);
  color: var(--bg);
}

/* Fixed corner controls on detail pages */
.corner-btn {
  position: fixed;
  top: calc(var(--header-h) + var(--space-1));
  z-index: 90;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--fs-nav);
  font-weight: var(--fw-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  padding: 0.6rem 1rem;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.corner-btn--back {
  left: var(--gutter);
}

.corner-btn:hover,
.corner-btn:focus-visible {
  border-color: var(--text);
}

/* =========================================================
   Work grid + cards (§7)
   ========================================================= */
.grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4) var(--grid-gap);
}

@media (min-width: 768px) {
  .grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1080px) {
  .grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.card {
  display: block;
  position: relative;
}

.card__media {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--bg-alt);
  aspect-ratio: 4 / 3;
}

.card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-med) var(--ease-out);
}

/* Software card: subtle scale-up on hover/focus */
.card--software:hover .card__img,
.card--software:focus-visible .card__img {
  transform: scale(1.03);
}

/* Software thumbnails: uniform height, uncropped. Wide images fill the
   width; tall images cap at the same height and simply get narrower
   (centered), so the whole image is always visible. */
.grid[data-type="software"] {
  align-items: start;
}

.card--software .card__media {
  aspect-ratio: auto;
  height: clamp(220px, 24vw, 340px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-3);
  background: var(--bg-alt);
}

.card--software .card__img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

/* Film card: centered play icon fades in on hover/focus (§9) */
.card__play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out);
  pointer-events: none;
}

.card__play svg {
  width: 64px;
  height: 64px;
  filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.35));
}

.card--film:hover .card__play,
.card--film:focus-visible .card__play {
  opacity: 1;
}

.card__meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.card__title {
  min-width: 0;
  font-family: var(--font-display);
  font-weight: var(--fw-subhead);
  font-size: var(--fs-h3);
  line-height: 1.15;
}

.card__tag {
  flex-shrink: 0;
  font-size: var(--fs-nav);
  font-weight: var(--fw-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-mute);
  text-align: right;
}

/* Film tags (client · role) are long — stack them under the title,
   left-aligned, so they never crowd or overlap the title. */
.card--film .card__meta {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-1);
}

.card--film .card__tag {
  text-align: left;
}

/* Distinguish client (emphasis) from role (muted) in the film tag. */
.card__client {
  color: var(--text);
  font-weight: var(--fw-subhead);
}

.card__role {
  color: var(--text-mute);
  font-weight: var(--fw-label);
}

.card__sep {
  color: var(--line);
}

/* Entrance animation (§6.3) — applied by grid.js */
.reveal {
  opacity: 0;
  transform: translateY(16px);
}

.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out);
}

/* =========================================================
   States: loading / empty / not found
   ========================================================= */
.state {
  padding-block: var(--space-6);
  text-align: center;
  color: var(--text-mute);
}

/* =========================================================
   Screenshot carousel (software detail, §7)
   ========================================================= */
.carousel {
  position: relative;
}

.carousel__track {
  display: flex;
  gap: var(--space-3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: var(--space-1);
  cursor: grab;
}

.carousel__track::-webkit-scrollbar {
  display: none;
}

.carousel__track.is-dragging {
  cursor: grabbing;
  scroll-behavior: auto;
  scroll-snap-type: none;
}

.carousel__slide {
  flex: 0 0 auto;
  scroll-snap-align: center;
  border-radius: var(--radius);
  overflow: hidden;
  background: transparent;
}

/* Size the slide by height so screenshots render at full height, never
   cropped. Width follows the image's aspect ratio (capped to the viewport
   so an extremely wide image can't overflow the screen). */
.carousel__slide img {
  display: block;
  height: min(78vh, 760px);
  width: auto;
  max-width: 92vw;
  object-fit: contain;
  -webkit-user-drag: none;
  user-select: none;
}

.carousel__controls {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.carousel__arrow {
  width: 3rem;
  height: 3rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--text);
  border-radius: 999px;
  transition: background var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out),
    opacity var(--dur-fast) var(--ease-out);
}

.carousel__arrow:hover:not(:disabled),
.carousel__arrow:focus-visible:not(:disabled) {
  background: var(--text);
  color: var(--bg);
}

.carousel__arrow:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.carousel__arrow svg {
  width: 20px;
  height: 20px;
}

.carousel__counter {
  font-size: var(--fs-nav);
  font-weight: var(--fw-label);
  letter-spacing: var(--tracking-label);
  color: var(--text-mute);
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}

.carousel__dots {
  display: flex;
  gap: var(--space-1);
}

.carousel__dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--line);
  transition: background var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out);
}

.carousel__dot.is-active {
  background: var(--text);
  transform: scale(1.25);
}

/* =========================================================
   Reduced motion (§6, §9)
   ========================================================= */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .reveal {
    opacity: 1;
    transform: none;
  }
}
