/* =====================================================================
   StoriesMaker — design system v4
   Space Grotesk (display) + Inter (body). Warm off-white base,
   near-black ink, olive green primary accent, terracotta secondary.
   Change the variables below to retheme the whole site.
   ===================================================================== */

:root {
  --color-bg: #f6f3ec;
  --color-bg-alt: #eeeae0;
  --color-ink: #1e1b16;
  --color-ink-soft: #5c5750;
  --color-accent: #4b5a34;        /* olive green — primary */
  --color-accent-dark: #3a4628;
  --color-accent-2: #c1592b;      /* terracotta — secondary, sparing use */
  --color-border: #ddd8ca;
  --color-card: #ffffff;

  --font-display: "Space Grotesk", sans-serif;
  --font-body: "Inter", sans-serif;

  --max-width: 1160px;
  --radius: 6px;

  /* placeholder cover-frame tints, cycled per card until real cover
     frames are added — keeps thumbnails reading as one coherent set */
  --tint-1: #e4ddc9;
  --tint-2: #d9cdbd;
  --tint-3: #c9c4b3;
  --tint-4: #cdd6c6;
  --tint-5: #e0c9b8;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; }

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

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

.site-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 22px 24px;
  position: relative;
  /* keeps the nav (and its mobile dropdown) stacked above later page
     content like the hero — without this, a positioned section further
     down the page can render on top of the open mobile menu */
  z-index: 100;
}

.logo {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.2rem;
}

.nav-center {
  display: flex;
  align-items: center;
  gap: 26px;
}

.nav-links {
  display: flex;
  gap: 26px;
  font-size: 0.9rem;
}

.nav-links a {
  padding-bottom: 4px;
  border-bottom: 1px solid transparent;
}
.nav-links a:hover, .nav-links a.active { border-bottom-color: var(--color-accent); }

.nav-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--color-accent);
  color: #fff;
  padding: 10px 18px;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 500;
  border: none;
  cursor: pointer;
}
.nav-cta:hover { background: var(--color-accent-dark); }

.nav-toggle {
  display: none;
  background: none;
  border: none;
  font-size: 1.4rem;
  cursor: pointer;
}

@media (max-width: 780px) {
  .nav-links {
    position: absolute;
    top: 64px; left: 0; right: 0;
    background: var(--color-bg);
    flex-direction: column;
    gap: 0;
    padding: 6px 24px 18px;
    border-bottom: 1px solid var(--color-border);
    display: none;
    z-index: 100;
    box-shadow: 0 8px 16px rgba(30, 27, 22, 0.08);
  }
  .nav-links.open { display: flex; }
  .nav-links a { padding: 10px 0; }
  .nav-toggle { display: block; order: 3; }
  .nav-cta { display: none; }
}

/* ---------------- Type helpers ---------------- */

.eyebrow {
  display: flex;
  align-items: center;
  gap: 8px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--color-ink-soft);
  margin-bottom: 16px;
}
.eyebrow::before {
  content: "";
  width: 8px; height: 8px;
  background: var(--color-accent);
  display: inline-block;
}

h1, h2, h3 { font-family: var(--font-display); font-weight: 700; margin: 0; }

h1 {
  font-size: clamp(2.1rem, 5vw, 3.1rem);
  line-height: 1.12;
}
h1 em, h2 em, h3 em { font-style: italic; color: var(--color-accent); }
.fade { color: var(--color-ink-soft); font-weight: 500; }

.intro { max-width: 48ch; color: var(--color-ink-soft); font-size: 1.02rem; }

/* ---------------- Buttons ---------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--color-accent);
  color: #fff;
  padding: 14px 24px;
  border-radius: 999px;
  font-size: 0.88rem;
  font-weight: 500;
  border: none;
  cursor: pointer;
}
.btn:hover { background: var(--color-accent-dark); }
.link-arrow { font-size: 0.9rem; border-bottom: 1px solid var(--color-ink); padding-bottom: 2px; }

/* ---------------- Page header ---------------- */

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 40px;
  padding: 44px 0 34px;
  flex-wrap: wrap;
}
.page-header .intro { padding-top: 10px; }

/* ---------------- Video cards ---------------- */

.video-card {
  position: relative;
  flex: 0 0 auto;
  border-radius: var(--radius);
  overflow: hidden;
  cursor: pointer;
  border: none;
  background: none;
  text-align: left;
  padding: 0;
  display: block;
}

