/* ============================================================
   Berkovish · Brand consultant, strategist & designer
   Headlines: Newsreader (Google Fonts, served locally; opsz-variable
   files pinned at weights 400/500). Chosen by David 2026-07-15,
   replacing Monomakh ("prestige, smart, updated" brief).
   Body/UI:   Metropolis (Chris Simpkins, via Fontsource r11, served locally)
   ============================================================ */

@font-face {
  font-family: 'Newsreader';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/newsreader-latin-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Newsreader';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/newsreader-latin-500.woff2') format('woff2');
}
@font-face {
  font-family: 'Metropolis';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/metropolis-latin-400-normal.woff2') format('woff2'),
       url('../fonts/metropolis-latin-400-normal.woff') format('woff');
}
@font-face {
  font-family: 'Metropolis';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/metropolis-latin-500-normal.woff2') format('woff2'),
       url('../fonts/metropolis-latin-500-normal.woff') format('woff');
}
@font-face {
  font-family: 'Metropolis';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/metropolis-latin-600-normal.woff2') format('woff2'),
       url('../fonts/metropolis-latin-600-normal.woff') format('woff');
}
@font-face {
  font-family: 'Metropolis';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/metropolis-latin-700-normal.woff2') format('woff2'),
       url('../fonts/metropolis-latin-700-normal.woff') format('woff');
}

:root {
  --black: #000;
  --white: #fff;
  --ink: #1a1a1a;
  --serif: 'Newsreader', 'Times New Roman', Georgia, serif;
  --sans: 'Metropolis', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  /* One shared deceleration curve: fast start, long soft landing. */
  --ease-soft: cubic-bezier(0.22, 1, 0.36, 1);

  /* ----------------------------------------------------------
     The editorial type system (promoted from the ADVTEES story
     and the About page, 2026-07-20). One voice per role:
       label:   12px sans, 500, 0.22em tracked, uppercase
       heading: serif 28-32px (set-piece lines, beat headings)
       display: serif 36-66px (page titles, bands, pull-quotes)
       body:    17px sans, 1.7, #333 running text
       caption: 15px serif, 1.45 under images
     Axes on desktop (min-width 900px): a 12-column grid with
     32px gaps inside a 1140px container; headings start on
     column 1 (the container edge), every running line of text
     starts on column 6 (the text axis).
     Spacing:  --gap-beat between beats, --gap-half for set
     pieces inside a beat, --gap-body for paragraph rhythm,
     --gap-caption under images.
     ---------------------------------------------------------- */
  --size-heading: clamp(28px, 2.4vw, 32px);
  --size-display: clamp(36px, 4.6vw, 66px);
  --gap-beat: clamp(84px, 12vh, 160px);
  --gap-half: clamp(44px, 6vh, 80px);
  --gap-body: 22px;
  --gap-caption: 14px;
}

/* Phones (2026-07-21): the desktop display voice is 66px against
   17px body, a ~4:1 contrast; the old 36px floor collapsed that to
   ~2:1 and the pages read flat. Width-driven sizes restore real
   display scale on small screens; from 900px up the desktop
   formulas above take over unchanged. */
@media (max-width: 899px) {
  :root {
    --size-display: clamp(42px, 11.3vw, 64px);
    --size-heading: clamp(30px, 8.2vw, 36px);
  }
}

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

html { scroll-behavior: smooth; }

body {
  font-family: var(--sans);
  font-weight: 400;
  color: var(--ink);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
  line-height: 1.5;
}

img { display: block; max-width: 100%; height: auto; }

a { color: inherit; }

/* img[tabindex] covers the lightbox-triggering project images,
   which are keyboard-activatable buttons (added 2026-07-21 so the
   focus ring is explicit and consistent, not left to UA defaults). */
a:focus-visible,
button:focus-visible,
img[tabindex]:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* ------------------------------------------------------------
   Skip link: hidden above the viewport until keyboard focus
   brings it in. Black on white pages, so it always reads.
   ------------------------------------------------------------ */

.skip-link {
  position: fixed;
  top: 0;
  inset-inline-start: 0;
  z-index: 300;
  padding: 12px 18px;
  background: var(--black);
  color: var(--white);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.03em;
  text-decoration: none;
  transform: translateY(-110%);
}

.skip-link:focus {
  transform: none;
}

/* ------------------------------------------------------------
   Header
   ------------------------------------------------------------ */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--white);
  padding: 18px 24px;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0);
  transition: padding 0.3s ease, box-shadow 0.3s ease;
}

/* Hairline + slightly compact height appear only once scrolled */
.site-header.is-scrolled {
  padding-top: 12px;
  padding-bottom: 12px;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12);
}

/* Anchor targets land below the sticky header */
[id] { scroll-margin-top: 88px; }

/* ------------------------------------------------------------
   Motion: reveal on scroll, hero load-in, link micro-transitions.
   Everything is gated on body.js so content stays fully visible
   when JavaScript is unavailable, and switched off entirely
   under prefers-reduced-motion (see the media query at the end).
   ------------------------------------------------------------ */

