/* ============================================================
   Silo — waiting for Troy

   One light in a dark room, and the light is the control:
   press the key and you are counted. Everything else on
   the page is something that light happens to fall on.

   Two custom properties carry every interactive state:
     --lit   how hard the key is burning
     --beat  how fast it breathes
   ============================================================ */


/* ---------- IBM Plex Mono, served from here ----------
   Self-hosted rather than pulled from Google. Two reasons, both real: the
   footer promises no third parties, and a request to fonts.googleapis.com
   hands a visitor's address to one before the first word is drawn. It is also
   simply faster — no extra DNS lookup and TLS handshake in front of the text.

   These are the exact files Google serves, latin and latin-ext only; the
   cyrillic and vietnamese subsets carry nothing this page can display. IBM
   Plex Mono is under the SIL Open Font License 1.1, which permits hosting and
   subsetting; the licence travels with the fonts in public/fonts/OFL.txt.
   ---------------------------------------------------- */

/* latin-ext */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 200;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-200-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 200;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-200-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* latin-ext */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-300-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-300-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* latin-ext */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* latin-ext */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-500-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --void:   #08090b;
  --ember:  #ff2f3e;
  --bone:   #ece6dd;
  --ash:    #757a82;
  --ash-dim:#4b4f56;
}

* { box-sizing: border-box; }

[hidden] { display: none !important; }

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

body {
  margin: 0;
  min-height: 100dvh;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--bone);
  background-color: var(--void);
  background-image:
    radial-gradient(140% 90% at 50% -10%, #14181d 0%, #0a0c0f 46%, #08090b 78%),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='280' height='280'><filter id='g'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/><feColorMatrix type='saturate' values='0'/></filter><rect width='280' height='280' filter='url(%23g)' opacity='.4'/></svg>");
  background-blend-mode: normal, soft-light;
}

.dark {
  --beat: 5.4s;
  --lit: 1;
  --glow-r: clamp(320px, 58vw, 760px);

  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100dvh;
  padding: clamp(10px, 2vh, 24px) clamp(16px, 4vw, 36px) clamp(22px, 3.5vh, 40px);
}

/* the key burns harder as you get closer to it */
.dark.is-in    { --lit: 1.16; --beat: 4.4s; }
.dark.is-hot   { --lit: 1.52; --beat: 2.2s; }
.dark.is-flare { --lit: 2.2;  --beat: .9s; }

/* Spans the window exactly; the gradient, not the box, does the spreading,
   so the light can never widen the page. JS keeps its centre on the key. */
.glow {
  position: absolute;
  /* Exactly the page, never taller: an absolutely positioned box still counts
     toward scroll height, and a fixed height here left the desktop scrolling
     into empty dark. The gradient does the spreading, the box does not. */
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    circle var(--glow-r) at var(--glow-x, 50%) var(--glow-y, 200px),
    rgba(255, 68, 88, .32)  0%,
    rgba(255, 52, 74, .185) 16%,
    rgba(240, 40, 64, .105) 30%,
    rgba(208, 30, 54, .050) 46%,
    rgba(172, 22, 44, .020) 62%,
    transparent 80%);
  filter: brightness(var(--lit));
  transition: filter .5s ease;
}

/* ---------- stage ---------- */

.stage {
  position: relative;
  z-index: 1;
  display: grid;
  justify-items: center;
  gap: clamp(6px, 1.4vh, 16px);
  width: 100%;
  max-width: 1020px;
}

/* ---------- the key, which is the button ---------- */

