/* Cyberpunk TCG lander - /cyberpunk
 *
 * Built to the supplied comp (1920 x 4670). Everything below the site header
 * and above the site footer is this file; the header and footer are the
 * storefront's own, which is the one deliberate departure from the comp.
 *
 * HOW IT SCALES. The comp is a fixed 1920 wide, so every measurement taken
 * off it is expressed as a percentage of that width through --u: one --u is
 * 1% of the design width, and it stops growing once the viewport passes
 * 1920 so the page does not keep inflating on a wide monitor. Type gets
 * clamp() instead, because type that is a pure percentage of the viewport
 * becomes unreadable on a phone long before the layout does.
 *
 * The artwork is the client's, supplied with the comp. Tomorrow is SIL Open
 * Font License (see fonts/OFL.txt), which permits commercial webfont use.
 * The comp's script face, Cyberway Riders, is NOT: it is licensed for
 * personal, non-commercial use only, so it is not served here. The two
 * script lines are build-your-crew.png, artwork rather than font software.
 */

@font-face {
  font-family: "Tomorrow";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/Tomorrow-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "Tomorrow";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/Tomorrow-Italic.woff2") format("woff2");
}
@font-face {
  font-family: "Tomorrow";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/Tomorrow-SemiBold.woff2") format("woff2");
}
@font-face {
  font-family: "Tomorrow";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/Tomorrow-Bold.woff2") format("woff2");
}
@font-face {
  font-family: "Tomorrow";
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url("fonts/Tomorrow-Black.woff2") format("woff2");
}

.cp {
  /* One --u is 1% of the 1920 design width, frozen at 1920. */
  --u: min(1vw, 19.2px);
  --cp-yellow: #fdf008;
  --cp-ink: #ece9f8;
  --cp-band: #14132b;
  --cp-icon: #9897e7;
  /* The tile grid, 1594 wide in the comp, and the 62px gutter between them. */
  --cp-grid: min(83vw, 1594px);
  --cp-gap: clamp(10px, 3.23vw, 62px);
  font-family: "Tomorrow", "Figtree", system-ui, sans-serif;
  display: block;
  overflow-x: clip;
}

.cp img {
  display: block;
  max-width: 100%;
  /* The width/height attributes are on every img so the browser reserves the
     right box before the bytes arrive. Without this they are also taken as
     the RENDERED height, and a 1679px-tall mark lands in a 144px slot. */
  height: auto;
}

/* Shared headings: the heavy yellow line and the letterspaced line under it.
   text-indent cancels the trailing letter-space, which would otherwise push a
   centred line left by half a space. */
.cp-h2 {
  /* Stated, not inherited: components.css sets the site face on `h2` itself,
     and an element selector beats anything .cp passes down. Same below. */
  font-family: "Tomorrow", "Figtree", system-ui, sans-serif;
  margin: 0;
  font-weight: 900;
  /* The comp condenses Tomorrow Black to ~87% and the first build copied it
     with scaleX(0.866). Real readers overruled the comp: at 87%, with the
     keyline fattening every glyph and the glow breathing over the top, the
     gaps closed and the line read as one welded block - the Discord
     screenshot that prompted this. 93% plus a whisker of tracking keeps the
     condensed voice and keeps daylight between letters; the font-size drops
     in step so the line stays about the comp's width. */
  font-size: clamp(24px, 3.95vw, 75px);
  line-height: 1;
  letter-spacing: 0.015em;
  text-indent: 0.015em;
  transform: scaleX(0.93);
  transform-origin: center;
  text-transform: uppercase;
  color: var(--cp-yellow);
  /* The comp's near-black keyline (#010010, sampled off it), THINNED from
     0.055em: paint-order on live text is not honoured by every engine, and
     where it is ignored the stroke straddles the glyph edge - every letter
     grows by half the stroke on each side, straight into the gap. At 0.03em
     the difference between engines is a hairline instead of a weld. */
  -webkit-text-stroke: 0.03em #010010;
  paint-order: stroke fill;
  text-align: center;
}

.cp-sub {
  font-family: "Tomorrow", "Figtree", system-ui, sans-serif;
  margin: clamp(8px, 1.35vw, 26px) 0 0;
  font-weight: 600;
  font-size: clamp(11px, 2.02vw, 39px);
  line-height: 1;
  letter-spacing: 0.475em;
  text-indent: 0.475em;
  text-transform: uppercase;
  color: var(--cp-yellow);
  text-align: center;
}

