/* =============================================================================
   pay.angleford.co

   Geometry is expressed in Figma artboard pixels.
   `--u` is one pixel of the 1600x900 desktop artboard (node 67:2464 / 70:2591),
   `--m` is one pixel of the 390x848 mobile artboard (node 70:2604).
   Scaling those two units instead of cropping a flattened export is what keeps
   the character whole on every viewport.
   ========================================================================== */

:root {
  --ink: #170023;
  --ink-90: rgb(23 0 35 / 90%);
  --mist: #e8f4f3;

  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-press: cubic-bezier(0.3, 0, 0.1, 1);

  /* desktop artboard unit, clamped so the artboard always fits the viewport */
  --u: min(calc(100vw / 1600), calc(100dvh / 900));
  /* mobile artboard unit, capped at 1px so tablets stop growing the panel */
  --m: min(1px, calc(100vw / 390));

  /* shadow/glow unit: follows the artboard but never drops below a real pixel */
  --sh: max(1px, var(--u));

}

* {
  box-sizing: border-box;
}

html,
body {
  min-width: 320px;
  min-height: 100%;
  margin: 0;
}

body {
  overflow-x: hidden;
  background: #f2dfe4;
  color: var(--ink);
  font-family: "Roboto Flex", sans-serif;
  text-rendering: optimizeLegibility;
}

button,
a {
  -webkit-tap-highlight-color: transparent;
}

button {
  font: inherit;
}

/* ============================================================ stage + frame */

.stage {
  position: relative;
  isolation: isolate;
  min-height: 100dvh;
  overflow: hidden;
}

.stage__bg {
  position: absolute;
  z-index: 0;
  inset: -2%;
  background: #f2dfe4 url("/assets/bg-gradient.webp") center center / cover no-repeat;
  animation: bg-settle 1400ms var(--ease-out-expo) both;
}

/* The 1600x900 artboard, pinned to the bottom edge so the character always
   stands on the floor of the viewport and any spare height becomes sky. */
.frame {
  position: absolute;
  bottom: 0;
  left: 50%;
  z-index: 1;
  width: calc(1600 * var(--u));
  height: calc(900 * var(--u));
  transform: translateX(-50%);
}

/* ================================================================ character */

.figure-wrap {
  position: absolute;
  bottom: 0;
  left: calc(294.2 * var(--u));
  display: block;
  width: calc(671.2 * var(--u));
  height: calc(891.4 * var(--u));
  animation: figure-enter 900ms var(--ease-out-quint) 60ms both;
}

.figure {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: 50% 100%;
}

/* =================================================================== poster */

.poster {
  position: absolute;
  inset: 0;
  z-index: 2;
}

.poster__glass {
  display: contents;
}

.poster__copy {
  position: absolute;
  top: calc(361 * var(--u));
  left: calc(1084 * var(--u));
  display: flex;
  width: calc(432 * var(--u));
  flex-direction: column;
  align-items: center;
  gap: calc(20 * var(--u));
  text-align: center;
}

.display-title {
  width: 100%;
  margin: 0;
  color: var(--ink);
  font-family: "Roboto Flex", "Arial Narrow", sans-serif;
  font-size: calc(73 * var(--u));
  font-style: oblique 0deg;
  font-weight: 800;
  font-stretch: 48%;
  font-variation-settings: "GRAD" -49, "XOPQ" 93, "XTRA" 468, "YOPQ" 79, "YTAS" 750, "YTDE" -203, "YTFI" 738, "YTLC" 514, "YTUC" 712, "slnt" 0, "wdth" 48;
  letter-spacing: normal;
  line-height: 1;
  text-transform: uppercase;
}

/* one masked line of display type — the inner span slides out from behind it.
   The inline padding widens the clip box sideways so a line that renders a hair
   wider than its column is never sliced; the mask still bites vertically. */
.tline {
  display: block;
  overflow: hidden;
  padding: 0 0.6em 0.14em;
  margin: 0 -0.6em -0.14em;
}

.tline > span {
  display: block;
  white-space: nowrap;
  animation: line-rise 950ms var(--ease-out-expo) 220ms both;
  will-change: transform;
}

.tline:nth-child(2) > span {
  animation-delay: 310ms;
}

