/* Refrac's look follows Afloat's: one glass token set for every floating surface, three radii,
   Instrument Sans for text and Plus Jakarta Sans for titles. The page is a lens page, so glass
   is the material throughout: the dial is a ring of it, the lens a disc of it. */

@property --lens-on {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

:root {
  --ink: #0f1720;
  --ink-2: rgba(15, 23, 32, 0.66);
  --ink-3: rgba(15, 23, 32, 0.4);
  --r-sm: 12px;
  --r-md: 18px;
  --r-lg: 24px;
  --glass-bg: rgba(255, 255, 255, 0.55);
  --glass-blur: blur(18px) saturate(1.4);
  --glass-border: rgba(255, 255, 255, 0.6);
  --glass-shadow: 0 8px 32px rgba(15, 23, 32, 0.12);
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --sans: 'Instrument Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --display: 'Plus Jakarta Sans', 'Instrument Sans', system-ui, sans-serif;

  /* Condition colours: the dial's arcs, the chips' dots and the lens tag share them. */
  --myopia: #3b7bea;
  --normal: #2fae74;
  --hyperopia: #e8933a;

  /* The lens: centre, diameter, and how far it has appeared (0 to 1), all set by app.js. */
  --lens-on: 0;
  --lx: 50vw;
  --ly: 45vh;
  --ld: 30vw;

  --dial-r: 240px;
  --dial-h: 170px;
  --ruler-h: 40px; /* the focus ruler under the dial (ruler.css) */
  --ruler-gap: 4px; /* air between the dial and the ruler */
  --edge-r: 6px; /* the slight rounding on the dial's bottom corners */
  --ring: 50px;
  --gap: 20px;

  font-family: var(--sans);
  font-size: 14px;
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: #0f1720;
  overscroll-behavior: none;
}

button {
  font: inherit;
  color: inherit;
}

[hidden] {
  display: none !important;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* No focus ring anywhere: the page shows focus by what it does (the dial turns, the glass moves). */
:focus,
:focus-visible {
  outline: none;
}

/* ---------- glass ---------- */

.glass {
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  box-shadow: var(--glass-shadow);
  border-radius: var(--r-md);
}

.glass-pill {
  background: rgba(255, 255, 255, 0.55);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  backdrop-filter: blur(14px) saturate(1.4);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.6),
    0 4px 16px rgba(15, 23, 32, 0.1);
  border-radius: 999px;
}

/* ---------- scene ---------- */

.stage {
  position: fixed;
  inset: 0;
  overflow: hidden;
}

/* The eye's view fills the screen; eye.js draws it at up to twice the CSS pixel density. */
.eye {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.eye.is-ready {
  opacity: 1;
}

/* At a swap, a still copy of the outgoing scene covers the view in full, then fades out over the
   next one (app.js showScene). */
.eye-fade {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.45s ease;
}

.eye-fade.is-on {
  opacity: 1;
  transition: none;
}

/* Without WebGL2 the scene shows as a plain, sharp image (app.js). */
img.eye {
  object-fit: cover;
}

/* ---------- lens ---------- */

.lens {
  position: absolute;
  left: var(--lx);
  top: var(--ly);
  width: var(--ld);
  height: var(--ld);
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(calc(0.85 + 0.15 * var(--lens-on)));
  opacity: var(--lens-on);
  pointer-events: none;
  cursor: grab;
  touch-action: none;
  /* A clean glass with no glare: one crisp rim and a soft shadow under it. The bend along the inside
     of the rim is drawn with the scene (eye.js lensBend). */
  box-shadow:
    0 0 0 1.5px rgba(255, 255, 255, 0.85),
    inset 0 0 0 1px rgba(255, 255, 255, 0.3),
    0 18px 48px rgba(15, 23, 32, 0.28);
}

body.lens-on .lens {
  pointer-events: auto;
}

body.lens-dragging .lens {
  cursor: grabbing;
}


/* ---------- top ---------- */

/* The wordmark, with the project's one line under it, in the top-left corner. */
.top {
  position: fixed;
  top: 0;
  left: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 7px;
  padding: 22px var(--gap) 0;
  pointer-events: none;
}

.tagline {
  margin: 0;
  font-size: 13px;
  line-height: 1.2;
  letter-spacing: 0.015em;
  color: var(--ink-2);
  transition: color 0.4s ease;
}

.top > * {
  pointer-events: auto;
}

/* The credit joins the line on a phone, and blurs with it (app.js farUpdate). */
.tagline-by {
  display: none;
}

.tagline-by a {
  color: var(--ink);
  font-weight: 600;
  text-underline-offset: 2px;
}

.top-on-dark .tagline-by a {
  color: #fff;
}

/* Top right: the scene's name, then a round glass button for another scene. The name reads in
   dark ink on bright skies and in white on dark ones, as the wordmark does (app.js toneTop). */
.scene-bar {
  position: fixed;
  top: 32px;
  right: var(--gap);
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 10px;
}

.scene-title {
  margin: 0;
  font: 600 15px/1.2 var(--display);
  letter-spacing: 0.01em;
  color: var(--ink);
  white-space: nowrap;
  transition: color 0.4s ease, opacity 0.4s ease;
}

.scene-on-dark .scene-title {
  color: #fff;
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.35);
}

/* Clear glass: the scene shows through it, lightly blurred, with a bright rim and a soft shadow. */
.next {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.16);
  -webkit-backdrop-filter: blur(6px) saturate(1.6);
  backdrop-filter: blur(6px) saturate(1.6);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.75),
    inset 0 1px 1px rgba(255, 255, 255, 0.5),
    0 2px 8px rgba(15, 23, 32, 0.14);
  cursor: pointer;
  transition: background 0.2s ease, transform 0.15s var(--ease-out);
}

