/* ==========================================================================
   SMARTART DIGITAL — Design System
   Premium / cinematic / editorial / minimal. DM Sans + IBM Plex Mono.
   ========================================================================== */

:root {
  /* near-black -- primary ground */
  --black: #0a0a0a;
  --black-2: #080808;
  /* warm graphite -- first tonal step off black */
  --graphite: #141310;
  --graphite-2: #1b1916;
  --graphite-3: #201e1a;
  --line: #2a2723;
  --line-soft: rgba(242, 240, 234, 0.08);
  /* warm bone / ivory -- the light tonal break */
  --ivory: #ede9e1;
  --ivory-2: #e8e3da;
  --ink: #171613;
  --ink-soft: #47443d;
  /* neutral off-white text on dark grounds */
  --off-white: #f2f0ea;
  --warm-gray: #8f8a7e;
  --warm-gray-dim: #5c584f;
  /* champagne/brass -- premium accent, used sparingly */
  --brass: #b68f56;
  --brass-soft: #8a7550;
  --brass-bright: #d1ac74;
  /* functional (accessible) variants, distinct from the decorative
     brass above: darker brass for small text on ivory, lighter gray
     for small text on black — both chosen for readable contrast, not
     just palette-matching. */
  --brass-ink: #7a5c34;
  --gray-functional: #a39d8f;

  --font-sans: "DM Sans", -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", monospace;
  --font-display: var(--font-sans);

  --ease: cubic-bezier(0.65, 0, 0.15, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

  /* 12-column desktop system: every section-level content max-width is a
     multiple of --col so the same invisible vertical axes run underneath
     different compositions (Hero, H2, Services, In Person, Journal,
     Contact) without forcing them to look alike. */
  --max: clamp(1400px, 92vw, 1680px);
  --col: calc(var(--max) / 12);
  --gutter: clamp(20px, 4.4vw, 64px);
  /* For a section that carries its OWN gutter padding AND a max-width
     cap on the same element: capping at --max there would inset content
     by gutter twice (the centering margin plus the padding), landing it
     ~1 gutter further right than sections capped on an inner wrapper
     (e.g. .screen-h2). This is --max already inclusive of that padding,
     so the padded content box lands at exactly --max wide either way. */
  --max-padded: calc(var(--max) + 2 * var(--gutter));

  --h1: clamp(2.6rem, 8vw, 7.4rem);
  --h2: clamp(1.7rem, 4.2vw, 3.9rem);
  /* Shared size for every section-opening headline EXCEPT the Hero H1
     itself (--h1, untouched) — MADE VISIBLE is the reference; H2, Services,
     In Person, Closing and every inner-page hero title match it exactly. */
  --h-major: clamp(2.6rem, 6.4vw, 5.2rem);
}

/* ---------- large-desktop / ultrawide: content and type keep growing past
   the standard-desktop cap instead of just banking the extra width as dead
   margin (a 1440 composition should not simply float in a 2560 canvas) ---------- */
@media (min-width: 1800px) {
  :root {
    --max: clamp(1680px, 74vw, 1900px);
    --gutter: clamp(64px, 4.6vw, 100px);
    --h1: clamp(7.4rem, 6vw, 8.6rem);
    --h2: clamp(3.9rem, 3.2vw, 4.6rem);
    --h-major: clamp(5.2rem, 4vw, 6rem);
  }
}

/* ---------- tonal-break sections: warm bone/ivory chapters ---------- */
.tone-light {
  background: var(--ivory);
  color: var(--ink);
}
.tone-light .mono { color: var(--ink-soft); }
.tone-light a { color: var(--ink); }
.tone-light .brass-line { background: var(--brass); }
/* accessible brass-on-ivory: the decorative --brass is too light for
   small text at this contrast; text uses the darker functional variant */
.tone-light .jt-row-cat,
.tone-light .portrait-info .more,
body.tone-light .filter-bar button[aria-pressed="true"] { color: var(--brass-ink); }

/* full-page light world: dedicated Journal + article pages */
body.tone-light { background: var(--ivory); color: var(--ink); }
body.tone-light .page-descriptor,
body.tone-light .page-lede { color: var(--ink-soft); }
body.tone-light .filter-bar button { color: var(--ink-soft); }
body.tone-light .filter-bar button[aria-pressed="true"] { color: var(--brass); }
body.tone-light .filter-bar button:hover { color: var(--ink); }
body.tone-light .journal-list,
body.tone-light .journal-list article,
body.tone-light .jt-row,
body.tone-light .jt-row:last-child { border-color: rgba(23,22,19,0.14); }
body.tone-light .jf-media,
body.tone-light .article-hero-media { background: var(--graphite-3); }
body.tone-light .article-body p { color: var(--ink); }
body.tone-light .case-next { border-color: rgba(23,22,19,0.14); }
body.tone-light .site-footer {
  background: var(--ivory); border-top: 1px solid rgba(23,22,19,0.14); color: var(--ink-soft);
}
body.tone-light .site-footer .wordmark { color: var(--ink); }
body.tone-light .footer-meta { color: var(--ink-soft); }

/* ---------- display-headline hygiene: no terminal punctuation clutter ---------- */
.headline-dash { margin: 0 0.5em; color: var(--brass); }

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

html { background: var(--black); }

body {
  background: var(--black);
  color: var(--off-white);
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.5;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

body.lock { overflow: hidden; height: 100vh; }

img, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; background: none; border: none; cursor: pointer; color: inherit; }
ul { list-style: none; }

::selection { background: var(--brass); color: var(--black); }

.mono {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

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

/* ---------- grain ---------- */
.grain {
  position: fixed; inset: 0; z-index: 9997;
  pointer-events: none; opacity: 0.016; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* Full ivory/editorial pages (Journal, article) drop it further still —
   texture over dark cinematic sections, not over light reading pages. */
body.tone-light .grain { opacity: 0.006; }

/* ==========================================================================
   CURSOR
   ========================================================================== */
.cursor {
  position: fixed; top: 0; left: 0;
  width: 8px; height: 8px; margin: -4px 0 0 -4px;
  border-radius: 50%; background: var(--off-white);
  pointer-events: none; z-index: 9999;
  transform: translate3d(0,0,0);
  transition: width .3s var(--ease), height .3s var(--ease), background .3s var(--ease), opacity .3s var(--ease);
  mix-blend-mode: difference;
}
.cursor-label {
  position: fixed; top: 0; left: 0; z-index: 9999;
  transform: translate3d(0,0,0);
  font-family: var(--font-mono); font-size: 0.65rem; letter-spacing: 0.14em;
  color: var(--black); background: var(--off-white);
  padding: 0.3em 0.7em; border-radius: 100px;
  pointer-events: none; opacity: 0; transition: opacity .25s var(--ease);
  white-space: nowrap;
}
.cursor-label.show { opacity: 1; }
@media (hover: none), (pointer: coarse) {
  .cursor, .cursor-label { display: none; }
}

/* ==========================================================================
   PRE-ENTRY
   ========================================================================== */
.pre-entry {
  position: fixed; inset: 0; z-index: 10000;
  background: var(--black-2);
  display: flex; align-items: center; justify-content: center;
  transition: opacity .9s var(--ease), visibility .9s var(--ease);
}
.pre-entry.hidden { opacity: 0; visibility: hidden; pointer-events: none; }

.pre-entry-inner {
  display: flex; flex-direction: column; align-items: center; gap: 1.9rem;
}
.pre-loader-line {
  width: min(30vw, 220px); height: 1px; background: var(--line);
  position: relative; overflow: hidden;
}
.pre-loader-line span {
  position: absolute; inset: 0; width: 0%;
  background: var(--brass); display: block;
}
.pre-wordmark {
  font-size: clamp(1.8rem, 4.4vw, 2.6rem);
  letter-spacing: 0.16em; font-weight: 500;
  position: relative; overflow: hidden;
  background: linear-gradient(90deg, var(--off-white) 0%, var(--off-white) 64%, var(--brass-bright) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.pre-wordmark::after {
  content: ""; position: absolute; top: 0; left: -60%; width: 35%; height: 100%;
  background: linear-gradient(115deg, transparent, rgba(255,255,255,0.5), transparent);
  mix-blend-mode: overlay; pointer-events: none;
  animation: preWordmarkSweep 1.6s ease-out 0.5s 1 both;
}
@keyframes preWordmarkSweep { to { left: 130%; } }
@media (prefers-reduced-motion: reduce) { .pre-wordmark::after { animation: none; display: none; } }
.pre-line {
  width: min(20vw, 150px); height: 1px;
  background: linear-gradient(90deg, transparent, var(--brass-soft), transparent);
  transform-origin: center;
}
.pre-start {
  display: flex; flex-direction: column; align-items: center; gap: 1.6rem;
  opacity: 0; transform: translateY(10px);
  transition: opacity .8s var(--ease), transform .8s var(--ease);
}
.pre-start.show { opacity: 1; transform: translateY(0); }
.pre-start-btn {
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.28em;
  color: var(--warm-gray); cursor: pointer; padding: 0.4em 0;
  border-bottom: 1px solid var(--line); transition: color .35s var(--ease), border-color .35s var(--ease);
}
.pre-start-btn:hover, .pre-start-btn:focus-visible { color: var(--off-white); border-color: var(--brass-soft); }
.pre-entry.is-dismissing .pre-loader-line { opacity: 0; transition: opacity .3s var(--ease); }

/* ==========================================================================
   HEADER + MENU
   ========================================================================== */
.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 500;
  /* Same ultrawide inset as the capped content sections below it, but via
     padding alone rather than max-width + margin-inline:auto — that
     combination on a position:fixed, mix-blend-mode element was tried and
     caused rendering corruption (ghosted/doubled content) on scroll. */
  padding: 1.6rem max(var(--gutter), calc((100vw - var(--max)) / 2));
  display: flex; align-items: center; justify-content: space-between;
  mix-blend-mode: difference;
}
.wordmark {
  font-size: 1rem; letter-spacing: 0.14em; font-weight: 500; color: var(--off-white);
}
/* premium gold treatment: three-stop gradient (not a hard two-tone split)
   so the letterforms carry a real warm transition instead of a flat
   white-then-suddenly-gold edge. A blend-mode specular sweep was tried
   here (nested mix-blend-mode inside the header's own difference blend)
   and caused ghosted/doubled rendering on some GPUs — removed; the
   gradient alone carries the premium read without the compositing risk. */
.site-header .wordmark {
  background: linear-gradient(90deg, var(--off-white) 0%, var(--off-white) 42%, var(--brass) 74%, var(--brass-bright) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.menu-trigger {
  display: flex; flex-direction: column; justify-content: center; gap: 6px;
  width: 34px; height: 20px; z-index: 501;
}
.menu-trigger span {
  display: block; height: 1px; width: 100%; background: var(--off-white);
  transition: transform .4s var(--ease), opacity .3s var(--ease);
}
.menu-trigger.active span:first-child { transform: translateY(3.5px) rotate(45deg); }
.menu-trigger.active span:last-child { transform: translateY(-3.5px) rotate(-45deg); }

.menu-panel {
  position: fixed; top: 0; right: 0; height: 100%;
  width: min(64vw, 620px);
  background: var(--graphite);
  border-left: 1px solid var(--line);
  z-index: 480;
  display: flex; flex-direction: column; justify-content: space-between;
  padding: clamp(6rem, 10vw, 8rem) var(--gutter) 3rem;
  transform: translateX(100%);
  transition: transform .7s var(--ease);
}
.menu-panel.open { transform: translateX(0); }
.menu-list { display: flex; flex-direction: column; gap: 0.4rem; }
.menu-list li { overflow: hidden; }
.menu-list a {
  display: inline-block; font-size: clamp(1.5rem, 3.4vw, 2.4rem);
  color: var(--warm-gray); padding: 0.5rem 0; transition: color .3s var(--ease);
}
.menu-list a:hover, .menu-list a:focus-visible { color: var(--off-white); }
.menu-list a.current { color: var(--off-white); position: relative; padding-left: 1.1em; }
.menu-list a.current::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 0.6em; height: 1px; background: var(--brass);
}
.menu-foot { display: flex; flex-direction: column; gap: 1rem; }
/* Desktop only: the panel used to spread nav links to the top edge and
   contact/lang/social to the bottom edge via space-between, so the menu
   read as filling the entire screen height. Clustering both groups at
   the top instead (where the panel already visually originates, right
   under the trigger) keeps it compact without moving it — same corner,
   just no longer stretched. Mobile keeps the original full-height,
   full-screen feel untouched. */
@media (min-width: 901px) {
  /* height:70vh, not 100% — the panel reads as a large floating
     editorial overlay anchored to the top-right corner rather than a
     full-height curtain, and the page content stays visible under it.
     .menu-backdrop dims the same area, not the whole viewport — inset:0
     pins its bottom edge to the screen bottom regardless of any height
     value, so bottom must be released to auto before height can
     actually take effect.
     Row, not column: nav links left, lang/email/social as a smaller
     secondary block on the right, both starting at the same top edge
     (align-items:flex-start) so the block lines up level with HOME.
     A single-column version (lang/email/social clustered under the nav
     links, taller panel) was also tried — this one reads better: the
     single-column variant left visible empty space under the content
     once the panel got taller, since flex-start doesn't stretch content
     to fill it; two columns actually use the width instead of leaving
     it dead. */
  .menu-panel {
    flex-direction: row; justify-content: space-between; align-items: flex-start;
    height: 70vh;
  }
  .menu-list a { font-size: clamp(1.1rem, 1.8vw, 1.5rem); }
  /* Back to the plain two-column layout (no location line, no extra
     offset) — only addition kept is the thin brass divider, tying the
     two columns together as one considered grid instead of two
     disconnected blocks. */
  .menu-foot { gap: 0.85rem; border-left: 1px solid var(--brass-soft); padding-left: 2rem; margin-top: 0.3cm; }
  .menu-backdrop { top: 0; right: 0; left: 0; bottom: auto; height: 70vh; }
}
.menu-lang { display: flex; gap: 0.8rem; }
.menu-lang button {
  font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.1em;
  color: var(--warm-gray-dim);
}
.menu-lang button[aria-pressed="true"] { color: var(--brass); }
.menu-lang button:disabled { opacity: 0.4; cursor: not-allowed; }
.menu-social { display: flex; gap: 1.6rem; font-family: var(--font-mono); font-size: 0.72rem; }
.menu-email { font-family: var(--font-mono); font-size: 0.78rem; }
/* The menu overlay is always dark regardless of the page it sits over —
   but `.tone-light a` (light-toned pages like Journal) targets every
   <a> on the page by tag, which out-specifies a plain class selector
   like .menu-email or inherited color from .menu-social. That silently
   swapped these two links to near-black text on the menu's dark
   background on tone-light pages only (invisible, not just wrong).
   Scoping under .menu-panel adds a class, which is enough to always win
   regardless of what tone the page underneath happens to be. */
.menu-panel .menu-email { color: var(--off-white); }
.menu-panel .menu-social a { color: var(--warm-gray); }
.menu-panel .menu-social a:hover { color: var(--brass); }

.menu-backdrop {
  position: fixed; inset: 0; z-index: 470; background: rgba(10,10,10,0.5);
  opacity: 0; pointer-events: none; transition: opacity .6s var(--ease);
}
.menu-backdrop.open { opacity: 1; pointer-events: auto; }

/* ==========================================================================
   HERO
   ========================================================================== */
.hero {
  position: relative; height: 100svh; min-height: 560px;
  display: flex; flex-direction: column; justify-content: flex-end;
  overflow: hidden; background: var(--black);
}
.hero-media {
  position: absolute; inset: 0; z-index: 0;
  clip-path: inset(49.5% 0 49.5% 0);
}
.hero-video-wrap { position: absolute; inset: 0; overflow: hidden; }
.hero-video {
  width: 100%; height: 100%; object-fit: cover;
  filter: brightness(0.62) saturate(0.85);
}
.hero-overlay {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(10,10,10,0.5) 0%, rgba(10,10,10,0.05) 32%, rgba(10,10,10,0.3) 64%, rgba(10,10,10,0.94) 100%);
}

.hero-content {
  position: relative; z-index: 2; padding: 0 var(--gutter) 5.5rem; max-width: calc(var(--col) * 9);
}
.hero-title {
  font-size: var(--h1); font-weight: 500; line-height: 1.05; letter-spacing: -0.02em;
  color: var(--off-white);
}
/* Serbian runs a few characters longer than English here — at the base
   size "SAMO PRVA VERZIJA" wraps to its own second line, landing 3
   lines total instead of 2. A small trim is enough to fit both lines
   at their intended split without visibly reading as a different
   scale from the English version. */
@media (min-width: 901px) {
  html[lang="sr"] .hero-title { font-size: calc(var(--h1) * 0.95); }
}
/* No overflow:hidden clip-reveal: an overflow-clipped parent around a
   transform-animated child was leaving a stale ghost of the pre-animation
   text position visible on some GPUs, even after the reveal settled and
   even without any will-change hint. The whole line now just fades/rises
   into place instead of sliding out from behind a clip mask. */
.hero-title .line { display: block; }
.hero-title .line > span { display: inline-block; }
.hero-title .word { display: inline-block; }

.hero-scroll {
  position: absolute; bottom: 2.2rem; right: var(--gutter); z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: 0.6rem;
}
.scroll-line { width: 1px; height: 42px; background: linear-gradient(180deg, var(--brass), transparent); }
.scroll-label {
  writing-mode: vertical-rl; font-family: var(--font-mono); font-size: 0.62rem;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--warm-gray);
}

/* sound toggle, global */
.sound-toggle {
  position: fixed; bottom: 2.2rem; left: var(--gutter); z-index: 460;
  display: flex; align-items: center; gap: 0.6rem;
  font-family: var(--font-mono); font-size: 0.65rem; letter-spacing: 0.14em;
  color: var(--warm-gray); mix-blend-mode: difference;
}
.sound-toggle .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--warm-gray-dim); transition: background .3s var(--ease); }
.sound-toggle[aria-pressed="true"] .dot { background: var(--brass); }
.sound-toggle:hover { color: var(--off-white); }

.footer-award {
  display: flex; align-items: center; gap: 0.4rem; text-decoration: none;
  font-family: var(--font-mono); font-size: 0.62rem; font-weight: 600; letter-spacing: 0.08em;
  color: var(--brass); opacity: 0.85; transition: opacity .3s var(--ease), color .3s var(--ease);
}
.footer-award:hover { opacity: 1; color: var(--brass-bright); }
.footer-award img { display: block; width: 16px; height: 16px; flex-shrink: 0; }

/* ==========================================================================
   H2 TRANSITION (THE SCREEN IS NOT THE END OF IT.)
   ========================================================================== */
.screen-transition {
  position: relative; min-height: 100vh; background: var(--graphite);
  display: flex; align-items: center; overflow: hidden;
  padding: clamp(6rem, 11vw, 9rem) var(--gutter);
}
.screen-transition-grid { width: 100%; max-width: var(--max); margin-inline: auto; display: flex; flex-direction: column; }
.screen-h2 {
  font-size: var(--h-major); font-weight: 500; line-height: 1.1; letter-spacing: -0.015em;
  margin-bottom: clamp(3.5rem, 7vw, 6rem);
  text-align: center;
}
/* One line, centered — not two stacked left-aligned lines. */
.screen-h2 .line { display: inline; }
.screen-h2 .line > span { display: inline; }
/* Both .line spans flow inline together and wrap wherever the text
   naturally runs out of room — usually lands between the two lines by
   coincidence, but Serbian's word lengths break mid-phrase instead
   ("KRAJ" / "PRIČE" split across lines). Forces the intended line1/
   line2 split instead, Serbian mobile only — EN and desktop keep their
   existing (already-fine) natural wrap. */
.sr-h2-break { display: none; }
@media (max-width: 900px) {
  html[lang="sr"] .sr-h2-break { display: block; }
}

.screen-strip {
  position: relative;
  /* Slightly smaller than the full column: at full width the film alone
     was tall enough to consume the entire section, leaving no real room
     for .screen-editorial to center in below it. */
  width: 88%; margin-inline: auto; aspect-ratio: 16 / 9; overflow: hidden; background: var(--graphite-2);
  clip-path: inset(48% 0 48% 0);
}
.screen-strip.revealed { clip-path: inset(0 0 0 0); transition: clip-path 1.4s var(--ease-out); }
.screen-strip img, .screen-strip video { width: 100%; height: 100%; object-fit: cover; }
.screen-strip video { filter: brightness(0.72) saturate(0.86); }
/* Shared "play this film's original sound" control — used on the H2
   office film and the Hero film, both original-audio videos a visitor
   can opt into on top of the site's own ambient/sfx track. */
.strip-sound {
  position: absolute; bottom: 1.1rem; right: 1.1rem; z-index: 2;
  width: 40px; height: 40px; border-radius: 50%;
  background: rgba(10,10,10,0.72); backdrop-filter: blur(6px);
  border: 1px solid rgba(242,240,234,0.35);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.78rem; color: var(--off-white);
  opacity: 0.95; transition: opacity .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease);
}
.strip-sound:hover, .strip-sound[aria-pressed="true"] {
  opacity: 1; color: var(--brass); border-color: var(--brass);
}
/* Hero already has the scroll indicator anchored to this same corner —
   sit above it instead of overlapping. */
