/* ============================================================
   TOKENS — Monolithic Cinema (Master Build Brief §4)
   ============================================================ */
:root{
  --black:#0A0A09;
  --black-2:#111110;
  --ivory:#F2EEE4;          /* warm ivory, not pure white */
  --ivory-dim:#B9B4A6;
  --ivory-soft:#D3CEC1;     /* reading paragraphs: a step brighter than dim (2026-10-01) */
  --hair:rgba(242,238,228,0.15);
  --hair-strong:rgba(242,238,228,0.30);
  --gold:#C7A15C;           /* restrained accent, used sparingly */

  --sans:'Space Grotesk','Space Grotesk fallback','Helvetica Neue',Arial,sans-serif;   /* monumental confident grotesk */
  --serif:'Fraunces','Fraunces fallback',Georgia,serif;                            /* italic serif — project names only */
  --mono:'IBM Plex Mono','IBM Plex Mono fallback',ui-monospace,monospace;               /* restrained numbering/captions */

  --ease:cubic-bezier(.19,.62,.24,1);
  --ease-slow:cubic-bezier(.22,.61,.36,1);

  /* per-project atmosphere colors (Master Brief §6.3) */
  --who-tint:#7C93B3;
  --emirates-tint:#B23A2E;
  --cyberark-tint:#3FB6C9;
  --shaping-tint:#2E7FD6;
  --culinary-tint:#C77B3F;
}
*{box-sizing:border-box;}
/* --header-h is the real measured height of the fixed header: 52px on a
   phone, 69px from 768 up. It drives the scroll offsets below, so an anchor
   or a focused element never lands underneath the bar. */
html{
  scroll-behavior:smooth;
  --header-h:52px;
  /* The root carried no background at all, so the only black on the page came
     from body. Between two documents the root canvas is painted before body
     exists, and that frame is the browser's own base colour, not ours. Naming
     the same black here means the very first paint of every navigation is
     already the site's black. */
  background:var(--black);
  scroll-padding-top:calc(var(--header-h) + 12px);
}
@media (min-width:768px){ html{ --header-h:69px; } }
:target, [id]{ scroll-margin-top:calc(var(--header-h) + 12px); }
body{
  margin:0; background:var(--black); color:var(--ivory);
  font-family:var(--sans); -webkit-font-smoothing:antialiased; overflow-x:hidden;
}

/* THE BLUE FLASH.

   Recorded, not guessed: a CDP screencast of a real touch on a project card
   showed a solid teal rectangle the exact size of the anchor, held for about
   five frames and then fading. Measured against the resting frame it
   composites to rgb(26,79,97) over the page's rgb(10,10,8) - roughly
   rgba(30,94,117,.8). It is Chromium's default -webkit-tap-highlight-color,
   which this stylesheet had never set. It is not :active (no such rule
   existed), not theme-color (already #0A0A09), and not unstyled content (the
   rest of the frame stayed fully styled throughout).

   Turning it off leaves a tap with no acknowledgement, so the press is
   answered in the site's own language instead: a short dim, no colour. */
a, button, summary, label,
input, select, textarea,
[role="button"], [tabindex]{
  -webkit-tap-highlight-color:transparent;
}
@media (hover:none) and (pointer:coarse){
  a:active, summary:active, button:active{
    opacity:.68;
    transition:opacity 90ms linear;
  }
}
@media (prefers-reduced-motion:reduce){
  a:active, summary:active, button:active{ transition:none; }
}

/* THE THREE CLOSING LINKS.
   .h-close a, .p-cta a and .a-go are one pattern - a line of text with a
   hairline under it - but they live in three different stylesheets, so the
   shared fix belongs in the shared one.

   Measured by hit testing at 320 and 375, their real touch areas were 30 to
   35px tall: wide enough, short enough to miss. The target is widened with an
   absolutely positioned overlay, the same device the contact page already
   uses. Out of flow means the text does not move, the hairline does not move,
   the page does not get taller and nothing can overflow sideways - the
   overlay is 100% of the link's own width and is never given a minimum width.
   A pseudo-element takes no focus, so the tab order and RTL are untouched. */
.h-close a, .p-cta a, .a-go{ position:relative; }
.h-close a::after, .p-cta a::after, .a-go::after{
  content:"";
  position:absolute; top:50%; left:50%;
  transform:translate(-50%,-50%);
  inline-size:100%;
  block-size:100%; min-block-size:44px;
}
::selection{ background:var(--gold); color:var(--black); }
img{max-width:100%; display:block;}
.wrap{ max-width:1560px; margin:0 auto; padding-left:clamp(24px,5vw,84px); padding-right:clamp(24px,5vw,84px); }
.hairline{ border:none; border-top:1px solid var(--hair); margin:0; }
:focus-visible{ outline:2px solid var(--gold); outline-offset:3px; }
/* Line breaks, site-wide (2026-10-01): headings split into even lines and
   paragraphs do not leave one word alone on the last line. Only where the
   break falls changes - no size, width or spacing. */
h1,h2,h3{ text-wrap:balance; }
p,li,dd,figcaption{ text-wrap:pretty; }
/* The menu still opens; it just stops sliding. */
@media (prefers-reduced-motion:reduce){
  header.site .narrow .menu[open] > nav{ animation:none; }
}

/* ============================================================
   HEADER — logo, Work, Contact only
   ============================================================ */
/* THE HEADER OVER THE PAGE.

   The bar is fixed and was transparent at every scroll position, so the
   wordmark and the nav sat directly on whatever scrolled under them -
   headings, body copy, the light half of a photograph. The text shadows were
   carrying the contrast on their own and they are not enough over a pale
   image.

   The default here is OPAQUE, and transparency is granted only to html.js.
   That ordering is the failure mode: with no JavaScript, or when the motion
   system's fail-open drops the .js class, there is no scroll listener to add
   .is-scrolled, and the header stays black and readable rather than
   transparent over text. Height, padding and the position of all three
   children are untouched - only background-color and a hairline change. */
header.site{
  position:fixed; top:0; left:0; right:0; z-index:500;
  display:flex; justify-content:space-between; align-items:center;
  padding:26px clamp(24px,5vw,84px);
  opacity:0;
  /* Fully opaque, not "almost". At .96 the ivory body text under the bar
     composites to about 19 against a background of 10 - a 4% ghost, faint but
     legible, and the brief's hard rule is that nothing from the page may show
     through. Since the colour is exactly the page's own black, full opacity
     looks identical over the page and only differs where it must: over a
     photograph. */
  background-color:var(--black);
  /* The hairline is a box-shadow, not a border. A 1px border - even a
     transparent one - is laid out, and it took the bar from 52 to 53 and from
     69 to 70. A shadow is painted outside the box and costs no height. */
  box-shadow:0 1px 0 0 rgba(242,238,228,0);
  transition:opacity 1.4s var(--ease),
             background-color .2s var(--ease),
             box-shadow .2s var(--ease);
}
html.js header.site{ background-color:transparent; box-shadow:0 1px 0 0 rgba(242,238,228,0); }
html.js header.site.is-scrolled{
  background-color:var(--black);
  box-shadow:0 1px 0 0 rgba(242,238,228,.07);
}
@media (prefers-reduced-motion:reduce){
  header.site{ transition:opacity 1.4s var(--ease); }
}
header.site.in{ opacity:1; }
header.site .mark{ font-family:var(--sans); font-weight:600; font-size:13px; letter-spacing:.16em; color:var(--ivory); text-shadow:0 1px 4px rgba(0,0,0,.7), 0 2px 16px rgba(0,0,0,.55); }
header.site nav{ display:flex; gap:32px; }
header.site nav a{ font-family:var(--sans); font-size:13px; letter-spacing:.04em; color:var(--ivory); text-decoration:none; opacity:.9; text-shadow:0 1px 4px rgba(0,0,0,.7), 0 2px 16px rgba(0,0,0,.55); }
header.site nav a:hover{ opacity:1; }

/* ============================================================
   1 — OPEN
   ============================================================ */