/* THE universal micro-reveal (2026-07-21): one tiny grammar for
   every content unit on every page. Opacity 0 to 1 with a 14px
   rise over 0.55s on the shared deceleration curve, zero
   overshoot; js/main.js staggers siblings 70ms apart when several
   enter together, and once revealed an element stays. Two forms
   of the same move: .reveal (block-level, transform) and
   .reveal-line (the manifesto's inline line spans, which cannot
   be transformed, so they rise on a relative top offset exactly
   like the hero phrases). Both classes are added only by
   js/main.js, so no-JS markup never carries them. */
body.js .reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.55s var(--ease-soft), transform 0.55s var(--ease-soft);
}

body.js .reveal.is-visible {
  opacity: 1;
  transform: none;
}

body.js .reveal-line {
  position: relative;
  opacity: 0;
  top: 14px;
  transition: opacity 0.55s var(--ease-soft), top 0.55s var(--ease-soft);
}

body.js .reveal-line.is-visible {
  opacity: 1;
  top: 0;
}

@keyframes rise-in {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: none; }
}

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Load-in cascade for the split hero (about pages): the photo
   settles first, the headline rises a beat later, the paragraph
   follows. Same soft curve throughout. The homepage manifesto
   hero has its own phrase-by-phrase build further down. */
body.js .hero-photo img { animation: fade-in 1.2s var(--ease-soft) both; }
body.js .hero-block h1  { animation: rise-in 0.9s var(--ease-soft) 0.1s both; }
body.js .hero-block p   { animation: rise-in 0.9s var(--ease-soft) 0.32s both; }

.header-nav a,
.footer-links a,
.overlay-contact a,
.view-all a {
  transition: opacity 0.25s ease, color 0.25s ease;
}

.header-nav a:hover { opacity: 0.6; }
.view-all a:hover { opacity: 0.6; }

.brand { display: inline-flex; }

.brand-logo { height: 26px; width: auto; }

.header-nav { display: none; }

.menu-toggle {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  width: 44px;
  height: 44px;
  padding: 8px;
  background: none;
  border: 0;
  cursor: pointer;
}

.menu-toggle span {
  display: block;
  height: 2.5px;
  width: 100%;
  background: var(--black);
}

/* ------------------------------------------------------------
   Overlay menu
   ------------------------------------------------------------ */

.overlay-menu {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--black);
  color: var(--white);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  padding: 40px 32px;
}

.overlay-menu[hidden] { display: none; }

.menu-close {
  position: absolute;
  top: 14px;
  right: 18px;
  width: 48px;
  height: 48px;
  background: none;
  border: 0;
  cursor: pointer;
}

.menu-close span {
  position: absolute;
  top: 50%;
  left: 10px;
  right: 10px;
  height: 2.5px;
  background: var(--white);
}

.menu-close span:first-child { transform: rotate(45deg); }
.menu-close span:last-child { transform: rotate(-45deg); }

.overlay-nav {
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.overlay-nav a {
  font-family: var(--serif);
  font-size: 44px;
  line-height: 1.1;
  text-decoration: none;
}

.overlay-nav a:hover { text-decoration: underline; text-underline-offset: 6px; }

.overlay-contact {
  margin-top: 56px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.overlay-contact a {
  font-size: 16px;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.85);
}

.overlay-contact a:hover { color: var(--white); text-decoration: underline; }

/* Links rise in with a small stagger each time the overlay opens.
   The overlay toggles through [hidden], so the animation restarts
   naturally; reduced-motion switches it off at the end of the file. */
.overlay-menu:not([hidden]) .overlay-nav a,
.overlay-menu:not([hidden]) .overlay-contact a {
  animation: rise-in 0.5s var(--ease-soft) both;
}

.overlay-menu:not([hidden]) .overlay-nav a:nth-child(1) { animation-delay: 0.05s; }
.overlay-menu:not([hidden]) .overlay-nav a:nth-child(2) { animation-delay: 0.11s; }
.overlay-menu:not([hidden]) .overlay-nav a:nth-child(3) { animation-delay: 0.17s; }
.overlay-menu:not([hidden]) .overlay-nav a:nth-child(4) { animation-delay: 0.23s; }
.overlay-menu:not([hidden]) .overlay-nav a:nth-child(5) { animation-delay: 0.29s; }
.overlay-menu:not([hidden]) .overlay-contact a:nth-child(1) { animation-delay: 0.37s; }
.overlay-menu:not([hidden]) .overlay-contact a:nth-child(2) { animation-delay: 0.42s; }

/* ------------------------------------------------------------
   Manifesto hero (home pages)
   One flowing typographic statement at display scale on a
   full-viewport black section; the page scrolls normally past it.
   The portrait sits in a circle above the text on desktop and
   beside the first line on phones. The h1 is marked up as six
   inline .phrase spans, the reveal units of a time-based build
   that starts on load: the portrait settles first, then each
   phrase rises softly into place (0.3em over 0.9s on the site's
   signature deceleration) and stays, in reading order, on pure
   CSS animation delays. A slightly longer pause follows each
   sentence-ending period, so the build breathes: setup (portrait),
   action (the six phrases accumulate), resolution (the hairline
   fades in once the last phrase lands). Zero overshoot.
   Phrases stay inline and animate opacity and a relative top
   offset only, so the paragraph wraps exactly like plain text and
   nothing ever shifts while it builds. All entrance styles are
   gated on body.js (without JavaScript the full text is simply
   there) and switched off under prefers-reduced-motion (see the
   media query near the end of this file).
   ------------------------------------------------------------ */

.manifesto-hero {
  position: relative;
  background: var(--black);
  color: var(--white);
  display: flex;
  align-items: center;
  min-height: 100vh;
  min-height: 100svh;
  /* Height-aware padding so the whole stack (portrait, text,
     hairline) always fits inside one viewport, short phone
     screens included. */
  padding: clamp(48px, 8vh, 76px) 28px clamp(48px, 9vh, 84px);
}

/* The showreel glaze: the reel plays behind everything at 20%
   opacity, so the hero stays black and the moving image is only
   a shimmer under the type. Absolutely positioned inside the
   hero (inset 0 + cover), so it never adds height, never scrolls
   the page, and never shifts layout. It paints first in the DOM;
   the inner column and the hairline are positioned, so both
   stack above it. Purely decorative: no pointer events, hidden
   from assistive tech in the markup, removed entirely under
   reduced motion (see the prefers-reduced-motion block near the
   end of this file). */
.hero-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.2;
  pointer-events: none;
}