/* Uniform crop: every card — portrait or landscape source — shows in the
   same 4:3 frame via object-fit:cover, so the grid reads as one evenly
   sized set instead of mixed portrait/landscape widths. */
.video-thumb {
  aspect-ratio: 4 / 3;
  height: auto;
  border-radius: var(--radius);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
}

.play-icon {
  width: 46px; height: 46px;
  border-radius: 50%;
  background: rgba(30, 27, 22, 0.72);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.95rem;
}

.video-meta { padding: 14px 2px 0; }
.video-meta h3 {
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.28;
  margin-bottom: 2px;
  /* wraps to up to 2 full lines (no cut-off mid-word) instead of
     truncating to 1 — and reserves exactly 2 lines' worth of height
     always, so every card's title takes the same space whether it needs
     1 line or 2. That's what keeps the subtitle/tag row, and the
     thumbnails above them, lined up evenly across a row. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  text-overflow: ellipsis;
  min-height: 2.56em;
}
.video-subtitle {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--color-ink-soft);
  margin-bottom: 8px;
  min-height: 2.7em;
}
.video-tag {
  display: inline-block;
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
  background: var(--color-bg-alt);
  padding: 3px 9px;
  border-radius: 999px;
}

.thumb-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.play-icon { z-index: 1; }

/* Featured carousel (scroll-snap row) */
.carousel-wrap { position: relative; margin-bottom: 56px; }
.carousel {
  display: flex;
  align-items: flex-start;
  gap: 26px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-bottom: 8px;
}
.carousel .video-card {
  scroll-snap-align: start;
  /* uniform width for every card, portrait or landscape source — matches
     the uniform 4:3 thumb crop above so the whole row reads as one evenly
     sized set (also prevents a longer subtitle spilling into the next card) */
  width: 240px;
}
.carousel-nav {
  position: absolute;
  top: 40%;
  width: 100%;
  display: flex;
  justify-content: space-between;
  pointer-events: none;
}
.carousel-nav button {
  pointer-events: all;
  width: 38px; height: 38px;
  border-radius: 50%;
  border: 1px solid var(--color-border);
  background: var(--color-bg);
  cursor: pointer;
  transform: translateX(-14px);
}
.carousel-nav button:last-child { transform: translateX(14px); }

/* More stories list */
.more-header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 18px; }
.more-header h2 { font-size: 1.25rem; }
.more-grid {
  display: grid;
  /* fixed 240px columns — matches .carousel .video-card's width exactly,
     so Featured and More Stories cards read as the same size */
  grid-template-columns: repeat(auto-fill, 240px);
  align-items: start;
  gap: 26px 20px;
  margin-bottom: 20px;
}
/* (More Stories cards inherit the same uniform 4:3 crop from .video-thumb above) */

/* Filter pills */
.filter-pills { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 34px; }
.filter-pills button {
  border: 1px solid var(--color-border);
  background: transparent;
  padding: 9px 17px;
  border-radius: 999px;
  font-size: 0.82rem;
  cursor: pointer;
}
.filter-pills button.active { background: var(--color-accent); color: #fff; border-color: var(--color-accent); }

/* ---------------- Lightbox ---------------- */

.lightbox {
  position: fixed; inset: 0;
  background: rgba(15, 13, 10, 0.92);
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  z-index: 1000;
  padding: 24px;
}
.lightbox.open { display: flex; }
/* Video and caption stack in normal flow (not overlapping) — video height
   is capped to leave guaranteed room for the caption below it. */
.lightbox video { border-radius: var(--radius); }
.lightbox video.portrait { height: 68vh; width: auto; max-width: 90vw; }
.lightbox video.landscape { width: 90vw; max-width: 860px; height: auto; max-height: 68vh; }
.lightbox-close {
  position: absolute; top: 22px; right: 26px;
  width: 40px; height: 40px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.3);
  background: transparent;
  color: #fff;
  font-size: 1.1rem;
  cursor: pointer;
  z-index: 1;
}
.lightbox-caption {
  max-width: 560px;
  text-align: center;
  padding: 0 12px;
}
.lightbox-caption h3 {
  font-family: var(--font-display);
  font-size: 1rem;
  color: #fff;
  margin-bottom: 4px;
}
.lightbox-caption p {
  font-size: 0.85rem;
  color: #d8d3c8;
  margin: 0;
}
.lightbox-rights {
  display: none;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}
