/* Landing page. Nothing here is shared with the trainer's style.css on purpose: the trainer is a
   dense tool UI, this is a poster, and mixing the two would mean fighting the same selectors. */

* { box-sizing: border-box; }

:root {
  --ink: #0a0806;
  --parchment: #efe3c6;
  --parchment-dim: #b7a684;
  --gold: #d8ac53;
  --gold-bright: #f4d489;
}

html, body { height: 100%; }

body {
  margin: 0;
  min-height: 100%;
  background: var(--ink);
  color: var(--parchment);
  font-family: "Palatino Linotype", "Book Antiqua", Palatino, Georgia, "Times New Roman", serif;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* `safe`, and it is load-bearing on a phone. The poster is centred in the window, which is right
     while it fits. When it does not, plain `center` splits the overflow across *both* edges, and
     the half that goes off the top is unreachable: the scroll range only covers what is below the
     viewport, so the logo and the headline were simply gone. Measured at 375x812, the hero started
     222px above the top of a document that could not be scrolled up. `safe` falls back to
     start-alignment exactly in that case, so a tall page begins at its beginning.
     The trainer had the same bug with `align-items` and the same fix note in HANDOFF.md. */
  justify-content: safe center;
  padding: 40px 24px 96px;
  overflow-x: hidden;
}

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

/* --- The ground ------------------------------------------------------------------------------ */
/*
   What used to be here was the scaffolding for a canvas renderer that drew five painted scenes,
   `.bg`, `.bg-canvas`, `.bg-scrim`, a scrim tuned per scene, and a whole inverted palette for the
   one scene that was light. The renderer was deleted a while ago and none of those elements have
   existed since, so all of it has gone too.

   In its place: three layers of nothing much. The page was flat ink, and flat ink reads as a page
   that has not been finished rather than as a page that is restrained. Depth is what was missing,
   not colour, the navy-and-gold is fine, it just had nothing to sit on.

     body            ink, with a fine grain over it so the dark is a surface and not a void
     body::before    a chessboard, barely there, faded out before it reaches any edge
     body::after     one warm light, drifting

   The board is the only thing here that says "chess" before a word is read, which is why it is the
   layer that gets the middle of the screen. It does not move: a still board reads as solid, and all
   the motion the page needs comes from the light crossing it.
*/

/* The grain sits on `background-color` rather than in a layer of its own, so it is under both
   pseudo-elements. It is doing more work than it looks like it is, without it the gradients below
   band visibly on a dark screen. */
body {
  background-color: var(--ink);
  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='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.038'/%3E%3C/svg%3E");
}

body::before,
body::after {
  content: '';
  position: fixed;
  z-index: 0;
  pointer-events: none;
}

/* The board. Squares from a repeating conic gradient rather than an image, and masked to an ellipse
   over the hero so it never reaches a corner, a checkerboard that runs to the edge of the window
   is a background pattern, and this has to read as a board the page is standing on. */
