/* Home: the split alphabet, and its opening curtain. */

/* The dark half runs into the scrollbar gutter that site.css reserves, so it
   still reaches the window edge. */
body {
  background-color: #30312e;
}

.hero {
  --letter-size: clamp(1.625rem, 8.205vw, 2rem);
  --letter-line: calc(var(--letter-size) * 1.1);
  position: relative;
  display: grid;
  align-items: center;
  min-height: max(100svh, calc(var(--letter-line) * 10));
  background: linear-gradient(to right, var(--paper) 50%, #30312e 50%);
  font-family: var(--font-sans);
  font-size: var(--letter-size);
  font-weight: 700;
  line-height: 1.1;
}

.alphabet {
  padding-block: var(--letter-line);
}

.row {
  --tracking: 0em;
  --duration: 280ms;
  --left-shift: calc(
    (var(--prefix-letters) + var(--half-gaps)) * var(--tracking)
  );
  display: grid;
  grid-template-columns: 1fr 1fr;
  height: var(--letter-line);
  white-space: nowrap;
}

.upper {
  color: var(--rule);
  text-align: right;
}

.upper-text,
.prefix-text,
.suffix {
  display: inline-block;
}

.upper-text,
.prefix-text {
  transform: translateX(calc(-1 * var(--left-shift)));
}

.accent {
  color: var(--accent);
}

.lower {
  color: #666;
}

.prefix,
.link {
  position: relative;
  display: inline-block;
}

.measure {
  visibility: hidden;
}

.light-prefix,
.dark-prefix {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.light-prefix {
  color: var(--rule);
  clip-path: inset(-1em 100% -1em -100vw);
}

.dark-prefix {
  clip-path: inset(-1em -100vw -1em 0);
}

.link {
  color: var(--paper);
  text-decoration: none;
}

.word {
  position: absolute;
  top: 0;
  left: 50%;
  width: max-content;
  /* CSS tracking includes a trailing space: exclude it from visual centring. */
  transform: translateX(calc(-50% + var(--tracking) / 2));
}

.suffix {
  transform: translateX(calc((var(--half-gaps) + 1) * var(--tracking)));
  pointer-events: none;
}

.upper-text,
.prefix-text,
.word,
.suffix {
  letter-spacing: var(--tracking);
  transition:
    letter-spacing var(--duration) cubic-bezier(0.22, 1, 0.36, 1),
    transform var(--duration) cubic-bezier(0.22, 1, 0.36, 1);
}

.link:focus-visible {
  outline-color: var(--paper);
  outline-offset: 2px;
}

/*
 * The opening, after the first ericzheng.nz (Paper: "Home intro"). The cover
 * is the plain alphabet in grey; a dark curtain falls through it, top down.
 * After a beat, the curtain's left half lifts, bottom up, to show the name.
 * Each moving edge is a 2px red line.
 */
.cover,
.curtain {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  align-items: center;
  /* The moving edges must not make Home scroll. */
  overflow: hidden;
  pointer-events: none;
  user-select: none;
}

.cover::before,
.curtain::before {
  content: "";
  position: absolute;
  inset: 0;
}

.cover {
  background: var(--paper);
  clip-path: inset(0);
  animation: fall 600ms cubic-bezier(0.65, 0, 0.35, 1) 150ms forwards;
}

.cover .row * {
  color: #666;
}

.cover::before {
  background: linear-gradient(var(--accent) 2px, transparent 0);
  translate: 0 -2px;
  animation: fall-edge 600ms cubic-bezier(0.65, 0, 0.35, 1) 150ms forwards;
}

/* 1px past the split, as in the original, so no seam shows. */
.curtain {
  background: #30312e;
  clip-path: inset(0 calc(50% - 1px) 0 0);
  animation: lift 600ms cubic-bezier(0.22, 1, 0.36, 1) 900ms forwards;
}

.curtain .row * {
  color: #666;
}

.curtain::before {
  background: linear-gradient(to top, var(--accent) 2px, transparent 0);
  translate: 0 2px;
  animation: lift-edge 600ms cubic-bezier(0.22, 1, 0.36, 1) 900ms forwards;
}

/*
 * Rows don't spread on hover or focus until the opening has finished. Then a
 * resting pointer eases the row open (280ms) instead of snapping: with no
 * closing keyframe, the hold ends on whatever hover asks for.
 */
@property --tracking {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}

.row {
  animation: hold-still 1780ms;
}

@keyframes hold-still {
  0%,
  84.27% {
    --tracking: 0em;
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
  }
  /* The release is the ease, so no transition runs on top of it. */
  0%,
  100% {
    --duration: 0ms;
  }
}

@keyframes fall {
  from {
    clip-path: inset(0);
  }
  to {
    clip-path: inset(100% 0 0 0);
  }
}

@keyframes fall-edge {
  from {
    translate: 0 0;
  }
  to {
    translate: 0 100%;
  }
}

@keyframes lift {
  to {
    clip-path: inset(0 calc(50% - 1px) 100% 0);
  }
}

@keyframes lift-edge {
  from {
    translate: 0 0;
  }
  to {
    translate: 0 -100%;
  }
}

/* Compact/touch layouts stay at rest; desktop keyboards share the hover cue. */
@media (min-width: 600px) and (hover: hover) and (pointer: fine) {
  .row:has(.link:hover, .link:focus-visible) {
    --tracking: 0.15em;
  }
}

@media (prefers-reduced-motion: reduce) {
  .upper-text,
  .prefix-text,
  .word,
  .suffix {
    transition: none;
  }
}

@media (prefers-reduced-motion: reduce), print, (forced-colors: active) {
  .cover,
  .curtain {
    display: none;
  }
  .row {
    animation: none;
  }
}

@media (min-width: 600px) {
  .hero {
    --letter-size: clamp(2rem, 5.556vw, 5rem);
  }
}
