/* ============================================================
   Žan Rekič Zupančič — portfolio
   Direction: "Type and nothing else".
   Brand constraint: black ground, colour carried by type only.
   Type scale: 13 / 17 / 21 / 36 / 62 / 122 / 168 / 250 / 297
   (the two hero sizes are the justified masthead, by design)
   ============================================================ */

:root {
  --bg: #000000;
  --paper: #F2F2F0;
  --bone: #DEDEDA;
  --dim: #8C8C86;
  --surface: #0B0B0B;

  --lime: #C6FF3D;
  --coral: #FF4D2E;
  --blue: #5B7CFF;
  --chalk: #E9E4D8;

  --display: "Barlow Condensed", "Arial Narrow", sans-serif;
  --text: "Barlow", system-ui, sans-serif;

  --edge: clamp(20px, 5vw, 84px);
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--paper);
  font-family: var(--text);
  font-size: clamp(17px, 1.08vw, 18px);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; height: auto; }
p { margin: 0; }
:focus-visible { outline: 2px solid var(--lime); outline-offset: 3px; }
::selection { background: var(--lime); color: #000; }

.ink-lime { color: var(--lime); }
.ink-coral { color: var(--coral); }
.ink-blue { color: var(--blue); }

/* --- cursor spotlight --------------------------------------------- */
/* taste-skill-ignore: light on black, not a decorative gradient band */
.spotlight {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    640px circle at var(--mx, 50%) var(--my, 18%),
    rgba(198, 255, 61, 0.07),
    rgba(91, 124, 255, 0.03) 44%,
    transparent 70%
  );
}

/* --- nav ----------------------------------------------------------- */
.nav {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: baseline;
  gap: 28px;
  padding: 16px var(--edge) 12px;
  background: #000;
  border-bottom: 1px solid transparent;
  transition: border-color .45s ease;
}

/* only once the masthead is gone do we need a seam to hold the nav down */
.nav.is-past { border-bottom-color: rgba(255, 255, 255, .1); }

.nav__mark {
  font-family: var(--display);
  font-weight: 700;
  font-size: 21px;
  letter-spacing: .06em;
  color: var(--lime);
}

.nav__links {
  display: flex;
  gap: clamp(12px, 2vw, 30px);
  font-size: 13px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dim);
}
.nav__links a { transition: color .25s ease; }
.nav__links a:hover { color: var(--paper); }

.nav__status {
  margin-left: auto;
  font-size: 14px;
  color: var(--dim);
  line-height: 1;
  white-space: nowrap;
}

/* --- hero ---------------------------------------------------------- */
.hero {
  position: relative;
  z-index: 1;
  padding: clamp(28px, 6vh, 72px) var(--edge) clamp(28px, 5vh, 56px);
  display: flex;
  flex-direction: column;
}

.hero__eyebrow {
  font-size: 13px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: clamp(14px, 3vh, 32px);
}
.sep { color: var(--coral); padding: 0 .35em; }

/* Justified masthead: each line sized to span the full measure. */
.hero__title {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  line-height: .8;
  letter-spacing: -.02em;
  text-transform: uppercase;
  /* the masthead leaves slightly slower than the page scrolls, and
     eases back a few percent as it goes */
  transform: translate3d(0, var(--drift, 0px), 0) scale(var(--zoom, 1));
}

.hero__title .line:nth-child(1) .line__in { font-size: clamp(62px, 20.6vw, 297px); }
.hero__title .line:nth-child(2) .line__in { font-size: clamp(56px, 17.3vw, 250px); }

.line {
  display: block;
  overflow: hidden;
  /* the display face puts carons above cap height, so a line-height under 1
     would slice them off; the padding widens the clip box, the margin cancels it */
  padding-top: .17em;
  margin-top: -.17em;
}
.line__in { display: block; }

/* proof row: fills the space under the masthead with facts, not void */
.hero__facts {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(22px, 4vw, 70px);
  margin: clamp(22px, 4.5vh, 50px) 0 0;
  padding: 0;
}

.hero__facts li { display: flex; flex-direction: column; gap: 4px; }

.hero__facts b {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(36px, 4.6vw, 62px);
  line-height: .85;
  letter-spacing: -.02em;
}

.hero__facts span {
  font-size: 13px;
  color: var(--dim);
}

.hero__foot {
  padding-top: clamp(26px, 5vh, 52px);
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px 40px;
}

.hero__lede {
  max-width: 32ch;
  font-size: clamp(17px, 1.35vw, 21px);
  line-height: 1.4;
  text-wrap: pretty;
}