.poster__subtitle,
.reveal__subtitle,
.contact-copy {
  margin: 0;
  font-style: normal;
  font-weight: 500;
  font-variation-settings: "GRAD" 0, "XOPQ" 96, "XTRA" 468, "YOPQ" 79, "YTAS" 750, "YTDE" -203, "YTFI" 738, "YTLC" 514, "YTUC" 712, "wdth" 100;
  line-height: 1.2;
}

.poster__subtitle {
  width: max(178px, calc(210 * var(--u)));
  color: rgb(23 0 35 / 90%);
  font-size: max(16px, calc(20 * var(--u)));
  animation: fade-rise 780ms var(--ease-out-expo) 470ms both;
}

.legal {
  position: absolute;
  bottom: calc(24 * var(--u));
  left: calc(25 * var(--u));
  width: calc(365 * var(--u));
  margin: 0;
  color: rgb(23 0 35 / 40%);
  font-size: max(10px, calc(14 * var(--u)));
  font-style: normal;
  font-weight: 500;
  font-variation-settings: "GRAD" 0, "XOPQ" 96, "XTRA" 468, "YOPQ" 79, "YTAS" 750, "YTDE" -203, "YTFI" 738, "YTLC" 514, "YTUC" 712, "wdth" 100;
  line-height: 1.2;
  animation: fade-rise 900ms var(--ease-out-expo) 860ms both;
}

/* ====================================================================== cta */

/* The button is one solid piece under a single lamp above-left: hover raises it
   into the light, press seats it back into the poster. Every layer below obeys
   that one light — that is what keeps it an object rather than a rectangle
   wearing effects. The resting state stays Figma-exact in every state. */

.cta-shell {
  position: absolute;
  top: calc(741 * var(--u));
  left: calc(1125 * var(--u));
  display: grid;
  width: calc(350 * var(--u));
  height: calc(93 * var(--u));
  place-items: center;
  animation: cta-enter 720ms var(--ease-out-expo) 420ms both;
}

.cta {
  --cta-unit: var(--u);
  --lift: 0px;
  --press: 1;
  --lift-duration: 240ms;
  --shadow-duration: 220ms;
  --label-shift-duration: 220ms;
  --glare-half-width: calc(180 * var(--cta-unit));
  --glare-half-height: calc(110 * var(--cta-unit));
  --lens-radius: calc(210 * var(--cta-unit));
  --px: var(--rest-px, calc(159 * var(--cta-unit)));
  --py: var(--rest-py, calc(20 * var(--cta-unit)));

  position: relative;
  display: grid;
  width: calc(318 * var(--u));
  height: calc(61 * var(--u));
  padding: 0 calc(23 * var(--u));
  overflow: hidden;
  border: 0;
  border-radius: calc(14 * var(--u));
  background: var(--ink-90);
  box-shadow:
    0 calc(3 * var(--sh)) calc(9 * var(--sh)) calc(-3 * var(--sh)) rgb(23 0 35 / 34%),
    inset 0 1px 0 rgb(255 255 255 / 12%);
  color: var(--mist);
  cursor: pointer;
  isolation: isolate;
  place-items: center;
  transform: translate3d(0, var(--lift), 0) scale(var(--press));
  transition: transform var(--lift-duration) var(--ease-out-quart), box-shadow var(--shadow-duration) var(--ease-out-quint);
  will-change: transform;
}

/* padding, negative margin and overflow are one unit: together they make the
   grid centre the label's margin box. Drop any one and the label shifts a pixel. */
.cta__label {
  position: relative;
  z-index: 2;
  display: block;
  overflow: hidden;
  padding: 0 0.3em 0.12em;
  margin: 0 -0.3em -0.12em;
  font-family: "Roboto Flex", "Arial Narrow", sans-serif;
  font-size: calc(41 * var(--u));
  font-style: oblique 0deg;
  font-weight: 800;
  font-stretch: 48%;
  font-variation-settings: "GRAD" -49, "XOPQ" 93, "XTRA" 468, "YOPQ" 79, "YTAS" 750, "YTDE" -203, "YTFI" 738, "YTLC" 514, "YTUC" 712, "slnt" 0, "wdth" 48;
  letter-spacing: normal;
  line-height: 1;
  white-space: nowrap;
  transition:
    transform var(--label-shift-duration) var(--ease-out-quart),
    color 220ms var(--ease-out-quint),
    text-shadow 220ms var(--ease-out-quint);
}