body::before {
  inset: 0;
  background-image: repeating-conic-gradient(
    rgba(216, 172, 83, 0.055) 0% 25%, transparent 0% 50%
  );
  background-size: 148px 148px;
  background-position: 50% 0;
  -webkit-mask-image: radial-gradient(ellipse 76% 60% at 50% 34%, #000 10%, transparent 70%);
  mask-image: radial-gradient(ellipse 76% 60% at 50% 34%, #000 10%, transparent 70%);
}

/* One warm light behind the mark, crossing slowly. Inset well past the viewport so it can travel
   without an edge ever coming into view, and moved with `transform` alone so the browser can
   composite it instead of repainting a full-screen gradient every frame. */
body::after {
  inset: -35%;
  background: radial-gradient(closest-side,
    rgba(216, 172, 83, 0.17) 0%,
    rgba(216, 172, 83, 0.06) 42%,
    transparent 72%);
  animation: hearth 26s ease-in-out infinite alternate;
  will-change: transform;
}

@keyframes hearth {
  from { transform: translate3d(-7%, -4%, 0) scale(1); }
  to { transform: translate3d(7%, 5%, 0) scale(1.14); }
}

/* --- Arriving --------------------------------------------------------------------------------- */
/*
   Everything in the hero rises into place once, in the order you would read it. Staggered rather
   than simultaneous, because a page where every element appears at the same instant reads as a page
   that was loaded, and one where they arrive in sequence reads as a page that was composed.
*/
@keyframes rise {
  from { opacity: 0; transform: translateY(15px); }
  to { opacity: 1; transform: none; }
}

.hero > * { animation: rise 620ms cubic-bezier(0.2, 0.8, 0.3, 1) both; }

.hero-logo { animation-delay: 40ms; }
.eyebrow { animation-delay: 140ms; }
.tagline { animation-delay: 300ms; }
.blurb { animation-delay: 380ms; }
.cta { animation-delay: 470ms; }
.cta-note { animation-delay: 515ms; }
.cta-aside { animation-delay: 570ms; }

/* The cards come in one at a time rather than as a block, so the row reads left to right like the
   three steps it describes. */
.features { animation: none; }
.features li { animation: rise 620ms cubic-bezier(0.2, 0.8, 0.3, 1) both; }
.features li:nth-child(1) { animation-delay: 620ms; }
.features li:nth-child(2) { animation-delay: 700ms; }
.features li:nth-child(3) { animation-delay: 780ms; }

/* None of this is load-bearing, and a perpetual light crossing the screen is the first thing to go
   for anyone who has asked for less movement. `animation: none` also drops the `both` fill, so the
   hero renders at its resting state rather than staying invisible at the start of an animation that
   is never going to run. */
@media (prefers-reduced-motion: reduce) {
  body::after { animation: none; }
  .hero > *,
  .features li { animation: none; }
}

/* --- Hero ---------------------------------------------------------------------------------- */

.hero {
  position: relative;
  z-index: 1;
  width: min(920px, 100%);
  text-align: center;
}

/* The mark, above the wordmark. Sized by height because it is tall and narrow: a width constraint
   would leave the strokes a fraction of the space they were given. The drop shadow follows the ink
   rather than a box, which is the point of keying the navy plate out of it. */
.hero-logo {
  display: block;
  height: clamp(96px, 13vw, 148px);
  width: auto;
  margin: 0 auto 22px;
  filter: drop-shadow(0 4px 14px rgba(0, 0, 0, 0.55));
}

.eyebrow {
  margin: 0 0 18px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 11px;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--gold-ink);
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.8);
}

.wordmark {
  display: block;
  margin: 0;
  font-size: clamp(52px, 11vw, 122px);
  font-weight: 400;
  line-height: 0.95;
  letter-spacing: 0.055em;
  text-transform: uppercase;
  color: var(--parchment);
  /* A filter rather than `text-shadow`, because the sheen below paints the letters with a
     background and leaves the text itself transparent, and a text-shadow under transparent text
     renders as a solid slab in the shape of the word. `drop-shadow` follows what is actually
     drawn, so it works either way. */
  filter: drop-shadow(0 2px 16px rgba(0, 0, 0, 0.7)) drop-shadow(0 1px 0 rgba(0, 0, 0, 0.5));
  animation:
    rise 620ms cubic-bezier(0.2, 0.8, 0.3, 1) 210ms both,
    sheen 2200ms cubic-bezier(0.32, 0, 0.24, 1) 780ms 1 both;
}