.hero__actions { display: flex; gap: 12px; flex-wrap: wrap; }

.btn {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 0 22px;
  background: var(--lime);
  color: #000;
  font-family: var(--display);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: .1em;
  text-transform: uppercase;
  border: 1px solid var(--lime);
  transition: background .22s ease, color .22s ease, transform .22s ease;
}

.btn:hover { background: transparent; color: var(--lime); transform: translateY(-1px); }

/* once the pointer drives transform directly, a .22s transition would smear
   every frame; hand transform to the rAF loop, keep the colour fade */
.btn.is-magnetic { transition-property: background, color, border-color; will-change: transform; }

.btn--ghost { background: transparent; color: var(--paper); border-color: #3A3A36; }
.btn--ghost:hover { color: var(--lime); border-color: var(--lime); }

/* --- band ---------------------------------------------------------- */
.band {
  position: relative;
  z-index: 1;
  overflow: hidden;
  padding: 14px 0;
  /* taste-skill-ignore: intentional display bleed; masked at both ends */
  white-space: nowrap;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
}

.band__track {
  display: inline-flex;
  gap: 22px;
  font-family: var(--display);
  font-weight: 600;
  font-size: 21px;
  letter-spacing: .16em;
  color: var(--lime);
  animation: band 42s linear infinite;
  will-change: transform;
}
.band__track span:nth-child(even) { color: var(--dim); }

@keyframes band {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
.band:hover .band__track { animation-play-state: paused; }

/* JS takes the wheel: scroll velocity drives the band, so the keyframes must
   stop or the two transforms fight each other */
.band.is-live .band__track { animation: none; }

/* --- section chrome ------------------------------------------------ */
.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px 30px;
  padding-bottom: clamp(16px, 2.2vw, 26px);
}

.section-title {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(36px, 4.4vw, 62px);
  line-height: .9;
  letter-spacing: -.01em;
  text-transform: uppercase;
}

.section-note { font-size: 13px; color: var(--dim); letter-spacing: .04em; }

/* --- work rows: separated by space and scale, not rules ------------ */
.work {
  position: relative;
  z-index: 1;
  padding: clamp(48px, 7vw, 104px) var(--edge);
  /* How far the row motion is allowed to travel, as a multiple of the
     measured offset. Narrow screens shrink it, because a fixed 66px of
     lateral travel clips the names against the viewport edge there. */
  --travel: 1;
  /* names now travel far enough to leave the section; clip instead of
     letting them push a horizontal scrollbar onto the page */
  overflow-x: clip;
}

.rows { list-style: none; margin: 0; padding: 0; }

.row { padding: clamp(30px, 4.4vw, 64px) 0; }

.row__top {
  display: flex;
  align-items: baseline;
  gap: clamp(10px, 1.6vw, 22px);
}

.row__name {
  margin: 0;
  flex: 1;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(40px, 8.6vw, 122px);
  line-height: .86;
  letter-spacing: -.02em;
  text-transform: uppercase;
  color: var(--ink, var(--paper));
}

.row__name a { display: inline-block; transition: transform .4s cubic-bezier(.2,.8,.2,1); }
.row__name a:hover { transform: translateX(8px); }

.row__tag {
  font-size: 13px;
  color: var(--dim);
  white-space: nowrap;
}

.row__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(18px, 3vw, 44px);
  margin-top: clamp(14px, 1.8vw, 24px);
}

.row__col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(20px, 2.4vw, 30px);
}

.row__col p {
  max-width: 44ch;
  color: var(--bone);
  font-size: clamp(17px, 1.05vw, 18px);
  text-wrap: pretty;
}

.row__open {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--dim);
  text-decoration: none;
  padding-bottom: 4px;
  border-bottom: 1px solid rgba(255, 255, 255, .22);
  transition: color .3s, gap .35s cubic-bezier(.16, 1, .3, 1), border-color .3s;
}

.row__open:hover,
.row__open:focus-visible {
  color: var(--ink);
  gap: 14px;
  border-bottom-color: var(--ink);
}
/* surface by fill, one tone step from the page - not an outline */
.row__shot {
  margin: 0;
  overflow: hidden;
  aspect-ratio: 16 / 10;
  background: var(--surface);
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .08);
}

/* real screenshot of the live page, edge-cropped to one frame */
.row__shot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  /* scaled up so the frame has room to pan inside itself on pointer move */
  transform: scale(1.045) translate3d(var(--px, 0px), calc(var(--py, 0px) + var(--sy, 0px)), 0);
  transition: transform .9s cubic-bezier(.16, 1, .3, 1);
}