.manifesto-inner {
  position: relative;
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
}

/* On phones the circle sits beside the first line and the text
   wraps around it: stacking it above the paragraph pushed the
   last line off short screens. Desktop restores the stacked
   composition (see the min-width: 900px block). float and margin
   use logical properties, so RTL mirrors on its own. */
.manifesto-portrait {
  float: inline-start;
  width: min(120px, 12vh);
  height: min(120px, 12vh);
  margin-inline-end: 18px;
  margin-bottom: 10px;
  border-radius: 50%;
  overflow: hidden;
}

.manifesto-portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

.manifesto-text {
  font-family: var(--serif);
  font-weight: 400;
  /* Height-aware type: the vh term keeps the wrapped paragraph
     inside short viewports where vw alone would overflow, and on
     phones the 4.5vw term drops to the 30px floor so the long
     English manifesto fits one screen. */
  font-size: clamp(30px, min(4.5vw, 5.2vh), 66px);
  line-height: 1.16;
  letter-spacing: 0.01em;
  text-wrap: pretty;
}

/* The .phrase spans are reveal units, not typography: they stay
   inline, so the manifesto wraps as one continuous paragraph.
   position: relative lets the entrance animate top without ever
   touching layout (a relative offset moves the drawn text only,
   and every line fragment of a wrapped phrase moves together).
   A .nobr span glues the multi-word brand name "In this life,"
   onto one line, which also keeps the Latin run intact inside
   the Hebrew paragraph. */
.manifesto-text .phrase { position: relative; }
.manifesto-text .nobr { white-space: nowrap; }

/* One entrance for every phrase: rise 0.3em, land soft, stay.
   fill both keeps a phrase invisible through its delay and holds
   it in place forever after. */
@keyframes phrase-rise {
  from { opacity: 0; top: 0.3em; }
  to   { opacity: 1; top: 0; }
}

body.js .manifesto-portrait { animation: fade-in 0.8s var(--ease-soft) both; }

body.js .manifesto-text .phrase {
  animation: phrase-rise 0.9s var(--ease-soft) both;
}

/* The breathing stagger, English: 0.6s between phrase starts
   within a sentence, 0.75s across a sentence-ending period.
   First phrase starts 0.4s in, once the portrait is settling;
   the last lands at ~4.75s. */
body.js .manifesto-text .phrase:nth-child(1) { animation-delay: 0.4s; }
body.js .manifesto-text .phrase:nth-child(2) { animation-delay: 1s; }
body.js .manifesto-text .phrase:nth-child(3) { animation-delay: 1.75s; }
body.js .manifesto-text .phrase:nth-child(4) { animation-delay: 2.5s; }
body.js .manifesto-text .phrase:nth-child(5) { animation-delay: 3.1s; }
body.js .manifesto-text .phrase:nth-child(6) { animation-delay: 3.85s; }

/* Hebrew phrasing ends phrases 4 and 5 on periods where the
   English runs on commas, so those pauses lengthen to the
   sentence-ender rhythm; the last phrase lands at ~4.9s. */
[dir="rtl"] body.js .manifesto-text .phrase:nth-child(5) { animation-delay: 3.25s; }
[dir="rtl"] body.js .manifesto-text .phrase:nth-child(6) { animation-delay: 4s; }

/* Quiet scroll cue: a thin hairline near the bottom, on the
   inline-end side so it never crosses the text axis (LTR: right,
   RTL: left, via the logical property). It fades in gently after
   the last phrase lands, resolving the build, and stays. */
.manifesto-scroll {
  position: absolute;
  bottom: 26px;
  inset-inline-end: 56px;
  width: 2px;
  height: 64px;
  background: rgba(255, 255, 255, 0.7);
}

body.js .manifesto-scroll { animation: fade-in 0.9s var(--ease-soft) 4.9s backwards; }

