/* nika sŭr-mã — portfolio
   ------------------------------------------------------------------ */

:root{
  --bg:#0a0a0b;
  --fg:#eceae5;
  --dim:#918e87;
  --faint:#56544f;
  --line:rgba(236,234,229,.16);
  --pad:clamp(20px,3.4vw,48px);
  --hdr:60px;
  --sans:"Inter","Helvetica Neue",Helvetica,Arial,system-ui,sans-serif;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;
}

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

/* A tilted cut-out sticks out past its own layout box, which is enough to
   put a horizontal scrollbar on the page. Clip rather than scroll — nothing
   here is meant to be reached sideways. */
html{-webkit-text-size-adjust:100%;overflow-x:hidden;overflow-x:clip}

body{
  margin:0;
  overflow-x:hidden;
  overflow-x:clip;
  background:var(--bg);
  color:var(--fg);
  font-family:var(--sans);
  font-weight:300;
  font-size:15px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

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

a{color:inherit;text-decoration:none}

::selection{background:var(--fg);color:var(--bg)}

/* ---- background ---------------------------------------------------- */
/* The loop rendered out of the TouchDesigner patch. #bg is a WebGL copy
   of the same footage that the cursor can displace; it only replaces the
   video once the shader is live, so without WebGL the video just plays.  */

#bgv,#bg{
  position:fixed;inset:0;z-index:0;
  width:100%;height:100%;
  opacity:var(--bg-opacity,1);
}
#bgv{display:block;object-fit:cover;background:#07080e}
#bg{display:none}
#bg.on{display:block}

body:not(.deck-page){--bg-opacity:.92}

#veil{
  position:fixed;inset:0;z-index:1;pointer-events:none;
  background:rgba(6,7,12,.22);
}
body:not(.deck-page) #veil{
  background:linear-gradient(rgba(6,7,12,.72),rgba(6,7,12,.90));
}

/* ---- splash --------------------------------------------------------- */
/* The way in: the same portrait loop as the about page, held closer, and
   two doors. */

body.splash-page{overflow:hidden;--bg-opacity:1}
body.splash-page #bgv,
body.splash-page #bg{transform:scale(1.42);transform-origin:52% 46%}
body.splash-page #veil{background:rgba(8,8,10,.56)}

.splash{
  position:relative;z-index:2;
  height:100dvh;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:clamp(14px,2.2vh,26px);
  padding:var(--hdr) var(--pad) 0;
  text-align:center;
}
.splash-name{
  margin:0;
  font-family:var(--display,var(--sans));
  font-weight:200;font-size:clamp(34px,7vw,96px);line-height:1;
  letter-spacing:.02em;text-transform:uppercase;
  text-shadow:0 2px 26px rgba(0,0,0,.6);
}
.splash-line{
  margin:0;
  font-family:var(--mono);font-size:10px;letter-spacing:.28em;
  text-transform:uppercase;color:#cfccc6;
  text-shadow:0 1px 10px rgba(0,0,0,.8);
}
.splash-doors{
  display:flex;flex-wrap:wrap;justify-content:center;
  gap:clamp(18px,5vw,64px);
  margin-top:clamp(20px,4vh,48px);
}
.splash-doors a{
  font-family:var(--display,var(--sans));
  font-size:clamp(13px,1.5vw,17px);font-weight:300;
  text-shadow:0 1px 12px rgba(0,0,0,.75);
  letter-spacing:.24em;text-transform:uppercase;
  padding:14px 4px 10px;
  border-bottom:1px solid var(--line);
  transition:color .3s,border-color .3s,letter-spacing .3s;
}
.splash-doors a:hover{color:#fff;border-color:#fff;letter-spacing:.3em}

@media (max-width:520px){
  .splash-doors{flex-direction:column;gap:6px}
}

/* The about page runs the blurred portrait clip: neutral rather than blue,
   and a shade lighter so the face stays present. */
body.about-page{--bg-opacity:.85}
body.about-page #veil{
  background:linear-gradient(rgba(8,8,10,.58),rgba(8,8,10,.88));
}

/* On the mapping page the background IS the work — documentation of the
   projection itself — so it is held back only as far as the text needs. */
body.bg-rain{--bg-opacity:1;--faint:#7e7b75}
body.bg-rain #veil{
  background:linear-gradient(rgba(6,7,12,.58),rgba(6,7,12,.86));
}
/* The glitch loop and the ice-blue installation both blow out to white,
   so they need holding back further. */
body.bg-error #veil,
body.bg-deconstruction #veil{
  background:linear-gradient(rgba(6,7,12,.74),rgba(6,7,12,.90));
}