#open{
  height:84svh; position:relative; overflow:hidden;
  display:flex; align-items:flex-end;
  background:#050504;
}
#open .media{
  position:absolute; inset:0; background-size:cover; background-position:50% 38%;
  opacity:0; transform:scale(1.05);
  transition:opacity 2.4s var(--ease-slow), transform 5s var(--ease-slow);
}
#open.in .media{ opacity:1; transform:scale(1); }
#open .grade{ position:absolute; inset:0;
  background:linear-gradient(0deg, rgba(5,5,4,.90) 0%, rgba(5,5,4,.15) 46%, rgba(5,5,4,.35) 100%); }
#open .content{ position:relative; z-index:2; width:100%; padding-bottom:9vh; }
#open h1{
  font-family:var(--sans); font-weight:300; font-size:clamp(32px,4.9vw,58px);
  line-height:1.16; letter-spacing:-.018em; margin:0 0 22px; max-width:15ch; color:var(--ivory);
  opacity:0; transform:translateY(18px); transition:opacity 1.3s var(--ease) .7s, transform 1.3s var(--ease) .7s;
}
#open.in h1{ opacity:1; transform:translateY(0); }
#open .supporting{
  font-family:var(--sans); font-weight:400; font-size:14px; letter-spacing:.02em; color:var(--ivory-dim);
  margin:0; opacity:0; transition:opacity 1.2s var(--ease) 1.3s;
}
#open.in .supporting{ opacity:1; }

/* ============================================================
   2 — IDENTITY
   ============================================================ */
#identity{ background:var(--black); padding:min(6.6vh,68px) 0; }
#identity p{
  font-family:var(--sans); font-weight:300; font-size:clamp(30px,4.4vw,56px);
  line-height:1.2; letter-spacing:-.015em; max-width:19ch; margin:0; color:var(--ivory);
  opacity:0; transform:translateY(14px); transition:opacity 1.1s var(--ease), transform 1.1s var(--ease);
}
#identity p.in{ opacity:1; transform:translateY(0); }

/* ============================================================
   3 — SELECTED WORK — shared "world" chrome
   ============================================================ */
#selected-work{ background:var(--black); }
.world{
  position:relative; padding:3vh 0 3.4vh; border-top:1px solid var(--hair);
}
.world .world-head{
  margin-bottom:1.8vh;
}
/* 2 - rhythm: projects 02 and 04 carry their head in the right-hand columns, so
   the five projects sway instead of repeating one template. Frames are untouched,
   so every image still starts at the same offset. */
.world:nth-of-type(even) .world-head{ padding-left:32%; }
.world .idx{ display:block; font-family:var(--mono); font-size:12px; letter-spacing:.1em; color:var(--ivory-dim); margin-bottom:16px; }
.world .name{
  font-family:var(--serif); font-style:italic; font-weight:400; font-size:clamp(24px,3.3vw,44px);
  color:var(--ivory); margin:0; line-height:1.2; max-width:19ch; text-align:left; letter-spacing:-.01em;
  /* reserve three lines so every section's frame starts at the same height,
     regardless of how many lines its headline wraps to */
  min-height:3.6em;
  opacity:0; transform:translateY(14px); transition:opacity 1s var(--ease), transform 1s var(--ease);
}
.world.in .name{ opacity:1; transform:translateY(0); }
.world figure{ margin:0; position:relative; overflow:hidden; background:var(--black-2); }
.world img{ width:100%; height:100%; object-fit:cover; display:block; object-position:var(--focal-d,50% 50%); }

/* --- WHO: panoramic, cool, slow push-in --- */
#w-who .frame{ aspect-ratio:21/9; }
#w-who img{
  transform:scale(1.06); transition:transform 3.2s var(--ease-slow);
  filter:saturate(.92) contrast(1.03);
}
#w-who.in img{ transform:scale(1); }

/* --- EMIRATES: wide, confident, cinematic — full logo + attendant together --- */
#w-emirates .frame{ width:100%; aspect-ratio:21/9; }
#w-emirates img{
  transform:scale(1.05); opacity:0; transition:transform 1.7s var(--ease-slow), opacity 1.5s var(--ease-slow);
  filter:saturate(1.08) contrast(1.02);
}
#w-emirates.in img{ transform:scale(1); opacity:1; }

/* --- CYBERARK: wide cinematic band, full width, sharp geometric feel --- */
#w-cyberark .frame{ width:100%; aspect-ratio:21/9; }
#w-cyberark img{
  transform:scale(1.04); transition:transform 1s var(--ease), filter 1s var(--ease);
  filter:saturate(1.15) hue-rotate(-4deg);
}
#w-cyberark.in img{ transform:scale(1); }

/* --- SHAPING THE FUTURE: bright, architecture + people together --- */
#w-shaping .frame{ width:100%; aspect-ratio:21/9; }
#w-shaping img{ filter:saturate(1.08) contrast(1.02); transform:translateY(3%); opacity:0; transition:transform 1.1s var(--ease-slow), opacity 1.1s var(--ease-slow); }
#w-shaping.in img{ transform:translateY(0); opacity:1; }

/* --- CULINARY EXPERIENCE: warm, human, cross-dissolve stack --- */
#w-culinary .stack{ position:relative; aspect-ratio:21/9; }
#w-culinary .stack img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
#w-culinary .stack .l-establish{ opacity:1; filter:brightness(.72) saturate(.95); }
#w-culinary .stack .l-primary{ opacity:0; transition:opacity 2.6s var(--ease-slow) .3s; }
#w-culinary.in .stack .l-primary{ opacity:1; }
#w-culinary .detail-row{ display:flex; justify-content:flex-end; margin-top:14px; }
#w-culinary .frame.detail{ width:min(26vw,340px); aspect-ratio:4/5; }
#w-culinary .frame.detail img{ opacity:0; transform:translateY(10px); transition:opacity 1.1s var(--ease) .5s, transform 1.1s var(--ease) .5s; }
#w-culinary.in .frame.detail img{ opacity:1; transform:translateY(0); }

/* ============================================================
   4 — RANGE FILMSTRIP
   ============================================================ */
#filmstrip{ background:var(--black); padding:4.2vh 0 4.8vh; overflow:hidden; }
#filmstrip .fs-cap{ font-family:var(--mono); font-size:11px; letter-spacing:.1em; color:var(--ivory-dim); margin:0 0 2.2vh; }
.strip{ display:flex; gap:14px; width:max-content; animation:scrollStrip 50s linear infinite; }
@keyframes scrollStrip{ from{ transform:translateX(0);} to{ transform:translateX(-50%);} }
.strip .tile{ height:min(46vw,440px); flex:0 0 auto; background:var(--black-2); overflow:hidden; }
.strip .tile img{ height:100%; width:auto; object-fit:cover; }
#filmstrip:hover .strip{ animation-play-state:paused; }
@media (prefers-reduced-motion:reduce){ .strip{ animation:none; flex-wrap:wrap; width:100%; } }

/* ============================================================
   5 — TRUST
   ============================================================ */
#trust{ background:var(--black-2); padding:4vh 0; border-top:1px solid var(--hair); border-bottom:1px solid var(--hair); overflow:hidden; }
#trust .cap{ font-family:var(--mono); font-size:11px; letter-spacing:.14em; color:var(--ivory-dim); margin:0 0 2.6vh; }
/* 5 - the names ride past the section edges instead of being cut off square */
.marquee-mask{
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 12%,#000 88%,transparent 100%);
          mask-image:linear-gradient(90deg,transparent 0,#000 12%,#000 88%,transparent 100%);
}
.marquee{ display:flex; width:max-content; align-items:center; animation:mq 42s linear infinite; }
@keyframes mq{ from{ transform:translateX(0);} to{ transform:translateX(-50%);} }
.marquee span{
  font-family:var(--sans); font-weight:600; font-size:clamp(24px,3.1vw,34px); color:var(--ivory);
  line-height:1.1; letter-spacing:-.01em;
  opacity:.94; margin-right:0; white-space:nowrap; padding:0 42px; position:relative;
}
.marquee span::after{
  content:""; position:absolute; right:0; top:50%; transform:translateY(-50%);
  width:5px; height:5px; border-radius:50%; background:var(--gold); opacity:.7;
}
@media (prefers-reduced-motion:reduce){ .marquee{ animation:none; flex-wrap:wrap; } }

/* ============================================================
   6 — AUTHORITY
   ============================================================ */
#authority{ background:var(--black); padding:min(7vh,72px) 0; text-align:center; }
#authority p{
  font-family:var(--sans); font-weight:300; font-size:clamp(28px,3.9vw,48px); letter-spacing:-.02em;
  line-height:1.25; color:var(--ivory); margin:0; opacity:0; transform:translateY(10px);
  transition:opacity 1.3s var(--ease), transform 1.3s var(--ease);
}
#authority p.in{ opacity:1; transform:translateY(0); }

