/* ==========================================================================
   Rage Inc. World — site
   Palette and typography are the client's CI. Ground is near-black because
   the work is shot in dark venues under stage light; anything lighter fights
   the photography.
   ========================================================================== */

:root{
  /* CI palette */
  --off-white: #ffe6c5;
  --mustard:   #fcac00;
  --orange:    #e35402;
  --red:       #ab2301;

  --ink:       #0a0a0b;
  --ink-2:     #121213;
  --ink-3:     #1a1a1c;
  --paper:     var(--off-white);
  --mute:      rgba(255,230,197,0.58);
  --dim:       rgba(255,230,197,0.34);
  --line:      rgba(255,230,197,0.13);
  --line-2:    rgba(255,230,197,0.07);
  --brand:     var(--mustard);

  /* CI typefaces */
  --display: 'Neue Machina', 'Helvetica Neue', Arial, sans-serif;
  --sans:    'Neue Machina', 'Helvetica Neue', Arial, sans-serif;
  --mono:    'Supply', ui-monospace, SFMono-Regular, Menlo, monospace;

  --gutter:  clamp(18px, 4vw, 56px);
  --measure: 1560px;
  --ease:    cubic-bezier(0.16, 1, 0.3, 1);
  --nav-h:   clamp(58px, 7vh, 78px);
}

*, *::before, *::after{ box-sizing: border-box; }

html{ scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce){ html{ scroll-behavior: auto; } }

body{
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* clip, not hidden. overflow-x:hidden turns <body> into a scroll container,
     which kills position:sticky on the work filters and stops scroll events
     ever reaching window, so the nav never picks up .is-stuck. clip contains
     the bleed without any of that. */
  overflow-x: clip;
}

img, video{ display: block; max-width: 100%; }
a{ color: inherit; }
button{ color: inherit; }

.wrap{ width: 100%; max-width: var(--measure); margin: 0 auto; padding: 0 var(--gutter); }

/* ------------------------------------------------------------------ type */

.mono{
  font-family: var(--mono);
  font-size: clamp(9px, 0.82vw, 10.5px);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mute);
  line-height: 1.6;
}

.h-xl{
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(2.6rem, 7.5vw, 7rem);
  line-height: 0.92;
  letter-spacing: -0.035em;
  margin: 0;
}
.h-lg{
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(1.9rem, 4.4vw, 3.6rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
  margin: 0;
}
.h-md{
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(1.25rem, 2.2vw, 1.85rem);
  line-height: 1.18;
  letter-spacing: -0.02em;
  margin: 0;
}
.lede{
  font-size: clamp(0.98rem, 1.35vw, 1.2rem);
  line-height: 1.55;
  color: var(--mute);
  max-width: 46ch;
  margin: 0;
}
.body{ font-size: 0.95rem; line-height: 1.7; color: var(--mute); }
.accent{ color: var(--brand); }

/* ------------------------------------------------------------------- nav */

.nav{
  position: fixed; inset: 0 0 auto; z-index: 90;
  height: var(--nav-h);
  display: flex; align-items: center;
  background: linear-gradient(180deg, rgba(10,10,11,0.92), rgba(10,10,11,0));
  transition: background 0.4s var(--ease), border-color 0.4s var(--ease);
  border-bottom: 1px solid transparent;
}
.nav.is-stuck{ background: rgba(10,10,11,0.94); backdrop-filter: blur(14px); border-bottom-color: var(--line-2); }
.nav-inner{ display: flex; align-items: center; justify-content: space-between; gap: 20px; width: 100%; max-width: var(--measure); margin: 0 auto; padding: 0 var(--gutter); }

.brand{ display: block; width: clamp(88px, 9vw, 122px); flex-shrink: 0; }
.brand svg{ width: 100%; height: auto; color: var(--paper); display: block; }
.brand svg path:not([fill]), .brand svg circle:not([fill]){ fill: currentColor; }

.nav-links{ display: flex; gap: clamp(18px, 2.6vw, 40px); align-items: center; }
.nav-links a{
  text-decoration: none; position: relative; padding: 4px 0;
  color: var(--mute); transition: color 0.3s var(--ease);
}
.nav-links a::after{
  content: ''; position: absolute; left: 0; bottom: 0; height: 1px; width: 100%;
  background: var(--brand); transform: scaleX(0); transform-origin: 0 50%;
  transition: transform 0.45s var(--ease);
}
.nav-links a:hover, .nav-links a[aria-current="page"]{ color: var(--paper); }
.nav-links a:hover::after, .nav-links a[aria-current="page"]::after{ transform: scaleX(1); }

.nav-toggle{ display: none; background: none; border: 0; padding: 8px; cursor: pointer; color: var(--paper); }
.nav-toggle span{ display: block; width: 22px; height: 1.5px; background: currentColor; transition: transform .4s var(--ease), opacity .3s; }
.nav-toggle span + span{ margin-top: 5px; }
.nav[data-open="true"] .nav-toggle span:nth-child(1){ transform: translateY(6.5px) rotate(45deg); }
.nav[data-open="true"] .nav-toggle span:nth-child(2){ opacity: 0; }
.nav[data-open="true"] .nav-toggle span:nth-child(3){ transform: translateY(-6.5px) rotate(-45deg); }

/* ---------------------------------------------------------------- section */

.section{ padding: clamp(64px, 11vh, 140px) 0; }
.section-head{
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 24px; margin-bottom: clamp(26px, 4vh, 52px);
  padding-bottom: 16px; border-bottom: 1px solid var(--line-2);
}

/* ---------------------------------------------------------------- button */

.btn{
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.15em; text-transform: uppercase;
  padding: 14px 22px; border-radius: 2px; text-decoration: none;
  border: 1px solid var(--line); color: var(--paper); background: none;
  cursor: pointer; transition: background .4s var(--ease), border-color .4s var(--ease), color .4s var(--ease);
}
.btn:hover{ border-color: var(--brand); color: var(--brand); }
.btn--solid{ background: var(--brand); border-color: var(--brand); color: var(--ink); font-weight: 700; }
.btn--solid:hover{ background: var(--off-white); border-color: var(--off-white); color: var(--ink); }
.btn:focus-visible{ outline: 2px solid var(--brand); outline-offset: 3px; }

/* ---------------------------------------------------------------- footer */

.footer{ border-top: 1px solid var(--line-2); padding: clamp(46px, 7vh, 84px) 0 clamp(26px, 4vh, 44px); }
.footer-grid{ display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: clamp(28px, 5vw, 72px); }
.footer h4{ font-family: var(--mono); font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--dim); margin: 0 0 16px; font-weight: 400; }
.footer a{ display: block; text-decoration: none; color: var(--mute); padding: 5px 0; transition: color .3s var(--ease); font-size: .92rem; }
.footer a:hover{ color: var(--paper); }
.footer-base{ display: flex; justify-content: space-between; gap: 18px; margin-top: clamp(34px, 5vh, 60px); padding-top: 20px; border-top: 1px solid var(--line-2); }