.cta__label > span {
  display: block;
  animation: line-rise 820ms var(--ease-out-expo) 700ms both;
}

/* ---------------------------------------------------------------- lighting */

/* Rim, face falloff and the underside line. The face is barely lifted on
   purpose: the button has to stay the only dark mass on that side of the
   poster, so the read comes from the edges, not from a wash. */
.cta__lit {
  position: absolute;
  z-index: 1;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(180deg, rgb(255 255 255 / 6%) 0%, rgb(255 255 255 / 1%) 30%, rgb(0 0 0 / 0%) 54%, rgb(0 0 0 / 22%) 100%);
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / 20%),
    inset 1px 0 0 rgb(255 255 255 / 8%),
    inset 0 -1px 0 rgb(0 0 0 / 65%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 380ms var(--ease-out-quint);
}

/* The broad glare is deliberately larger than the pointer. It reads as light
   travelling through the material, rather than as a small white spot painted
   on top of the button. */
.cta__glare {
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  width: calc(360 * var(--cta-unit));
  height: calc(220 * var(--cta-unit));
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(255 255 255 / 42%) 0%, rgb(220 240 255 / 28%) 32%, rgb(173 208 255 / 11%) 62%, rgb(173 208 255 / 0) 88%);
  mix-blend-mode: plus-lighter;
  opacity: 0;
  pointer-events: none;
  transform: translate3d(calc(var(--px) - var(--glare-half-width)), calc(var(--py) - var(--glare-half-height)), 0);
  transition: opacity 220ms var(--ease-out-quint), transform 120ms var(--ease-out-quint);
}

/* The lens traces only a soft, local edge catch. The focus outline is kept out
   of this layer so it never reads as a second button inside the first one. */
.cta__lens {
  position: absolute;
  z-index: 3;
  inset: 0;
  padding: var(--sh);
  border-radius: inherit;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  transition: opacity 320ms var(--ease-out-quint);
}

.cta__lens > span {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  width: calc(420 * var(--cta-unit));
  height: calc(420 * var(--cta-unit));
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(255 255 255 / 72%) 0%, rgb(236 248 255 / 38%) 26%, rgb(190 224 255 / 7%) 56%, rgb(190 224 255 / 0) 76%);
  transform: translate3d(calc(var(--px) - var(--lens-radius)), calc(var(--py) - var(--lens-radius)), 0);
  transition: transform 120ms var(--ease-out-quint);
}

/* ------------------------------------------------------------------- focus */

/* One clear outer focus outline works on both the pastel poster and the blurred
   reveal. Keeping it outside avoids the nested-rectangle effect. */
.cta:focus-visible {
  outline: calc(2 * var(--sh)) solid rgb(23 0 35 / 72%);
  outline-offset: calc(2 * var(--sh));
}

.cta__ring {
  display: none;
}

/* ------------------------------------------------------------------- hover */

/* `.is-hover` is the touch parity class: a tap lights the button for a beat, so
   nothing here is reachable only with a mouse. Native hover is kept inside a
   fine-pointer media query, preventing sticky touch hover from becoming state. */
.cta.is-hover {
  --lift: calc(-3 * var(--cta-unit));
  --press: 1.008;
  --lift-duration: 360ms;
  --shadow-duration: 300ms;
  --label-shift-duration: 300ms;

  box-shadow:
    0 calc(10 * var(--sh)) calc(22 * var(--sh)) calc(-8 * var(--sh)) rgb(23 0 35 / 40%),
    0 calc(22 * var(--sh)) calc(46 * var(--sh)) calc(-20 * var(--sh)) rgb(23 0 35 / 26%),
    inset 0 1px 0 rgb(255 255 255 / 26%);
}

.cta.is-hover :is(.cta__lit, .cta__glare) {
  opacity: 1;
}

.cta.is-hover .cta__lens {
  opacity: 0.72;
}

.cta.is-hover .cta__label {
  color: #ffffff;
  text-shadow: 0 calc(1 * var(--sh)) calc(2 * var(--sh)) rgb(9 0 16 / 62%);
  transform: translate3d(0, calc(-1 * var(--cta-unit)), 0);
}