/* ============================================================
   7 — CLOSE
   ============================================================ */
#close{ height:84svh; position:relative; overflow:hidden; display:flex; flex-direction:column; justify-content:flex-end; background:#050504; }
#close .media{ position:absolute; inset:0; background-size:cover; background-position:50% 42%; opacity:.9; }
#close .grade{ position:absolute; inset:0; background:linear-gradient(0deg, rgba(5,5,4,.88) 0%, rgba(5,5,4,.25) 55%, rgba(5,5,4,.55) 100%); }
#close .content{ position:relative; z-index:2; width:100%; padding-bottom:9vh; display:flex; justify-content:space-between; align-items:flex-end; gap:30px 48px; flex-wrap:wrap; }
#close h2{ font-family:var(--sans); font-weight:300; font-size:clamp(30px,4.2vw,52px); color:var(--ivory); margin:0; max-width:13ch; line-height:1.12; letter-spacing:-.018em; }
#close .cta{
  font-family:var(--mono); font-size:12px; letter-spacing:.08em; color:var(--black); background:var(--gold);
  padding:16px 24px; text-decoration:none; white-space:nowrap; transition:background .3s var(--ease);
}
#close .cta:hover{ background:var(--ivory); }
footer{ position:relative; z-index:2; padding:22px clamp(24px,5vw,84px) 30px; display:flex; justify-content:space-between; align-items:center;
  font-family:var(--mono); font-size:11px; letter-spacing:.05em; color:rgba(242,238,228,.58); flex-wrap:wrap; gap:8px; }
footer .brand-mark{ height:18px; width:auto; opacity:.8; display:block; }

/* ============================================================
   RESPONSIVE �?" everything here is scoped below 1200px.
   The approved 1440px desktop layout is deliberately untouched.
   ============================================================ */

/* 1024-1199 �?" the measure narrows, so the frames open up */
@media (max-width:1199px){
  #w-who .frame, #w-emirates .frame, #w-cyberark .frame, #w-shaping .frame{ aspect-ratio:2/1; }
  #w-culinary .stack{ aspect-ratio:2/1; }
}

/* below 1024 �?" one column, so the alternating head indent has nowhere to go */
@media (max-width:1023px){
  .world:nth-of-type(even) .world-head{ padding-left:0; }
  #w-who .frame, #w-emirates .frame, #w-cyberark .frame, #w-shaping .frame{ aspect-ratio:16/9; }
  #w-culinary .stack{ aspect-ratio:16/9; }
  .strip .tile{ height:min(52vw,400px); }
}

/* phones �?" frames run edge to edge and go squarer, so a project image is a
   moment on the screen instead of a 140px strip */
@media (max-width:767px){
  header.site{ padding:18px clamp(24px,5vw,84px); }
  header.site nav{ gap:22px; }

  #open, #close{ height:88svh; }
  #open .content, #close .content{ padding-bottom:7vh; }

  .world{ padding:2.6vh 0 3.2vh; }
  .world .world-head{ margin-bottom:1.6vh; }
  /* three reserved lines exist to align five frames on a wide screen; in a
     single column that is just dead space */
  .world .name{ min-height:0; }

  #w-who .frame, #w-emirates .frame, #w-cyberark .frame, #w-shaping .frame, #w-culinary .stack{
    width:auto;
    margin-left:calc(-1 * clamp(24px,5vw,84px));
    margin-right:calc(-1 * clamp(24px,5vw,84px));
    aspect-ratio:4/3;
  }
  /* the config has carried focalMobile all along; this is where it earns its keep */
  .world img{ object-position:var(--focal-m,50% 50%); }

  #identity{ padding:min(7vh,64px) 0; }
  #authority{ padding:min(7vh,64px) 0; }

  #filmstrip{ padding:4vh 0 4.6vh; }
  .strip{ gap:10px; }
  .strip .tile{ height:min(64vw,360px); }

  #trust{ padding:4vh 0; }
  .marquee span{ padding:0 26px; }
  .marquee-mask{
    -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 7%,#000 93%,transparent 100%);
            mask-image:linear-gradient(90deg,transparent 0,#000 7%,#000 93%,transparent 100%);
  }

  #close .content{ gap:22px; }
  #close .cta{ padding:15px 20px; }
  footer{ padding:18px clamp(24px,5vw,84px) 24px; }
}

/* 6 �?" touch and low-power devices: keep the fades, drop the full-frame
   push-ins, which are the expensive part and read as jitter on a phone */
@media (hover:none),(max-width:767px){
  #open .media, #open.in .media{ transform:none; }
  #w-who img, #w-who.in img,
  #w-emirates img, #w-emirates.in img,
  #w-cyberark img, #w-cyberark.in img{ transform:none; }
  #w-shaping img, #w-shaping.in img{ transform:none; }
}

@media (prefers-reduced-motion: reduce){
  *{ transition-duration:.01ms !important; animation-duration:.01ms !important; scroll-behavior:auto !important; }
}

/* ============================================================
   PROJECT PAGE
   Every selector here is scoped under .page-project. Nothing in
   this block can reach the home page.
   ============================================================ */
.page-project .p-open{
  height:78svh; position:relative; overflow:hidden;
  display:flex; align-items:flex-end; background:#050504;
}
.page-project .p-open .media{ position:absolute; inset:0; background-size:cover; background-position:50% 50%; }
.page-project .p-open .grade{ position:absolute; inset:0;
  background:linear-gradient(0deg, rgba(5,5,4,.92) 0%, rgba(5,5,4,.20) 52%, rgba(5,5,4,.40) 100%); }
.page-project .p-open .wrap{ position:relative; z-index:2; width:100%; padding-bottom:7vh; }
.page-project .p-client{
  font-family:var(--mono); font-size:12px; letter-spacing:.1em; color:var(--ivory-dim);
  display:block; margin-bottom:18px;
}
.page-project .p-moment{
  font-family:var(--serif); font-style:italic; font-weight:400; font-size:clamp(28px,3.6vw,48px);
  line-height:1.18; letter-spacing:-.01em; color:var(--ivory); margin:0; max-width:20ch;
}

/* the brief — plain prose, the one place on the site that explains anything */
.page-project .p-brief{ background:var(--black); padding:min(9vh,92px) 0; }
.page-project .p-brief p{
  font-family:var(--sans); font-weight:300; font-size:clamp(20px,2.1vw,28px);
  line-height:1.5; letter-spacing:-.01em; color:var(--ivory); margin:0; max-width:46ch;
}

/* the evidence layer the home page deliberately leaves out */
.page-project .p-facts{ border-top:1px solid var(--hair); border-bottom:1px solid var(--hair); padding:4vh 0; }
.page-project .p-facts dl{ display:flex; flex-wrap:wrap; gap:26px clamp(28px,5vw,72px); margin:0; }
.page-project .p-facts div{ display:flex; flex-direction:column; gap:7px; }
.page-project .p-facts dt{ font-family:var(--mono); font-size:11px; letter-spacing:.1em; color:var(--ivory-dim); }
.page-project .p-facts dd{ font-family:var(--sans); font-weight:400; font-size:clamp(15px,1.4vw,18px); color:var(--ivory); margin:0; }