/* ------------------------------------------------------------- reveal fx */

/* Content is visible by default and only hidden once JS has confirmed it can
   animate it. Hiding from plain CSS means any failure of IntersectionObserver
   leaves the page blank, which is not a risk worth taking on a live site. */
.js-reveal [data-reveal]{ opacity: 0; transform: translateY(18px); }
[data-reveal]{ transition: opacity .9s var(--ease), transform .9s var(--ease); }
.js-reveal [data-reveal].is-in{ opacity: 1; transform: none; }
[data-reveal-delay="1"]{ transition-delay: .08s; }
[data-reveal-delay="2"]{ transition-delay: .16s; }
[data-reveal-delay="3"]{ transition-delay: .24s; }

@media (prefers-reduced-motion: reduce){
  [data-reveal]{ opacity: 1; transform: none; transition: none; }
}

/* ----------------------------------------------------------- responsive */

@media (max-width: 860px){
  .nav-toggle{ display: block; }
  .nav-links{
    position: fixed; inset: var(--nav-h) 0 auto; flex-direction: column; align-items: flex-start;
    gap: 0; padding: 8px var(--gutter) 26px; background: rgba(10,10,11,0.98);
    backdrop-filter: blur(16px); border-bottom: 1px solid var(--line-2);
    transform: translateY(-8px); opacity: 0; pointer-events: none;
    transition: opacity .3s var(--ease), transform .3s var(--ease);
  }
  .nav[data-open="true"] .nav-links{ opacity: 1; transform: none; pointer-events: auto; }
  .nav-links a{ width: 100%; padding: 15px 0; border-bottom: 1px solid var(--line-2); font-size: 1.05rem; }
  .footer-grid{ grid-template-columns: 1fr; gap: 30px; }
  .footer-base{ flex-direction: column; }
}

/* ==========================================================================
   Home
   ========================================================================== */

.hero{ position: relative; min-height: 100svh; display: flex; align-items: flex-end; overflow: hidden; }

.hero-media{ position: absolute; inset: 0; z-index: 0; }
.hero-plate{
  position: absolute; inset: 0;
  background-size: cover; background-position: center;
  opacity: 0; transform: scale(1.06);
  transition: opacity 1.6s var(--ease);
  /* Their work is often shot bright. Pull it down so the headline holds
     without needing an opaque scrim over the whole frame. */
  filter: contrast(1.04) saturate(0.9) brightness(0.72);
}
.hero-plate.is-live{ opacity: 1; animation: hero-push 9s linear forwards; }

/* The reel plate. It carries its own movement, so it is spared the slow push
   the stills get. It is still graded down, but less hard than the first cut
   needed: this one is drone work over grass and a built set, which measures
   some forty luma points darker than the balloons-against-sky opening, and
   .46 on top of that buried it. */