/* Small type has to survive passing over the bright parts of a projection. */
body.bg-rain .meta,
body.bg-rain .prose,
body.bg-rain .section-label,
body.bg-rain .grid figcaption,
body.bg-rain .next,
body.bg-rain .foot,
body.bg-error .meta,
body.bg-error .prose,
body.bg-error .section-label,
body.bg-error .next,
body.bg-error .foot,
body.bg-deconstruction .meta,
body.bg-deconstruction .prose,
body.bg-deconstruction .section-label,
body.bg-deconstruction .next,
body.bg-deconstruction .foot{text-shadow:0 1px 3px rgba(0,0,0,.85)}

main{position:relative;z-index:2}

/* ---- language switching ------------------------------------------ */
/* Every translatable fragment exists twice; CSS reveals one.          */

[data-t]{display:none}
html[lang="en"] [data-t="en"]{display:revert}
html[lang="ru"] [data-t="ru"]{display:revert}

/* ---- header ------------------------------------------------------- */

.hdr{
  position:fixed;top:0;left:0;right:0;height:var(--hdr);z-index:60;
  display:flex;align-items:center;justify-content:space-between;
  padding:0 var(--pad);
  pointer-events:none;
}
.hdr::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(to bottom,rgba(0,0,0,.72),rgba(0,0,0,0));
}
.hdr > *{pointer-events:auto}

.mark{
  font-family:var(--display,var(--sans));
  font-size:11px;font-weight:400;letter-spacing:.22em;text-transform:uppercase;
  white-space:nowrap;
}

.nav{display:flex;align-items:center;gap:clamp(12px,2vw,26px)}
.nav a,.nav button{
  font-family:var(--sans);font-size:11px;font-weight:400;letter-spacing:.1em;
  color:var(--dim);background:none;border:0;padding:0;cursor:pointer;
  transition:color .25s;
}
.nav a:hover,.nav button:hover,.nav a[aria-current="page"]{color:var(--fg)}

.lang{display:flex;gap:7px;padding-left:6px;border-left:1px solid var(--line);margin-left:2px}
.lang button{font-family:var(--mono);letter-spacing:.06em;color:var(--faint)}
.lang button[aria-pressed="true"]{color:var(--fg)}

/* ---- slide deck (home) -------------------------------------------- */

body.deck-page{overflow:hidden}

.deck{
  height:100dvh;overflow-y:scroll;overscroll-behavior-y:contain;
  scroll-snap-type:y mandatory;scroll-behavior:smooth;
  scrollbar-width:none;
}
.deck::-webkit-scrollbar{display:none}

.slide{
  position:relative;height:100dvh;scroll-snap-align:start;
  display:flex;align-items:center;justify-content:space-between;
  gap:clamp(16px,4vw,64px);
  padding:calc(var(--hdr) + 8px) var(--pad) 72px;
}
.slide::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:0;
  background:linear-gradient(100deg,rgba(6,6,8,.80) 0%,rgba(6,6,8,.42) 40%,rgba(6,6,8,0) 74%);
}

.slide .cap{
  position:relative;z-index:3;
  flex:1 1 44%;max-width:min(620px,48vw);
}
.slide .cut{flex:0 0 auto;z-index:2}
.slide .cut img{
  width:auto;height:auto;
  max-width:min(50vw,800px);
  max-height:min(70vh,740px);
}
/* A video has no intrinsic size to size the paper by, so it is given one. */
.slide .cut video{width:min(42vw,560px)}
.kicker{
  font-family:var(--mono);font-size:10px;letter-spacing:.24em;
  text-transform:uppercase;color:var(--dim);
}
.slide h2{
  margin:.5em 0 .42em;
  font-family:var(--display,var(--sans));
  font-weight:200;font-size:clamp(31px,5.6vw,78px);line-height:1.02;
  letter-spacing:.004em;text-transform:uppercase;
}
.slide .sub{
  margin:0;max-width:46ch;font-size:13px;line-height:1.65;
  color:#cbc8c2;letter-spacing:.012em;
}
.slide .go{
  display:inline-block;margin-top:22px;
  font-family:var(--mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--dim);border-bottom:1px solid var(--line);padding-bottom:4px;
  transition:color .25s,border-color .25s;
}
.slide a.hit{position:absolute;inset:0;z-index:5}
.slide:hover .go{color:var(--fg);border-color:var(--fg)}

/* ---- paper cutouts ------------------------------------------------- */
/* Work documentation is pasted onto the page as scissor-cut paper:
   a light margin under the photograph, an irregular edge, a hard shadow,
   and a spring as each one lands. Dome frames are already cut round, so
   they get the shadow and the spring but no paper behind them.          */