/* the work */
.page-project .p-work{ background:var(--black); padding:min(9vh,92px) 0 min(4vh,42px); }
.page-project .p-work figure{ margin:0 0 clamp(18px,2.6vh,28px); overflow:hidden; background:var(--black-2); }
.page-project .p-work img{ width:100%; height:100%; object-fit:cover; display:block; }
.page-project .p-work .wide{ aspect-ratio:21/9; }
.page-project .p-work .tall{ aspect-ratio:16/9; }

/* next project */
.page-project .p-next{ position:relative; display:block; text-decoration:none; overflow:hidden;
  border-top:1px solid var(--hair); }
.page-project .p-next .media{ height:46svh; background-size:cover; background-position:50% 50%;
  filter:brightness(.42) saturate(.9); transition:filter .6s var(--ease); }
.page-project .p-next:hover .media{ filter:brightness(.56) saturate(1); }
.page-project .p-next .label{ position:absolute; inset:0; display:flex; flex-direction:column;
  justify-content:center; padding:0 clamp(24px,5vw,84px); }
.page-project .p-next .eyebrow{ font-family:var(--mono); font-size:11px; letter-spacing:.1em; color:var(--ivory-dim); margin-bottom:12px; }
.page-project .p-next .title{ font-family:var(--serif); font-style:italic; font-size:clamp(24px,2.8vw,38px);
  color:var(--ivory); line-height:1.2; max-width:18ch; }

@media (max-width:767px){
  .page-project .p-open{ height:62svh; }
  .page-project .p-brief, .page-project .p-work{ padding:min(6vh,58px) 0; }
  .page-project .p-facts dl{ gap:22px 32px; }
  .page-project .p-work .wide, .page-project .p-work .tall{ aspect-ratio:4/3; }
  .page-project .p-work figure{
    width:auto;
    margin-left:calc(-1 * clamp(24px,5vw,84px));
    margin-right:calc(-1 * clamp(24px,5vw,84px));
  }
  .page-project .p-next .media{ height:38svh; }
}

/* the wordmark is a link on the inner pages and a plain div on the home page;
   this keeps both looking identical */
header.site .mark{ text-decoration:none; display:inline-block; }

/* ============================================================
   WORK INDEX
   Scoped under .page-work. The home page stacks one project per
   screen; this is the index, so it runs two columns and stays
   rigidly consistent — the repetition is what makes it an index.
   ============================================================ */
.page-work .w-head{ background:var(--black); padding:calc(69px + min(9vh,92px)) 0 min(6vh,64px); }
.page-work .w-head h1{
  font-family:var(--sans); font-weight:300; font-size:clamp(30px,4.2vw,52px);
  line-height:1.16; letter-spacing:-.018em; color:var(--ivory); margin:0; max-width:17ch;
}
.page-work .w-list{ background:var(--black); padding-bottom:min(8vh,84px); }
.page-work .w-row{
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,2fr); gap:clamp(24px,3vw,48px);
  align-items:start; padding:clamp(26px,4vh,44px) 0; border-top:1px solid var(--hair);
  text-decoration:none; color:inherit;
}
.page-work .w-row:last-child{ border-bottom:1px solid var(--hair); }
.page-work .w-idx{ font-family:var(--mono); font-size:12px; letter-spacing:.1em; color:var(--ivory-dim); display:block; margin-bottom:14px; }
.page-work .w-client{
  font-family:var(--sans); font-weight:600; font-size:clamp(18px,1.7vw,22px);
  letter-spacing:-.01em; color:var(--ivory); display:block; margin-bottom:10px;
}
.page-work .w-moment{
  font-family:var(--serif); font-style:italic; font-weight:400; font-size:clamp(18px,1.6vw,21px);
  line-height:1.3; color:var(--ivory-dim); margin:0 0 16px; max-width:26ch;
}
.page-work .w-meta{ font-family:var(--mono); font-size:11px; letter-spacing:.08em; color:var(--ivory-dim); }
.page-work .w-frame{ aspect-ratio:21/9; overflow:hidden; background:var(--black-2); }
.page-work .w-frame img{
  width:100%; height:100%; object-fit:cover; display:block;
  transform:scale(1.03); transition:transform 1.1s var(--ease-slow), filter 1.1s var(--ease-slow);
  filter:brightness(.82);
}
.page-work .w-row:hover .w-frame img,
.page-work .w-row:focus-visible .w-frame img{ transform:scale(1); filter:brightness(1); }

@media (max-width:899px){
  .page-work .w-row{ grid-template-columns:1fr; gap:18px; }
  .page-work .w-frame{ aspect-ratio:16/9; }
}
@media (max-width:767px){
  .page-work .w-head{ padding:calc(58px + min(6vh,60px)) 0 min(4vh,42px); }
  .page-work .w-frame{ aspect-ratio:4/3; width:auto;
    margin-left:calc(-1 * clamp(24px,5vw,84px)); margin-right:calc(-1 * clamp(24px,5vw,84px)); }
}
@media (hover:none){
  .page-work .w-frame img{ transform:none; filter:brightness(1); }
}

/* ============================================================
   EXHIBITIONS
   Scoped under .page-exh.

   Since the approved copy of 2026-10-01 the page opens like a project
   page: its name on the photograph, one statement, one paragraph. The
   old four-line .e-edge section went with its copy.
   ============================================================ */
/* The bar itself keeps its height and stays transparent; what changes is what
   sits behind it. A short fall of black, dense enough at the very top to carry
   13px type and gone before it reaches the picture — so bright frames scroll
   under the mark without ever competing with it. Scoped here on purpose: the
   home page is approved and frozen. */
.page-exh header.site::before{
  content:""; position:absolute; inset:0 0 auto 0;
  height:calc(100% + 30px); pointer-events:none; z-index:-1;
  background:linear-gradient(180deg,
    rgba(5,5,4,.78) 0%, rgba(5,5,4,.62) 38%, rgba(5,5,4,.30) 72%, rgba(5,5,4,0) 100%);
}

