/* ==========================================================================
   Mukthar Amiyan — style.css
   Tokens → base → grid → scenes
   ========================================================================== */

/* ---------- Fonts (self-hosted, Latin subset, OFL — licenses in /fonts) ---------- */

@font-face {
  font-family: "Inter Tight";
  src: url("../fonts/inter-tight-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/jetbrains-mono-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ---------- Tokens ---------- */

:root {
  /* Color */
  --paper: #F5F3EE;
  --ink: #151515;
  --red: #E52320;
  --grey: #888888;       /* lines and decoration only */
  --grey-text: #6B6B6B;  /* small text on paper (4.8:1) */
  --grey-text-on-ink: #9A9A9A; /* small text on ink (6.6:1) */
  --rule: rgba(21, 21, 21, 0.1); /* hairlines */
  --ghost: #E3E0D8;      /* faded type, barely there */

  /* Type */
  --font-display: "Inter Tight", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace;
  --display-size: 17.5vw;
  --display-weight: 600;
  --display-leading: 0.9;
  --display-track: -0.035em;
  --label-size: 12px;
  --dot: calc(var(--display-size) * 0.2); /* the red dot, same size in every scene */

  /* Grid — 4 columns on narrow screens */
  --cols: 4;
  --margin: clamp(16px, 3.2vw, 56px);
  --gutter: clamp(10px, 1.4vw, 24px);

  color-scheme: light;
}

/* Wide screens, and phones held sideways — 12 columns, two-line headline */
@media (min-width: 900px), (min-aspect-ratio: 4/3) {
  :root {
    --cols: 12;
    --display-size: 10.5vw;
  }
}

/* ---------- Base ---------- */

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-display);
  font-kerning: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1,
p {
  margin: 0;
  font: inherit;
}

::selection {
  background: var(--red);
  color: var(--paper);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- Grid ---------- */

.scene {
  position: relative;
}

/* Each scene's composition lives on a stage */
.stage {
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  grid-template-rows: auto 1fr auto;
  column-gap: var(--gutter);
  min-height: 100vh;
  min-height: 100svh;
  padding: var(--margin);
}

/* Motion mode: a tall scene pins its stage while the visitor scrolls
   through it. --length is the scene height in screens. */
.motion .scene--tall {
  height: calc(var(--length, 3) * 100vh);
}

.motion .scene--tall > .stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  min-height: 0;
  overflow: hidden;
}

/* ---------- Small mono labels ---------- */

.label,
.cue,
.index,
.caption,
.timecode {
  font-family: var(--font-mono);
  font-size: var(--label-size);
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--grey-text);
}

/* Name and clock sit on column lines, not just next to each other */
.label {
  grid-column: 1 / -1;
  grid-row: 1;
  /* Same columns as the scene (it spans the full width with the same gap) */
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  column-gap: var(--gutter);
}

.label__name {
  grid-column: 1 / span 2;
  color: var(--ink);
}

.label__clock {
  grid-column: 3 / span 1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap; /* room for "awake, building" */
}

.label__clock:empty {
  display: none;
}

@media (min-width: 900px), (min-aspect-ratio: 4/3) {
  .label__name  { grid-column: 1 / span 3; }
  .label__clock { grid-column: 4 / span 2; }
}

.cue {
  grid-column: -2 / -1;
  grid-row: 1;
  justify-self: end;
}

/* ---------- Scene 1 — Point ---------- */

.headline {
  grid-column: 1 / -1;
  grid-row: 3;
  align-self: end;
  font-family: var(--font-display);
  font-size: var(--display-size);
  font-weight: var(--display-weight);
  line-height: var(--display-leading);
  letter-spacing: var(--display-track);
  /* Pull the first letter's side bearing onto the margin line */
  margin-left: -0.04em;
  /* Sit the baseline-ish bottom on the bottom margin */
  margin-bottom: -0.08em;
}

/* Line breaks: narrow = 3 lines, wide = 2 lines */
.br-wide   { display: none; }
.br-narrow { display: inline; }

@media (min-width: 900px), (min-aspect-ratio: 4/3) {
  .br-wide   { display: inline; }
  .br-narrow { display: none; }
}

/* The full stop is the red dot — the main character of the site.
   An inline-block with no in-flow content puts its bottom edge on the
   baseline, so the circle sits exactly where a period would. */