.hero-plate--reel{ transform: none; filter: contrast(1.03) saturate(.88) brightness(.58); }
.hero-plate--reel.is-live{ animation: none; transform: none; }
.hero-reel{ position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
@keyframes hero-push{ from{ transform: scale(1.06); } to{ transform: scale(1.14); } }

.hero-scrim{
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    /* weighted to the lower third, which is where the type sits */
    linear-gradient(180deg,
      rgba(10,10,11,.80) 0%,
      rgba(10,10,11,.30) 26%,
      rgba(10,10,11,.55) 55%,
      rgba(10,10,11,.88) 78%,
      rgba(10,10,11,.98) 100%),
    linear-gradient(90deg, rgba(10,10,11,.72) 0%, rgba(10,10,11,.10) 55%, transparent 100%),
    radial-gradient(130% 90% at 50% 35%, transparent 38%, rgba(10,10,11,.55) 100%);
}

.hero-body{ position: relative; z-index: 2; width: 100%; padding-bottom: clamp(38px, 7vh, 84px); }
.hero-kicker{ margin: 0 0 clamp(14px, 2.4vh, 24px); color: var(--brand); }
.hero-title{
  max-width: 16ch;
  /* The headline breaks after "Rage" on every screen (the <br> is in the
     markup), so "Welcome to Rage" has to fit one line. It measures 8.68em;
     below about 410px the usual 2.6rem floor is wider than the space between
     the gutters, and it wrapped to three lines. Capped at that space here,
     with a little to spare. Everywhere wider, the cap is larger than the
     normal size, so nothing changes there. */
  font-size: min(clamp(2.6rem, 7.5vw, 7rem), calc((100vw - 2 * var(--gutter)) / 8.95));
  text-shadow: 0 2px 40px rgba(10,10,11,.85), 0 1px 8px rgba(10,10,11,.6);
}
.hero-kicker, .hero-foot .lede{ text-shadow: 0 1px 16px rgba(10,10,11,.8); }
.hero-foot{ display: flex; align-items: flex-end; justify-content: space-between; gap: 28px; margin-top: clamp(22px, 4vh, 44px); flex-wrap: wrap; }
.hero-counter{ display: flex; gap: 8px; align-items: center; }
.hero-dot{ width: 20px; height: 2px; background: var(--line); transition: background .5s var(--ease); }
.hero-dot.is-on{ background: var(--brand); }

/* ------------------------------------------------------------ work teaser */

.teaser-grid{
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(8px, 1vw, 16px);
}
.tile{
  position: relative; overflow: hidden; border-radius: 2px;
  background: var(--ink-2); text-decoration: none; display: block;
  aspect-ratio: 1;
}
.tile img{ width: 100%; height: 100%; object-fit: cover; transition: transform 1.1s var(--ease), filter .6s var(--ease); }
.tile:hover img{ transform: scale(1.05); }
.tile-meta{
  position: absolute; inset: auto 0 0; z-index: 2; padding: 16px;
  /* The two labels are spans. Inline elements ignore vertical margin, so
     without this they render on one line and the client name runs straight
     into the category. */
  display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
  background: linear-gradient(0deg, rgba(10,10,11,.9), transparent);
  opacity: 0; transform: translateY(8px);
  transition: opacity .45s var(--ease), transform .45s var(--ease);
}
.tile:hover .tile-meta, .tile:focus-visible .tile-meta{ opacity: 1; transform: none; }
.tile-client{ font-family: var(--display); font-weight: 800; font-size: 1rem; letter-spacing: -.02em; line-height: 1.2; color: var(--paper); }
.tile-cat{ font-family: var(--mono); font-size: 9px; letter-spacing: .16em; text-transform: uppercase; color: var(--brand); }

/* deliberately irregular so the grid does not read as a contact sheet */
.tile--a{ grid-column: span 7; aspect-ratio: 16/10; }
.tile--b{ grid-column: span 5; aspect-ratio: 4/5; }
.tile--c{ grid-column: span 4; aspect-ratio: 1; }
.tile--d{ grid-column: span 4; aspect-ratio: 1; }
.tile--e{ grid-column: span 4; aspect-ratio: 1; }

/* Row one is two tiles of different shape: seven columns at 16/10 beside
   five at 4/5. The narrow one is much the taller, the row takes its height,
   and the wide one was left sitting short with the page showing through
   underneath it. It stretches to the row instead, and the image covers.
   Below the breakpoint they stack into rows of their own, so the ratio is
   still what sets the height there. */
@media (min-width: 861px){
  .tile--a{ aspect-ratio: auto; }
  /* Out of flow, or the picture's own proportions set the height of the tile,
     the tile sets the height of the row, and the wide one ends up taller than
     the tall one instead of matching it. Absolute means the row is measured
     from tile--b alone and tile--a stretches to whatever that comes to.
     .tile is already position: relative with overflow hidden. */
  .tile--a img{ position: absolute; inset: 0; }
}

/* ----------------------------------------------------------- client strip */

.clients{ border-block: 1px solid var(--line-2); padding: clamp(30px, 5vh, 56px) 0; }
.client-row{ display: flex; flex-wrap: wrap; align-items: center; gap: clamp(26px, 5vw, 76px); justify-content: space-between; }
.client-name{
  font-family: var(--display); font-weight: 800;
  font-size: clamp(1rem, 2vw, 1.6rem); letter-spacing: -.02em;
  color: var(--dim); transition: color .4s var(--ease);
}
.client-name:hover{ color: var(--paper); }

/* ------------------------------------------------------ marketplace band */

.band{
  position: relative; overflow: hidden;
  background: var(--ink-2);
  border-block: 1px solid var(--line-2);
  padding: clamp(56px, 10vh, 118px) 0;
}
.band::before{
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(115deg, rgba(252,172,0,.13), transparent 46%);
}
.band-inner{ position: relative; z-index: 1; display: grid; grid-template-columns: 1.25fr 1fr; gap: clamp(28px, 5vw, 76px); align-items: center; }
.band-actions{ display: flex; gap: 12px; flex-wrap: wrap; margin-top: clamp(20px, 3vh, 32px); }

@media (max-width: 860px){
  .teaser-grid{ grid-template-columns: repeat(6, 1fr); }
  .tile--a{ grid-column: span 6; }
  .tile--b{ grid-column: span 6; aspect-ratio: 4/3; }
  .tile--c, .tile--d, .tile--e{ grid-column: span 3; }
  .tile--e{ grid-column: span 6; aspect-ratio: 16/9; }
  .band-inner{ grid-template-columns: 1fr; }
  .client-row{ gap: 18px 28px; justify-content: flex-start; }
}

/* ==========================================================================
   Work
   ========================================================================== */

.page-head{ padding: calc(var(--nav-h) + clamp(48px, 9vh, 110px)) 0 clamp(26px, 4vh, 46px); }
.page-head .h-xl{ max-width: 14ch; }
.page-head .lede{ margin-top: clamp(16px, 2.6vh, 26px); }

.filters{
  display: flex; gap: 8px; flex-wrap: wrap;
  padding: 14px 0 clamp(16px, 2.4vh, 26px);
  margin-bottom: clamp(22px, 4vh, 44px);
  position: sticky; top: var(--nav-h); z-index: 20;
}
/* Full-bleed backing so the bar runs edge to edge instead of stopping at the
   wrap gutters, and the same glass as .nav.is-stuck so the two read as one
   bar rather than two different treatments stacked on each other. A gradient
   here let tile tops smear through underneath. */
.filters::before{
  content: ''; position: absolute; z-index: -1;
  top: 0; bottom: 0; left: 50%; width: 100vw; transform: translateX(-50%);
  background: rgba(10,10,11,.94);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line-2);
}
.filter{
  font-family: var(--mono); font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
  padding: 9px 16px; border-radius: 999px; border: 1px solid var(--line);
  background: none; color: var(--mute); cursor: pointer;
  transition: color .3s var(--ease), border-color .3s var(--ease), background .3s var(--ease);
}
.filter:hover{ color: var(--paper); border-color: var(--mute); }
.filter[aria-pressed="true"]{ background: var(--brand); border-color: var(--brand); color: var(--ink); font-weight: 700; }
.filter:focus-visible{ outline: 2px solid var(--brand); outline-offset: 2px; }

.work-grid{
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  gap: clamp(8px, 1vw, 16px);
}
.work-item{
  position: relative; overflow: hidden; border-radius: 2px; background: var(--ink-2);
  border: 0; padding: 0; cursor: zoom-in; display: block; width: 100%;
  transition: opacity .5s var(--ease), transform .5s var(--ease);
}
.work-item img{ width: 100%; height: 100%; object-fit: cover; aspect-ratio: 1; transition: transform 1.1s var(--ease); }
.work-item:hover img{ transform: scale(1.05); }
.work-item[hidden]{ display: none; }
.work-item:focus-visible{ outline: 2px solid var(--brand); outline-offset: 3px; }
.work-item.is-filtering{ opacity: 0; transform: scale(.97); }

/* every third item runs tall, so the grid has rhythm rather than a lattice */
.work-item:nth-child(6n+1) img{ aspect-ratio: 4/5; }
.work-item:nth-child(6n+4) img{ aspect-ratio: 4/5; }

.work-cap{
  position: absolute; inset: auto 0 0; padding: 14px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
  background: linear-gradient(0deg, rgba(10,10,11,.92), transparent);
  text-align: left; opacity: 0; transform: translateY(8px);
  transition: opacity .4s var(--ease), transform .4s var(--ease);
}
.work-item:hover .work-cap, .work-item:focus-visible .work-cap{ opacity: 1; transform: none; }

.work-empty{ padding: clamp(40px, 8vh, 90px) 0; text-align: center; }

/* -------------------------------------------------------------- lightbox */

.lightbox{
  position: fixed; inset: 0; z-index: 200;
  display: flex; flex-direction: column;
  background: rgba(6,6,7,.96); backdrop-filter: blur(10px);
  opacity: 0; pointer-events: none; transition: opacity .4s var(--ease);
  padding: clamp(52px, 7vh, 76px) clamp(12px, 3vw, 40px) clamp(12px, 2vh, 22px);
  gap: clamp(10px, 1.6vh, 18px);
}
.lightbox[data-open="true"]{ opacity: 1; pointer-events: auto; }

/* The figure takes whatever height is left once the strip and caption have
   been laid out, and the image fills it. min-height: 0 is what allows a flex
   child to shrink below its content size; without it the image would push
   the strip off the bottom. */
.lightbox figure{
  margin: 0; flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column;
  gap: clamp(8px, 1.4vh, 14px);
}
/* scale-down, not contain: contain would happily blow a 1600px file up to
   fill a 4K viewport and go soft. scale-down caps it at its natural size. */