.page-exh .e-open{ height:76svh; position:relative; overflow:hidden; display:flex; align-items:flex-end; background:#050504; }
.page-exh .e-open .media{ position:absolute; inset:0; background-size:cover; background-position:50% 50%; }
.page-exh .e-open .grade{ position:absolute; inset:0;
  background:linear-gradient(0deg, rgba(5,5,4,.90) 0%, rgba(5,5,4,.18) 55%, rgba(5,5,4,.34) 100%); }
.page-exh .e-open .wrap{ position:relative; z-index:2; width:100%; padding-bottom:7vh; }
.page-exh .e-open h1{
  font-family:var(--sans); font-weight:300; font-size:clamp(32px,4.9vw,58px);
  line-height:1.14; letter-spacing:-.018em; color:var(--ivory); margin:0; max-width:14ch;
}

/* The approved copy (2026-10-01): the page name sits on the photograph as
   the h1, the way a client name heads a project page; under it, the one
   statement at the size the old offer line had, and the paragraph set to be
   read. The old "edge" section and its four lines are gone with their copy.
   Hebrew measures in em, for the reason given at .page-work in work.css. */
.page-exh .e-offer{ background:var(--black); padding:min(10vh,104px) 0 min(7vh,72px); }
.page-exh .e-offer h2{
  font-family:var(--sans); font-weight:300; font-size:clamp(26px,3.4vw,44px);
  line-height:1.2; letter-spacing:-.015em; color:var(--ivory); margin:0; max-width:18ch;
  text-wrap:balance;
}
.page-exh .e-offer .body{
  font-family:var(--sans); font-weight:300; font-size:clamp(17px,1.35vw,20px);
  line-height:1.62; letter-spacing:0; color:var(--ivory-soft); margin:clamp(22px,3vh,32px) 0 0; max-width:58ch;
}
/* The hero heading's 14ch in em for Hebrew (Rubik 300 "0" = .616em), so
   the fallback font's "0" cannot rewrap it before the latin file lands -
   measured 0.0095 CLS from exactly that when the page name changed. */
/* "Exhibitions & Stands" is 20 characters; at the old 14ch it left "& Stands"
   alone on a second line. */
.page-exh .e-open h1{ max-width:21ch; }
html[lang="he"] .page-exh .e-open h1{ max-width:8.62em; }
html[lang="he"] .page-exh .e-cta p{ max-width:16.02em; }
html[lang="he"] .page-exh .e-offer h2{ font-family:var(--sans-he); letter-spacing:0; line-height:1.25; max-width:11.09em; }
html[lang="he"] .page-exh .e-offer .body{ font-family:var(--sans-he); line-height:1.78; max-width:35.73em; }

/* the work, one body, no grouping */
.page-exh .e-work{ background:var(--black); padding:0 0 min(7vh,72px); }
.page-exh .e-work > .wrap > h2{
  font-family:var(--mono); font-weight:400; font-size:12.5px; letter-spacing:.12em; /* was 11px; 12.5 is the site floor for secondary text (2026-10-01) */
  color:var(--ivory-dim); margin:0 0 3.4vh; padding-top:min(5vh,50px); border-top:1px solid var(--hair);
}
.page-exh .build{ margin:0 0 clamp(20px,3vh,34px); }
.page-exh .build figure{ margin:0; overflow:hidden; background:var(--black-2); }
.page-exh .build img{ width:100%; height:100%; object-fit:cover; display:block; }
.page-exh .build figcaption{
  font-family:var(--mono); font-size:13px; letter-spacing:.06em; color:var(--ivory); /* was 11px: the client names on this page */
  padding-top:12px;
}
/* Two frames, and only two. A full-measure frame is 16:9; a half-measure frame
   is 4:3 and never appears alone. Both sit on the same left and right lines, so
   a pair's outer edges land exactly where a full frame's edges do. Frames that
   have depth you could walk into run full measure; flat elevations pair up. */
.page-exh .wide figure{ aspect-ratio:16/9; }
.page-exh .pair figure{ aspect-ratio:4/3; }
/* Three frames for one client, read as one body of work. The gaps inside the
   set are tight so the run holds together as a single object, and one caption
   sits under the whole thing instead of repeating the name three times. */
.page-exh .set figure{ aspect-ratio:16/9; }
.page-exh .set figure + figure{ margin-top:14px; }
/* Same block, laid side by side: used when a client has two frames that read
   better as a pair than as a stack. The caption spans both columns so it still
   belongs to the set and not to the frame above it. */
.page-exh .set.side{ display:grid; grid-template-columns:1fr 1fr; gap:clamp(18px,2.2vw,30px); }
.page-exh .set.side figure{ aspect-ratio:4/3; }
.page-exh .set.side figure + figure{ margin-top:0; }
.page-exh .set.side figcaption{ grid-column:1 / -1; }
.page-exh .pair{
  display:grid; grid-template-columns:1fr 1fr; gap:clamp(18px,2.2vw,30px);
  margin:0 0 clamp(20px,3vh,34px);
}
.page-exh .pair .build{ margin:0; }
/* A build that has its own project page is the link to it (generated from
   projects.json "exhibitions"). It looks exactly like the other builds; the
   caption warms to gold on hover and keyboard focus, the site's link answer. */
.page-exh a.build{ display:block; text-decoration:none; color:inherit; }
.page-exh a.build figcaption{ transition:color .3s var(--ease); }
.page-exh a.build:hover figcaption,
.page-exh a.build:focus-visible figcaption{ color:var(--gold); }

/* The film control and its sheet are shared with project pages since
   2026-09-30: :is(.page-exh,.page-proj) keeps the exact specificity of the
   original .page-exh selectors, so Exhibitions renders byte-for-byte as before
   and a project page with a film gets the same button, triangle and sheet.
   Only the player is shared; the .build reveal rules stay Exhibitions-only. */
/* Two quiet actions under the project caption. Same mono voice as the caption,
   one step dimmer, with a hairline that lights up on hover - so they read as
   things you can do, not as another label. */
/* Stacked, 14px apart, so the two films read as one small group belonging to
   the project above them - not as two loose links. */
/* 26px, not 14px. Each film button carries a 44px hit overlay (below), and
   the label box is 19px, so a 14px gap put the two overlays 33px apart and
   they overlapped by 11px - a tap just under the first film opened the
   second one. 19 + 26 = 45px of pitch, so each film now owns its whole
   target and neither can steal from the other. */
:is(.page-exh,.page-proj) .plays{ margin:12px 0 0; display:flex; flex-direction:column; align-items:flex-start; gap:26px; }
:is(.page-exh,.page-proj) .plays .play{
  -webkit-appearance:none; appearance:none; background:none; border:0; border-radius:0;
  padding:0 0 4px; cursor:pointer;
  display:inline-flex; align-items:center; gap:9px;
  font-family:var(--mono); font-size:11px; letter-spacing:.08em; color:var(--ivory-dim);
  border-bottom:1px solid var(--hair);
  transition:color .3s var(--ease), border-color .3s var(--ease);
}
/* A 6px triangle drawn in CSS rather than a glyph: the ready-made play
   characters render as colour emoji on some platforms, which would break the
   palette. It inherits currentColor, so it warms with the label on hover. */
:is(.page-exh,.page-proj) .plays .play .mk{
  flex:none; width:0; height:0;
  border-style:solid; border-width:4px 0 4px 6px;
  border-color:transparent transparent transparent currentColor;
}
:is(.page-exh,.page-proj) .plays .play:hover,
:is(.page-exh,.page-proj) .plays .play:focus-visible{ color:var(--ivory); border-bottom-color:var(--gold); }
/* The label is small type, so the button's own box is far below a usable tap
   target - measured 18px. The overlay grows the hit area without moving a
   pixel of the type. It was 32px, which clears the WCAG 24px floor but not
   the 44px a primary action deserves on a phone; now 44. */
:is(.page-exh,.page-proj) .plays .play{ position:relative; }
:is(.page-exh,.page-proj) .plays .play::after{
  content:""; position:absolute; inset-inline:0; top:50%;
  transform:translateY(-50%); block-size:44px;
}

/* The film plays on black and nothing else. No frame, no chrome beyond the
   player's own controls and one way out. */
/* The video sheet.

   It is a column, not a centring box: a close row, then the stage. That is
   the whole fix for the phone. Before, the modal centred a 16:9 video in a
   full-height flex box, so on a 375x812 screen a 375x211 strip floated in
   812px of black with a 11px "Close" hiding in a corner - it read as a page
   that had failed to load rather than as a dialog.

   100dvh, not 100vh: on a phone with dynamic browser chrome, vh is the
   LARGER viewport, so the bottom of a vh-sized dialog sits under the toolbar.
   svh is kept as the fallback for engines without dvh. */
:is(.page-exh,.page-proj) .lb{
  position:fixed; inset:0; z-index:900; background:#050504;
  block-size:100svh; block-size:100dvh;
  display:flex; flex-direction:column;
  padding:clamp(24px,5vw,84px);
  animation:lb-in .2s var(--ease);
}
:is(.page-exh,.page-proj) .lb[hidden]{ display:none; }
@keyframes lb-in{ from{ opacity:0 } to{ opacity:1 } }
:is(.page-exh,.page-proj) .lb-stage{
  flex:1 1 auto; min-block-size:0;
  inline-size:100%; max-inline-size:1600px; margin-inline:auto;
  display:flex; align-items:center; justify-content:center;
}
/* contain, never cover: the film keeps its own shape and is never cropped to
   fill a box it does not fit. max-block-size:100% is what lets it use the
   height the column gives it instead of overflowing past the close row. */
:is(.page-exh,.page-proj) .lb video{
  inline-size:100%; block-size:auto;
  max-block-size:100%; object-fit:contain;
  display:block; background:#000;
}
/* Names the film, directly under it. Quiet, and it is the only thing in the
   dark area below the video on a phone. */
:is(.page-exh,.page-proj) .lb-cap{
  flex:none; margin:14px auto 0; max-inline-size:1600px; inline-size:100%;
  font-family:var(--mono); font-size:12px; letter-spacing:.06em;
  color:var(--ivory-dim); text-align:start;
}
html[lang="he"] :is(.page-exh,.page-proj) .lb-cap{ font-family:var(--mono-he); letter-spacing:0; font-size:13.5px; }
:is(.page-exh,.page-proj) .lb-cap:empty{ display:none; }
:is(.page-exh,.page-proj) .lb-x{
  position:absolute; top:clamp(14px,3vw,28px); right:clamp(14px,3vw,28px);
  -webkit-appearance:none; appearance:none; background:none; border:0; cursor:pointer;
  min-height:44px; min-width:64px; display:inline-flex; align-items:center; justify-content:center;
  font-family:var(--mono); font-size:11px; letter-spacing:.08em; color:var(--ivory-dim);
  transition:color .3s var(--ease);
}
:is(.page-exh,.page-proj) .lb-x:hover{ color:var(--ivory); }

/* close */
.page-exh .e-cta{ background:var(--black); padding:min(8vh,84px) 0 min(11vh,116px); }
.page-exh .e-cta p{
  font-family:var(--sans); font-weight:300; font-size:clamp(21px,2.5vw,31px);
  line-height:1.32; letter-spacing:-.012em; color:var(--ivory); margin:0 0 4vh;
  padding-top:min(6vh,62px); border-top:1px solid var(--hair); max-width:26ch;
}
.page-exh .e-cta a.go{
  display:inline-block; font-family:var(--mono); font-size:12px; letter-spacing:.08em;
  color:var(--black); background:var(--gold); padding:16px 24px; text-decoration:none;
  transition:background .3s var(--ease);
}
.page-exh .e-cta a.go:hover{ background:var(--ivory); }
html[lang="he"] .page-exh .e-cta a.go{ font-family:var(--mono-he,var(--mono)); letter-spacing:0; font-size:13.5px; }
/* The exhibitions desk's address under the button: a quiet text link, the
   same hairline underline the Contact page gives its addresses. */
.page-exh .e-cta .mail{
  margin:22px 0 0; padding:0; border:0; max-width:none; letter-spacing:0;
  font-family:var(--sans); font-weight:300; font-size:clamp(16px,1.2vw,18px); line-height:1.4;
}
.page-exh .e-cta .mail a{
  display:inline-block; color:var(--ivory-dim); text-decoration:none;
  border-bottom:1px solid var(--hair); padding-bottom:2px; position:relative;
  transition:color .3s var(--ease), border-color .3s var(--ease);
}
.page-exh .e-cta .mail a:hover, .page-exh .e-cta .mail a:focus-visible{ color:var(--gold); border-bottom-color:var(--gold); }
.page-exh .e-cta .mail a::after{ content:""; position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); inline-size:100%; block-size:100%; min-block-size:45px; }