.scene-on-dark .next {
  color: #fff;
}

.next:hover {
  background: rgba(255, 255, 255, 0.3);
}

.next:active {
  transform: scale(0.97);
}

/* While the next scene is still loading. */
.next[aria-busy='true'] {
  cursor: progress;
  opacity: 0.6;
}

.next svg {
  width: 14px;
  height: 14px;
  filter: drop-shadow(0 1px 1px rgba(255, 255, 255, 0.35));
}

.scene-on-dark .next svg {
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.45));
}

/* The words in the picture (app.js farUpdate): the wordmark and its line (with the credit in it on a
   phone), the scene's name and its button blur as the horizon does at the dial's power. Where the
   glass covers one, it fades out inside the glass's circle as the glass fades in, and the sharp
   copy below shows there instead. */
.words-blurred .brand svg,
.words-blurred .brand-name,
.words-blurred .tagline,
.words-blurred .scene-title,
.words-blurred .next {
  filter: blur(var(--far-blur));
}

.words-blurred .lens-over {
  -webkit-mask-image: radial-gradient(circle at var(--hx) var(--hy), rgba(0, 0, 0, calc(1 - var(--lens-on))) calc(var(--ld) / 2 - 0.5px), #000 calc(var(--ld) / 2 + 0.5px));
  mask-image: radial-gradient(circle at var(--hx) var(--hy), rgba(0, 0, 0, calc(1 - var(--lens-on))) calc(var(--ld) / 2 - 0.5px), #000 calc(var(--ld) / 2 + 0.5px));
}

/* The sharp copy covers the screen and shows only inside the glass, as the glass fades in. */
.words-sharp {
  position: fixed;
  inset: 0;
  z-index: 5;
  display: none;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(circle at var(--lx) var(--ly), rgba(0, 0, 0, var(--lens-on)) calc(var(--ld) / 2 - 0.5px), transparent calc(var(--ld) / 2 + 0.5px));
  mask-image: radial-gradient(circle at var(--lx) var(--ly), rgba(0, 0, 0, var(--lens-on)) calc(var(--ld) / 2 - 0.5px), transparent calc(var(--ld) / 2 + 0.5px));
}

.words-blurred .words-sharp {
  display: block;
}

.words-blurred .words-sharp .brand svg,
.words-blurred .words-sharp .brand-name,
.words-blurred .words-sharp .tagline,
.words-blurred .words-sharp .scene-title,
.words-blurred .words-sharp .next {
  filter: none;
  -webkit-mask-image: none;
  mask-image: none;
}

/* ---------- dial ---------- */

/* The dock at the foot: the top of the dial, on the focus ruler, on the bottom edge of the screen. */
.dock {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
  /* the hollow's glass, the ring's when it has focus, and the ring's outer edge */
  --hub-bg: rgba(255, 255, 255, 0.72);
  --ring-focus-bg: rgba(255, 255, 255, 0.72);
  --dial-edge: rgba(255, 255, 255, 0.85);
}

/* Over a dark scene the dial and the ruler turn to smoked glass with white ink, so they sit in the
   scene instead of glaring on it (app.js toneTop measures the render behind the dial). The
   condition colours stay. */
.dock-on-dark .dock {
  --ink: #fff;
  --ink-2: rgba(255, 255, 255, 0.74);
  --ink-3: rgba(255, 255, 255, 0.45);
  --glass-bg: rgba(14, 18, 22, 0.36);
  --hub-bg: rgba(14, 18, 22, 0.5);
  --ring-focus-bg: rgba(14, 18, 22, 0.55);
  --dial-edge: rgba(255, 255, 255, 0.4);
  color: var(--ink);
}

/* A swap into a scene of the other tone changes the glass and the ink with the dissolve. */
.dial-ring,
.dial-hub {
  transition: background 0.45s ease;
}

.dial-kind,
.readout,
.tip,
.tip b {
  transition: color 0.45s ease;
}

/* Only the top of the ring shows, about 145 degrees of it, with room in the bowl for the
   condition, the power and one short sentence. */
.control {
  position: relative;
  width: calc(var(--dial-r) * 2);
  height: var(--dial-h);
  overflow: hidden;
  /* ruler.js RULER_roundDial clips this to the dial's outline, its bottom corners rounded to match
     the ruler's */
}

.dial {
  position: absolute;
  left: 0;
  top: 0;
  width: calc(var(--dial-r) * 2);
  height: calc(var(--dial-r) * 2);
  border-radius: 50%;
  touch-action: none;
  cursor: grab;
  pointer-events: auto;
  -webkit-mask: radial-gradient(circle closest-side, transparent calc(100% - var(--ring)), #000 calc(100% - var(--ring) + 0.5px));
  mask: radial-gradient(circle closest-side, transparent calc(100% - var(--ring)), #000 calc(100% - var(--ring) + 0.5px));
}

.dial:focus-visible {
  outline: none;
}

.dial:focus-visible .dial-ring {
  background: var(--ring-focus-bg);
}

.dial.is-dragging {
  cursor: grabbing;
}

.dial-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
}

.dial-ticks {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.dial-edge {
  fill: none;
  stroke: var(--dial-edge);
  stroke-width: 1.5;
}

.dial-tick {
  stroke: var(--ink-2);
  stroke-width: 1.4;
  stroke-linecap: round;
}

.dial-band {
  fill: none;
  stroke-width: 3;
  stroke-linecap: round;
  opacity: 0.85;
}

.dial-band.myopia {
  stroke: var(--myopia);
}

.dial-band.normal {
  stroke: var(--normal);
}

.dial-band.hyperopia {
  stroke: var(--hyperopia);
}

.dial-labels > span {
  position: absolute;
  transform: translate(-50%, -50%);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.015em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  white-space: nowrap;
  pointer-events: none;
}

.dial-labels > span.is-now {
  color: var(--ink);
  font-weight: 700;
  font-size: 15px;
}

/* The notch at the top: the power under it is the power in use. */
.dial-notch {
  position: absolute;
  left: 50%;
  top: 0;
  width: 0;
  height: 0;
  transform: translateX(-50%);
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-top: 9px solid var(--ink);
}

/* The hollow of the dial: one even disc of glass, frostier than the ring, so the centre reads as a
   surface and the scene does not show through it like a protractor. It stays still while the ring
   turns, and lets drags through to the dial. */
.dial-hub {
  position: absolute;
  left: var(--ring);
  top: var(--ring);
  width: calc((var(--dial-r) - var(--ring)) * 2);
  height: calc((var(--dial-r) - var(--ring)) * 2);
  border-radius: 50%;
  background: var(--hub-bg);
  -webkit-backdrop-filter: blur(24px) saturate(1.4);
  backdrop-filter: blur(24px) saturate(1.4);
  pointer-events: none;
}

/* The condition, inside the dial just above the readout: Myopia, Perfect vision or Hyperopia. */
.dial-kind {
  position: absolute;
  left: 50%;
  bottom: 40px;
  transform: translateX(-50%);
  white-space: nowrap;
  font: 700 16px/1.2 var(--display);
  letter-spacing: -0.005em;
  color: var(--ink);
  pointer-events: none;
}

.readout {
  position: absolute;
  left: 50%;
  bottom: 64px;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 7px 4px 8px;
  white-space: nowrap;
  font: 700 26px/1 var(--display);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

/* ---------- wordmark ---------- */

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--ink);
  transition: color 0.4s ease;
}

/* Over a dark scene the wordmark and its line turn white; app.js measures the render behind them. */
.top-on-dark .brand {
  color: #fff;
}

.top-on-dark .tagline {
  color: rgba(255, 255, 255, 0.8);
}

.top-on-dark .top {
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.35);
}

/* The icon as tall as the wordmark and its line together. */
.brand svg {
  flex: none;
  width: 50px;
  height: 50px;
}

.brand-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

.brand-name {
  font: 800 24px/1 var(--display);
  letter-spacing: 0.1em;
}

/* What the condition means, at the foot of the dial's bowl, under the header. */
.tip {
  position: absolute;
  left: 50%;
  bottom: 18px;
  width: max-content;
  max-width: 300px;
  margin: 0;
  transform: translateX(-50%);
  font-size: 13px;
  line-height: 1.4;
  letter-spacing: 0.015em;
  color: var(--ink-2);
  text-align: center;
  text-wrap: balance;
  pointer-events: none;
}

.tip b {
  font-weight: 600;
  color: var(--ink);
}

/* ---------- credit ---------- */

/* The maker's credit in the bottom-right corner, as Afloat carries it. */
.madeby {
  position: fixed;
  right: var(--gap);
  bottom: 16px;
  margin: 0;
  font-size: 12px;
  letter-spacing: 0.03em;
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 1px 8px rgba(15, 23, 32, 0.55);
}

.madeby a {
  color: #ffffff;
  text-underline-offset: 2px;
}

/* ---------- tour ---------- */

/* A small glass card that sits next to what it talks about (tour.js): on the dial, its tail
   pointing down at it, or under the wordmark. The tour keeps all three cards on the dial. */
.tour {
  position: fixed;
  left: 50%;
  z-index: 20;
  width: min(360px, calc(100vw - 2 * var(--gap)));
  padding: 18px 20px 16px;
  transform: translateX(-50%);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.78);
  text-align: center;
  outline: none;
  transition: opacity 0.22s ease;
}

.tour[data-anchor='top'] {
  top: 104px;
}

.tour[data-anchor='dial'] {
  bottom: calc(var(--dial-h) + var(--ruler-gap) + var(--ruler-h) + env(safe-area-inset-bottom, 0px) + 18px);
}

/* The tail: a triangle that hangs below the card only, in the card's own glass, so nothing of it
   shows through the card. */
.tour[data-anchor='dial']::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 100%;
  width: 16px;
  height: 8px;
  transform: translateX(-50%);
  background: rgba(255, 255, 255, 0.78);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}

