/* ---------------------------------------------------------------------------
   Loading screen.
   Layout: the city runs full bleed; the record sits in a rail on the left,
   held there by a gradient scrim rather than a panel, so the two never feel
   like separate windows.
   --------------------------------------------------------------------------- */

#sky, .grain, .scrim, .vignette {
  position: fixed;
  inset: 0;
  pointer-events: none;
}

#sky { width: 100%; height: 100%; display: block; }

.scrim {
  background: linear-gradient(
    90deg,
    rgba(8, 9, 11, 0.97) 0%,
    rgba(8, 9, 11, 0.93) 34%,
    rgba(8, 9, 11, 0.72) 58%,
    rgba(8, 9, 11, 0.15) 82%,
    rgba(8, 9, 11, 0) 100%
  );
}

.vignette {
  background: radial-gradient(120% 90% at 62% 45%, transparent 40%, rgba(0, 0, 0, 0.55) 100%);
}

/* film grain, drawn once as an SVG turbulence tile */
.grain {
  opacity: 0.16;
  mix-blend-mode: overlay;
  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='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grainshift 640ms steps(2) infinite;
}
@keyframes grainshift {
  0%   { transform: translate(0, 0); }
  50%  { transform: translate(-3px, 2px); }
  100% { transform: translate(2px, -2px); }
}

/* --- rail ---------------------------------------------------------------- */

.rail {
  position: relative;
  z-index: 2;
  width: var(--sheet);
  height: 100%;
  padding: var(--gut-y) var(--gut-x);
  display: grid;
  grid-template-rows: auto 1fr auto auto;
  gap: clamp(20px, 2.4vh, 34px);
}

/* staged entrance; each element declares its own delay */
.reveal {
  opacity: 0;
  transform: translateY(10px);
  animation: rise 900ms var(--ease-out) forwards;
  animation-delay: var(--d, 0ms);
}
@keyframes rise {
  to { opacity: 1; transform: none; }
}

/* --- file header --------------------------------------------------------- */

.file {
  border-top: 1px solid rgba(217,178,60,.42);
  padding-top: 14px;
}
.file .serial {
  margin-top: 7px;
  color: rgba(233,226,204,.62);
}
.file .serial span { color: var(--canary); }

/* --- wordmark ------------------------------------------------------------ */

.brand { align-self: end; }

.wordmark {
  font-size: clamp(46px, 5.2vw, 82px);
  font-weight: 800;
  line-height: 0.86;
  letter-spacing: 0.3em;
  text-indent: 0.3em;          /* keeps the wide tracking optically centred */
  opacity: 0;
  animation: settle 1500ms var(--ease-out) 180ms forwards;
}
/* the name tightens into place, like a stamp being pressed */
@keyframes settle {
  0%   { opacity: 0; letter-spacing: 0.3em; text-indent: 0.3em; filter: blur(6px); }
  60%  { opacity: 1; }
  100% { opacity: 1; letter-spacing: -0.028em; text-indent: 0; filter: blur(0); }
}

.tagrow {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 16px;
}
.tagline {
  font-family: 'Plex Mono', monospace;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.42em;
  color: var(--canary);
  text-transform: uppercase;
}
.dash {
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, rgba(217,178,60,.42), transparent);
}

/* --- notices ------------------------------------------------------------- */

.notices { align-self: center; }

.notice-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(233,226,204,.14);
}
.notice-index { color: rgba(233,226,204,.40); }

.notice { padding-top: 18px; min-height: 132px; }

.notice-title {
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin-bottom: 8px;
}
.notice-body {
  font-size: 14.5px;
  color: rgba(233,226,204,.62);
  max-width: 40ch;
}

.notice.swap .notice-title,
.notice.swap .notice-body { animation: none; }

.notice-title, .notice-body {
  animation: noticein 620ms var(--ease-out) both;
}
.notice-body { animation-delay: 70ms; }
@keyframes noticein {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: none; }
}

/* --- progress ------------------------------------------------------------ */

.load { align-self: end; }

