/* =====================================================================
   SULAYMON RUZIBOEV — PORTFOLIO
   Design system + components. Dark-first, one accent, editorial type.
   ---------------------------------------------------------------------
   1.  Tokens
   2.  Reset & base
   3.  Typography primitives
   4.  Layout primitives
   5.  Cursor / preloader
   6.  Header + menu overlay
   7.  Buttons & links
   8.  Hero (WebGL)
   9.  Marquee
   10. Section headers
   11. Work grid + cards
   12. Services
   13. Stats / marquee strip
   14. Lightbox
   15. Page hero (inner pages)
   16. About page
   17. Contact page
   18. Footer
   19. Reveal / motion
   20. Responsive
   ===================================================================== */

/* ========================= 1. TOKENS ========================= */
:root {
  /* Surface ramp — near-black, slightly cool */
  --bg:        #08080a;
  --bg-2:      #0e0e11;
  --surface:   #141418;
  --surface-2: #1c1c21;

  /* Ink ramp */
  --ink:   #f4f4f2;
  --ink-2: rgba(244, 244, 242, 0.62);
  --ink-3: rgba(244, 244, 242, 0.38);
  --ink-4: rgba(244, 244, 242, 0.16);

  /* Hairlines */
  --line:      rgba(255, 255, 255, 0.09);
  --line-soft: rgba(255, 255, 255, 0.05);

  /* Accent — ember. One hue, used sparingly. */
  --accent:      #ff6b12;
  --accent-soft: #ff8f45;
  --accent-dim:  rgba(255, 107, 18, 0.14);

  /* Type */
  --font-display: "Anton", "Oswald", Impact, sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Modular scale (fluid) */
  --t-mega:  clamp(3.2rem, 11vw, 11rem);
  --t-xxl:   clamp(2.4rem, 6.5vw, 6rem);
  --t-xl:    clamp(1.9rem, 4vw, 3.4rem);
  --t-lg:    clamp(1.35rem, 2.2vw, 1.9rem);
  --t-md:    clamp(1rem, 1.15vw, 1.125rem);
  --t-sm:    0.9375rem;
  --t-xs:    0.8125rem;
  --t-micro: 0.6875rem;

  /* Space */
  --s-1: 0.5rem;  --s-2: 1rem;   --s-3: 1.5rem;  --s-4: 2rem;
  --s-5: 3rem;    --s-6: 4rem;   --s-7: 6rem;    --s-8: 9rem;
  --gutter: clamp(1.25rem, 5vw, 5.5rem);
  --maxw: 1560px;

  /* Motion */
  --ease-out:  cubic-bezier(0.22, 1, 0.36, 1);
  --ease-io:   cubic-bezier(0.65, 0, 0.35, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
  --dur-1: 0.18s; --dur-2: 0.35s; --dur-3: 0.6s; --dur-4: 1.1s;

  --radius: 4px;
  --header-h: 84px;
}

/* ========================= 2. RESET & BASE ========================= */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html {
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Reserve the scrollbar gutter always. The justified grid solves card
     widths from the container width; if the scrollbar appears afterwards
     the container narrows and every row overflows and wraps. */
  scrollbar-gutter: stable;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-md);
  line-height: 1.6;
  font-feature-settings: "kern" 1, "liga" 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

img, video, svg, canvas { display: block; max-width: 100%; }
img, video { height: auto; }

a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
input, textarea, select { font: inherit; color: inherit; }

::selection { background: var(--accent); color: #fff; }

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

/* Scrollbar */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: #2a2a30; border: 3px solid var(--bg); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: #3a3a42; }

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

.skip-link {
  position: fixed; top: 0; left: 50%; transform: translate(-50%, -120%);
  background: var(--accent); color: #fff; padding: 0.75rem 1.5rem;
  z-index: 10000; font-weight: 600; transition: transform var(--dur-2) var(--ease-out);
}
.skip-link:focus { transform: translate(-50%, 0); }

/* ========================= 3. TYPOGRAPHY ========================= */
.display {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 0.86;
  letter-spacing: -0.015em;
  text-transform: uppercase;
}

.t-mega { font-size: var(--t-mega); }
.t-xxl  { font-size: var(--t-xxl); }
.t-xl   { font-size: var(--t-xl); }

.eyebrow {
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3);
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
}
.eyebrow::before {
  content: "";
  width: 28px; height: 1px;
  background: var(--accent);
  flex: none;
}
.eyebrow--plain::before { display: none; }

.lead {
  font-size: clamp(1.05rem, 1.5vw, 1.375rem);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 62ch;
}

.muted { color: var(--ink-2); }
.accent { color: var(--accent); }

/* Ink-fill accent word */
.hl { color: var(--accent); }

/* ========================= 4. LAYOUT ========================= */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: clamp(4.5rem, 11vh, 9rem); position: relative; }
.section--tight { padding-block: clamp(3rem, 7vh, 5rem); }
.section--alt { background: var(--bg-2); }

.rule { height: 1px; background: var(--line); border: 0; }

/* ========================= 5. CURSOR / PRELOADER ========================= */
/* Cursor trail canvas.
   NO mix-blend-mode. This element covers the whole viewport, and a blend
   mode on it forces every pixel underneath into a blended compositing
   group — tinting artwork and altering text rasterisation across the
   entire site, even while the canvas itself is empty. The particles are
   painted normally instead. */
.cursor-fx {
  position: fixed; inset: 0;
  z-index: 9500;
  pointer-events: none;
}

/* Page transition curtain.
   Columns wipe up to cover on the way out, then wipe up and away on the
   next page. Inert (scaleY 0, no pointer events) unless a transition is
   actually running, so it can never trap clicks. */
.pt {
  position: fixed; inset: 0;
  z-index: 9700;
  pointer-events: none;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
}
/* scaleX(1.02) makes each column overrun its grid track so neighbours
   overlap. Without it, fractional track widths plus transform antialiasing
   leave hairline seams between the panels. */
.pt__col {
  background: #ffffff;
  transform: scale(1.02, 0);
  transform-origin: bottom;
  will-change: transform;
}

