/* Three layers, stacked: the CODETUG lettering (two <pre> blocks on the back
   stage), the rope (a canvas over the whole hero that effects.js fills with
   characters a frame at a time), and the play key (on the front stage). Both
   stages share one 1672 by 560 drawing, and --u is one unit of it. The rope
   only ever draws over the lettering; it never cuts into it. */
.hero {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  min-height: 440px;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  color: #f2eee0;
  background: radial-gradient(ellipse at 50% 48%, #06050b 0%, #05050a 64%, #040408 100%);
}
.hero-art { position: relative; min-height: 0; container-type: size; }
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: .012;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.89' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Cpath fill='%23fff' filter='url(%23n)' d='M0 0h180v180H0z'/%3E%3C/svg%3E");
}
.hero-stage {
  position: absolute;
  top: 56%;
  left: 50%;
  width: min(100%, 242cqh);
  aspect-ratio: 1672 / 560;
  transform: translate(-50%, -50%);
  container-type: inline-size;
}
.hero-back { z-index: 0; }
.hero-front { z-index: 3; pointer-events: none; }
.hero-code, .hero-tug { --u: calc(100cqw / 1672); }
/* A layer sets its type unscaled and is then squeezed as a whole, which is what
   makes the figures tall and narrow. The letter spacing tops every glyph up to
   one full column, whichever monospace font the system has. The art was drawn
   at the default glyph weight, so the page's thinner smoothing is switched off. */
.hero-ascii {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  margin: 0;
  font: 700 calc(var(--size) * var(--u)) / calc(var(--row) * var(--u)) "Courier New", Courier, monospace;
  letter-spacing: calc(var(--col) * var(--u) - 1ch);
  font-variant-ligatures: none;
  -webkit-font-smoothing: auto;
  -moz-osx-font-smoothing: auto;
  -webkit-text-size-adjust: none;
  text-size-adjust: none;
  transform-origin: 0 0;
  transform: scale(var(--sx), var(--sy));
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
}
.hero-code, .hero-tug {
  --size: 12.1; --col: 8.3647; --row: 9.5611; --sx: .85; --sy: 1.23; --y: -.5;
  color: #d6d8d9;
  background-size: 260% 260%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: hero-glimmer 7.5s ease-in-out infinite;
}
.hero-code {
  --x: 50.235;
  background-image: linear-gradient(
    112deg,
    #cfd2d4 0%,
    #d6d8d9 36%,
    #a8d0ff 44%,
    #ffffff 49%,
    #e6f1ff 53%,
    #d6d8d9 61%,
    #cfd2d4 100%
  );
  filter: drop-shadow(0 0 calc(6px * var(--blue-glint, 0.15)) rgba(45, 130, 255, 0.35));
}
.hero-tug {
  --x: 946.095;
  background-image: linear-gradient(
    112deg,
    #cfd2d4 0%,
    #d6d8d9 36%,
    #ffb3ad 44%,
    #ffffff 49%,
    #ffe3e0 53%,
    #d6d8d9 61%,
    #cfd2d4 100%
  );
  animation-delay: -3.2s;
  filter: drop-shadow(0 0 calc(6px * var(--red-glint, 0.15)) rgba(255, 58, 52, 0.35));
}
@keyframes hero-glimmer {
  0%, 100% { background-position: 135% 50%; }
  48%, 56% { background-position: -25% 50%; }
}
/* The rope and clawing hands layer. Placed above the key stage with
   pointer-events: none so the ASCII fingers claw directly onto the left and
   right edges of the button without blocking clicks or hover. */