/* ------------------------------------------------------------------- press */

/* 90ms in, 260ms back out on the base transition: immediate confirmation, then
   a calm return without a bounce. */
.cta:is(:active, .is-pressed) {
  --lift: calc(1 * var(--cta-unit));
  --press: 0.992;

  box-shadow:
    0 calc(1 * var(--sh)) calc(3 * var(--sh)) calc(-1 * var(--sh)) rgb(23 0 35 / 44%),
    inset 0 calc(2 * var(--sh)) calc(7 * var(--sh)) rgb(0 0 0 / 50%),
    inset 0 -1px 0 rgb(255 255 255 / 8%);
  transition-duration: 90ms, 90ms;
  transition-timing-function: var(--ease-press), var(--ease-press);
}

.cta:is(:active, .is-pressed) .cta__label {
  text-shadow: 0 calc(1 * var(--sh)) calc(2 * var(--sh)) rgb(0 0 0 / 55%);
  transform: translate3d(0, calc(1 * var(--cta-unit)), 0);
  transition-duration: 90ms;
  transition-timing-function: var(--ease-press);
}

/* seated below the rim, the light can no longer rake across the face */
.cta:is(:active, .is-pressed) .cta__glare {
  opacity: 0.45;
}

.cta:is(:active, .is-pressed) .cta__lens {
  opacity: 0.55;
}

@media (hover: hover) and (pointer: fine) {
  .cta:hover {
    --lift: calc(-3 * var(--cta-unit));
    --press: 1.008;
    --lift-duration: 360ms;
    --shadow-duration: 300ms;
    --label-shift-duration: 300ms;

    box-shadow:
      0 calc(10 * var(--sh)) calc(22 * var(--sh)) calc(-8 * var(--sh)) rgb(23 0 35 / 40%),
      0 calc(22 * var(--sh)) calc(46 * var(--sh)) calc(-20 * var(--sh)) rgb(23 0 35 / 26%),
      inset 0 1px 0 rgb(255 255 255 / 26%);
  }

  .cta:hover :is(.cta__lit, .cta__glare) {
    opacity: 1;
  }

  .cta:hover .cta__lens {
    opacity: 0.72;
  }

  .cta:hover .cta__label {
    color: #ffffff;
    text-shadow: 0 calc(1 * var(--sh)) calc(2 * var(--sh)) rgb(9 0 16 / 62%);
    transform: translate3d(0, calc(-1 * var(--cta-unit)), 0);
  }
}

/* Keyboard focus keeps one quiet outer contour. Suppress the inner lens while
   it is visible so a pointer moving over a focused CTA cannot draw two nested
   rounded rectangles. */
.cta:focus-visible .cta__lens {
  opacity: 0;
}

.cta:focus-visible .cta__lit {
  opacity: 0;
}

.cta:focus-visible .cta__glare {
  opacity: 0.68;
}

/* =================================================================== reveal */

.reveal {
  position: absolute;
  z-index: 5;
  inset: 0;
  overflow: hidden;
  backdrop-filter: blur(0);
  -webkit-backdrop-filter: blur(0);
  background: rgb(0 0 0 / 40%);
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 220ms var(--ease-out-quint),
    backdrop-filter 220ms var(--ease-out-quint),
    -webkit-backdrop-filter 220ms var(--ease-out-quint),
    visibility 0s linear 220ms;
  visibility: hidden;
}

.reveal.is-open {
  backdrop-filter: blur(39.65px);
  -webkit-backdrop-filter: blur(39.65px);
  opacity: 1;
  pointer-events: auto;
  transition:
    opacity 380ms var(--ease-out-quint),
    backdrop-filter 620ms var(--ease-out-expo),
    -webkit-backdrop-filter 620ms var(--ease-out-expo),
    visibility 0s;
  visibility: visible;
}

.reveal .frame {
  top: 50%;
  bottom: auto;
  z-index: auto;
  transform: translate(-50%, -50%);
}

.reveal__content {
  position: absolute;
  top: calc(69 * var(--u));
  left: calc(407 * var(--u));
  display: flex;
  width: calc(784 * var(--u));
  flex-direction: column;
  align-items: center;
  gap: calc(43 * var(--u));
  text-align: center;
  transform: translateY(calc(18 * var(--u))) scale(0.99);
  transition: transform 220ms var(--ease-out-quint);
}