.lightbox img{
  flex: 1 1 auto; min-height: 0; width: 100%; height: auto;
  object-fit: scale-down; border-radius: 2px;
}
.lightbox figcaption{ flex: 0 0 auto; text-align: center; }

/* --- filmstrip ---------------------------------------------------------- */
.lb-strip{
  flex: 0 0 auto; display: flex; gap: 8px;
  overflow-x: auto; overflow-y: hidden;
  padding: 10px 2px 2px; scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
  scroll-snap-type: x proximity;
}
.lb-strip::-webkit-scrollbar{ height: 6px; }
.lb-strip::-webkit-scrollbar-thumb{ background: var(--line); border-radius: 3px; }
.lb-thumb{
  flex: 0 0 auto; scroll-snap-align: center;
  width: clamp(54px, 7vh, 84px); aspect-ratio: 1;
  padding: 0; border: 0; border-radius: 2px; overflow: hidden; cursor: pointer;
  background: var(--ink-2); opacity: .42;
  outline: 1px solid transparent; outline-offset: 2px;
  transition: opacity .3s var(--ease), outline-color .3s var(--ease);
}
.lb-thumb img{ width: 100%; height: 100%; object-fit: cover; border-radius: 0; }
.lb-thumb:hover, .lb-thumb:focus-visible{ opacity: .85; }
.lb-thumb[aria-current="true"]{ opacity: 1; outline-color: var(--brand); }
.lb-close{
  position: absolute; top: clamp(14px, 3vw, 30px); right: clamp(14px, 3vw, 30px);
  width: 42px; height: 42px; border-radius: 50%; border: 1px solid var(--line);
  /* backed, not transparent: a wide image can reach the top corners and the
     glyph has to stay readable over it */
  background: rgba(10,10,11,.6); backdrop-filter: blur(6px);
  color: var(--paper); cursor: pointer; font-size: 17px; line-height: 1;
  transition: border-color .3s var(--ease), color .3s var(--ease);
}
.lb-close:hover{ border-color: var(--brand); color: var(--brand); }
.lb-nav{
  position: absolute; top: calc(50% - clamp(30px, 5vh, 56px)); transform: translateY(-50%);
  width: 46px; height: 46px; border-radius: 50%; border: 1px solid var(--line);
  background: rgba(10,10,11,.6); backdrop-filter: blur(6px);
  color: var(--paper); cursor: pointer; font-size: 19px;
  transition: border-color .3s var(--ease), color .3s var(--ease);
}
.lb-nav:hover{ border-color: var(--brand); color: var(--brand); }
.lb-prev{ left: clamp(8px, 2vw, 26px); }
.lb-next{ right: clamp(8px, 2vw, 26px); }

/* ==========================================================================
   Marketplace — deliberately a different temperature from the portfolio.
   Lighter ground, product language, not showcase language.
   ========================================================================== */

.mkt{ background: var(--ink-2); }
.mkt-head{ background: var(--ink-3); border-bottom: 1px solid var(--line-2); }
.mkt-split{ display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(12px, 1.6vw, 22px); margin-top: clamp(24px, 4vh, 42px); }
.mkt-card{
  padding: clamp(24px, 3.4vw, 40px);
  border: 1px solid var(--line); border-radius: 3px;
  background: var(--ink); display: flex; flex-direction: column; gap: 12px;
  transition: border-color .4s var(--ease), transform .4s var(--ease);
}
.mkt-card:hover{ border-color: var(--brand); transform: translateY(-3px); }
.mkt-card .btn{ align-self: flex-start; margin-top: auto; }
.mkt-role{ color: var(--brand); }

/* The route through the product, as labels rather than prose. Six lines a
   reader scans in a second beats a paragraph they skip. */
.mkt-steps{ list-style: none; margin: 6px 0 8px; padding: 0; }
.mkt-steps li{
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 13px;
  align-items: baseline; padding: 9px 0; border-top: 1px solid var(--line-2);
}
.mkt-steps li:first-child{ border-top: 0; padding-top: 0; }
.mkt-steps b{ color: var(--brand); font-size: 10px; letter-spacing: .1em; font-weight: 400; }
.mkt-steps span{ color: var(--mute); font-size: .92rem; line-height: 1.5; }

.listings{ display: flex; flex-direction: column; gap: 10px; margin-top: clamp(22px, 3.6vh, 40px); }
.listing{
  display: grid; grid-template-columns: 1.6fr 1fr 1fr auto; gap: 18px; align-items: center;
  padding: clamp(16px, 2vw, 22px); border: 1px solid var(--line-2); border-radius: 3px;
  background: var(--ink); transition: border-color .35s var(--ease), background .35s var(--ease);
}
.listing:hover{ border-color: var(--line); background: var(--ink-3); }
.listing h3{ margin: 0; font-family: var(--display); font-weight: 800; font-size: 1.05rem; letter-spacing: -.02em; }
.listing-co{ margin: 3px 0 0; }
.stars{ color: var(--brand); letter-spacing: .1em; font-size: .85rem; }

.mkt-note{ margin-top: clamp(26px, 4vh, 48px); padding: 18px 20px; border-left: 2px solid var(--brand); background: var(--ink); }

/* ==========================================================================
   Contact
   ========================================================================== */