.tour.is-moving {
  opacity: 0;
}

/* tour.js gives the words the height of the tallest card; shorter ones sit in its middle. */
.tour-text {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.tour-title {
  margin: 0 0 6px;
  font: 700 19px/1.2 var(--display);
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.tour-body {
  max-width: 300px;
  margin: 0 auto;
  font-size: 14.5px;
  line-height: 1.45;
  letter-spacing: 0.015em;
  color: var(--ink-2);
  text-wrap: pretty;
}

.tour-body b {
  font-weight: 600;
  color: var(--ink);
}

/* The glass's line fades in with the glass itself. */
.tour-glass-line {
  margin: 4px auto 0;
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: 0.015em;
  color: var(--ink);
  opacity: 0;
  transform: translateY(4px);
  transition:
    opacity 0.5s ease,
    transform 0.5s var(--ease-out);
}

.tour-glass-line.is-on {
  opacity: 1;
  transform: none;
}

/* One button, centred under the dots. */
.tour-next {
  display: block;
  min-width: 112px;
  height: 38px;
  margin: 12px auto 0;
  padding: 0 22px;
  border: 0;
  border-radius: 999px;
  background: var(--ink);
  color: #ffffff;
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.015em;
  cursor: pointer;
}

.tour-dots {
  display: flex;
  justify-content: center;
  gap: 7px;
  margin-top: 14px;
}

.tour-dots i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ink-3);
  transition: background 0.2s ease, transform 0.2s ease;
}