/* One pass of light across the wordmark as the page settles, and then never again. A permanent
   shimmer on a logotype is a screensaver; once is a material catching the light.

   Guarded, because the trick needs `background-clip: text`, without it `color: transparent` would
   simply make the word disappear. Both ends of the gradient are the resting parchment, so wherever
   the animation stops, or if it never runs at all, the wordmark is the colour it should be. */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
  .wordmark {
    background-image: linear-gradient(100deg,
      var(--parchment) 0%,
      var(--parchment) 42%,
      #fffaf0 50%,
      var(--parchment) 58%,
      var(--parchment) 100%);
    background-size: 280% 100%;
    background-position: 0 0;
    background-repeat: no-repeat;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

/*
 * The sweep runs between 100% and 0%, and those two numbers are the whole of the care needed here.
 *
 * With a background wider than its box, a position percentage P puts the image at P × (box − image),
 * so at 280% wide, P = 0% covers 0→280% and P = 100% covers −180%→100%. Every value between them
 * still covers the box. Step outside that range and it does not: the first attempt animated from
 * 130% to −30%, which left the image starting at +54% of the way across the word, and with
 * `no-repeat` the letters before that had no background at all. Since the text itself is
 * transparent, they were not pale. They were gone. The wordmark came to rest reading "IFY".
 *
 * Within the range, the highlight sits off the left edge at 100% and off the right edge at 0%, so
 * this sweeps left to right and settles with the word evenly parchment.
 */
@keyframes sheen {
  from { background-position: 100% 0; }
  to { background-position: 0 0; }
}

.tagline {
  margin: 22px 0 0;
  font-size: clamp(18px, 2.6vw, 26px);
  font-style: italic;
  color: var(--parchment);
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.85), 0 0 22px rgba(0, 0, 0, 0.6);
}

.blurb {
  margin: 16px auto 0;
  max-width: 58ch;
  font-size: clamp(14px, 1.6vw, 16.5px);
  line-height: 1.65;
  color: var(--parchment-dim);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.9);
}

/* --- Buttons ------------------------------------------------------------------------------- */

.cta {
  margin-top: 38px;
  display: flex;
  gap: 16px;
  justify-content: center;
  flex-wrap: wrap;
}

/* The two buttons on this page are the page's only job, so they are sized as such rather than at
   the same weight as a button inside a form. Scoped to `.cta` so the smaller `.btn` everywhere else
   on the poster, and in the tour that sits on top of it, is untouched. */
.cta .btn {
  padding: 17px 42px;
  font-size: 15px;
  letter-spacing: 0.16em;
}

/* Square corners and a hard, un-blurred offset shadow: the same rules the pixel art follows. */
.btn {
  display: inline-block;
  padding: 13px 26px;
  border: 2px solid #1b140d;
  background: #2b2119;
  color: var(--parchment);
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 12.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.55);
  /* Anchors get this for free and `<button>`s do not, and both wear this class now: the trial
     dialog's submit and the tour's closing button are real buttons, so without it the two controls
     that look identical behave differently under the cursor. */
  cursor: pointer;
  transition: transform 90ms steps(2), box-shadow 90ms steps(2), background-color 120ms linear;
}

.btn:hover { background: #3a2d21; }

.btn:active,
.btn:focus-visible {
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.55);
}

.btn:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 3px; }

.btn-primary {
  background: var(--gold);
  border-color: #3d2a10;
  color: #201505;
  font-weight: 700;
}

.btn-primary:hover { background: var(--gold-bright); }

/* Hover is a state a finger cannot leave: iOS applies `:hover` on tap and holds it until something
   else is tapped, so the last button pressed stays lit. It shows worse here than in the app,
   because "Try now" is the only lit thing on a dark poster. The base values are repeated rather
   than the rules above being rewritten, since those are right anywhere a cursor can hover. */
@media (hover: none) {
  .btn:hover { background: #2b2119; }
  .btn-primary:hover { background: var(--gold); }
}

/* The way past the funnel, and the analysis board. Set as text rather than as two more buttons:
   three equal-weight buttons would leave nothing obviously the thing to press. */
.cta-aside {
  margin: 18px 0 0;
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--parchment-dim);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.9);
}