.hero-media .strip-sound { bottom: 6.4rem; }

.screen-editorial {
  /* Matches the title-to-video gap above, so the video reads as
     deliberately spaced from both neighbors rather than hugging the
     text right below it. */
  margin-top: clamp(3.5rem, 7vw, 6rem);
  display: grid; grid-template-columns: 1fr 1fr; gap: 4vw; max-width: calc(var(--col) * 7);
}
.screen-editorial .se-col .se-label {
  font-family: var(--font-mono); font-size: 0.65rem; letter-spacing: 0.14em; color: var(--brass);
  margin-bottom: 0.9rem; display: block;
}
.screen-editorial .se-col p {
  font-size: 1rem; color: var(--warm-gray); line-height: 1.6; max-width: 380px;
}

@media (max-width: 900px) {
  .screen-strip { width: 100%; }
  .screen-editorial { grid-template-columns: 1fr; gap: 2rem; }
}

/* ==========================================================================
   MADE VISIBLE — pinned horizontal editorial portfolio, cinematic stage
   ========================================================================== */
.made-visible { background: var(--black); overflow: hidden; }
.mv-heading {
  padding: clamp(5rem, 9vw, 7rem) var(--gutter) clamp(3rem, 6vw, 5rem);
  max-width: var(--max-padded); margin-inline: auto;
  display: flex; align-items: baseline; justify-content: space-between; gap: 2rem; flex-wrap: wrap;
  position: relative;
}
.mv-tag { font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.14em; color: var(--warm-gray); }

