/* spider.fun
   One black observation chart. The furniture of the chart never changes: the wordmark hangs at
   the top, five silk tags hang under it, registration marks sit in the corners. What changes is
   the specimen in the middle.
   Four inks on black, all of them read off the reference plate in art/ref/plate.jpg. */

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

:root {
  --paper: #000000;
  --silk: #e6ddf8;
  --silk-dim: #9a90c4;
  --amber: #f7f58e;
  --rose: #f5bcf0;
  --ash: #55507a;
  --ash-deep: #221f38;

  /* Departure Mono is drawn on an 11 px grid: 22 / 33 / 44 / 66 stay crisp. */
  --t-body: 22px;
  --t-lead: 33px;
  --t-title: 44px;
  --t-display: 66px;

  --gap: 72px;
  --rule: 1px;
  --tap: 56px;

  color-scheme: dark;
}

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

html {
  overflow-x: clip;
  background: var(--paper);
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--paper);
  color: var(--silk);
  font-family: "Departure Mono", ui-monospace, "Cascadia Mono", Menlo, monospace;
  font-size: var(--t-body);
  line-height: 1.5;
  font-synthesis: none;
  -webkit-font-smoothing: none;
  position: relative;
  z-index: 1;
}

img,
canvas {
  image-rendering: pixelated;
  max-width: 100%;
}

img {
  height: auto;
}

a {
  color: var(--amber);
  text-decoration: none;
}

a:hover {
  color: var(--silk);
}

:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 3px;
}

[hidden] {
  display: none !important;
}

/* ---- the living ground ------------------------------------------------- */
/* More of the world, blurred, moving on its own clock. Never with the pointer. */

.ground {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background: var(--paper);
}

/* the world sinks away from the middle, so the specimen is never in competition with it */
.ground::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 50% 46%, rgba(0, 0, 0, 0.92) 0%, rgba(0, 0, 0, 0.66) 38%, rgba(0, 0, 0, 0.42) 70%, rgba(0, 0, 0, 0.7) 100%);
}

.ground video,
.ground img {
  position: absolute;
  inset: -6%;
  width: 112%;
  height: 112%;
  object-fit: cover;
  opacity: 0.26;
  filter: blur(9px) saturate(0.8);
  animation: drift 96s ease-in-out infinite alternate;
}

@keyframes drift {
  from {
    transform: translate3d(-1.2%, -0.8%, 0) scale(1.03);
  }
  to {
    transform: translate3d(1.2%, 0.8%, 0) scale(1.07);
  }
}

/* ---- the chart --------------------------------------------------------- */

.chart {
  position: relative;
  z-index: 1;
  max-width: 1680px;
  margin: 0 auto;
  padding: 40px 32px 96px;
}

/* Registration marks in the four corners of the sheet, like the reference plate. */
/* The two brackets that hold the sheet, with a registration corner top and bottom, straight off
   the reference plate. They are rules, not panels: nothing is drawn inside them. */
.chart::before,
.chart::after {
  content: "";
  position: absolute;
  top: 18px;
  bottom: 40px;
  width: 26px;
  pointer-events: none;
  border-top: var(--rule) solid var(--ash);
  border-bottom: var(--rule) solid var(--ash);
}

.chart::before {
  left: 14px;
  border-left: var(--rule) solid var(--ash);
}

.chart::after {
  right: 14px;
  border-right: var(--rule) solid var(--ash);
}

/* ---- the hanging lockup and the nav tags -------------------------------- */

.hang {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  padding-top: 0;
}

.hang__wordmark {
  display: block;
  width: min(320px, 52vw);
  margin: 0 auto 6px;
}

/* the silk thread the tags hang from */
.tags {
  position: relative;
  width: 100%;
  display: flex;
  justify-content: center;
  gap: clamp(8px, 1.6vw, 26px);
  padding-top: 22px;
  margin-bottom: 44px;
  flex-wrap: wrap;
}

.tags::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: var(--rule);
  background: linear-gradient(
    90deg,
    transparent,
    var(--ash) 8%,
    var(--silk-dim) 50%,
    var(--ash) 92%,
    transparent
  );
}

.tag {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  width: 128px;
  height: 148px;
  padding: 0 10px 22px;
  background: none;
  border: 0;
  color: var(--silk);
  font: inherit;
  cursor: pointer;
  background: url("../img/tag.png") center / 100% 100% no-repeat;
  transform-origin: 50% -26px;
  animation: sway 7s ease-in-out infinite alternate;
  text-align: center;
}