.hero-rope {
  position: absolute;
  inset: 0;
  z-index: 4;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.hero-play {
  position: absolute;
  left: 50%;
  top: 90%;
  width: 24.76%;
  aspect-ratio: 414 / 128;
  transform: translate(-50%, -50%);
  translate: var(--pull-x, 0) var(--pull-y, 0);
  pointer-events: auto;
  border: 0;
  padding: 0;
  background: transparent;
  color: #08080b;
  text-decoration: none;
  text-transform: uppercase;
  font: 700 2.87cqw/1 Menlo, Consolas, monospace;
  letter-spacing: -.02em;
  -webkit-tap-highlight-color: transparent;
  filter:
    drop-shadow(-10px 4px 18px rgba(16, 118, 255, 0.24))
    drop-shadow(10px 4px 18px rgba(255, 48, 44, 0.24))
    drop-shadow(0 10px 22px rgba(0, 0, 0, 0.8));
  transition: filter .26s cubic-bezier(.16, 1, .3, 1);
}
.hero-key { display: block; width: 100%; height: 100%; overflow: visible; }
.hero-key-top, .hero-play-label {
  transition: transform .22s cubic-bezier(.16, 1, .3, 1), color .18s ease, text-shadow .18s ease;
}
.hero-key-badge, .hero-key-arrow, .hero-key-hatch {
  transition: fill .2s ease, transform .22s cubic-bezier(.16, 1, .3, 1), filter .22s ease, opacity .2s ease;
  transform-box: fill-box;
  transform-origin: center;
}
.hero-key-sheen {
  transform: skewX(-22deg) translateX(0);
  opacity: 0;
  transition: transform .6s cubic-bezier(.16, 1, .3, 1), opacity .28s ease;
}
.hero-play-label {
  position: absolute;
  inset: 0 11% 17% 29%;
  display: grid;
  place-content: center;
  white-space: nowrap;
}
.hero-play:focus-visible { outline: 2px dashed #f4efe2; outline-offset: 6px; }
.hero-play:active {
  filter:
    drop-shadow(-6px 2px 12px rgba(16, 118, 255, 0.36))
    drop-shadow(6px 2px 12px rgba(255, 48, 44, 0.36))
    drop-shadow(0 4px 10px rgba(0, 0, 0, 0.86));
}
.hero-play:active .hero-key-top { transform: translateY(5px); transition-duration: .06s; }
.hero-play:active .hero-play-label { transform: translateY(.12em); transition-duration: .06s; }
@media (hover: hover) {
  .hero-play:hover:not(:active) {
    filter:
      drop-shadow(-14px 5px 26px rgba(24, 132, 255, 0.5))
      drop-shadow(14px 5px 26px rgba(255, 52, 48, 0.5))
      drop-shadow(0 14px 28px rgba(0, 0, 0, 0.88));
  }
  .hero-play:hover:not(:active) .hero-key-top { transform: translateY(-2.5px); }
  .hero-play:hover:not(:active) .hero-play-label {
    transform: translateY(-.06em);
    color: #000;
    text-shadow: -1px 0 0 rgba(18, 120, 255, 0.22), 1px 0 0 rgba(255, 48, 44, 0.22);
  }
  .hero-play:hover:not(:active) .hero-key-arrow { transform: translateX(2.5px); fill: #fff; }
  .hero-play:hover:not(:active) .hero-key-sheen {
    transform: skewX(-22deg) translateX(620px);
    opacity: .85;
  }
}
/* On portrait screens CODE stands over TUG, each centred and enlarged, and the
   rope runs between them. */
@media (max-aspect-ratio: 4/5) {
  .hero-stage {
    width: min(100%, 72cqh);
    aspect-ratio: 1 / 1.29;
  }
  .hero-code, .hero-tug { --u: calc(92.4cqw / 895); }
  .hero-code { left: calc(50% + (var(--x) - 496.5) * var(--u)); }
  .hero-tug {
    left: calc(50% + (var(--x) - 1285.3) * var(--u));
    top: calc(100% + (var(--y) - 560) * var(--u));
  }
  .hero-play {
    left: 50%;
    top: 50.7%;
    width: 57%;
    font-size: 6.6cqw;
  }
}
@media (min-aspect-ratio: 4/5) and (max-aspect-ratio: 5/4) {
  .hero-play { width: 31%; font-size: 3.59cqw; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-code, .hero-tug, .hero-key-sheen { animation: none; }
  .hero-key-top, .hero-play-label, .hero-key-arrow { transition: none; }
}

/* The landing's controls are keys from styles.css; this file only places them.
   Two sit in the top corners. The deck under the Play key holds the mode, the
   turn clock, and one line that says what Play will do. Choosing Private opens
   its key into a slot for a room code, and the Play key hosts or joins. */
.hero-nav {
  position: relative; z-index: 5; display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: max(clamp(16px, 3.7svh, 36px), env(safe-area-inset-top)) max(3.3vw, 16px) 0;
}
.nav-cluster { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.account-key { min-width: 0; max-width: min(48vw, 250px); }
.account-key .player-avatar { margin: 0 0 0 -7px; }
.account-key .i-chevron { width: 14px; height: 14px; margin-left: -2px; }

.hero-controls {
  position: relative; z-index: 5; display: grid;
  grid-template-columns: minmax(0, 500px) 222px; align-items: start; justify-content: center; gap: 8px 36px;
  width: min(100% - 40px, 760px); margin: 0 auto; padding: 5px 0 max(clamp(18px, 5svh, 50px), env(safe-area-inset-bottom));
}
.mode-group, .hero-time { min-width: 0; }
.hero-time { margin: 0; padding: 0; border: 0; }
.deck-label { display: flex; align-items: center; gap: 6px; margin: 0 0 8px; padding: 0; color: var(--text-3); font: 500 13px/18px var(--font); }
.deck-label .icon { width: 14px; height: 14px; }
.deck-label .i-clock.spin .hand { animation: hand-spin .5s var(--ease); }
.i-clock .hand { transform-box: view-box; transform-origin: 12px 13px; }
@keyframes hand-spin { to { transform: rotate(360deg); } }
.mode-options { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; transition: grid-template-columns .32s var(--ease); }
.hero[data-mode="private"] .mode-options { grid-template-columns: .74fr .74fr 1.52fr; }
.mode-options .key { display: flex; width: 100%; }
.mode-options .key > .key-cap { padding: 0 10px; }
.private-slot { position: relative; min-width: 0; }
.time-options { display: flex; gap: 6px; }
.time-options .key { flex: 1 1 0; font: 500 12px/1 var(--mono); font-stretch: 90%; }
.time-options .key > .key-cap { padding: 0 4px; }

/* The room code: six cells in a well, where the Private key was. */
.code-slot {
  --edge: var(--cream); gap: 9px; height: 48px; margin-top: 3px; padding: 0 9px 0 13px;
  animation: slot-open .28s var(--ease);
}
@keyframes slot-open { from { opacity: .3; transform: translateY(-3px); } }
.code-slot .i-lock { flex: none; width: 18px; height: 18px; color: var(--cream); }
.code-slot[data-state="open"] .i-lock .shackle { transform: translateY(-2px) rotate(-14deg); transform-origin: 100% 100%; }
.code-slot input {
  position: absolute; z-index: 2; inset: 0; flex: none; width: 100%; height: 100%; padding: 0; opacity: 0;
  font: 16px/1 var(--mono); cursor: text;
}
.code-slot[data-state="open"] input { cursor: copy; }
.code-cells { display: flex; flex: 1; justify-content: center; gap: 3px; min-width: 0; }
.code-cells i {
  position: relative; display: grid; place-items: center; flex: 1 1 0; min-width: 0; max-width: 29px; height: 30px; background: #17181e;
  color: var(--chalk); font: 600 16px/1 var(--mono); font-stretch: 100%; font-style: normal;
  transition: background-color .15s var(--ease), color .15s var(--ease);
}
/* An empty cell shows where a character goes; the caret is the one that blinks. */
.code-cells i:empty::after { content: ""; position: absolute; left: 7px; right: 7px; bottom: 6px; height: 2px; background: #4d4e5a; }
.code-slot:focus-within .code-cells i.at:empty::after { left: 4px; right: 4px; background: var(--cream); animation: caret 1.06s steps(1) infinite; }
.code-slot:focus-within .code-cells i.at:not(:empty)::before { content: ""; position: absolute; left: 0; top: 4px; bottom: 4px; width: 2px; background: var(--cream); animation: caret 1.06s steps(1) infinite; }
.code-slot:focus-within .code-cells i.sel { background: rgba(240, 235, 217, .26); }
@keyframes caret { 50% { opacity: 0; } }
.code-cells i.land { animation: cell-land .24s var(--ease); }
@keyframes cell-land { from { background: var(--cream); color: var(--ink); transform: translateY(-5px); } }
/* Asking the server about a code: a light runs along the cells. */
.code-slot[data-state="busy"] .code-cells i { animation: cell-scan .72s var(--ease) infinite; }
.code-cells i:nth-child(2) { animation-delay: .06s; }
.code-cells i:nth-child(3) { animation-delay: .12s; }
.code-cells i:nth-child(4) { animation-delay: .18s; }
.code-cells i:nth-child(5) { animation-delay: .24s; }
.code-cells i:nth-child(6) { animation-delay: .3s; }
@keyframes cell-scan { 30% { background: #4d4e5a; } }
/* Your own room, open: the code is lit, and pressing it copies it. */
.code-slot[data-state="open"] .code-cells i { background: var(--cream); color: var(--ink); animation: cell-land .3s var(--ease) backwards; }
.code-slot.refused { --edge: var(--danger); animation: shake .28s var(--ease); }
.code-slot.refused .code-cells i { color: var(--danger-text); }
.code-copy {
  position: relative; z-index: 3; display: grid; place-items: center; flex: none; width: 30px; height: 30px; padding: 0; border: 0;
  background: #17181e; color: var(--cream); cursor: pointer; transition: background-color .15s var(--ease), transform .12s var(--ease);
}
.code-copy .icon { width: 16px; height: 16px; }
.code-copy .done, .code-copy.copied .copy { display: none; }
.code-copy.copied .done { display: block; animation: cell-land .24s var(--ease); }
.code-copy:hover { background: #2c2d37; }
.code-copy:active { transform: scale(.88); }
.code-copy:focus-visible { outline: 2px solid var(--chalk); outline-offset: 1px; }

/* What Play will do, and while a room waits, who it is waiting for. */
.mode-hint {
  grid-column: 1 / -1; display: flex; align-items: center; gap: 9px; min-height: 20px; margin: 0;
  color: var(--text-2); font: 450 13px/18px var(--font);
}
.mode-hint[data-tone="error"] { color: var(--danger-text); }
.hint-seats { display: inline-flex; gap: 3px; flex: none; }
.hint-seats i { width: 10px; height: 10px; background: var(--blue); }
.hint-seats i + i { background: transparent; box-shadow: inset 0 0 0 1.5px var(--red); animation: seat-wait 1.3s steps(1) infinite; }
@keyframes seat-wait { 50% { background: var(--red); } }
.hint-time { color: var(--text-3); font: 400 12px/18px var(--mono); font-stretch: 87.5%; font-variant-numeric: tabular-nums; }

/* The words on the Play key change with the mode; its art does not. */
.hero-play-label .rolling { overflow: visible; }

@media (max-width: 740px) {
  .hero { min-height: 510px; }
  .hero-controls { grid-template-columns: minmax(0, 1fr); width: min(calc(100% - 32px), 480px); gap: 10px; }
  .hero-time { display: grid; grid-template-columns: auto 1fr; align-items: center; column-gap: 14px; }
  .hero-time .deck-label { float: left; margin: 0; }
  .mode-group .deck-label { display: none; }
  .time-options .key { --cap: 40px; }
  .mode-hint { justify-content: center; text-align: center; }
  .hero[data-mode="private"] .mode-options { grid-template-columns: .62fr .62fr 1.76fr; }
  .hero[data-mode="private"] .mode-key .icon { display: none; }
  .mode-key { font-size: 15px; }
  .mode-options .key > .key-cap { gap: 7px; padding: 0 6px; }
}
@media (max-width: 400px) {
  .code-slot { gap: 6px; padding: 0 7px 0 9px; }
  .mode-key .icon { display: none; }
  .hero-nav .key > .key-cap { padding: 0 12px; }
}
@media (min-aspect-ratio: 4/5) and (max-height: 540px) {
  .hero { min-height: 340px; }
  .hero-nav { padding-top: 10px; }
  .hero-controls { padding-bottom: 10px; }
  .mode-group .deck-label, .hero-time .deck-label { display: none; }
}