.row:hover .row__shot img { transform: scale(1.02) translate3d(var(--px, 0px), var(--py, 0px), 0); }

/* while the pointer is inside, follow it tightly instead of easing over .9s */
.row__shot.is-tilting img { transition-duration: .16s; }

/* --- about --------------------------------------------------------- */
.about {
  position: relative;
  z-index: 1;
  padding: clamp(32px, 5vw, 78px) var(--edge) clamp(48px, 7vw, 104px);
}

.about__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  gap: clamp(26px, 5vw, 72px);
  padding-top: clamp(20px, 3vw, 36px);
}

.about__wide {
  font-size: clamp(21px, 2.4vw, 36px);
  line-height: 1.26;
  letter-spacing: -.012em;
  max-width: 26ch;
  text-wrap: pretty;
}

.about__rest {
  margin-top: 1em;
  max-width: 44ch;
  font-size: clamp(17px, 1.05vw, 18px);
  color: var(--bone);
}

.facts { margin: 0; display: grid; gap: 20px; align-content: start; }

.facts dt {
  font-family: var(--display);
  font-weight: 600;
  font-size: 21px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--coral);
}

.facts dd { margin: 4px 0 0; font-size: 17px; line-height: 1.5; color: var(--bone); }

/* --- cta: biggest lime type, black ground (no colour fills) -------- */
.cta {
  position: relative;
  z-index: 1;
  padding: clamp(40px, 7vw, 104px) var(--edge) clamp(36px, 6vw, 84px);
}

.cta__title {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(46px, 12.4vw, 168px);
  line-height: .82;
  letter-spacing: -.026em;
  text-transform: uppercase;
  color: var(--lime);
}

.cta__links {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px clamp(20px, 3vw, 40px);
  margin-top: clamp(28px, 4vw, 50px);
  font-size: 13px;
  color: var(--dim);
}

.cta__links a { border-bottom: 1px solid transparent; transition: color .25s ease, border-color .25s ease; }
.cta__links a:hover { color: var(--lime); border-color: var(--lime); }

/* taste-skill-ignore: link underline, not a divider rule */
.cta__mail {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(21px, 2.2vw, 36px);
  letter-spacing: .01em;
  text-transform: none;
  color: var(--paper);
  border-bottom-color: var(--coral) !important;
}

/* --- footer -------------------------------------------------------- */
.foot {
  position: relative;
  z-index: 1;
  padding: clamp(20px, 3vw, 36px) var(--edge) 0;
  overflow: hidden;
}

.foot__wordmark {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(35px, 11.4vw, 168px);
  line-height: .78;
  letter-spacing: -.03em;
  color: transparent;
  -webkit-text-stroke: 1px #4A4A44;
  white-space: nowrap;
  text-align: center;
  margin: 0;
}

.foot__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 26px;
  justify-content: space-between;
  padding: 18px 0 24px;
  margin-top: clamp(14px, 2.4vw, 28px);
  font-size: 13px;
  color: var(--dim);
}

/* --- reveal motion (JS only, so no-JS keeps everything visible) ---- */
.js .reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity .85s cubic-bezier(.2,.8,.2,1), transform .85s cubic-bezier(.2,.8,.2,1);
  transition-delay: var(--d, 0ms);
}

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

.js .line__in.reveal {
  transform: translateY(102%);
  opacity: 1;
  transition: transform 1.05s cubic-bezier(.16,1,.3,1);
  transition-delay: var(--d, 0ms);
}
.js .line__in.reveal.is-in { transform: none; }

/* The masked reveal is driven by the parent: a span translated fully outside
   its overflow:hidden line has no visible area, so observing it never fires. */
.js .cta__title .line__in {
  transform: translateY(102%);
  transition: transform 1.05s cubic-bezier(.16,1,.3,1);
}
.js .cta__title .line:nth-child(2) .line__in { transition-delay: 90ms; }
.js .cta__title.is-in .line__in { transform: none; }

.js .line__in.reveal-now {
  transform: translateY(102%);
  animation: line-up 1.15s cubic-bezier(.16,1,.3,1) forwards;
}
.js .line:nth-child(2) .line__in.reveal-now { animation-delay: .12s; }

@keyframes line-up { to { transform: none; } }

/* --- motion layer v2 ----------------------------------------------- */
/* Leonardo-scale motion, on a site whose only medium is type.
   Word stagger: titles assemble word by word instead of fading as a block. */