.tag:nth-child(2) {
  animation-duration: 8.5s;
}
.tag:nth-child(3) {
  animation-duration: 6.4s;
}
.tag:nth-child(4) {
  animation-duration: 9.2s;
}
.tag:nth-child(5) {
  animation-duration: 7.7s;
}

/* the short thread from the top rule into the tag's punched hole */
.tag::before {
  content: "";
  position: absolute;
  top: -22px;
  left: 50%;
  width: var(--rule);
  height: 22px;
  background: var(--silk-dim);
}

.tag__label {
  color: var(--ash-deep);
  font-size: var(--t-body);
  letter-spacing: 0.02em;
  mix-blend-mode: normal;
}

.tag[aria-current="page"] .tag__label {
  color: #1a1530;
  text-shadow: 0 0 0 var(--amber);
}

.tag[aria-current="page"] {
  filter: drop-shadow(0 0 6px rgba(247, 245, 142, 0.75));
}

.tag:hover {
  filter: drop-shadow(0 0 7px rgba(230, 221, 248, 0.7));
}

@keyframes sway {
  from {
    transform: rotate(-1.4deg);
  }
  to {
    transform: rotate(1.4deg);
  }
}

/* ---- the stage: margin callouts, the specimen, margin callouts ---------- */

.stage {
  display: grid;
  grid-template-columns: minmax(200px, 290px) minmax(320px, 820px) minmax(200px, 290px);
  gap: clamp(20px, 3vw, 56px);
  align-items: start;
  justify-content: center;
}

.margin {
  display: flex;
  flex-direction: column;
  gap: 30px;
  padding-top: 18px;
}

.margin--left {
  text-align: right;
}

.callout {
  position: relative;
}

.callout__label {
  display: block;
  color: var(--silk-dim);
  font-size: var(--t-body);
  letter-spacing: 0.06em;
}

.callout__value {
  display: block;
  color: var(--amber);
  font-size: var(--t-lead);
  line-height: 1.25;
  word-break: break-word;
}

.callout__value--rose {
  color: var(--rose);
}

.callout__note {
  display: block;
  color: var(--ash);
  font-size: var(--t-body);
}

/* the leader line that ties a margin note to the specimen */
.callout::after {
  content: "";
  position: absolute;
  top: 16px;
  height: var(--rule);
  width: 46px;
  background: var(--ash);
}

.margin--left .callout::after {
  right: -46px;
}

.margin--right .callout::after {
  left: -46px;
}

/* ---- the specimen ------------------------------------------------------ */

.specimen {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 0;
}

.scene {
  position: relative;
  width: min(100%, max(520px, 56vh), 700px);
  aspect-ratio: 1 / 1;
  margin: 0 auto;
}

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

/* The label of a sample specimen sits UNDER it, on the sheet, never across the silk. */
.scene__state {
  margin: 8px 0 0;
  color: var(--silk-dim);
  font-size: var(--t-body);
  text-align: center;
  text-wrap: balance;
}

/* ---- the stabilimentum: the only place the marks live ------------------ */

/* The stabilimentum: the zigzag ribbon an orb weaver writes into the middle of its web. It runs
   along the top and the bottom of the block; the writing sits on the black between them. */
.band {
  width: min(100%, max(520px, 56vh), 700px);
  margin: 12px auto 0;
  padding: 54px 30px 56px;
  background:
    url("../img/band.png") center top / 100% 42px no-repeat,
    url("../img/band.png") center bottom / 100% 42px no-repeat,
    rgba(4, 3, 10, 0.86);
}

.band__head {
  display: flex;
  align-items: baseline;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.band__name {
  color: var(--amber);
  font-size: var(--t-lead);
}

.band__ticker {
  color: var(--silk);
  font-size: var(--t-body);
}

.band__addr {
  display: block;
  width: 100%;
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--silk);
  font-size: var(--t-body);
  line-height: 1.35;
  padding: 12px 0 18px;
  user-select: all;
}

.band__addr--empty {
  color: var(--silk-dim);
  user-select: none;
}

.keys {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}

/* ---- keys (every button on the site is one) ---------------------------- */

.key {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: var(--tap);
  padding: 15px 30px 17px;
  background: none;
  border: 0;
  color: #17132b;
  font: inherit;
  font-size: var(--t-body);
  cursor: pointer;
  border-image: url("../img/key.png") 70 100 fill / 20px 34px / 0 stretch;
  transition: transform 90ms steps(2);
  text-align: center;
}