.lightbox-rights .rights-text {
  font-size: 0.72rem;
  line-height: 1.55;
  color: #a89f8f;
  margin: 0 0 8px;
}
.lightbox-rights .rights-link {
  display: inline-block;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-accent-2);
  border-bottom: 1px solid var(--color-accent-2);
  padding-bottom: 2px;
}

/* ---------------- Home hero ---------------- */

.hero {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  margin-top: 20px;
  min-height: 520px;
  display: flex;
  align-items: flex-end;
  background: linear-gradient(160deg, #2b2620, #17140f);
}
.hero-photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0.55; }

/* Soft floating color blobs — fill the otherwise-empty dark space with
   slow motion until real photography/illustration replaces this hero. */
.hero-blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  opacity: 0.4;
  pointer-events: none;
  animation: heroFloat 16s ease-in-out infinite;
}
.hero-blob-a {
  width: 380px; height: 380px;
  background: radial-gradient(circle, var(--color-accent) 0%, transparent 70%);
  top: -100px; left: 32%;
}
.hero-blob-b {
  width: 320px; height: 320px;
  background: radial-gradient(circle, var(--color-accent-2) 0%, transparent 70%);
  bottom: -110px; right: 8%;
  animation-delay: -8s;
}
@keyframes heroFloat {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(26px, -18px) scale(1.08); }
}

/* Big faint outline word — a typographic device to give the hero some
   graphic weight without needing a photo or illustration. */
.hero-word {
  position: absolute;
  right: -30px;
  bottom: -36px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(6rem, 17vw, 12.5rem);
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1.5px rgba(255, 255, 255, 0.14);
  letter-spacing: -0.02em;
  pointer-events: none;
  user-select: none;
}

.hero-copy { position: relative; padding: 44px; color: #fff; max-width: 640px; }
.hero-copy .eyebrow { color: #cfc9bd; }
.hero-copy .eyebrow::before { background: var(--color-accent-2); }
.hero-copy h1 { color: #fff; }
.hero-copy h1 em { color: var(--color-accent-2); }
.hero-copy .intro { color: #d8d3c8; margin: 14px 0 26px; max-width: 42ch; }
.scroll-hint {
  display: block;
  margin-top: 22px;
  font-size: 0.7rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: #b9b2a3;
}

/* "Trusted by" strip under the hero — fills the follow-through space
   with real credibility instead of empty air. Names match the venues
   already named on the video cards, so nothing here is new information. */
.trust-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 14px;
  padding: 22px 0;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 6px;
  font-size: 0.78rem;
  color: var(--color-ink-soft);
}
.trust-strip .trust-label {
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 600;
  color: var(--color-ink);
  flex-shrink: 0;
}

.hero-side {
  position: absolute;
  right: 40px;
  bottom: 34px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
}
.hero-side .mascot-bubble {
  background: rgba(255, 255, 255, 0.92);
  color: var(--color-ink);
  padding: 8px 14px;
  border-radius: 999px 999px 4px 999px;
  font-size: 0.8rem;
  font-family: var(--font-display);
}

/* mascot — simple SVG placeholder with cursor-tracking eyes.
   Swap the <svg class="mascot"> markup in the HTML for the final
   illustrated character once ready — keep the "pupil" class on
   whatever should track the cursor and these part classes still work
   if the new art reuses them. */
.mascot { width: 108px; }
.mascot .pupil { fill: var(--color-ink); transition: transform 0.08s linear; }
.mascot-ear-a { fill: var(--color-accent); }
.mascot-ear-b { fill: var(--color-accent-2); }
.mascot-head { fill: #fff; stroke: var(--color-ink); stroke-width: 2; }
.mascot-nose { fill: var(--color-accent-2); }
.mascot-whisker { stroke: var(--color-ink); stroke-width: 1.5; }
.mascot-mouth { fill: none; stroke: var(--color-ink); stroke-width: 2; stroke-linecap: round; }
.mascot-cheek { fill: var(--color-accent-2); opacity: 0.3; }

.hero-side .mascot {
  width: 120px;
  align-self: flex-end;
  animation: mascotBob 4.5s ease-in-out infinite;
}
@keyframes mascotBob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-9px); }
}
.step-mascot.mascot { width: 68px; }

@media (max-width: 860px) {
  /* Stack instead of overlay: below this width, hero-side (mascot +
     speech bubble) was absolutely positioned over the same bottom-left
     corner as the CTA button/scroll-hint, causing them to overlap. Making
     the hero a column flow puts hero-side in normal document flow right
     after hero-copy instead — same visual order, no collision. */
  .hero {
    min-height: unset;
    flex-direction: column;
    align-items: stretch;
  }
  .hero-copy { padding: 28px 24px 20px; max-width: none; }
  .hero-side {
    position: static;
    align-items: flex-end;
    padding: 0 24px 26px;
  }
  .hero-side .mascot { width: 66px; }
  .hero-word { display: none; }
  .hero-blob { opacity: 0.25; }
}

.home-followup { text-align: center; padding: 56px 24px 10px; max-width: 640px; margin: 0 auto; }
.home-followup h2 { font-size: clamp(1.5rem, 4vw, 2.1rem); margin-bottom: 14px; }
.home-followup p { color: var(--color-ink-soft); margin-bottom: 26px; }

/* ---------------- Studio ---------------- */

.studio-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; padding: 40px 0; align-items: start; }
.studio-belief p { color: var(--color-ink-soft); margin-bottom: 16px; }
blockquote.pull-quote {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.15rem;
  border-left: 3px solid var(--color-accent);
  padding: 4px 0 4px 20px;
  margin: 22px 0;
}
.team-photo { margin: 32px 0 22px; border-radius: var(--radius); overflow: hidden; }
.team-photo .video-thumb { height: 340px; aspect-ratio: unset; }