.dot {
  display: inline-block;
  position: relative;
  width: 0.2em;
  height: 0.2em;
  margin-left: 0.05em;
  margin-bottom: -0.012em; /* optical overshoot: round forms dip below the baseline */
  border-radius: 50%;
  background: var(--red);
}

/* Small structural labels */
.index {
  grid-column: 1 / span 2;
  grid-row: 1;
}

.timecode {
  grid-column: -3 / -1;
  grid-row: 1;
  justify-self: end;
  font-variant-numeric: tabular-nums;
}

/* Motion (JS) — the dot's intro, hover and ripple */
.intro .scene--point .dot {
  transform: scale(0);
}

.is-near {
  cursor: pointer;
}

/* Rings are drawn at full size and scaled up from small, so the
   1px border stays thin instead of growing with the scale */
.ripple {
  --size: 24px;
  --grow: 9;
  position: absolute;
  width: calc(var(--size) * var(--grow));
  height: calc(var(--size) * var(--grow));
  border: 1px solid var(--red);
  border-radius: 50%;
  pointer-events: none;
  animation: ripple 1.2s cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

@keyframes ripple {
  from {
    transform: translate(-50%, -50%) scale(0.11);
    opacity: 1;
  }
  to {
    transform: translate(-50%, -50%) scale(1);
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ripple {
    transform: translate(-50%, -50%) scale(0.3);
    animation-name: ripple-fade;
    animation-duration: 0.8s;
  }
}

@keyframes ripple-fade {
  from { opacity: 1; }
  to   { opacity: 0; }
}

/* ---------- Scene 2 — Line → Plane ---------- */

/* The plane: column lines on the real grid, six equal rows */
.plane {
  position: absolute;
  inset: var(--margin);
}

.plane__edge {
  position: absolute;
}

.plane__edge--right {
  top: 0;
  right: 0;
  bottom: 0;
  border-right: 1px solid var(--rule);
  transform-origin: top;
}

.plane__edge--bottom {
  left: 0;
  right: 0;
  bottom: 0;
  border-bottom: 1px solid var(--rule);
  transform-origin: left;
}

.plane__cols,
.plane__rows {
  position: absolute;
  inset: 0;
  display: grid;
}

.plane__cols {
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  column-gap: var(--gutter);
}

.plane__rows {
  grid-template-rows: repeat(6, 1fr);
}

.plane__cols span { border-left: 1px solid var(--rule); transform-origin: top; }
.plane__rows span { border-top: 1px solid var(--rule); transform-origin: left; }

.plane__cols span:nth-child(n + 5) { display: none; }

/* The dot, stretched into a line along the second row line */
.plane__line {
  --span: 3;
  position: absolute;
  top: calc(100% / 6 * 2);
  left: 0;
  width: calc((100% + var(--gutter)) / var(--cols) * var(--span) - var(--gutter));
  height: 2px;
  margin-top: -1px;
  background: var(--red);
  transform-origin: left;
}

/* Sits on the line's left end; in motion it walks to the right end */
.plane__dot {
  position: absolute;
  top: calc(100% / 6 * 2);
  left: 0;
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background: var(--red);
  transform: translate(-50%, -50%);
}

@media (min-width: 900px), (min-aspect-ratio: 4/3) {
  .plane__cols span:nth-child(n + 5) { display: block; }
  .plane__line { --span: 8; }
}

/* Words placed on the grid like a staircase */
.stair {
  position: relative; /* above the plane */
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  column-gap: var(--gutter);
}

.stair > span { white-space: nowrap; }

/* Words need a box to move in */
.motion .stair .word {
  display: inline-block;
}
.stair__1 { grid-column: 1 / -1; }
.stair__2 { grid-column: 2 / -1; }
.stair__3 { grid-column: 2 / -1; }

@media (min-width: 900px), (min-aspect-ratio: 4/3) {
  .stair__2 { grid-column: 4 / -1; }
  .stair__3 { grid-column: 7 / -1; }
}

/* ---------- Scene 3 — Volume ---------- */

.sphere {
  grid-column: 1 / -1;
  grid-row: 2;
  align-self: center;
  justify-self: center;
  width: min(100%, 64svh);
  margin: 0;
}

.sphere svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

/* Drag sideways to spin; vertical swipes still scroll the page */
.js .sphere svg {
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}

.is-dragging .sphere svg {
  cursor: grabbing;
}

.sphere path,
.sphere circle,
.sphere ellipse,
.sphere line {
  fill: none;
  vector-effect: non-scaling-stroke;
}

.sphere__back {
  stroke: var(--grey);
  stroke-width: 1;
  stroke-dasharray: 2 4;
  opacity: 0.6;
}

.sphere__outline,
.sphere__front {
  stroke: var(--ink);
  stroke-width: 1.25;
}

.sphere__axis {
  stroke: var(--red);
  stroke-width: 1.25;
}

.sphere__axis--inside {
  stroke-dasharray: 2 4;
}

.sphere .sphere__dot {
  fill: var(--red);
}

@media (min-width: 900px), (min-aspect-ratio: 4/3) {
  .sphere {
    grid-column: 5 / span 6;
    width: min(100%, 72svh);
  }
}

.caption {
  grid-column: 1 / -1;
  grid-row: 3;
  display: flex;
  flex-direction: column;
  font-variant-numeric: tabular-nums;
}

/* ---------- Scene 4 — Light ---------- */

.scene--light {
  background: var(--ink);
  color: var(--paper);
}

.scene--light .index {
  color: var(--grey-text-on-ink);
}

.see {
  /* Lens centre and radius, in em of the big word so the lens lands on
     the same part of the "S" at any screen size. JS moves the centre and
     sets the motion-blur values while it travels. */
  --lx: 0.32em;
  --ly: 0.385em;
  --lr: 0.17em;
  --zoom: 1.7;
  --ang: 0deg;      /* direction of travel */
  --sx: 1;          /* stretch along it */
  --mb: 0px;        /* blur while moving */

  position: relative;
  grid-column: 1 / -1;
  grid-row: 2;
  align-self: center;
  font-size: min(50vw, 100vh);
  font-weight: var(--display-weight);
  line-height: 0.74;
  letter-spacing: -0.04em;
}

.see__word {
  display: block;
  margin: 0 0 0 -0.02em;
  white-space: nowrap;
}

/* The lens is a small round window that slides over the word. Inside it,
   a magnified copy slides the opposite way so the two line up. Both move
   with transforms only, so moving the lens never repaints the word.
   While moving, it stretches along its path and blurs a little. */
.see__lens {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(var(--lr) * 2);
  height: calc(var(--lr) * 2);
  overflow: hidden;
  border-radius: 50%;
  /* Safari ignores border-radius clipping when the content inside is
     blurred or GPU-moved, and shows a square. clip-path always clips. */
  -webkit-clip-path: circle(50% at 50% 50%);
  clip-path: circle(50% at 50% 50%);
  background: var(--ink);
  transform:
    translate(calc(var(--lx) - var(--lr)), calc(var(--ly) - var(--lr)))
    rotate(var(--ang)) scaleX(var(--sx)) rotate(calc(var(--ang) * -1));
  will-change: transform;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
}

.see__lens-inner {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  transform:
    translate(calc(var(--lr) - var(--lx) * var(--zoom)), calc(var(--lr) - var(--ly) * var(--zoom)))
    scale(var(--zoom));
  filter: blur(var(--mb));
  will-change: transform;
}

/* Rainbow fringe: spectrum bands stacked behind the letter, warm colours
   spilling to the left, cool to the right. Inner bands are listed first so
   they sit on top and each outer band shows only as a thin edge. */
.see__lens-inner .see__word {
  text-shadow:
    -0.005em 0 0.002em rgba(255, 224, 70, 0.85),
    -0.01em 0 0.002em rgba(255, 150, 40, 0.85),
    -0.015em 0 0.002em rgba(255, 59, 47, 0.9),
    0.005em 0 0.002em rgba(100, 255, 150, 0.75),
    0.01em 0 0.002em rgba(60, 205, 255, 0.8),
    0.015em 0 0.002em rgba(80, 110, 255, 0.85),
    0.02em 0 0.002em rgba(170, 80, 255, 0.7);
}

/* Slight film grain, fixed to the glass */
.see__grain {
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' 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 .6 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: 0.07;
  mix-blend-mode: screen;
}

/* Rim of the lens */
.see__lens::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid rgba(245, 243, 238, 0.5);
  border-radius: 50%;
}

/* The dot, now the point of focus */
.see__lens::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 1;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  border-radius: 50%;
  background: var(--red);
}