[dir="rtl"] body.js .manifesto-scroll { animation-delay: 5.05s; }

/* ------------------------------------------------------------
   Split hero (about pages)
   ------------------------------------------------------------ */

.hero-photo img {
  width: 100%;
  height: auto;
}

.hero-block {
  background: var(--black);
  color: var(--white);
  padding: 64px 34px 72px;
}

.hero-block h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(46px, 15.4vw, 64px);
  line-height: 1.15;
  letter-spacing: 0.01em;
  max-width: 12ch;
}

.hero-block p {
  margin-top: 36px;
  font-size: 19px;
  line-height: 1.5;
  max-width: 34ch;
}

/* ------------------------------------------------------------
   Case studies
   ------------------------------------------------------------ */

.case-studies {
  padding: 72px 24px 40px;
}

.case-studies h1,
.case-studies h2 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: var(--size-display);
  line-height: 1.12;
  letter-spacing: 0.01em;
  text-align: center;
  margin-bottom: 48px;
}

.case-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 72px;
}

/* The kicker carries the project's category label, mirroring the
   category shown on the inner page. (Index numbers removed 2026-07-15
   per David.) */
.case-kicker {
  display: flex;
  align-items: baseline;
  gap: 16px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #333;
  margin-bottom: 14px;
}

/* Every case study shows exactly one media frame, image or video,
   locked to the same 16:9 ratio so the grid reads evenly. */
.case figure {
  overflow: hidden;
  background: var(--black);
  aspect-ratio: 16 / 9;
}

.case img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.8s ease;
}

/* Slow, subtle zoom inside the clipped frame */
.case:hover img { transform: scale(1.03); }

.case h3 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: var(--size-heading);
  line-height: 1.35;
  letter-spacing: 0.01em;
  margin-top: 18px;
}

.case p {
  margin-top: 10px;
  font-size: 17px;
  line-height: 1.7;
  color: #333;
}

/* The kicker keeps the 12px label voice; without this the .case p
   rule above outranks .case-kicker on specificity and inflates the
   label to body size. */
.case p.case-kicker {
  font-size: 12px;
  line-height: 1.5;
}

/* Phones: the full description under every card ran 12-18 lines
   and buried the frames and titles that carry the page. Four lines
   here; the complete text lives on the project's own page. Nothing
   is cut from the markup, so search engines and readers who tap
   through lose nothing. Desktop keeps the full paragraphs. */
@media (max-width: 899px) {
  .case p:not(.case-kicker) {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    line-clamp: 4;
    overflow: hidden;
  }
}

/* Video embeds: responsive 16:9, black frame, lazy iframes.
   The video is the project's single media frame and sits first in the card. */
.case-video {
  aspect-ratio: 16 / 9;
  background: var(--black);
}

.case-video iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* The whole card, image and title area together, is one link to the
   project's inner page. Inherit color, no underline; the hover zoom
   on the framed image carries the affordance. */
.case-link {
  display: block;
  color: inherit;
  text-decoration: none;
}

/* Quiet link from the homepage selection to the full case-study page */
.view-all {
  margin-top: 64px;
  text-align: center;
}

.view-all a {
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.03em;
  text-decoration: underline;
  text-underline-offset: 5px;
}

/* ------------------------------------------------------------
   Project pages (site/project/<slug>.html)
   One project per page: back link, title, description, then the
   full media flow at natural aspect ratios inside a ~1140px column.
   ------------------------------------------------------------ */

.project-page {
  padding: 40px 24px 0;
  max-width: 1140px;
  margin: 0 auto;
}

.back-link {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.back-link a {
  text-decoration: none;
  transition: opacity 0.25s ease;
}

.back-link a:hover { opacity: 0.6; }

.project-category {
  margin-top: var(--gap-half);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #333;
}

.project-title {
  font-family: var(--serif);
  font-weight: 400;
  font-size: var(--size-display);
  line-height: 1.12;
  letter-spacing: 0.01em;
}

/* Label-to-line pairing, same 10px as the essay and lookbook
   labels; the description then breathes at the body rhythm. */
.project-title { margin-top: 10px; }

.project-description {
  margin-top: var(--gap-body);
  font-size: 17px;
  line-height: 1.7;
  color: #333;
  max-width: 58ch;
}

/* Design boards and campaign shots stack full-width at their natural
   aspect ratio; no 16:9 cropping on inner pages. */
.project-media {
  margin-top: var(--gap-beat);
  display: grid;
  gap: var(--gap-half);
}

.media-item { margin: 0; }

.media-item img {
  width: 100%;
  height: auto;
  display: block;
}

/* One caption voice under images, everywhere. */
.project-media figcaption {
  margin-top: var(--gap-caption);
  font-family: var(--serif);
  font-weight: 400;
  font-size: 15px;
  line-height: 1.45;
  color: var(--ink);
}

/* Small source files (animation loops, low-res boards) sit centered
   at their natural size instead of stretching blurry to full width. */
.media-narrow img {
  width: auto;
  max-width: 100%;
  margin: 0 auto;
}

/* The film keeps a 16:9 frame; everything else breathes freely. */
.media-video {
  aspect-ratio: 16 / 9;
  background: var(--black);
}

.media-video iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Self-hosted films sit in the same dark 16:9 frame as the embeds. */
.media-video video {
  display: block;
  width: 100%;
  height: 100%;
}

/* Portrait film (the Cyrebro explainer): centered at its natural
   upright aspect instead of being cropped or letterboxed to 16:9. */
.media-video-portrait video {
  display: block;
  margin: 0 auto;
  width: min(100%, 540px);
  height: auto;
  aspect-ratio: 720 / 944;
  background: var(--black);
}

/* Previous/next navigation through the 26-project cycle.
   Each direction is one large link: a small tracking label, the
   neighbor's 16:9 cover filling the column, and the name in the
   serif beneath. The cover zooms on hover exactly like the cards.
   Narrow screens stack the two links; from 900px up they sit as
   two wide columns, the next link aligned to the outer edge. */
.project-nav {
  margin-top: var(--gap-beat);
  padding: 36px 0 80px;
  border-top: 1px solid rgba(0, 0, 0, 0.15);
  display: flex;
  flex-direction: column;
  gap: 56px;
}

.project-nav a {
  display: block;
  font-family: var(--serif);
  font-size: var(--size-heading);
  line-height: 1.35;
  text-decoration: none;
}

.project-nav-label {
  display: block;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #333;
  margin-bottom: 14px;
}

.project-nav-body {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 16px;
}

.project-nav-thumb {
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--black);
}

