/* Seam Transitions · the page frame, the studio page, and what the seams share. */

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

:root {
  --dark: #111;
  --paper: #fff;
  --ink: #111;
  --font: 'Plus Jakarta Sans', system-ui, sans-serif;
  --gutter: 24px;
  --hero: 100vh; /* the hero fills the screen; index.js reads its real height */
  font-size: 12px;
}

html,
body {
  margin: 0;
  background: var(--dark);
}

body {
  color: var(--ink);
  font-family: var(--font);
  line-height: 1.4;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

p,
h1,
h2,
h3,
ul {
  margin: 0;
}

/* Until the fonts and photographs are in: a hairline bar, then the page. */
.js .loading::before,
.js .loading::after {
  content: '';
  position: fixed;
  z-index: 1000;
}

.js .loading::before {
  inset: 0;
  background: var(--dark);
}

.js .loading::after {
  top: 50%;
  left: 50%;
  width: 120px;
  height: 1px;
  margin-left: -60px;
  background: var(--paper);
  transform-origin: 0 50%;
  animation: loading 1.2s ease-in-out infinite alternate;
}

@keyframes loading {
  from {
    transform: scaleX(0.1);
  }
  to {
    transform: scaleX(1);
  }
}

/* Frame ------------------------------------------------------------------ */

/* Codrops' frame, over the hero, in the hero's own colour, and it scrolls
   away with it, so the seams never pass under it. Along the top: the
   title, links and tags and, on the live site, the sponsor on the right
   (#cdawrap, put in the frame by Codrops' sponsor script). Under the title,
   the variations, in a white box so they can't be missed. Nothing sits low
   in the hero, where the seams work: the credits are in the footer. */
.frame {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  grid-template-columns: auto auto 1fr auto;
  grid-template-rows: auto auto 1fr;
  grid-template-areas:
    'title links tags sponsor'
    'demos demos demos .'
    '. . . .';
  gap: 8px 32px;
  align-items: start;
  padding: var(--gutter);
  pointer-events: none;
}

.frame a {
  pointer-events: auto;
}

.frame__title {
  grid-area: title;
  font-size: 1rem;
  font-weight: 400;
}

.frame__links {
  grid-area: links;
}

.frame__tags {
  grid-area: tags;
}

.frame__links,
.frame__tags {
  display: flex;
  gap: 12px;
}

.frame__links a:hover,
.frame__tags a:hover,
.frame__demo:hover {
  opacity: 0.6;
}

.frame__tags {
  opacity: 0.75;
}

/* The variations, numbered, in a white box, the current one filled in. */
.frame__demos {
  grid-area: demos;
  justify-self: start;
  display: grid;
  grid-template-columns: auto repeat(11, auto);
  gap: 2px 10px;
  align-items: center;
  margin-top: 12px;
  padding: 10px 14px;
  border-radius: 10px;
  background: var(--paper);
  color: var(--ink);
}

.frame__demos-label {
  opacity: 0.75;
}

.frame__demo {
  font-variant-numeric: tabular-nums;
}

.frame__demo--current {
  margin: 0 -4px;
  padding: 0 4px;
  border-radius: 3px;
  background: var(--ink);
  color: var(--paper);
}

.frame #cdawrap {
  grid-area: sponsor;
  justify-self: end;
  max-width: 300px;
  text-align: right;
}

/* The studio page ------------------------------------------------------------- */

/* The hero: a photograph in daylight across the whole screen, each page's
   chosen for its seam, and the studio's name on it in white, in the middle
   of the screen. Below the name it's kept clear: that's where the seams
   work. Dark until the photograph is in. */
.hero {
  position: relative;
  height: var(--hero);
  overflow: hidden;
  background: var(--dark);
  color: var(--paper);
}

/* The photograph is drawn as it is (shaders draw it the same, glsl.js,
   photo()). Its box can reach below the hero by --bleed, cropped by it, so
   a seam can show the rest of the picture under the page (Ink). */
.hero__img {
  position: absolute;
  inset: 0 0 auto;
  width: 100%;
  height: calc(100% + var(--bleed, 0px));
  object-fit: cover;
}

/* A veil over the photograph so the white type reads: darkest at the top,
   behind the frame and the name, lighter towards the bottom, where the
   page comes in. index.js reads the same numbers for the seams, which
   draw the photograph under the same veil. */
.hero {
  --veil-top: 0.5;
  --veil-mid: 0.38;
  --veil-stop: 0.62; /* where --veil-mid is, 0 to 1 down the hero */
  --veil-bottom: 0.12;
}

.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    rgb(0 0 0 / var(--veil-top)),
    rgb(0 0 0 / var(--veil-mid)) calc(var(--veil-stop) * 100%),
    rgb(0 0 0 / var(--veil-bottom))
  );
}

.hero__content {
  position: absolute;
  z-index: 1;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  grid-template-rows: 1fr auto 1fr;
  column-gap: var(--gutter);
  padding: 120px var(--gutter); /* the same above and below, so the name is in the middle */
}

.hero__title {
  grid-column: 1 / -1;
  grid-row: 2;
  align-self: last baseline;
  font-size: clamp(56px, 14vw, 220px);
  font-weight: 500;
  line-height: 0.8;
  letter-spacing: -0.07em;
}