.tour-dots i.is-on {
  background: var(--ink);
  transform: scale(1.15);
}

/* ---------- smaller screens ---------- */

@media (max-width: 860px) {
  :root {
    --dial-r: 170px;
    --dial-h: 150px;
    --ring: 44px;
    --gap: 16px;
  }

  .dial-kind {
    bottom: 34px;
    font-size: 14px;
  }

  .readout {
    bottom: 54px;
    font-size: 22px;
  }

  .tip {
    bottom: 14px;
    max-width: 230px;
    font-size: 12px;
  }

  /* The dial takes the foot of a narrow screen, so the credit moves up under Next scene. */
  .madeby {
    top: 76px;
    bottom: auto;
  }
}

/* Phones: the top holds the wordmark, with the credit in its line; the scene's name and its
   button sit centred just above the dial, in reach of a thumb. */
@media (max-width: 600px) {
  .top {
    padding-top: max(18px, env(safe-area-inset-top, 0px));
  }

  /* the top runs centred across the screen: the logo shrinks onto the line with REFRAC, and the
     line of words sits centred under both */
  .top {
    right: 0;
    align-items: center;
  }

  .brand {
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    column-gap: 8px;
    row-gap: 6px;
  }

  .brand-text {
    display: contents;
  }

  .brand svg {
    width: 24px;
    height: 24px;
  }

  .tagline {
    flex-basis: 100%;
    text-align: center;
  }

  .brand-name {
    font-size: 20px;
  }

  .tagline {
    font-size: 12px;
  }

  /* the credit joins the line under the wordmark: "Corrective lenses visualized by @anirudhux" */
  .tagline-by {
    display: inline;
  }

  .madeby {
    display: none;
  }

  .scene-bar {
    top: auto;
    right: auto;
    left: 50%;
    bottom: calc(var(--dial-h) + var(--ruler-gap) + var(--ruler-h) + env(safe-area-inset-bottom, 0px) + 12px);
    transform: translateX(-50%);
    gap: 8px;
  }

  .scene-title {
    font-size: 14px;
  }

  /* down by the dial the scene's name and its button are the way to the next scene, so they stay
     sharp at every power */
  .words-blurred .scene-title,
  .words-blurred .next {
    filter: none;
    -webkit-mask-image: none;
    mask-image: none;
  }

  /* the tour's card stands in that same place above the dial */
  .touring .scene-bar {
    visibility: hidden;
  }
}