.cta-aside a { color: var(--parchment-dim); text-underline-offset: 3px; }
.cta-aside a:hover { color: var(--gold-bright); }
.aside-sep { margin: 0 10px; opacity: 0.5; }

/* One line under the buttons saying what the first of them does. Set in the body serif rather than
   in the aside's monospace: it is a sentence to be read, where the line below it is a row of links
   to be scanned, and giving them the same treatment made the aside look like a second paragraph. */
.cta-note {
  margin: 16px auto 0;
  max-width: 46ch;
  font-size: 14px;
  line-height: 1.55;
  color: var(--parchment-dim);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.9);
}

/* --- The trial dialog ------------------------------------------------------------------------ */
/*
   "Try now" opens this: a username, then a scan running in front of you. It borrows the tour's
   entrance wholesale, see tour.css for why it is done in CSS rather than on a timer, and is a
   fraction of its size because there is no board in it.

   Scoped under `.trial-*`, and the buttons in it are this page's own `.btn`, minus the oversized
   `.cta .btn` treatment, which is reserved for the two on the poster itself.
*/
.trial-dialog {
  position: relative;
  width: min(560px, calc(100vw - 32px));
  max-height: calc(100dvh - 40px);
  padding: 30px 32px 26px;
  border: 1px solid rgba(216, 172, 83, 0.34);
  border-radius: 16px;
  background:
    radial-gradient(120% 90% at 0% 0%, rgba(216, 172, 83, 0.10), transparent 62%),
    #100d0a;
  color: var(--parchment);
  font-family: "Palatino Linotype", "Book Antiqua", Palatino, Georgia, "Times New Roman", serif;
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.7);
  overflow-y: auto;

  opacity: 0;
  transform: translateY(10px) scale(0.985);
  transition:
    opacity 240ms ease,
    transform 300ms cubic-bezier(0.2, 0.9, 0.28, 1),
    overlay 300ms allow-discrete,
    display 300ms allow-discrete;
}

.trial-dialog[open] { opacity: 1; transform: none; }

@starting-style {
  .trial-dialog[open] { opacity: 0; transform: translateY(10px) scale(0.985); }
}

.trial-dialog::backdrop {
  background: rgba(4, 3, 2, 0.72);
  backdrop-filter: blur(3px);
  opacity: 0;
  transition:
    opacity 260ms ease,
    overlay 260ms allow-discrete,
    display 260ms allow-discrete;
}

.trial-dialog[open]::backdrop { opacity: 1; }

@starting-style {
  .trial-dialog[open]::backdrop { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .trial-dialog {
    transform: none;
    transition: opacity 120ms linear, overlay 120ms allow-discrete, display 120ms allow-discrete;
  }
  @starting-style {
    .trial-dialog[open] { transform: none; }
  }
}

.trial-close {
  position: absolute;
  top: 10px;
  right: 12px;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 8px;
  background: none;
  color: var(--parchment-dim);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

.trial-close:hover { color: var(--parchment); border-color: rgba(216, 172, 83, 0.4); }
.trial-close:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.trial-eyebrow {
  margin: 0 0 8px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 10.5px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--gold);
}

.trial-title {
  margin: 0 0 12px;
  font-size: clamp(22px, 3.4vw, 28px);
  font-weight: 400;
  letter-spacing: 0.01em;
}

.trial-lede {
  margin: 0 0 20px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--parchment-dim);
}

.trial-lede-tight { margin: 16px 0 0; font-size: 13.5px; }

/* Which site the games come from. Two buttons rather than a <select>, because there are exactly
   two and both should be readable without opening anything. */
.trial-seg {
  display: flex;
  gap: 0;
  margin-bottom: 14px;
  border: 1px solid rgba(216, 172, 83, 0.3);
  border-radius: 8px;
  overflow: hidden;
}

.trial-seg button {
  flex: 1;
  padding: 10px 8px;
  border: 0;
  background: transparent;
  color: var(--parchment-dim);
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 11.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 140ms linear, color 140ms linear;
}