/* --- Hero ------------------------------------------------------------------
   The plate carries its own yellow zigzag along the bottom edge, so the strip
   below it butts straight on with nothing drawn between. */
.cp-hero {
  position: relative;
  aspect-ratio: 1920 / 751;
  min-height: 240px;
  display: grid;
  place-items: center;
  background: #1b1026 url("banner-copy.jpg") center / cover no-repeat;
}

.cp-hero__logo {
  width: calc(var(--u) * 52.9);
  max-width: 1015px;
  height: auto;
}

/* --- Colour chips ----------------------------------------------------------
   A shallow band the chips stand proud of, above and below. The lift is what
   makes them read as sitting ON the seam rather than inside a box.
   NO PAINT OF ITS OWN (the client's call, 1 Sep): the flat --cp-band strip
   read as a plain purple bar between the divider and the intro, so the
   intro's city backdrop is pulled up behind this row instead - see the
   negative margin on .cp-intro. The chips keep z-index 2 to ride above it. */
.cp-chips {
  position: relative;
  z-index: 2;
  height: clamp(46px, 4.375vw, 84px);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(16px, 10.3vw, 198px);
}

.cp-chips img {
  height: clamp(52px, 6.9vw, 133px);
  width: auto;
  transform: translateY(calc(var(--u) * -0.94));
}

/* --- Intro -----------------------------------------------------------------
   The comp staggers the two blocks: the script sits left, the paragraph
   starts almost half way across, and the Night City mark hangs above and to
   the right of both. Held apart down to tablet, then stacked, because the
   stagger needs width it does not have on a phone. */
.cp-intro {
  position: relative;
  /* The comp opened this section with 13.18u of empty ground - a plain
     purple band below the chips that the client asked to lose (1 Sep).
     6.5u keeps just enough air for the Night City mark to hang in without
     crowding the chips; the mark's own top offset below moves in step.
     THE BACKDROP CLIMBS UP BEHIND THE CHIPS: the chips row paints nothing
     of its own any more, so this section backs under it by exactly the
     row's height and the padding grows by the same amount - the content
     does not move, only the city image reaches the divider. */
  margin-top: calc(clamp(46px, 4.375vw, 84px) * -1);
  padding: calc(var(--u) * 6.5 + clamp(46px, 4.375vw, 84px)) 0 calc(var(--u) * 3.85);
  background: #121332 url("intro-bg.jpg") center / cover no-repeat;
}

.cp-intro__inner {
  position: relative;
  width: var(--cp-grid);
  margin-inline: auto;
}

.cp-intro__crew {
  width: 41.7%;
  margin-left: 16.5%;
  filter: drop-shadow(0 calc(var(--u) * 0.35) calc(var(--u) * 0.3) rgba(8, 4, 20, 0.85));
}

.cp-intro__nc {
  position: absolute;
  /* Twice the comp's size, at the client's ask. It is the only piece of
     Night City branding on the page and the comp had it as a footnote beside
     the headline; at 27% it is a second mark rather than a sticker. Pulled
     further up and left so the extra width does not run past the column or
     collide with the script line under it.
     -4.3u, not -11u: the section's top padding shrank by 6.7u when the
     plain band went, and this offset moves with it so the mark keeps the
     same 2.2u of air below the chips seam. */
  top: calc(var(--u) * -4.3);
  left: 64%;
  width: 22%;
}

.cp-intro__copy {
  font-family: "Tomorrow", "Figtree", system-ui, sans-serif;
  width: 43%;
  margin: calc(var(--u) * 4.375) 0 0 39.2%;
  font-size: clamp(15px, 1.04vw, 20px);
  line-height: 2.1;
  color: var(--cp-ink);
}

.cp-intro__copy em {
  font-style: italic;
}

.cp-intro__arrows {
  width: 48px;
  margin: calc(var(--u) * 4.43) auto 0;
}

/* Straddles the seam into the products section, which is why it is absolute
   and why the section below opens with enough padding to clear it. */
.cp-intro__divider {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(var(--u) * -2.2);
  z-index: 3;
  width: 100%;
}