/* Motion: the stage is ink, hidden under a paper cover. The red dot grows
   to flood the screen, the cover drops away underneath, and the red fades
   to reveal the ink. */
.flood,
.cover {
  display: none;
}

.motion .scene--light {
  background: var(--paper);
}

.motion .scene--light .stage {
  background: var(--ink);
}

.motion .scene--light .cover {
  display: block;
  position: absolute;
  inset: 0;
  background: var(--paper);
}

.motion .scene--light .flood {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: var(--red);
  transform: translate(-50%, -50%) scale(0);
  pointer-events: none;
  /* No will-change here: it would freeze the circle at its tiny starting
     resolution and blur it as it grows */
}

/* ---------- Scene 5 — Time ---------- */

.time__line {
  grid-row: 2;
  align-self: start;
  margin-top: 8vh;
}

/* A chronophotograph of one spring: each dot is a frame */
.frames {
  position: relative;
  grid-column: 1 / -1;
  grid-row: 3;
  height: var(--dot);
  margin-bottom: 4vh;
}

.frames::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  border-top: 1px solid var(--rule);
}

.frames__dot {
  position: absolute;
  top: 0;
  left: calc((100% - var(--dot)) * var(--x));
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background: var(--red);
  opacity: var(--o);
}

/* Where the spring comes to rest */
.frames__target {
  position: absolute;
  top: calc(var(--dot) * -0.75);
  bottom: calc(var(--dot) * -0.75);
  left: calc((100% - var(--dot)) * 0.84 + var(--dot) / 2);
  border-left: 1px solid var(--red);
}