@media (max-width:767px){
  .page-exh .e-open{ height:62svh; }
  .page-exh .e-offer{ padding:min(7vh,64px) 0 min(6vh,54px); }
  .page-exh .pair{ grid-template-columns:1fr; gap:clamp(20px,3vh,34px); }
  .page-exh .wide figure, .page-exh .pair figure, .page-exh .set figure{ aspect-ratio:4/3; }
  .page-exh .set figure + figure{ margin-top:10px; }
  .page-exh .set.side{ grid-template-columns:1fr; gap:10px; }
  .page-exh .set.side figure + figure{ margin-top:0; }
  :is(.page-exh,.page-proj) .plays{ gap:26px; margin-top:14px; }

  /* Phone: the close control becomes the sheet's header rather than a word
     tucked in a corner. Full width, 56px tall, ivory instead of dimmed, and
     a hairline under it - so the moment it opens it is obviously a dialog
     and obviously dismissible. */
  :is(.page-exh,.page-proj) .lb{ padding:0; }
  :is(.page-exh,.page-proj) .lb-x{
    position:static; order:-1;
    inline-size:100%; min-block-size:56px;
    justify-content:flex-end;
    padding-inline:clamp(24px,5vw,84px);
    font-size:13px; letter-spacing:.06em; color:var(--ivory);
    border-block-end:1px solid var(--hair);
  }
  /* A 16:9 film inside a 375px portrait screen is 375x211, and no amount of
     CSS changes that without cropping it - which contain exists to prevent.
     So the question is not how to remove the dark area but where to put it.
     Centring split it into two roughly equal bands above and below, which is
     what made the screen read as empty. Anchored under the header it becomes
     one region below the film, which reads as a sheet with its content at the
     top - and the player's own controls stay at the film's edge instead of
     floating in the middle of nowhere. */
  :is(.page-exh,.page-proj) .lb-stage{ padding-inline:0; flex:none; align-items:flex-start; }
  :is(.page-exh,.page-proj) .lb-cap{ padding-inline:clamp(24px,5vw,84px); margin-block-start:18px; }

  /* 11px was too small to read on a real device and the labels carry the
     client names. */
  .page-exh .build figcaption{ font-size:13px; letter-spacing:.06em; padding-top:12px; }
  :is(.page-exh,.page-proj) .plays .play{ font-size:13px; letter-spacing:.06em; color:var(--ivory); }
  .page-exh .build img{ object-position:var(--focal-m,50%) 50%; }
  .page-exh .build figure{ width:auto;
    margin-left:calc(-1 * clamp(24px,5vw,84px)); margin-right:calc(-1 * clamp(24px,5vw,84px)); }
  .page-exh .build figcaption{ padding-top:10px; }
  .page-exh .e-cta{ padding:min(6vh,58px) 0 min(8vh,84px); }
}

/* three nav items leave almost no room beside the wordmark on a phone */
@media (max-width:767px){
  header.site nav{ gap:14px; }
  header.site nav a{ font-size:12px; letter-spacing:.02em; }
  header.site .mark{ font-size:12px; letter-spacing:.12em; }
}

/* ------------------------------------------------------------
   Nav hit area and the 320px overflow.

   The links were 15px tall, which is a 15px target. Padding grows the
   hit area to ~41px and the matching negative margin hands the space
   straight back, so the header keeps the height it already had --
   measured before and after at 1536, 375 and 320.
   ------------------------------------------------------------ */
header.site nav{ align-items:center; }
header.site nav a{ padding-block:15px; margin-block:-15px; }

/* The wordmark needs the same treatment and never got it, because it sits
   OUTSIDE <nav> and the rule above only reaches links inside one. Measured
   102x15 on a phone and 116x17 on a tablet - a 17px target on the one control
   that appears on all 32 pages.

   Not scoped to a width. It was, at first, and 768 then fell through the gap:
   an iPad in portrait is a touch device reading 768px, so a phone-only rule
   left the commonest tablet with the defect it was written to fix. The
   padding and the matching negative margin cancel, so the header keeps the
   height it had - measured unchanged at 320, 375, 768, 1366 and 1536. */
header.site .mark{
  display:inline-flex; align-items:center;
  padding-block:15px; margin-block:-15px;
}

/* The old 320 rule wrapped the whole header onto two rows, because four
   inline labels plus the wordmark needed 368px inside 320. That was the
   right fix for four items and the wrong one for six: measured, six need
   304px against 272px available, so wrapping no longer saves it.

   The header now carries two navs and shows one (see below), and the
   phone header is the wordmark, the language link and one word. That
   fits 320 on a single line with room to spare, so the wrap is gone. */

/* ------------------------------------------------------------
   TWO NAVS, ONE SHOWN

   .wide is the inline row, unchanged in look from the four-item version.
   .narrow is the phone header: the language switch, which stays OUT of
   the menu so a reader who landed in the wrong language can leave without
   opening anything, and a <details> menu labelled with a word rather than
   three lines, because this site has no icons anywhere else.

   They are swapped with display:none, which also takes the hidden one out
   of the accessibility tree - so a screen reader meets each link once, not
   twice. Forcing one <details> open with CSS on desktop would have avoided
   the duplication in the markup, but it depends on overriding how each
   engine hides a closed details' contents, and that is not dependable.
   ------------------------------------------------------------ */
header.site .narrow{ display:none; }