.loadhead {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  margin-bottom: 11px;
  gap: 16px;
}
.step {
  color: rgba(233,226,204,.62);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pct {
  font-family: 'Plex Mono', monospace;
  font-weight: 500;
  font-size: 28px;
  line-height: 1;
  color: var(--stock-hi);
  font-variant-numeric: tabular-nums;
}
.pct i {
  font-style: normal;
  font-size: 13px;
  color: rgba(233,226,204,.40);
  margin-left: 2px;
}

.track {
  position: relative;
  height: 2px;
  background: rgba(233,226,204,.14);
  overflow: hidden;
}
.bar {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--canary);
  transition: width 420ms var(--ease);
}
/* a light runs ahead of the fill so the bar reads as active even when the
   game stalls on a long step */
.bar::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  width: 64px;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 159, 69, 0.85));
  animation: crawl 1900ms linear infinite;
}
@keyframes crawl {
  0%   { transform: translateX(-64px); opacity: 0; }
  35%  { opacity: 1; }
  100% { transform: translateX(0); opacity: 0; }
}

/* --- volume fader -------------------------------------------------------- */

.fader {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 26px;
  padding-top: 18px;
  border-top: 1px solid rgba(233,226,204,.07);
}

.mute {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid rgba(233,226,204,.14);
  color: rgba(233,226,204,.62);
  cursor: pointer;
  transition: color 180ms var(--ease), border-color 180ms var(--ease), transform 120ms var(--ease);
}
.mute:hover { color: var(--canary); border-color: rgba(217,178,60,.42); }
.mute:active { transform: translateY(1px); }
.mute.off #wave { opacity: 0.18; }
.mute.off { color: rgba(233,226,204,.40); }

input[type='range'] {
  flex: 1;
  -webkit-appearance: none;
  appearance: none;
  height: 22px;
  background: transparent;
  cursor: pointer;
}
input[type='range']::-webkit-slider-runnable-track {
  height: 2px;
  background: rgba(233,226,204,.14);
}
input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 3px;
  height: 15px;
  margin-top: -6.5px;
  background: var(--canary);
  border: 0;
  border-radius: 0;
  transition: height 160ms var(--ease), margin-top 160ms var(--ease);
}
input[type='range']:hover::-webkit-slider-thumb,
input[type='range']:focus-visible::-webkit-slider-thumb {
  height: 21px;
  margin-top: -9.5px;
}

.volval { width: 3ch; text-align: right; color: rgba(233,226,204,.40); }

.audiohint {
  margin-top: 10px;
  color: var(--canary);
  animation: pulse 2.4s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: 0.45; } }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Once the world is ready the rail steps aside and reveals the live camera.
   The page background has to go transparent too, otherwise the fade reveals
   nothing but our own backdrop colour. */
body.handover, body.handover .rail { background: transparent !important; }
body.handover .scrim  { transition: opacity 1400ms var(--ease); opacity: 0; }
body.handover #sky    { transition: opacity 1400ms var(--ease); opacity: 0; }
body.handover .grain  { transition: opacity 1400ms var(--ease); opacity: 0; }
body.handover .rail   { transition: opacity 900ms var(--ease), transform 1200ms var(--ease); opacity: 0; transform: translateY(-12px); }


/* ---------------------------------------------------------------------------
   The loading screen is the only screen with no paper on it, so the three
   voices have to be restated in their light-on-dark values.
   --------------------------------------------------------------------------- */
.eyebrow { color: rgba(233,226,204,.42); }
.data    { color: rgba(233,226,204,.60); }
body     { color: var(--stock-hi); }

/* The posted notice is a real notice: a slip of the same stock the rest of the
   product is printed on, taped to the window of a city that is still loading. */
.notice {
  background: var(--stock);
  color: var(--ink);
  padding: 15px 17px 16px;
  box-shadow: var(--lift-1);
  border-left: 3px solid var(--canary);
}
.notice-head { border-bottom: 1px solid var(--rule); padding-bottom: 7px; margin-bottom: 9px; }
.notice-index { color: var(--ink-3); }
.notice-title { color: var(--ink); }
.notice-body  { color: var(--ink-2); }