/* The dial and the ruler stay clear of a phone's home bar. */
.dock {
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* ---------- the first load ----------
   While the first scene's files come in, a ring in the middle counts them from 0 to 100% (app.js
   loading); app.js shows it only when the load takes over 250 ms, so a quick load never flashes it. The scene fades in, then the dial rises
   into place, then the ruler, then, on a first visit, the tour. body.intro holds them back until
   app.js adds is-loaded, dial-in and ruler-in in turn. */
.loader {
  position: fixed;
  left: 50%;
  top: 50%;
  z-index: 30;
  width: 72px;
  height: 72px;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  color: #fff;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.loader.is-on {
  opacity: 1;
}

.loader svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  rotate: -90deg; /* the count starts at the top */
}

.loader circle {
  fill: none;
  stroke-width: 2;
}

.loader-track {
  stroke: rgba(255, 255, 255, 0.16);
}

.loader-arc {
  stroke: #fff;
  stroke-dasharray: 100;
  stroke-dashoffset: calc(100 - var(--p, 0));
  transition: stroke-dashoffset 0.3s ease;
}

.loader-pct {
  font: 600 14px/1 var(--sans);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

.intro .eye {
  transition-duration: 0.9s;
}

.intro .control,
.intro .mode,
.intro .ruler,
.intro .madeby,
.intro:not(.is-loaded) .scene-bar {
  opacity: 0;
}

.is-loaded .scene-bar {
  animation: fade-in 0.9s ease both;
}

.dial-in .control,
.dial-in .mode {
  animation: rise-in 0.8s var(--ease-out) both;
}

.ruler-in .ruler,
.ruler-in .madeby {
  animation: rise-in 0.7s var(--ease-out) both;
}

.tour {
  animation: rise-in 0.6s var(--ease-out);
}

/* Both ends spelled out: under .intro the pieces rest at opacity 0, so an implied end would stay 0. */
@keyframes rise-in {
  from {
    opacity: 0;
    translate: 0 24px;
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .is-loaded .scene-bar,
  .dial-in .control,
  .dial-in .mode,
  .ruler-in .ruler,
  .ruler-in .madeby,
  .tour {
    animation: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .eye,
  .tour,
  .tour-glass-line,
  .tour-dots i {
    transition: none;
  }
}