@media (max-width:767px){
  header.site nav.wide{ display:none; }
  header.site .narrow{ display:flex; align-items:center; gap:18px; }

  /* The language link sits OUTSIDE <nav> here, so none of the
     "header.site nav a" rules reach it and it was rendering as a default
     blue underlined link. It gets the same treatment explicitly. */
  header.site .narrow > .lang{
    font-family:var(--sans); font-size:12px; letter-spacing:.02em;
    color:var(--ivory); text-decoration:none; opacity:.9;
    padding-block:15px; margin-block:-15px;
    text-shadow:0 1px 4px rgba(0,0,0,.7), 0 2px 16px rgba(0,0,0,.55);
  }
  header.site .narrow > .lang:hover{ opacity:1; }

  /* The button read as a second language link: same 12px, same 400, same .9
     opacity, and a 32x42 box. It now carries a little more weight and full
     opacity so it is legibly the action rather than a sibling link, and a
     mark that says it opens something.

     The mark is one glyph. A plus rotated 45 degrees IS a multiplication
     sign, so open and closed are the same character at two angles - there is
     no swap, nothing reflows, and the two states cannot disagree. The word
     still swaps in CSS, so it is correct with scripting off.

     44x44 is met with padding and a negative margin of the same size, so the
     touch target grows and the header keeps its 52px. */
  header.site .narrow .menu > summary{
    list-style:none; cursor:pointer; user-select:none;
    /* flex, not inline-flex. An inline-level summary makes <details> lay out
       an inline formatting context, and the strut of its own 16px font then
       set a 21px line box - which pushed the 52px bar to 56 in Hebrew and 58
       in English. Block-level, the details is exactly as tall as the button's
       16px margin box and the header keeps its height. */
    display:flex; align-items:center; gap:7px;
    font-family:var(--sans); font-size:12.5px; font-weight:600; letter-spacing:.06em;
    /* Pinned to the same 16px line box the wordmark already has. The bar is
       36px of padding plus its tallest child, so leaving this to the font's
       own metrics grew the header to 56 in Hebrew and 58 in English. Pinned,
       it stays 52 in both. */
    line-height:16px;
    color:var(--ivory); opacity:1;
    position:relative;
    padding-block:13px; margin-block:-13px;
    text-shadow:0 1px 4px rgba(0,0,0,.7), 0 2px 16px rgba(0,0,0,.55);
  }
  /* 44x44 without costing a pixel of layout: the target is an absolutely
     positioned overlay centred on the button, the same device the contact
     page already uses. Sizing the button itself would move the header. */
  header.site .narrow .menu > summary::after{
    content:""; position:absolute; top:50%; left:50%;
    transform:translate(-50%,-50%);
    inline-size:100%; min-inline-size:44px;
    block-size:100%; min-block-size:44px;
  }
  header.site .narrow .menu > summary .m-mark{
    display:inline-block; font-weight:400; font-size:15px; line-height:16px;
    transform:rotate(0deg); transform-origin:50% 50%;
    transition:transform .2s var(--ease);
  }
  header.site .narrow .menu[open] > summary .m-mark{ transform:rotate(45deg); }
  @media (prefers-reduced-motion:reduce){
    header.site .narrow .menu > summary .m-mark{ transition:none; }
  }
  /* The press feedback the rest of the site gets. The general rule is
     summary:active at (0,1,1), and the button's own rule sets opacity:1 at
     (0,3,3), so the general one never reached it and this was the only
     interactive thing on the site with no answer to a tap. Same value, same
     90ms, same touch-only gate - just stated at a specificity that wins. */
  @media (hover:none) and (pointer:coarse){
    header.site .narrow .menu > summary:active{
      opacity:.68; transition:opacity 90ms linear;
    }
  }
  @media (prefers-reduced-motion:reduce){
    header.site .narrow .menu > summary:active{ transition:none; }
  }
  header.site .narrow .menu > summary::-webkit-details-marker{ display:none; }
  header.site .narrow .menu > summary::marker{ content:""; }
  header.site .narrow .menu > summary:focus-visible{ outline:2px solid var(--gold); outline-offset:3px; }

  /* The label swaps in CSS, so it is still right when scripting is off. */
  header.site .narrow .menu .m-close{ display:none; }
  header.site .narrow .menu[open] .m-open{ display:none; }
  header.site .narrow .menu[open] .m-close{ display:inline; }

  /* Header and panel are one surface.

     The header is transparent everywhere else on the site, because it sits
     over a photograph. With the menu open that left a band of photograph
     showing behind the wordmark and a solid panel starting immediately
     under it - a seam that read as accidental.

     :has() does this in CSS alone, so it is right with scripting off too,
     and background is not a layout property: nothing moves, nothing
     reflows, and the header keeps the height it already had. The hairline
     between the two stays, but now it divides one surface instead of
     marking where a panel was dropped under a transparent bar. */
  header.site:has(.menu[open]){ background:var(--black); }

  /* Closed means closed, said explicitly.

     Browsers hide a closed <details>' contents through a slot, not through a
     rule you can count on, and giving this panel position:absolute and
     display:flex was enough to defeat it: measured, the closed panel still
     reported a 254px box with visibility:visible, so its five links stayed in
     the tab order and in the accessibility tree. This one line settles it in
     every engine instead of trusting each engine to agree. */
  header.site .narrow .menu:not([open]) > nav{ display:none; }

  /* The panel hangs off the header, which is fixed and therefore the
     containing block. Solid, not translucent: these links sit over a
     photograph on most pages. */
  /* The panel arrives, it does not unfold. height and max-height both make
     the browser lay the page out again on every frame; opacity and a 6px
     lift are composited and cost nothing. A keyframe rather than a
     transition, because you cannot transition out of display:none - and
     using display:none is what keeps the closed panel out of the tab order.
     It plays on open only; closing is immediate, which is what you want from
     a menu you have just used. No JavaScript is involved, so it is the same
     with scripting off. */
  @keyframes menu-in{
    from{ opacity:0; transform:translateY(-6px); }
    to{ opacity:1; transform:none; }
  }
  header.site .narrow .menu[open] > nav{
    animation:menu-in .22s var(--ease) both;
    position:absolute; inset-inline:0; inset-block-start:100%;
    display:flex; flex-direction:column; gap:0;
    /* align-items must be reset: the shared "header.site nav" rule centres
       the inline row, and inherited into a column it centred every link and
       shrank each hairline to the width of its own word. */
    align-items:stretch;
    background:var(--black); border-block-start:1px solid var(--hair);
    padding-inline:clamp(24px,5vw,84px); padding-block:4px 10px;
  }
  header.site .narrow .menu > nav a{
    padding-block:14px; margin-block:0;
    font-size:15px; letter-spacing:.01em; opacity:1; text-shadow:none;
    text-align:start;
    border-block-end:1px solid var(--hair);
  }
  header.site .narrow .menu > nav a:last-child{ border-block-end:0; }
  header.site .narrow .menu > nav a[aria-current="page"]{ color:var(--gold); }
}

/* ------------------------------------------------------------
   STAGE 4 - PHONE LEGIBILITY, HIT AREAS, AND THE EXHIBITION LABELS

   Three separate things, all measured at 375 on the built pages.

   1. The wordmark hit area moved out of this block and up to the nav
      hit-area rule above, unscoped: at 768 - an iPad in portrait - a
      phone-only rule left the target at 17px, which is the defect it was
      written to fix.

   2. The exhibition labels. These carry the client names, which is the
      single most load-bearing text on that page, and they were at 13px.
      They go to 14.5px; the two film buttons to 14px, which keeps them
      a step below the name they belong to. The section label and the
      gold CTA come up with them. The 44px hit overlay on the film
      buttons is unchanged and still does the work there.

   3. The footer line at 11px, the smallest type anywhere on the site,
      to 12px. It is a colophon, not a headline, but 11px on a phone is
      below the floor.
   ------------------------------------------------------------ */