/* rail: grows left->right on entry, threads through the section */
.mv-rail {
  position: absolute; left: var(--gutter); right: var(--gutter); bottom: 0;
  height: 1px; background: var(--line); overflow: hidden;
}
.mv-rail::after {
  content: ""; position: absolute; inset: 0; background: var(--brass);
  transform: scaleX(0); transform-origin: left; transition: transform 1.1s var(--ease-out);
}
.mv-rail.grown::after { transform: scaleX(1); }

.mv-track-wrap { position: relative; height: 100vh; min-height: 560px; display: flex; align-items: center; overflow: hidden; }
/* Flush with the wrap's own bottom edge — since every piece is centered
   in this wrap (align-items:center), that makes the gap from the piece
   down to this line exactly equal the gap from the wrap's top down to
   the piece, instead of a fixed 8% that didn't track the piece's actual
   (now-unified) height. */
.mv-track-wrap::after {
  content: ""; position: absolute; left: var(--gutter); right: var(--gutter); bottom: 0;
  height: 1px; background: var(--brass-soft); opacity: 0.5; pointer-events: none;
}
/* symmetric edge padding: lets the first AND last piece reach a
   centered, fully-visible state, not only the one nearest the end */
.mv-track { display: flex; align-items: center; gap: 7vw; padding: 0 14vw; will-change: transform; }

/* one consistent cinematic stage for every work — same height as the
   4-portrait gallery stage. Shorter than the wrap's own 100vh on purpose:
   the leftover space is what gives the rail (above) and the line (below)
   real breathing room instead of the frame nearly touching both. Width
   still varies by piece. */
.mv-piece {
  position: relative; flex: 0 0 auto; overflow: hidden;
  width: min(74vw, 1180px); height: min(66vh, 620px);
  background: var(--graphite);
  border: 1px solid var(--line-soft);
  /* Restrained, in-keeping-with-the-site tonal treatment instead of raw
     footage at full brightness/saturation — subtler at rest, easing up
     (not all the way to "raw") once a piece is actually in focus. */
  transform: scale(0.94); filter: brightness(0.75) saturate(0.85);
  transition: transform .38s var(--ease-out), filter .38s var(--ease-out);
}
.mv-piece.is-active { transform: scale(1); filter: brightness(0.88) saturate(0.94); }
.mv-piece::before {
  content: ""; position: absolute; top: -1px; right: -1px; width: 46px; height: 1px; background: var(--brass-soft); opacity: 0.75;
}
.mv-piece::after {
  content: ""; position: absolute; bottom: -1px; right: -1px; width: 1px; height: 46px; background: var(--brass-soft); opacity: 0.75;
}
.mv-piece video, .mv-piece img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* Smederevo: contain-fit at the default box height left visible graphite
   letterboxing around the video (its aspect ratio doesn't match the box) —
   match the gallery piece's height and crop-fill instead, so the frame
   reads as snug around the footage the same way the gallery does. */
.mv-piece[data-media="workSmederevo"] { height: min(72vh, 660px); }
.mv-piece[data-media="workSmederevo"] video { object-fit: cover; }
.mv-piece[data-media="workWebsite"] { height: min(72vh, 660px); }
.mv-piece[data-media="workWebsite"] video { object-fit: cover; }
.mv-piece[data-media="workWebsite"]::before,
.mv-piece[data-media="workWebsite"]::after { display: none; }
/* Soft edge vignette (not a flat dark film over everything) — center
   stays clear, the frame's own edges ease toward the graphite ground it
   sits on. Sits above the video, below the sound/index labels. */
.mv-vignette {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(ellipse at center, transparent 50%, rgba(10,9,8,0.42) 100%);
}
/* vertical works: true native aspect ratio, never cropped into a
   synthetic box — height fixed, width follows the source, with
   intentional graphite negative space either side */
.mv-piece.is-vertical { display: flex; align-items: center; justify-content: center; }
.mv-piece.is-vertical video, .mv-piece.is-vertical img {
  width: auto; height: 90%; max-width: 42%; object-fit: contain;
}
.mv-piece .mv-frame-lines { position: absolute; inset: 0; pointer-events: none; display: none; }
.mv-piece.is-vertical .mv-frame-lines { display: block; }
.mv-piece.is-vertical .mv-frame-lines::before,
.mv-piece.is-vertical .mv-frame-lines::after {
  content: ""; position: absolute; left: 12%; right: 12%; height: 1px; background: var(--line-soft);
}
.mv-piece.is-vertical .mv-frame-lines::before { top: 9%; }
.mv-piece.is-vertical .mv-frame-lines::after { bottom: 9%; }

.mv-piece .mv-sound {
  position: absolute; bottom: 1rem; right: 1rem; z-index: 2;
  width: 34px; height: 34px; border-radius: 50%;
  background: rgba(10,10,10,0.55); backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  /* always at least dimly visible so it reads as a real control, not
     something that only exists on hover (which touch visitors never
     get) — full opacity once the piece is active/hovered/engaged. */
  opacity: 0.6; transition: opacity .3s var(--ease);
  font-family: var(--font-mono); font-size: 0.65rem; color: var(--off-white);
}
/* JS marks the in-view piece "is-active" — this previously read "active"
   and never matched, so the icon was effectively hover-only. */
.mv-piece.is-active .mv-sound,
.mv-piece:hover .mv-sound,
.mv-piece .mv-sound[aria-pressed="true"] { opacity: 1; }
.mv-piece .mv-sound[aria-pressed="true"] { color: var(--brass); }

/* gallery stage: one cinematic frame carrying four vertical works at once —
   wider than the single-work stage since it holds four, and a bit taller
   too: its cells use object-fit:cover (crop-to-fill), so shrinking this
   frame the same amount as the single-video stages cropped noticeably
   more out of each portrait video than the plain letterboxed pieces lost. */
.mv-piece.is-gallery {
  width: min(96vw, 1640px); height: min(72vh, 660px);
  display: flex; align-items: stretch; justify-content: center;
}
.mv-gallery-grid {
  display: flex; align-items: stretch; justify-content: center;
  width: 100%; height: 100%; gap: clamp(18px, 2.2vw, 34px);
  padding: clamp(14px, 1.8vw, 24px);
}
.mv-gallery-cell {
  position: relative; flex: 1 1 0; min-width: 0; overflow: hidden;
  background: var(--graphite-2);
}
.mv-gallery-cell video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block;
  filter: brightness(0.75) saturate(0.85);
  transition: transform .6s var(--ease-out), filter .38s var(--ease-out);
}
.mv-gallery-cell:hover video { transform: scale(1.03); }
.mv-piece.is-active .mv-gallery-cell video { filter: brightness(0.88) saturate(0.94); }
.mv-gallery-cell .mv-vignette {
  background: radial-gradient(ellipse at center, transparent 42%, rgba(10,9,8,0.48) 100%);
}