.project-nav-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.8s ease;
}

.project-nav a:hover .project-nav-thumb img { transform: scale(1.03); }

.project-nav-name { transition: opacity 0.25s ease; }

.project-nav a:hover .project-nav-name { opacity: 0.6; }

/* ------------------------------------------------------------
   Lightbox (inner project pages)
   Markup is built entirely by js/main.js, so without JavaScript
   the images remain plain images. Near-black overlay, image at
   natural aspect up to 95vw/90vh, quiet white controls. The
   inline-start/end properties keep the controls on the correct
   side on the Hebrew RTL pages.
   ------------------------------------------------------------ */

body.js .project-media .media-item img,
body.js .persona-grid .media-item img { cursor: zoom-in; }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(0, 0, 0, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.25s var(--ease-soft);
}

.lightbox[hidden] { display: none; }

.lightbox.is-open { opacity: 1; }

.lightbox-img {
  max-width: 95vw;
  max-height: 90vh;
  width: auto;
  height: auto;
  transform: scale(0.97);
  transition: transform 0.25s var(--ease-soft);
}

.lightbox.is-open .lightbox-img { transform: none; }

.lightbox button {
  position: absolute;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: rgba(255, 255, 255, 0.7);
  transition: color 0.25s ease;
}

.lightbox button:hover,
.lightbox button:focus-visible { color: var(--white); }

.lightbox-close {
  top: 14px;
  inset-inline-end: 18px;
  width: 48px;
  height: 48px;
}

.lightbox-close span {
  position: absolute;
  top: 50%;
  left: 12px;
  right: 12px;
  height: 2px;
  background: currentColor;
}

.lightbox-close span:first-child { transform: rotate(45deg); }
.lightbox-close span:last-child { transform: rotate(-45deg); }

.lightbox-arrow {
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 64px;
  font-family: var(--sans);
  font-size: 26px;
  line-height: 1;
}

.lightbox-prev { inset-inline-start: clamp(4px, 1.5vw, 24px); }
.lightbox-next { inset-inline-end: clamp(4px, 1.5vw, 24px); }

/* ------------------------------------------------------------
   Page transitions
   A short rise-and-fade on entry, a quicker fade on exit; both
   gated on body.js and switched off under reduced motion. The
   is-leaving class is added by js/main.js just before internal
   navigation and removed again on pageshow, so back/forward
   restores from the browser cache never land on a blank page.
   ------------------------------------------------------------ */

@media (prefers-reduced-motion: no-preference) {
  body.js { animation: fade-in 0.3s var(--ease-soft) backwards; }
  body.js main { animation: page-rise 0.3s var(--ease-soft) backwards; }
  body.js.is-leaving { animation: fade-out 0.15s ease forwards; }
}

@keyframes page-rise {
  from { transform: translateY(10px); }
  to   { transform: none; }
}

@keyframes fade-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

/* ------------------------------------------------------------
   Card "view" affordance
   A small arrow slides in after the card title on hover and on
   keyboard focus. Pure CSS, so it needs no JavaScript; the RTL
   pages get the mirrored glyph and slide direction.
   ------------------------------------------------------------ */

.case h3::after {
  content: '\2192';
  display: inline-block;
  margin-inline-start: 0.35em;
  font-size: 0.72em;
  opacity: 0;
  transform: translateX(-8px);
  transition: opacity 0.25s var(--ease-soft), transform 0.25s var(--ease-soft);
}

.case-link:hover h3::after,
.case-link:focus-visible h3::after {
  opacity: 1;
  transform: none;
}

[dir="rtl"] .case h3::after {
  content: '\2190';
  transform: translateX(8px);
}

[dir="rtl"] .case-link:hover h3::after,
[dir="rtl"] .case-link:focus-visible h3::after { transform: none; }

