/* latency.zone
   One family at two widths. Colour is data, so the interface itself stays
   almost monochrome and lets the wires carry the hue. */

@font-face {
  font-family: 'Archivo';
  src: url('assets/fonts/archivo-var.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
}

:root {
  --ink: #070A0C;
  --ink-2: #0B1116;
  --text: #E7EDF1;
  --muted: #7A8B96;
  --faint: #4A5C67;
  --hair: rgba(122, 154, 176, 0.16);
  --ice: #B8EAFF;
  --edge: 30px;
  --font: 'Archivo', ui-sans-serif, system-ui, -apple-system, 'Helvetica Neue', sans-serif;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body { height: 100%; overflow: hidden; background: var(--ink); }

body {
  font-family: var(--font);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.55;
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
  -webkit-tap-highlight-color: transparent;
}

#stage { position: fixed; inset: 0; touch-action: none; }
#stage canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
#gl { z-index: 0; cursor: grab; }
#gl:active { cursor: grabbing; }
#overlay { z-index: 1; pointer-events: none; }

#hint {
  position: absolute;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  z-index: 2;
  font-size: 10.5px;
  font-stretch: 108%;
  letter-spacing: 0.06em;
  color: var(--faint);
  pointer-events: none;
  opacity: 0;
  transition: opacity 700ms var(--ease);
}
#hint[data-show] { opacity: 1; }

#hud {
  position: fixed;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  display: grid;
  grid-template-columns: minmax(0, 340px) minmax(0, 1fr) 196px;
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas:
    'mast  .  status'
    '.     .  legend'
    'find  .  foot';
  gap: 20px 28px;
  padding: max(var(--edge), env(safe-area-inset-top)) max(var(--edge), env(safe-area-inset-right))
           max(var(--edge), env(safe-area-inset-bottom)) max(var(--edge), env(safe-area-inset-left));
}

/* Masthead ---------------------------------------------------------------- */

.masthead { grid-area: mast; }

.masthead h1 {
  font-size: 21px;
  font-weight: 700;
  font-stretch: 118%;
  letter-spacing: -0.005em;
  line-height: 1;
  color: var(--text);
}
.masthead h1 span { color: var(--ice); }

.masthead p {
  margin-top: 9px;
  max-width: 24ch;
  font-size: 11.5px;
  color: var(--muted);
  text-wrap: pretty;
}

/* Status ------------------------------------------------------------------ */

.status { grid-area: status; text-align: right; }
.status p {
  font-size: 12px;
  font-stretch: 108%;
  color: var(--text);
}
.status .sub {
  margin-top: 2px;
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.status[data-done] p:first-child { color: var(--muted); }

/* Legend: the live list doubles as the progress indicator ----------------- */

.legend {
  grid-area: legend;
  align-self: center;
  justify-self: end;
  min-height: 0;
  width: 100%;
  overflow: hidden;
}

#legend-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 1px;
  counter-reset: none;
}

#legend-list li {
  display: grid;
  grid-template-columns: 13px minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  height: 16px;
  font-size: 10.5px;
  color: var(--faint);
  opacity: 0.45;
  transition: opacity 500ms var(--ease), color 500ms var(--ease);
}
#legend-list li[data-on] { opacity: 1; color: var(--text); }
#legend-list li[data-dead] { opacity: 0.3; }

#legend-list .swatch {
  width: 13px;
  height: 2px;
  background: currentColor;
  opacity: 0.35;
}
#legend-list li[data-on] .swatch { opacity: 1; }

#legend-list .city {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-stretch: 96%;
}

#legend-list .ms {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-stretch: 108%;
  letter-spacing: 0.01em;
}
#legend-list li[data-dead] .ms { font-weight: 400; color: var(--faint); }

/* Findings: sentences, not stat cards ------------------------------------- */

.findings { grid-area: find; align-self: end; max-width: 40ch; }
.findings[hidden] { display: none; }

.findings p {
  font-size: 13px;
  line-height: 1.6;
  color: var(--muted);
  text-wrap: pretty;
  opacity: 0;
  transform: translateY(6px);
  animation: rise 800ms var(--ease) forwards;
}
.findings p + p { margin-top: 9px; }
.findings p:nth-child(2) { animation-delay: 90ms; }
.findings p:nth-child(3) { animation-delay: 180ms; }
.findings p:nth-child(4) { animation-delay: 270ms; }

.findings b {
  font-weight: 600;
  color: var(--text);
}
.findings b.n {
  font-variant-numeric: tabular-nums;
  font-stretch: 112%;
  color: var(--ice);
}
.findings .quiet { font-size: 11px; color: var(--faint); margin-top: 13px; }
.findings .quiet b { color: var(--muted); font-weight: 600; }

@keyframes rise { to { opacity: 1; transform: none; } }

/* Footer ------------------------------------------------------------------ */

.foot { grid-area: foot; align-self: end; text-align: right; padding-bottom: 42px; }

.note {
  font-size: 10.5px;
  line-height: 1.62;
  color: var(--faint);
  text-wrap: pretty;
}