/* ==========================================================================
   SERVICES
   ========================================================================== */
.services { padding: clamp(7.5rem, 14vw, 11rem) var(--gutter); max-width: var(--max-padded); margin-inline: auto; border-top: 1px solid var(--line); }
/* One designed title, one line on desktop — not two justified rows with
   dead space stretched between each word. Wraps gracefully on narrow
   viewports via flex-wrap rather than a separate stacked layout. */
.services-title {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center;
  gap: 0.3em 0.34em;
  font-size: var(--h-major); font-weight: 500; letter-spacing: -0.015em;
  line-height: 1.15; max-width: calc(var(--col) * 11);
  /* Centered — equal distance from both edges — instead of sitting at
     the left gutter like a ragged-left section title. */
  margin-inline: auto;
  text-align: center;
  /* Same gap below the title (down to the first service row's line) as
     above it (the section's own top padding/divider), instead of a
     visibly smaller margin. Both grown a bit so the title itself gets
     more breathing room, not just tight against its neighbors. */
  margin-bottom: clamp(7.5rem, 14vw, 11rem);
}
.services-title i { font-style: normal; }

.services-grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: 5vw; align-items: start; }
.services-list { display: flex; flex-direction: column; }
.service-row {
  display: flex; align-items: baseline; gap: 1.6rem;
  padding: 1.5rem 0; border-top: 1px solid var(--line);
  transition: opacity .4s var(--ease);
  cursor: default;
}
.services-list:hover .service-row { opacity: 0.4; }
.services-list .service-row:hover,
.services-list .service-row.is-active { opacity: 1; }
.service-row:last-child { border-bottom: 1px solid var(--line); }
.service-row:focus-visible { outline: 1px solid var(--brass-soft); outline-offset: 4px; }
.service-num { font-family: var(--font-mono); font-size: 0.72rem; color: var(--brass); transition: color .3s var(--ease); }
.service-row.is-active .service-num { color: var(--brass-bright); }
.service-title { font-size: clamp(1.3rem, 2.6vw, 2rem); font-weight: 500; letter-spacing: -0.01em; }
.service-tap {
  font-size: 0.6rem; font-weight: 400; letter-spacing: 0.14em; color: var(--warm-gray);
  vertical-align: middle; margin-left: 0.3em; opacity: 0.65;
}
.service-row.is-active .service-tap { display: none; }
.service-copy { font-size: 0.85rem; color: var(--warm-gray); max-width: 320px; margin-top: 0.5rem; display: none; }
.service-row:hover .service-copy, .service-row.is-active .service-copy { display: block; }

/* adaptive media stage: stable outer box, media fits without cropping */
.services-preview {
  position: sticky; top: 6rem;
  /* Centered within its column instead of flush against the left edge
     of the (wider) grid cell — shifts it right and balances the space
     around it. */
  margin-inline: auto;
  width: 100%; max-width: 480px; height: min(65vh, 560px);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; opacity: 0; transition: opacity .5s var(--ease);
  transform: translateY(-1cm);
}
.services-preview.show { opacity: 1; }
.services-preview video, .services-preview img {
  max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain;
  transition: opacity .28s var(--ease), transform .5s var(--ease-out);
}
.services-preview.is-portrait video, .services-preview.is-portrait img { height: 92%; width: auto; }
.services-preview.switching video, .services-preview.switching img { opacity: 0; transform: scale(0.98); }

@media (max-width: 900px) {
  .services-grid { grid-template-columns: 1fr; }
  .services-preview { position: relative; top: auto; transform: none; max-width: 100%; height: min(74vw, 420px); margin: 0.3rem 0 1.5rem; }
  .service-copy { display: block !important; }
}

/* ==========================================================================
   SMARTART, IN PERSON — asymmetric editorial portrait spread (light chapter)
   ========================================================================== */
.in-person { padding: clamp(6rem, 12vw, 9rem) var(--gutter); max-width: var(--max-padded); margin-inline: auto; border-top: 1px solid var(--line); }
.tone-light.in-person { border-top: 1px solid rgba(23,22,19,0.1); }
.in-person-title {
  font-size: var(--h-major); font-weight: 500; letter-spacing: -0.02em; line-height: 1.08;
  margin-bottom: clamp(3.5rem, 8vw, 6.5rem); max-width: calc(var(--col) * 10);
  margin-inline: auto;
  text-align: center;
}
/* Both lines are inline-block so text-align:center actually centers them
   (a block-level line would just span full width and center its own
   text, not the line itself). */
.in-person-title .ip-line { display: inline-block; }
.in-person-title .ip-line-1 { display: block; }
.in-person-title .ip-line-2 {
  margin-top: 0.12em;
}

.portrait-grid {
  position: relative; margin: 0 auto;
  display: grid; grid-template-columns: 1.1fr 0.92fr;
  /* Wider gap pushes Gordan left and Sandra right, away from the
     centerline — the max-width grows to match so the extra gap doesn't
     just shrink both photos to make room. */
  column-gap: clamp(3rem, 6vw, 6rem);
  max-width: calc(var(--col) * 10);
}
.portrait-grid::before {
  /* Exact midpoint of the gap for a 1.1fr / 0.92fr split (not the
     eyeballed 55% this used to be) — so both photos sit precisely the
     same distance from the line regardless of their own width ratio. */
  content: ""; position: absolute; left: calc(1.1 / 2.02 * 100%); top: 4%; width: 1px; height: 60%;
  background: linear-gradient(180deg, transparent, var(--brass-soft) 40%, transparent);
  opacity: 0.6; pointer-events: none;
}
.portrait-card { display: flex; flex-direction: column; gap: 1.4rem; }
.portrait-card--primary { grid-column: 1; }
.portrait-card--primary .portrait-frame { transform: scale(0.95); }
/* Center-anchored scale pulls the frame's own left edge in by half the
   shrink (2.5%) — nudge the caption block the same amount so it still
   lines up under the photo's new edge instead of the old one. */
.portrait-card--primary .portrait-info { margin-left: 2.5%; }
.portrait-card--secondary { grid-column: 2; margin-top: clamp(2rem, 5vw, 4rem); max-width: 94%; }

.portrait-frame {
  display: block; position: relative; aspect-ratio: 4 / 5; overflow: hidden; background: var(--graphite);
  cursor: pointer;
}
.portrait-frame img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transition: opacity .8s var(--ease), transform .7s var(--ease);
}
.portrait-frame img.bw { filter: grayscale(1) contrast(1.05) brightness(0.95); opacity: 1; }
.portrait-frame img.color { opacity: 0; }
.portrait-frame.in-view img.color { opacity: 1; }
.portrait-frame.in-view img.bw { opacity: 0; }
.portrait-frame.in-view img { transform: scale(1.025); }

.portrait-info h3 { font-size: 1.15rem; font-weight: 500; letter-spacing: 0.01em; }
.portrait-info .role { font-size: 0.85rem; color: var(--ink-soft); margin-top: 0.25rem; }
.tone-light .portrait-info .role { color: var(--ink-soft); }
.portrait-info .more {
  display: inline-block; margin-top: 0.9rem; font-family: var(--font-mono);
  font-size: 0.66rem; letter-spacing: 0.1em; color: var(--brass); border-bottom: 1px solid var(--brass-soft);
}

@media (max-width: 640px) {
  .portrait-grid { grid-template-columns: 1fr; max-width: 420px; }
  .portrait-grid::before { display: none; }
  .portrait-card--primary, .portrait-card--secondary { grid-column: 1; margin-top: 0; max-width: 100%; }
  .portrait-card + .portrait-card { margin-top: 2.5rem; }
}

/* ==========================================================================
   JOURNAL TEASER
   ========================================================================== */
.journal-teaser { padding: clamp(6rem, 12vw, 9rem) var(--gutter); max-width: var(--max-padded); margin-inline: auto; border-top: 1px solid var(--line); }
.tone-light.journal-teaser { border-top: 1px solid rgba(23,22,19,0.1); }
.jt-title { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.16em; color: var(--warm-gray); margin-bottom: clamp(2.5rem, 5vw, 4rem); }
@media (max-width: 900px) {
  .journal-teaser { padding-top: calc(clamp(6rem, 12vw, 9rem) - 1cm); }
  .jt-title { font-weight: 600; }
}
.jt-list { display: flex; flex-direction: column; }
.jt-row {
  display: flex; align-items: center; justify-content: space-between; gap: 2rem;
  padding: 1.6rem 0; border-top: 1px solid var(--line);
}
.tone-light .jt-row { border-top: 1px solid rgba(23,22,19,0.12); }
.jt-row:last-child { border-bottom: 1px solid var(--line); }
.tone-light .jt-row:last-child { border-bottom: 1px solid rgba(23,22,19,0.12); }
.jt-row-title { font-size: clamp(1.1rem, 2vw, 1.5rem); font-weight: 400; max-width: 640px; color: inherit; }
.jt-row-cat { font-family: var(--font-mono); font-size: 0.65rem; letter-spacing: 0.1em; color: var(--brass); white-space: nowrap; }
.jt-row:hover .jt-row-title { color: var(--brass); transition: color .3s var(--ease); }

/* ==========================================================================
   CLOSING SIGNATURE
   ========================================================================== */