/* leaving: grow up from the bottom */
.pt.is-out .pt__col {
  transform: scale(1.02, 1);
  transform-origin: bottom;
  transition: transform 0.42s var(--ease-io);
  transition-delay: calc(var(--i) * 0.045s);
}
/* arriving: start covered, retract upward */
.pt.is-cover .pt__col { transform: scale(1.02, 1); transform-origin: top; }
.pt.is-in .pt__col {
  transform: scale(1.02, 0);
  transform-origin: top;
  transition: transform 0.55s var(--ease-out);
  transition-delay: calc((4 - var(--i)) * 0.045s);
}

@media (prefers-reduced-motion: reduce) {
  .pt { display: none; }
}

/* Preloader */
.preloader {
  position: fixed; inset: 0; z-index: 9800;
  background: var(--bg);
  display: grid; place-items: center;
  transition: opacity 0.7s var(--ease-out), visibility 0.7s;
}
.preloader.is-done { opacity: 0; visibility: hidden; }

.preloader__inner { width: min(360px, 70vw); text-align: center; }
.preloader__mark {
  font-family: var(--font-display);
  font-size: clamp(2rem, 6vw, 3.4rem);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1;
  margin-bottom: 1.4rem;
}
.preloader__mark span { display: inline-block; }
.preloader__bar {
  height: 1px; background: var(--ink-4); position: relative; overflow: hidden;
}
.preloader__fill {
  position: absolute; inset: 0 100% 0 0;
  background: var(--accent);
  transition: right 0.25s linear;
}
.preloader__pct {
  margin-top: 0.9rem;
  font-size: var(--t-micro); letter-spacing: 0.2em;
  color: var(--ink-3); font-variant-numeric: tabular-nums;
}

/* ========================= 6. HEADER + MENU ========================= */
.header {
  position: fixed; top: 0; left: 0; right: 0;
  z-index: 8000;
  padding-block: 1.35rem;
  transition: background var(--dur-3) var(--ease-out),
              backdrop-filter var(--dur-3) var(--ease-out),
              padding var(--dur-3) var(--ease-out),
              transform var(--dur-3) var(--ease-out);
}
.header::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 1px;
  background: var(--line); opacity: 0;
  transition: opacity var(--dur-3) var(--ease-out);
}
.header.is-stuck {
  background: rgba(8, 8, 10, 0.72);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  padding-block: 0.85rem;
}
.header.is-stuck::after { opacity: 1; }
.header.is-hidden { transform: translateY(-105%); }

.nav {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--s-2);
}

.nav__logo { justify-self: center; display: block; }
.nav__logo img {
  height: 54px; width: auto;
  transition: height var(--dur-3) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
.header.is-stuck .nav__logo img { height: 42px; }
.nav__logo:hover img { transform: scale(1.06); }

.nav__right { justify-self: end; display: flex; align-items: center; gap: 1.75rem; }

.nav__link {
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
  position: relative;
  padding-block: 0.35rem;
  transition: color var(--dur-2) var(--ease-out);
}
.nav__link::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: 0;
  height: 1px; background: var(--accent);
  transition: right var(--dur-3) var(--ease-out);
}
.nav__link:hover { color: var(--ink); }
.nav__link:hover::after { right: 0; }
.nav__link.is-active { color: var(--ink); }
.nav__link.is-active::after { right: 0; }

@media (max-width: 900px) { .nav__links { display: none; } }
.nav__links { display: flex; gap: 1.75rem; align-items: center; }

/* Burger */
.burger {
  justify-self: start;
  display: inline-flex; align-items: center; gap: 0.8rem;
  padding: 0.5rem 0;
  color: var(--ink);
}
.burger__lines { display: grid; gap: 5px; width: 26px; }
.burger__lines i {
  display: block; height: 1.5px; background: currentColor; width: 100%;
  transform-origin: center;
  transition: transform var(--dur-3) var(--ease-out), opacity var(--dur-2),
              width var(--dur-3) var(--ease-out);
}
.burger__lines i:nth-child(2) { width: 62%; }
.burger:hover .burger__lines i:nth-child(2) { width: 100%; }
.burger__text {
  font-size: var(--t-micro); font-weight: 600;
  letter-spacing: 0.2em; text-transform: uppercase;
}
body.menu-open .burger__lines i:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
body.menu-open .burger__lines i:nth-child(2) { opacity: 0; transform: scaleX(0); }
body.menu-open .burger__lines i:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

/* Full-screen menu overlay */
.menu {
  position: fixed; inset: 0; z-index: 8500;
  background: var(--bg);
  visibility: hidden;
  clip-path: inset(0 0 100% 0);
  transition: clip-path 0.8s var(--ease-out), visibility 0.8s;
}
body.menu-open .menu {
  visibility: visible;
  clip-path: inset(0 0 0 0);
}
.menu__inner {
  height: 100%;
  display: grid;
  grid-template-rows: var(--header-h) 1fr auto;
  padding-inline: var(--gutter);
  max-width: var(--maxw); margin-inline: auto; width: 100%;
}
.menu__body {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: var(--s-6);
  align-content: center;
  align-items: center;
  padding-block: var(--s-4);
}

.menu__nav { display: grid; gap: 0.15em; }
.menu__link {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 7.5vw, 6.5rem);
  line-height: 0.95;
  text-transform: uppercase;
  color: var(--ink);
  display: flex; align-items: baseline; gap: 1rem;
  position: relative;
  width: max-content; max-width: 100%;
  overflow: hidden;
  transform: translateY(110%);
  opacity: 0;
  transition: color var(--dur-2) var(--ease-out);
}
body.menu-open .menu__link {
  animation: menu-in 0.75s var(--ease-out) forwards;
  animation-delay: calc(0.16s + var(--i) * 0.075s);
}
@keyframes menu-in { to { transform: translateY(0); opacity: 1; } }

.menu__link i {
  font-style: normal;
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--ink-3);
  transition: color var(--dur-2);
}
.menu__link::after {
  content: ""; position: absolute; left: 0; bottom: 0.12em;
  width: 100%; height: 2px; background: var(--accent);
  transform: scaleX(0); transform-origin: right;
  transition: transform 0.5s var(--ease-out);
}
.menu__link:hover { color: var(--accent); }
.menu__link:hover i { color: var(--accent); }
.menu__link:hover::after { transform: scaleX(1); transform-origin: left; }
.menu__link.is-active i { color: var(--accent); }