/* --- Products --------------------------------------------------------------
   Five tiles, three then two, the second row centred under the first. A
   six-column grid does that without a second container: each tile spans two
   columns, and the back row starts one column in. */
.cp-products {
  position: relative;
  overflow: hidden;
  padding: calc(var(--u) * 8.33) 0 calc(var(--u) * 8.9);
  background: linear-gradient(180deg, #35354f 0%, #2b144a 8%, #231139 55%, #1b0d2e 100%);
}

.cp-connect {
  position: relative;
  overflow: hidden;
  padding: calc(var(--u) * 7.76) 0 calc(var(--u) * 9.95);
  background: #010010;
}

/* The circuit plates, which run across the seam between the two sections. */
.cp-circuit {
  position: absolute;
  z-index: 0;
  width: calc(var(--u) * 30.6);
  max-width: 587px;
  pointer-events: none;
  user-select: none;
}

.cp-circuit--pr {
  right: 0;
  bottom: calc(var(--u) * -8);
  width: calc(var(--u) * 34.7);
  max-width: 667px;
}

.cp-circuit--cl {
  left: 0;
  top: calc(var(--u) * -6);
}

.cp-circuit--cr {
  right: 0;
  top: calc(var(--u) * 4);
  width: calc(var(--u) * 34.7);
  max-width: 667px;
  opacity: 0.55;
}

.cp-products > *:not(.cp-circuit),
.cp-connect > *:not(.cp-circuit) {
  position: relative;
  z-index: 1;
}

.cp-tiles {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--cp-gap);
  width: var(--cp-grid);
  margin: calc(var(--u) * 5.36) auto 0;
  list-style: none;
  padding: 0;
}

.cp-tile {
  grid-column: span 2;
  aspect-ratio: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding: 7% 7% 6%;
  /* The frame and its dark fill are one image, so nothing has to reproduce
     the notched border in CSS. */
  background: url("product-backing.png") center / 100% 100% no-repeat;
}

/* Two tiles, centred: start one column in and the gutters fall where the
   front row's do. */
.cp-tile:nth-child(4) {
  grid-column: 2 / span 2;
}

.cp-tile:nth-child(5) {
  grid-column: 4 / span 2;
}

.cp-tile__shot {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  place-items: center;
  width: 100%;
}