.closing { position: relative; height: 240vh; background: var(--black); }
.closing-stage { position: sticky; top: 0; height: 100svh; overflow: hidden; background: var(--black); }
.closing-layer { position: absolute; left: 0; width: 100%; height: 56%; overflow: hidden; }
.closing-layer.upper { top: 0; }
.closing-layer.lower { bottom: 0; }
.closing-layer video {
  position: absolute; left: 0; width: 100%; height: 100svh; object-fit: cover;
}
.closing-layer.upper video { top: 0; }
.closing-layer.lower video { bottom: 0; }
/* Permanent seam mask, independent of the shade fade timing/opacity and
   of the upper/lower panels being two independently-playing (unsynced)
   <video> elements — either of those could leave a sliver of the source
   footage's bright rim visible right at the panels' meeting line. This
   sits there always, so that line is covered outright rather than relying
   on the animation timing to hide it. */
.closing-stage::after {
  content: ""; position: absolute; left: 0; top: 50%; width: 100%; height: 28px;
  transform: translateY(-50%); background: var(--black); z-index: 2; pointer-events: none;
}

.closing-cta {
  position: absolute; inset: 0; z-index: 3;
  display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
  gap: 1.8rem; opacity: 0;
}
.closing-cta-title {
  font-size: var(--h-major); font-weight: 500; letter-spacing: -0.02em; line-height: 1.1;
}
.closing-start {
  font-family: var(--font-mono); font-size: 0.85rem; letter-spacing: 0.1em; color: var(--brass);
  border-bottom: 1px solid var(--brass-soft); padding-bottom: 0.3rem;
}
.closing-contacts { display: flex; gap: 2rem; margin-top: 0.6rem; font-family: var(--font-mono); font-size: 0.75rem; color: var(--warm-gray); }
.closing-contacts a:hover { color: var(--brass); }

/* ==========================================================================
   FOOTER
   ========================================================================== */
.site-footer {
  background: var(--black); border-top: 1px solid var(--line);
  padding: 2.4rem var(--gutter); display: flex; flex-wrap: wrap; gap: 1.2rem;
  align-items: center; justify-content: space-between;
}
.site-footer .wordmark { font-size: 0.85rem; }
.footer-meta { font-family: var(--font-mono); font-size: 0.68rem; color: var(--gray-functional); display: flex; gap: 1.6rem; }
.footer-info { display: flex; flex-direction: column; align-items: flex-end; gap: 0.5rem; }

/* Award credits: same fine-print register as .footer-meta, one step
   quieter, so recognition reads as a credential line rather than a badge. */
.footer-awards {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.1em;
  text-transform: uppercase; display: flex; flex-wrap: wrap; gap: 1.4rem;
}
/* Same ink as .footer-meta in both tones — the smaller size and wider
   tracking carry the hierarchy. Going a step greyer looked right on the
   dark footer but fell to 2.8:1 there and 2.2:1 on ivory, and this line
   contains links. */
.footer-awards a, .footer-awards span { color: var(--gray-functional); transition: color 0.4s var(--ease); }
.footer-awards a:hover { color: var(--brass); }
body.tone-light .footer-awards a, body.tone-light .footer-awards span { color: var(--ink-soft); }
body.tone-light .footer-awards a:hover { color: var(--brass-ink); }

/* Desktop: a hairline tick between the three credits so they read as
   separate entries instead of one long run of mono caps. Not after the
   last one — flush against the right edge it would look like a stray
   mark. Its colour is fixed rather than currentColor, so hovering a
   credit tints the text without dragging the divider brass with it.
   The flex gap gives way to symmetric margins around the tick. */
@media (min-width: 641px) {
  .footer-awards { gap: 0; }
  .footer-awards a:not(:last-child)::after {
    content: ""; display: inline-block;
    width: 1px; height: 0.85em;
    background: var(--warm-gray-dim);
    margin: 0 1.1rem; vertical-align: -0.12em;
  }
  body.tone-light .footer-awards a:not(:last-child)::after { background: rgba(23,22,19,0.25); }
}

/* Phone: the footer stops being a left/right row and stacks, so the
   flex-end alignment that keeps .footer-info hugging the right edge on
   desktop leaves the short copyright line indented while the wrapped
   award credits start at the left. Align everything to the same left
   edge as the wordmark and give the rows even, deliberate spacing. */
@media (max-width: 640px) {
  .footer-info { align-items: flex-start; gap: 0.8rem; width: 100%; }
  .footer-meta { flex-wrap: wrap; gap: 0.35rem 1.2rem; }
  .footer-awards { flex-direction: column; gap: 0.45rem; }
}

/* ==========================================================================
   SHARED: page hero / inner-page primitives
   ========================================================================== */
.page-hero {
  padding: clamp(9rem, 16vw, 12rem) var(--gutter) clamp(4rem, 8vw, 6rem);
}
/* Journal specifically — .page-hero itself has no max-width, so its
   text sat flush at the gutter while .journal-featured below it (which
   does have max-width + auto margins, same as .work-sequence) centered
   narrower, throwing the two out of alignment. Matching the same
   max-width/centering here lines their outer edges up. The extra
   padding-left on top of that accounts for .work-hscroll-track's own
   gutter padding (needed so the pinned row has entry room) stacking on
   top of .journal-featured's — the actual visible image content sits
   one more gutter-width in than a plain edge-match would land. */
body[data-page="journal.html"] .page-hero {
  max-width: var(--max-padded); margin-inline: auto;
  text-align: center;
}
body[data-page="journal.html"] .page-lede { margin-inline: auto; }
/* Studio ("SmartArt — In Person") — same centered treatment. */
body[data-page="studio.html"] .page-hero { text-align: center; }
/* "SMARTART LIČNO" reads better on its own second line than run into
   "SMARTART" on one — English "SMARTART IN PERSON" doesn't have the
   same issue, so this break only shows up for the Serbian title, and
   only on desktop (mobile already wraps this naturally at its own
   narrower width, no forced break needed there). */
.ip-title-break { display: none; }
@media (min-width: 901px) {
  html[lang="sr"] .ip-title-break { display: block; }
}
/* Contact ("Let's Make Something Worth Seeing") — centered too, with
   extra room below before the form starts. */
body[data-page="contact.html"] .page-hero {
  text-align: center;
  padding-top: calc(clamp(9rem, 16vw, 12rem) + 3cm);
  padding-bottom: calc(clamp(8rem, 14vw, 11rem) + 6.5cm);
}
.page-hero h1 {
  font-size: var(--h-major); font-weight: 500; line-height: 1.05; letter-spacing: -0.02em;
}
.page-hero h1 .line { display: block; }
.page-hero h1 .line > span { display: inline-block; }
.page-descriptor {
  margin-top: 1.6rem; font-family: var(--font-mono); font-size: 0.72rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--brass);
}

/* Services page: full-viewport image stands in for the title entirely
   (h1 kept for SEO/accessibility, visually hidden). */