/* Animated "film strip" banner — a row of storyboard frames, each with
   its own small story icon (camera, voice, narrative, feeling, moment,
   journey), and a highlighted playhead that jumps from frame to frame,
   like scanning through footage scene by scene, while the icon it lands
   on pulses to life. Unmistakably about video storytelling (StoriesMaker's
   actual medium), not an abstract chart. Built in JS (initFilmstrip in
   main.js), which re-measures the real rendered frames on every tick so
   the playhead is always pixel-aligned to exactly one frame; parks on
   the middle frame, no motion, under prefers-reduced-motion. */
.filmstrip-banner {
  background: linear-gradient(135deg, var(--color-bg-alt), var(--tint-3) 140%);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 5%;
}
.filmstrip {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
}
.filmstrip .frame {
  position: relative;
  flex: 1 1 0;
  aspect-ratio: 4 / 3;
  border-radius: 4px;
  border: 2px solid rgba(30, 27, 22, 0.1);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.filmstrip .frame::before,
.filmstrip .frame::after {
  content: "";
  position: absolute;
  left: 6px;
  right: 6px;
  height: 3px;
  border-radius: 1px;
  background: rgba(30, 27, 22, 0.14);
}
.filmstrip .frame::before { top: 6px; }
.filmstrip .frame::after { bottom: 6px; }
.filmstrip .frame-icon {
  width: 24px;
  height: 24px;
  color: var(--color-ink);
  opacity: 0.3;
  transform: scale(1);
  transition: transform 0.3s ease, opacity 0.3s ease;
}
.filmstrip .frame.active .frame-icon {
  color: var(--color-accent-2);
  opacity: 0.85;
  transform: scale(1.22);
}
.filmstrip .playhead {
  position: absolute;
  top: -6px;
  bottom: -6px;
  border-radius: 7px;
  border: 3px solid var(--color-accent-2);
  box-shadow: 0 4px 14px rgba(193, 89, 43, 0.28);
  pointer-events: none;
  transition: left 0.15s ease, width 0.15s ease;
}

@media (max-width: 600px) {
  .team-photo .video-thumb { height: 220px; }
  .filmstrip { gap: 8px; }
  .filmstrip .frame { border-width: 1.5px; }
}

/* Placeholder frame for real photography not yet shot — a warm gradient
   instead of a flat tint, so it reads as "photo coming soon" rather than
   a broken/empty box. Swap for a real <img> the moment photos are ready. */
.photo-placeholder {
  background: linear-gradient(135deg, var(--tint-2), var(--tint-4)) !important;
  position: relative;
}
.photo-placeholder::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 30% 25%, rgba(255,255,255,0.5), transparent 55%);
}
.photo-placeholder span {
  position: relative;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 0.85rem !important;
  color: var(--color-ink-soft) !important;
}
.role-row { display: flex; gap: 24px; flex-wrap: wrap; }
.role-row > div { flex: 1; min-width: 160px; }
.role-row h4 { font-size: 0.95rem; margin-bottom: 6px; }
.role-row p { font-size: 0.85rem; color: var(--color-ink-soft); }
.role-dot { width: 8px; height: 8px; background: var(--color-accent-2); display: inline-block; margin-right: 8px; }