.cut{
  position:relative;margin:0;display:block;--tilt:0deg;
  background:#efece4;
  padding:clamp(6px,.85vw,15px);
  transform:rotate(var(--tilt));
  transform-origin:50% 88%;          /* hinged near its base, like a pinned cut-out */
  filter:drop-shadow(0 16px 22px rgba(0,0,0,.55)) drop-shadow(0 3px 4px rgba(0,0,0,.45));
  transition:filter .45s ease;
}
/* Every photograph is monochrome, so the collage reads as one cut-out world. */
.cut img{display:block;filter:grayscale(1) contrast(1.06)}
.cut[data-fit="contain"]{background:none;padding:0;clip-path:none}
/* Pinned up the wrong way round, on purpose — a cut-out may hold a
   video as well as a photograph, and both have to turn. */
.cut[data-flip="1"] img,
.cut[data-flip="1"] video{transform:rotate(180deg)}

/* Left in its own colour, against the monochrome of everything else. */
.cut[data-colour="1"] img,
.cut[data-colour="1"] video{filter:none}

.cut[data-shape="1"]{clip-path:polygon(0.0% 1.4%,20.0% 0.2%,40.0% 1.4%,60.0% 3.1%,80.0% 2.6%,100.0% 1.3%,98.3% 20.0%,98.6% 40.0%,98.1% 60.0%,98.1% 80.0%,97.4% 100.0%,80.0% 96.9%,60.0% 99.8%,40.0% 98.7%,20.0% 99.7%,0.0% 97.2%,2.4% 80.0%,1.9% 60.0%,3.2% 40.0%,2.4% 20.0%)}
.cut[data-shape="2"]{clip-path:polygon(0.0% 0.4%,20.0% 1.7%,40.0% 1.7%,60.0% 2.9%,80.0% 0.3%,100.0% 0.8%,98.0% 20.0%,98.1% 40.0%,97.3% 60.0%,98.1% 80.0%,97.5% 100.0%,80.0% 97.4%,60.0% 97.4%,40.0% 98.0%,20.0% 99.2%,0.0% 97.9%,0.4% 80.0%,2.8% 60.0%,1.5% 40.0%,2.8% 20.0%)}
.cut[data-shape="3"]{clip-path:polygon(0.0% 3.2%,20.0% 2.3%,40.0% 1.8%,60.0% 3.2%,80.0% 2.4%,100.0% 2.4%,98.1% 20.0%,99.1% 40.0%,98.0% 60.0%,97.8% 80.0%,98.0% 100.0%,80.0% 97.4%,60.0% 96.8%,40.0% 96.8%,20.0% 97.0%,0.0% 98.9%,2.0% 80.0%,1.0% 60.0%,1.8% 40.0%,3.0% 20.0%)}
.cut[data-shape="4"]{clip-path:polygon(0.0% 3.2%,20.0% 1.1%,40.0% 1.4%,60.0% 1.8%,80.0% 0.1%,100.0% 0.2%,98.1% 20.0%,99.7% 40.0%,97.5% 60.0%,98.2% 80.0%,97.3% 100.0%,80.0% 96.6%,60.0% 97.7%,40.0% 97.4%,20.0% 100.0%,0.0% 99.3%,0.8% 80.0%,2.7% 60.0%,0.7% 40.0%,0.0% 20.0%)}
.cut[data-shape="5"]{clip-path:polygon(0.0% 2.1%,20.0% 0.9%,40.0% 0.7%,60.0% 0.6%,80.0% 0.8%,100.0% 3.1%,99.4% 20.0%,99.0% 40.0%,97.8% 60.0%,98.0% 80.0%,99.2% 100.0%,80.0% 98.2%,60.0% 99.9%,40.0% 98.9%,20.0% 99.3%,0.0% 97.4%,2.8% 80.0%,3.4% 60.0%,3.2% 40.0%,3.0% 20.0%)}

/* Nothing is hidden at rest. The spring is added when a cutout lands, so a
   browser that never runs the animation still shows every photograph.
   Once it has landed the piece keeps rocking on its hinge — stepped, not
   eased, because cut-out animation is shot frame by frame. The steps also
   keep it cheap: the element only repaints when it jumps. */