.trial-seg button + button { border-left: 1px solid rgba(216, 172, 83, 0.3); }
.trial-seg button:hover { background: rgba(216, 172, 83, 0.09); color: var(--parchment); }
.trial-seg button[aria-pressed="true"] { background: rgba(216, 172, 83, 0.2); color: var(--gold-bright); }
.trial-seg button:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }

.trial-form { display: flex; gap: 10px; flex-wrap: wrap; }

.trial-input {
  flex: 1 1 200px;
  min-width: 0;
  padding: 13px 14px;
  border: 1px solid rgba(216, 172, 83, 0.3);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.35);
  color: var(--parchment);
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 14px;
}

.trial-input::placeholder { color: rgba(183, 166, 132, 0.5); }
.trial-input:focus { outline: 2px solid var(--gold); outline-offset: 1px; }

/* Square corners on the poster's buttons and a rounded field beside one would fight, so the button
   in this row follows the field rather than the poster. */
.trial-form .btn { border-radius: 8px; padding: 13px 22px; }

.trial-error {
  margin: 14px 0 0;
  font-size: 14px;
  line-height: 1.5;
  color: #e8836f;
}

.trial-foot {
  margin: 18px 0 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: rgba(183, 166, 132, 0.72);
}

/* --- The scan pane -------------------------------------------------------------------------- */

.trial-bar {
  height: 6px;
  margin: 4px 0 12px;
  border-radius: 3px;
  background: rgba(239, 227, 198, 0.12);
  overflow: hidden;
}

.trial-bar span {
  display: block;
  width: 0;
  height: 100%;
  background: var(--gold);
  transition: width 400ms ease;
}

/* While the archive is downloading there is nothing to be a fraction of: both platforms send the
   whole thing in one response and report nothing on the way. A bar sitting at zero for ten seconds
   reads as a page that has stopped, so it slides instead of filling, which is the honest shape for
   "working, and I cannot tell you how far yet". It fills properly the moment there is a game count
   to fill against. */
.trial-bar.is-waiting span {
  width: 34%;
  animation: trial-wait 1.5s ease-in-out infinite;
}

@keyframes trial-wait {
  from { transform: translateX(-105%); }
  to { transform: translateX(300%); }
}

@media (prefers-reduced-motion: reduce) {
  .trial-bar.is-waiting span { width: 100%; opacity: 0.3; animation: none; }
}

.trial-progress {
  margin: 0;
  min-height: 1.4em;
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 12.5px;
  letter-spacing: 0.05em;
  color: var(--parchment-dim);
}

.trial-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 18px; }
/* Sized here rather than with `.btn-small`: that class only exists in style.css, which this page
   does not load, so using it would be asking for a size nothing in scope defines. */
.trial-actions .btn { border-radius: 8px; padding: 10px 16px; font-size: 11.5px; }

/* --- Features ------------------------------------------------------------------------------ */

.features {
  margin: 56px 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 18px;
  text-align: left;
}

.features li {
  position: relative;
  padding: 18px 18px 20px;
  border: 1px solid rgba(216, 172, 83, 0.28);
  background: rgba(12, 9, 7, 0.62);
  backdrop-filter: blur(2px);
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--parchment-dim);
  transition:
    transform 180ms cubic-bezier(0.2, 0.8, 0.3, 1),
    border-color 180ms ease,
    box-shadow 180ms ease,
    color 180ms ease;
}

/* The cards are the only things on the page that reward a pointer, so they are the only things
   that answer one. A lift and a warmer edge, no colour change beyond the border, because three
   cards lighting up differently would compete with the two buttons above them. */
.features li:hover {
  transform: translateY(-3px);
  border-color: rgba(216, 172, 83, 0.62);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.55);
  color: var(--parchment);
}

.features li:hover .feat-rune { color: var(--gold-bright); }
.feat-rune { transition: color 180ms ease; }