.contact-grid{ display: grid; grid-template-columns: 1fr 1.1fr; gap: clamp(32px, 6vw, 90px); align-items: start; }
.field-row{ display: grid; grid-template-columns: 1fr 1fr; gap: clamp(12px, 1.6vw, 20px); }
.field{ display: flex; flex-direction: column; gap: 7px; margin-bottom: clamp(14px, 2vh, 20px); }
.field label{ font-family: var(--mono); font-size: 9.5px; letter-spacing: .15em; text-transform: uppercase; color: var(--dim); }
.field input, .field select, .field textarea{
  background: var(--ink-2); border: 1px solid var(--line-2); border-radius: 2px;
  padding: 13px 14px; color: var(--paper); font-family: var(--sans); font-size: .95rem;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.field textarea{ resize: vertical; min-height: 128px; }
.field input:focus, .field select:focus, .field textarea:focus{ outline: none; border-color: var(--brand); background: var(--ink-3); }
.field input::placeholder, .field textarea::placeholder{ color: var(--dim); }
.form-msg{ min-height: 1.3em; margin: 6px 0 0; }
.form-msg[data-state="ok"]{ color: var(--brand); }
.form-msg[data-state="err"]{ color: var(--orange); }

.contact-aside dt{ font-family: var(--mono); font-size: 9.5px; letter-spacing: .15em; text-transform: uppercase; color: var(--dim); margin-top: 22px; }
.contact-aside dd{ margin: 6px 0 0; font-size: 1rem; }
.contact-aside a{ text-decoration: none; border-bottom: 1px solid var(--line); padding-bottom: 2px; transition: border-color .3s var(--ease); }
.contact-aside a:hover{ border-color: var(--brand); }

@media (max-width: 860px){
  .mkt-split, .contact-grid, .field-row{ grid-template-columns: 1fr; }
  .listing{ grid-template-columns: 1fr; gap: 8px; }
  .filters{ position: static; }
}

/* ==========================================================================
   Home — additional sections
   ========================================================================== */

/* --- positioning statement: does the job an About page would ------------ */
.statement{ padding: clamp(70px, 13vh, 160px) 0; }
.statement-inner{ display: grid; grid-template-columns: minmax(0,1fr) minmax(0,.8fr); gap: clamp(28px, 6vw, 90px); align-items: end; }
.statement h2{
  font-family: var(--display); font-weight: 800;
  font-size: clamp(1.7rem, 3.9vw, 3.2rem); line-height: 1.06;
  letter-spacing: -.03em; margin: 0; max-width: 20ch;
}
.statement h2 em{ font-style: normal; color: var(--brand); }
.stat-row{ display: flex; gap: clamp(22px, 4vw, 56px); margin-top: clamp(24px, 4vh, 40px); flex-wrap: wrap; }
.stat b{ display: block; font-family: var(--display); font-weight: 800; font-size: clamp(1.6rem, 3vw, 2.4rem); letter-spacing: -.03em; line-height: 1; }
.stat span{ display: block; margin-top: 6px; }

/* --- capabilities ------------------------------------------------------- */
.caps{ display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(8px, 1vw, 16px); }
.cap{
  position: relative; overflow: hidden; border-radius: 2px; text-decoration: none;
  display: block; aspect-ratio: 3/4; background: var(--ink-2);
}
.cap img{ width: 100%; height: 100%; object-fit: cover; filter: brightness(.6); transition: transform 1.1s var(--ease), filter .6s var(--ease); }
.cap:hover img{ transform: scale(1.06); filter: brightness(.78); }
.cap-body{ position: absolute; inset: auto 0 0; padding: clamp(14px, 1.6vw, 22px); background: linear-gradient(0deg, rgba(10,10,11,.94), transparent); }
.cap-body h3{ font-family: var(--display); font-weight: 800; font-size: clamp(1rem, 1.4vw, 1.25rem); letter-spacing: -.02em; margin: 0 0 4px; }
.cap-n{ position: absolute; top: clamp(12px, 1.4vw, 18px); left: clamp(12px, 1.4vw, 18px); color: var(--brand); }

/* --- full-bleed breakout ------------------------------------------------ */
.breakout{ position: relative; min-height: clamp(360px, 62vh, 640px); display: flex; align-items: center; overflow: hidden; }
.breakout img{ position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: brightness(.5) saturate(.95); }
.breakout::after{ content: ''; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(10,10,11,.9) 0%, rgba(10,10,11,.35) 60%, rgba(10,10,11,.7) 100%); }
.breakout .wrap{ position: relative; z-index: 2; }
.breakout blockquote{
  margin: 0; max-width: 22ch; font-family: var(--display); font-weight: 800;
  font-size: clamp(1.5rem, 3.4vw, 2.9rem); line-height: 1.1; letter-spacing: -.03em;
  text-shadow: 0 2px 30px rgba(10,10,11,.8);
}

/* --- the six divisions -------------------------------------------------- */
.divisions{ display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(8px, 1vw, 14px); }
.division{
  position: relative; padding: clamp(20px, 2.4vw, 30px);
  border: 1px solid var(--line-2); border-radius: 3px; background: var(--ink-2);
  overflow: hidden; transition: border-color .4s var(--ease), transform .4s var(--ease);
}
.division::before{
  content: ''; position: absolute; inset: auto 0 0 0; height: 2px; background: var(--c, var(--brand));
  transform: scaleX(0); transform-origin: 0 50%; transition: transform .5s var(--ease);
}
.division:hover{ border-color: var(--line); transform: translateY(-3px); }
.division:hover::before{ transform: scaleX(1); }
.division-dot{ width: 8px; height: 8px; border-radius: 50%; background: var(--c, var(--brand)); box-shadow: 0 0 0 1px rgba(255,230,197,.18); }
.division h3{ font-family: var(--display); font-weight: 800; font-size: clamp(1.05rem, 1.5vw, 1.3rem); letter-spacing: -.02em; margin: 14px 0 6px; }

/* Locations are not divisions. Kept as a quiet line under the grid so the
   list of divisions can grow without a city sitting next to Post. */
.divisions-where{ margin: clamp(20px, 3vh, 32px) 0 0; color: var(--dim); }

/* --- how it works ------------------------------------------------------- */
/* Two lanes, because the two audiences are asking different questions and
   reading the wrong answer is worse than reading none. */
.how{ display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(8px, 1vw, 16px); }
.how-col{
  border: 1px solid var(--line-2); border-radius: 3px; background: var(--ink-2);
  padding: clamp(20px, 2.4vw, 34px);
}
.how-role{ margin: 0 0 clamp(14px, 2.2vh, 22px); color: var(--brand); }
.how-steps{ list-style: none; margin: 0; padding: 0; }
.how-step{
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(12px, 1.5vw, 20px);
  padding: clamp(13px, 1.9vh, 18px) 0;
  border-top: 1px solid var(--line-2);
}
.how-step:first-child{ border-top: 0; padding-top: 0; }
.how-step:last-child{ padding-bottom: 0; }
.how-n{ color: var(--brand); line-height: 1.7; }
/* Inline spans ignore vertical margin, so the pair has to be a flex column
   for the gap to exist at all. Same reason .tile-meta is one. */
.how-txt{ display: flex; flex-direction: column; gap: 5px; }
.how-txt b{
  font-family: var(--display); font-weight: 800;
  font-size: clamp(.98rem, 1.3vw, 1.1rem); letter-spacing: -.02em;
}
.how-txt span{ color: var(--mute); font-size: .88rem; line-height: 1.55; }

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

/* An author `display` outranks the UA's [hidden] rule, so anything toggled
   through the attribute can stay stubbornly visible. The dashboard hit this;
   the waitlist success panel would hit it next. */
[hidden]{ display: none !important; }

/* --- founding creator --------------------------------------------------- */
/* Set apart from the list above it, because it is an offer rather than a
   description, and the two should not read as one run of bullets. */
.founding{
  margin-top: clamp(26px, 4vh, 40px);
  border: 1px solid rgba(252,172,0,.3); border-radius: 3px;
  background: linear-gradient(150deg, rgba(252,172,0,.07), transparent 62%), var(--ink-2);
  padding: clamp(20px, 2.6vw, 28px);
}
.founding-tag{ margin: 0 0 12px; color: var(--brand); }
.founding-lead{
  margin: 0 0 16px; font-family: var(--display); font-weight: 800;
  font-size: clamp(1rem, 1.6vw, 1.2rem); letter-spacing: -.02em; line-height: 1.3;
}
.founding-sub{ margin: 0 0 10px; color: var(--dim); }
.founding-list{ list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.founding-list li{
  position: relative; padding-left: 20px; color: var(--mute);
  font-size: .88rem; line-height: 1.55;
}
.founding-list li::before{
  content: ''; position: absolute; left: 0; top: .5em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--brand);
}
/* The same offer, one line, where the primary call to action lives. */
.band-founding{
  margin: clamp(16px, 2.4vh, 22px) 0 0; color: var(--brand);
  letter-spacing: .04em; text-transform: none; font-size: 11px; line-height: 1.6;
}