.lamp {
  display: block;
  padding: clamp(4px, 1.2vh, 12px) 18px;
  border: 0;
  border-radius: 34px;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.lamp:focus-visible {
  outline: 2px solid rgba(255, 90, 105, .9);
  outline-offset: 6px;
}

.pendant {
  width: clamp(118px, 16vw, 176px);
  height: auto;
  display: block;
  overflow: visible;
  transition: transform .5s cubic-bezier(.22, 1, .36, 1);
}

.dark.is-hot .pendant   { transform: scale(1.03); }
.dark.is-flare .pendant { transform: scale(.982); }

.pendant__num {
  font-family: "IBM Plex Mono", monospace;
  font-size: 30px;
  font-weight: 400;
  letter-spacing: 4px;
  fill: #5e0a13;
  opacity: .72;
}

/* ---------- the wait ---------- */

.wait { width: 100%; text-align: center; }

.clock {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: clamp(2px, .8vw, 10px);
  margin-bottom: clamp(14px, 2.4vh, 26px);
}

.unit {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .85em;
  min-width: 0;
  padding-inline: clamp(3px, 1.3vw, 15px);
}

.unit__n {
  font-size: clamp(1.9rem, 8.4vw, 4.6rem);
  font-weight: 200;
  line-height: .86;
  letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
  color: #fbf7f2;
  text-shadow:
    0 0 26px rgba(255, 72, 92, .32),
    0 0 70px rgba(255, 52, 74, .17);
}

.unit__l {
  font-size: clamp(.5rem, 1.8vw, .66rem);
  font-weight: 300;
  letter-spacing: .2em;
  text-indent: .2em;
  color: var(--ash-dim);
}

.clock__sep {
  font-size: clamp(1.2rem, 5vw, 2.9rem);
  font-weight: 200;
  line-height: 1.05;
  color: #fbf7f2;
  opacity: .22;
}

.title {
  margin: 0;
  font-size: clamp(1.3rem, 4vw, 1.9rem);
  font-weight: 300;
  letter-spacing: .5em;
  text-indent: .5em;
  color: var(--bone);
  text-shadow: 0 0 40px rgba(255, 50, 64, .22);
}

.synopsis {
  margin: .9em 0 0;
  font-size: clamp(.8rem, 1.9vw, .92rem);
  font-weight: 300;
  line-height: 1.7;
  color: var(--ash);
}

.caption {
  display: inline-block;
  font-size: .86em;
  color: var(--ash-dim);
}

.when {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .45em;
  margin: clamp(16px, 2.4vh, 24px) auto 0;
}

/* The whole time line is the button. It has to look like text until you go
   near it, or it competes with the key for attention. */
.when__row {
  display: flex;
  align-items: center;
  gap: .55em;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: inherit;
  cursor: pointer;
}

.when__row:hover .when__at,
.when__row:focus-visible .when__at,
.when__row:hover .share,
.when__row:focus-visible .share {
  color: rgba(255, 130, 138, .95);
}

.when__row:focus-visible {
  outline: 1px solid rgba(255, 47, 62, .45);
  outline-offset: 6px;
  border-radius: 6px;
}

/* the assistive-only half of the button's name */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.when__at {
  font-size: clamp(.95rem, 2.3vw, 1.12rem);
  font-weight: 400;
  letter-spacing: .03em;
  color: var(--bone);
}

.when__zone {
  font-size: clamp(.66rem, 1.6vw, .72rem);
  font-weight: 300;
  letter-spacing: .1em;
  color: var(--ash-dim);
}

.ack {
  margin: clamp(12px, 1.8vh, 18px) auto 0;
  min-height: 1.4em;
  font-size: clamp(.72rem, 1.7vw, .8rem);
  font-weight: 300;
  letter-spacing: .06em;
  color: var(--ash-dim);
  transition: color .3s ease;
}

.dark.is-hot .ack { color: rgba(255, 120, 130, .85); }
.dark.is-in  .ack { color: rgba(255, 120, 130, .85); }

/* Not a button any more — the line around it is. This is only the sign that
   the line does something, so it carries no border and no box of its own. */
.share {
  display: grid;
  place-items: center;
  flex: none;
  width: 1.05em;
  height: 1.05em;
  color: var(--ash-dim);
  transition: color .25s ease;
}

.share svg {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: opacity .18s ease;
}

/* one glyph at a time, both stacked in the same grid cell */
.share__tick { opacity: 0; }
.when__row.is-done .share__icon { opacity: 0; }
.when__row.is-done .share__tick { opacity: 1; }
.when__row.is-done .share { color: rgba(255, 130, 138, .95); }

.go {
  display: inline-block;
  margin-top: clamp(16px, 2.4vh, 24px);
  padding: .95em 2.3em;
  border-radius: 999px;
  font-size: clamp(.82rem, 2vw, .92rem);
  font-weight: 400;
  letter-spacing: .16em;
  text-indent: .16em;
  text-decoration: none;
  color: #180305;
  background: linear-gradient(#ff5a63, var(--ember));
  box-shadow: 0 0 46px -8px rgba(255, 47, 62, .75);
  transition: transform .2s ease, box-shadow .2s ease;
}

.go:hover { transform: translateY(-1px); box-shadow: 0 0 60px -6px rgba(255, 47, 62, .9); }

.itsout {
  margin: 0 0 clamp(16px, 2.6vh, 28px);
  font-size: clamp(1.8rem, 6.6vw, 3.4rem);
  font-weight: 200;
  letter-spacing: .06em;
  color: #fbf7f2;
  text-shadow: 0 0 34px rgba(255, 60, 74, .4), 0 0 90px rgba(255, 40, 54, .2);
}

/* ---------- who else is down here ---------- */

.census {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 900px;
  margin-top: clamp(30px, 6vh, 64px);
  text-align: center;
}

/* one row, one border, one thing to read */
.census__line {
  display: inline-flex;
  align-items: center;
  gap: clamp(11px, 2.2vw, 20px);
  margin: 0;
  padding: .62em 1.35em;
  border: 1px solid rgba(236, 230, 221, .09);
  border-radius: 999px;
  background: rgba(236, 230, 221, .026);
  font-size: clamp(.7rem, 1.7vw, .78rem);
  font-weight: 300;
  letter-spacing: .1em;
  color: var(--ash);
}

.census__rule {
  width: 1px;
  height: 1.15em;
  background: rgba(236, 230, 221, .14);
}

.stat { display: inline-flex; align-items: baseline; gap: .5em; }

.census__n {
  font-size: clamp(1rem, 2.5vw, 1.18rem);
  font-weight: 300;
  font-variant-numeric: tabular-nums;
  color: var(--bone);
}

.census__link {
  display: inline-flex;
  align-items: center;
  gap: .55em;
  font-size: .66rem;
  letter-spacing: .14em;
  color: var(--ash-dim);
}

.census__link::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--ash-dim);
}

