/* The door.
 *
 * Everything here is the phone's opening screen, rebuilt for a browser: the same sky, the same
 * wordmark settling from slightly too large, the same hairline drawing under it. A venue that
 * installs the app after seeing this page should recognise the first frame.
 *
 * The page holds no argument and no content on purpose - the site is written once the product is in
 * venues. What it must do is be a door: two ways in, and the app for the room's own phone. */

:root {
  --ink: #EEF2F7;
  --muted: #9AA7B5;
  --accent: #3E85D3;
  --accent-deep: #2C68AE;
  --panel: #1C2534;
  --bot: #10151C;
  --line: rgba(255, 255, 255, .16);
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  color: var(--ink);
  font-family: 'Syne', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  background: var(--bot);
  display: flex;
  flex-direction: column;
  overflow: hidden;                       /* the door is one screen, never a scroll */
}

/* ---------------------------------------------------------------- the sky */

.sky {
  position: fixed;
  inset: 0;
  background: linear-gradient(160deg, var(--panel) 0%, var(--bot) 100%);
  opacity: 0;
  animation: sky-in .55s ease-out forwards;
}

/* React Native has no radial gradient, so the app draws its glow as three discs of decreasing
   opacity. The browser could do it in one line - and then the two would not match, which is the
   only thing that matters here. */
.bloom {
  position: absolute;
  left: 50%;
  top: 14%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--accent);
  /* Softened just enough to kill the stair-stepping on a curve this large, and no further. The
     rings are meant to be seen: the phone draws its glow as three discs, and their edges are what
     make it read as a lit room rather than as a gradient. Blurring them away - which is what a
     browser tempts you to do - threw out the thing that makes the two screens the same screen. */
  filter: blur(26px);
}
/* Off the SHORT side, which is what makes the rings visible on both shapes of screen: on a phone
   the short side is the width, exactly as the app sizes them, and on a desktop it is the height, so
   the curve shows at the left and right instead of running off the frame. Sized off the long side
   they vanish - the whole screen sits inside the smallest disc and the glow flattens into a wash. */
.b1 { width: 240vmin; height: 240vmin; opacity: .05; }
.b2 { width: 170vmin; height: 170vmin; opacity: .05; }
.b3 { width: 110vmin; height: 110vmin; opacity: .06; }

@keyframes sky-in { to { opacity: 1; } }

/* ---------------------------------------------------------------- the mark */

.door {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* the bottom keeps room for the app row and the footer, which stand under this centred group */
  padding: 40px 24px 150px;
  text-align: center;
}

/* The rule is as wide as the name, and it opens to that width - so it belongs to the word rather
   than being a line of its own beneath it. Shrink-wrapping the column is what gives it that width
   without anybody measuring the text. */
.mark { display: inline-flex; flex-direction: column; align-items: stretch; }

.word {
  margin: 0;
  /* 750. Syne is a variable font, so this is a real weight rather than a rounding to 700 or 800 -
     asked for twice because Safari still honours the axis more reliably than the shorthand. */
  font-weight: 750;
  font-variation-settings: 'wght' 750;
  font-size: clamp(38px, 8.2vw, 68px);
  letter-spacing: .02em;
  line-height: 1;
  /* letter-spacing hangs after the last O, so the line would sit wider than the word without this */
  padding-right: .02em;
  opacity: 0;
  transform: scale(1.18);
  /* Slower, and with a longer tail: the name should look like it is settling rather than
     arriving. Everything below follows in the same easing, so the page reads as one movement. */
  animation: mark-in 1.75s cubic-bezier(.22, .68, .16, 1) .55s forwards;
}

.rule {
  width: 100%;
  height: 1px;
  margin-top: 22px;
  background: rgba(255, 255, 255, .45);
  transform: scaleX(0);
  transform-origin: center;
  animation: rule-in .95s cubic-bezier(.22, .68, .16, 1) 2.05s forwards;
}

@keyframes mark-in { to { opacity: 1; transform: scale(1); } }
@keyframes rule-in { to { transform: scaleX(1); } }

/* Everything after the mark arrives once the opening has finished, in the order a person reads it.
   The delays are the app's own timing continued, not a second animation with its own opinion. */