.menu__aside { display: grid; gap: var(--s-4); align-content: center; }
.menu__block { display: grid; gap: 0.45rem; }
.menu__block h4 {
  font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--ink-3);
  font-family: var(--font-body);
}
.menu__block a, .menu__block p { font-size: var(--t-sm); color: var(--ink-2); }
.menu__block a:hover { color: var(--accent); }

.menu__foot {
  display: flex; justify-content: space-between; align-items: center;
  gap: var(--s-3); flex-wrap: wrap;
  padding-block: var(--s-4);
  border-top: 1px solid var(--line);
  font-size: var(--t-xs); color: var(--ink-3);
}
.menu__socials { display: flex; gap: 1.25rem; }
.menu__socials a { color: var(--ink-2); letter-spacing: 0.1em; text-transform: uppercase; font-size: var(--t-micro); font-weight: 600; }
.menu__socials a:hover { color: var(--accent); }

/* ========================= 7. BUTTONS ========================= */
.btn {
  --btn-bg: transparent;
  --btn-ink: var(--ink);
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.7rem;
  padding: 1.05rem 2.1rem;
  font-size: var(--t-xs); font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--btn-ink);
  border: 1px solid var(--line);
  background: var(--btn-bg);
  overflow: hidden;
  isolation: isolate;
  transition: color var(--dur-3) var(--ease-out), border-color var(--dur-3) var(--ease-out);
}
.btn::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--accent);
  transform: translateY(101%);
  transition: transform 0.5s var(--ease-out);
}
.btn:hover { color: #fff; border-color: var(--accent); }
.btn:hover::before { transform: translateY(0); }
.btn svg { width: 14px; height: 14px; flex: none; }

.btn--solid { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn--solid::before { background: #fff; }
.btn--solid:hover { color: var(--bg); }

.btn--ghost { border-color: var(--ink-4); }

/* Text link with animated underline */
.link {
  display: inline-flex; align-items: center; gap: 0.55rem;
  font-size: var(--t-xs); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  padding-bottom: 0.35rem;
  position: relative;
  color: var(--ink);
}
.link::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 1px; width: 100%;
  background: currentColor;
  transform-origin: right; transform: scaleX(1);
  transition: transform 0.45s var(--ease-out);
}
.link:hover { color: var(--accent); }
.link:hover::after { transform: scaleX(0); transform-origin: left; }
.link .arr { transition: transform var(--dur-3) var(--ease-out); }
.link:hover .arr { transform: translateX(5px); }

/* ========================= 8. HERO ========================= */
/* Split hero. Every piece in this portfolio is a *graphic design* piece —
   it carries its own headline type. So the artwork gets its own stage on
   the right and the site's headline sits on clean ground at the left.
   Nothing is ever set on top of the work. */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  background: var(--bg);
  padding-block: calc(var(--header-h) + clamp(1.5rem, 4vh, 3rem)) clamp(4rem, 10vh, 6rem);
  overflow: hidden;
}

.hero__content {
  position: relative; z-index: 2;
  width: 100%;
  display: grid;
  grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.14fr);
  gap: clamp(2rem, 4vw, 4.5rem);
  align-items: center;
}

.hero__mid { display: grid; align-content: center; gap: 1.15rem; }

/* Sized to fit its column, not the viewport — it no longer has to
   compete with the artwork for attention. */
.hero__title {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 4.6vw, 4.6rem);
  line-height: 0.88;
  text-transform: uppercase;
  letter-spacing: -0.015em;
  color: #fff;   /* match the caption exactly, not the warmer --ink */
}

/* ---- the artwork stage ---- */
.hero__stage {
  position: relative;
  display: grid;
  gap: 1.1rem;
}

.hero__frame {
  position: relative;
  aspect-ratio: 16 / 9;
  background: #0e0e11;
  border: 1px solid var(--line);
  overflow: hidden;
  box-shadow: 0 40px 90px rgba(0, 0, 0, 0.55);
}

.hero__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }

/* Static fallback: shown until WebGL takes over, and permanently if it
   never does (file:// or no WebGL). `contain`, to match the shader. */
.hero__fallback {
  position: absolute; inset: 0;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  transition: opacity 0.8s var(--ease-out);
}
.hero.gl-ready .hero__fallback { opacity: 0; }
.hero__title span { display: block; overflow: hidden; }
.js .hero__title span > b {
  display: block; font-weight: inherit;
  transform: translateY(100%);
  transition: transform 1.1s var(--ease-out);
}
.hero.is-in .hero__title span > b { transform: translateY(0); }
.hero__title span:nth-child(2) > b { transition-delay: 0.09s; }
.hero__title .thin {
  -webkit-text-stroke: 1px rgba(244,244,242,0.55);
  color: transparent;
}

.hero__sub {
  max-width: 46ch;
  color: var(--ink-2);
  font-size: clamp(0.95rem, 1.2vw, 1.1rem);
}
.js .hero__sub {
  opacity: 0; transform: translateY(18px);
  transition: opacity 0.9s var(--ease-out) 0.4s, transform 0.9s var(--ease-out) 0.4s;
}
.hero.is-in .hero__sub { opacity: 1; transform: none; }

.hero__actions {
  display: flex; gap: 1rem; flex-wrap: wrap; margin-top: 0.8rem;
}
.js .hero__actions {
  opacity: 0; transform: translateY(18px);
  transition: opacity 0.9s var(--ease-out) 0.55s, transform 0.9s var(--ease-out) 0.55s;
}
.hero.is-in .hero__actions { opacity: 1; transform: none; }

/* Caption strip under the stage — names the piece on screen. */
.hero__bottom {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3); flex-wrap: wrap;
}
.js .hero__bottom { opacity: 0; transition: opacity 0.9s var(--ease-out) 0.75s; }
.hero.is-in .hero__bottom { opacity: 1; }

.hero__meta { display: grid; gap: 0.15rem; min-width: 0; }
.hero__meta .k { font-size: var(--t-micro); letter-spacing: 0.2em; text-transform: uppercase; color: var(--accent); font-weight: 600; }
/* Sized up from --t-lg. At ~30px Anton's stems are thin enough that
   antialiasing blends most of the glyph into the black behind it, so the
   same white reads noticeably greyer than the headline. Larger glyphs put
   proportionally less of the letter on the antialiased edge. */
.hero__meta .v {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 2.7vw, 2.3rem);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  color: #fff;
}