.page-hero-visual {
  width: 100vw; height: 100vh; height: 100dvh;
  overflow: hidden;
}
.page-hero-visual img, .page-hero-visual video {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.page-hero-visual video { filter: brightness(0.7); }
/* Work page's made1.mp4 specifically — perceptual sharpening only (no
   real upscaling tool available to touch the source file itself): a
   contrast/saturation lift reads as crisper detail, and
   optimize-contrast hints the browser to favor a sharper scaling
   algorithm over its default smooth/blurred one. */
body[data-page="work.html"] .page-hero-visual video {
  filter: brightness(0.58) contrast(1.18) saturate(1.12);
  image-rendering: -webkit-optimize-contrast;
}
.page-lede { margin-top: 1.4rem; max-width: calc(var(--col) * 4); font-size: 1rem; color: var(--warm-gray); }
body.studio-page .page-lede { max-width: none; }

.text-link {
  font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.08em; color: var(--brass);
  border-bottom: 1px solid var(--brass-soft); padding-bottom: 0.2rem; width: fit-content;
}

/* ---------- filter bar ---------- */
.filter-bar { display: flex; gap: 1.6rem; padding: 0 var(--gutter) 3rem; font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.1em; }
.filter-bar button { color: var(--gray-functional); }
.filter-bar button[aria-pressed="true"] { color: var(--brass); }
.filter-bar button:hover { color: var(--off-white); }

/* ---------- work sequence (dedicated Work page) — large vertical editorial
   sequence reusing the MADE VISIBLE cinematic stage language, quieter ---------- */
.work-sequence {
  padding: 4cm var(--gutter) clamp(7rem, 12vw, 10rem); max-width: var(--max-padded); margin-inline: auto;
  display: flex; flex-direction: column; gap: 3cm;
}
.work-item, .work-group-cell { display: flex; flex-direction: column; align-items: center; gap: 1.4rem; }
/* Hscroll video trio (the pinned, sideways-sliding row) — 2cm less than
   the shared 3cm gap below it, so the trio -> poster row transition
   reads tighter too. Targets both the desktop case (GSAP wraps
   .work-hscroll-wrap in a .pin-spacer, which becomes the direct child
   instead) and the sub-900px case (no pin at all — .work-hscroll-wrap
   stays the direct child itself). */
.work-sequence > .pin-spacer,
.work-sequence > .work-hscroll-wrap { margin-bottom: -2cm; }

/* curated portrait rows: several vertical works sharing one row instead of
   each sitting alone in an oversized, mostly-empty landscape box.
   --row-gap-h is the horizontal gap between visuals sharing a row —
   deliberately separate from .work-sequence's vertical row-to-row gap
   above, which stays on its own original rhythm. */
.work-group {
  --row-gap-h: 4cm;
  display: flex; gap: var(--row-gap-h); align-items: flex-start; justify-content: center;
  width: 100%; max-width: calc(var(--col) * 10); margin: 0 auto;
}
/* Fixed per-cell width (not flex-grow-to-fill) so a 2-up row's cells come
   out the same size as a 3-up row's — a shorter row just reads as
   narrower/centered instead of stretching its two cells wider than the
   ones above, which is what was cropping them harder. */
.work-group-cell { flex: 0 1 calc(var(--col) * 3.2); min-width: 0; width: auto; }
.work-group .work-stage { max-width: 100%; margin: 0; width: 100%; }
.work-group .work-stage.is-vertical { max-width: 100%; }
/* Tall enough that a 3-up row reads as portrait cells, not near-square
   ones — at square-ish proportions cover-fit was cropping away most of
   each vertical piece's actual composition. */
.work-group .work-stage { height: min(80vh, 760px); }

@media (max-width: 900px) {
  /* align-items:flex-start on the base rule top-aligns cells in the
     desktop row — once flex-direction flips to column here, the same
     property switches to controlling horizontal alignment instead and
     left-aligns them, which is why these read as shifted left rather
     than centered. */
  .work-group { flex-direction: column; align-items: center; gap: clamp(3rem, 6vw, 4rem); }
  .work-group .work-stage { height: 58vh; }
  .work-group .work-group-cell { flex: none; width: 80.3vw; }
  .work-sequence { padding-top: 2cm; }
  /* Desktop's -2cm tightens hscroll-trio -> poster-row to 1cm; mobile
     wants that gap 2cm bigger (3cm total), so cancel the reduction here
     without touching the desktop value. */
  .work-sequence > .work-hscroll-wrap { margin-bottom: -1cm; }
  .work-sequence > .pin-spacer,
  .work-sequence > .work-hscroll-wrap { margin-top: -4cm; }
  /* Smederevo + Website's stacked pair — matched to the same size as each
     other (not their old individually-tuned sizes), scaled down so the
     whole pair fits inside the pinned section's 100vh/overflow:hidden
     box with room to spare. Both are 16:9, so equal height also means
     equal width — one shared height var keeps them identical. */
  .work-hscroll-pair { gap: 0.8cm; --pair-item-h: calc((90vh - 0.8cm) / 2); }
  .work-hscroll-pair .work-stage[data-key="smederevo"],
  .work-hscroll-pair .work-stage[data-key="website"] {
    height: var(--pair-item-h);
    width: calc(var(--pair-item-h) * 16 / 9);
  }
}

/* horizontal-scroll trio: pinned like Home's "Made Visible" track — the
   viewport holds still and the row itself slides left as the visitor
   scrolls, instead of the pieces stacking downward. */
.work-hscroll-wrap { position: relative; height: 100vh; min-height: 560px; display: flex; align-items: center; overflow: hidden; }
.work-hscroll-track { display: flex; align-items: center; gap: 4cm; padding: 0 var(--gutter); will-change: transform; }
.work-hscroll-track .work-stage {
  flex: 0 0 auto; max-width: none; margin: 0;
  height: min(72vh, 680px); width: calc(min(72vh, 680px) * 16 / 9);
}
.work-hscroll-track .work-stage.is-vertical { width: calc(min(72vh, 680px) * 0.72); }

@media (max-width: 900px) {
  /* Same reduction applied to every gap in the trio (green-drops ->
     business-vertical -> the smederevo/website pair), not just the
     first one. Placed after the base rule above (not in the earlier
     mobile block) so it isn't overridden back by it — equal-specificity
     rules resolve by source order, not by which @media is narrower. */
  .work-hscroll-track { gap: 2cm; }
}

/* Smederevo + Website share one slide/slot in the horizontal sequence,
   stacked instead of side by side. Sizing for each (mobile-specific,
   matching what was already tuned for them individually) is set below in
   the max-width:900px block — this structural rule alone is what's safe
   to share with desktop, which gets its sizing from the ordinary
   .work-hscroll-track .work-stage default instead. */
.work-hscroll-pair { display: flex; flex-direction: column; align-items: center; gap: 1.4cm; flex: 0 0 auto; }

@media (prefers-reduced-motion: reduce) {
  .work-hscroll-wrap { height: auto; min-height: 0; display: block; overflow: visible; }
  .work-hscroll-track {
    flex-direction: column; padding: 0 var(--gutter); gap: clamp(3rem, 6vw, 4rem);
    transform: none !important;
  }
  .work-hscroll-track .work-stage, .work-hscroll-track .work-stage.is-vertical { width: 100%; height: 58vh; }
}

/* Poster row: plain wrapping flow, no pin/hscroll — same box dimensions
   as the video trio's stages above so the two rows read as one visual
   family, but ordinary document flow so its spacing is governed by the
   same flex `gap` as every other row (no GSAP pin involved to go wrong). */
.work-poster-row {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: 4cm;
  width: 100%; max-width: calc(var(--col) * 10); margin: 0 auto;
}
.work-poster-row .work-stage {
  flex: 0 0 auto; max-width: none; margin: 0;
  height: min(72vh, 680px); width: calc(min(72vh, 680px) * 16 / 9);
}

@media (max-width: 900px) {
  /* Full-bleed to the screen edges — cancels out .work-sequence's own
     gutter padding (the only padding layer between this stage and the
     viewport edge, same situation as the Website stage fix above) — and
     the same height as Smederevo's box, so these read as bigger than the
     single-gutter-width stages above by exactly the two gutters' worth
     of extra width. */
  .work-poster-row .work-stage {
    width: calc(100% + 2 * var(--gutter)); margin-left: calc(-1 * var(--gutter) + 20px);
    height: calc(46vh - 3cm);
  }
  .work-poster-row .work-stage[data-key="closing-reel"] { height: calc(46vh + 3cm); }
  .work-poster-row { gap: 2cm; }
  .work-sequence { padding-bottom: calc(clamp(7rem, 12vw, 10rem) - 1cm); }
}

.work-stage {
  position: relative; width: 100%; max-width: calc(var(--col) * 10); margin: 0 auto;
  height: min(82vh, 780px); overflow: hidden;
  background: var(--graphite); border: 1px solid var(--line-soft);
}
/* Vertical pieces get a narrower, portrait-proportioned stage instead of
   floating a shrunk-down thumbnail in the middle of a landscape box —
   same crop-fill language as every other frame on the site now. */
.work-stage.is-vertical { max-width: calc(var(--col) * 6); }
.work-stage::before { content: ""; position: absolute; top: -1px; right: -1px; width: 46px; height: 1px; background: var(--brass); }
.work-stage::after { content: ""; position: absolute; bottom: -1px; right: -1px; width: 1px; height: 46px; background: var(--brass); }
.work-stage img, .work-stage video {
  width: 100%; height: 100%; object-fit: cover; display: block;
  filter: brightness(0.78) saturate(0.88);
  transition: transform .6s var(--ease), filter .4s var(--ease);
}
.work-stage:hover img, .work-stage:hover video { transform: scale(1.03); filter: brightness(0.94) saturate(0.98); }
/* Closing reel (made2.mp4) — same perceptual-sharpening treatment as
   the page's opening video: a contrast lift plus optimize-contrast,
   layered on top of (not replacing) the shared brightness/saturate
   this piece already gets as a .work-stage member. */
.work-stage[data-key="closing-reel"] video {
  filter: brightness(0.78) contrast(1.16) saturate(0.92);
  image-rendering: -webkit-optimize-contrast;
}
.work-stage[data-key="closing-reel"]:hover video { filter: brightness(0.94) contrast(1.16) saturate(1.02); }

@media (max-width: 900px) {
  .work-stage { height: 58vh; }
}

/* ---------- services page: four chapters, varied pacing ---------- */
.service-block {
  padding: clamp(4rem, 8vw, 6rem) var(--gutter); max-width: var(--max-padded); margin-inline: auto; border-top: 1px solid var(--line);
  display: grid; grid-template-columns: 1.4fr 1fr; gap: 3vw; align-items: center;
  min-height: 100vh; min-height: 100dvh; box-sizing: border-box;
}
.service-block:last-of-type { border-bottom: 1px solid var(--line); }
.service-block-body h2 { font-size: clamp(1.8rem, 3.4vw, 2.8rem); font-weight: 500; letter-spacing: -0.015em; line-height: 1.1; }
.service-block-body p { margin-top: 1rem; max-width: 460px; color: var(--warm-gray); font-size: 0.95rem; }
.service-block-body .text-link { margin-top: 1.6rem; }
.service-activity { margin-top: 1.4rem; display: flex; flex-direction: column; gap: 0.55rem; }
.service-activity li { color: var(--warm-gray-dim); padding-left: 1.1em; position: relative; }
.service-activity li::before { content: "—"; position: absolute; left: 0; color: var(--brass-soft); }
.service-block-media {
  aspect-ratio: 4/5; overflow: hidden; background: var(--graphite);
  transform: translateX(-100px) scale(1.07);
}
.service-block-media img, .service-block-media video { width: 100%; height: 100%; object-fit: cover; }
.service-block-media.is-vertical { display: flex; align-items: center; justify-content: center; background: var(--graphite-2); }
.service-block-media.is-vertical video, .service-block-media.is-vertical img { width: auto; height: 88%; max-width: 76%; object-fit: contain; }

/* All four chapters share the base grid-template-columns (body / media
   start at the same x across chapters) and the same h2 type size —
   pacing still varies chapter to chapter (padding, media aspect,
   opacity), but the title scale and left alignment no longer do. */

/* 01 — most dramatic: wide cinematic frame. Same horizontal padding as
   02-04 (not indented further in) so its video comes out the same size
   as the ones below it. */
.chapter-01 {
  padding-top: clamp(5rem, 10vw, 8rem); padding-bottom: clamp(5rem, 10vw, 8rem);
}
.chapter-01 .service-block-media { aspect-ratio: 16/9; background: none; }
.chapter-01 .service-block-media video { filter: brightness(0.7); }

/* 02 — cleaner, architectural, more breathing space, less motion */
.chapter-02 .service-block-media { aspect-ratio: 16/9; background: none; }
.chapter-02 .service-block-media video { transition: none; filter: brightness(0.6); }

/* 03 — landscape video, same frame treatment as 01/02 */
.chapter-03 .service-block-media { aspect-ratio: 16/9; background: none; }
.chapter-03 .service-block-media video { filter: brightness(0.7); }

/* 04 — quietest: structural list, media recedes */
.chapter-04 { opacity: 0.96; }
.chapter-04 .service-block-media { aspect-ratio: 16/9; background: none; }
.chapter-04 .service-block-media video { filter: brightness(0.7); }

@media (max-width: 900px) {
  .service-block, .chapter-01, .chapter-02, .chapter-04 { grid-template-columns: 1fr; gap: 1.5rem; }
  /* Desktop's translateX(-100px) is part of that layout's offset-media
     look — once the grid collapses to a single column here, it just
     shoves the video off-center instead. */
  .service-block-media { transform: none; }
}

/* ---------- studio page: two human chapters + typographic interlude ---------- */
.studio-chapter {
  display: flex; align-items: center; gap: clamp(3rem, 6vw, 6rem);
  padding: clamp(4rem, 8vw, 7rem) var(--gutter); max-width: var(--max-padded); margin-inline: auto; border-top: 1px solid var(--line);
}
.studio-chapter.reverse { flex-direction: row-reverse; }
.sc-media { flex: 0 0 38%; aspect-ratio: 4/5; overflow: hidden; background: var(--graphite); }
.sc-media img { width: 100%; height: 100%; object-fit: cover; }
.sc-info { flex: 1; max-width: calc(var(--col) * 4); }
.sc-info h2 { font-size: clamp(1.8rem, 3.6vw, 3rem); font-weight: 500; letter-spacing: -0.01em; }
.sc-role { color: var(--brass); margin-top: 0.6rem; }
.sc-bio { margin-top: 1.6rem; display: flex; flex-direction: column; gap: 1.1rem; }
.sc-bio p { color: var(--warm-gray); font-size: 0.98rem; line-height: 1.75; }

.typo-interlude {
  padding: clamp(3rem, 6vw, 5rem) var(--gutter); max-width: var(--max-padded); margin-inline: auto; border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; justify-content: center; gap: 0.9em;
  font-size: 0.78rem; letter-spacing: 0.16em; color: var(--warm-gray-dim); text-align: center;
}
.typo-interlude span:not(:last-child)::after { content: "/"; margin-left: 0.9em; color: var(--brass-soft); }

/* ==========================================================================
   RECOGNITION — award credits, typeset in the site's own voice rather than
   dropped in as vendor badges (the official monogram stays, everything
   around it is Plex Mono / DM Sans on brass).
   ========================================================================== */
.recognition {
  padding: clamp(4.5rem,8vw,6.5rem) var(--gutter); max-width: var(--max-padded);
  margin-inline: auto; border-top: 1px solid var(--line); text-align: center;
}
.recognition-tag { color: var(--brass); }
/* Bigger than .mono's default 0.72rem, desktop only — phone keeps the
   inherited size since the eyebrow line has less room to breathe there. */
@media (min-width: 641px) {
  .recognition-tag { font-size: 0.92rem; }
}
.recognition-grid {
  margin-top: clamp(2.6rem,5vw,3.6rem); display: flex; flex-wrap: wrap;
  justify-content: center; align-items: stretch; gap: 0;
}
.award {
  display: flex; flex-direction: column; align-items: center; gap: 0.55rem;
  max-width: 17rem; padding-inline: clamp(1.6rem,4vw,3.2rem);
}
/* Hairline between the two, centred by the equal padding above — the
   structure is what makes a two-item row read as a set rather than as
   two loose credits. */
.award + .award { border-left: 1px solid var(--line); }
.award-org {
  font-family: var(--font-mono); font-size: 0.63rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--gray-functional);
}
.award-title { font-size: clamp(1.05rem,2vw,1.3rem); font-weight: 500; letter-spacing: -0.01em; line-height: 1.25; }
/* A card with only one title line (Orpetron) reserves the height its
   two-line neighbours use — 2 × line-height plus the flex gap between
   them — and centres its single line in that box, so it floats midway
   between the tier label and the award name beside it while the date
   and link rows below still land on the same lines. */