.line, .stores {
  opacity: 0;
  transform: translateY(12px);
  animation: up .9s cubic-bezier(.22, .68, .16, 1) forwards;
}
.line   { animation-delay: 2.95s; }
.stores { animation-delay: 3.25s; }

@keyframes up { to { opacity: 1; transform: none; } }

.line {
  margin: 26px 0 0;
  font-size: clamp(15px, 2.2vw, 19px);
  font-weight: 400;
  color: var(--muted);
  max-width: 34ch;
  line-height: 1.55;
}

/* ---------------------------------------------------------------- the two ways in */

.bar {
  position: absolute;
  top: 0; right: 0; left: 0;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 20px 24px;
  z-index: 2;
  opacity: 0;
  /* The one thing on the page that is an action rather than a statement, so it does not wait for
     the whole opening to finish - three and a half seconds before a visitor can press "se
     connecter" is a slow page, however smooth. It arrives while the rule is still drawing. */
  animation: up .9s cubic-bezier(.22, .68, .16, 1) 2.55s forwards;
}

/* The shape the product uses. The app's buttons are 8px-cornered rectangles, and a pill on the
   door would be the only round thing a venue meets before it signs in - the same mistake as the
   wordmark wearing a weight nothing else wears. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 11px 20px;
  border-radius: 8px;
  font: inherit;
  font-weight: 600;
  font-size: 13.5px;
  text-decoration: none;
  cursor: pointer;
  border: 1px solid transparent;
  transition: transform .18s cubic-bezier(.2, .8, .2, 1), background .18s, border-color .18s, filter .18s;
}
.btn:active { transform: translateY(1px); }

.solid {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.solid:hover { filter: brightness(1.08); }

.ghost {
  border-color: var(--line);
  color: var(--ink);
  background: rgba(255, 255, 255, .05);
}
.ghost:hover { border-color: rgba(255, 255, 255, .34); background: rgba(255, 255, 255, .09); }

/* ---------------------------------------------------------------- the app */

/* The mark and the two doors sit in the middle of the screen; the app row lives at the bottom
   rather than being pushed there, which is what left a hole down the centre of a wide window. */
.stores { position: absolute; left: 0; right: 0; bottom: 26px; }

.stores-lead {
  margin: 0 0 12px;
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(154, 167, 181, .8);
}

.store-row { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

.store {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 18px 9px 14px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, .04);
  color: var(--ink);
  text-decoration: none;
  transition: border-color .18s, background .18s, transform .18s;
}
.store:hover { border-color: rgba(255, 255, 255, .32); background: rgba(255, 255, 255, .08); }
.store svg { width: 22px; height: 22px; fill: currentColor; flex: 0 0 auto; }
.store span { display: flex; flex-direction: column; line-height: 1.2; text-align: left; }
.store b { font-size: 13.5px; font-weight: 700; }
.store i { font-size: 11px; font-style: normal; color: var(--muted); }

/* A store button that leads nowhere is worse than no button, so when there is no link yet it stops
   pretending to be one and the reason is written underneath. */
.store.pending { cursor: default; opacity: .55; }
.store.pending:hover { border-color: var(--line); background: rgba(255, 255, 255, .04); }

.soon { margin: 12px 0 0; font-size: 12px; color: var(--muted); }

.foot {
  position: relative;
  padding: 0 24px 22px;
  text-align: center;
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(154, 167, 181, .55);
  opacity: 0;
  animation: up .9s cubic-bezier(.22, .68, .16, 1) 3.45s forwards;
}

/* ---------------------------------------------------------------- small screens */

@media (max-height: 620px) {
  .line { margin-top: 18px; }
  .stores { position: static; margin-top: 30px; }
  body { overflow: auto; }
}

@media (max-width: 420px) {
  .bar { padding: 14px 14px; gap: 8px; }
  .btn { padding: 10px 14px; font-size: 12.5px; }
}

/* Someone who has asked their machine to stop moving things has asked for a reason. The page is
   identical, it simply arrives already finished. */
@media (prefers-reduced-motion: reduce) {
  .sky, .word, .rule, .line, .bar, .stores, .foot { animation: none; }
  .sky { opacity: 1; }
  .word { opacity: 1; transform: none; }
  .rule { transform: scaleX(1); }
  .line, .bar, .stores, .foot { opacity: 1; transform: none; }
}
