/*
  Cross-browser base reset
  (снижает различия отображения между Chrome/Safari/Firefox + мобильными)
*/
*, *::before, *::after{ box-sizing: border-box; }
html, body{ height: 100%; }
body{ margin: 0; }

img, svg{ display: block; max-width: 100%; }

button, input, textarea, select{ font: inherit; color: inherit; }
button{ -webkit-tap-highlight-color: transparent; }
input, textarea, select{ -webkit-appearance: none; appearance: none; }

:root{
  --nav-h: 70px;
  --orb-spin-dur: 18s;
  --orb-spin-delay: 0s;
}


main, header, footer{
  position: relative;
  z-index: 1;
}


.fx-panel{
  background: rgba(0,0,0,0.36);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 24px;
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow:
    0 22px 60px rgba(0,0,0,0.75),
    inset 0 1px 0 rgba(255,255,255,0.06);
}

@media (max-width: 520px){
  .fx-panel{ border-radius: 18px; }
}


body.fx{
  position: relative;
  overflow-x: hidden;
}

body.fx{
  --fractal-image: none;
  --fractal-opacity: 0.55;
  --fractal-saturate: 1.15;
  --fractal-brightness: 1.05;
}


body.fx[data-fractal="blue"]{
  --fractal-image: url("../img/fractal-blue.png");
  --fractal-opacity: 0.72;
}
body.fx[data-fractal="deep"]{
  --fractal-image: url("../img/fractal-deep-yellow.jpg");
  --fractal-opacity: 0.68;
}
body.fx[data-fractal="licenses"]{
  --fractal-image: url("../img/fractal-licenses.jpg");
  --fractal-opacity: 0.68;
}
body.fx[data-fractal="gallery"]{
  --fractal-image: url("../img/fractal-1151616_1280.jpg");
  --fractal-opacity: 0.60;
}
body.fx[data-fractal="premium"]{
  --fractal-image: none;
  --fractal-opacity: 1;
  --fractal-saturate: 1;
  --fractal-brightness: 1;
}
body.fx[data-fractal="none"]{
  --fractal-image: none;
  --fractal-opacity: 0;
}

body.fx::before{
  content:"";
  position: fixed;
  inset: -22px;
  pointer-events: none;
  z-index: -2;

  background-image:
    radial-gradient(circle at center,
      rgba(0,0,0,0.65) 0%,
      rgba(0,0,0,0.78) 55%,
      rgba(0,0,0,0.92) 100%),
    var(--fractal-image);

  background-position: center, center;
  background-size: cover, cover;
  background-repeat: no-repeat, no-repeat;

  opacity: var(--fractal-opacity);
  filter: saturate(var(--fractal-saturate)) brightness(var(--fractal-brightness));
  animation: fxFractalBreath 22s ease-in-out infinite alternate;
  transform: translate3d(0,0,0) scale(1.06);
}

@keyframes fxFractalBreath{
  0%   { transform: scale(1.05) translate3d(0,0,0); }
  50%  { transform: scale(1.10) translate3d(10px,-8px,0); }
  100% { transform: scale(1.13) translate3d(-10px,10px,0); }
}

body.fx::after{
  content:"";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: -1; 

  opacity: 0.08;
  background-image:
    repeating-linear-gradient(0deg,
      rgba(255,255,255,0.05) 0,
      rgba(255,255,255,0.05) 1px,
      rgba(0,0,0,0) 2px,
      rgba(0,0,0,0) 4px);
  mix-blend-mode: multiply;
}



body.fx[data-fractal="premium"]::before{
  background-image:
    radial-gradient(circle at 18% 12%, rgba(255,255,255,0.08) 0%, rgba(255,255,255,0.02) 40%, rgba(0,0,0,0) 72%),
    radial-gradient(circle at 82% 88%, rgba(155,92,255,0.10) 0%, rgba(0,0,0,0) 62%),
    linear-gradient(180deg, rgba(0,0,0,0.96) 0%, rgba(10,10,14,0.98) 100%);
  opacity: 1;
  filter: none;
  animation: none;
  transform: none;
}

body.fx[data-fractal="premium"]::after{
  opacity: 0.10;
}

body.fx nav{
  background: rgba(8,8,10,0.92) !important;
  border-bottom: 1px solid rgba(255,255,255,0.10) !important;
}

body.fx nav a{
  opacity: 0.74 !important;
  letter-spacing: 0.14em !important;
}

body.fx nav a::after{
  background: rgba(255,255,255,0.45) !important;
}

body.fx nav a:hover{
  opacity: 1 !important;
}

body.fx .nav-logo{
  text-shadow: none !important;
}

body.fx .nav-cta{
  background: rgba(255,255,255,0.06) !important;
  box-shadow: 0 10px 28px rgba(0,0,0,0.35) !important;
}

body.fx .nav-cta:hover{
  box-shadow: 0 16px 46px rgba(0,0,0,0.55) !important;
}

/* =========================================================
   React fractal background (all pages except main)
   - injected by js/app.js
   ========================================================= */

#fx-fractal-react{
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  overflow: hidden;
}

#fx-fractal-react .fx-fractal-canvas{
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0.34;
  mix-blend-mode: multiply;
  filter: blur(0.25px) saturate(1.65) contrast(1.35);

  /* мягко прячем края, чтобы эффект не лез в интерфейс */
  -webkit-mask-image: radial-gradient(circle at center,
    rgba(0,0,0,1) 0%,
    rgba(0,0,0,1) 58%,
    rgba(0,0,0,0) 92%
  );
  mask-image: radial-gradient(circle at center,
    rgba(0,0,0,1) 0%,
    rgba(0,0,0,1) 58%,
    rgba(0,0,0,0) 92%
  );
}