.award-title-solo {
  min-height: calc(2 * 1.25em + 0.55rem);
  display: flex; align-items: center; justify-content: center;
}
/* STAR is its own .award-title line stacked above "Site of the Day" —
   same class, same size and color, no separate rule needed; the flex
   column on .award already stacks it as its own row. */
.award-date { font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.14em; color: var(--warm-gray); }
.award-proof {
  margin-top: 0.35rem; font-family: var(--font-mono); font-size: 0.62rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--brass);
  transition: color 0.4s var(--ease);
}
a.award-proof:hover { color: var(--brass-bright); }

/* Closing note under the three cards: same typeface and brass as the
   eyebrow above it, at its own larger size. Not uppercased like .mono —
   this is a sentence, and caps would turn it into a second label.
   Tracking is eased off 0.14em, which is tuned for short caps labels and
   reads too loose across a full sentence. */
.recognition-note {
  margin-top: clamp(2.2rem,4vw,3rem);
  font-family: var(--font-mono);
  font-size: clamp(0.92rem,1.6vw,1.05rem);
  color: var(--brass); letter-spacing: 0.04em;
}

/* Ivory chapters (home page, above the closing stage). Follows the
   brass-on-ivory note further up: --brass is decorative only, small text
   takes the darker --brass-ink. These sit after .tone-light .mono and
   .tone-light a so they win on source order at equal specificity. */
.recognition.tone-light { border-top-color: rgba(23,22,19,0.14); }
.tone-light .recognition-tag { color: var(--brass-ink); }
/* border-color, not border-left-color: the mobile rule below swaps the
   divider to border-top, and a left-only override left a hard --line
   rule sitting on ivory. */
.tone-light .award + .award { border-color: rgba(23,22,19,0.14); }
.tone-light .award-org,
.tone-light .award-date { color: var(--ink-soft); }
.tone-light .award-title { color: var(--ink); }
.tone-light .award-proof { color: var(--brass-ink); }
.tone-light .recognition-note { color: var(--brass-ink); }
.tone-light a.award-proof:hover { color: var(--ink); }

/* Two columns squeeze to ~115px on a phone and the mono tracking wraps
   mid-name — stack instead, matching how .studio-values breaks. */
@media (max-width: 640px) {
  .recognition-grid { flex-direction: column; align-items: stretch; gap: 0; }
  .award { max-width: none; width: 100%; padding-inline: 0; }
  .award + .award { border-left: 0; border-top: 1px solid var(--line); margin-top: 2.4rem; padding-top: 2.4rem; }
  /* The reserved two-line height only exists to keep the three columns on
     the same rows side by side. Stacked, there is nothing to align to and
     it would just open a gap under the org name. */
  .award-title-solo { min-height: 0; display: block; }
}

.studio-values { padding: clamp(5rem,9vw,7rem) var(--gutter); max-width: var(--max-padded); margin-inline: auto; border-top: 1px solid var(--line); text-align: center; }
.studio-values .mobile-break { display: none; }
.studio-values h2 { font-size: clamp(1.8rem,4vw,3rem); font-weight: 500; letter-spacing: -0.015em; line-height: 1.15; }
.studio-values ul { margin-top: 2.2rem; display: flex; flex-direction: column; gap: 0.6rem; align-items: center; }
.studio-values li { color: var(--warm-gray); font-size: 1rem; }

@media (max-width: 800px) {
  .studio-chapter, .studio-chapter.reverse { flex-direction: column; }
  .sc-media { flex: none; width: 100%; max-width: 340px; }
  .studio-values .dash-sep { display: none; }
  .studio-values .mobile-break { display: block; }
}

/* ---------- journal page ---------- */
.journal-featured { padding: 0 var(--gutter) clamp(5rem,8vw,7rem); max-width: var(--max-padded); margin-inline: auto; }
.jf-media { aspect-ratio: 21/9; background: var(--graphite); overflow: hidden; margin-bottom: 1.6rem; }
/* CSS-only editorial cover for articles with no fitting stock footage —
   typography + a faint oversized brand fragment, no borrowed filler video */
.editorial-cover { display: flex; align-items: center; justify-content: center; }
.editorial-cover .ec-mark {
  font-family: var(--font-mono); font-size: clamp(3rem, 13vw, 8rem); letter-spacing: 0.1em;
  color: rgba(242,240,234,0.05); white-space: nowrap; pointer-events: none;
}
body.tone-light .editorial-cover .ec-mark { color: rgba(23,22,19,0.06); }
.jf-media img, .jf-media video { width: 100%; height: 100%; object-fit: cover; }
.jf-title { font-size: clamp(1.8rem, 4vw, 3rem); font-weight: 500; letter-spacing: -0.01em; line-height: 1.2; max-width: calc(var(--col) * 6); }
.jf-meta { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.1em; color: var(--warm-gray); margin-top: 0.8rem; }

.journal-list { padding: 0 var(--gutter) clamp(6rem,9vw,8rem); max-width: var(--max-padded); margin-inline: auto; display: grid; grid-template-columns: 1fr 1fr; gap: 3vw 4vw; border-top: 1px solid var(--line); }
.journal-list article { padding: 2.4rem 0; border-bottom: 1px solid var(--line); }
.journal-list h3 { font-size: 1.2rem; font-weight: 500; }
.journal-list .jf-meta { margin-top: 0.6rem; }
@media (max-width: 800px) { .journal-list { grid-template-columns: 1fr; } }