html.js .cut.in{
  animation:
    cut-pop .58s cubic-bezier(.18,1.32,.32,1) var(--d,0ms) backwards,
    cut-rock 3.6s steps(3,end) calc(var(--d,0ms) + .58s) infinite;
}
@keyframes cut-pop{
  0%  {opacity:0;transform:rotate(calc(var(--tilt) * 3.2)) scale(.68)}
  55% {opacity:1}
  100%{opacity:1;transform:rotate(var(--tilt)) scale(1)}
}
@keyframes cut-rock{
  0%,100%{transform:rotate(var(--tilt)) translateY(0)}
  25%    {transform:rotate(calc(var(--tilt) + .85deg)) translateY(-2px)}
  50%    {transform:rotate(var(--tilt)) translateY(1px)}
  75%    {transform:rotate(calc(var(--tilt) - .85deg)) translateY(-1px)}
}
@media (prefers-reduced-motion:reduce){
  html.js .cut.in{animation:none}
}

/* Hovering flaps the piece harder, the way Gilliam's hinges snap. */
.slide:hover .cut,
.cut-item:hover .cut,
.hero:hover .cut,
.portrait:hover .cut{
  filter:drop-shadow(0 28px 36px rgba(0,0,0,.6)) drop-shadow(0 4px 6px rgba(0,0,0,.5));
}
html.js .slide:hover .cut.in,
html.js .cut-item:hover .cut.in,
html.js .hero:hover .cut.in,
html.js .portrait:hover .cut.in{
  animation-duration:.58s,1.1s;
}

/* ---- pager -------------------------------------------------------- */

.pager{
  position:fixed;left:var(--pad);bottom:20px;z-index:60;
  display:flex;flex-wrap:wrap;gap:13px;
  font-family:var(--mono);font-size:11px;letter-spacing:.05em;
}
.pager button{
  background:none;border:0;padding:0 0 4px;cursor:pointer;
  color:var(--faint);border-bottom:1px solid transparent;
  font:inherit;transition:color .25s,border-color .25s;
}
.pager button:hover{color:var(--dim)}
.pager button[aria-current="true"]{color:var(--fg);border-bottom-color:var(--fg)}

/* ---- interior pages ----------------------------------------------- */