@media (prefers-reduced-motion: reduce){
  #fx-fractal-react .fx-fractal-canvas{ opacity: 0.18; }
}

/* =========================================================
   Fallback (если React/CDN недоступны): "fractal dust" overlay
   ========================================================= */

.fractal-dust{
  position: fixed;
  inset: -30vh -30vw;
  z-index: -2;
  pointer-events: none;
  opacity: 0.10;
  filter: saturate(0.9) brightness(1.05) blur(0.3px);
  mix-blend-mode: multiply;
  background-image:
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='480'%20height='480'%20viewBox='0%200%20480%20480'%3E%3Cfilter%20id='n'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='0.85'%20numOctaves='3'%20stitchTiles='stitch'/%3E%3CfeColorMatrix%20type='matrix'%20values='1%200%200%200%200%200%201%200%200%200%200%200%201%200%200%200%200%200%200.30%200'/%3E%3C/filter%3E%3Crect%20width='100%25'%20height='100%25'%20filter='url(%23n)'/%3E%3C/svg%3E"),
    radial-gradient(circle at 18% 22%, rgba(255, 105, 180, 0.22), rgba(255, 105, 180, 0) 55%),
    radial-gradient(circle at 82% 28%, rgba(255, 153, 0, 0.18), rgba(255, 153, 0, 0) 58%),
    radial-gradient(circle at 72% 78%, rgba(168, 85, 247, 0.18), rgba(168, 85, 247, 0) 60%),
    radial-gradient(circle at 20% 82%, rgba(34, 197, 94, 0.16), rgba(34, 197, 94, 0) 62%);
  background-size: 360px 360px, 1200px 1200px, 1200px 1200px, 1200px 1200px, 1200px 1200px;
  background-repeat: repeat, no-repeat, no-repeat, no-repeat, no-repeat;
  transform: translate3d(0,0,0);
  animation: fractalDustDrift 110s linear infinite;
}

@keyframes fractalDustDrift{
  0%   { transform: translate3d(0,0,0) scale(1); }
  50%  { transform: translate3d(-3vw,-2vh,0) scale(1.02); }
  100% { transform: translate3d(-6vw,-4vh,0) scale(1.04); }
}

@media (prefers-reduced-motion: reduce){
  .fractal-dust{ animation: none; }
}

/* =========================================================
   Portfolio card gallery controls
   ========================================================= */

.portfolio-image[data-images]{
  position: relative;
}

.portfolio-image .pg-btn{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.22);
  background: rgba(0,0,0,0.38);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.18s ease, transform 0.18s ease;
}

.portfolio-image:hover .pg-btn{
  opacity: 1;
}

.portfolio-image .pg-btn:active{
  transform: translateY(-50%) scale(0.98);
}

.portfolio-image .pg-prev{ left: 10px; }
.portfolio-image .pg-next{ right: 10px; }

.portfolio-image .pg-dots{
  position: absolute;
  left: 50%;
  bottom: 10px;
  transform: translateX(-50%);
  display: flex;
  gap: 6px;
  padding: 6px 8px;
  border-radius: 999px;
  background: rgba(0,0,0,0.26);
  border: 1px solid rgba(255,255,255,0.14);
  opacity: 0;
  transition: opacity 0.18s ease;
}

.portfolio-image:hover .pg-dots{ opacity: 1; }

.portfolio-image .pg-dot{
  width: 8px;
  height: 8px;
  border-radius: 999px;
  border: 0;
  background: rgba(255,255,255,0.35);
  cursor: pointer;
  padding: 0;
}

.portfolio-image .pg-dot.active{ background: rgba(255,255,255,0.92); }

@media (max-width: 768px){
  .portfolio-image .pg-btn,
  .portfolio-image .pg-dots{ opacity: 1; }
}

/* Extra line inside portfolio description */
.portfolio-content p .docline{
  display: inline-block;
  margin-top: 10px;
  opacity: 0.82;
  font-size: 0.86em;
}


body::before{
  z-index: -3;
}



@keyframes orbSpin{
  0%   { transform: translateZ(0) rotate(0deg); }
  100% { transform: translateZ(0) rotate(360deg); }
}


@keyframes orbCoreSpin{
  0%   { transform: translateZ(0) scale(1.12) rotate(0deg); }
  100% { transform: translateZ(0) scale(1.12) rotate(360deg); }
}

.orb-spin{
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
  opacity: 0.98;
  pointer-events: none;
  user-select: none;


  animation: orbSpin var(--orb-spin-dur) linear infinite;
  animation-delay: var(--orb-spin-delay);

  transform-origin: center center;
  will-change: transform;
  transform: translateZ(0);


  -webkit-mask-image: radial-gradient(circle at center,
    rgba(0,0,0,1) 0%,
    rgba(0,0,0,1) 88%,
    rgba(0,0,0,0) 100%
  );
  mask-image: radial-gradient(circle at center,
    rgba(0,0,0,1) 0%,
    rgba(0,0,0,1) 88%,
    rgba(0,0,0,0) 100%
  );
  -webkit-mask-repeat:no-repeat;
  mask-repeat:no-repeat;
  -webkit-mask-position:center;
  mask-position:center;
  -webkit-mask-size:100% 100%;
  mask-size:100% 100%;
}


.orb-stage{
  position: relative;
  width: 100%;
  height: 100%;
  isolation: isolate;
  pointer-events: none;
  user-select: none;
}

.orb-canvas,
.cube-canvas{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  background: transparent;
}


.orb-canvas{
  filter: drop-shadow(0 28px 60px rgba(0,0,0,.55));
}


.cube-canvas{
  /* Тёплая золотая подсветка под рёбра куба (кроссбраузерно) */
  filter: drop-shadow(0 14px 28px rgba(212,175,55,.26));
}