.hero__ctrl { display: flex; align-items: center; gap: 1.25rem; }
.hero__dots { display: flex; gap: 0.7rem; }
.hero__dot {
  width: 46px; height: 2px; background: var(--ink-4);
  position: relative; overflow: hidden; cursor: pointer;
}
.hero__dot::after {
  content: ""; position: absolute; inset: 0 100% 0 0; background: var(--ink);
  transition: right 0.3s var(--ease-out);
}
.hero__dot:hover::after { right: 60%; }
.hero__dot.is-active::after { right: 0; transition: right 5.6s linear; }
.hero__dot.is-active.is-paused::after { transition: none; }

/* Hexagon, not a circle — carries over the shape language from the
   original design. The outline is a stroked <polygon> rather than a
   border, since border-radius can't cut a hexagon. */
.hero__toggle {
  position: relative;
  width: 46px; height: 46px;
  display: grid; place-items: center;
  color: var(--ink-4);
  transition: color var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
.hero__toggle .hex {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 3;
  stroke-linejoin: round;
  transition: fill var(--dur-2) var(--ease-out);
}
.hero__toggle:hover { color: var(--accent); transform: scale(1.08); }
.hero__toggle:hover .hex { fill: var(--accent-dim); }

.hero__toggle .i-pause,
.hero__toggle .i-play {
  position: relative; z-index: 1;
  width: 11px; height: 11px;
  fill: var(--ink);
}
.hero__toggle .i-play { display: none; }
.hero__toggle.is-paused .i-play { display: block; }
.hero__toggle.is-paused .i-pause { display: none; }

.hero__scroll {
  position: absolute; left: 50%; bottom: 1.6rem; transform: translateX(-50%);
  z-index: 4;
  display: grid; justify-items: center; gap: 0.6rem;
  font-size: var(--t-micro); letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--ink-3);
}
.hero__scroll i { display: block; width: 1px; height: 42px; background: linear-gradient(var(--ink-3), transparent); position: relative; overflow: hidden; }
.hero__scroll i::after {
  content: ""; position: absolute; inset: 0; background: var(--accent);
  animation: scroll-tick 2.2s var(--ease-io) infinite;
}
@keyframes scroll-tick {
  0%   { transform: translateY(-100%); }
  60%, 100% { transform: translateY(100%); }
}
@media (max-width: 700px) { .hero__scroll { display: none; } }

/* ========================= 9. MARQUEE ========================= */
.marquee {
  --speed: 34s;
  overflow: hidden; position: relative;
  border-block: 1px solid var(--line);
  padding-block: 1.15rem;
  background: var(--bg);
}
.marquee__track {
  display: flex; width: max-content;
  animation: marquee var(--speed) linear infinite;
}
.marquee--rev .marquee__track { animation-direction: reverse; }
.marquee:hover .marquee__track { animation-play-state: paused; }
@keyframes marquee { to { transform: translateX(-50%); } }

.marquee__item {
  display: inline-flex; align-items: center; gap: 1.6rem;
  padding-inline: 1.6rem;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3.2vw, 2.8rem);
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
}
.marquee__item .dot { width: 7px; height: 7px; background: var(--accent); border-radius: 50%; flex: none; }
.marquee__item.is-out { -webkit-text-stroke: 1px var(--ink-3); color: transparent; }

/* Tools strip */
.tools {
  display: flex; width: max-content;
  animation: marquee var(--tools-speed, 40s) linear infinite;
  align-items: center;
}
/* Fixed box, not width:auto — every icon must occupy identical space so
   the two halves of the track are exactly equal and translateX(-50%)
   wraps seamlessly. `contain` keeps each logo's own aspect inside it. */
.tools img {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  object-fit: contain;
  margin-inline: clamp(1.5rem, 4vw, 3.5rem);
  /* The source SVGs are near-black, so `brightness()` can't lift them off
     a dark background. Flatten to black, then invert to a bright, even
     grey — every logo lands at the same weight regardless of its artwork. */
  filter: brightness(0) invert(0.82);
  opacity: 1;
  transition: opacity var(--dur-2), filter var(--dur-2), transform var(--dur-2);
}
.tools img:hover { filter: none; transform: scale(1.12); }
.tools-strip { overflow: hidden; padding-block: 2.2rem; position: relative; }
.tools-strip::before, .tools-strip::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: clamp(60px, 12vw, 200px); z-index: 2; pointer-events: none;
}
.tools-strip::before { left: 0;  background: linear-gradient(to right, var(--bg), transparent); }
.tools-strip::after  { right: 0; background: linear-gradient(to left,  var(--bg), transparent); }
.section--alt .tools-strip::before { background: linear-gradient(to right, var(--bg-2), transparent); }
.section--alt .tools-strip::after  { background: linear-gradient(to left,  var(--bg-2), transparent); }

/* ========================= 10. SECTION HEADERS ========================= */
.shead {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s-4); flex-wrap: wrap;
  margin-bottom: clamp(2.5rem, 5vw, 4.5rem);
}
.shead__l { display: grid; gap: 1.1rem; max-width: 34ch; }
.shead__title {
  font-family: var(--font-display);
  font-size: var(--t-xxl);
  line-height: 0.9;
  text-transform: uppercase;
}
.shead__r { display: grid; gap: 1.2rem; max-width: 42ch; }

