/* The first-visit gate. Loading screen and bot check, once a day.
 *
 * This is the first thing every visitor sees, so it is the one screen that has
 * to look like the product rather than like infrastructure. It is also the one
 * screen that must never get stuck: everything here is styled so that removing
 * the element is the only cleanup needed, and gate.js has three separate
 * timeouts that do exactly that.
 *
 * Loaded in the head alongside shell.css, because an overlay that arrives after
 * the page has painted is not a loading screen, it is an interruption.
 */

.ghgate {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: grid;
  place-items: center;
  padding: var(--s-5);
  /* Opaque. A translucent gate over a half-drawn page reads as a page that
     failed rather than a page that is arriving. */
  background: var(--bg);
  opacity: 1;
  transition: opacity 0.42s var(--ease);
}
/* Removed from the flow the moment it is done, so nothing behind it is ever
   left with a dead layer on top intercepting clicks. */
.ghgate[data-done="1"] { opacity: 0; pointer-events: none; }

.ghgate-in {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-5);
  text-align: center;
  max-width: 26rem;
}

/* The mark, breathing rather than spinning. A spinner says "wait"; this says
   "arriving", and it is the same logo the header carries so the gate reads as
   part of the site instead of a checkpoint in front of it. */
.ghgate-mk {
  width: 4.5rem;
  height: 4.5rem;
  border-radius: var(--rad-large);
  filter: drop-shadow(0 0 22px var(--bloom));
  animation: ghgate-breathe 2.6s var(--ease) infinite;
}
@keyframes ghgate-breathe {
  0%, 100% { transform: scale(1); opacity: 0.92; }
  50% { transform: scale(1.045); opacity: 1; }
}

.ghgate-txt {
  font-size: var(--t-sm);
  color: var(--mut);
  min-height: 1.4em;
  /* The status line changes at most twice. Cross-fading it stops the layout
     from twitching under a word that got longer. */
  transition: opacity 0.22s ease;
}
.ghgate[data-swap="1"] .ghgate-txt { opacity: 0; }

/* A determinate-looking bar over an indeterminate wait, which is a lie every
   loading screen tells. It is kept honest by being short: it fills once, in the
   time the check usually takes, and then holds rather than looping forever and
   implying progress that is not happening. */
.ghgate-bar {
  width: min(15rem, 60vw);
  height: 2px;
  border-radius: 2px;
  background: var(--ln);
  overflow: hidden;
}
.ghgate-bar > i {
  display: block;
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, var(--acc), var(--acc2, var(--acc)));
  transform-origin: 0 50%;
  transform: scaleX(0.04);
  transition: transform 2.4s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.ghgate[data-armed="1"] .ghgate-bar > i { transform: scaleX(0.86); }
.ghgate[data-done="1"] .ghgate-bar > i { transform: scaleX(1); transition-duration: 0.24s; }

/* Where the widget lands. It has no height until Turnstile fills it, so the
   layout does not reserve a hole for a check most visits never see. */
.ghgate-cf:empty { display: none; }
.ghgate-cf {
  display: flex;
  justify-content: center;
  min-height: 65px;
}

/* The way out, and it only appears once the check has visibly stalled.
 *
 * Offered rather than forced: cancelling a challenge somebody is halfway through
 * drops them onto the page with no pass and challenges them again a click later.
 * Understated on purpose. It is a door, not an invitation, and a bot never
 * clicks it. */
.ghgate-skip {
  appearance: none;
  background: none;
  border: 0;
  padding: var(--s-2) var(--s-3);
  font: inherit;
  font-size: var(--t-sm);
  color: var(--mut);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  border-radius: var(--rad-soft);
  transition: color var(--t-tint) ease;
  animation: ghgate-arrive 0.32s var(--ease) both;
}
.ghgate-skip:hover, .ghgate-skip:focus-visible { color: var(--fg); }
@keyframes ghgate-arrive {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

.ghgate-note {
  font-size: var(--t-label);
  color: var(--mut);
  opacity: 0.75;
  max-width: 22rem;
  line-height: 1.5;
}

@media (prefers-reduced-motion: reduce) {
  .ghgate, .ghgate-bar > i, .ghgate-txt { transition: none; }
  .ghgate-mk { animation: none; }
}