.reveal.is-open .reveal__content {
  transform: none;
  transition: transform 620ms var(--ease-out-expo);
}

/* troll head: 250x141 slot, artwork intentionally spills over the headline */
.troll-slot {
  position: relative;
  z-index: 3;
  width: calc(250 * var(--u));
  height: calc(141 * var(--u));
}

.troll-clip {
  position: absolute;
  top: calc(-0.5 * var(--u));
  left: 0;
  display: block;
  width: calc(250 * var(--u));
  height: calc(212 * var(--u));
  overflow: hidden;
  transform-origin: 50% 30%;
}

.troll {
  display: block;
  width: calc(250 * var(--u));
  height: calc(250 * var(--u));
  margin-top: calc(-14.5 * var(--u));
}

.reveal.is-open .troll-clip {
  animation:
    troll-pop 760ms var(--ease-out-expo) 80ms both,
    troll-idle 3800ms ease-in-out 900ms infinite;
}

.reveal__intro {
  position: relative;
  z-index: 2;
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: center;
  gap: calc(12 * var(--u));
}

.reveal__title {
  color: rgb(255 255 255 / 86%);
}

.reveal .tline > span {
  animation: none;
}

.reveal.is-open .tline > span {
  animation: line-rise 880ms var(--ease-out-expo) 240ms both;
}

.reveal.is-open .tline:nth-child(2) > span {
  animation-delay: 330ms;
}

.reveal__subtitle {
  width: calc(544 * var(--u));
  color: rgb(255 255 255 / 70%);
  font-size: max(15px, calc(20 * var(--u)));
}

.reveal.is-open .reveal__subtitle {
  animation: fade-rise 760ms var(--ease-out-expo) 440ms both;
}

.contact-copy {
  position: relative;
  z-index: 1;
  display: flex;
  width: calc(384 * var(--u));
  flex-direction: column;
  gap: calc(12 * var(--u));
  color: rgb(255 255 255 / 70%);
  font-size: max(15px, calc(20 * var(--u)));
}

.contact-copy p {
  margin: 0;
}

.reveal.is-open .contact-copy p {
  animation: fade-rise 720ms var(--ease-out-expo) both;
}

.reveal.is-open .contact-copy p:nth-child(1) { animation-delay: 520ms; }
.reveal.is-open .contact-copy p:nth-child(2) { animation-delay: 590ms; }
.reveal.is-open .contact-copy p:nth-child(3) { animation-delay: 660ms; }

.contact-copy__links {
  color: rgb(255 255 255 / 86%);
}

/* 14px at the reference size — present enough to label the channel, quiet
   enough that the address stays the thing you read. */
.glyph {
  width: 0.7em;
  height: 0.7em;
  margin-right: 0.3em;
  opacity: 0.4;
  transition: opacity 200ms var(--ease-out-quint);
  vertical-align: -0.055em;
}

.contact-copy a:hover .glyph,
.contact-copy a:focus-visible .glyph {
  opacity: 0.75;
}

.contact-copy a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 0.22em;
  transition: color 180ms var(--ease-out-quint), text-decoration-color 180ms var(--ease-out-quint);
}

.contact-copy__hint {
  color: rgb(255 255 255 / 40%);
  font-size: max(12px, calc(14 * var(--u)));
}

.close-shell {
  position: absolute;
  top: calc(783 * var(--u));
  left: calc(516.5 * var(--u));
  display: grid;
  width: calc(565 * var(--u));
  height: calc(77 * var(--u));
  place-items: center;
}

.cta--wide {
  width: calc(549 * var(--u));
}

.reveal .cta__label > span {
  animation: none;
}

.reveal.is-open .close-shell {
  animation: cta-enter 720ms var(--ease-out-expo) 620ms both;
}

.reveal.is-open .cta__label > span {
  animation: line-rise 760ms var(--ease-out-expo) 760ms both;
}

/* =============================================================== keyframes */