/* Counter chip */
.count-chip {
  font-size: var(--t-micro); letter-spacing: 0.18em; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

/* ========================= 11. WORK GRID ========================= */
.filters {
  display: flex; flex-wrap: wrap; gap: 0.5rem;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}
.filter {
  padding: 0.6rem 1.15rem;
  font-size: var(--t-xs); font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--ink-3);
  border: 1px solid var(--line-soft);
  border-radius: 99px;
  transition: color var(--dur-2), border-color var(--dur-2), background var(--dur-2);
  white-space: nowrap;
}
.filter:hover { color: var(--ink); border-color: var(--ink-4); }
.filter.is-active { color: #fff; background: var(--accent); border-color: var(--accent); }
.filter sup { font-size: 0.65em; opacity: 0.7; margin-left: 0.3em; }

/* Justified layout. Widths and heights are solved in JS (see justify() in
   main.js) so each card keeps its artwork's exact aspect ratio while every
   row still spans the full container width. Nothing is cropped and no row
   has a gap at the end. */
.grid__rows {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: clamp(0.9rem, 1.6vw, 1.6rem);
}

/* Fallback sizing. The card's images are absolutely positioned, so without
   an explicit size a card collapses to its 1px borders and every image
   stays unloaded — an invisible grid. These defaults give a perfectly
   usable wrapped grid even if the JS solver never runs. `is-sized` is set
   by measure() once real widths are applied, releasing the min-height so
   solved row heights are free to be shorter. */
.grid__rows .card { flex: 1 1 320px; min-height: 240px; }
.grid__rows.is-sized .card { min-height: 0; }

/* The card is a <button> built from spans, so the block-level
   display values have to be declared rather than inherited. */
.card {
  position: relative;
  display: block;
  text-align: left;
  background: var(--surface);
  overflow: hidden;
  border: 1px solid var(--line-soft);
  cursor: pointer;
  transition: border-color var(--dur-3) var(--ease-out),
              transform var(--dur-3) var(--ease-out);
}
.card:hover { border-color: rgba(255, 107, 18, 0.4); }

.card__media {
  display: block;
  position: relative;
  height: 100%;
  overflow: hidden;
  background: var(--surface-2);
}

/* Poster and video are stacked in the same box, both absolutely
   positioned. Declare position ONCE here — a later rule re-declaring
   these selectors at equal specificity silently wins and drops the video
   out of the stack into normal flow. */
/* Poster and video are stacked in the same box, both absolutely
   positioned. Declare position ONCE here — a later rule re-declaring
   these selectors at equal specificity silently wins and drops the video
   out of the stack into normal flow.

   No resting scale and no resting filter: the card is already cut to the
   artwork's exact aspect ratio, so at rest the piece is shown whole, at
   full saturation, edge to edge. */
.card__media img,
.card__media video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1);
  transition: transform 0.9s var(--ease-out),
              opacity 0.45s var(--ease-out);
}
.card__media img   { z-index: 1; }
.card__media video { z-index: 2; opacity: 0; }

/* Transient hover push-in only. Delete this block for zero crop ever. */
.card:hover .card__media img,
.card:hover .card__media video {
  transform: scale(1.04);
}
.card.is-playing .card__media video { opacity: 1; }
.card.is-playing .card__media img { opacity: 0; }

/* Transparent logo PNGs need a light tile and breathing room around the
   mark — the one case where `contain` is correct. */
.card.is-light .card__media { background: #f2f2ef; }
.card.is-light .card__media img { object-fit: contain; padding: 9%; }
.card.is-light:hover .card__media img { transform: scale(1.03); }

/* Loading shimmer until the image decodes */
.card__media::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(100deg, var(--surface-2) 30%, #24242b 50%, var(--surface-2) 70%);
  background-size: 220% 100%;
  animation: shimmer 1.4s linear infinite;
  opacity: 1; transition: opacity 0.4s;
}
.card.is-loaded .card__media::before { opacity: 0; animation: none; }
@keyframes shimmer { to { background-position: -220% 0; } }

/* Kept tight to the bottom edge. Its only job is to make the caption
   legible — it must not dim the artwork. The old gradient reached 70% up
   the card, which was tolerable on tall cards but swallowed square ones
   whole, especially dark pieces like the Chanel ad. It now clears by 38%
   and is fully transparent above that. */
.card__veil {
  position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: linear-gradient(to top,
    rgba(8, 8, 10, 0.90) 0%,
    rgba(8, 8, 10, 0.45) 16%,
    rgba(8, 8, 10, 0) 38%);
}

.card__body {
  position: absolute; inset: auto 0 0 0; z-index: 4;
  padding: clamp(1rem, 2vw, 1.6rem);
  display: grid; gap: 0.35rem;
  transform: translateY(0);
  transition: transform var(--dur-3) var(--ease-out);
  /* Legibility comes from a halo behind the glyphs, not from darkening
     the picture. Keeps the caption readable over a bright image while
     the artwork itself stays untouched. */
  text-shadow: 0 1px 3px rgba(8, 8, 10, 0.85), 0 2px 14px rgba(8, 8, 10, 0.75);
}
.card:hover .card__body { transform: translateY(-4px); }

.card__cat {
  display: block;
  font-size: var(--t-micro); font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--accent);
}
.card__title {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1.9vw, 1.8rem);
  line-height: 1;
  text-transform: uppercase;
}
.card__meta {
  font-size: var(--t-xs); color: var(--ink-3);
  display: flex; gap: 0.5rem; align-items: center;
  max-height: 0; overflow: hidden; opacity: 0;
  transition: max-height var(--dur-3) var(--ease-out), opacity var(--dur-3) var(--ease-out), margin var(--dur-3);
}
.card:hover .card__meta { max-height: 3em; opacity: 1; margin-top: 0.25rem; }
.card__meta i { font-style: normal; color: var(--ink-4); }

.card__badge {
  position: absolute; top: 0.9rem; right: 0.9rem; z-index: 4;
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.35rem 0.65rem;
  background: rgba(8, 8, 10, 0.62);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--line);
  font-size: 9px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-2);
}
.card__badge svg { width: 9px; height: 9px; fill: var(--accent); }

/* Grid entrance */
.js .card { opacity: 0; transform: translateY(34px); }
.js .card.is-shown { opacity: 1; transform: translateY(0); transition: opacity 0.75s var(--ease-out), transform 0.75s var(--ease-out), border-color var(--dur-3); }
.card.is-hidden { display: none; }

.grid-empty {
  padding: var(--s-7) 0;
  text-align: center; color: var(--ink-3);
}

/* ========================= 12. SERVICES ========================= */
.services { display: grid; border-top: 1px solid var(--line); }
.service {
  display: grid;
  grid-template-columns: 5rem minmax(0, 1fr) minmax(0, 1.1fr) auto;
  gap: var(--s-3);
  align-items: start;
  padding-block: clamp(1.8rem, 3.5vw, 2.8rem);
  border-bottom: 1px solid var(--line);
  position: relative;
  transition: padding-left var(--dur-3) var(--ease-out);
}
.service::before {
  content: ""; position: absolute; inset: 0 100% 0 0; z-index: -1;
  background: linear-gradient(90deg, var(--accent-dim), transparent 60%);
  transition: right 0.6s var(--ease-out);
}
.service:hover::before { right: 0; }
.service:hover { padding-left: 1.2rem; }