@media (max-width:767px){
  .page-exh .build figcaption{ font-size:14.5px; letter-spacing:.05em; padding-top:12px; }
  html[lang="he"] .page-exh .build figcaption{ letter-spacing:0; font-size:15px; }
  :is(.page-exh,.page-proj) .plays .play{ font-size:14px; letter-spacing:.05em; }
  .page-exh .e-work > .wrap > h2{ font-size:12.5px; letter-spacing:.1em; }
  .page-exh .e-cta a.go{ font-size:13px; padding:17px 26px; }

  footer{ font-size:12px; }
}

/* ============================================================
   STAGE 5 - MOTION ON EXHIBITIONS

   Last, and deliberately so: the video sheet and the grid had to
   be right before anything was allowed to move. Same html.js
   contract as the rest of the site, opacity and transform only.

   The sheet itself already opens in 200ms (lb-in, above) and the
   video element is never animated - not on open, not on close,
   and never during playback. A film that is scaling or sliding
   while it plays is a film nobody can watch.
   ============================================================ */
html.js .page-exh .e-offer h2,
html.js .page-exh .e-offer .body,
html.js .page-exh .e-cta p,
html.js .page-exh .e-cta a.go{ opacity:0; transform:translateY(14px); }
html.js .page-exh .e-offer.in h2,
html.js .page-exh .e-offer.in .body,
html.js .page-exh .e-cta.in p,
html.js .page-exh .e-cta.in a.go{
  opacity:1; transform:none;
  transition:opacity .8s var(--ease), transform .8s var(--ease);
}
html.js .page-exh .e-offer.in .body{ transition-delay:.1s; }
html.js .page-exh .e-cta.in a.go,
html.js .page-exh .e-cta.in .mail{ transition-delay:.1s; }

/* A build is its frame, its caption and its film buttons arriving
   as one thing, because that is what they are. The frame leads and
   the label follows by 100ms - the same order the work index uses
   inverted, since here the picture is what is being introduced and
   the client name is what it turns out to be. */
html.js .page-exh .build figure{ opacity:0; transform:translateY(16px); }
html.js .page-exh .build figcaption,
html.js .page-exh .build .plays{ opacity:0; }
html.js .page-exh .build.in figure{
  opacity:1; transform:none;
  transition:opacity .8s var(--ease), transform .8s var(--ease);
}
html.js .page-exh .build.in figcaption,
html.js .page-exh .build.in .plays{
  opacity:1; transition:opacity .75s var(--ease) .1s;
}

@media (prefers-reduced-motion:reduce){
  html.js .page-exh .e-offer h2, html.js .page-exh .e-offer .body,
  html.js .page-exh .e-cta p, html.js .page-exh .e-cta a.go,
  html.js .page-exh .build figure, html.js .page-exh .build figcaption,
  html.js .page-exh .build .plays{
    opacity:1; transform:none; transition:none;
  }
  :is(.page-exh,.page-proj) .lb{ animation:none; }
}

/* ------------------------------------------------------------
   THE LANGUAGE LINK'S HIT AREA

   Height comes from the padding above. Width cannot: the link says
   "English" on the Hebrew page and the shorter "עברית" on the
   English one, so a padding value tuned for one word leaves the
   other short - measured 51px against 39px for the same rule.

   An overlay sizes itself from the larger of the text and 44px, so
   both words clear the floor without either being padded to a width
   it does not need. Centred with a translate, so the rule is correct
   in both directions, and it changes no layout: the link occupies
   exactly the space it did before and the header keeps its height.
   ------------------------------------------------------------ */
header.site .narrow > .lang{ position:relative; }
header.site .narrow > .lang::after{
  content:"";
  position:absolute;
  top:50%; left:50%;
  transform:translate(-50%,-50%);
  inline-size:100%; min-inline-size:44px;
  block-size:100%; min-block-size:44px;
}

/* ============================================================
   THE OFFICIAL LOGO IN THE HEADER, AND THE SHARED FOOTER (2026-09-30)
   ============================================================ */

/* The header mark is the official logo's KALEIDOSCOPE row, a lossless
   crop (assets/brand/kaleidoscope-logo-header.png, 467x72). Both sides are
   stated so the box is known before the file arrives and nothing can move:
   18px tall from 768 (116.75 wide, 36 device px at DPR 2 from a 72px
   source - a downscale, so it stays sharp), 16px on a phone. The shadow is
   the one the typed wordmark carried, so the mark stays legible over the
   home page photograph; drop-shadow is a filter on the painted image and
   leaves the file itself untouched. The link keeps its padding and
   negative margin, so the hit area stays 48px (46px on a phone) and the
   header keeps its 69px / 52px height. */
header.site .mark img{
  display:block; block-size:18px; inline-size:116.75px;
  /* 18px paints the mark at its legible size; the old typed wordmark's line
     box was 17px, so 1px of negative block margin keeps the header at its
     locked 69px without shrinking the logo. */
  margin-block:-.5px;
  filter:drop-shadow(0 1px 4px rgba(0,0,0,.7)) drop-shadow(0 2px 16px rgba(0,0,0,.55));
}
@media (max-width:767px){
  header.site .mark img{ block-size:16px; inline-size:103.78px; }
}

/* The site footer (contents approved 2026-10-01): the four navigation links,
   the office address, the three social links and the copyright. No slogan.

   A quiet index, not a second page: one hairline inside the gutter, then two
   rows - where to go and how to write on the first, where else to follow and
   the copyright on the second - with the start column for places and the end
   column for addresses and the line of record. It stacks on a phone. Every
   link is a 45px target (min-block-size, so the rows sit on it and nothing
   overlaps). Logical properties and grid areas, so RTL is just the mirror.
   The footer's own side padding stays off: .wrap carries the page gutter. */
footer.site-foot{ display:block; padding:clamp(28px,4vh,44px) 0 clamp(26px,4vh,40px); }
.site-foot .wrap{
  display:grid; grid-template-columns:minmax(0,1fr) auto;
  grid-template-areas:"rule rule" "nav mail" "social copy";
  align-items:center; column-gap:40px; row-gap:0;
}
/* The hairline is a grid row of its own, so it spans the text column and not
   the gutter - the same edge as every other rule on the site. */
.site-foot .wrap::before{
  content:""; grid-area:rule; border-block-start:1px solid var(--hair);
  margin-block-end:clamp(14px,2vh,22px);
}
.site-foot p{ margin:0; }
.site-foot .f-nav{ grid-area:nav; display:flex; flex-wrap:wrap; column-gap:28px; }
.site-foot .f-mail{ grid-area:mail; justify-self:end; }
.site-foot .f-social{ grid-area:social; list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; column-gap:24px; }
.site-foot .copy{ grid-area:copy; justify-self:end; font-size:12.5px; letter-spacing:.04em; }
.site-foot a{
  display:inline-flex; align-items:center; min-block-size:45px; min-inline-size:45px;
  font-family:var(--sans); font-weight:400; font-size:14px; letter-spacing:.02em;
  color:var(--ivory-dim); text-decoration:none; transition:color .3s var(--ease);
}
.site-foot a:hover, .site-foot a:focus-visible{ color:var(--ivory); }
html[lang="he"] .site-foot .f-nav a{ font-family:var(--sans-he); letter-spacing:0; font-size:14.5px; }
html[lang="he"] .site-foot .copy{ font-family:var(--mono-he,var(--mono)); letter-spacing:0; font-size:12.5px; }
@media (max-width:767px){
  .site-foot .wrap{ grid-template-columns:minmax(0,1fr); grid-template-areas:"rule" "nav" "mail" "social" "copy"; }
  .site-foot .f-mail, .site-foot .copy{ justify-self:start; }
  /* Four links do not fit one 327px row; two even rows instead of one link
     left alone on the second. */
  .site-foot .f-nav{ display:grid; grid-template-columns:repeat(2,max-content); column-gap:32px; }
  .site-foot .copy{ margin-block-start:12px; }
  .site-foot a{ font-size:15px; }
  .site-foot .copy{ font-size:13px; letter-spacing:0; } /* one line at 375 */
  html[lang="he"] .site-foot .f-nav a{ font-size:15.5px; }
  html[lang="he"] .site-foot .copy{ font-size:13.5px; }
}