.key:hover:not([disabled]) {
  filter: drop-shadow(0 0 7px rgba(247, 245, 142, 0.55));
}

.key:active:not([disabled]) {
  transform: translateY(3px);
}

.key[disabled] {
  cursor: default;
  filter: grayscale(0.7) brightness(0.62);
  color: #ffffff;
}

.key--primary {
  color: #17132b;
  filter: drop-shadow(0 0 5px rgba(247, 245, 142, 0.6));
}

.key__mark {
  width: 24px;
  height: 24px;
  flex: none;
  image-rendering: auto;
}

.key__mark--inverse {
  filter: invert(1);
}

/* ---- panels (a generated technical frame, nine sliced) ----------------- */

.panel {
  border-image: url("../img/panel.png") 60 fill / 30px / 0 stretch;
  padding: 44px 40px 40px;
  min-width: 0;
}

.panel__title {
  margin: 0 0 22px;
  overflow-wrap: anywhere;
  min-width: 0;
  font-size: var(--t-lead);
  font-weight: 400;
  color: var(--amber);
  letter-spacing: 0.02em;
}

/* two column plates: the loom and its preview, the lookup and its answer */
.stage--two {
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: 40px;
}

/* the answer panel follows the form instead of leaving a half empty column beside it */
.stage--two > :last-child {
  position: sticky;
  top: 24px;
}

.section--first {
  margin-top: 0;
}

.note--spaced {
  margin-top: 24px;
}

.keys--spaced {
  margin-top: 28px;
}

.band-wrap {
  margin-top: 28px;
}

/* ---- sections --------------------------------------------------------- */

.section {
  margin-top: var(--gap);
}

.section__title {
  margin: 0 0 12px;
  overflow-wrap: anywhere;
  min-width: 0;
  font-size: var(--t-title);
  font-weight: 400;
  color: var(--silk);
  letter-spacing: 0.01em;
  line-height: 1.2;
}

.section__lead {
  margin: 0 0 40px;
  max-width: 62ch;
  color: var(--silk-dim);
  font-size: var(--t-body);
}

/* ---- the four step scheme --------------------------------------------- */

.steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  align-items: stretch;
}

.step {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.step__frame {
  border: var(--rule) solid var(--ash);
  padding: 10px;
  background: #050409;
}

.step__frame img {
  display: block;
  width: 100%;
}

.step__n {
  display: block;
  margin-top: 18px;
  color: var(--amber);
  font-size: var(--t-body);
}

.step__text {
  margin: 4px 0 0;
  color: var(--silk);
  font-size: var(--t-body);
}

/* ---- rows of facts ----------------------------------------------------- */

.rows {
  display: grid;
  gap: 0;
}

.row {
  display: grid;
  grid-template-columns: minmax(200px, 320px) 1fr;
  gap: 24px;
  padding: 18px 0;
  border-bottom: var(--rule) solid var(--ash-deep);
  align-items: baseline;
}

.row:last-child {
  border-bottom: 0;
}

.row__k {
  color: var(--silk-dim);
  min-width: 0;
  overflow-wrap: anywhere;
}

.row__v {
  color: var(--silk);
  min-width: 0;
  overflow-wrap: anywhere;
}

.row__v--amber {
  color: var(--amber);
}

.row__v--rose {
  color: var(--rose);
}

/* ---- the forest -------------------------------------------------------- */

.forest {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 28px;
}

.forest__cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 22px 18px 26px;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  cursor: pointer;
  border-image: url("../img/panel.png") 60 fill / 26px / 0 stretch;
}

.forest__cell:hover {
  filter: drop-shadow(0 0 8px rgba(230, 221, 248, 0.5));
}

.forest__cell canvas {
  width: 100%;
  max-width: 200px;
  aspect-ratio: 1 / 1;
  height: auto;
}

.forest__name {
  color: var(--amber);
  font-size: var(--t-body);
}

.forest__sub {
  color: var(--silk-dim);
  font-size: var(--t-body);
  text-align: center;
}

.empty {
  margin-bottom: 44px;
  padding: 56px 40px;
  text-align: center;
  color: var(--silk-dim);
  border-image: url("../img/panel.png") 60 fill / 30px / 0 stretch;
}

/* ---- forms (the loom) -------------------------------------------------- */