.cp-tile__shot img {
  max-width: 92%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

.cp-tile__name {
  font-family: "Tomorrow", "Figtree", system-ui, sans-serif;
  margin: 4% 0 0;
  font-weight: 700;
  font-size: clamp(11px, 2.08vw, 40px);
  line-height: 1.1;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: #fff;
  text-align: center;
}

/* --- Connect ---------------------------------------------------------------
   Four marks on one row. Equal centre-to-centre spacing, not equal gaps: the
   glyphs are different widths, and spacing the boxes would leave the row
   looking lopsided. A fixed slot per mark is what the comp does. */
.cp-social {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: clamp(10px, 4.6vw, 88px);
  margin: calc(var(--u) * 4.53) 0 0;
  padding: 0;
  list-style: none;
}

.cp-social a {
  display: grid;
  place-items: center;
  /* A slot, so the four marks are spaced centre to centre the way the comp
     spaces them. Width only: the HEIGHT has to come from the images. */
  width: clamp(52px, 6.4vw, 123px);
  transition: transform 0.18s ease, filter 0.18s ease;
}

.cp-social img {
  /* Sized off height, because the four glyphs are different shapes and the
     comp lines them up on height. A percentage max-height was the first
     attempt: it resolves to none against a grid area of indefinite height, so
     only max-width bound them and the two TALL narrow marks - Facebook and
     the map pin - came out half as big again as the other two. */
  height: clamp(30px, 5.2vw, 100px);
  width: auto;
  max-width: none;
}

.cp-social a:hover,
.cp-social a:focus-visible {
  transform: translateY(-3px);
  filter: brightness(1.25);
}

@media (prefers-reduced-motion: reduce) {
  .cp-social a {
    transition: none;
  }
  .cp-social a:hover,
  .cp-social a:focus-visible {
    transform: none;
  }
}

/* --- Narrow ----------------------------------------------------------------
   The stagger is the first thing to go: below 900px there is not enough width
   for a 43% column to hold a readable line, so both blocks go full width and
   the Night City mark comes back into the flow above the script. */
@media (max-width: 900px) {
  .cp {
    --cp-grid: 86vw;
  }

  .cp-hero {
    aspect-ratio: 16 / 10;
  }

  .cp-hero__logo {
    width: 82vw;
  }

  .cp-intro {
    /* Same compensation as the base rule: the section backs up under the
       chips row (the inherited negative margin), so the top padding carries
       the row's height on top of its own clamp. */
    padding: calc(clamp(38px, 9vw, 90px) + clamp(46px, 4.375vw, 84px)) 0 clamp(46px, 11vw, 110px);
  }

  .cp-intro__nc {
    position: static;
    /* A third of the viewport, the client's number (31 Aug) - the clamp it
       replaces held the badge at 180px on a phone, nearly half the screen. */
    width: 33vw;
    margin: 0 auto clamp(14px, 4vw, 28px);
  }

  .cp-intro__crew {
    width: 100%;
    margin-left: 0;
  }

  .cp-intro__copy {
    width: 100%;
    margin: clamp(20px, 6vw, 40px) 0 0;
    line-height: 1.85;
  }

  .cp-intro__arrows {
    margin-top: clamp(24px, 7vw, 44px);
  }

  .cp-products {
    padding: clamp(46px, 12vw, 110px) 0 clamp(46px, 12vw, 110px);
  }

  .cp-connect {
    padding: clamp(46px, 12vw, 110px) 0 clamp(52px, 14vw, 120px);
  }

  .cp-tiles {
    margin-top: clamp(26px, 8vw, 60px);
  }

  /* Two up, and the odd one out centres itself on the last row. */
  .cp-tiles {
    grid-template-columns: repeat(4, 1fr);
  }

  .cp-tile,
  .cp-tile:nth-child(4) {
    grid-column: span 2;
  }

  .cp-tile:nth-child(5) {
    grid-column: 2 / span 2;
  }

  .cp-circuit {
    opacity: 0.4;
  }
}

/* --- Connect, between phone and desktop -------------------------------------
   From 561px to 900px the base clamps sit near their floors: at 700px the
   heading ran at 28px, the strapline at 14px and the marks at 36px - a
   desktop layout at phone scale, the client's call (31 Aug). The vw
   coefficients step up through this band only; the phone block below and
   the desktop sizes above both stand exactly where they were. */
@media (min-width: 561px) and (max-width: 900px) {
  .cp-connect .cp-h2 {
    font-size: clamp(28px, 5.6vw, 50px);
  }

  .cp-connect .cp-sub {
    font-size: clamp(15px, 3vw, 27px);
  }

  .cp-social {
    gap: clamp(24px, 7vw, 63px);
  }

  .cp-social a {
    width: clamp(64px, 9.6vw, 86px);
  }

  .cp-social img {
    height: clamp(44px, 7.8vw, 70px);
  }
}

@media (max-width: 560px) {
  .cp-tiles {
    grid-template-columns: repeat(2, 1fr);
  }

  .cp-tile,
  .cp-tile:nth-child(4),
  .cp-tile:nth-child(5) {
    grid-column: span 2;
  }

  .cp-tile__name {
    font-size: clamp(13px, 4.4vw, 22px);
  }

  .cp-sub {
    font-size: clamp(10px, 2.9vw, 16px);
    letter-spacing: 0.3em;
    text-indent: 0.3em;
  }

  .cp-h2 {
    font-size: clamp(23px, 7.1vw, 40px);
    -webkit-text-stroke-width: 0.025em;
    /* Nearly natural width on a phone: the line wraps here, and condensed
       wrapped lines read worse than two at their own width. */
    transform: scaleX(0.97);
  }
}

/* --- Motion ----------------------------------------------------------------
 * Neon that sits perfectly still reads as a flat picture of neon. Four small
 * pieces, none of them looping fast enough to pull the eye off the copy:
 *
 *   the chips     breathe in their own colour, staggered so the row is never
 *                 all at one brightness
 *   the arrows    bob, which is the one bit of motion with a job - it is the
 *                 scroll cue, and it sits at the fold
 *   the headings  breathe a soft glow, the same yellow as the type
 *   the tiles     light up on hover, which is the only interactive thing on
 *                 the page and until now did not say so
 *
 * All of it is filter and text-shadow. Nothing here animates transform,
 * because the chips are already translated onto the seam and the headings are
 * already scaled to the comp's width, and an animation would overwrite both.
 * Every piece is off under prefers-reduced-motion, at the foot of the file.
 */

@keyframes cp-breathe {
  0%, 100% { filter: drop-shadow(0 0 calc(var(--u) * 0.28) var(--cp-flare)); }
  50%      { filter: drop-shadow(0 0 calc(var(--u) * 0.95) var(--cp-flare)); }
}

.cp-chips img {
  --cp-flare: #fdf008;
  animation: cp-breathe 4.2s ease-in-out infinite;
  will-change: filter;
}

/* Each in its own colour, sampled off the comp's chips, and offset so the
   four are never in step. */
.cp-chips img:nth-child(1) { --cp-flare: #d21e24; animation-delay: 0s; }
.cp-chips img:nth-child(2) { --cp-flare: #e8d81a; animation-delay: 0.55s; }
.cp-chips img:nth-child(3) { --cp-flare: #00a14f; animation-delay: 1.1s; }
.cp-chips img:nth-child(4) { --cp-flare: #2bc3e8; animation-delay: 1.65s; }

@keyframes cp-bob {
  0%, 100% { transform: translateY(0);                       opacity: 0.75; }
  50%      { transform: translateY(calc(var(--u) * 0.55));   opacity: 1; }
}

.cp-intro__arrows {
  animation: cp-bob 1.9s ease-in-out infinite;
}

@keyframes cp-glow {
  /* Halved from 1.5u @ .62: at full breath the halo was wider than the
     letter gaps, so twice a cycle the heading fused into one glowing slab -
     which is the moment the screenshot in the feedback happened to catch.
     Neon should sit ON the sign, not dissolve it. */
  0%, 100% { text-shadow: 0 0 calc(var(--u) * 0.4) rgba(253, 240, 8, 0.25); }
  50%      { text-shadow: 0 0 calc(var(--u) * 0.8) rgba(253, 240, 8, 0.45); }
}

.cp-h2 {
  animation: cp-glow 5.5s ease-in-out infinite;
}

/* The hero mark gets the same treatment, slower, so the top of the page is
   not completely still while the strip below it moves. */
.cp-hero__logo {
  --cp-flare: rgba(253, 240, 8, 0.5);
  animation: cp-breathe 7s ease-in-out infinite;
}

.cp-tile {
  transition: filter 0.25s ease, transform 0.25s ease;
}

/* drop-shadow rather than box-shadow: the frame is a PNG with notched corners
   and transparent ground, so a box shadow would trace a rectangle that is not
   there. drop-shadow follows the alpha, so the glow takes the frame's shape. */
.cp-tile:hover,
.cp-tile:focus-within {
  filter: drop-shadow(0 0 calc(var(--u) * 0.9) rgba(253, 240, 8, 0.55));
  transform: translateY(calc(var(--u) * -0.35));
}

@media (prefers-reduced-motion: reduce) {
  .cp-chips img,
  .cp-intro__arrows,
  .cp-h2,
  .cp-hero__logo {
    animation: none;
  }

  /* The glow stays, at its resting value: it is part of how the page looks,
     and only the movement was the thing being asked about. */
  .cp-chips img { filter: drop-shadow(0 0 calc(var(--u) * 0.3) var(--cp-flare)); }
  .cp-h2 { text-shadow: 0 0 calc(var(--u) * 0.4) rgba(253, 240, 8, 0.25); }
  .cp-intro__arrows { opacity: 0.85; }

  .cp-tile {
    transition: none;
  }

  .cp-tile:hover,
  .cp-tile:focus-within {
    transform: none;
  }
}

/* --- "Coming soon" ---------------------------------------------------------
 * Raised by cyberpunk.js when a visitor clicks anything that goes into the
 * shop. A <dialog> rather than a div: showModal() gives the focus trap, the
 * Esc key, the inert background and the top layer for nothing, and all four
 * are things a hand-rolled overlay gets wrong.
 *
 * Styled to the PAGE, not to the site chrome around it. The visitor is
 * looking at the Cyberpunk takeover when they click, so a purple-and-gold
 * Ravenspire panel would read as a different site interrupting them.
 */

@media (prefers-reduced-motion: reduce) {
}

/* --- The three borrowed from the source ------------------------------------
 *
 * Cyberpunk's own interface has a small vocabulary and uses it sparingly, and
 * the sparingly is the part that gets copied least. Its published design
 * principles say it in as many words: keep the glitch subtle, treat scanlines
 * as optional. Everything below is either idle or one-shot; nothing loops in
 * the reader's eye while they are trying to read.
 */

/* 1. THE TEAR. The game's signature text treatment is a second copy of a word
 *    displaced sideways in a contrasting colour for a few frames. This is that
 *    copy: the same logo file, hue-rotated off the brand yellow towards cyan,
 *    invisible for ten and a half seconds out of eleven.
 *
 *    steps(1, end) rather than an ease, because a glitch does not accelerate.
 *    It is there or it is not. */
@keyframes cp-tear {
  0%, 95.4%  { opacity: 0; transform: translateX(0); }
  95.5%      { opacity: .5;  transform: translateX(calc(var(--u) * -0.45)); }
  96.4%      { opacity: 0; }
  97.0%      { opacity: .38; transform: translateX(calc(var(--u) * 0.36)); }
  97.9%      { opacity: 0; }
  98.4%      { opacity: .28; transform: translateX(calc(var(--u) * -0.2)); }
  99.0%, 100% { opacity: 0; transform: translateX(0); }
}

.cp-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: url("banner-logo.png") center / calc(var(--u) * 52.9) auto no-repeat;
  /* The logo is brand yellow at roughly 57deg; +123 lands it near cyan, which
     is the contrast the source uses and not a colour the page owns anywhere
     else - so the tear reads as interference rather than as a second brand. */
  filter: hue-rotate(123deg);
  opacity: 0;
  animation: cp-tear 11s steps(1, end) infinite;
}

/* The mark itself jolts on the same 11s beat, so the tear reads as one event
   rather than two. A separate animation from cp-breathe because they drive
   different properties - transform here, filter there - and two animations on
   one property would simply mean the last one wins. */
@keyframes cp-jolt {
  0%, 95.4%, 99%, 100% { transform: translateX(0) skewX(0); }
  95.5%                { transform: translateX(calc(var(--u) * 0.28)) skewX(-0.8deg); }
  96.4%                { transform: translateX(0) skewX(0); }
  97.0%                { transform: translateX(calc(var(--u) * -0.22)) skewX(0.6deg); }
  97.9%                { transform: translateX(0) skewX(0); }
}

.cp-hero__logo {
  position: relative;
  z-index: 2;
  animation: cp-breathe 7s ease-in-out infinite,
             cp-jolt 11s steps(1, end) infinite;
}

/* 2. SCANLINES, and only on the hero. Static, 3% black, two pixels apart: a
 *    CRT texture over photographic artwork, which is where the source uses it.
 *    Not over the copy below, where it would be sitting on top of the thing
 *    somebody is reading. */
.cp-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, .16) 0 1px,
    transparent 1px 3px);
  mix-blend-mode: multiply;
}

/* 3. THE DECODE. cyberpunk.js scrambles a heading's characters and resolves
 *    them once, the first time it comes into view. This is the game's menus,
 *    which decode rather than fade, and it is the one place on this page worth
 *    spending the effect - a heading is read once, so a one-shot on it costs
 *    the reader nothing and a loop would cost them the sentence.
 *
 *    Held at the width the resolved text will occupy, so the line does not
 *    reflow under the reader as characters settle. */
.cp-h2[data-decode="waiting"] { visibility: hidden; }

@media (prefers-reduced-motion: reduce) {
  .cp-hero::before,
  .cp-hero__logo { animation: none; }
  .cp-hero::before { opacity: 0; }
  /* The scanlines stay: they do not move, and the reduced-motion request is
     about movement rather than about texture. */
}

/* The one tile that says more than its name: the beta kits are the
   Kickstarter reward, and this page's audience is exactly the people who
   backed it. Yellow, small, under the name - a caption, not a second title. */
.cp-tile__note {
  margin: 2% 0 0;
  font-weight: 600;
  font-size: clamp(9px, 1.1vw, 19px);
  line-height: 1.2;
  letter-spacing: 0.14em;
  text-indent: 0.14em;
  text-transform: uppercase;
  color: var(--cp-yellow);
  text-align: center;
}