.actions {
  /* The footer column is narrow so the note wraps well, but four buttons need
     more room than that. Let the row grow leftward past the column edge
     instead of stacking into a staircase. */
  /* Pinned to the corner rather than laid out in the footer column: that
     column is deliberately narrow so the note wraps well, which is far too
     narrow for four controls, and they were folding into a staircase. */
  position: fixed;
  right: max(var(--edge), env(safe-area-inset-right));
  bottom: max(var(--edge), env(safe-area-inset-bottom));
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: flex-end;
  pointer-events: auto;
}

button, .actions a {
  font: inherit;
  white-space: nowrap;
  font-size: 11px;
  font-weight: 600;
  font-stretch: 106%;
  letter-spacing: 0.005em;
  padding: 7px 13px 6px;
  border: 1px solid var(--hair);
  background: none;
  color: var(--text);
  cursor: pointer;
  text-decoration: none;
  transition: border-color 220ms var(--ease), color 220ms var(--ease), background 220ms var(--ease);
}
button:hover:not(:disabled), .actions a:hover { border-color: var(--ice); color: var(--ice); }
button:disabled { opacity: 0.32; cursor: default; }
button#save:not(:disabled) { border-color: rgba(184, 234, 255, 0.55); color: var(--ice); }
button.on { border-color: var(--ice); color: var(--ink); background: var(--ice); }
button.on:hover { background: #cdf1ff; color: var(--ink); }
button#save:not(:disabled):hover { background: rgba(184, 234, 255, 0.1); }
.actions a { border-color: transparent; color: var(--muted); padding-left: 4px; padding-right: 4px; }
:focus-visible { outline: 1px solid var(--ice); outline-offset: 3px; }

/* Method ------------------------------------------------------------------ */

.method {
  position: fixed;
  right: max(var(--edge), env(safe-area-inset-right));
  bottom: calc(max(var(--edge), env(safe-area-inset-bottom)) + 8px);
  width: min(400px, calc(100vw - 2 * var(--edge)));
  padding: 20px 20px 18px;
  background: var(--ink-2);
  border: 1px solid var(--hair);
  pointer-events: auto;
  animation: rise 420ms var(--ease) forwards;
}
.method[hidden] { display: none; }
.method h2 {
  font-size: 12px;
  font-weight: 700;
  font-stretch: 112%;
  margin-bottom: 10px;
}
.method p {
  font-size: 11.5px;
  line-height: 1.65;
  color: var(--muted);
  text-wrap: pretty;
}
.method p + p { margin-top: 9px; }
.method em { color: var(--text); font-style: normal; font-weight: 600; }
.method button { margin-top: 14px; }

.fallback {
  position: fixed; inset: 0;
  display: grid; place-content: center;
  padding: 40px; text-align: center;
  color: var(--muted);
}

/* Legibility: the globe sits behind live text, so give the columns somewhere
   dark to sit without drawing panels around them. */
#hud::before, #hud::after {
  content: '';
  position: fixed;
  top: 0; bottom: 0;
  width: 30vw;
  pointer-events: none;
  z-index: -1;
}
#hud::before { left: 0; background: linear-gradient(to right, rgba(7,10,12,0.9), rgba(7,10,12,0)); }
#hud::after { right: 0; background: linear-gradient(to left, rgba(7,10,12,0.82), rgba(7,10,12,0)); }

@media (max-height: 780px) {
  #legend-list li { height: 14px; font-size: 10px; }
  .findings p { font-size: 12px; }
  .findings p + p { margin-top: 7px; }
}

/* Narrow ------------------------------------------------------------------ */

@media (max-width: 900px) {
  #hud { grid-template-columns: minmax(0, 290px) minmax(0, 1fr) 186px; gap: 16px 18px; }
  .findings { max-width: 34ch; font-size: 12px; }
}

@media (max-width: 760px) {
  :root { --edge: 16px; }
  html, body { overflow: hidden; }
  #hud {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto auto;
    grid-template-areas: 'mast' '.' 'find' 'foot';
    gap: 10px;
    overflow: hidden;
  }
  .status {
    grid-area: mast;
    align-self: start;
    justify-self: end;
    text-align: right;
    padding-top: 2px;
  }
  .masthead { padding-right: 108px; }
  .masthead p { display: none; }
  .legend { display: none; }
  .findings { max-width: none; }
  .findings p { font-size: 12px; }
  .findings p + p { margin-top: 7px; }
  .findings .quiet { display: none; }
  .note { display: none; }
  .foot { text-align: left; }
  .actions { position: static; justify-content: flex-start; flex-wrap: wrap; margin-top: 10px; }
  .foot { padding-bottom: 0; }
  #hud::before, #hud::after { display: none; }
  #hint { bottom: auto; top: 64px; }
  .method { left: var(--edge); right: var(--edge); width: auto; bottom: 76px; }
}

@media (prefers-reduced-motion: reduce) {
  .findings p { animation-duration: 1ms; animation-delay: 0ms !important; }
  #hint { transition: none; }
  * { scroll-behavior: auto; }
}
