@font-face {
  font-family: "Playstation";
  src: url("Playstation.woff2") format("woff2"),
       url("Playstation.ttf") format("truetype");
  font-weight: 400 900;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("Inter.woff2") format("woff2"),
       url("Inter.ttf") format("truetype");
  /* 400-800, because that is every weight this stylesheet asks for: 400, 500,
     600, 700, 800. The woff2 carries exactly that range and 64 KB less than the
     100-900 one did (232 KB -> 168 KB) with not one codepoint dropped.
     The `opsz` axis stays variable ON PURPOSE. Pinning it saved another 57 KB
     and changed the rendering: browsers apply `font-optical-sizing: auto` by
     default, so the h1 was being drawn with the display design and started
     being drawn with the 14pt one — measured at 3.97% of the hero's pixels,
     and visible as wider, looser headline tracking. Trimming the weight axis
     alone changes 0.21%, which is anti-aliasing on glyph edges: the letterforms
     and their positions are identical. */
  font-weight: 400 800;
  font-display: swap;
}
/* Gaming display font for the brand wordmark next to the logo. */
@font-face {
  font-family: "Audiowide";
  src: url("Audiowide.woff2") format("woff2"),
       url("Audiowide.ttf") format("truetype");
  font-weight: 400;
  font-display: swap;
}

/* Armenian-aware fallback stack: Playstation/Inter don't ship Armenian
   glyphs, so without explicit Armenian fonts the browser substitutes a
   random system font whose metrics blow up the line-height and cause
   neighbouring lines to collide. */
:root {
  --font-arm: "Noto Sans Armenian", "Sylfaen", "DejaVu Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
}

html[lang="hy"] body { font-family: var(--font-arm); }
html[lang="hy"] .hero-title {
  font-family: var(--font-arm);
  font-size: clamp(30px, 5.2vw, 60px);
  letter-spacing: 0;
  line-height: 1.18;
  word-break: break-word;
  overflow-wrap: anywhere;
}
html[lang="hy"] .section-head h2 {
  font-family: var(--font-arm);
  font-size: clamp(26px, 3.8vw, 46px);
  letter-spacing: 0;
  line-height: 1.22;
  word-break: break-word;
  overflow-wrap: anywhere;
}
html[lang="hy"] .mobile-text h2 {
  font-family: var(--font-arm);
  font-size: clamp(26px, 3.8vw, 44px);
  letter-spacing: 0;
  line-height: 1.22;
}
html[lang="hy"] .platform-card h3,
html[lang="hy"] .dl-block-head h3 {
  font-family: var(--font-arm);
  font-size: 19px;
  letter-spacing: 0;
}
html[lang="hy"] .feature h3 {
  font-family: var(--font-arm);
  font-size: 17px;
  line-height: 1.3;
}
html[lang="hy"] .platform-feat li,
html[lang="hy"] .bullet,
html[lang="hy"] .contact-list li,
html[lang="hy"] .contact-form span,
html[lang="hy"] .stat-label,
html[lang="hy"] .eyebrow,
html[lang="hy"] .kicker {
  font-family: var(--font-arm);
}
html[lang="hy"] .nav-brand-text,
html[lang="hy"] .footer-brand,
html[lang="hy"] .phone-brand {
  font-family: "Audiowide", sans-serif; /* brand name stays Latin */
}

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }
/* Somebody who has asked their system for less motion means the page too: an
   anchor jump, and the back-to-top button, arrive rather than travel. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

html, body {
  /* Combined with the per-element width caps below, this makes
     `documentElement.scrollWidth` exactly equal to `window.innerWidth`
     on every viewport and language — no horizontal scroll, ever. */
  width: 100%;
  max-width: 100vw;
  overflow-x: hidden;
}
/* Last-line-of-defence belt: never let any direct child of body grow
   wider than the viewport. `position: relative` containers (the hero, the
   sections, the footer) sometimes report a sub-pixel wider scrollWidth
   on Chromium because of `transform` or `box-shadow` overflow boxes. */
body > * {
  max-width: 100vw;
  overflow-x: clip;
}

body {
  margin: 0;
  background: #020514;
  color: #e6edf6;
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* Long Armenian words ("ԿԱՌԱՎԱՐՎՈՂ ՀԱՄԱԿԱՐԳԻՉՆԵՐ") combined with uppercase
   transform + 1.5px letter-spacing on `.stat-label` push the hero stats card
   ~3px past a 375px viewport. Soft-wrap inside the label and let the row
   itself wrap (already enabled by the @media 540px rule). */
.stat-label {
  word-break: break-word;
  overflow-wrap: anywhere;
  text-align: center;
  max-width: 100%;
}
.kicker {
  max-width: 100%;
  word-break: break-word;
  overflow-wrap: anywhere;
}

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }

/* ============ Reveal animation ============ */
/* The animation MOVES content; it no longer hides it. There is no `opacity: 0`
   in any reveal rule, and `tools/verify.mjs` fails the build if one comes back.
   Two separate measurements are behind that rule:
   - On production, `.reveal { opacity: 0 }` was unscoped and no `js` class was
     set at all, so every section was invisible: **1 of 22 visible** at
     Googlebot's 411x731 viewport.
   - Scoping it to `html.js` fixed the JavaScript-less case but not the indexed
     one: a renderer that executes JavaScript and does not scroll still saw
     **21 of 51** sections, because the rest were waiting on an
     IntersectionObserver that only fires on scroll.
   A slide has no such failure mode: an unrevealed section is 28px low and
   completely readable, to a crawler and to a person whose scroll never reaches
   it. `transform` also cannot contribute to CLS, which stays at 0. */
.js .reveal { transform: translateY(28px); transition: transform 700ms cubic-bezier(0.2, 0.8, 0.2, 1); }
.js .reveal.in { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js .reveal { transform: none; transition: none; }
}

/* ============ NAV ============ */
.nav {
  position: fixed; top: 0; left: 0; right: 0;
  z-index: 100;
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 40px;
  background: rgba(2, 5, 20, 0.65);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid rgba(7, 221, 241, 0.08);
  transition: padding 200ms ease, background 200ms ease;
}
.nav.scrolled { padding: 12px 40px; background: rgba(2, 5, 20, 0.88); }