.service__n {
  font-family: var(--font-display);
  font-size: var(--t-lg);
  color: var(--ink-4);
  transition: color var(--dur-3);
}
.service:hover .service__n { color: var(--accent); }
.service__title {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 2.6vw, 2.2rem);
  line-height: 1; text-transform: uppercase;
}
.service__body { color: var(--ink-2); font-size: var(--t-sm); }
.service__tags { display: flex; flex-wrap: wrap; gap: 0.4rem; justify-content: flex-end; }

/* Two-column variant used in the About page sidebar (no body copy). */
.services--compact .service { grid-template-columns: 3rem minmax(0, 1fr); gap: var(--s-2); }
.services--compact .service__tags { grid-column: 2; justify-content: flex-start; margin-top: 0.5rem; }
.tag {
  font-size: var(--t-micro); letter-spacing: 0.1em; text-transform: uppercase;
  padding: 0.35rem 0.7rem; border: 1px solid var(--line);
  color: var(--ink-3); border-radius: 99px; white-space: nowrap;
}

/* ========================= 13. STATS ========================= */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
.stat { background: var(--bg); padding: clamp(1.6rem, 3vw, 2.6rem); display: grid; gap: 0.4rem; }
.stat__n {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 5vw, 4rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.stat__n sup {
  font-size: 0.55em;
  line-height: 1;
  vertical-align: top;
  margin-left: 0.06em;
  color: var(--accent);
}
.stat__l { font-size: var(--t-micro); letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-3); }
.section--alt .stat { background: var(--bg-2); }

/* ========================= 14. LIGHTBOX ========================= */
.lb {
  position: fixed; inset: 0; z-index: 9200;
  display: grid; grid-template-rows: auto 1fr auto;
  background: rgba(6, 6, 8, 0.86);
  backdrop-filter: blur(26px) saturate(120%);
  -webkit-backdrop-filter: blur(26px) saturate(120%);
  opacity: 0; visibility: hidden;
  transition: opacity 0.45s var(--ease-out), visibility 0.45s;
}
.lb.is-open { opacity: 1; visibility: visible; }

.lb__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3);
  padding: 1.1rem var(--gutter);
  border-bottom: 1px solid var(--line);
}
.lb__idx { font-size: var(--t-micro); letter-spacing: 0.2em; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.lb__close {
  width: 44px; height: 44px; border: 1px solid var(--line); border-radius: 50%;
  display: grid; place-items: center;
  transition: background var(--dur-2), border-color var(--dur-2), transform var(--dur-2);
}
.lb__close:hover { background: var(--accent); border-color: var(--accent); transform: rotate(90deg); }
.lb__close svg { width: 14px; height: 14px; stroke: currentColor; stroke-width: 1.6; }

.lb__stage {
  position: relative;
  display: grid; place-items: center;
  padding: clamp(1rem, 3vw, 2.5rem) var(--gutter);
  min-height: 0;
}
.lb__frame {
  position: relative;
  max-width: min(1200px, 100%);
  max-height: 100%;
  display: grid; place-items: center;
}
/* The image is ALWAYS visible. It used to start at opacity 0 and wait for
   an `is-ready` class added on load — if that reveal failed for any reason
   the lightbox opened with the caption and an invisible picture, which is
   exactly the failure that hid the Chanel piece. The whole panel already
   fades in via .lb.is-open, so the per-image fade bought nothing and could
   only ever fail open-with-nothing-showing. */
.lb__frame img, .lb__frame video {
  max-width: 100%;
  max-height: calc(100svh - 260px);
  width: auto; object-fit: contain;
  box-shadow: 0 40px 120px rgba(0, 0, 0, 0.7);
  opacity: 1;
}
.lb.is-light .lb__frame img { background: #f2f2ef; padding: 3rem; }

.lb__nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 54px; height: 54px; border-radius: 50%;
  border: 1px solid var(--line);
  background: rgba(8, 8, 10, 0.55);
  backdrop-filter: blur(10px);
  display: grid; place-items: center;
  transition: background var(--dur-2), border-color var(--dur-2), transform var(--dur-2);
  z-index: 3;
}
.lb__nav:hover { background: var(--accent); border-color: var(--accent); }
.lb__nav--prev { left: clamp(0.5rem, 2vw, 2rem); }
.lb__nav--next { right: clamp(0.5rem, 2vw, 2rem); }
.lb__nav:hover.lb__nav--prev { transform: translateY(-50%) translateX(-4px); }
.lb__nav:hover.lb__nav--next { transform: translateY(-50%) translateX(4px); }
.lb__nav svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.6; }

.lb__info {
  padding: 1.3rem var(--gutter) 2rem;
  border-top: 1px solid var(--line);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) auto;
  gap: var(--s-3); align-items: start;
}
.lb__title { font-family: var(--font-display); font-size: var(--t-xl); line-height: 1; text-transform: uppercase; }
.lb__cat { font-size: var(--t-micro); letter-spacing: 0.18em; text-transform: uppercase; color: var(--accent); margin-bottom: 0.4rem; }
.lb__blurb { color: var(--ink-2); font-size: var(--t-sm); max-width: 62ch; }
.lb__tools { display: flex; gap: 0.4rem; flex-wrap: wrap; justify-content: flex-end; }

@media (max-width: 860px) {
  .lb__info { grid-template-columns: 1fr; }
  .lb__tools { justify-content: flex-start; }
  .lb__frame img, .lb__frame video { max-height: calc(100svh - 340px); }
}

/* ========================= 15. PAGE HERO ========================= */
.phero {
  position: relative;
  padding-top: calc(var(--header-h) + clamp(3.5rem, 9vh, 7rem));
  padding-bottom: clamp(2.5rem, 6vh, 4.5rem);
  overflow: hidden;
}
.phero::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 1px; background: var(--line);
}
.phero__grid {
  display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: var(--s-5); align-items: end;
}
.phero__title {
  font-family: var(--font-display);
  font-size: clamp(3rem, 10vw, 9rem);
  line-height: 0.84; text-transform: uppercase; letter-spacing: -0.02em;
}
.phero__title .thin { -webkit-text-stroke: 1px rgba(244,244,242,0.5); color: transparent; }