.features strong {
  display: block;
  margin: 8px 0 6px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 11.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--parchment);
}

.feat-rune {
  font-size: 22px;
  line-height: 1;
  color: var(--gold-ink);
}

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

.foot {
  position: relative;
  z-index: 1;
  margin-top: 44px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  /* Was #7d7059, which measured 4.13:1 against the poster, under AA, on 11px tracked-out
     monospace, which is the least forgiving text on the page. */
  color: #968871;
}

.foot code { color: var(--gold-ink); }

@media (prefers-reduced-motion: reduce) {
  .btn { transition: none; }
  .wordmark { animation: none; }
  .features li { transition: none; }
  .features li:hover { transform: none; }
}

/* --- Document pages ---------------------------------------------------------------------------
 *
 * The poster is one hero centred in the viewport. `/pricing` and `/motifs` are documents: dressed in
 * the same ink, gold and serif, but read from the top downwards. These three rules are what they
 * both need and the poster does not, and they lived in `pricing.css` until the archive became the
 * second page wanting them. A rule two pages share belongs where both can reach it. */

.back-link {
  position: relative;
  z-index: 1;
  align-self: flex-start;
  margin: 0 0 26px 4px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--parchment-dim);
}

.back-link:hover { color: var(--gold-bright); }

/* Not `.wordmark`: that is the logotype, and reusing it would put the brand name's treatment on a
   sentence. Same family and same drop shadow, two-thirds the size, and it wraps. */
.page-title {
  margin: 0;
  font-size: clamp(30px, 5vw, 52px);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: 0.01em;
  color: var(--parchment);
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.85), 0 0 24px rgba(0, 0, 0, 0.55);
}

.section-title {
  margin: 72px 0 22px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--gold-ink);
}

/* The bar for somebody arriving here with a trial behind them, built by `mountTrialReturn` in
   `trial.js`. Its markup is JavaScript rather than part of `landing.html` for the same reason the
   trial dialog's is: this page is a poster, and a poster should not carry hidden furniture for a
   state most of its visitors are never in.

   `position: fixed`, at the bottom, and neither half of that is a style preference.

   `body` is a flex column with `justify-content: safe center`, and the note above on that `safe`
   is the whole reason this is out of flow: an ordinary flex item added at the top makes the column
   taller, the extra height is split across both edges by the centring, and the half above the top
   is unreachable because the scroll range only covers what is below the viewport. Measured, before
   this was fixed: the bar rendered at `top: -30px` with its first line already cut off.

   The bottom rather than the top because that is the edge the centring is not fighting over, and a
   bar there covers the foot of a poster nobody scrolls to rather than the headline everybody
   reads. `body.has-trial-return` below buys back the height it covers. */
.trial-return {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  box-sizing: border-box;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px 16px;
  padding: 12px 20px;
  background: #17110a;
  border-top: 1px solid var(--gold);
  text-align: center;
}

/* Set by `mountTrialReturn`, and only when it actually draws the bar. A fixed element is out of
   flow, so without this the bar sits on top of whatever the poster ends with.

   The height is measured and written back by that function rather than being a number here, and it
   has to be: the bar is one line at 1280px and three at 375px, so it is 70px tall on a desktop and
   143px on a phone. A constant generous enough for the phone wastes half a screen on the desktop,
   and one sized for the desktop, which is what was here first, covers the last 35px of the poster
   on the phone. The fallback is only for the instant before the observer first fires. */
body.has-trial-return { padding-bottom: calc(var(--trial-return-h, 143px) + 24px); }

.trial-return-text {
  margin: 0;
  max-width: 62ch;
  color: var(--parchment);
  font-size: 15px;
  line-height: 1.45;
}

/* Not `flex: 1`. The text beside it already grows, and a button that grows with the viewport is the
   mistake this whole change is undoing on the trainer's own dialog. */
.trial-return-go { flex: none; }