/* ------------------------------------------------------------
   404 page: one big serif line, a quiet way home, and a small
   Hebrew line for readers of the other edition.
   ------------------------------------------------------------ */

.not-found {
  min-height: 55vh;
  padding: 96px 24px 80px;
  max-width: 1140px;
  margin: 0 auto;
}

.not-found h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(44px, 10vw, 88px);
  line-height: 1.1;
  letter-spacing: 0.01em;
}

.not-found p {
  margin-top: 22px;
  font-size: 17px;
  color: #333;
}

.not-found-links a {
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 5px;
  transition: opacity 0.25s ease;
}

.not-found-links a:hover { opacity: 0.6; }

.not-found-he {
  margin-top: 40px;
  font-size: 15px;
}

.not-found-he a {
  color: #333;
  text-decoration: underline;
  text-underline-offset: 4px;
  transition: opacity 0.25s ease;
}

.not-found-he a:hover { opacity: 0.6; }

/* ------------------------------------------------------------
   About page (about.html / he/about.html)
   Opens with the same black hero composition as the homepage,
   then a large serif pull-quote, the career in flowing
   paragraphs, and a five-frame persona grid whose photographs
   are still to come; until then each frame is a quiet
   placeholder with a small tracked label.
   ------------------------------------------------------------ */

.about-quote {
  padding: 88px 34px 32px;
  max-width: 1200px;
  margin: 0 auto;
}

.about-quote blockquote p {
  font-family: var(--serif);
  font-weight: 400;
  /* Phone floor lifted 2026-07-21 (was 32px): the opening quote is
     the About page's display moment and needs display scale. The
     desktop block below overrides with its own clamp from 900px. */
  font-size: clamp(38px, 10.3vw, 44px);
  line-height: 1.22;
  letter-spacing: 0.01em;
  max-width: 20ch;
}

.about-story {
  padding: 56px 34px 8px;
  max-width: 1200px;
  margin: 0 auto;
}

.about-story h2,
.persona h2 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 38px;
  margin-bottom: 28px;
}

.about-story p,
.persona p {
  font-size: 17px;
  line-height: 1.7;
  color: #333;
  max-width: 58ch;
}

.about-story p + p,
.persona p + p { margin-top: 22px; }

.persona {
  padding: 80px 34px 96px;
  max-width: 1200px;
  margin: 0 auto;
}

.persona-grid {
  margin-top: 56px;
  display: grid;
  grid-template-columns: 1fr;
  gap: 28px;
}

.persona-grid .media-item {
  margin: 0;
}

.persona-grid .media-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Quiet placeholder frames at a casual-photo 3:2 ratio. When the
   real photographs land, the <img> replaces the frame div inside
   the same figure and inherits the crop, the scroll reveal and
   the lightbox. */
.media-slot {
  aspect-ratio: 3 / 2;
  background: #f4f4f4;
}

.media-slot-frame {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.media-slot-label {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #333;
}

/* ------------------------------------------------------------
   Closing contact section (home pages)
   One large serif line, then the two quiet contact links.
   ------------------------------------------------------------ */

.contact {
  background: var(--black);
  color: var(--white);
  border-top: 1px solid rgba(255, 255, 255, 0.18);
  padding: 112px 34px 120px;
}

.contact h2 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(56px, 16vw, 76px);
  line-height: 1.05;
  letter-spacing: 0.01em;
}

.contact-links {
  margin-top: 44px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Icons added 2026-07-27 (David): a quiet line icon before each
   contact link; the WhatsApp number is no longer displayed, the
   link itself still opens the chat. */
.contact-links a {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: 16px;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.85);
  transition: color 0.25s ease;
}

.contact-links a svg {
  width: 20px;
  height: 20px;
  flex: none;
  opacity: 0.85;
}

.contact-links a:hover { color: var(--white); text-decoration: underline; }

/* ------------------------------------------------------------
   Footer, redesigned 2026-07-27 (David: "a better footer that
   also has all the pages that are in the menu"). Three quiet
   layers: the wordmark with the site's pages beside it, the two
   contact links with their icons, then a hairline base row with
   the legal links and the copyright. The Hebrew mirror keeps the
   old .footer-links markup; its rules remain further down.
   ------------------------------------------------------------ */

.site-footer {
  background: var(--black);
  color: var(--white);
  padding: 44px 34px 32px;
  border-top: 1px solid rgba(255, 255, 255, 0.18);
}

.footer-top {
  display: flex;
  flex-direction: column;
  gap: 26px;
  align-items: flex-start;
}

.footer-nav {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.footer-nav a {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.03em;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.85);
  transition: color 0.25s ease;
}

.footer-nav a:hover { color: var(--white); text-decoration: underline; text-underline-offset: 5px; }

.footer-contact {
  margin-top: 26px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.footer-contact a {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 15px;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.85);
  transition: color 0.25s ease;
}

.footer-contact a svg {
  width: 17px;
  height: 17px;
  flex: none;
  opacity: 0.85;
}

.footer-contact a:hover { color: var(--white); text-decoration: underline; }

