/* Shared styles for the 2026 refresh: dither background, ferrofluid accent,
 * scroll reveal. Hosts keep their own backgrounds; canvases layer over them
 * and real content is lifted above. */

/* ── Dither waves ────────────────────────────────────────────────────────── */

[data-dither] {
  position: relative;
  overflow: hidden;
}

.dither-canvas {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Full-bleed heroes: the section spans the viewport and dither waves run
 * edge to edge, from under the topbar down into the page background. */
.hero,
.page-hero,
.speed-hero {
  width: 100%;
}

/* Real content sits above the canvas. Canvas elements are excluded: the
 * starry-sky canvas must keep its absolute positioning from effects.css. */
[data-dither] > :not(canvas) {
  position: relative;
  z-index: 1;
}

/* Narrow screens: hero copy keeps the centered composition of the home
 * page instead of snapping to the left edge. */
@media (max-width: 760px) {
  .page-hero-grid { text-align: center; }
  .page-hero-grid .eyebrow { justify-content: center; }
}

/* ── Ferrofluid accent ───────────────────────────────────────────────────── */

[data-ferrofluid] {
  position: relative;
}

.ferrofluid-canvas {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: auto;
}

[data-ferrofluid] > :not(canvas) {
  position: relative;
  z-index: 2;
}

/* ── Section seams ───────────────────────────────────────────────────────── */

/* The light page meets dark sections with a fine luminous horizon line that
 * fades toward the edges, so the boundary reads as designed, not cut. */
.apps-section::after {
  content: "";
  position: absolute;
  top: 0;
  left: 7%;
  right: 7%;
  height: 1px;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to right, transparent, rgba(129, 226, 255, 0.4), transparent);
}

html[data-theme="dark"] .apps-section::after {
  background: linear-gradient(to right, transparent, rgba(129, 226, 255, 0.26), transparent);
}

/* Telegram cabinet hero re-renders on every state refresh, so a WebGL canvas
 * would be destroyed repeatedly. A pure-CSS fluid sheen is used there. */
.cabin-hero::after {
  content: "";
  position: absolute;
  inset: -40%;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(38% 46% at 24% 38%, color-mix(in srgb, var(--sky) 26%, transparent), transparent 70%),
    radial-gradient(30% 42% at 74% 66%, color-mix(in srgb, var(--violet) 24%, transparent), transparent 72%),
    radial-gradient(22% 30% at 58% 22%, color-mix(in srgb, var(--blue) 14%, transparent), transparent 70%);
  filter: blur(18px);
  animation: cabin-fluid 14s ease-in-out infinite alternate;
}

@keyframes cabin-fluid {
  0% { transform: translate3d(-2.5%, -1.5%, 0) rotate(0deg) scale(1); }
  50% { transform: translate3d(2.5%, 2%, 0) rotate(3deg) scale(1.06); }
  100% { transform: translate3d(-1.5%, 2.5%, 0) rotate(-2.5deg) scale(1.02); }
}

@media (prefers-reduced-motion: reduce) {
  .cabin-hero::after { animation: none; }
}

/* ── Scroll reveal ───────────────────────────────────────────────────────── */

/* Elements are only hidden while JS has armed the effect (data-reveal-ready)
 * and each element has not revealed yet. No-JS or script failure = visible. */
html[data-reveal-ready] [data-reveal]:not(.is-revealed) {
  opacity: 0;
  transform: translateY(26px);
  will-change: opacity, transform;
}

html[data-reveal-ready] [data-reveal] {
  transition:
    opacity 720ms cubic-bezier(0.22, 0.72, 0.18, 1),
    transform 720ms cubic-bezier(0.22, 0.72, 0.18, 1);
}

html[data-reveal-ready] [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  html[data-reveal-ready] [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .dither-canvas,
  .ferrofluid-canvas { display: none; }
}

/* ── Globe refresh: subtle halo and label polish, no behavior change ─────── */

.globe-panel::after,
.cta-panel::after {
  /* Soft light bleed behind the panel edge; keeps the atlas feeling lit. */
  pointer-events: none;
}

/* ── Mobile typography hygiene ───────────────────────────────────────────
 * Unbounded is very wide; at phone widths long words overflow their grid
 * tracks and inflate parents (clipped headings, sideways sections).
 * Grid items may shrink below content size and oversized words wrap. */
@media (max-width: 760px) {
  .truth-grid > *,
  .price-stage > *,
  .include-board > *,
  .payment-ledger > *,
  .cta-panel > *,
  .apps-head > *,
  .bot-stage-shell > *,
  .speed-heading > *,
  .page-hero-grid > * { min-width: 0; }

  .section-title,
  .include-card h3,
  .app-card h3,
  .cta-panel h2,
  .document-section h2,
  .truth-copy h2,
  .price-copy h2,
  .route-card h2,
  .faq-intro h2,
  .page-hero h1,
  .speed-heading h1 {
    overflow-wrap: anywhere;
    hyphens: auto;
  }

  /* Hairline label rows ("два варианта / создаются одной кнопкой") wrap
     instead of pushing the heading out of the panel. */
  .section-label,
  .panel-label,
  .eyebrow { overflow-wrap: break-word; }

  /* Bot route rail: node names like "санкт-петербург" must wrap inside
   * their 1fr cells instead of stretching the rail. */
  .bot-route-rail li,
  .bot-route-rail li b,
  .bot-route-rail li span { overflow-wrap: anywhere; }
}

/* info hero: portal.css narrows the first column for the desktop side note;
 * without this the narrow track survives the mobile breakpoint and squeezes
 * the h1 into a 45px sliver. */
@media (max-width: 980px) {
  .info-hero .page-hero-grid { grid-template-columns: minmax(0, 1fr); }
}

.globe-wrap::before {
  content: "";
  position: absolute;
  inset: auto 8% 6% 8%;
  height: 26%;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 62%, rgba(83, 101, 246, 0.16), transparent 68%);
  filter: blur(14px);
}

html[data-theme="dark"] .globe-wrap::before {
  background: radial-gradient(ellipse at 50% 62%, rgba(117, 216, 255, 0.12), transparent 68%);
}

.speed-atlas .network-atlas__canvas-wrap::before {
  content: "";
  position: absolute;
  inset: auto 8% 6% 8%;
  height: 26%;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 62%, rgba(117, 216, 255, 0.12), transparent 68%);
  filter: blur(14px);
}