.crumbs { display: flex; gap: 0.6rem; align-items: center; font-size: var(--t-micro); letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 1.4rem; }
.crumbs a:hover { color: var(--accent); }
.crumbs span { color: var(--ink-4); }

/* ========================= 16. ABOUT ========================= */
.about-grid {
  display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(2rem, 5vw, 5rem); align-items: start;
}
.portrait {
  position: relative; overflow: hidden;
  border: 1px solid var(--line);
  background: var(--surface);
  aspect-ratio: 4 / 5;
}
.portrait img { width: 100%; height: 100%; object-fit: contain; padding: 12%; }
.portrait::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(120% 90% at 50% 20%, rgba(255,107,18,0.14), transparent 62%);
  pointer-events: none;
}
.portrait__tag {
  position: absolute; left: 0; bottom: 0; z-index: 2;
  background: var(--accent); color: #fff;
  padding: 0.6rem 1.1rem;
  font-size: var(--t-micro); font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase;
}

.prose { display: grid; gap: 1.3rem; }
.prose p { color: var(--ink-2); font-size: clamp(1rem, 1.25vw, 1.15rem); line-height: 1.7; }
.prose p strong { color: var(--ink); font-weight: 600; }
.prose h3 {
  font-family: var(--font-display); font-size: var(--t-lg);
  text-transform: uppercase; margin-top: 0.8rem;
}

.skills { display: grid; gap: 1.3rem; }
.skill { display: grid; gap: 0.55rem; }
.skill__row { display: flex; justify-content: space-between; align-items: baseline; }
.skill__name { font-size: var(--t-sm); font-weight: 500; letter-spacing: 0.04em; }
.skill__pct { font-size: var(--t-micro); color: var(--ink-3); font-variant-numeric: tabular-nums; }
.skill__bar { height: 2px; background: var(--ink-4); position: relative; overflow: hidden; }
.skill__bar i {
  position: absolute; inset: 0 100% 0 0; background: var(--accent);
  transition: right 1.2s var(--ease-out);
}
.skill.is-shown .skill__bar i { right: var(--rest); }

.timeline { display: grid; }
.tl {
  display: grid; grid-template-columns: 8rem minmax(0, 1fr);
  gap: var(--s-3);
  padding-block: clamp(1.4rem, 2.6vw, 2.1rem);
  border-top: 1px solid var(--line);
  align-items: start;
}
.timeline .tl:last-child { border-bottom: 1px solid var(--line); }
.tl__year { font-family: var(--font-display); font-size: var(--t-lg); color: var(--accent); }
.tl__title { font-size: var(--t-lg); font-weight: 600; margin-bottom: 0.35rem; letter-spacing: -0.01em; }
.tl__body { color: var(--ink-2); font-size: var(--t-sm); max-width: 60ch; }

/* ========================= 17. CONTACT ========================= */
.contact-grid {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: clamp(2.5rem, 6vw, 6rem); align-items: start;
}

.field { display: grid; gap: 0.5rem; margin-bottom: 1.6rem; position: relative; }
.field label {
  font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ink-3);
}
.field input, .field textarea, .field select {
  width: 100%;
  background: transparent;
  border: 0; border-bottom: 1px solid var(--line);
  padding: 0.85rem 0;
  font-size: var(--t-md);
  color: var(--ink);
  transition: border-color var(--dur-2);
  border-radius: 0;
}
.field select { appearance: none; cursor: pointer; }
.field select option { background: var(--surface); color: var(--ink); }
.field textarea { resize: vertical; min-height: 130px; }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none; border-bottom-color: var(--accent);
}
.field input::placeholder, .field textarea::placeholder { color: var(--ink-4); }
.field .err { font-size: var(--t-xs); color: #ff5b5b; min-height: 1.2em; }
.field.has-error input, .field.has-error textarea { border-bottom-color: #ff5b5b; }

.form-note { font-size: var(--t-xs); color: var(--ink-3); margin-top: 1rem; max-width: 46ch; }
.form-status {
  margin-top: 1.2rem; padding: 0.9rem 1.1rem;
  border: 1px solid var(--line); font-size: var(--t-sm);
  display: none;
}
.form-status.is-shown { display: block; }
.form-status.is-ok { border-color: rgba(255,107,18,0.5); color: var(--ink); background: var(--accent-dim); }

.info-list { display: grid; }
.info {
  display: grid; gap: 0.3rem;
  padding-block: 1.4rem;
  border-top: 1px solid var(--line);
}
.info-list .info:last-child { border-bottom: 1px solid var(--line); }
.info__k { font-size: var(--t-micro); letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-3); }
.info__v { font-size: clamp(1rem, 1.5vw, 1.25rem); font-weight: 500; }
.info__v a:hover { color: var(--accent); }

.social-row { display: flex; gap: 0.7rem; flex-wrap: wrap; margin-top: 1.8rem; }
.social {
  display: inline-flex; align-items: center; gap: 0.6rem;
  padding: 0.75rem 1.15rem;
  border: 1px solid var(--line);
  font-size: var(--t-xs); letter-spacing: 0.12em; text-transform: uppercase; font-weight: 600;
  transition: background var(--dur-2), border-color var(--dur-2), transform var(--dur-2);
}
.social img { width: 16px; height: 16px; object-fit: contain; filter: brightness(2.4) grayscale(1); }
.social:hover { border-color: var(--accent); background: var(--accent-dim); transform: translateY(-2px); }

.avail {
  display: inline-flex; align-items: center; gap: 0.6rem;
  font-size: var(--t-xs); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-2);
}
.avail i {
  width: 8px; height: 8px; border-radius: 50%; background: #37d67a;
  box-shadow: 0 0 0 0 rgba(55, 214, 122, 0.6);
  animation: pulse 2.4s var(--ease-out) infinite;
}
@keyframes pulse {
  70%  { box-shadow: 0 0 0 10px rgba(55, 214, 122, 0); }
  100% { box-shadow: 0 0 0 0 rgba(55, 214, 122, 0); }
}