/* --- marketplace preview ------------------------------------------------ */
/* Two small cards standing in for the product, on the home page, next to the
   pitch. It is drawn rather than screenshotted so it cannot fall out of date
   and does not depend on the prototype screens, which do not ship. */
.preview{ display: flex; flex-direction: column; gap: 10px; }
.preview-tag{ margin: 0 0 2px; color: var(--dim); }
.pv-card{
  border: 1px solid var(--line); border-radius: 3px;
  background: rgba(10, 10, 11, .58); padding: clamp(14px, 1.6vw, 20px);
  backdrop-filter: blur(6px);
}
.pv-head{ display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 12px; align-items: center; }
/* The empty state, not a placeholder we never got round to filling. A new
   profile has no picture on it yet, and this card is addressed to the person
   reading it, so a stranger's face would be both wrong and a claim we cannot
   make about them. */
.pv-avatar{
  width: 36px; height: 36px; border-radius: 50%;
  display: grid; place-items: center; flex: none;
  background: rgba(252,172,0,.08);
  border: 1px solid rgba(252,172,0,.26);
  color: rgba(252,172,0,.6);
}
.pv-avatar svg{ width: 17px; height: 17px; display: block; }
/* Inline spans ignore vertical margin; the pair has to be a column. */
.pv-id{ display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.pv-id b{ font-family: var(--display); font-weight: 800; font-size: .95rem; letter-spacing: -.02em; }
.pv-id span{ color: var(--dim); font-size: 9.5px; }
.pv-state{ color: #6ee7a8; font-size: 9px; letter-spacing: .08em; white-space: nowrap; }
.pv-tags{ display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
.pv-tags span{
  padding: 3px 9px; border: 1px solid var(--line-2); border-radius: 999px;
  font-family: var(--mono); font-size: 9px; letter-spacing: .06em; color: var(--mute);
}
.pv-foot{
  display: flex; gap: 16px; flex-wrap: wrap; margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--line-2); color: var(--dim); font-size: 9px;
}
.pv-kicker{ margin: 0 0 8px; color: var(--brand); font-size: 9px; }
.pv-title{ font-family: var(--display); font-weight: 800; font-size: 1rem; letter-spacing: -.02em; display: block; }
.pv-meta{ display: flex; gap: 14px; flex-wrap: wrap; margin-top: 10px; color: var(--dim); font-size: 9.5px; }

/* --- status pill -------------------------------------------------------- */
/* In the nav, because that is where someone looks to find out what a site
   has, and "something new is happening here" is the whole message. */
.pill{
  display: inline-block; margin-left: 7px; padding: 2px 6px;
  border: 1px solid rgba(252,172,0,.42); border-radius: 999px;
  color: var(--brand); font-size: 8.5px; letter-spacing: .1em;
  text-transform: uppercase; vertical-align: 1px; white-space: nowrap;
}
.nav-links a:hover .pill{ border-color: var(--brand); }

/* --- the marketplace, once it is open ----------------------------------- */
/* Added to the public pages by marketplace-open.js, and only where an API
   answers behind them. On a site with nothing behind it, none of this
   exists and the page is the one that was written before it did. */
.mkt-open{
  margin-top: clamp(28px, 4vh, 46px); padding: clamp(20px, 2.6vw, 30px);
  border: 1px solid rgba(252,172,0,.3); border-radius: 3px; background: var(--ink-2);
}
.mkt-open-tag{ margin: 0 0 12px; color: var(--brand); }
.mkt-open-actions{ display: flex; flex-wrap: wrap; gap: 10px; }
.mkt-open-people{ display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
.mkt-open-people .pv-card{ transition: border-color .3s var(--ease), transform .5s var(--ease); }
.mkt-open-people .pv-card:hover{ border-color: var(--brand); transform: translateY(-2px); }
/* Where the waitlist form was. A list is for demand you cannot serve; this
   is the thing the list was standing in for. */
.mkt-claim{
  border: 1px solid rgba(252,172,0,.28); border-radius: 3px;
  background: var(--ink-2); padding: clamp(24px, 3vw, 38px); align-self: start;
}

/* --- waitlist success --------------------------------------------------- */
/* Replaces the form rather than sitting under it. Someone who has just signed
   up should not be looking at the thing they already did. */
.waitlist-done{
  border: 1px solid rgba(252,172,0,.28); border-radius: 3px;
  background: var(--ink-2); padding: clamp(24px, 3vw, 38px);
}
.waitlist-done h3{
  font-family: var(--display); font-weight: 800; margin: 0 0 12px;
  font-size: clamp(1.15rem, 2vw, 1.5rem); letter-spacing: -.025em;
}
.waitlist-done p{ margin: 0 0 14px; color: var(--mute); font-size: .92rem; line-height: 1.65; }
.waitlist-done .btn{ width: 100%; justify-content: center; margin-top: 8px; }
.waitlist-done:focus{ outline: none; }
.waitlist-done:focus-visible{ outline: 2px solid var(--brand); outline-offset: 3px; }

/* --- legal prose -------------------------------------------------------- */
/* Narrow measure on purpose. A privacy notice nobody can read is not a
   notice, and full-width lines at this size are not readable. */
.legal{ max-width: 68ch; }
.legal-block{ padding: clamp(22px, 3.4vh, 34px) 0; border-top: 1px solid var(--line-2); }
.legal-block:first-child{ border-top: 0; padding-top: 0; }
.legal h2{
  font-family: var(--display); font-weight: 800;
  font-size: clamp(1.05rem, 1.7vw, 1.35rem); letter-spacing: -.025em; margin: 0 0 14px;
}
.legal p, .legal ul{ margin: 0 0 14px; color: var(--mute); line-height: 1.7; font-size: .95rem; }
.legal ul{ padding-left: 1.15em; }
.legal li{ margin-bottom: 6px; }
.legal p:last-child, .legal ul:last-child{ margin-bottom: 0; }
.legal b{ color: var(--paper); font-weight: 500; }
.legal a{ color: var(--brand); text-decoration: none; border-bottom: 1px solid rgba(252,172,0,.35); }
.legal a:hover{ border-bottom-color: var(--brand); }
.legal-updated{ color: var(--dim); margin-top: 20px; }

/* --- consent ------------------------------------------------------------ */
/* Unticked, always. A pre-ticked box is not consent under POPIA, and the
   whole point of asking separately is that the answer is a real one. */
.consent{
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 10px;
  align-items: start; margin: 2px 0 4px; cursor: pointer;
}
.consent input{ width: 15px; height: 15px; margin: 3px 0 0; accent-color: var(--brand); }
.consent span{ color: var(--mute); font-size: .82rem; line-height: 1.55; }
.form-note{ color: var(--dim); font-size: .78rem; line-height: 1.6; margin: 14px 0 0; }
.form-note a{ color: var(--mute); text-decoration: none; border-bottom: 1px solid var(--line); }
.form-note a:hover{ color: var(--brand); border-bottom-color: var(--brand); }

/* --- closing call ------------------------------------------------------- */
.cta-end{ padding: clamp(70px, 13vh, 160px) 0; text-align: center; border-top: 1px solid var(--line-2); }
.cta-end h2{ font-family: var(--display); font-weight: 800; font-size: clamp(2rem, 5.4vw, 4.4rem); line-height: 1; letter-spacing: -.035em; margin: 0 auto; max-width: 16ch; }
.cta-end .btn{ margin-top: clamp(24px, 4vh, 40px); }

@media (max-width: 980px){
  .caps{ grid-template-columns: repeat(2, 1fr); }
  .divisions{ grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px){
  .statement-inner{ grid-template-columns: 1fr; }
  .divisions{ grid-template-columns: 1fr; }
}

/* ====================================================================== */
/* motion                                                                  */
/*                                                                         */
/* Everything here is additive: without JS, or with reduced motion, the    */
/* page still reads exactly as it does now. Nothing is hidden by CSS       */
/* alone. The block at the end of this file turns all of it off.          */
/* ====================================================================== */

/* --- scroll progress ---------------------------------------------------- */
.scroll-progress{
  position: fixed; top: 0; left: 0; height: 2px; width: 100%;
  transform: scaleX(0); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--brand), var(--rage-orange, #e35402));
  z-index: 95; pointer-events: none;
}

/* --- headings wipe up behind their own line ----------------------------- */
/* clip-path rather than opacity: type arrives from under a hard edge, the
   way a title card does, instead of dissolving. */
.js-reveal [data-wipe]{ clip-path: inset(0 0 105% 0); transform: translateY(.22em); }
[data-wipe]{ transition: clip-path 1s var(--ease), transform 1s var(--ease); }
.js-reveal [data-wipe].is-in{ clip-path: inset(0 0 -20% 0); transform: none; }
[data-wipe-delay="1"]{ transition-delay: .09s; }
[data-wipe-delay="2"]{ transition-delay: .18s; }
[data-wipe-delay="3"]{ transition-delay: .27s; }

/* --- images uncover, and settle out of a slow push-in -------------------- */
/* Driven through a custom property rather than by setting transform here.
   Setting transform directly would outrank every .x:hover img rule above and
   silently kill the hover zooms. */
.reveal-media{ overflow: hidden; }
.reveal-media img{ transform: scale(var(--rm, 1)); transition: transform 1.5s cubic-bezier(.16,.84,.34,1); }
.js-reveal .reveal-media:not(.is-in) img{ --rm: 1.14; }
.reveal-media:hover img{ --rm: 1.05; transition-duration: 1.1s; }

/* --- parallax ----------------------------------------------------------- */
/* Driven from JS via --par so a browser without it simply sits still. */
[data-parallax]{ will-change: transform; }
/* Oversized enough that the travel never exposes an edge: the layer moves by
   at most half of data-parallax in each direction. */
[data-parallax] > img{ transform: translate3d(0, var(--par, 0px), 0) scale(1.3); }

/* --- section rules draw themselves in ------------------------------------ */
/* The plain border stays as the no-JS fallback; under .js-reveal it hands
   over to a pseudo-element that can be scaled. */
.js-reveal .section-head{ position: relative; border-bottom-color: transparent; }
.js-reveal .section-head::after{
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--line-2); transform: scaleX(0); transform-origin: 0 50%;
  transition: transform 1.1s var(--ease) .12s;
}
.js-reveal .section-head.is-in::after{ transform: scaleX(1); }

/* --- counters ----------------------------------------------------------- */
.stat b{ font-variant-numeric: tabular-nums; }

/* --- client marquee ----------------------------------------------------- */
/* Duplicated track, translated by exactly half its width, so the seam never
   lands mid-name. Falls back to the static flex row if JS does not run. */
.client-marquee{ overflow: hidden; -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.client-marquee .client-row{ flex-wrap: nowrap; width: max-content; animation: marquee 38s linear infinite; }
.client-marquee:hover .client-row{ animation-play-state: paused; }
@keyframes marquee{ from{ transform: translate3d(0,0,0); } to{ transform: translate3d(-50%,0,0); } }

/* --- division rows sweep their accent ----------------------------------- */
.division{ position: relative; }
.division::before{
  content: ''; position: absolute; inset: -10px -14px; border-radius: 10px;
  background: var(--c, var(--brand)); opacity: 0;
  transition: opacity .45s var(--ease); pointer-events: none; z-index: -1;
}
.division:hover::before{ opacity: .07; }
.division-dot{ transition: transform .45s var(--ease), box-shadow .45s var(--ease); }
.division:hover .division-dot{ transform: scale(1.9); box-shadow: 0 0 0 5px color-mix(in srgb, var(--c, var(--brand)) 22%, transparent); }

/* --- hero settles on load ----------------------------------------------- */
/* On .hero-media, the container, rather than on .hero-plate: the plates are
   already running the 9s hero-push keyframes and a transform here would
   fight them. Nesting the two composes instead. */
.js-reveal .hero-media{ transform: scale(1.08); }
.hero-media{ transition: transform 2.2s cubic-bezier(.16,.84,.34,1); }
.js-reveal .hero.is-ready .hero-media{ transform: none; }

@media (prefers-reduced-motion: reduce){
  .js-reveal [data-wipe],
  .js-reveal [data-wipe].is-in{ clip-path: none; transform: none; transition: none; }
  .js-reveal .section-head::after,
  .js-reveal .section-head.is-in::after{ transform: none; transition: none; }
  .js-reveal .reveal-media:not(.is-in) img,
  .reveal-media:hover img,
  .js-reveal .hero-media,
  [data-parallax] > img{ transform: none; transition: none; }
  .client-marquee .client-row{ animation: none; width: auto; flex-wrap: wrap; }
  .scroll-progress{ display: none; }
  .division:hover .division-dot{ transform: none; }
}

/* --- marketplace waitlist ----------------------------------------------- */
/* Replaced the illustrative brief listings. Invented companies on a public
   page imply commercial relationships that do not exist, and this converts
   better anyway: it asks who someone is, which is the number that says
   whether the marketplace has a supply problem or a demand problem. */
/* minmax(0, 1fr), not 1fr. A bare 1fr is minmax(auto, 1fr), and that auto
   floors the track at the item's min-content width, so one wide child pushes
   the column past the viewport instead of wrapping inside it. */
.waitlist{ display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(30px, 5vw, 80px); align-items: start; }
.waitlist-why{ list-style: none; margin: clamp(26px, 4vh, 40px) 0 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.waitlist-why li{
  position: relative; padding-left: 22px; color: var(--mute);
  font-size: .92rem; line-height: 1.6;
}
.waitlist-why li::before{
  content: ''; position: absolute; left: 0; top: .55em;
  width: 7px; height: 7px; border-radius: 50%; background: var(--brand);
}
.waitlist-form{
  border: 1px solid var(--line-2); border-radius: 3px;
  background: var(--ink-2); padding: clamp(22px, 3vw, 34px);
}
.waitlist-form .btn{ width: 100%; justify-content: center; margin-top: 6px; }
.waitlist-legal{
  margin: 16px 0 0; font-size: 10px; line-height: 1.7; color: var(--dim);
  letter-spacing: .04em; text-transform: none;
}
.waitlist-form .note{ font-size: .76rem; color: var(--dim); }

@media (max-width: 860px){
  .waitlist{ grid-template-columns: minmax(0, 1fr); }
}

/* ================================================================ splash
   The showreel gate on the home page. Shown only while <html> carries
   .splash-on, which the inline script in <head> sets before first paint.
   Leaving is a curtain: the logo and button lift away first, then the whole
   panel is clipped upward from its bottom edge, so the hero headline, which
   sits low in the frame, is the first thing uncovered.
   ======================================================================= */

.splash{
  position: fixed; inset: 0; z-index: 1000;
  display: none; place-items: center;
  overflow: hidden;
  /* Frame zero of the wide cut, painted before the video has a frame. */
  background: var(--ink) url('../media/showreel/poster-wide.jpg') center / cover no-repeat;
  clip-path: inset(0 0 0 0);
  transition: clip-path 1.15s cubic-bezier(.77, 0, .18, 1) .18s;
}
/* Must match the test in site.js that picks the tall file. */
@media (max-aspect-ratio: 3/4){
  .splash{ background-image: url('../media/showreel/poster-tall.jpg'); }
}
.splash-on .splash{ display: grid; }
.splash-lock, .splash-lock body{ overflow: hidden; }

.splash.is-leaving{ clip-path: inset(0 0 100% 0); pointer-events: none; }

.splash-video{
  position: absolute; inset: 0;
  width: 100%; height: 100%; max-width: none; object-fit: cover;
  opacity: 0;
  transition: opacity .6s linear, transform 1.4s cubic-bezier(.77, 0, .18, 1) .18s;
}
/* Faded in on its first real frame rather than shown at once: a video
   element that has not decoded anything yet can paint black over the poster. */
.splash.is-playing .splash-video{ opacity: 1; }
/* Drifts up more slowly than the curtain edge travels, which reads as the
   panel being drawn away rather than a hard wipe. */
.splash.is-leaving .splash-video{ transform: translateY(-9%) scale(1.03); }

.splash-shade{
  position: absolute; inset: 0; pointer-events: none;
  background:
    /* holds the logo and button over the brightest frames of the reel */
    radial-gradient(58% 46% at 50% 50%, rgba(10,10,11,.46) 0%, rgba(10,10,11,.16) 68%, transparent 100%),
    linear-gradient(180deg, rgba(10,10,11,.38) 0%, transparent 20%, transparent 68%, rgba(10,10,11,.72) 100%);
}

/* Grain is drawn here rather than baked into the video, where noise is the
   most expensive thing there is to compress. */
.splash-grain{
  position: absolute; inset: -50%; pointer-events: none;
  opacity: .075;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1.4 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: splash-grain .8s steps(5) infinite;
}
@keyframes splash-grain{
  0%   { transform: translate(0, 0); }
  20%  { transform: translate(-2%, 1.5%); }
  40%  { transform: translate(1.5%, -2%); }
  60%  { transform: translate(-1%, -1%); }
  80%  { transform: translate(2%, 2%); }
  100% { transform: translate(0, 0); }
}

.splash-body{
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  gap: clamp(30px, 5.5vh, 56px);
  padding: 0 var(--gutter);
  transition: opacity .45s var(--ease), transform .7s var(--ease);
}
.splash.is-leaving .splash-body{ opacity: 0; transform: translateY(-26px); }

.splash-logo{
  width: clamp(230px, 38vw, 580px);
  color: var(--paper);
  filter: drop-shadow(0 6px 34px rgba(0,0,0,.4));
  animation: splash-in 1.3s var(--ease) .1s both;
}
.splash-logo svg{ display: block; width: 100%; height: auto; }
.splash-logo svg path:not([fill]), .splash-logo svg circle:not([fill]){ fill: currentColor; }

.splash-enter{
  display: inline-flex; align-items: center; gap: 14px;
  font-family: var(--mono); font-size: clamp(10.5px, .9vw, 12px);
  letter-spacing: .2em; text-transform: uppercase;
  padding: 17px 28px;
  color: var(--paper);
  background: rgba(10,10,11,.28);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border: 1px solid rgba(255,230,197,.42);
  border-radius: 999px;
  cursor: pointer;
  transition: background .45s var(--ease), border-color .45s var(--ease), color .45s var(--ease);
  animation: splash-in 1.3s var(--ease) .45s both;
}
.splash-enter-arrow{ display: inline-block; transition: transform .45s var(--ease); }
.splash-enter:hover{ background: var(--brand); border-color: var(--brand); color: var(--ink); }
.splash-enter:hover .splash-enter-arrow{ transform: translateX(5px); }
.splash-enter:focus-visible{ outline: 2px solid var(--brand); outline-offset: 5px; }

.splash-foot{
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
  padding: 0 var(--gutter) max(24px, env(safe-area-inset-bottom));
  color: var(--mute);
  transition: opacity .4s var(--ease);
  animation: splash-in 1.3s var(--ease) .75s both;
}
.splash-foot a{ text-decoration: none; transition: color .3s var(--ease); }
.splash-foot a:hover{ color: var(--brand); }
.splash-foot a:focus-visible{ outline: 2px solid var(--brand); outline-offset: 4px; }
.splash.is-leaving .splash-foot{ opacity: 0; }
@media (max-width: 560px){ .splash-foot span{ display: none; } .splash-foot{ justify-content: center; } }

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

/* No curtain, no drift, no grain shimmer: a plain crossfade out. site.js
   also leaves the video unloaded, so this is the poster as a still. */
@media (prefers-reduced-motion: reduce){
  .splash{ clip-path: none; transition: opacity .45s linear; }
  .splash.is-leaving{ clip-path: none; opacity: 0; }
  .splash.is-leaving .splash-video,
  .splash.is-leaving .splash-body{ transform: none; }
  .splash-grain, .splash-logo, .splash-enter, .splash-foot{ animation: none; }
}