.nav-brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
}
.nav-logo {
  width: 32px;
  height: 32px;
  display: block;
  flex-shrink: 0;
  object-fit: contain;
  filter: drop-shadow(0 0 12px rgba(7, 221, 241, 0.35));
  transition: filter 220ms ease, transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.nav-brand:hover .nav-logo {
  filter: drop-shadow(0 0 18px rgba(7, 221, 241, 0.6));
  transform: rotate(-4deg);
}
.nav-brand-text {
  font-family: "Audiowide", "Inter", sans-serif;
  font-size: 20px;
  font-weight: 400;
  letter-spacing: 1px;
  background: linear-gradient(120deg, #07ddf1, #32aff7 45%, #d152fa);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* soft, eye-comfortable neon halo */
  filter: drop-shadow(0 0 2px rgba(7, 221, 241, 0.5)) drop-shadow(0 0 8px rgba(49, 175, 247, 0.3));
}

/* Brand wordmark animation: neon "switch-on" once on load, then a gentle,
   eye-comfortable glow pulse. Applies to every place the brand sits next to
   the logo (nav / footer / phone mock-up). */
.nav-brand-text,
.footer-brand,
.phone-brand {
  /* --flicker-every: how often the neon flickers. Set 5s / 8s / 10s to taste. */
  --flicker-every: 8s;
  animation: brandFlicker var(--flicker-every) ease-in-out infinite,
             brandGlow 5s ease-in-out infinite;
}
/* Short neon "flicker" burst at the start of every cycle, then steady glow.
   The burst lives in the first ~11% of the cycle (~0.9s at 8s), so the text
   reads calmly the rest of the time and only blinks once per period. */
@keyframes brandFlicker {
  0%   { opacity: .4; }
  2%   { opacity: 1; }
  3.5% { opacity: .35; }
  5%   { opacity: 1; }
  6.5% { opacity: .2; }
  8%   { opacity: .95; }
  9.5% { opacity: .55; }
  11%  { opacity: 1; }
  100% { opacity: 1; }
}
@keyframes brandGlow {
  /* clearly visible "breathing": dim soft halo -> fuller neon (still comfy) */
  0%, 100% { filter: drop-shadow(0 0 1px rgba(7, 221, 241, 0.40))
                     drop-shadow(0 0 4px rgba(49, 175, 247, 0.22)); }
  50%      { filter: drop-shadow(0 0 5px rgba(7, 221, 241, 0.85))
                     drop-shadow(0 0 16px rgba(49, 175, 247, 0.55))
                     drop-shadow(0 0 28px rgba(209, 82, 250, 0.40)); }
}
/* Respect users who prefer less motion — hold the calm resting state. */
@media (prefers-reduced-motion: reduce) {
  .nav-brand-text,
  .footer-brand,
  .phone-brand { animation: none; }
}
@media (max-width: 720px) {
  /* Reclaim horizontal space on small screens — keep just the logo +
     wordmark, drop the icon glow that costs no perceptible value at
     phone size. */
  .nav-logo { width: 26px; height: 26px; }
  .nav-brand-text { font-size: 16px; letter-spacing: 0.5px; }
  /* Footer logo follows the nav at the same breakpoint so both
     brand marks shrink in lockstep — no visual mismatch on phones. */
  .footer-logo { width: 26px; height: 26px; }
}

.nav-links {
  display: flex; gap: 28px;
  list-style: none; margin: 0; padding: 0;
}
.nav-links a {
  font-size: 14px; font-weight: 500; color: #94a3b8;
  transition: color 160ms ease;
}
.nav-links a:hover { color: #07ddf1; }

.lang-switch {
  display: inline-flex;
  background: rgba(7, 221, 241, 0.06);
  border: 1px solid rgba(7, 221, 241, 0.18);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}
.lang-btn {
  background: transparent;
  border: 0;
  color: #94a3b8;
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
  padding: 5px 12px;
  border-radius: 999px;
  cursor: pointer;
  transition: color 160ms ease, background 160ms ease;
}
.lang-btn:hover { color: #cfe9ee; }
.lang-btn.active {
  background: linear-gradient(90deg, #07ddf1, #32aff7 50%, #d152fa);
  color: #ffffff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

/* ============ Mobile navigation ============ */
/* The nav links used to be `display: none` below 720px with nothing to open
   them. Google indexes mobile-first, so the only links pointing at the subject
   pages were hidden on the viewport it actually reads, and a phone visitor had
   no way to reach them at all. They now live behind a real toggle, and without
   JavaScript they simply stay in the flow (see the `.js` guard). */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  /* 44px is the smallest comfortable thumb target; it used to shrink to 36px
     at 480px and 34px at 360px, i.e. it got hardest to hit exactly where it
     is the only way to open the menu. */
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 12px;
  border: 1px solid rgba(7, 221, 241, 0.22);
  background: rgba(7, 221, 241, 0.06);
  color: #cfe9ee;
  cursor: pointer;
}
.nav-toggle:hover { border-color: rgba(7, 221, 241, 0.45); color: #07ddf1; }
.nav-toggle svg { width: 20px; height: 20px; display: block; }
.nav-toggle .nav-toggle-close { display: none; }
.nav-toggle[aria-expanded="true"] .nav-toggle-open { display: none; }
.nav-toggle[aria-expanded="true"] .nav-toggle-close { display: block; }

@media (max-width: 860px) {
  .nav { padding: 14px 20px; flex-wrap: wrap; gap: 12px; }
  /* Only a page whose JavaScript is running gets the button, because only
     there can pressing it do anything. Without it the links stay in the flow
     and a dead burger beside them would be the confusing part. */
  .js .nav-toggle { display: inline-flex; }

  /* ...and a page without JavaScript keeps all five links, so the bar is five
     rows tall. Fixed, a bar that tall lies on top of the hero it is meant to
     sit above: the links covered the headline and the headline showed through
     the links. Letting it scroll away with the page is the honest fallback —
     the links are still the first thing on the page, just not over the top of
     something else. */
  html:not(.js) .nav { position: static; }
  .lang-switch { padding: 2px; }

  /* Only a page that can open the menu is allowed to close it. */
  .js .nav-links {
    display: none;
    order: 3;
    width: 100%;
    flex-direction: column;
    gap: 2px;
    padding: 6px 0 2px;
    border-top: 1px solid rgba(7, 221, 241, 0.12);
  }
  .js .nav[data-menu="open"] .nav-links { display: flex; }
  .nav-links {
    order: 3;
    width: 100%;
    flex-direction: column;
    gap: 2px;
  }
  .nav-links a {
    display: block;
    padding: 11px 4px;
    font-size: 15px;
    min-height: 44px;   /* touch target */
  }
}

/* ============ HERO — pure video viewport ============ */
/* The hero is now exactly one viewport tall and contains nothing but the
   gaming video, the gradient overlays, and the bouncing scroll cue. The
   text content lives in `.hero-text` (the section right below) so the
   visitor sees an immersive scene on first paint, then scrolls down to
   the headline. */
.hero {
  position: relative;
  height: 100vh;
  width: 100%;
  overflow: hidden;
  background: #020514;
}

/* ============ HERO-TEXT — section right after .hero ============ */
.hero-text {
  /* Same dark bedrock as the rest of the page; the brand-tinted blooms
     give it a smooth visual handoff from the bottom of the video. */
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(ellipse at 18% 18%, rgba(7, 221, 241, 0.10) 0%, transparent 55%),
    radial-gradient(ellipse at 82% 82%, rgba(209, 82, 250, 0.08) 0%, transparent 55%),
    #020514;
  padding: 80px 40px 90px;
}
.hero-text .hero-inner {
  max-width: 980px;
  margin: 0 auto;
  text-align: center;
  position: relative;
  z-index: 1;
}
@media (max-width: 720px) {
  .hero-text { padding: 60px 22px 70px; }
}

/* ============ HERO-TEXT --lead variant ============ */
/* Used when the animated hero is disabled and `.hero-text` is the
   first screen. Adds a tall top inset so the headline clears the
   fixed nav, plus three static blur orbs for brand atmosphere. */
.hero-text--lead {
  padding-top: 180px;
  padding-bottom: 120px;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
@media (max-width: 720px) {
  .hero-text--lead {
    padding-top: 130px;
    padding-bottom: 80px;
    min-height: auto;
  }
}

.hero-text-orbs {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 0;
}
.hero-text-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  opacity: 0.55;
  /* Static — no animation. Gives the same brand glow the animated hero
     used to provide, but doesn't repaint a single pixel after layout. */
}
.hero-text-orb--cyan {
  width: 60vmin; height: 60vmin;
  top: -12vmin; left: -10vmin;
  background: radial-gradient(circle, rgba(7, 221, 241, 0.85) 0%, rgba(7, 221, 241, 0.20) 50%, transparent 75%);
}
.hero-text-orb--magenta {
  width: 55vmin; height: 55vmin;
  bottom: -14vmin; right: -10vmin;
  background: radial-gradient(circle, rgba(209, 82, 250, 0.75) 0%, rgba(209, 82, 250, 0.18) 50%, transparent 75%);
}
.hero-text-orb--blue {
  width: 40vmin; height: 40vmin;
  top: 38%; left: 52%;
  background: radial-gradient(circle, rgba(50, 175, 247, 0.55) 0%, rgba(50, 175, 247, 0.15) 50%, transparent 75%);
}

/* ============ Hero animation layers ============ */
/* Three composed layers — adapted from AnimVault (Particle Flow,
   Abstract Motion orbs, Animated Grid) and recoloured to the brand
   palette. Stacking order inside `.hero`, back → front:
     -3  .hero-canvas + .hero-orbs   particles + drifting blooms
     -2  .hero-bg                    brand-tinted gradient overlay
     -1  .hero-grid                  pulsing cyber grid lines */

.hero-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* No negative z-index here — `.hero` has a solid background, and a
     negatively-stacked child paints BEHIND that solid background and
     becomes invisible. We keep the canvas in the default stacking
     order so the hero's bg paints first, then the canvas, then the
     other layers in DOM order. */
  pointer-events: none;
  display: block;
  background: #020514;
}

/* Two ambient orbs floating slowly behind the gradient overlay. The
   blur + low opacity makes them read as glow, not solid shapes. */
.hero-orbs {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}
.hero-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(40px);
  opacity: 0.85;
  will-change: transform;
}
.hero-orb--cyan {
  width: 70vmin; height: 70vmin;
  top: -15vmin; left: -15vmin;
  background: radial-gradient(circle, rgba(7, 221, 241, 0.85) 0%, rgba(7, 221, 241, 0.25) 45%, transparent 75%);
  animation: orb-drift-a 22s ease-in-out infinite;
}
.hero-orb--magenta {
  width: 60vmin; height: 60vmin;
  bottom: -15vmin; right: -15vmin;
  background: radial-gradient(circle, rgba(209, 82, 250, 0.75) 0%, rgba(209, 82, 250, 0.20) 45%, transparent 75%);
  animation: orb-drift-b 28s ease-in-out infinite;
}
.hero-orb--blue {
  width: 45vmin; height: 45vmin;
  top: 35%; left: 55%;
  background: radial-gradient(circle, rgba(50, 175, 247, 0.55) 0%, rgba(50, 175, 247, 0.15) 50%, transparent 75%);
  animation: orb-drift-c 35s ease-in-out infinite;
}
@keyframes orb-drift-a {
  0%, 100% { transform: translate(0, 0) scale(1); }
  25%      { transform: translate(15vmin, 8vmin) scale(1.1); }
  50%      { transform: translate(8vmin, 18vmin) scale(0.95); }
  75%      { transform: translate(-6vmin, 10vmin) scale(1.05); }
}
@keyframes orb-drift-b {
  0%, 100% { transform: translate(0, 0) scale(1); }
  33%      { transform: translate(-12vmin, -10vmin) scale(1.08); }
  66%      { transform: translate(-4vmin, -16vmin) scale(0.92); }
}
@keyframes orb-drift-c {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(-20vmin, -8vmin) scale(1.15); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-orb { animation: none; }
}

.hero-bg {
  position: absolute; inset: 0;
  /* Light overlay above the canvas + orbs — just a bottom-fade so the
     hero-text section below blends in cleanly. No centre vignette so
     the animation can fully shine. */
  background:
    linear-gradient(180deg,
      transparent 0%,
      transparent 75%,
      rgba(2, 5, 20, 0.85) 100%);
  pointer-events: none;
}

/* Hero-text content sits on its own dark section now (not on top of the
   video), so we no longer need a frosted-glass plate behind it. The
   subtle radial blooms on `.hero-text` provide the visual texture. */
.hero-grid {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(7, 221, 241, 0.10) 1px, transparent 1px),
    linear-gradient(90deg, rgba(7, 221, 241, 0.10) 1px, transparent 1px);
  background-size: 60px 60px;
  -webkit-mask-image: radial-gradient(ellipse at center, #000 30%, transparent 75%);
  mask-image: radial-gradient(ellipse at center, #000 30%, transparent 75%);
  pointer-events: none;
  animation:
    grid-drift 30s linear infinite,
    grid-pulse 4s ease-in-out infinite;
}
@keyframes grid-drift {
  from { background-position: 0 0; }
  to   { background-position: 60px 60px; }
}
@keyframes grid-pulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1;    }
}
@media (prefers-reduced-motion: reduce) {
  .hero-grid { animation: grid-drift 60s linear infinite; }
}
.hero-fade {
  position: absolute; bottom: 0; left: 0; right: 0; height: 120px;
  background: linear-gradient(180deg, transparent 0%, #020514 100%);
  pointer-events: none;
}

.hero-inner {
  max-width: 980px;
  text-align: center;
  position: relative;
}

.kicker {
  display: inline-block;
  font-size: 12px; font-weight: 600; letter-spacing: 2px; text-transform: uppercase;
  color: #07ddf1;
  background: rgba(7, 221, 241, 0.08);
  border: 1px solid rgba(7, 221, 241, 0.25);
  padding: 6px 14px; border-radius: 999px;
  margin-bottom: 28px;
  animation: cp-fadein 800ms ease-out 100ms both;
}

.hero-title {
  font-family: "Playstation", "Inter", sans-serif;
  font-size: clamp(40px, 7vw, 84px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -1px;
  margin: 0 0 24px;
  animation: cp-fadein 800ms cubic-bezier(0.2, 0.8, 0.2, 1) 200ms both;
}

.gradient-text {
  background: linear-gradient(90deg, #07ddf1, #32aff7 50%, #d152fa);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero-sub {
  font-size: clamp(15px, 1.4vw, 18px);
  color: #cbd5e1;
  max-width: 760px;
  margin: 0 auto 40px;
  animation: cp-fadein 800ms ease-out 350ms both;
  /* The 4-paragraph hero copy lives in a single text node with `\n\n`
     between paragraphs (so the i18n dictionary stays one key per language).
     `pre-line` preserves the newlines while still allowing soft-wrap inside
     a paragraph, giving us paragraph spacing without extra DOM. */
  white-space: pre-line;
  line-height: 1.65;
  text-align: center;
}
@media (max-width: 720px) {
  .hero-sub {
    text-align: left;
    font-size: 15px;
    line-height: 1.55;
  }
}

.hero-cta {
  display: flex; gap: 14px; justify-content: center; flex-wrap: wrap;
  margin-bottom: 70px;
  animation: cp-fadein 800ms ease-out 500ms both;
}

.btn {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 14px 26px;
  border-radius: 999px;
  font-size: 15px; font-weight: 600;
  border: none; cursor: pointer;
  transition: transform 200ms ease, box-shadow 200ms ease, opacity 200ms ease;
  font-family: inherit;
}
.btn-primary {
  background: linear-gradient(90deg, #07ddf1, #32aff7 55%, #d152fa);
  color: #ffffff;
  font-weight: 700;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  box-shadow: 0 10px 30px rgba(7, 221, 241, 0.25);
}
.btn-primary svg { color: #ffffff; }
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 14px 40px rgba(7, 221, 241, 0.4); }
.btn-ghost {
  background: rgba(255, 255, 255, 0.04);
  color: #e6edf6;
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.btn-ghost:hover { background: rgba(7, 221, 241, 0.08); border-color: rgba(7, 221, 241, 0.4); }

.hero-stats {
  display: inline-flex; align-items: center; gap: 36px;
  padding: 18px 30px;
  background: rgba(11, 18, 36, 0.55);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(7, 221, 241, 0.15);
  border-radius: 20px;
  animation: cp-fadein 800ms ease-out 700ms both;
}
.stat { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.stat-num { font-size: 28px; font-weight: 800; color: #07ddf1; font-variant-numeric: tabular-nums; }
.stat-label { font-size: 11px; letter-spacing: 1.5px; text-transform: uppercase; color: #94a3b8; }
.stat-sep { width: 1px; height: 32px; background: rgba(255, 255, 255, 0.1); }

@keyframes cp-fadein {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: none; }
}

/* ============ SECTIONS ============ */
.section { padding: 110px 40px; position: relative; }
.section-alt {
  background:
    linear-gradient(180deg, rgba(2, 5, 20, 0.92) 0%, rgba(7, 221, 241, 0.04) 50%, rgba(2, 5, 20, 0.92) 100%);
}
.container { max-width: 1180px; margin: 0 auto; }

.section-head { max-width: 740px; margin: 0 auto 70px; text-align: center; }
.eyebrow {
  display: inline-block;
  font-size: 12px; font-weight: 700; letter-spacing: 3px; text-transform: uppercase;
  color: #07ddf1;
  margin-bottom: 14px;
}
.section-head h2 {
  font-family: "Playstation", "Inter", sans-serif;
  font-size: clamp(32px, 4.5vw, 56px);
  font-weight: 800; line-height: 1.1; letter-spacing: -1px;
  margin: 0 0 18px;
}
.lead {
  color: #94a3b8;
  font-size: clamp(15px, 1.2vw, 17px);
  margin: 0;
}
/* Stacked lead paragraphs in a section head (e.g. #follow) get a small
   gap between them without touching single-lead sections. */
.section-head .lead + .lead { margin-top: 14px; }
.muted { color: #94a3b8; }

/* ============ FEATURES ============ */
.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  margin-bottom: 60px;
}
@media (max-width: 880px) { .grid-3 { grid-template-columns: 1fr; } }

.feature {
  background: rgba(11, 18, 36, 0.6);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(7, 221, 241, 0.14);
  border-radius: 18px;
  padding: 28px 26px;
  transition: transform 280ms ease, border-color 280ms ease, box-shadow 280ms ease;
}
.feature:hover {
  transform: translateY(-4px);
  border-color: rgba(7, 221, 241, 0.4);
  box-shadow: 0 20px 50px rgba(7, 221, 241, 0.1);
}
.feature-icon {
  width: 48px; height: 48px;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, rgba(7, 221, 241, 0.15), rgba(209, 82, 250, 0.15));
  border: 1px solid rgba(7, 221, 241, 0.3);
  border-radius: 12px;
  color: #07ddf1;
  margin-bottom: 18px;
}
.feature-icon svg { width: 24px; height: 24px; }
.feature h3 { font-size: 18px; font-weight: 700; margin: 0 0 10px; color: #fff; }
.feature p { color: #94a3b8; font-size: 14px; margin: 0; }

.bullets {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px 30px;
  max-width: 920px;
  margin: 0 auto;
}
@media (max-width: 720px) { .bullets { grid-template-columns: 1fr; } }
.bullet {
  display: flex; align-items: center; gap: 12px;
  font-size: 14px; color: #cbd5e1;
}
.bullet-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: #07ddf1;
  box-shadow: 0 0 12px #07ddf1;
  flex-shrink: 0;
}

/* ============ PLATFORM ============ */
.platform-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
@media (max-width: 980px) { .platform-grid { grid-template-columns: 1fr; } }

.platform-card {
  background:
    linear-gradient(180deg, rgba(11, 18, 36, 0.85) 0%, rgba(2, 5, 20, 0.85) 100%);
  border: 1px solid rgba(7, 221, 241, 0.15);
  border-radius: 20px;
  padding: 32px 28px;
  position: relative;
  transition: transform 280ms ease, border-color 280ms ease;
}
.platform-card:hover { transform: translateY(-6px); border-color: rgba(7, 221, 241, 0.45); }
.platform-card::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: 20px;
  padding: 1px;
  background: linear-gradient(135deg, rgba(7, 221, 241, 0.4), transparent 50%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  opacity: 0; transition: opacity 280ms ease;
}
.platform-card:hover::before { opacity: 1; }
.platform-tag {
  display: inline-block;
  font-size: 11px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase;
  color: #07ddf1;
  background: rgba(7, 221, 241, 0.1);
  padding: 4px 12px; border-radius: 999px;
  margin-bottom: 16px;
}
.platform-card h3 {
  font-family: "Playstation", "Inter", sans-serif;
  font-size: 22px; margin: 0 0 12px; font-weight: 700;
}
.platform-card p { color: #94a3b8; font-size: 14px; margin: 0 0 18px; }
.platform-feat { list-style: none; padding: 0; margin: 0; }
.platform-feat li {
  font-size: 13px; color: #cbd5e1; padding: 6px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  position: relative; padding-left: 18px;
}
.platform-feat li::before {
  content: "→"; position: absolute; left: 0; color: #07ddf1;
}
.platform-feat li:first-child { border-top: 0; }

/* ============ DOWNLOAD ============ */
.dl-block { margin-bottom: 56px; }
.dl-block-head { margin-bottom: 22px; }
.dl-block-head h3 {
  font-family: "Playstation", "Inter", sans-serif;
  font-size: 22px; font-weight: 700; margin: 0 0 4px;
}

.dl-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}
@media (max-width: 980px) { .dl-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 540px) { .dl-grid { grid-template-columns: 1fr; } }

.dl-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
  padding: 22px;
  background: rgba(11, 18, 36, 0.65);
  border: 1px solid rgba(7, 221, 241, 0.12);
  border-radius: 14px;
  transition: transform 200ms ease, border-color 200ms ease, box-shadow 200ms ease;
  cursor: pointer;
}
.dl-card:hover {
  transform: translateY(-3px);
  border-color: #07ddf1;
  box-shadow: 0 14px 40px rgba(7, 221, 241, 0.18);
}
.dl-card.disabled {
  cursor: not-allowed;
  opacity: 0.5;
}
.dl-card.disabled:hover {
  transform: none; border-color: rgba(7, 221, 241, 0.12); box-shadow: none;
}

.os-badge {
  font-size: 10px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase;
  padding: 4px 10px; border-radius: 999px;
}
.os-badge.linux   { color: #fbbf24; background: rgba(251, 191, 36, 0.12); border: 1px solid rgba(251, 191, 36, 0.3); }
.os-badge.windows { color: #60a5fa; background: rgba(96, 165, 250, 0.12); border: 1px solid rgba(96, 165, 250, 0.3); }
.os-badge.mac     { color: #cbd5e1; background: rgba(203, 213, 225, 0.12); border: 1px solid rgba(203, 213, 225, 0.3); }

.dl-os { font-size: 18px; font-weight: 700; color: #fff; }
.dl-meta { font-size: 12px; color: #94a3b8; }
.dl-meta.soon { color: #f59e0b; font-weight: 600; }

/* ============ MOBILE SECTION ============ */
.mobile-wrap {
  display: grid;
  grid-template-columns: 1fr 360px;
  gap: 60px;
  align-items: center;
}
@media (max-width: 880px) { .mobile-wrap { grid-template-columns: 1fr; } }

.mobile-text h2 {
  font-family: "Playstation", "Inter", sans-serif;
  font-size: clamp(32px, 4.5vw, 52px);
  font-weight: 800; line-height: 1.1;
  margin: 14px 0 18px;
}

.store-row { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 28px; }
.store-badge {
  display: inline-flex; align-items: center; gap: 12px;
  padding: 12px 20px;
  background: #0b1224;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 12px;
  transition: transform 200ms ease, border-color 200ms ease, background 200ms ease;
}
.store-badge svg { width: 26px; height: 26px; color: #fff; }
.store-badge span { display: flex; flex-direction: column; line-height: 1.1; }
.store-badge .small { font-size: 12px; color: #94a3b8; letter-spacing: 0.4px; }
.store-badge .big   { font-size: 16px; font-weight: 700; color: #fff; }
.store-badge:hover { transform: translateY(-2px); border-color: #07ddf1; background: #101a35; }
.store-badge.disabled {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
  filter: grayscale(40%);
}

.mobile-note { color: #f59e0b; font-size: 12px; margin-top: 14px; }

/* ============ HOW-IT-WORKS STEPS ============ */
.steps {
  list-style: none;
  margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 22px;
}
@media (max-width: 980px) {
  .steps { grid-template-columns: 1fr; gap: 16px; }
}
.step {
  position: relative; z-index: 1;
  background: rgba(11, 18, 36, 0.6);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(7, 221, 241, 0.14);
  border-radius: 18px;
  padding: 26px 24px;
  transition: transform 280ms ease, border-color 280ms ease, box-shadow 280ms ease;
}
.step:hover {
  transform: translateY(-4px);
  border-color: rgba(7, 221, 241, 0.4);
  box-shadow: 0 20px 50px rgba(7, 221, 241, 0.1);
}
.step-head {
  display: flex; align-items: center; gap: 16px;
  margin-bottom: 16px;
}
.step-num {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 54px; height: 54px;
  border-radius: 14px;
  font-family: "Playstation", "Inter", sans-serif;
  font-size: 20px; font-weight: 800;
  color: #020514;
  background: linear-gradient(135deg, #07ddf1, #32aff7 55%, #d152fa);
  box-shadow: 0 8px 24px rgba(7, 221, 241, 0.28);
}
.step h3 { font-size: 18px; font-weight: 700; margin: 0; color: #fff; }
.step-body { display: flex; flex-direction: column; gap: 12px; }
.step-body p { color: #94a3b8; font-size: 14px; line-height: 1.6; margin: 0; }
.step-list {
  list-style: none;
  margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 8px;
}
.step-list li {
  position: relative;
  color: #94a3b8; font-size: 14px; line-height: 1.55;
  padding-left: 20px;
}
.step-list li::before {
  content: "";
  position: absolute;
  left: 2px; top: 9px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: linear-gradient(135deg, #07ddf1, #d152fa);
}
.steps-outro {
  margin: 26px auto 0;
  max-width: 760px;
  text-align: center;
  color: #cbd5e1;
  font-size: 15px; line-height: 1.6;
}

/* ============ PRODUCT STATUS CARDS ============ */
.status-card {
  background:
    linear-gradient(180deg, rgba(11, 18, 36, 0.85) 0%, rgba(2, 5, 20, 0.85) 100%);
  border: 1px solid rgba(7, 221, 241, 0.15);
  border-radius: 18px;
  padding: 28px 26px;
  transition: transform 280ms ease, border-color 280ms ease, box-shadow 280ms ease;
}
.status-card:hover {
  transform: translateY(-4px);
  border-color: rgba(7, 221, 241, 0.4);
  box-shadow: 0 20px 50px rgba(7, 221, 241, 0.1);
}
.status-badge {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 13px 6px 11px;
  border-radius: 999px;
  font-size: 12px; font-weight: 700; letter-spacing: 1.3px; text-transform: uppercase;
  margin-bottom: 16px;
  border: 1px solid transparent;
}
.status-dot {
  width: 8px; height: 8px; border-radius: 50%;
  flex-shrink: 0;
  animation: status-pulse 2.4s ease-in-out infinite;
}
.status-badge--live { color: #34d399; background: rgba(16, 185, 129, 0.10); border-color: rgba(16, 185, 129, 0.35); }
.status-badge--live .status-dot { background: #34d399; box-shadow: 0 0 10px #34d399; }
.status-badge--beta { color: #07ddf1; background: rgba(7, 221, 241, 0.10); border-color: rgba(7, 221, 241, 0.35); }
.status-badge--beta .status-dot { background: #07ddf1; box-shadow: 0 0 10px #07ddf1; }
.status-badge--dev  { color: #f59e0b; background: rgba(245, 158, 11, 0.10); border-color: rgba(245, 158, 11, 0.35); }
.status-badge--dev .status-dot { background: #f59e0b; box-shadow: 0 0 10px #f59e0b; }
@keyframes status-pulse {
  0%, 100% { opacity: 1;    transform: scale(1); }
  50%      { opacity: 0.45; transform: scale(0.82); }
}
.status-card h3 { font-size: 18px; font-weight: 700; margin: 0 0 10px; color: #fff; }
.status-card p { color: #94a3b8; font-size: 14px; margin: 0; }
.status-card p + p { margin-top: 12px; }
/* Two-card status band: centre the pair and cap its width so it doesn't
   stretch edge-to-edge in the 3-col grid with an empty third column. */
.grid-3.status-grid {
  grid-template-columns: repeat(2, 1fr);
  max-width: 880px;
  margin-left: auto;
  margin-right: auto;
}
@media (max-width: 880px) {
  .grid-3.status-grid { grid-template-columns: 1fr; }
}

/* ============ FOLLOW / SOCIAL QR CARDS ============ */
.social-card {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  background: rgba(11, 18, 36, 0.6);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(7, 221, 241, 0.14);
  border-radius: 20px;
  padding: 26px 24px 22px;
  position: relative;
  overflow: hidden;
  transition: transform 280ms ease, border-color 280ms ease, box-shadow 280ms ease;
}
/* Platform accent bar along the top edge — the one place each card
   carries its own brand colour so the trio still reads as one system. */
.social-card::before {
  content: "";
  position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: var(--social-accent, #07ddf1);
  opacity: 0.9;
}
/* Two networks, so the row is two columns, centred — inheriting .grid-3's
   three would leave an empty cell on the right. Collapses at the same
   breakpoint .grid-3 does, so the section does not disagree with the rest of
   the page. */
.social-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 780px; margin-left: auto; margin-right: auto; }
@media (max-width: 880px) { .social-grid { grid-template-columns: 1fr; } }

.social-card--instagram { --social-accent: linear-gradient(90deg, #f9ce34, #ee2a7b 55%, #6228d7); }
.social-card--facebook  { --social-accent: linear-gradient(90deg, #1877f2, #0a5edb); }
.social-card:hover {
  transform: translateY(-6px);
  border-color: rgba(7, 221, 241, 0.4);
  box-shadow: 0 24px 60px rgba(7, 221, 241, 0.12);
}
.social-head {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 18px;
}
.social-icon {
  width: 38px; height: 38px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 11px;
  color: #fff;
  background: var(--social-accent, #07ddf1);
}
.social-icon svg { width: 20px; height: 20px; }
.social-name { font-size: 17px; font-weight: 700; color: #fff; letter-spacing: 0.2px; }
.social-qr {
  position: relative;
  line-height: 0;
  border-radius: 14px;
  overflow: hidden;
}
.social-qr img {
  width: 220px; height: auto; display: block;
}
/* Faint cyan "scanning" sweep on hover — decorative only and kept low
   opacity so it never obscures the code for a phone camera. */
.social-qr::after {
  content: "";
  position: absolute; left: 0; right: 0; top: 0; height: 45%;
  background: linear-gradient(180deg, rgba(7, 221, 241, 0.18), transparent);
  transform: translateY(-120%);
  opacity: 0;
  pointer-events: none;
}
.social-card:hover .social-qr::after {
  opacity: 1;
  animation: qr-scan 1.6s ease-in-out infinite;
}
@keyframes qr-scan {
  0%   { transform: translateY(-120%); }
  100% { transform: translateY(300%); }
}
.social-scan {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 16px;
  font-size: 12.5px; font-weight: 600; letter-spacing: 0.3px;
  color: #07ddf1;
}
.social-scan svg { width: 16px; height: 16px; }

.mobile-art {
  display: flex; justify-content: center;
  position: relative;
}
.phone-frame {
  position: relative;
  width: 280px; height: 560px;
  background: linear-gradient(180deg, #0b1224, #020514);
  border: 2px solid rgba(7, 221, 241, 0.3);
  border-radius: 36px;
  padding: 18px 14px;
  box-shadow:
    0 30px 80px rgba(7, 221, 241, 0.2),
    inset 0 0 0 1px rgba(255, 255, 255, 0.04);
}
.phone-glow {
  position: absolute;
  inset: -40px;
  background: radial-gradient(circle at center, rgba(7, 221, 241, 0.25) 0%, transparent 70%);
  z-index: -1;
  filter: blur(40px);
  animation: glow-pulse 4s ease-in-out infinite;
}
@keyframes glow-pulse {
  0%, 100% { opacity: 0.6; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.05); }
}
.phone-screen {
  position: relative;
  display: flex; flex-direction: column; gap: 10px;
  height: 100%;
  border-radius: 28px;
  overflow: hidden;
}
.phone-screen::before {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(2, 5, 20, 0.82) 0%, rgba(2, 5, 20, 0.92) 100%),
    radial-gradient(ellipse at 50% 0%, rgba(7, 221, 241, 0.18) 0%, transparent 60%),
    url("bg-section.jpg") center/cover no-repeat;
  z-index: 0;
}
.phone-screen > * { position: relative; z-index: 1; }
.phone-bar {
  height: 4px; width: 60px; background: rgba(255, 255, 255, 0.2);
  border-radius: 2px; margin: 6px auto 12px;
}
.phone-brand {
  font-family: "Audiowide", sans-serif;
  font-size: 16px; font-weight: 400; letter-spacing: 0.5px;
  text-align: center;
  background: linear-gradient(120deg, #07ddf1, #32aff7 45%, #d152fa);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 2px rgba(7, 221, 241, 0.5)) drop-shadow(0 0 7px rgba(49, 175, 247, 0.3));
  margin-bottom: 14px;
}
.phone-tile {
  display: flex; justify-content: space-between; align-items: center;
  gap: 8px;
  padding: 12px 14px;
  background: rgba(7, 221, 241, 0.06);
  border: 1px solid rgba(7, 221, 241, 0.2);
  border-radius: 10px;
  font-size: 12px;
  animation: tile-slide 600ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
  /* Without min-width:0 a flex child cannot shrink below its content size,
     so longer translations (e.g. "Cyber Arena · ..." in EN/RU) overflow the
     phone mockup horizontally on small viewports. */
  min-width: 0;
}
.phone-tile:nth-child(3) { animation-delay: 100ms; }
.phone-tile:nth-child(4) { animation-delay: 200ms; }
.phone-tile:nth-child(5) { animation-delay: 300ms; }
.phone-tile .phone-tile-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.phone-tile b {
  color: #07ddf1; font-weight: 700;
  flex: 0 0 auto;          /* never shrink the "free seats" badge */
  white-space: nowrap;
}
@keyframes tile-slide {
  from { opacity: 0; transform: translateX(20px); }
  to   { opacity: 1; transform: none; }
}
.phone-cta {
  margin-top: auto; margin-bottom: 6px;
  padding: 12px;
  background: linear-gradient(90deg, #07ddf1, #d152fa);
  color: #020514;
  text-align: center;
  font-weight: 700; font-size: 13px;
  border-radius: 10px;
}

/* ============ CONTACT ============ */
.contact-wrap {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  align-items: start;
}
@media (max-width: 880px) { .contact-wrap { grid-template-columns: 1fr; } }

.contact-list {
  list-style: none; padding: 0; margin: 24px 0 0;
  display: flex; flex-direction: column; gap: 12px;
}
.contact-list li {
  /* Stack label and value vertically — label on top (small, uppercase,
     muted), value below (cyan link or plain). The previous flex-row
     layout had a fixed 90 px label width that was too narrow for the
     Armenian "Աշխատանքային ժամեր" string and the value fell against
     the label with no visible gap. Vertical stacking is consistent
     across all three languages and looks cleaner anyway. */
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.contact-list li:first-child { border-top: 0; }
.contact-list span:first-child {
  font-size: 12px;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  color: #94a3b8;
  width: auto;
}
.contact-list a,
.contact-list li > span:last-child:not(:first-child) {
  color: #07ddf1;
  font-weight: 500;
  font-size: 14px;
  /* 22px tall was under the 24px pointer-target floor on desktop as well */
  padding: 3px 0;
  letter-spacing: 0;
  text-transform: none;
}
.contact-list a:hover { text-decoration: underline; }
/* The "hours" row uses two spans (label + .muted value); the second one
   should be readable (not cyan-bright like a link), but still bigger
   than the label. */
.contact-list span.muted {
  color: #cbd5e1;
  font-size: 14px;
  letter-spacing: 0;
  text-transform: none;
}

.contact-form {
  background: rgba(11, 18, 36, 0.6);
  backdrop-filter: blur(14px);
  border: 1px solid rgba(7, 221, 241, 0.15);
  border-radius: 18px;
  padding: 28px;
  display: flex; flex-direction: column; gap: 14px;
}
.contact-form label { display: flex; flex-direction: column; gap: 6px; }
.contact-form span {
  font-size: 12px; font-weight: 600; letter-spacing: 0.5px;
  color: #94a3b8;
}
.contact-form input,
.contact-form textarea,
.contact-form select {
  background: rgba(2, 5, 20, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  padding: 12px 14px;
  color: #e6edf6;
  font-family: inherit;
  font-size: 14px;
  outline: none;
  resize: vertical;
  transition: border-color 160ms ease, box-shadow 160ms ease;
  width: 100%;
}
.contact-form input:focus,
.contact-form textarea:focus,
.contact-form select:focus {
  border-color: #07ddf1;
  box-shadow: 0 0 0 3px rgba(7, 221, 241, 0.12);
}
/* Custom <select> chrome — premium glass treatment. The native control
   chrome on Chrome / Firefox / Safari is crude and breaks the brand
   palette; we draw our own caret (a clean cyan chevron via SVG data-URL)
   and frame the field in subtle glass so it sits naturally with the
   .contact-form glass card around it. */
.contact-form select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  cursor: pointer;
  padding-right: 44px;
  background-color: rgba(11, 18, 36, 0.55);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none'><path d='M1 1.5L6 6.5L11 1.5' stroke='%2307ddf1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 16px center;
  background-size: 12px 8px;
  border: 1px solid rgba(7, 221, 241, 0.18);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  letter-spacing: 0.2px;
  transition:
    border-color 200ms ease,
    box-shadow 220ms ease,
    background-color 200ms ease,
    transform 160ms ease;
}
.contact-form select:hover {
  border-color: rgba(7, 221, 241, 0.45);
  background-color: rgba(11, 18, 36, 0.7);
}
.contact-form select:focus {
  border-color: #07ddf1;
  /* layered focus ring — outer cyan halo + inner soft tint = bigger
     visible focus without a hard double-ring look */
  box-shadow:
    0 0 0 3px rgba(7, 221, 241, 0.18),
    0 0 24px rgba(7, 221, 241, 0.25);
  background-color: rgba(11, 18, 36, 0.75);
}
/* Restore default text colour for the placeholder option even though it
   is `disabled` (browsers grey it out by default). */
.contact-form select:invalid {
  color: #94a3b8;
}
.contact-form select option {
  background: #0b1224;
  color: #e6edf6;
  padding: 10px;
}
.contact-form select option:disabled {
  color: #64748b;
}
.contact-form select.invalid {
  border-color: #ef4444;
  box-shadow:
    0 0 0 3px rgba(239, 68, 68, 0.18),
    0 0 24px rgba(239, 68, 68, 0.20);
  animation: cp-shake 360ms cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}
@keyframes cp-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-4px); }
  40% { transform: translateX(4px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(2px); }
}

/* Form submit button — premium hover treatment. Idle state stays solid
   cyan with dark text (12.6:1 contrast, AAA). On hover a cyan→magenta
   gradient sweeps from left to right *behind* the label, the arrow icon
   slides forward, and a halo glow expands. The whole composition reads
   as "this button is alive and ready". */
.btn-submit {
  position: relative;
  display: inline-flex; align-items: center; gap: 10px;
  padding: 13px 28px;
  border-radius: 999px;
  border: 1px solid rgba(7, 221, 241, 0.6);
  font-size: 15px; font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  background: #07ddf1;
  color: #020514;
  text-shadow: none;
  box-shadow:
    0 6px 20px rgba(7, 221, 241, 0.22),
    inset 0 1px 0 rgba(255, 255, 255, 0.4);
  overflow: hidden;
  isolation: isolate; /* keeps the ::before sweep clipped to the button */
  transition:
    transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1),
    box-shadow 240ms ease,
    border-color 200ms ease;
}
/* Sweep layer — sits at z-index 0 between the solid cyan plate and the
   text/icon (which we lift to z-index 1). On hover it slides right and
   reveals the gradient. */
.btn-submit::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    #07ddf1 0%,
    #32aff7 45%,
    #d152fa 100%);
  transform: translateX(-100%);
  transition: transform 480ms cubic-bezier(0.2, 0.8, 0.2, 1);
  z-index: 0;
}
.btn-submit > span,
.btn-submit > svg {
  position: relative;
  z-index: 1;
  transition: transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
/* The form's label spans (.contact-form span) set color:#94a3b8 +
   font-size:12px which would normally win over .btn-submit because the
   selector is more specific (.contact-form span beats .btn-submit). We
   reset the inner span here at higher specificity so the label inherits
   the button's strong dark colour and font weight. */
.contact-form .btn-submit > span {
  color: inherit;
  font-size: inherit;
  font-weight: inherit;
  letter-spacing: 0.2px;
}
.btn-submit svg { color: #020514; }
.btn-submit:hover {
  transform: translateY(-2px);
  border-color: rgba(209, 82, 250, 0.55);
  box-shadow:
    0 14px 38px rgba(7, 221, 241, 0.42),
    0 6px 18px rgba(209, 82, 250, 0.30),
    inset 0 1px 0 rgba(255, 255, 255, 0.45);
}
.btn-submit:hover::before { transform: translateX(0); }
.btn-submit:hover > svg { transform: translateX(4px); }
.btn-submit:active {
  transform: translateY(0) scale(0.98);
  transition-duration: 80ms;
}
.btn-submit:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 3px;
}

.contact-form button { align-self: flex-start; margin-top: 4px; }
.form-status { font-size: 13px; min-height: 18px; color: #22c55e; }
.form-status.error { color: #ef4444; }

/* Footer domain link — keep the chip look from the previous span and add
   subtle hover affordance because it's now a real link to cyberplace.pro. */
.footer-domain {
  text-decoration: none;
  cursor: pointer;
  transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease;
}
.footer-domain:hover {
  background: rgba(7, 221, 241, 0.16);
  border-color: rgba(7, 221, 241, 0.5);
  color: #2be4f5;
}

/* ============ FOOTER ============ */
.footer {
  padding: 40px 40px;
  border-top: 1px solid rgba(7, 221, 241, 0.1);
  background: #020514;
}
/* Footer is a 2-column flex: brand block (left), meta block (right).
   Previously copy + tag were 2nd and 3rd flex children of the row,
   so mid-width viewports wrapped them onto separate lines and broke
   the visual grouping. Wrapping both into .footer-meta keeps them
   stacked on the same vertical baseline ("aligned") regardless of
   viewport width. */
.footer-inner {
  display: flex; justify-content: space-between; align-items: center;
  flex-wrap: wrap; gap: 18px;
}
/* Footer brand block — logo, wordmark and domain chip in a single
   flex row. `gap: 14px` replaces the old `margin-right: 14px` on
   .footer-brand so all three children sit on the same rhythm
   (logo → wordmark → domain), rather than one custom margin and
   nothing for the new logo. */
.footer-brand-block {
  display: flex; align-items: center; gap: 14px;
}
/* Mirrors .nav-logo dimensions exactly (32px desktop, 26px ≤720px)
   so the footer brand mark sits at the same size as the navbar.
   Glow is a touch quieter (10px / 0.3 vs nav's 12px / 0.35) and
   no hover-rotate, because footers should feel calmer than the
   primary nav. object-fit:contain preserves logo.png's 134:116
   aspect ratio inside the square box. */
.footer-logo {
  width: 32px;
  height: 32px;
  display: block;
  flex-shrink: 0;
  object-fit: contain;
  filter: drop-shadow(0 0 10px rgba(7, 221, 241, 0.3));
}
.footer-meta {
  display: flex; flex-direction: column; align-items: flex-end;
  gap: 4px; text-align: right;
}
.footer-meta .muted { line-height: 1.45; }
@media (max-width: 720px) {
  .footer-inner { justify-content: center; }
  .footer-meta { align-items: center; text-align: center; }
}
.footer-brand {
  font-family: "Audiowide", "Inter", sans-serif;
  font-weight: 400; letter-spacing: 1px;
  background: linear-gradient(120deg, #07ddf1, #32aff7 45%, #d152fa);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 2px rgba(7, 221, 241, 0.5)) drop-shadow(0 0 8px rgba(49, 175, 247, 0.3));
  /* margin-right removed — spacing now handled uniformly by
     .footer-brand-block { gap: 14px } so logo / wordmark / domain
     all sit on the same rhythm. */
}
.footer-domain {
  display: inline-block;
  font-size: 12px;
  color: #07ddf1;
  letter-spacing: 1.5px;
  padding: 3px 10px;
  background: rgba(7, 221, 241, 0.08);
  border: 1px solid rgba(7, 221, 241, 0.25);
  border-radius: 999px;
  vertical-align: middle;
}

/* ============ Responsive nav ============ */
@media (max-width: 720px) {
  .section { padding: 80px 22px; }
  .hero { padding: 100px 20px 60px; }
  .hero-stats { gap: 18px; padding: 14px 18px; }
  .stat-sep { display: none; }
}

/* On very narrow viewports the longer Armenian / Russian stat labels
   ("Կառավարվող համակարգիչներ", "Управляемых ПК") would otherwise
   horizontally overflow the rounded stats card. Allowing the row to wrap
   keeps everything inside the viewport without shrinking text. */
@media (max-width: 540px) {
  .hero-stats {
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px 22px;
    padding: 12px 16px;
  }
  .hero-cta .btn { padding: 12px 20px; font-size: 14px; }
  .contact-form { padding: 22px 18px; }
}

/* Tablet — keep platform/feature grid responsive without losing the
   3-column desktop layout above 980px. */
@media (min-width: 880px) and (max-width: 980px) {
  .platform-grid { grid-template-columns: 1fr 1fr; }
}

/* ============ Hero scroll-cue ============ */
/* Animated double-chevron prompt pinned to the bottom-centre of the
   viewport so it stays visible regardless of the hero's actual height
   (the bottom-aligned 4-paragraph copy can push the hero past 100 vh).
   Hides itself as soon as the user has scrolled more than 120 px,
   driven by the .is-hidden class toggled in app.js. */
.hero-scroll-cue {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 50;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: rgba(7, 221, 241, 0.85);
  text-decoration: none;
  cursor: pointer;
  /* Defer entry until everything else is in place — feels like a "now
     scroll" invitation rather than competing with the headline. */
  animation: scroll-cue-fade 900ms ease-out 1700ms both;
  transition: color 200ms ease, transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1), opacity 400ms ease;
}
.hero-scroll-cue:hover {
  color: #07ddf1;
  transform: translateX(-50%) translateY(-3px);
}
.hero-scroll-chevron {
  /* Continuous gentle bounce + opacity pulse — long enough (2.4s) that
     it doesn't feel anxious, short enough that it reads as "alive". */
  animation: scroll-cue-bounce 2.4s cubic-bezier(0.5, 0.05, 0.5, 0.95) infinite;
  filter: drop-shadow(0 0 8px rgba(7, 221, 241, 0.45));
}
@keyframes scroll-cue-bounce {
  0%, 100% { transform: translateY(0); opacity: 0.55; }
  35%      { transform: translateY(6px); opacity: 1; }
  70%      { transform: translateY(-1px); opacity: 0.85; }
}
@keyframes scroll-cue-fade {
  from { opacity: 0; transform: translate(-50%, 12px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}
/* Hide the cue once the user has clearly engaged with the page (handled
   in app.js by toggling .scrolled on the nav; we reuse that signal). */
.nav.scrolled ~ * .hero-scroll-cue,
.nav.scrolled + * .hero-scroll-cue {
  /* Selector won't match the actual DOM tree (nav + header siblings),
     so we fall back to a JS-toggled class — see `.is-scrolled` rule
     below applied to the cue itself. */
}
.hero-scroll-cue.is-hidden {
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, 8px);
  transition: opacity 400ms ease, transform 400ms ease;
}
@media (prefers-reduced-motion: reduce) {
  .hero-scroll-chevron { animation: none; }
  .hero-scroll-cue { animation: none; }
}

/* ============ Section reveal — premium polish ============ */
/* The base .reveal rule (top of file) handles a single fade-in-up. Add
   directional variants and a stagger so feature cards / platform cards /
   bullets enter in sequence rather than all at once — gives the page a
   choreographed feel without being slow.

   Scoped to `html.js` for the same reason as the base rule: the offset below
   is applied to every section and only `.in` — which an IntersectionObserver
   adds — takes it back. Unscoped, a visitor without JavaScript read the whole
   page shifted 36px down, with the last section's offset uncorrected. The
   `transition-delay` rules further down need no guard: a delay on a transition
   that never runs changes nothing. */
.js .reveal {
  /* Slightly more dramatic than the base — longer duration, tighter easing
     curve, larger initial offset. Transform only: see the base rule. */
  transition: transform 900ms cubic-bezier(0.2, 0.8, 0.2, 1);
  transform: translateY(36px);
}
.js .reveal.in {
  transform: none;
}

/* Stagger nested children inside grid sections for a "wave" reveal. The
   IntersectionObserver still adds .in to the parent; nth-child here
   spaces the transitions visually. */
.grid-3 > .feature.reveal,
.platform-grid > .platform-card.reveal,
.bullets > .bullet.reveal,
.dl-grid > .dl-card.reveal {
  transition-delay: 0ms;
}
.grid-3 > .feature.reveal:nth-child(2),
.platform-grid > .platform-card.reveal:nth-child(2) { transition-delay: 120ms; }
.grid-3 > .feature.reveal:nth-child(3),
.platform-grid > .platform-card.reveal:nth-child(3) { transition-delay: 240ms; }
.bullets > .bullet.reveal:nth-child(2) { transition-delay: 80ms; }
.bullets > .bullet.reveal:nth-child(3) { transition-delay: 160ms; }
.bullets > .bullet.reveal:nth-child(4) { transition-delay: 240ms; }
.bullets > .bullet.reveal:nth-child(5) { transition-delay: 320ms; }
.bullets > .bullet.reveal:nth-child(6) { transition-delay: 400ms; }

/* Same wave reveal for the new step / status / social grids. */
.steps > .step.reveal:nth-child(2),
.grid-3 > .status-card.reveal:nth-child(2),
.social-grid > .social-card.reveal:nth-child(2) { transition-delay: 120ms; }
.steps > .step.reveal:nth-child(3),
.grid-3 > .status-card.reveal:nth-child(3),
.social-grid > .social-card.reveal:nth-child(3) { transition-delay: 240ms; }
.steps > .step.reveal:nth-child(4) { transition-delay: 360ms; }

@media (prefers-reduced-motion: reduce) {
  .js .reveal { transition: none; transform: none; }
  .js .reveal.in { transform: none; }
  /* Silence the decorative loops for motion-sensitive visitors. */
  .status-dot { animation: none; }
  .social-card:hover .social-qr::after { animation: none; opacity: 0; }
}

/* ============ Toast (top-right) ============ */
/* Single shared element re-used for success and error states. JS sets
   .toast.show and adds .toast--success | .toast--error for colour.
   Position: fixed top-right with safe-area inset so it floats above
   the iOS notch when the landing is opened from a webclip / PWA. */
.toast {
  position: fixed;
  top: calc(20px + env(safe-area-inset-top, 0px));
  right: 20px;
  z-index: 9999;
  min-width: 240px;
  max-width: min(380px, calc(100vw - 40px));
  padding: 14px 18px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.45;
  color: #fff;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
  border: 1px solid transparent;
  backdrop-filter: blur(8px);
  opacity: 0;
  transform: translateY(-12px);
  pointer-events: none;
  transition: opacity 220ms ease, transform 220ms ease;
}
.toast.show {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.toast--success {
  background: linear-gradient(180deg, rgba(16, 185, 129, 0.96), rgba(5, 150, 105, 0.96));
  border-color: rgba(16, 185, 129, 0.55);
}
.toast--error {
  background: linear-gradient(180deg, rgba(239, 68, 68, 0.96), rgba(185, 28, 28, 0.96));
  border-color: rgba(239, 68, 68, 0.55);
}
@media (max-width: 540px) {
  .toast {
    left: 12px;
    right: 12px;
    max-width: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .toast { transition: opacity 120ms linear; transform: none; }
}


/* ============ Content pages (/club-management/, ...) ============
   Long-form subject pages generated by tools/build-i18n.mjs. They reuse the
   landing's shell and its spacing scale; the only thing they need that the
   landing did not is a readable measure for running text, because a paragraph
   set to the full container width is a paragraph nobody finishes. */
.content-page { max-width: 780px; }
.content-page h1 { margin: 8px 0 16px; }
.content-page .kicker a { color: inherit; text-decoration: none; opacity: .8; }
.content-page .kicker a:hover { opacity: 1; text-decoration: underline; }
.content-block { margin: 32px 0; }
.content-block h2 { margin: 0 0 12px; }
.content-block h3 { margin: 20px 0 8px; }
.content-block p { margin: 0 0 12px; line-height: 1.7; }

/* ============================================================================
   PRODUCT SECTIONS
   ----------------------------------------------------------------------------
   The page used to describe the product in adjectives. These blocks show it:
   real panel and app screenshots in the frame they actually run in, the two
   staff roles side by side, and the seat statuses the floor board really uses.

   The status colours are the system's own vocabulary, not decoration. A seat
   is free, reserved or in session in the panel, in the player app and here,
   and it is the same three colours in all three places — which is why they are
   tokens rather than values typed into each rule.
   ========================================================================== */
:root {
  --seat-free: #3ddc84;
  --seat-booked: #ffb547;
  --seat-live: #ff4d6d;

  --panel-bg: rgba(11, 18, 36, 0.6);
  --panel-line: rgba(7, 221, 241, 0.14);
  --panel-line-strong: rgba(7, 221, 241, 0.34);
  --ink: #e6edf6;
  --ink-dim: #94a3b8;
}

/* ---- hero trust row -------------------------------------------------------
   Three chips naming the three applications. Placed under the CTA because the
   first question a club owner has after the headline is "what do I actually
   install", and the answer is short enough to be a label rather than a
   paragraph. */
.hero-trust {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 34px;
}
.hero-trust li {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid var(--panel-line);
  background: rgba(11, 18, 36, 0.55);
  color: #cfe9ee;
  font-size: 13px;
  font-weight: 600;
}
.hero-trust svg { width: 16px; height: 16px; flex-shrink: 0; color: #07ddf1; }
.hero-trust { list-style: none; margin-left: 0; padding-left: 0; }

/* ---- showcase: one screenshot, one explanation ---------------------------- */
.showcase {
  display: grid;
  /* The screenshot is the argument; the text beside it is the caption. Give
     the image the wider column or the product ends up illegible at 1440. */
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 48px;
  align-items: center;
}
.showcase + .showcase { margin-top: 90px; }
.showcase--flip .showcase-media { order: 2; }
.showcase h3 {
  font-family: "Playstation", "Inter", sans-serif;
  font-size: clamp(22px, 2.4vw, 30px);
  line-height: 1.18;
  margin: 0 0 16px;
  color: #fff;
}
html[lang="hy"] .showcase h3 { font-family: var(--font-arm); font-size: clamp(20px, 2.2vw, 26px); }
.showcase p { color: var(--ink-dim); margin: 0 0 18px; font-size: 15px; }

.showcase-points { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.showcase-points li {
  position: relative;
  padding-left: 26px;
  color: #cbd5e1;
  font-size: 14.5px;
  line-height: 1.55;
}
.showcase-points li::before {
  content: "";
  position: absolute;
  left: 0; top: 8px;
  width: 8px; height: 8px;
  border-radius: 2px;
  background: linear-gradient(135deg, #07ddf1, #d152fa);
}

@media (max-width: 980px) {
  .showcase { grid-template-columns: 1fr; gap: 32px; }
  .showcase--flip .showcase-media { order: 0; }
  .showcase + .showcase { margin-top: 64px; }
}

/* ---- app frame: the panel is a desktop application, not a website ---------
   A browser chrome with an address bar would be a lie: the panel is an
   Electron app staff open from their desktop. The frame is therefore a plain
   window title bar carrying the screen's own name. */
/* The frame is the DEVICE the screen runs on, drawn in CSS around the
   screenshot: a laptop for the staff panel, a monitor on a stand for the kiosk
   agent (a gaming PC is not a laptop). Two pseudo-elements carry the whole
   illusion — `::before` is the webcam, `::after` is the deck or the stand — so
   no image, no library and no extra markup is involved, and the screenshot
   itself is never scaled or cropped: it sits at its own aspect ratio inside
   the bezel, which is the only thing that keeps a product screenshot readable.

   The lid tilts 3deg away from the viewer and straightens on hover. That is
   the whole animation: enough to read as an object with depth, small enough
   that the text on the screen stays legible at rest, which a heavier rotation
   destroys. */
.app-frame {
  position: relative;
  padding: 12px 12px 13px;
  border-radius: 20px 20px 12px 12px;
  border: 1px solid rgba(255, 255, 255, 0.09);
  background:
    linear-gradient(168deg, #222c42 0%, #131b2d 42%, #0a1120 100%);
  box-shadow:
    0 34px 70px rgba(0, 0, 0, 0.6),
    0 2px 0 rgba(255, 255, 255, 0.05) inset,
    0 0 0 1px rgba(7, 221, 241, 0.07);
  transform: rotateX(3deg);
  transform-origin: 50% 100%;
  transition: transform 420ms cubic-bezier(0.2, 0.8, 0.2, 1),
              box-shadow 420ms ease;
  margin-bottom: 26px;   /* the deck lives under the lid, outside the box */
}
/* Webcam, centred in the top bezel. */
.app-frame::before {
  content: "";
  position: absolute;
  top: 5px;
  left: 50%;
  width: 5px;
  height: 5px;
  margin-left: -2.5px;
  border-radius: 50%;
  background: #05070f;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.07), 0 0 3px rgba(7, 221, 241, 0.35) inset;
}
/* The deck: wider than the lid, with a hinge line at the top and a shallow
   dent where the trackpad would be. */
.app-frame::after {
  content: "";
  position: absolute;
  top: 100%;
  left: -4.5%;
  right: -4.5%;
  height: 13px;
  border-radius: 0 0 10px 10px / 0 0 20px 20px;
  background:
    radial-gradient(60px 10px at 50% 0%, rgba(255, 255, 255, 0.1), transparent 70%),
    linear-gradient(#26304a 0 2px, #151d30 2px, #0b1120 78%, #070b14 100%);
  box-shadow: 0 22px 34px rgba(0, 0, 0, 0.5);
}
/* The kiosk agent runs full screen on a gaming PC, so its screens sit on a
   monitor. Same lid, different furniture: one clip-path draws the neck and the
   foot inside the frame's own width, which is also why it can never widen a
   row on a phone. */
.app-frame--monitor { border-radius: 16px; margin-bottom: 44px; }
.app-frame--monitor::after {
  left: 0;
  right: 0;
  height: 36px;
  border-radius: 0;
  background: linear-gradient(#1b2438, #0d1424 60%, #080d18);
  clip-path: polygon(
    44% 0%, 56% 0%, 58% 24px, 70% 24px, 72% 30px, 72% 36px,
    28% 36px, 28% 30px, 30% 24px, 42% 24px);
  box-shadow: none;
}
/* Hover straightens the lid and lifts it. `.showcase-media` is the hover
   target rather than the frame itself so the pointer does not fall out of the
   element it just moved. */
.showcase-media { perspective: 1800px; }
.showcase-media:hover .app-frame,
.showcase-media:focus-within .app-frame {
  transform: rotateX(0deg) translateY(-6px) scale(1.012);
  box-shadow:
    0 46px 90px rgba(0, 0, 0, 0.66),
    0 2px 0 rgba(255, 255, 255, 0.07) inset,
    0 0 0 1px rgba(7, 221, 241, 0.16);
}
@media (prefers-reduced-motion: reduce) {
  .app-frame { transform: none; transition: none; }
  .showcase-media:hover .app-frame,
  .showcase-media:focus-within .app-frame { transform: none; }
}
.app-frame-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.04);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  /* `overflow: hidden` used to round the screen; the frame needs visible
     overflow now to draw its deck, so the two children carry the radius. */
  border-radius: 9px 9px 0 0;
}
.app-frame-dots { display: inline-flex; gap: 6px; }
.app-frame-dots span { width: 10px; height: 10px; border-radius: 50%; background: rgba(255, 255, 255, 0.16); }
.app-frame-title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.4px;
  color: var(--ink-dim);
  margin-left: 6px;
}
.app-frame img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: 0 0 9px 9px;
  background: #05070f;
}
/* A frame with no title bar (the agent runs full screen) rounds all four
   corners of the screen instead. */
.app-frame > img:first-child { border-radius: 9px; }
.shot-caption {
  margin: 12px 2px 0;
  font-size: 13px;
  color: var(--ink-dim);
}

/* ---- screenshot strip: several screens of the same product ---------------- */
.shot-strip {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 28px;
}
@media (max-width: 880px) { .shot-strip { grid-template-columns: 1fr; } }

/* One screenshot, centred, for the sections that carry a single frame. */
.shot-single {
  max-width: 820px;
  margin: 44px auto 0;
}
.shot-single .showcase-media { margin: 0; }

/* ---- roles: owner and manager --------------------------------------------
   Two blocks, never one. The difference between them is the single thing a
   visitor most needs to understand before buying, and a merged list would
   hide exactly the part they came for. */
/* Owner and manager are two BLOCKS, not two cards in a grid.
   Side by side they read as a comparison table, and a visitor has to hold both
   columns in their head to learn what either role does. One block per role,
   each with its own heading, its own list and a screenshot of what that role
   actually sees, answers the only question being asked: which of these two am
   I, and what will I be looking at all evening. The screenshot alternates side
   so the eye has somewhere to go, and both blocks stack on a phone with the
   text first — the picture is the evidence, not the argument. */
.role-blocks {
  display: grid;
  gap: 28px;
}
.role-block {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: 34px;
  align-items: center;
  background: var(--panel-bg);
  border: 1px solid var(--panel-line);
  border-radius: 20px;
  padding: 34px 32px;
  position: relative;
  overflow: hidden;
}
/* Each role keeps its own edge colour, so the two stay told apart on a skim
   and the matrix further down can reuse the same two hues. */
.role-block::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
}
.role-block--owner::before { background: linear-gradient(90deg, #07ddf1, #32aff7); }
.role-block--manager::before { background: linear-gradient(90deg, #d152fa, #f472b6); }
.role-block--manager .role-block-text { order: 2; }
.role-block--manager .role-block-shot { order: 1; }
/* The screenshot column is the wider one in both blocks. Grid tracks are
   assigned by visual order, so the mirrored block needs its ratio mirrored
   too — without this the manager's board is rendered noticeably smaller than
   the owner's for no reason a reader could guess. */
.role-block--manager { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
.role-block-shot { margin: 0; }

.role-badge {
  margin-left: auto;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: #07ddf1;
  background: rgba(7, 221, 241, 0.08);
  border: 1px solid rgba(7, 221, 241, 0.22);
  border-radius: 999px;
  padding: 5px 11px;
  white-space: nowrap;
}
.role-block--manager .role-badge {
  color: #e9a6ff;
  background: rgba(209, 82, 250, 0.09);
  border-color: rgba(209, 82, 250, 0.26);
}
/* What the role does NOT do. Saying it out loud is the fastest way to explain
   the other role, and it is the half a feature list always leaves out. */
.role-limit {
  margin: 18px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--panel-line);
  color: var(--ink-dim);
  font-size: 13.5px;
  line-height: 1.55;
}

@media (max-width: 880px) {
  /* `minmax(0, 1fr)`, not `1fr`. A bare `1fr` track has an automatic minimum,
     so the widest min-content inside it sizes the track — and the nowrap badge
     in the head row made that min-content about 330px, which is 30px more than
     a 390px phone has to give. The whole text column then hung 30px past the
     card's own padding. Measured, not guessed, and the viewport-level overflow
     check could not see it: the card overflowed, the document did not.
     Both halves matter — the wrap below removes the pressure, this removes the
     track's ability to act on it — which is why reverting either one alone no
     longer reproduces the original 30px. */
  .role-block { grid-template-columns: minmax(0, 1fr); gap: 26px; padding: 28px 22px; }
  /* The badge is nowrap by design — "Company level" must not break across two
     lines — so on a narrow card the head row wraps instead and the badge takes
     its own line under the role name. */
  .role-head { flex-wrap: wrap; }
  .role-badge { margin-left: 0; }
  .role-block--manager .role-block-text { order: 1; }
  .role-block--manager .role-block-shot { order: 2; }
}

.role-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.role-icon {
  width: 42px; height: 42px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 12px;
  border: 1px solid var(--panel-line);
  background: rgba(7, 221, 241, 0.07);
}
.role-block--manager .role-icon { background: rgba(209, 82, 250, 0.08); border-color: rgba(209, 82, 250, 0.2); }
.role-icon svg { width: 21px; height: 21px; color: #07ddf1; }
.role-block--manager .role-icon svg { color: #d152fa; }
.role-block h3 { margin: 0; font-size: 20px; font-weight: 700; color: #fff; }
html[lang="hy"] .role-block h3 { font-family: var(--font-arm); font-size: 18px; }
.role-block-text > p { color: var(--ink-dim); font-size: 14.5px; margin: 0 0 18px; }
.role-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.role-list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 14.5px;
  line-height: 1.5;
  color: #cbd5e1;
}
.role-list svg { width: 16px; height: 16px; margin-top: 3px; flex-shrink: 0; color: var(--seat-free); }

.role-note {
  margin: 28px auto 0;
  max-width: 720px;
  text-align: center;
  font-size: 14px;
  color: var(--ink-dim);
}

/* ---- seat legend: the three statuses, stated once ------------------------- */
.seat-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 18px;
  margin: 0 0 40px;
  padding: 0;
  list-style: none;
}
.seat-legend li {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 13.5px;
  color: #cbd5e1;
}
.seat-legend .dot { width: 10px; height: 10px; border-radius: 3px; }
.seat-legend .dot--free { background: var(--seat-free); box-shadow: 0 0 12px rgba(61, 220, 132, 0.5); }
.seat-legend .dot--booked { background: var(--seat-booked); box-shadow: 0 0 12px rgba(255, 181, 71, 0.5); }
.seat-legend .dot--live { background: var(--seat-live); box-shadow: 0 0 12px rgba(255, 77, 109, 0.5); }

/* ---- phone screenshots: real app screens in a phone outline --------------- */
.phone-shots {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: 26px;
  flex-wrap: wrap;
  perspective: 1500px;
}
.phone-shot { width: 232px; max-width: 100%; }
/* A handset, not a rounded rectangle: a dark metal body, a thicker top bezel
   with the earpiece pill inside it, and one side button. The pill sits in the
   bezel rather than over the screen on purpose — these screenshots were taken
   inside the app, so there is no OS status bar for it to sit in, and an island
   drawn over the content would cover the app's own header.

   The outer two handsets turn slightly towards the middle one. It is the trio
   that reads as a product shot; a fan of three flat pictures reads as three
   pictures. */
.phone-shot-frame {
  position: relative;
  border-radius: 40px;
  padding: 16px 10px 13px;
  background:
    linear-gradient(150deg, #39445e 0%, #151d2f 26%, #0a1020 58%, #2a3450 100%);
  box-shadow:
    0 30px 66px rgba(0, 0, 0, 0.6),
    0 0 0 1px rgba(255, 255, 255, 0.07) inset,
    0 0 26px rgba(7, 221, 241, 0.1);
  transform-origin: 50% 90%;
  transition: transform 420ms cubic-bezier(0.2, 0.8, 0.2, 1),
              box-shadow 420ms ease;
}
.phone-shot-frame img {
  width: 100%;
  height: auto;
  display: block;
  /* Not the 30px the 40px body and 10px bezel would suggest: the screenshot
     itself has controls in its corners. The nearest one — the player's back
     button — sits 14px in and 6px down in the 240px-wide source, which at the
     209-232px this renders at is a hard ceiling of 28.7px before the arc
     starts eating it, and 23.9px on the 174px phone layout. 18px clears every
     size with room to spare and still reads as a screen. Measured, not
     guessed; the numbers are in the note at the end of this sheet. */
  border-radius: 18px;
  background: #020514;
}
/* Earpiece pill. */
.phone-shot-frame::before {
  content: "";
  position: absolute;
  top: 6px;
  left: 50%;
  width: 52px;
  height: 6px;
  margin-left: -26px;
  border-radius: 999px;
  background: #05070f;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.05);
}
/* Side button. */
.phone-shot-frame::after {
  content: "";
  position: absolute;
  right: -2px;
  top: 108px;
  width: 3px;
  height: 46px;
  border-radius: 0 3px 3px 0;
  background: linear-gradient(#3b4763, #1a2235);
}
@media (min-width: 880px) {
  .phone-shots > .phone-shot:first-child .phone-shot-frame { transform: rotateY(9deg); }
  .phone-shots > .phone-shot:last-child .phone-shot-frame { transform: rotateY(-9deg); }
  .phone-shot-frame:hover,
  .phone-shot-frame:focus-within,
  .phone-shots > .phone-shot:first-child .phone-shot-frame:hover,
  .phone-shots > .phone-shot:last-child .phone-shot-frame:hover,
  .phone-shots > .phone-shot:first-child .phone-shot-frame:focus-within,
  .phone-shots > .phone-shot:last-child .phone-shot-frame:focus-within {
    transform: rotateY(0deg) translateY(-8px) scale(1.02);
    box-shadow:
      0 44px 84px rgba(0, 0, 0, 0.66),
      0 0 0 1px rgba(255, 255, 255, 0.1) inset,
      0 0 34px rgba(7, 221, 241, 0.2);
  }
}
@media (prefers-reduced-motion: reduce) {
  .phone-shot-frame,
  .phone-shots > .phone-shot:first-child .phone-shot-frame,
  .phone-shots > .phone-shot:last-child .phone-shot-frame {
    transform: none;
    transition: none;
  }
}
/* Three handsets stacked on a phone is a lot of scrolling for one section, so
   they get smaller where they are the only thing in the column. */
@media (max-width: 520px) {
  .phone-shots { gap: 20px; }
  .phone-shot { width: 190px; }
  .phone-shot-frame { border-radius: 34px; padding: 13px 8px 11px; }
  .phone-shot-frame::after { top: 88px; height: 38px; }
}
.phone-shot figcaption {
  margin-top: 12px;
  text-align: center;
  font-size: 13px;
  color: var(--ink-dim);
}
/* The middle phone sits a little higher so the trio reads as one object
   rather than three separate cards. */
@media (min-width: 880px) {
  .phone-shot--raised { margin-bottom: 34px; }
}

/* ---- compact feature grid, two columns ------------------------------------ */
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
}
@media (max-width: 880px) { .grid-2 { grid-template-columns: 1fr; } }

/* ---- footer navigation ---------------------------------------------------- */
.footer-nav {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 28px;
  padding: 0 0 34px;
  margin: 0 0 30px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
.footer-nav h2 {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: #cfe9ee;
  margin: 0 0 14px;
}
.footer-nav ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.footer-nav a, .footer-nav li { font-size: 14px; color: var(--ink-dim); }
.footer-nav a:hover { color: #07ddf1; }
@media (max-width: 720px) {
  .footer-nav { grid-template-columns: 1fr; gap: 24px; }
}

/* ---- content pages: related links ---------------------------------------- */
.content-related ul {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.content-related a {
  display: inline-flex;
  padding: 10px 18px;
  border-radius: 999px;
  border: 1px solid var(--panel-line);
  background: rgba(11, 18, 36, 0.55);
  color: #cfe9ee;
  font-size: 14px;
  font-weight: 600;
  transition: border-color 160ms ease, color 160ms ease;
}
.content-related a:hover { border-color: var(--panel-line-strong); color: #07ddf1; }

/* ---- nav fits one row on a phone ------------------------------------------
   brand + toggle + language switch came to 365px of content inside a 350px
   row at 390px wide, so the switch wrapped onto a second line and made the
   bar 111px tall. The switch has to stay visible on every layout (it is how a
   visitor changes language), so the three of them are tightened instead. */
@media (max-width: 480px) {
  .nav { gap: 8px; padding: 12px 16px; }
  .nav-brand { gap: 9px; }
  .nav-brand-text { font-size: 15px; letter-spacing: 0.3px; }
  .lang-btn { padding: 4px 7px; letter-spacing: 0.6px; }
}

/* ---- anchored sections clear the fixed bar --------------------------------
   Following "#about" used to land with the heading underneath the nav. */
.section[id],
main[id],
#top { scroll-margin-top: 92px; }
@media (max-width: 860px) { .section[id], main[id], #top { scroll-margin-top: 76px; } }

/* ---- keyboard focus -------------------------------------------------------
   Only the contact form and its submit button had a visible focus ring, so a
   keyboard user tabbing through the nav, the language switch or any call to
   action could not tell where they were. One ring, everywhere, and only for
   keyboard focus so a mouse click does not leave it behind. */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid #07ddf1;
  outline-offset: 3px;
  border-radius: 6px;
}
.btn:focus-visible,
.lang-btn:focus-visible,
.content-related a:focus-visible { border-radius: 999px; }

/* ---- skip link ------------------------------------------------------------
   First stop for a keyboard or screen-reader user: jump past a fixed header
   that otherwise has to be tabbed through on every page. */
.skip-link {
  position: absolute;
  left: 16px;
  top: -60px;
  z-index: 200;
  padding: 10px 18px;
  border-radius: 0 0 12px 12px;
  background: #07ddf1;
  color: #020514;
  font-weight: 700;
  font-size: 14px;
  transition: top 160ms ease;
}
.skip-link:focus { top: 0; }

/* `main` is now the single body child holding the page, so the viewport-width
   clamp that used to apply to each section has to reach through it. */
main > * { max-width: 100vw; overflow-x: clip; }

/* ---- definition list beside a screenshot ----------------------------------
   A term and its explanation, rather than three sentences that read as one
   paragraph broken by bullets. */
.showcase-list { margin: 22px 0 0; }
.showcase-list dt {
  font-weight: 700;
  color: #fff;
  font-size: 15px;
  margin-top: 16px;
}
.showcase-list dt:first-child { margin-top: 0; }
.showcase-list dd {
  margin: 5px 0 0;
  color: var(--ink-dim);
  font-size: 14.5px;
  line-height: 1.55;
}

/* ---- audit fixes ----------------------------------------------------------
   Found by walking every page at ten viewport widths:
   1. The language buttons were 10-11px text in a 24px target. They are the
      one control every visitor may need, so they get legible type and a
      target a thumb can hit, while still fitting one nav row at 320px.
   2. The footer brand block was a non-wrapping row and pushed 7px past a
      320px viewport. */
.lang-btn { font-size: 12px; padding: 9px 12px; }
@media (max-width: 860px) {
  .lang-btn { padding: 13px 10px; font-size: 12px; }
}
@media (max-width: 480px) {
  .lang-btn { padding: 13px 9px; font-size: 12px; letter-spacing: 0.3px; }
}
/* 320px is the narrowest viewport still worth supporting, and the bar has to
   hold the brand, the menu button and three language links on one row there.
   Every value below is the smallest that keeps it to one line. */
@media (max-width: 360px) {
  .nav { padding: 12px; gap: 6px; }
  .nav-brand { gap: 7px; }
  .nav-brand-text { font-size: 13px; }
  .nav-logo { width: 24px; height: 24px; }
  .lang-switch { padding: 2px; gap: 0; }
  .lang-btn { padding: 13px 5px; font-size: 12px; letter-spacing: 0; }
}

.footer-brand-block { flex-wrap: wrap; }
@media (max-width: 380px) {
  .footer-domain { margin-left: 0; }
}

/* Store badges: the "coming soon" line was 10px, below the floor the rest of
   the page keeps. */
.store-badge .small { font-size: 12px; }

/* Footer links are a real tap target on a phone, not an 17px line of text. */
@media (max-width: 720px) {
  .footer-nav ul { gap: 2px; }

}

/* Nav and footer links were a 17px line of text: fine for a mouse, too small
   for a finger on a tablet, where the bar is still horizontal. Padding grows
   the hit area without moving anything on screen. */
.nav-links a { display: inline-block; padding: 8px 0; }
.footer-nav a { display: inline-block; padding: 4px 0; }
@media (max-width: 860px) {
  .nav-links a { padding: 11px 4px; }
}

/* ---- player-app summary under the phones ---------------------------------
   The bullets and the store badges sat hard left under three centred phones.
   They are a closing statement about the app, so they read as one centred
   block with the points in two columns where there is room. */
.mobile-summary {
  margin-top: 56px;
  display: flex;
  justify-content: center;
}
.mobile-summary > div {
  max-width: 640px;
  width: 100%;
}
.mobile-summary .showcase-points {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 28px;
}
.mobile-summary .store-row { justify-content: center; margin-top: 28px; }
@media (max-width: 720px) {
  .mobile-summary .showcase-points { grid-template-columns: 1fr; }
}

/* ============ Touch targets ============ */
/* Everything a finger has to hit is at least 44px tall below 860px — the same
   breakpoint the collapsed nav uses, because 768px and 834px tablets are touch
   devices too. Measured before: the burger 36x36, the language pills 34px, the
   footer links 40px, the email and Telegram rows 22px, the brand link 26px.
   Two reasons this block sits at the end of the file rather than beside the
   rules it corrects: an earlier attempt put it in the `max-width: 720px` block,
   which left both tablet widths untouched, and `.footer-nav a` is restated at
   top level further down the sheet, which silently won on equal specificity. */
@media (max-width: 860px) {
  .footer-nav ul { gap: 2px; }
  .footer-nav a {
    display: inline-block;
    padding: 12px 2px;
    min-height: 44px;
  }
  .contact-list a {
    display: inline-block;
    padding: 11px 0;
    min-height: 44px;
  }
  .nav-brand { padding: 9px 0; }
  .footer-domain {
    display: inline-block;
    padding: 9px 0;
    min-height: 44px;
  }
}

/* ============ Screenshot viewer ============
   The zoom control and the overlay are created by assets/lightbox.js, so none
   of this is reachable on a page without JavaScript — there is nothing to
   style into existence and nothing to press that would not work. */
.shot-zoom {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  padding: 14px;
  border: 0;
  border-radius: inherit;
  background: transparent;
  cursor: zoom-in;
  /* The button covers the screenshot; the chip is the only painted part. */
  -webkit-tap-highlight-color: transparent;
}
.shot-zoom-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 13px;
  border-radius: 999px;
  border: 1px solid rgba(7, 221, 241, 0.35);
  background: rgba(2, 5, 20, 0.82);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: #cfe9ee;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 200ms ease, transform 200ms ease;
}
.shot-zoom-chip svg { width: 15px; height: 15px; }
.app-frame:hover .shot-zoom-chip,
.phone-shot-frame:hover .shot-zoom-chip,
.shot-zoom:focus-visible .shot-zoom-chip {
  opacity: 1;
  transform: none;
}
/* Hover does not exist on a touch screen, so there the affordance is simply
   always on — a screenshot nobody knows they can open is a screenshot nobody
   opens. */
@media (hover: none) {
  .shot-zoom-chip { opacity: 1; transform: none; }
  .shot-zoom { padding: 10px; }
  .shot-zoom-chip { padding: 7px 11px; font-size: 12px; }
}
/* A chip with a label does not fit a 232px handset, and on a phone screen it
   would cover a third of a laptop too, so below that width it is the icon
   alone. The label is the chip's only <span>. */
.phone-shot-frame .shot-zoom-chip > span { display: none; }
.phone-shot-frame .shot-zoom-chip { padding: 9px; }
/* Clear of the bezel and of the screen's rounded corner, at every size. */
.phone-shot-frame .shot-zoom { padding: 15px 13px; }
@media (max-width: 560px) {
  .shot-zoom-chip > span { display: none; }
  .shot-zoom-chip { padding: 10px; }
}
@media (prefers-reduced-motion: reduce) {
  .shot-zoom-chip { transition: none; }
}

.lb {
  position: fixed;
  inset: 0;
  z-index: 500;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 28px 16px;
  background: rgba(2, 5, 20, 0.92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  opacity: 0;
  transition: opacity 180ms ease;
  overscroll-behavior: contain;
}
/* `display: flex` above would otherwise win over the hidden attribute. */
.lb[hidden] { display: none; }
.lb.is-open { opacity: 1; }
.lb-figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  max-width: 100%;
  max-height: 100%;
}
.lb-img {
  max-width: min(1500px, 94vw);
  max-height: 82vh;
  width: auto;
  height: auto;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 40px 90px rgba(0, 0, 0, 0.7);
  cursor: default;
}
.lb-caption {
  max-width: 720px;
  text-align: center;
  font-size: 14px;
  color: var(--ink-dim);
}
.lb-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 46px;
  height: 46px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 14px;
  border: 1px solid rgba(7, 221, 241, 0.3);
  background: rgba(11, 18, 36, 0.9);
  color: #cfe9ee;
  cursor: pointer;
}
.lb-close:hover { border-color: rgba(7, 221, 241, 0.6); color: #07ddf1; }
.lb-close svg { width: 20px; height: 20px; }
html.lb-open { overflow: hidden; }
@media (prefers-reduced-motion: reduce) {
  .lb { transition: none; }
}

/* ============ Mobile navigation: one row, everything else behind the button ============
   The bar used to carry the brand, the burger AND the three language links at
   every width, which is 3 controls competing for 320px and the reason the
   language pills had to be squeezed to 5px of padding to fit. The switch now
   travels with the links into the menu, and the bar is what a phone header
   should be: the logo, and one way in.

   `.js` scoping is the same rule the links already follow. Without JavaScript
   nothing can open the menu, so nothing may be hidden behind it — the switch
   stays in the bar exactly as before, and a visitor can still change language.
   (CLAUDE.md's "always visible on mobile" rule is narrowed to that case, in
   the same change.) */
@media (max-width: 860px) {
  .js .lang-switch {
    display: none;
    order: 4;
    width: 100%;
    justify-content: center;
    background: transparent;
    border: 0;
    border-top: 1px solid rgba(7, 221, 241, 0.12);
    border-radius: 0;
    padding: 8px 0 2px;
    margin-top: 2px;
    gap: 6px;
  }
  .js .nav[data-menu="open"] .lang-switch { display: inline-flex; }
  /* Inside the menu each language is a real target rather than a pill in a
     3-up group: there is a whole row to spend. */
  .js .nav[data-menu="open"] .lang-btn {
    flex: 1;
    max-width: 120px;
    text-align: center;
    border-radius: 10px;
    background: rgba(7, 221, 241, 0.06);
    border: 1px solid rgba(7, 221, 241, 0.16);
  }
  .js .nav[data-menu="open"] .lang-btn.active {
    background: linear-gradient(90deg, #07ddf1, #32aff7 50%, #d152fa);
    border-color: transparent;
  }
  /* The last link in the menu is the one the page is trying to get to, so in
     the menu it reads as the action it is. No new element: the same link. */
  .js .nav[data-menu="open"] .nav-cta {
    display: block;
    width: 100%;
    margin-top: 8px;
    border-radius: 12px;
    background: linear-gradient(90deg, rgba(7, 221, 241, 0.16), rgba(209, 82, 250, 0.16));
    border: 1px solid rgba(7, 221, 241, 0.3);
    color: #ffffff;
    font-weight: 700;
    text-align: center;
  }
  /* An open menu covers the page, so it needs a floor of its own. The bar is
     translucent by design, and `backdrop-filter` is the only thing separating
     it from the content underneath — which iOS Safari and any GPU-less
     renderer may not apply at all, leaving the links written over a
     screenshot. Opaque while open is the version that cannot fail. */
  .js .nav[data-menu="open"] {
    background: rgba(2, 5, 20, 0.97);
    border-bottom-color: rgba(7, 221, 241, 0.2);
  }

  /* A menu taller than the screen — five links, three languages and a phone
     held sideways — has to be able to scroll on its own instead of running off
     the bottom of a fixed bar. */
  .js .nav[data-menu="open"] {
    max-height: 100vh;
    max-height: 100dvh;
    overflow-y: auto;
  }
}

/* The brand link is 44px because of the padding above plus a 26px logo. Below
   360px the logo drops to 24px and the sum is 42, so the padding grows by the
   difference. It has to be stated HERE, after the 860px block: the same rule
   set earlier in the sheet loses to it on equal specificity — the trap already
   documented for `.footer-nav a`. */
@media (max-width: 360px) {
  .nav-brand { padding: 10px 0; }
}

/* ============ About: the positioning paragraphs ============
   Two columns where there is room, one where there is not. Capped at 80
   characters a line, which is where prose stops being comfortable. */
.about-more {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 22px 44px;
  max-width: 1000px;
  margin: 0 auto 44px;
}
.about-more p {
  margin: 0;
  color: var(--ink-dim);
  font-size: 15px;
  line-height: 1.7;
}
@media (max-width: 880px) {
  .about-more { grid-template-columns: 1fr; gap: 16px; margin-bottom: 36px; }
}

/* ============ What is running today ============
   Four figures and the one club they are true in. The numbers are set in the
   display face at a size that carries the section, because the figure IS the
   argument here — the label underneath only says what it counts. */
.trust-figures {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
  margin: 0 0 30px;
  padding: 0;
}
.trust-figure {
  padding: 26px 22px;
  border-radius: 18px;
  border: 1px solid var(--panel-line);
  background: rgba(11, 18, 36, 0.55);
}
.trust-figures dt {
  font-family: "Playstation", "Inter", sans-serif;
  font-size: clamp(38px, 4.6vw, 58px);
  line-height: 1;
  font-weight: 400;
  background: linear-gradient(120deg, #07ddf1, #32aff7 45%, #d152fa);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.trust-figures dd {
  margin: 12px 0 0;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink-dim);
}
@media (max-width: 980px) {
  .trust-figures { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 520px) {
  .trust-figures { grid-template-columns: 1fr; gap: 12px; }
  .trust-figure { padding: 20px 18px; display: flex; align-items: baseline; gap: 16px; }
  /* Side by side the digits have different widths, so "1" and "4" started
     their labels in different places. One column for the figure fixes it. */
  .trust-figures dt { font-size: 34px; flex: 0 0 auto; min-width: 34px; }
  .trust-figures dd { margin-top: 0; }
}

/* The pilot club: a monogram rather than a logo. A logo is somebody else's
   property and needs their permission; a name the status band already carries
   needs none. */
.trust-pilot {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 24px;
  padding: 26px 28px;
  border-radius: 20px;
  border: 1px solid var(--panel-line-strong);
  background:
    linear-gradient(120deg, rgba(7, 221, 241, 0.07), rgba(209, 82, 250, 0.07)),
    rgba(11, 18, 36, 0.6);
}
.trust-mono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  flex-shrink: 0;
  border-radius: 18px;
  border: 1px solid rgba(7, 221, 241, 0.3);
  background: rgba(2, 5, 20, 0.6);
  font-family: "Audiowide", "Inter", sans-serif;
  font-size: 22px;
  letter-spacing: 1px;
  color: #07ddf1;
}
.trust-pilot-body h3 {
  margin: 0 0 8px;
  font-size: 19px;
  font-weight: 700;
  color: #fff;
}
.trust-pilot-body p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-dim);
}
.trust-pilot-cta { white-space: nowrap; }
@media (max-width: 880px) {
  .trust-pilot {
    grid-template-columns: auto minmax(0, 1fr);
    gap: 18px;
    padding: 22px 20px;
  }
  .trust-pilot-cta { grid-column: 1 / -1; justify-content: center; }
}
@media (max-width: 420px) {
  .trust-pilot { grid-template-columns: 1fr; }
  .trust-mono { width: 54px; height: 54px; font-size: 19px; }
}

/* ============ Partners: two marquee rows ============
   The track holds the list TWICE and slides exactly half its own width, so at
   the end of the animation the second copy sits precisely where the first
   started: no seam, no jump, and no need to measure anything in JavaScript.
   Only `transform` is animated, so the browser can keep the whole band on the
   compositor and nothing reflows while it moves. */
.marquees {
  display: grid;
  gap: 16px;
  /* The band is full-bleed on purpose: cards must run out past the container
     rather than stopping at a margin, which is what makes it read as a strip
     rather than a list. */
  margin-top: 8px;
}
.marquee {
  overflow: hidden;
  /* Fades the two ends instead of cutting them, so a card entering the strip
     does not pop into existence at a hard edge. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.marquee-track {
  display: flex;
  /* The spacing is a margin on the card, NOT `gap` on the track, and that is
     load-bearing. With `gap`, a track holding the list twice is
     2N*card + (2N-1)*gap wide, so half of it lands half a gap short of where
     the second copy begins — a 7px jerk on every loop, measured. A trailing
     margin makes the two halves exactly equal and -50% exact. */
  width: max-content;
  margin: 0;
  padding: 6px 0;
  list-style: none;
  animation: marquee-ltr var(--marquee-speed, 64s) linear infinite;
  will-change: transform;
}
.marquee--rtl .marquee-track { animation-name: marquee-rtl; --marquee-speed: 78s; }
.marquee--slow .marquee-track { --marquee-speed: 96s; }
@keyframes marquee-ltr {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
@keyframes marquee-rtl {
  from { transform: translate3d(-50%, 0, 0); }
  to   { transform: translate3d(0, 0, 0); }
}
/* A strip that keeps moving under the pointer cannot be read. Hovering stops
   it; a touch screen has no hover, so there it simply keeps going. */
@media (hover: hover) {
  .marquee:hover .marquee-track,
  .marquee:focus-within .marquee-track { animation-play-state: paused; }
}

.partner-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 196px;
  flex: 0 0 auto;
  margin-right: 14px;   /* see the note on .marquee-track */
  padding: 18px 16px 16px;
  border-radius: 16px;
  border: 1px solid var(--panel-line);
  background: linear-gradient(170deg, rgba(20, 28, 48, 0.75), rgba(11, 18, 36, 0.55));
  transition: transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1),
              border-color 260ms ease, box-shadow 260ms ease;
}
.partner-card:hover,
.partner-card:focus-within {
  transform: translateY(-6px) scale(1.03);
  border-color: var(--panel-line-strong);
  box-shadow: 0 22px 44px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(7, 221, 241, 0.12);
}
/* One visual height for every mark, whatever shape it is. */
.partner-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 48px;
  width: 100%;
}
.partner-logo-img {
  /* One visual height for every mark, whatever shape the file is, and
     `contain` so no logo is ever stretched. Some brands supplied a mark on
     white and some on black; the tile is neutral so both sit on the same
     field without anything being recoloured or redrawn. */
  height: 48px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  border-radius: 10px;
  filter: grayscale(1) contrast(1.05);
  opacity: 0.82;
  transition: filter 320ms cubic-bezier(0.2, 0.8, 0.2, 1),
              opacity 320ms ease,
              transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.partner-card:hover .partner-logo-img,
.partner-card:focus-within .partner-logo-img {
  filter: none;
  opacity: 1;
  transform: scale(1.12);
}
/* The fallback for a company whose logo we do not have the right to publish.
   Initials in the display face — a monogram, not a pretend logo. */
.partner-mono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 12px;
  border: 1px solid rgba(7, 221, 241, 0.22);
  background: rgba(2, 5, 20, 0.55);
  font-family: "Audiowide", "Inter", sans-serif;
  font-size: 15px;
  letter-spacing: 0.5px;
  color: #7fd7e8;
  transition: color 260ms ease, border-color 260ms ease;
}
.partner-card:hover .partner-mono { color: #07ddf1; border-color: rgba(7, 221, 241, 0.45); }
.partner-name {
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  text-align: center;
  line-height: 1.25;
}
.partner-where {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--ink-dim);
  text-align: center;
  line-height: 1.3;
}
.partner-flag { font-size: 14px; line-height: 1; }
.partner-card--featured {
  border-color: rgba(7, 221, 241, 0.34);
  background: linear-gradient(170deg, rgba(7, 221, 241, 0.1), rgba(209, 82, 250, 0.08)), rgba(11, 18, 36, 0.7);
}
.partner-badge {
  margin-top: 2px;
  padding: 4px 10px;
  border-radius: 999px;
  background: linear-gradient(90deg, #07ddf1, #32aff7 55%, #d152fa);
  color: #04121b;
  /* 12px is the floor the rest of the page keeps, and smoke.py enforces it. */
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.3px;
}

/* Testimonials use the same strip; the cards are wider because a quote has to
   be readable in one pass. */
.quote-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: 340px;
  flex: 0 0 auto;
  margin-right: 14px;   /* see the note on .marquee-track */
  padding: 22px 22px 20px;
  border-radius: 18px;
  border: 1px solid var(--panel-line);
  background: rgba(11, 18, 36, 0.6);
}
.quote-card blockquote {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.6;
  color: #cbd5e1;
}
.quote-who { display: flex; flex-direction: column; gap: 2px; }
.quote-name { font-size: 14px; font-weight: 700; color: #fff; }
.quote-role { font-size: 12.5px; color: var(--ink-dim); }
@media (max-width: 520px) {
  .quote-card { width: 280px; }
}

/* Motion off: the strip stops, and because a stopped strip would hide every
   card past the third one, it becomes something the reader can push instead. */
@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none; }
  .marquee {
    overflow-x: auto;
    scrollbar-width: thin;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .partner-card, .partner-logo-img, .partner-mono { transition: none; }
  .partner-card:hover { transform: none; }
  .partner-card:hover .partner-logo-img { transform: none; }
}

/* The pilot card's logo, same treatment as the band's. */
.trust-logo {
  width: 64px;
  height: 64px;
  flex-shrink: 0;
  border-radius: 16px;
  object-fit: contain;
  border: 1px solid rgba(7, 221, 241, 0.3);
  background: rgba(2, 5, 20, 0.6);
}

/* ---- review cards ----------------------------------------------------------
   Same strip, wider cards: a quote has to be readable in one pass, which is
   also why this row runs slower than the partners band. */
.quote-stars {
  font-size: 15px;
  letter-spacing: 2px;
  color: #ffc861;
  line-height: 1;
}
.quote-card blockquote::before { content: "“"; }
.quote-card blockquote::after { content: "”"; }
.quote-who { flex-direction: row; align-items: center; gap: 12px; }
.quote-logo {
  height: 40px;
  width: auto;
  max-width: 88px;
  object-fit: contain;
  border-radius: 8px;
  flex-shrink: 0;
}
.quote-lines { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.quote-where {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--ink-dim);
}
.quote-cta { display: flex; justify-content: center; margin-top: 34px; }
/* A card wide enough to read, and narrow enough that the next one shows at the
   edge — which is what tells a reader there is more. */
@media (max-width: 560px) {
  .quote-card { width: 88vw; max-width: 340px; }
}

/* ---- reviews, before there are any --------------------------------------
   An empty state, not a placeholder: it says where the reviews will be and
   asks for one. It disappears on its own the moment TESTIMONIALS has an
   entry, and it deliberately carries no stars and no quotation — nothing here
   may be mistaken for a review that somebody actually wrote. */
.quote-invite {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  max-width: 640px;
  margin: 0 auto;
  padding: 34px 30px 30px;
  border-radius: 20px;
  border: 1px dashed rgba(7, 221, 241, 0.26);
  background:
    linear-gradient(160deg, rgba(7, 221, 241, 0.05), rgba(209, 82, 250, 0.04)),
    rgba(11, 18, 36, 0.5);
  text-align: center;
}
.quote-invite-mark {
  font-family: "Playstation", "Inter", serif;
  font-size: 40px;
  line-height: 0.6;
  color: rgba(7, 221, 241, 0.45);
}
.quote-invite-text {
  margin: 0;
  max-width: 52ch;
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink-dim);
}
@media (max-width: 560px) {
  .quote-invite { padding: 26px 20px 24px; }
}

/* ---- review cards: stars, the sample label, the wider strip --------------- */
.quote-card {
  /* A quote has to be readable in one pass, so these are the widest cards on
     the page; the strip beneath them runs slower for the same reason. */
  width: 400px;
}
/* A sample card looks like any other card; what marks it is the line under
   the heading and the absence of a name or a company on it. */
.quote-card blockquote { font-size: 15px; }
.quote-disclaimer { font-size: 13.5px; opacity: 0.85; }
@media (max-width: 880px) {
  .quote-card { width: 360px; }
}
@media (max-width: 560px) {
  /* One card fully visible plus the edge of the next, so it reads as a strip
     with more to come rather than a single stranded card. */
  .quote-card { width: 86vw; max-width: 330px; }
}

/* ============ The mobile menu opens instead of appearing ============
   It used to flip between `display: none` and `display: flex`, which cannot
   be animated: the links were simply there on the next frame. The panel is
   laid out at all times now and animates its height, so opening reads as the
   bar unfolding.

   `visibility` is what keeps a closed menu out of reach — of a tap, of Tab and
   of a screen reader — because a zero-height box with `overflow: hidden` is
   still focusable. It is delayed by the length of the animation on close so
   the links do not vanish halfway through it. */
@media (max-width: 860px) {
  .js .nav-links,
  .js .lang-switch {
    display: flex;
    max-height: 0;
    opacity: 0;
    visibility: hidden;
    overflow: hidden;
    padding-top: 0;
    padding-bottom: 0;
    border-top-width: 0;
    transition: max-height 320ms cubic-bezier(0.2, 0.8, 0.2, 1),
                opacity 200ms ease,
                padding 320ms cubic-bezier(0.2, 0.8, 0.2, 1),
                visibility 0s linear 320ms;
  }
  .js .nav[data-menu="open"] .nav-links,
  .js .nav[data-menu="open"] .lang-switch {
    max-height: 60vh;
    opacity: 1;
    visibility: visible;
    overflow-y: auto;
    transition: max-height 340ms cubic-bezier(0.2, 0.8, 0.2, 1),
                opacity 260ms ease 60ms,
                padding 340ms cubic-bezier(0.2, 0.8, 0.2, 1),
                visibility 0s linear;
  }
  .js .nav[data-menu="open"] .nav-links { padding: 6px 0 2px; border-top-width: 1px; }
  .js .nav[data-menu="open"] .lang-switch { padding: 8px 0 2px; border-top-width: 1px; }
  /* The burger icon turns rather than swaps. */
  .nav-toggle svg { transition: transform 280ms cubic-bezier(0.2, 0.8, 0.2, 1); }
  .nav-toggle[aria-expanded="true"] .nav-toggle-close { transform: rotate(90deg); }
}
@media (prefers-reduced-motion: reduce) {
  .js .nav-links,
  .js .lang-switch,
  .js .nav[data-menu="open"] .nav-links,
  .js .nav[data-menu="open"] .lang-switch,
  .nav-toggle svg { transition: none; }
}

/* ============ Cards sized for a thumb ============
   Partner cards were 196px at every width, which on a 390px screen leaves the
   second card sliced in half and the text cramped. Smaller cards fit two
   whole ones with room to read. Review cards keep their width — a quote needs
   it — but lose the padding and type size that were tuned for a desktop. */
@media (max-width: 560px) {
  .partner-card {
    width: 152px;
    padding: 14px 12px 13px;
    gap: 6px;
    margin-right: 10px;
  }
  .partner-logo { height: 38px; }
  .partner-logo-img { height: 38px; }
  .partner-name { font-size: 13px; }
  .partner-where { font-size: 12px; gap: 5px; }
  .partner-flag { font-size: 13px; }

  .quote-card { width: 84vw; max-width: 320px; padding: 18px 18px 16px; gap: 11px; }
  .quote-card blockquote { font-size: 14px; line-height: 1.55; }
  .quote-stars { font-size: 14px; }
}
@media (max-width: 380px) {
  .partner-card { width: 142px; }
  .quote-card { width: 86vw; }
}

/* ============ The strips, under a finger ============
   A finger cannot grab a CSS animation. On a coarse pointer the animation
   comes off and each strip becomes natively scrollable, so a swipe works in
   both directions with the platform's own momentum — and it works whether or
   not assets/marquee.js ever loads. That file only adds the drift back on
   top, by moving `scrollLeft`, which is the same thing the finger moves. */
@media (hover: none) {
  .marquee {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* A dragged strip should follow the finger, not the page. */
    touch-action: pan-x;
  }
  .marquee::-webkit-scrollbar { display: none; }
  .marquee-track { animation: none; will-change: auto; }
}

/* ============ Community cards on a phone ============
   The two QR cards stacked into one column below 880px, which made the
   section three screens tall on a phone for two links. They stay side by side
   instead, with a smaller code: nobody scans a QR with the phone that is
   showing it, so on a phone the card is really a link and the code is there
   for the person standing next to you. */
@media (max-width: 880px) {
  .social-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .social-card { padding: 20px 14px 18px; }
  .social-qr img { width: 100%; max-width: 180px; }
  .social-head { margin-bottom: 14px; gap: 8px; }
}
@media (max-width: 560px) {
  .social-card { padding: 16px 10px 14px; border-radius: 16px; }
  .social-head { flex-direction: column; gap: 6px; margin-bottom: 10px; }
  .social-icon { width: 34px; height: 34px; border-radius: 10px; }
  .social-name { font-size: 15px; }
  .social-qr img { max-width: 132px; }
  /* The label wraps to two lines in a 166px card, which left the little scan
     icon stranded beside the first one. Stack it instead. */
  .social-scan {
    flex-direction: column;
    align-items: center;
    font-size: 12px;
    gap: 5px;
    text-align: center;
  }
  .social-scan svg { width: 15px; height: 15px; }
}
@media (max-width: 360px) {
  .social-grid { gap: 10px; }
  .social-qr img { max-width: 112px; }
}

/* ============ Two mobile fixes ============ */

/* 1. The hero kicker sat under the fixed bar.
   `.hero-text--lead` asks for 130px of top inset at 720px, and the later
   `.section { padding: 80px 22px }` — same specificity, further down the
   sheet — quietly replaced the whole shorthand with 80px. The first line of
   «Գեյմինգ ակումբի կառավարման միասնական համակարգ» was therefore 7px behind
   the bar at 390px. Restated here, after that rule, which is the only place
   it wins. */
@media (max-width: 720px) {
  .hero-text--lead { padding-top: 136px; padding-bottom: 84px; }
}

/* 2. The zoom chip sat over the bezel corner rather than on the screen, at
   the phone layout's tighter padding. (The screen's corner radius, the other
   half of this fix, is on `.phone-shot-frame img` itself — it was cut off at
   every width, not only here, so it does not belong in a media query.) */
@media (max-width: 520px) {
  .phone-shot-frame .shot-zoom { padding: 16px 14px; }
}

/* ============ Back to top ============ */

/* Built by nav.js on every page (see the note there: without JavaScript it
   would be a button that does nothing). Bottom-right, so it never meets the
   hero's scroll cue, which is bottom-centre and gone by 120px anyway; under
   the bar (z-index 100) and well under the image viewer (500). The chip
   vocabulary is the screenshots' zoom chip — same border, same glass, same
   corner — because this is the same kind of control. */
.to-top {
  position: fixed;
  right: 20px;
  bottom: calc(20px + env(safe-area-inset-bottom, 0px));
  z-index: 90;
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid rgba(7, 221, 241, 0.35);
  border-radius: 999px;
  background: rgba(2, 5, 20, 0.82);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: #cfe9ee;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.45), 0 0 18px rgba(7, 221, 241, 0.12);
  /* Out of the way until there is something to go back up from. `visibility`
     rather than `display` so it can fade, and so it is out of the tab order
     while it is invisible. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition: opacity 240ms ease, transform 240ms ease,
              visibility 0s linear 240ms, border-color 200ms ease,
              box-shadow 200ms ease;
}
.to-top.is-in {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}
.to-top svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* The hop is the whole affordance: a still circle in a corner reads as an
     ornament. Two pixels, slowly — enough to catch the eye at the edge of
     vision, not enough to compete with the section being read. */
  animation: to-top-hop 1900ms ease-in-out infinite;
}
@keyframes to-top-hop {
  0%, 100% { transform: translateY(2px); }
  50%      { transform: translateY(-2px); }
}
.to-top:hover {
  border-color: rgba(7, 221, 241, 0.7);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.5), 0 0 24px rgba(7, 221, 241, 0.26);
}
.to-top:focus-visible {
  outline: 2px solid rgba(7, 221, 241, 0.9);
  outline-offset: 3px;
}
/* On a phone it has to be spotted without being in the way: the accessible
   minimum, tucked closer to the corner, above the home indicator. */
@media (max-width: 560px) {
  .to-top { width: 44px; height: 44px; right: 14px; bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }
  .to-top svg { width: 18px; height: 18px; }
}
/* Nothing floats over the open viewer or over the open menu. */
.lb-open .to-top,
.nav[data-menu="open"] ~ .to-top {
  opacity: 0;
  visibility: hidden;
  transition-delay: 0s;
}
@media (prefers-reduced-motion: reduce) {
  .to-top { transition: none; }
  .to-top svg { animation: none; transform: none; }
}

/* ============ Carrying your place across a language switch ============ */

/* Set by nav.js for one load, when the visitor arrives from the language
   switcher and the script has just put the page back where they were. Both
   rules exist so that the page APPEARS there rather than travelling there:
   the sheet's smooth scrolling would animate the jump, and the reveal
   transition would slide every visible section in as if the page had just
   been opened — which is exactly what the visitor asked us to stop doing.
   The class is removed as soon as the position has settled, so the next
   section they scroll to still animates normally. */
html.scroll-carry { scroll-behavior: auto; }
html.scroll-carry .reveal { transition: none; }

/* ============ The contact rows have to look like links ============ */

/* They were cyan text with an underline that appeared only on hover, next to a
   grey value on the "hours" row that is not a link at all — so the only signal
   was the colour, and the owner reported that people did not realise they could
   be pressed. Three signals now, in order of how quickly they read:
   the channel's own glyph, a permanent underline, and — on the two that leave
   the site — the corner arrow every browser user already knows. */
.contact-list a {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  /* The underline lives on the text, not on the flex box: a decoration set on
     a flex container is not reliably drawn under its text children. */
  text-decoration: none;
}
.contact-list a .contact-text {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(7, 221, 241, 0.45);
  text-underline-offset: 4px;
  transition: text-decoration-color 180ms ease;
}
.contact-list a:hover .contact-text,
.contact-list a:focus-visible .contact-text {
  text-decoration-color: currentColor;
}
.contact-icon,
.contact-out {
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.contact-icon { width: 18px; height: 18px; }
/* Smaller and quieter than the channel glyph: it is a note about where the
   link goes, not a second icon competing with the first. */
.contact-out {
  width: 13px;
  height: 13px;
  opacity: 0.65;
  transition: transform 180ms ease, opacity 180ms ease;
}
.contact-list a:hover .contact-out,
.contact-list a:focus-visible .contact-out {
  transform: translate(2px, -2px);
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .contact-list a .contact-text,
  .contact-out { transition: none; }
  .contact-list a:hover .contact-out,
  .contact-list a:focus-visible .contact-out { transform: none; }
}