.footer-base {
  margin-top: 36px;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.footer-logo {
  height: 20px;
  width: auto;
  filter: invert(1);
}

.footer-links {
  margin-top: 22px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.footer-links a {
  font-size: 15px;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.85);
}

.footer-links a:hover { color: var(--white); text-decoration: underline; }

/* Quiet legal row (terms / privacy / accessibility), added 2026-07-21
   for launch readiness. Same muted voice as the copyright line. */
.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 24px;
}

.footer-legal a {
  font-size: 13px;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.55);
  transition: color 0.25s ease;
}

.footer-legal a:hover { color: var(--white); text-decoration: underline; }

.copyright {
  margin-top: 26px;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.55);
}

/* Inside the new base row the hairline carries the separation */
.footer-base .copyright { margin-top: 0; }

/* ------------------------------------------------------------
   Desktop (min-width 900px)
   ------------------------------------------------------------ */

@media (min-width: 900px) {

  .site-header {
    padding: 26px 56px;
  }

  .brand-logo { height: 30px; }

  .menu-toggle { display: none; }

  .header-nav {
    display: flex;
    gap: 40px;
  }

  .header-nav a {
    font-size: 15px;
    font-weight: 500;
    letter-spacing: 0.03em;
    text-decoration: none;
  }

  .header-nav a:hover {
    text-decoration: underline;
    text-underline-offset: 5px;
  }

  /* Manifesto hero: the circle capped by viewport height, one
     monumental display size wrapping into several lines. Every
     dimension carries a vh term so circle, manifesto and hairline
     sit inside one viewport on any desktop height, 800-813px
     laptops included. */
  .manifesto-hero {
    padding: clamp(48px, 9vh, 96px) 56px clamp(56px, 10vh, 92px);
  }

  .manifesto-portrait {
    float: none;
    width: min(280px, 18vh);
    height: min(280px, 18vh);
    margin-inline-end: 0;
    margin-bottom: 0;
  }

  .manifesto-text {
    margin-top: 30px;
    font-size: clamp(30px, min(4.5vw, 5.2vh), 66px);
    line-height: 1.12;
  }
}

@media (min-width: 900px) {

  /* Split hero (about pages): full-bleed two-column composition */
  .hero {
    display: grid;
    grid-template-columns: 1fr 1fr;
    min-height: min(86vh, 900px);
    background: var(--black);
  }

  .hero-photo {
    order: 1;
    overflow: hidden;
  }

  .hero-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top center;
  }

  .hero-block {
    order: 2;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 96px 8vw;
  }

  .hero-block h1 {
    font-size: clamp(52px, 4.6vw, 76px);
  }

  .hero-block p {
    font-size: 18px;
    max-width: 40ch;
  }

  /* Case studies: editorial two-column grid. The tightened top
     padding and h2 margin land the scroll out of the hero on
     real content within one viewport. */
  .case-studies {
    padding: 72px 56px 64px;
    max-width: 1400px;
    margin: 0 auto;
  }

  .case-studies h1,
  .case-studies h2 {
    margin-bottom: 88px;
  }

  .case-studies h2 { margin-bottom: 56px; }

  .case-grid {
    grid-template-columns: 1fr 1fr;
    column-gap: 80px;
    row-gap: 112px;
    align-items: start;
  }

  /* Stagger removed 2026-07-26 (David: strict aligned grid on all
     pages). Rows sit level; every frame is the same 16:9 size. */
  .case h3 { margin-top: 22px; }

  .case p { max-width: 58ch; }

  .view-all { margin-top: 104px; }

  /* Project pages on desktop: the conversation header (Option B,
     David's pick 2026-07-26, replacing the old two-axis layout
     where the description jumped to column 6 below the title).
     Back link runs full width; the category and title live in a
     left column (.ph-left), the description sits beside them on
     the right, bottom lines aligned. Title and story face each
     other on one row. */
  .project-page { padding: 56px 56px 0; }

  .not-found { padding: 152px 56px 128px; }

  .project-header {
    display: grid;
    grid-template-columns: 7fr 5fr;
    column-gap: 64px;
    align-items: end;
  }

  .project-header > * { grid-column: auto; }

  .project-header .back-link { grid-column: 1 / -1; margin-bottom: 24px; }

  .project-header .ph-left { grid-column: 1; }

  .project-header .project-description { grid-column: 2; margin-top: 0; }

  /* Two wide columns; the covers are the dominant element */
  .project-nav {
    padding-top: 44px;
    padding-bottom: 104px;
    flex-direction: row;
    justify-content: space-between;
    gap: 6%;
  }

  .project-nav a {
    flex: 0 0 47%;
    max-width: 47%;
  }

  .project-nav-label { margin-bottom: 16px; }

  .project-nav-body { gap: 20px; }

  /* Next keeps to the far edge, its text aligned outward.
     Logical properties, so the Hebrew RTL pages mirror on their own:
     previous sits on the right, next on the left. */
  .project-nav-next {
    margin-inline-start: auto;
    text-align: end;
  }

  .about-quote {
    padding: 152px 56px 48px;
  }

  .about-quote blockquote p {
    font-size: clamp(48px, 4.6vw, 66px);
  }

  .about-story {
    padding: 72px 56px 8px;
  }

  .about-story h2,
  .persona h2 { font-size: 54px; margin-bottom: 40px; }

  .about-story p,
  .persona p { font-size: 19px; max-width: 62ch; }

  .persona {
    padding: 112px 56px 152px;
  }

  .persona-grid {
    margin-top: 88px;
    grid-template-columns: 1fr 1fr;
    gap: 44px;
  }

  .contact {
    padding: 184px 56px 192px;
  }

  .contact-inner {
    max-width: 1200px;
    margin: 0 auto;
  }

  .contact h2 { font-size: clamp(88px, 9.5vw, 148px); }

  .contact-links {
    flex-direction: row;
    gap: 48px;
    margin-top: 56px;
  }

  .site-footer {
    padding: 56px 56px 36px;
  }

  /* Desktop footer: wordmark left, the site's pages and the two
     contact links as columns on the right; base row splits legal
     left / copyright right. */
  .footer-top {
    flex-direction: row;
    justify-content: space-between;
    align-items: flex-start;
  }

  .footer-cols {
    display: flex;
    gap: 96px;
  }

  .footer-contact { margin-top: 0; }

  .footer-base {
    margin-top: 56px;
    flex-direction: row;
    justify-content: space-between;
    align-items: baseline;
  }

  .footer-links {
    flex-direction: row;
    gap: 48px;
  }
}