/* Motion: scrolling moves one live dot along the spring; frames appear
   behind it and a thin red trail marks how far it has travelled */
.frames__live,
.frames__trail {
  display: none;
}

.motion .frames__live {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background: var(--red);
  will-change: transform;
}

.motion .frames__trail {
  display: block;
  position: absolute;
  top: 50%;
  left: calc(var(--dot) / 2);
  right: calc(var(--dot) / 2);
  height: 1px;
  margin-top: -0.5px;
  background: var(--red);
  transform: scaleX(0);
  transform-origin: left;
}

.motion .frames__dot {
  transition: opacity 0.3s;
}

/* ---------- Scene 6 — Return ---------- */

.scene--return .label__name {
  grid-column: 1 / -1;
}

.social {
  grid-column: -3 / -1;
  grid-row: 1;
  justify-self: end;
  display: flex;
  gap: 4px;
  /* Big tap targets, small icons: pull the padding back so icons align to the margin */
  margin: -13px -13px 0 0;
}

.social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  color: var(--grey-text);
  transition: color 0.2s, transform 0.2s;
}

.social a:hover,
.social a:focus-visible {
  color: var(--red);
  transform: translateY(-2px);
}

.social a:focus-visible {
  outline: 1px solid var(--red);
  outline-offset: -6px;
}

.headline--ghost {
  color: var(--ghost);
  user-select: none;
}

/* Motion: the line starts in full ink and JS fades each word to ghost */
.motion .headline--ghost {
  color: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  .social a { transition: none; }
  .social a:hover,
  .social a:focus-visible { transform: none; }
}

/* ---------- Easter eggs ---------- */

/* Margin notes: revealed when a big line is selected */
.headline,
.see {
  position: relative;
}

.note {
  position: absolute;
  bottom: 100%;
  left: 0;
  margin-bottom: 14px;
  font-family: var(--font-mono);
  font-size: var(--label-size);
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.02em;
  color: var(--red);
  white-space: nowrap;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.3s, transform 0.3s;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
}

.is-noted > .note {
  opacity: 1;
  transform: none;
}

/* Falling dots */
.rain {
  position: fixed;
  inset: 0;
  z-index: 20;
  pointer-events: none;
  transition: opacity 0.4s;
}

.rain.is-gone {
  opacity: 0;
}

.rain__dot {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 50%;
  background: var(--red);
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  .note { transition: none; }
}