.form {
  display: grid;
  gap: 28px;
}

.field {
  display: grid;
  gap: 10px;
  min-width: 0;
}

.field__label {
  color: var(--silk-dim);
  font-size: var(--t-body);
}

.field input[type="text"],
.field input[type="number"] {
  width: 100%;
  min-width: 0;
  min-height: var(--tap);
  padding: 12px 18px;
  background: #060510;
  border: var(--rule) solid var(--ash);
  color: var(--silk);
  font: inherit;
  font-size: var(--t-body);
  border-radius: 0;
}

.field input:focus {
  border-color: var(--amber);
  outline: none;
}

.field input::placeholder {
  color: var(--ash);
}

.field__note {
  color: var(--ash);
  font-size: var(--t-body);
}

.field__note--bad {
  color: var(--rose);
}

.field__note--ok {
  color: var(--amber);
}

.threads-form {
  display: grid;
  gap: 18px;
}

.thread-row {
  display: grid;
  grid-template-columns: 1fr 190px;
  gap: 16px;
  align-items: end;
}

input[type="range"] {
  width: 100%;
  accent-color: var(--amber);
  min-height: 44px;
}

/* ---- toast ------------------------------------------------------------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  z-index: 40;
  padding: 16px 26px;
  background: #07060f;
  border: var(--rule) solid var(--amber);
  color: var(--amber);
  font-size: var(--t-body);
  max-width: 90vw;
  text-align: center;
}

.toast--bad {
  border-color: var(--rose);
  color: var(--rose);
}

/* ---- small print (never below 22 px on a pixel face) ------------------- */

.note {
  color: var(--silk-dim);
  font-size: var(--t-body);
  max-width: 68ch;
}

.skip {
  position: absolute;
  left: -9999px;
}

.skip:focus {
  left: 16px;
  top: 16px;
  z-index: 60;
  padding: 14px 20px;
  background: var(--paper);
  border: var(--rule) solid var(--amber);
}

/* ---- widths ------------------------------------------------------------ */

@media (max-width: 1366px) {
  :root {
    --gap: 60px;
  }
  .stage {
    grid-template-columns: minmax(180px, 250px) minmax(320px, 700px) minmax(180px, 250px);
    gap: 24px;
  }
  .callout::after {
    width: 26px;
  }
  .margin--left .callout::after {
    right: -26px;
  }
  .margin--right .callout::after {
    left: -26px;
  }
}

@media (max-width: 1100px) {
  .stage {
    grid-template-columns: 1fr;
  }
  .margin {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 28px;
    padding-top: 0;
    text-align: left;
  }
  .margin--left {
    text-align: left;
  }
  .margin--left .callout::after,
  .margin--right .callout::after {
    display: none;
  }
  .specimen {
    order: -1;
  }
  .steps {
    grid-template-columns: repeat(2, 1fr);
  }
  .stage--two {
    grid-template-columns: 1fr;
  }
  .stage--two > :last-child {
    position: static;
  }
}

@media (max-width: 640px) {
  :root {
    --gap: 48px;
    --t-title: 33px;
  }
  .chart {
    padding: 22px 16px 64px;
  }
  .hang__wordmark {
    width: 70vw;
  }
  .tags {
    gap: 10px;
  }
  /* five tags in two rows, three and two, small enough to leave the web on the first screen */
  .tag {
    width: calc(33.333% - 8px);
    height: 104px;
    padding: 0 6px 14px;
  }
  .chart::before,
  .chart::after {
    display: none;
  }
  .margin {
    grid-template-columns: 1fr;
  }
  .stage--two {
    grid-template-columns: 1fr;
    gap: 28px;
  }
  .stage--two > :last-child {
    position: static;
  }
  .panel {
    padding: 40px 22px 32px;
    border-image-width: 22px;
  }
  .steps {
    grid-template-columns: 1fr;
  }
  .thread-row {
    grid-template-columns: 1fr;
    gap: 12px;
  }
  .row {
    grid-template-columns: 1fr;
    gap: 6px;
  }
  .band {
    padding: 26px 22px 30px;
  }
  .key {
    width: 100%;
  }
  .keys {
    gap: 12px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ground video,
  .ground img,
  .tag {
    animation: none !important;
  }
  .key {
    transition: none;
  }
}

@media (max-width: 370px) {
  /* two tags a row: at this width three of them leave no air around the longest word */
  .tag {
    width: calc(50% - 6px);
  }
}