@media (max-width: 900px) {
  /* Shallower box than the shared 16:9 .work-hscroll-track default —
     these stills are shot closer to 4:3, so the wider/shorter box crops
     less off the sides than the taller 16:9 frame did. */
  #journalFeatured .work-stage {
    height: min(58vh, 480px);
    width: calc(min(58vh, 480px) * 4 / 3);
  }
  #journalFeatured .work-hscroll-track { gap: 1cm; }
  .journal-featured { margin-top: -4cm; }
  /* Desktop's manual break keeps the lede's two clauses on separate
     lines there — on mobile's narrower column each clause alone still
     wraps twice, landing at 4 lines total, so the forced break just
     adds an extra one. Letting it flow naturally here settles at 3. */
  .page-lede .desktop-break { display: none; }
  .journal-featured { margin-bottom: -4cm; }
}

/* Top padding was 0 — with .site-header fixed/floating, the article's
   own title and meta line started right underneath it with nothing to
   clear it, overlapping the wordmark. clamp(...) top matches the same
   header-clearance value .page-hero uses elsewhere on the site. */
.article-body { padding: clamp(9rem, 16vw, 12rem) var(--gutter) clamp(6rem,9vw,8rem); max-width: calc(var(--col) * 5); margin: 0 auto; }
@media (max-width: 900px) {
  .article-body {
    padding-top: calc(clamp(9rem, 16vw, 12rem) - 2cm);
    padding-bottom: calc(clamp(6rem, 9vw, 8rem) - 1cm);
  }
}
.article-body p { margin-top: 1.4rem; color: var(--off-white); font-size: 1.02rem; line-height: 1.75; }
.article-hero-media { position: relative; aspect-ratio: 16/9; background: var(--graphite); overflow: hidden; margin: 2.4rem auto; max-width: calc(var(--col) * 7); }
.article-hero-media img, .article-hero-media video { width: 100%; height: 100%; object-fit: cover; }

/* ---------- contact page ---------- */
.contact-grid { padding: 0 var(--gutter) clamp(6rem,10vw,9rem); max-width: var(--max-padded); margin-inline: auto; display: grid; grid-template-columns: 5fr 7fr; gap: clamp(2.5rem, 6vw, 5rem); }
.contact-info { display: flex; flex-direction: column; gap: 1.8rem; }
.contact-info a { font-size: 1.1rem; }
.contact-info a:hover { color: var(--brass); }
.contact-info .mono { color: var(--warm-gray); }
.contact-info .contact-social a { font-size: 0.72rem; }
.contact-form-wrap { position: relative; }
.contact-form { display: flex; flex-direction: column; gap: 1.6rem; }
/* .contact-form's own class-level `display: flex` otherwise beats the
   browser's default `[hidden] { display: none }` UA rule (same
   specificity, but this is an author stylesheet), so setting
   form.hidden = true in JS after a submission silently did nothing —
   the form stayed visible under the confirmation message. */
.contact-form[hidden] { display: none; }
.field { position: relative; display: flex; flex-direction: column; gap: 0.6rem; border-bottom: 1px solid var(--line); padding-bottom: 0.8rem; }
.field::after {
  content: ""; position: absolute; left: 0; bottom: -1px; height: 1px; width: 0%;
  background: var(--brass); transition: width .45s var(--ease-out);
}
.field:focus-within::after { width: 100%; }
.field label { font-family: var(--font-mono); font-size: 0.65rem; letter-spacing: 0.1em; color: var(--warm-gray); }
.field input, .field textarea {
  background: transparent; border: none; color: var(--off-white); font-family: var(--font-display);
  font-size: 1rem; resize: none; outline: none;
}
.field input:focus, .field textarea:focus { color: var(--brass); }
.form-submit {
  align-self: flex-start; margin-top: 0.6rem; font-family: var(--font-mono); font-size: 0.78rem;
  letter-spacing: 0.1em; color: var(--off-white); border: 1px solid var(--line); padding: 0.9rem 2rem;
  transition: border-color .3s var(--ease), color .3s var(--ease);
}
.form-submit:hover { border-color: var(--brass); color: var(--brass); }
.form-submit:disabled { opacity: 0.55; cursor: default; }

.form-state { display: flex; flex-direction: column; gap: 0.9rem; align-items: flex-start; }
/* Same [hidden]-vs-class-display issue as .contact-form above — without
   this, the confirmation message rendered visible from the very first
   page load (before any submission), stacked right on top of the form. */
.form-state[hidden] { display: none; }
.form-state .mono { color: var(--brass); letter-spacing: 0.14em; }
.form-state p:not(.mono) { color: var(--warm-gray); max-width: 420px; }
.form-state--error .mono { color: var(--warm-gray); }

@media (max-width: 900px) { .contact-grid { grid-template-columns: 1fr; gap: 3rem; } }

/* Contact is a warm-graphite tonal step off pure black, not flat black */
body[data-page="contact.html"] { background: var(--graphite); }

/* ---------- work viewer (single work, no fake multi-media case study) ---------- */
.case-back {
  position: fixed; top: 1.7rem;
  /* Base inset must match .site-header's own — plain var(--gutter)
     undershot it on wide viewports (the header uses the larger of the
     two so its content stays inset from an ultrawide edge, not flush to
     it), landing this link on top of the wordmark instead of past it. */
  left: calc(max(var(--gutter), calc((100vw - var(--max)) / 2)) + 8rem);
  z-index: 450;
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.1em; color: var(--warm-gray);
  mix-blend-mode: difference;
}
.case-back:hover { color: var(--off-white); }
.case-hero { position: relative; height: 92vh; min-height: 520px; overflow: hidden; background: var(--black); }
.case-hero video, .case-hero img { width: 100%; height: 100%; object-fit: cover; }
.case-hero.is-vertical { display: flex; align-items: center; justify-content: center; background: var(--graphite); }
.case-hero.is-vertical video, .case-hero.is-vertical img { width: auto; height: 90%; max-width: 46%; object-fit: contain; }
.case-hero-overlay { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(10,10,10,0.2), rgba(10,10,10,0.85)); display: flex; align-items: flex-end; padding: 0 var(--gutter) 4rem; pointer-events: none; }
.case-hero-overlay h1 { font-size: clamp(2rem,5.6vw,4.2rem); font-weight: 500; }
.case-meta { display: flex; gap: 2rem; font-family: var(--font-mono); font-size: 0.7rem; color: var(--warm-gray); margin-top: 1rem; }
.case-sound {
  position: absolute; bottom: 1.4rem; right: var(--gutter); z-index: 2;
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.1em; color: var(--warm-gray);
  border: 1px solid var(--line); padding: 0.5rem 1rem; background: rgba(10,10,10,0.4); backdrop-filter: blur(6px);
}
.case-sound:hover, .case-sound[aria-pressed="true"] { color: var(--brass); border-color: var(--brass-soft); }
.case-body { padding: clamp(4rem,8vw,6rem) var(--gutter); max-width: calc(var(--col) * 6); }
.case-body p { color: var(--warm-gray); font-size: 1rem; line-height: 1.75; }
.case-next { padding: clamp(5rem,9vw,7rem) var(--gutter); border-top: 1px solid var(--line); text-align: center; }
.case-next a { font-size: clamp(1.6rem,3.6vw,2.6rem); font-weight: 500; }

/* ==========================================================================
   RESPONSIVE — global
   ========================================================================== */
@media (max-width: 900px) {
  .menu-panel { width: 100vw; border-left: none; }
  .hero-content { padding-bottom: 3.5rem; padding-left: 0; padding-right: 0; max-width: none; text-align: center; }
  .services-grid { gap: 2rem; }

  .mv-track-wrap { height: auto; min-height: 0; display: block; overflow: visible; }
  .mv-track { flex-direction: column; padding: 0 var(--gutter); gap: 2.2rem; transform: none !important; }
  .mv-piece {
    width: 100%; max-width: 100%; height: 58vh; max-height: 480px;
    transform: none; filter: none;
  }
  .mv-piece.is-gallery { height: auto; max-height: none; }
  .mv-piece[data-media="workSmederevo"],
  .mv-piece[data-media="workWebsite"] { height: auto; max-height: none; aspect-ratio: 16 / 9; }
  /* This piece's footage is mostly dark, so the shared 1px frame border
     (barely visible on the lighter pieces) reads as a stray light line
     along the bottom/sides instead of an intentional frame. */
  .mv-piece[data-media="workWebsite"] { border-color: transparent; }
  .mv-gallery-grid { flex-wrap: wrap; }
  .mv-gallery-cell { flex: 1 1 45%; height: 42vh; max-height: 340px; }
  .mv-rail { display: none; }

  .closing { height: 220vh; }

  /* Guarantees enough scrollable height below the near-full-screen case
     hero so its bottom-anchored title fully clears the fixed header
     before the page runs out of scroll room, regardless of how short
     a given case's description text is. */
  .case-body { min-height: 58vh; }
}

@media (max-width: 560px) {
  .sound-toggle { bottom: 1.4rem; left: 1.2rem; }
  .closing-contacts { flex-direction: column; gap: 0.6rem; align-items: center; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
}

/* Real reduced-motion fallbacks (not just faster transitions): the
   horizontal pinned exhibition becomes a plain stacked column, matching
   the mobile treatment, instead of a scroll-jacked scrub. */
html.reduce-motion .mv-track-wrap { height: auto; min-height: 0; display: block; overflow: visible; }
html.reduce-motion .mv-track { flex-direction: column; padding: 0 var(--gutter); gap: 2.2rem; transform: none !important; }
html.reduce-motion .mv-piece { width: 100%; max-width: 100%; height: 58vh; max-height: 480px; transform: none; filter: none; }
html.reduce-motion .mv-piece.is-gallery { height: auto; max-height: none; }
html.reduce-motion .mv-gallery-grid { flex-wrap: wrap; }
html.reduce-motion .mv-gallery-cell { flex: 1 1 45%; height: 42vh; max-height: 340px; }
html.reduce-motion .mv-rail { display: none; }
html.reduce-motion .closing { height: 100vh; }