@keyframes bg-settle {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes figure-enter {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes line-rise {
  from {
    transform: translateY(118%);
  }

  to {
    transform: translateY(0);
  }
}

@keyframes fade-rise {
  from {
    opacity: 0;
    transform: translateY(calc(14 * var(--u)));
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes cta-enter {
  from {
    opacity: 0;
    transform: translateY(calc(30 * var(--u))) scale(0.94);
  }

  60% {
    opacity: 1;
  }

  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes troll-pop {
  from {
    opacity: 0;
    transform: translateY(calc(26 * var(--u))) scale(0.62) rotate(-9deg);
  }

  to {
    opacity: 1;
    transform: translateY(0) scale(1) rotate(0deg);
  }
}

@keyframes troll-idle {
  0%,
  100% {
    transform: rotate(-1.6deg) translateY(0);
  }

  50% {
    transform: rotate(1.6deg) translateY(calc(-4 * var(--u)));
  }
}

/* ============================================================ mobile layout */

/* Portrait (and square) viewports use the 390x848 mobile artboard.
   Landscape phones keep the poster layout — the panel would not fit their height. */
@media (max-aspect-ratio: 1/1) {
  .stage {
    min-height: 100dvh;
  }

  .stage__bg {
    background-position: 57.1% 50%;
    background-size: 157% 105%;
  }

  .frame {
    left: 0;
    width: 100%;
    height: 100%;
    inset: 0;
    transform: none;
  }

  /* contain guarantees the whole cut-out is on screen at any phone ratio */
  .figure-wrap {
    top: 0;
    bottom: auto;
    left: 0;
    width: 100%;
    height: 100%;
  }

  .figure {
    object-position: 50% 0;
  }

  .poster {
    top: auto;
    display: flex;
    padding: calc(12 * var(--m));
    justify-content: center;
  }

  .poster__glass {
    position: relative;
    z-index: 1;
    display: flex;
    width: 100%;
    max-width: calc(430 * var(--m));
    flex-direction: column;
    align-items: center;
    gap: calc(48 * var(--m));
    padding: calc(24 * var(--m));
    border-radius: calc(24 * var(--m));
    backdrop-filter: blur(24px);
    -webkit-backdrop-filter: blur(24px);
    animation: fade-rise 900ms var(--ease-out-expo) 120ms both;
  }

  /* the soft ellipse that lifts the glass panel off the photo */
  .poster::before {
    position: absolute;
    bottom: calc(-531.5 * var(--m));
    left: 50%;
    z-index: 0;
    width: calc(1983 * var(--m));
    height: calc(1092 * var(--m));
    background: url("/assets/mobile-ellipse.svg") center / 100% 100% no-repeat;
    content: "";
    pointer-events: none;
    transform: translateX(-50%);
  }

  .poster__copy {
    position: static;
    width: 100%;
    gap: calc(20 * var(--m));
  }

  .poster__copy .display-title {
    width: calc(432 * var(--m));
    max-width: none;
    flex-shrink: 0;
    font-size: calc(54 * var(--m));
  }

  .reveal__title {
    width: 100%;
  }

  .poster__subtitle {
    width: calc(210 * var(--m));
    font-size: calc(20 * var(--m));
  }

  .cta-shell {
    position: static;
    width: 100%;
    height: calc(61 * var(--m));
    border-radius: calc(14 * var(--m));
  }

  .cta {
    --cta-unit: var(--m);
    width: 100%;
    height: calc(61 * var(--m));
    padding: 0 calc(23 * var(--m));
    border-radius: calc(14 * var(--m));
  }

  .cta__label {
    font-size: calc(41 * var(--m));
  }

  .legal {
    position: static;
    bottom: auto;
    width: 100%;
    font-size: calc(12 * var(--m));
    text-align: center;
  }

  /* -------------------------------------------------------- mobile reveal */

  .reveal {
    display: flex;
    overflow: hidden auto;
    flex-direction: column;
    padding: calc(28 * var(--m)) calc(18 * var(--m)) calc(30 * var(--m));
  }

  .reveal .frame {
    position: relative;
    transform: none;
    display: flex;
    height: auto;
    flex: 1;
    flex-direction: column;
    gap: calc(48 * var(--m));
    justify-content: center;
    inset: auto;
  }

  .reveal__content {
    position: static;
    width: min(100%, calc(540 * var(--m)));
    margin: 0 auto;
    gap: calc(30 * var(--m));
  }

  .troll-slot {
    width: calc(188 * var(--m));
    height: calc(117 * var(--m));
  }

  .troll-clip {
    top: calc(-0.5 * var(--m));
    width: calc(188 * var(--m));
    height: calc(159 * var(--m));
  }

  .troll {
    width: calc(188 * var(--m));
    height: calc(188 * var(--m));
    margin-top: calc(-11 * var(--m));
  }

  .reveal__intro {
    gap: calc(12 * var(--m));
  }

  .reveal__title {
    font-size: calc(31 * var(--m));
    overflow-wrap: anywhere;
  }

  .reveal .tline > span {
    white-space: normal;
  }

  .reveal__subtitle {
    width: min(100%, calc(480 * var(--m)));
    font-size: calc(18 * var(--m));
  }

  .contact-copy {
    width: min(100%, calc(384 * var(--m)));
    font-size: calc(18 * var(--m));
  }

  .contact-copy__hint {
    font-size: calc(14 * var(--m));
  }

  .close-shell {
    position: static;
    width: min(100%, calc(520 * var(--m)));
    height: auto;
    margin: 0 auto;
  }

  .cta--wide {
    width: 100%;
    min-height: calc(61 * var(--m));
    height: auto;
    padding: calc(10 * var(--m)) calc(23 * var(--m));
  }

  .reveal .cta__label {
    font-size: calc(24 * var(--m));
  }
}

/* Short landscape viewports (a phone on its side): the artboard shrinks faster
   than the legibility floors do, so let the reveal flow and scroll rather than
   letting the contacts collide with the dismiss button. */
@media (min-aspect-ratio: 1/1) and (max-height: 620px) {
  .reveal {
    display: flex;
    overflow: hidden auto;
    flex-direction: column;
    padding: 18px 24px;
    justify-content: center;
  }

  .reveal .frame {
    position: relative;
    display: flex;
    width: 100%;
    height: auto;
    flex-direction: column;
    align-items: center;
    gap: 20px;
    inset: auto;
    transform: none;
  }

  .reveal__content {
    position: static;
    width: min(100%, 784px);
    gap: 14px;
  }

  .troll-slot {
    width: 148px;
    height: 100px;
  }

  .troll-clip {
    top: 0;
    width: 148px;
    height: 125px;
  }

  .troll {
    width: 148px;
    height: 148px;
    margin-top: -9px;
  }

  .reveal__intro {
    gap: 8px;
  }

  .reveal__title {
    width: 100%;
    font-size: 30px;
  }

  .reveal__subtitle {
    width: min(100%, 520px);
    font-size: 15px;
  }

  .contact-copy {
    width: min(100%, 420px);
    gap: 6px;
    font-size: 15px;
  }

  .contact-copy__hint {
    font-size: 12px;
  }

  .close-shell {
    position: static;
    width: auto;
    height: auto;
  }

  .cta--wide {
    width: auto;
    min-height: 44px;
    height: auto;
    padding: 8px 20px;
  }

  .reveal .cta__label {
    font-size: 22px;
  }
}

/* Touch devices scale the artboard down far enough that the Figma button height
   drops under a comfortable tap target; hold a floor without moving anything else. */
@media (pointer: coarse) {
  .cta {
    min-height: 44px;
  }
}

/* ==================================================== pointer affordances */

@media (hover: hover) and (pointer: fine) {
  .contact-copy a:hover {
    color: #fff;
    text-decoration-color: rgb(255 255 255 / 55%);
  }
}

/* ======================================================== reduced motion */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-delay: 0s !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
    transition-delay: 0s !important;
    transition-duration: 0.01ms !important;
  }

  .reveal.is-open .troll-clip {
    animation: none !important;
  }

  /* The button keeps its lighting, colour and shadow changes — those are the
     state — but the glare parks in one place instead of chasing the pointer. */
  .cta {
    --lift: 0px !important;
    --press: 1 !important;
  }

  .cta .cta__label {
    transform: none !important;
  }

  .cta__glare {
    transform: translate3d(calc(52 * var(--u)), calc(-36 * var(--u)), 0) !important;
  }

  .cta__lens > span {
    transform: translate3d(calc(9 * var(--u)), calc(-120 * var(--u)), 0) !important;
  }
}