@media (max-width: 860px) { .studio-grid { grid-template-columns: 1fr; } }

/* ---------------- How We Work ---------------- */

.process { list-style: none; margin: 40px 0; padding: 0; display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
.process li { border: 1px solid var(--color-border); border-radius: var(--radius); padding: 24px; }
.step-badge {
  width: 40px; height: 40px;
  border-radius: 50%;
  background: var(--color-accent);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-family: var(--font-display);
  margin-bottom: 14px;
}
.step-mascot { width: 68px; height: 68px; margin-bottom: 10px; }
.process h3 { font-size: 1.02rem; margin-bottom: 8px; }
.process p { font-size: 0.88rem; color: var(--color-ink-soft); margin: 0; }
.process-arrow { display: none; }

@media (max-width: 900px) { .process { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .process { grid-template-columns: 1fr; } }

/* ---------------- Contact ---------------- */

.contact-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; padding: 40px 0 70px; }
.contact-form { display: flex; flex-direction: column; gap: 14px; margin-top: 22px; }
.contact-form input, .contact-form textarea {
  padding: 14px 16px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: #fff;
  font-family: var(--font-body);
  font-size: 0.95rem;
}
.contact-form textarea { min-height: 120px; resize: vertical; }
.contact-form button { align-self: flex-start; }
.contact-visual { border-radius: var(--radius); overflow: hidden; min-height: 380px; }
.contact-visual img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Honeypot field for the contact form — invisible and unreachable to
   real visitors (off-screen, not just display:none, so it still
   "exists" for careless bots to fill in), skipped entirely by anyone
   using a keyboard or screen reader. */
.hp-field {
  position: absolute !important;
  left: -9999px !important;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Success/error banner shown after contact-handler.php redirects back
   here with ?sent=ok or ?sent=error — see initContactFormStatus() in
   main.js. */
.form-status {
  margin: 0 0 16px;
  padding: 12px 16px;
  border-radius: var(--radius);
  font-size: 0.9rem;
  line-height: 1.5;
}
.form-status-ok {
  background: rgba(75, 90, 52, 0.12);
  color: var(--color-accent-dark);
  border: 1px solid rgba(75, 90, 52, 0.28);
}
.form-status-error {
  background: rgba(193, 89, 43, 0.12);
  color: var(--color-accent-2);
  border: 1px solid rgba(193, 89, 43, 0.3);
}

@media (max-width: 780px) { .contact-grid { grid-template-columns: 1fr; } }

/* ---------------- Motion: entrance + scroll reveal ----------------
   Two small, reusable systems instead of a page-specific animation:
   1. "enter" classes play once on load (nav, hero, page headers).
   2. .reveal / .revealed is driven by IntersectionObserver in main.js —
      any element gets data-reveal in the HTML (or the class is added by
      JS for dynamically-rendered video cards) and fades/slides in the
      first time it scrolls into view.
   Both are fully disabled under prefers-reduced-motion (see bottom). */

@keyframes fadeSlideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } }
@keyframes fadeSlideUp   { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }

.nav-enter { animation: fadeSlideDown 0.6s cubic-bezier(.16,1,.3,1) both; }

.enter { opacity: 0; animation: fadeSlideUp 0.7s cubic-bezier(.16,1,.3,1) forwards; }
.enter-1 { animation-delay: 0.05s; }
.enter-2 { animation-delay: 0.16s; }
.enter-3 { animation-delay: 0.28s; }
.enter-4 { animation-delay: 0.42s; }
.enter-5 { animation-delay: 0.56s; }

.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.6s cubic-bezier(.16,1,.3,1), transform 0.6s cubic-bezier(.16,1,.3,1);
}
.reveal.revealed { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  .nav-enter, .enter, .reveal {
    animation: none !important;
    transition: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

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

.site-footer { border-top: 1px solid var(--color-border); padding: 26px 0 40px; margin-top: 40px; }
.footer-inner { display: flex; justify-content: space-between; align-items: flex-end; flex-wrap: wrap; gap: 10px; font-size: 0.82rem; color: var(--color-ink-soft); }