.js [data-split] .w {
  display: inline-block;
  opacity: 0;
  transform: translateY(.4em);
  filter: blur(7px);
  transition:
    opacity .45s cubic-bezier(.2, .8, .2, 1),
    transform .72s cubic-bezier(.16, 1, .3, 1),
    filter .45s cubic-bezier(.2, .8, .2, 1);
  transition-delay: calc(var(--i, 0) * 70ms);
}
.js [data-split].is-in .w { opacity: 1; transform: none; filter: none; }

/* The wall. The reference site opens on a wall of generated images.
   What this site generates is shipped software, so the wall is made of
   names: solid above, outlined below, drifting opposite ways. */
.wall {
  position: relative;
  z-index: 1;
  overflow: hidden;
  padding: clamp(26px, 4.4vw, 58px) 0;
  pointer-events: none;
  /* a mask fade at both ends, not a decorative fill */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent); /* taste-skill-ignore: mask fade */
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent); /* taste-skill-ignore: mask fade */
}
.wall__row { overflow: hidden; }
.wall__track {
  display: flex;
  align-items: baseline;
  width: max-content;
  transform: translate3d(var(--wx, 0px), 0, 0);
  will-change: transform;
}
.wall__track span {
  display: inline-block;
  padding-right: .26em;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(32px, 6.4vw, 86px);
  line-height: 1.1;
  letter-spacing: -.02em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink, var(--paper));
}
.wall__row--out .wall__track span {
  color: transparent;
  -webkit-text-stroke: 1px rgba(244, 241, 234, .32);
}

/* Project names slide sideways as each row crosses the viewport. */
.js .row__name { transform: translate3d(calc(var(--dx, 0px) * var(--travel, 1)), 0, 0); }

/* Inter-row motion. The gaps between works were dead space; now each row
   breathes vertically (translate, not transform, so the entrance reveal
   keeps its own channel), the tag converges on the name from the opposite
   side, and neighbouring rows drift apart and back together as you scroll. */
.js .row { translate: 0 calc(var(--ry, 0px) * var(--travel, 1)); }
.js .row__tag { transform: translate3d(calc(var(--tx, 0px) * var(--travel, 1)), 0, 0); }

/* The nav marks the section you are actually in. */
.js .nav__links a.is-current { color: var(--lime); }

/* Press feedback on a real press, not a hover. No transition: the point
   of a press state is that it lands instantly. */
.btn:active,
.row__open:active,
.cta__links a:active,
.nav__mark:active { scale: .96; }

/* --- responsive ---------------------------------------------------- */
@media (max-width: 860px) {
  .hero { min-height: auto; }
  .hero__foot { margin-top: 32px; }
  .row__body { grid-template-columns: 1fr; }
  .about__grid { grid-template-columns: 1fr; }
  .row__top { flex-wrap: wrap; }
  .nav__links { display: none; }
  .row__tag { width: 100%; }
  /* less horizontal room, so less travel */
  .work { --travel: .45; }
}

@media (max-width: 520px) {
  .row__name { font-size: clamp(34px, 12.4vw, 56px); }
  /* a phone has no room for lateral travel: keep it a hint, not a slide */
  .work { --travel: .28; }
  .hero__facts {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 16px;
  }
  .hero__facts b { font-size: clamp(28px, 9.6vw, 38px); }
  .hero__facts span { font-size: 11.5px; line-height: 1.35; }
  .cta__title { font-size: 10.4vw; }
  .cta__links { gap: 10px 20px; }
}

/* --- reduced motion ------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js .reveal,
  .js .line__in.reveal,
  .js .line__in.reveal-now {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
    transition: none !important;
  }
  .band__track { animation: none; }
  .spotlight { display: none; }
  .hero__title { transform: none; }
  .row__shot img,
  .row:hover .row__shot img { transform: none; }
  .btn.is-magnetic { transition-property: background, color, border-color; }
  .plate__line { animation: none; }
  /* motion layer v2: every new movement is inert here, and the content
     that the stagger reveals is simply present */
  .js [data-split] .w {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }
  .wall__track { transform: none !important; }
  .js .row__name { transform: none !important; }
  /* inter-row motion is additive only: with reduce, the rows sit exactly
     where the document puts them and the gaps never breathe */
  .js .row { translate: none !important; }
  .js .row__tag { transform: none !important; }
  .hero__title { transform: none !important; }
  .js .nav__links a.is-current { color: var(--paper); }
}