/* A Japanese character after the name (Mend's 金, gold): set in a typeface
   that has it, untracked, and sized and raised so its ink is as tall as the
   name's capitals and sits on their baseline (a Japanese character fills a
   square that reaches below the baseline). */
.hero__title [lang='ja'] {
  font-family: 'Zen Kaku Gothic New', sans-serif;
  font-size: 0.85em;
  letter-spacing: 0;
  vertical-align: 0.036em;
}

/* Beside the name, on its baseline, so nothing sits below it. */
.hero__note {
  grid-column: 7 / -1;
  grid-row: 2;
  align-self: last baseline;
  justify-self: end;
  text-align: right;
  opacity: 0.75;
}

/* A cue to scroll, at the bottom of the hero, in the middle: a word over a
   short line. index.js fades it out over the first few px of scroll,
   before the seam comes up to it. */
.hero__scroll {
  position: absolute;
  z-index: 1;
  left: 50%;
  bottom: var(--gutter);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: var(--paper);
  transform: translateX(-50%);
  pointer-events: none;
}

.hero__scroll::after {
  content: '';
  width: 1px;
  height: 28px;
  background: currentColor;
}

/* The seam: a box straddling the hero's bottom edge, `--above` into the
   hero and `--below` into the page under it. Each seam draws in it on a
   canvas; it never takes the pointer. */
.seam {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--hero) - var(--above, 0px));
  height: calc(var(--above, 0px) + var(--below, 0px));
  z-index: 5;
  pointer-events: none;
}

.seam canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* The page under the hero: white, the studio's introduction and its
   latest work. Its top is left open: the seam plays out there. */
.next {
  position: relative;
  background: var(--paper);
  color: var(--ink);
  padding: 34vh var(--gutter) var(--gutter); /* the footer as close to the bottom as the frame is to the top */
  overflow-x: clip; /* the marquee runs to the screen's edges, not past them */
}

.next__intro {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: baseline;
}

.next__label {
  grid-column: 1 / 3;
  opacity: 0.5;
}

.next__text {
  grid-column: 3 / -1;
  font-size: clamp(20px, 2.2vw, 32px);
  line-height: 1.15;
  letter-spacing: -0.035em;
  word-spacing: 0.12em; /* the words, kept apart in capitals set this tight */
}

/* A letter a seam has drunk from (Roots, whose roots reach the first line):
   its ink drawn off from the top down to --level, px down its box, leaving
   it pale, and paler still as --dry goes from 0 to 1 (45% of its ink left,
   down to 12%). Only while there's something drawn off, so untouched
   letters are plain text. */
.next__char--drunk {
  --pale: color-mix(in srgb, var(--ink) calc(45% - 33% * var(--dry, 0)), var(--paper));
  background: linear-gradient(var(--pale) var(--level), var(--ink) var(--level));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* The latest work: six 4:5 photographs in a tight row, captions under
   them, right-aligned. With motion it's a marquee: index.js adds a second
   set after the first and `.projects--marquee`, which lines them all up
   at the same size, `--across` to the screen. */
.projects {
  --across: 6;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 60px 7px;
  margin: 20vh 0 0;
  padding: 0;
  list-style: none;
}

.projects img {
  display: block;
  width: 100%;
  height: auto; /* the ratio below, not the height="…" in the markup */
  aspect-ratio: 4 / 5;
  object-fit: cover;
  background: #eee;
}

.projects--marquee {
  display: flex;
  gap: 7px;
  width: max-content;
}

.projects--marquee li {
  flex: none;
  width: calc((100vw - 2 * var(--gutter) - (var(--across) - 1) * 7px) / var(--across));
}

.projects p {
  margin-top: 6px;
  text-align: right;
}

.projects span {
  opacity: 0.5;
}

/* The footer: the studio's email, the demo's credits in the middle, the
   section's name. */
.next__foot {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 8px var(--gutter);
  align-items: baseline;
  margin-top: 24vh;
}

.next__foot > :last-child {
  justify-self: end;
}

.next__credits {
  text-align: center;
  opacity: 0.6;
}

.next__credits a {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.next__credits a:hover {
  opacity: 0.6;
}

/* Small screens ------------------------------------------------------------ */

@media (max-width: 760px) {
  :root {
    --gutter: 16px;
  }

  .frame {
    grid-template-columns: 1fr;
    grid-template-rows: repeat(5, auto) 1fr;
    grid-template-areas: 'title' 'demos' 'links' 'tags' 'sponsor' '.';
  }

  .frame__demos {
    margin-top: 4px;
  }

  .frame #cdawrap {
    justify-self: start;
    text-align: left;
  }

  .hero__content {
    padding-block: 180px;
  }

  /* The name fills the width: the note goes under it. */
  .hero__note {
    grid-column: 1 / -1;
    grid-row: 3;
    align-self: start;
    padding-top: 24px;
  }

  /* The credits above the email and the section's name. */
  .next__foot {
    grid-template-columns: 1fr 1fr;
  }

  .next__credits {
    grid-column: 1 / -1;
    grid-row: 1;
    margin-bottom: 16px;
  }

  .next__intro {
    grid-template-columns: 1fr;
    gap: 16px;
  }

  .next__label,
  .next__text {
    grid-column: 1;
  }

  .projects {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    --across: 2.4;
  }
}