.census__link[data-state="live"] { color: rgba(255, 107, 115, .82); }
.census__link[data-state="live"]::before {
  background: var(--ember);
  box-shadow: 0 0 10px var(--ember);
}
.census__link[data-state="down"] { color: #8a5f3a; }
.census__link[data-state="down"]::before { background: #8a5f3a; }

.roll {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px clamp(8px, 1.6vw, 14px);
  margin: clamp(14px, 2.2vh, 20px) 0 0;
  padding: 0;
}

.roll li {
  display: inline-flex;
  align-items: center;
  gap: .55em;
  padding: .45em .95em;
  border-radius: 999px;
  background: rgba(236, 230, 221, .04);
  font-size: clamp(.66rem, 1.6vw, .74rem);
  font-weight: 300;
  letter-spacing: .05em;
  color: var(--ash);
  transition: background .25s ease, color .25s ease, transform .25s ease;
}

.roll li:hover {
  background: rgba(255, 80, 96, .11);
  color: #cfd4da;
  transform: translateY(-1px);
}

.roll__flag { font-size: 1.05em; line-height: 1; }
.roll__n { color: var(--bone); font-variant-numeric: tabular-nums; }
.roll__empty { background: none; color: var(--ash-dim); }
.roll__empty:hover { background: none; transform: none; }

.census__foot {
  margin: clamp(12px, 2vh, 18px) 0 0;
  min-height: 1.1em;
  font-size: .68rem;
  font-weight: 300;
  letter-spacing: .08em;
  color: var(--ash-dim);
}

/* the two all-time tallies, as one small block: labels right-aligned against
   their numbers so the pair reads as a table rather than two stray lines */
.tally {
  display: grid;
  grid-template-columns: auto auto;
  align-items: baseline;
  justify-content: center;
  gap: .45em .85em;
  margin: clamp(11px, 1.8vh, 16px) auto 0;
  font-size: .66rem;
  font-weight: 300;
  letter-spacing: .06em;
  color: var(--ash-dim);
}

.tally__label {
  text-align: right;
  color: #3e424a;
  white-space: nowrap;
}

.tally__row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .45em;
}

.tally__one {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.tally__dot { opacity: .35; }

/* ---------- fine print ---------- */

.fineprint {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 60ch;
  margin: clamp(22px, 3.5vh, 38px) auto 0;
  text-align: center;
}

.fineprint p {
  margin: 0 0 .7em;
  font-size: .66rem;
  font-weight: 300;
  line-height: 1.85;
  color: #3e424a;
}

.fineprint__src { color: #33363d !important; }

/* the footer is one quiet line; the privacy text lives behind the mark */
.fineprint__row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .6em;
}

.fineprint__row .fineprint__src { margin-bottom: 0; }

.privacy__mark {
  display: grid;
  place-items: center;
  width: 1.5em;
  height: 1.5em;
  padding: 0;
  border: 1px solid #33363d;
  border-radius: 999px;
  background: none;
  font: inherit;
  font-size: .66rem;
  font-style: italic;
  line-height: 1;
  color: #33363d;
  cursor: pointer;
  transition: color .25s ease, border-color .25s ease;
}

.privacy__mark:hover,
.privacy__mark:focus-visible {
  color: var(--ash);
  border-color: var(--ash-dim);
}

/* the popup itself. It is in the top layer, so it needs its own everything —
   a popover inherits no position and no colour from the page behind it. */
.privacy {
  width: min(42ch, calc(100vw - 2.5rem));
  margin: auto;               /* centres it in the viewport */
  padding: 1.5em 1.6em 1.3em;
  border: 1px solid rgba(236, 230, 221, .1);
  border-radius: 16px;
  background: #0c0e11;
  box-shadow: 0 26px 70px rgba(0, 0, 0, .62);
  color: var(--ash);
  text-align: left;
}

/* Hidden by default and revealed by whichever mechanism is available. Written
   as three separate rules on purpose: an engine that does not know
   `:popover-open` drops that one rule and keeps the other two, so the panel
   stays hidden and the shim can still open it. Folding them into one selector
   list would invalidate all three and leave the text sitting in the page. */
.privacy { display: none; }
.privacy:popover-open { display: block; }
.privacy.is-open { display: block; position: fixed; inset: 0; }

.privacy::backdrop {
  background: rgba(4, 5, 7, .62);
}

.privacy__title {
  margin: 0 0 .75em;
  font-size: .72rem;
  font-weight: 400;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--ash-dim);
}

.privacy .privacy__text {
  margin: 0;
  font-size: .76rem;
  font-weight: 300;
  line-height: 1.85;
  color: #6d7481;
}

.privacy__close {
  display: block;
  margin: 1.35em 0 0 auto;
  padding: .5em 1.1em;
  border: 1px solid rgba(236, 230, 221, .12);
  border-radius: 999px;
  background: none;
  font: inherit;
  font-size: .66rem;
  font-weight: 300;
  letter-spacing: .1em;
  color: var(--ash-dim);
  cursor: pointer;
  transition: color .25s ease, border-color .25s ease;
}

.privacy__close:hover,
.privacy__close:focus-visible {
  color: var(--ash);
  border-color: var(--ash-dim);
}

/* ---------- motion: the light breathes, and answers you ---------- */

@keyframes ember {
  0%, 100% { opacity: .86; }
  50%      { opacity: 1; }
}

@keyframes emberCore {
  0%, 100% { opacity: .88; }
  50%      { opacity: 1; }
}

@keyframes emberBody {
  0%, 100% { filter: brightness(.955); }
  50%      { filter: brightness(1.045); }
}

@keyframes bump {
  0%   { transform: none; }
  35%  { transform: translateY(-3px) scale(1.09); }
  100% { transform: none; }
}

.glow           { animation: ember var(--beat) ease-in-out infinite; }
.pendant__bloom {
  animation: emberCore var(--beat) ease-in-out infinite;
  filter: brightness(var(--lit));
  transition: filter .5s ease;
}
.pendant__core  { animation: emberBody var(--beat) ease-in-out infinite; }

.census__n.bump { display: inline-block; animation: bump .55s cubic-bezier(.22, 1, .36, 1); }

@media (prefers-reduced-motion: reduce) {
  .glow, .pendant__bloom, .pendant__core, .census__n.bump { animation: none; }
  .pendant, .go, .roll li, .glow, .ack, .share, .share svg { transition: none; }
  .dark.is-hot .pendant, .dark.is-flare .pendant { transform: none; }
}

/* ---------- wide: key beside the wait, not above it ---------- */

@media (min-width: 900px) {
  .stage {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    justify-items: start;
    gap: clamp(34px, 5vw, 76px);
  }
  .wait { text-align: left; }
  .clock { justify-content: flex-start; }
  .when { align-items: flex-start; margin-inline: 0; }
  .ack { margin-inline: 0; }
}

/* ---------- narrow ---------- */

@media (max-width: 520px) {
  .clock { gap: 0; width: 100%; }
  .unit { padding-inline: 2px; flex: 1 1 0; }
  .unit__l { letter-spacing: .04em; text-indent: 0; }
  .clock__sep { align-self: center; margin-top: -.45em; }
  .title { letter-spacing: .32em; text-indent: .32em; }
}