/* FAQ */
.faq { display: grid; }
.faq__item { border-top: 1px solid var(--line); }
.faq:last-child .faq__item:last-child { border-bottom: 1px solid var(--line); }
.faq__q {
  width: 100%; text-align: left;
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  padding-block: 1.35rem;
  font-size: clamp(1rem, 1.4vw, 1.2rem); font-weight: 500;
  transition: color var(--dur-2);
}
.faq__q:hover { color: var(--accent); }
.faq__q i {
  flex: none; width: 18px; height: 18px; position: relative;
}
.faq__q i::before, .faq__q i::after {
  content: ""; position: absolute; inset: 50% 0 auto 0; height: 1px; background: currentColor;
  transition: transform var(--dur-3) var(--ease-out);
}
.faq__q i::after { transform: rotate(90deg); }
.faq__item.is-open .faq__q i::after { transform: rotate(0); }
.faq__item.is-open .faq__q { color: var(--accent); }
.faq__a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.5s var(--ease-out); }
.faq__item.is-open .faq__a { grid-template-rows: 1fr; }
.faq__a > div { overflow: hidden; }
.faq__a p { color: var(--ink-2); font-size: var(--t-sm); padding-bottom: 1.4rem; max-width: 68ch; }

/* ========================= 18. FOOTER ========================= */
.cta {
  position: relative;
  padding-block: clamp(5rem, 14vh, 10rem);
  text-align: center;
  overflow: hidden;
  border-top: 1px solid var(--line);
}
.cta__title {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 9vw, 8rem);
  line-height: 0.85; text-transform: uppercase; letter-spacing: -0.02em;
  margin-block: 1.2rem 1.8rem;
}
.cta__title a { display: inline-block; transition: color var(--dur-3) var(--ease-out); }
.cta__title a:hover { color: var(--accent); }

.footer { border-top: 1px solid var(--line); background: var(--bg); }
.footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: var(--s-4);
  padding-block: clamp(3rem, 7vw, 5rem);
}
.footer__brand { display: grid; gap: 1rem; align-content: start; }
.footer__brand img { height: 58px; width: auto; }
.footer__brand p { color: var(--ink-3); font-size: var(--t-sm); max-width: 34ch; }

.footer__col { display: grid; gap: 0.75rem; align-content: start; }
.footer__col h4 {
  font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: 0.3rem;
}
.footer__col a, .footer__col p { color: var(--ink-2); font-size: var(--t-sm); }
.footer__col a { transition: color var(--dur-2), padding-left var(--dur-2); }
.footer__col a:hover { color: var(--accent); padding-left: 5px; }

.footer__bot {
  border-top: 1px solid var(--line);
  padding-block: 1.6rem;
  display: flex; justify-content: space-between; align-items: center;
  gap: var(--s-3); flex-wrap: wrap;
  font-size: var(--t-xs); color: var(--ink-3);
}
.footer__bot a:hover { color: var(--accent); }

.to-top {
  display: inline-flex; align-items: center; gap: 0.6rem;
  font-size: var(--t-micro); letter-spacing: 0.16em; text-transform: uppercase; font-weight: 600;
}
.to-top svg { width: 12px; height: 12px; transition: transform var(--dur-2) var(--ease-out); }
.to-top:hover svg { transform: translateY(-4px); }

/* ========================= 19. REVEAL ========================= */
/* Every hidden-until-revealed state is scoped to .js (set by main.js on
   first execution). Without JS the page renders fully visible instead of
   as a column of blank sections. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.9s var(--ease-out), transform 0.9s var(--ease-out);
  transition-delay: var(--d, 0s);
}
.js [data-reveal].is-shown { opacity: 1; transform: none; }

.js [data-reveal="fade"] { transform: none; }
.js [data-reveal="left"]  { transform: translateX(-40px); }
.js [data-reveal="right"] { transform: translateX(40px); }
.js [data-reveal="clip"]  {
  opacity: 1; transform: none;
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1s var(--ease-out) var(--d, 0s);
}
.js [data-reveal="clip"].is-shown { clip-path: inset(0 0 0 0); }

/* Split-line headline reveal */
.lines > span { display: block; overflow: hidden; }
.js .lines > span > b {
  display: block; font-weight: inherit;
  transform: translateY(105%);
  transition: transform 1s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 0.08s);
}
.js .lines.is-shown > span > b { transform: translateY(0); }

/* Parallax host */
[data-parallax] { will-change: transform; }

/* ========================= 20. RESPONSIVE ========================= */
@media (max-width: 1180px) {
  .service { grid-template-columns: 3.5rem minmax(0, 1fr) minmax(0, 1fr); }
  .service__tags { grid-column: 1 / -1; justify-content: flex-start; margin-top: 0.6rem; }
  .footer__top { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 980px) {
  :root { --header-h: 72px; }
  /* Stack the hero: copy first, then the artwork stage below it. */
  .hero { min-height: 0; }
  .hero__content { grid-template-columns: 1fr; gap: clamp(2rem, 6vw, 3rem); }
  .hero__title { font-size: clamp(2.4rem, 9vw, 4rem); }
  .menu__body { grid-template-columns: 1fr; gap: var(--s-4); }
  .menu__aside { display: none; }
  .about-grid, .contact-grid, .phero__grid { grid-template-columns: 1fr; }
  .phero__grid { gap: var(--s-3); align-items: start; }
  .portrait { max-width: 420px; }
  /* Card sizing is solved in JS — nothing to override here. */
}

@media (max-width: 760px) {
  .hero__bottom { flex-direction: column; align-items: flex-start; gap: 1rem; }
  .hero__ctrl { width: 100%; justify-content: space-between; }
  .service { grid-template-columns: 2.5rem 1fr; }
  .service__body { grid-column: 2; }
  .footer__top { grid-template-columns: 1fr; }
  .tl { grid-template-columns: 1fr; gap: 0.5rem; }
}

@media (max-width: 560px) {
  .card__meta { max-height: 3em; opacity: 1; margin-top: 0.25rem; }
  .nav__right { gap: 0.9rem; }
  .burger__text { display: none; }
  .filters { gap: 0.4rem; }
  .filter { padding: 0.5rem 0.85rem; font-size: 0.75rem; }
}

/* ========================= REDUCED MOTION ========================= */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal], .card, .lines > span > b, .hero__title span > b,
  .hero__sub, .hero__actions, .hero__bottom {
    opacity: 1 !important; transform: none !important; clip-path: none !important;
  }
  .cursor-fx { display: none; }
}