.hero{
  position:relative;min-height:min(88vh,880px);
  display:flex;align-items:center;justify-content:space-between;
  gap:clamp(16px,4vw,64px);
  padding:calc(var(--hdr) + clamp(28px,6vh,70px)) var(--pad) clamp(28px,6vh,70px);
}
.hero::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:0;
  background:linear-gradient(100deg,rgba(6,6,8,.78) 0%,rgba(6,6,8,.40) 40%,rgba(6,6,8,0) 74%);
}
.hero .cap{position:relative;z-index:3;flex:1 1 46%;max-width:min(640px,50vw)}
.hero .cut{flex:0 0 auto;z-index:2}
.hero .cut img{
  width:auto;height:auto;
  max-width:min(46vw,720px);
  max-height:min(64vh,680px);
}
.hero .cut video{width:min(40vw,520px)}
.hero h1{
  margin:.5em 0 .34em;
  font-family:var(--display,var(--sans));font-weight:200;font-size:clamp(28px,5vw,66px);line-height:1.04;
  letter-spacing:.004em;text-transform:uppercase;
}
.hero .sub{margin:0;max-width:52ch;font-size:13px;color:#cbc8c2}

.wrap{max-width:1280px;margin:0 auto;padding:0 var(--pad)}

.cols{
  display:grid;gap:clamp(30px,5vw,74px);
  grid-template-columns:minmax(0,1fr);
  padding:clamp(46px,7vw,96px) 0 clamp(30px,5vw,60px);
}
@media (min-width:900px){
  .cols{grid-template-columns:minmax(0,300px) minmax(0,1fr)}
}

.meta{font-family:var(--mono);font-size:11px;line-height:1.85;letter-spacing:.02em}
.meta dl{margin:0;display:grid;grid-template-columns:1fr;gap:0}
.meta dt{color:var(--faint);text-transform:uppercase;letter-spacing:.14em;font-size:9.5px;margin-top:16px}
.meta dt:nth-of-type(1),.meta dt:nth-of-type(2){margin-top:0}
.meta dd{margin:2px 0 0;color:#cbc8c2}
.meta a{border-bottom:1px solid var(--line)}
.meta a:hover{border-color:var(--fg)}

.prose{max-width:66ch;font-size:15.5px;line-height:1.78;color:#d9d6d0;font-weight:300}
.prose p{margin:0 0 1.35em}
.prose p:last-child{margin-bottom:0}
.prose strong{font-weight:400;color:var(--fg)}
.prose ul{margin:0 0 1.35em;padding-left:1.1em}
.prose li{margin-bottom:.5em}
.prose a{border-bottom:1px solid var(--line)}
.prose a:hover{border-color:var(--fg)}

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

.section-label{
  font-family:var(--mono);font-size:9.5px;letter-spacing:.24em;text-transform:uppercase;
  color:var(--faint);padding:clamp(34px,5vw,64px) 0 18px;
}

/* ---- galleries ---------------------------------------------------- */

.grid{
  display:grid;gap:clamp(24px,3.6vw,56px);
  padding-bottom:clamp(54px,7vw,104px);
  grid-template-columns:repeat(auto-fill,minmax(min(100%,270px),1fr));
  align-items:start;
}
.cut-item{margin:0}
.grid .cut img{width:100%;height:auto}
.grid figcaption{
  font-family:var(--mono);font-size:10px;letter-spacing:.06em;color:var(--faint);
  padding:14px 2px 0;
}

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

.next{
  display:flex;flex-wrap:wrap;gap:10px 26px;align-items:baseline;
  padding:clamp(30px,5vw,58px) 0;border-top:1px solid var(--line);
}
.next .lbl{font-family:var(--mono);font-size:9.5px;letter-spacing:.24em;text-transform:uppercase;color:var(--faint)}
.next .ttl{font-family:var(--display,var(--sans));font-size:clamp(20px,3vw,34px);font-weight:200;text-transform:uppercase;letter-spacing:.01em}
.next a:hover .ttl{color:#fff}

.foot{
  display:flex;flex-wrap:wrap;gap:14px 30px;justify-content:space-between;
  padding:26px 0 34px;border-top:1px solid var(--line);
  font-family:var(--mono);font-size:10px;letter-spacing:.1em;color:var(--faint);
  text-transform:uppercase;
}
.foot a:hover{color:var(--fg)}

/* ---- about -------------------------------------------------------- */

.about-top{padding:calc(var(--hdr) + clamp(50px,10vh,120px)) 0 0}
.about-top h1{
  margin:0 0 .5em;
  font-family:var(--display,var(--sans));font-weight:200;font-size:clamp(30px,5.4vw,70px);line-height:1.05;
  text-transform:uppercase;letter-spacing:.004em;
}
.portrait{padding-top:6px}
.portrait .cut img{width:100%;filter:grayscale(1) contrast(1.04)}

/* A reel pinned to the page: vertical, silent, and a way through to Instagram. */
.cut video{display:block;height:auto;filter:grayscale(1) contrast(1.06)}
.portrait .cut video{width:100%}
.reel{cursor:pointer}
.reel .reel-tag{
  position:absolute;left:50%;transform:translateX(-50%);
  bottom:calc(clamp(6px,.85vw,15px) + 12px);
  font-family:var(--mono);font-size:9px;letter-spacing:.22em;text-transform:uppercase;
  color:#14140f;background:rgba(239,236,228,.92);padding:5px 10px;
  transition:background .25s,color .25s;
}
.reel:hover .reel-tag{background:#14140f;color:#efece4}

.cv{font-family:var(--mono);font-size:11.5px;line-height:1.75;letter-spacing:.015em}
.cv .row{
  display:grid;grid-template-columns:56px 1fr;gap:14px;
  padding:11px 0;border-top:1px solid var(--line);
}
.cv .row:last-child{border-bottom:1px solid var(--line)}
.cv .yr{color:var(--faint)}
.cv .what{color:#cbc8c2}
.cv .what b{font-weight:400;color:var(--fg)}

.contact{font-family:var(--mono);font-size:12px;letter-spacing:.04em}
.contact a{border-bottom:1px solid var(--line)}
.contact a:hover{border-color:var(--fg)}

/* ---- misc --------------------------------------------------------- */

.hint{
  position:fixed;right:var(--pad);bottom:22px;z-index:60;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--faint);pointer-events:none;
}
@media (max-width:760px){
  .hint{display:none}
  .pager{gap:10px;font-size:10px;right:var(--pad)}

  /* Portrait screens: the cutout sits above the type rather than beside it. */
  .slide,.hero{
    flex-direction:column-reverse;justify-content:center;
    gap:clamp(16px,3.4vh,32px);
  }
  .slide{padding-bottom:66px}
  .hero{min-height:auto;padding-top:calc(var(--hdr) + 34px)}
  .slide .cap,.hero .cap{flex:0 0 auto;max-width:100%}
  .slide .cut img{max-width:84vw;max-height:40vh}
  .hero .cut img{max-width:84vw;max-height:44vh}
  .slide .cut video,.hero .cut video{width:min(82vw,420px)}
  .slide::after,.hero::after{
    background:linear-gradient(to top,rgba(6,6,8,.88) 0%,rgba(6,6,8,.5) 46%,rgba(6,6,8,.12) 100%);
  }
}

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