/* Respect reduced-motion preferences: no reveals, no zoom, no
   header resize animation. Content is simply there. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .case img { transition: none; }
  .case:hover img { transform: none; }
  .project-nav-thumb img { transition: none; }
  .project-nav a:hover .project-nav-thumb img { transform: none; }
  .site-header { transition: none; }
  .header-nav a,
  .footer-links a,
  .overlay-contact a,
  .contact-links a,
  .back-link a,
  .project-nav-name,
  .view-all a,
  .not-found-links a,
  .not-found-he a { transition: none; }
  body.js .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
  body.js .reveal-line {
    opacity: 1;
    top: 0;
    transition: none;
  }
  body.js .hero-photo img,
  body.js .hero-block h1,
  body.js .hero-block p { animation: none; }
  /* Manifesto hero: no build; portrait, phrases and hairline are
     simply there, fully visible, immediately (animation: none
     falls back to the natural styles, which are all visible). */
  /* The showreel glaze is motion by definition: reduced motion
     removes it outright (not just the autoplay), so the static
     hero is pure black with no poster showing through. Not gated
     on body.js; it holds with or without JavaScript. */
  .hero-bg { display: none; }
  body.js .manifesto-portrait,
  body.js .manifesto-scroll,
  body.js .manifesto-text .phrase { animation: none; }
  .overlay-menu:not([hidden]) .overlay-nav a,
  .overlay-menu:not([hidden]) .overlay-contact a { animation: none; }
  /* Lightbox opens and closes instantly, no fade or scale */
  .lightbox,
  .lightbox-img,
  .lightbox button { transition: none; }
  .lightbox-img { transform: none; }
  /* Card arrow appears without sliding */
  .case h3::after { transition: none; }
}

/* ============================================================
   Hebrew edition (site/he/)
   Headlines: Frank Ruhl Libre (Google Fonts, served locally,
              variable file covering 400-700)
   Body/UI:   Heebo (Google Fonts, served locally, variable
              file covering 400-700)
   Monomakh and Metropolis carry no Hebrew glyphs, so Hebrew
   pages swap the font variables; the Latin originals remain
   in the stack as fallbacks. The layout itself mirrors through
   dir="rtl": flex and grid flows flip on their own, so only
   the few physical left/right properties are overridden here.
   ============================================================ */

@font-face {
  font-family: 'Frank Ruhl Libre';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/frank-ruhl-libre-hebrew-400.woff2') format('woff2');
  unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
}
@font-face {
  font-family: 'Frank Ruhl Libre';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/frank-ruhl-libre-latin-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Heebo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/heebo-hebrew-400.woff2') format('woff2');
  unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
}
@font-face {
  font-family: 'Heebo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/heebo-latin-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

[dir="rtl"] {
  --serif: 'Frank Ruhl Libre', 'Newsreader', 'Times New Roman', Georgia, serif;
  --sans: 'Heebo', 'Metropolis', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

/* Physical left/right overrides that dir="rtl" cannot flip on its own */
[dir="rtl"] .menu-close {
  right: auto;
  left: 18px;
}

/* Hebrew letterforms carry less tracking than uppercase Latin;
   the numbered index (western digits) keeps the original spacing. */
[dir="rtl"] .back-link,
[dir="rtl"] .project-category,
[dir="rtl"] .case-kicker,
[dir="rtl"] .project-nav-label,
[dir="rtl"] .media-slot-label {
  letter-spacing: 0.12em;
}


/* Quiet language switch in the header nav and overlay menu */
.header-nav .lang-switch {
  opacity: 0.55;
}

.header-nav .lang-switch:hover {
  opacity: 1;
  text-decoration: none;
}

.overlay-nav .lang-switch {
  font-family: var(--sans);
  font-size: 20px;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.85);
}
