/* พื้นหลังสีน้ำเงินแบบขยับ
   ===========================================================================
   โหลดเป็นไฟล์สุดท้ายของ index.html เพื่อให้ทับค่าพื้นหลังเดิมได้
   แยกเป็นไฟล์ของตัวเองเพื่อให้ปิดทั้งหมดได้ด้วยการลบ <link> บรรทัดเดียว

   วิธีทำงาน
   ---------------------------------------------------------------------------
   วางม่านแสงสองชั้นไว้หลังเนื้อหาทั้งหน้า (body::before และ body::after)
   แต่ละชั้นเป็นก้อนแสง radial-gradient ที่ค่อย ๆ เลื่อนคนละทิศคนละจังหวะ
   สองชั้นเหลื่อมกันทำให้ดูเหมือนแสงไหลจริง ไม่ใช่ภาพเดียวขยับไปมา

   ทำไมต้องแตะพื้นหลังของ section ด้วย
   ---------------------------------------------------------------------------
   .hero .pricing .faq .closing เดิมมีพื้นหลังทึบของตัวเอง ถ้าไม่ทำให้โปร่ง
   ม่านแสงจะถูกบังจนเห็นเฉพาะช่วงกลางหน้า กลายเป็นขยับแค่บางส่วน
   จึงเปลี่ยนเป็นสีเดิมแบบโปร่งแสง ให้แสงลอดขึ้นมาได้ทั้งหน้าอย่างต่อเนื่อง

   เรื่องที่ต้องระวังถ้าจะแก้ต่อ
   ---------------------------------------------------------------------------
   1. สีของก้อนแสงต้องเป็นน้ำเงินเข้ม ไม่ใช่น้ำเงินสด ถ้าสว่างกว่านี้ตัวหนังสือ
      สีขาวบนพื้นจะอ่านยากลง ซึ่งผิดเกณฑ์ contrast ที่หน้านี้ผ่านอยู่
   2. เลื่อนด้วย transform เท่านั้น ห้ามใช้ background-position หรือ filter: blur()
      เพราะสองอย่างหลังทำให้เบราว์เซอร์วาดใหม่ทุกเฟรม เครื่องช้าและมือถือจะกระตุก
   3. ต้องเหลือ @media (prefers-reduced-motion: reduce) ไว้เสมอ คนที่ตั้งค่าเครื่อง
      ว่าไม่เอาภาพเคลื่อนไหวมักมีเหตุผลด้านสุขภาพ เช่น เวียนหัวจากการมองภาพขยับ
   =========================================================================== */

/* พื้นสีฐานย้ายไปไว้ที่ html เพราะถ้า body ยังมีพื้นทึบอยู่ จะบังม่านแสงที่วาง
   ไว้ข้างหลัง (ชั้น z-index ติดลบ ถูกวาดก่อนพื้นหลังของ body) */
html { background: var(--gts-bg-950, #020812); }
body { background: transparent; }

body::before,
body::after {
  content: "";
  position: fixed;
  /* ล้นออกนอกจอไว้ เวลาก้อนแสงเลื่อนจะได้ไม่เห็นขอบว่าง */
  inset: -30vmax;
  /* อยู่ลึกกว่ากริด 3D หนึ่งชั้น ให้เส้นกริดคมอยู่ข้างหน้าแสง ไม่ถูกแสงกลบ */
  z-index: -2;
  pointer-events: none;
  will-change: transform;
}

body::before {
  background:
    radial-gradient(36vmax 30vmax at 20% 24%, rgba(16, 96, 196, .58), transparent 66%),
    radial-gradient(42vmax 34vmax at 52% 92%, rgba(11, 68, 152, .52), transparent 68%);
  animation: gtsAuroraDriftA 30s ease-in-out infinite alternate;
}

body::after {
  background:
    radial-gradient(32vmax 28vmax at 82% 36%, rgba(0, 134, 224, .44), transparent 66%),
    radial-gradient(28vmax 24vmax at 8% 72%, rgba(20, 108, 208, .38), transparent 68%);
  animation: gtsAuroraDriftB 42s ease-in-out infinite alternate;
}

/* ระยะเลื่อนกว้างขึ้นกว่าเดิมเพื่อให้เห็นว่าขยับชัดขึ้น แต่ยังเป็นหน่วย % ของ
   ตัวชั้นแสงเอง ซึ่งล้นออกนอกจอไว้ 30vmax แล้ว จึงไม่มีทางเลื่อนจนเห็นขอบว่าง */
@keyframes gtsAuroraDriftA {
  0%   { transform: translate3d(-5%, -4%, 0) scale(1.04); }
  50%  { transform: translate3d(7%, 5%, 0) scale(1.18); }
  100% { transform: translate3d(-3%, 8%, 0) scale(1.08); }
}

@keyframes gtsAuroraDriftB {
  0%   { transform: translate3d(5%, 5%, 0) scale(1.12); }
  50%  { transform: translate3d(-7%, -4%, 0) scale(1.02); }
  100% { transform: translate3d(3%, -8%, 0) scale(1.15); }
}

/* ── เปิดทางให้แสงลอดผ่าน section ที่เคยทึบ ───────────────────────────────── */

/* ยังเก็บลวดลายเดิมของแต่ละ section ไว้ครบ เปลี่ยนแค่สีพื้นชั้นล่างสุด
   จากทึบเป็นโปร่ง เพื่อให้ยังแยกออกว่าแต่ละ section เริ่มและจบตรงไหน */

/* เฮโร่ — ก้อนแสงน้ำเงินสองก้อนของเดิมยังอยู่ครบ โปร่งเฉพาะชั้นพื้นล่างสุด */
.gx-hero {
  background:
    radial-gradient(ellipse 60% 55% at 72% 38%, rgba(0, 90, 180, .32), transparent 70%),
    radial-gradient(ellipse 50% 60% at 10% 30%, rgba(7, 40, 90, .45), transparent 70%),
    linear-gradient(180deg, rgba(2, 8, 18, .56) 0%, rgba(4, 16, 36, .66) 55%, rgba(2, 8, 18, .56) 100%);
}

/* หน้านี้ไล่แถบสลับเข้ม–อ่อนทีละ section อยู่แล้ว ถ้าปล่อยให้ทึบตามเดิม
   ม่านแสงจะโผล่แค่ section เว้น section กลายเป็นขยับ ๆ หาย ๆ */
main > .section:nth-of-type(even) {
  background: linear-gradient(180deg, rgba(2, 8, 18, .44), rgba(4, 16, 31, .58) 50%, rgba(2, 8, 18, .44));
}

/* section ลำดับคี่เดิมไม่มีพื้นหลังเลย ตัวหนังสือจึงวางอยู่บนแสงเต็ม ๆ
   วัดแล้วได้ contrast 3.53 ซึ่งตกเกณฑ์ AA (4.5) อ่านยากจริงตรงจุดที่แสงแรงสุด
   จึงต้องมีผ้าคลุมบาง ๆ รองไว้ บางพอที่ยังเห็นกริดและแสงลอดผ่านชัด */
main > .section:nth-of-type(odd) {
  background: linear-gradient(180deg, rgba(2, 8, 18, .38), rgba(2, 8, 18, .46) 50%, rgba(2, 8, 18, .38));
}

/* สามอันนี้ต้องเขียนเจาะจงเท่ากฎแถบสลับด้านบนและวางทีหลัง ไม่งั้นจะโดนทับ
   (แพ็กเกจเป็นลำดับคู่ ส่วนคำถามและท้ายเว็บเป็นลำดับคี่) */
main > .section.pricing {
  background:
    radial-gradient(circle at 50% 8%, rgba(27, 94, 177, .22), transparent 30%),
    rgba(6, 17, 32, .52);
}

main > .section.faq { background: rgba(6, 17, 32, .50); }

main > .section.closing {
  background:
    radial-gradient(ellipse 60% 70% at 50% 100%, rgba(0, 120, 230, .22), transparent 70%),
    radial-gradient(ellipse 40% 50% at 15% 0%, rgba(255, 191, 63, .1), transparent 70%),
    rgba(2, 8, 18, .52);
}

/* ── กริดเพอร์สเปกทีฟ 3D ──────────────────────────────────────────────────
   ม่านแสงให้สีกับความเคลื่อนไหว แต่ไม่ให้ "ความลึก" เพราะตาเราอ่านความลึก
   จากเส้นที่ลู่เข้าหาจุดเดียวกัน กริดสามระนาบนี้คือส่วนที่ทำให้เห็นเป็น 3D

   วิธีทำ: ระนาบแบน ๆ สามอัน เอียงด้วย rotateX ภายใต้ perspective ของกล่องแม่
   พื้นสองอันเอียงขึ้น เพดานหนึ่งอันเอียงลง เส้นจึงลู่ไปรวมกันที่เส้นขอบฟ้ากลางจอ

   เรื่องที่ต้องระวังถ้าจะแก้ต่อ
   ---------------------------------------------------------------------------
   1. ระยะเลื่อนในคีย์เฟรมต้องเท่ากับขนาดช่องกริดพอดี (background-size) ไม่งั้น
      ตอนวนกลับไปเฟรมแรกภาพจะกระตุกให้เห็น เพราะเส้นไม่ได้ต่อกันพอดี
   2. เลื่อนด้วย transform เท่านั้นเหมือนม่านแสง ห้ามขยับ background-position
   3. ระนาบไกลต้องเลื่อนช้ากว่าระนาบใกล้ ความต่างของความเร็วคือสิ่งที่ทำให้
      สมองอ่านว่าอันหนึ่งอยู่ไกลกว่าอีกอัน ถ้าเท่ากันจะแบนทันที
   =========================================================================== */

.gx-depth {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  /* ค่านี้คือความแรงของมุมมอง ยิ่งน้อยยิ่งลู่แรง ดูเหมือนยืนใกล้พื้น */
  perspective: 1200px;
  perspective-origin: 50% 50%;
}

.gx-depth-plane {
  position: absolute;
  /* กว้างเกินจอมาก เพราะพอเอียงแล้วขอบซ้ายขวาจะหดเข้าหากลางจอ
     ถ้ากว้างเท่าจอจะเห็นขอบระนาบเป็นสามเหลี่ยมว่าง ๆ ที่มุมล่าง */
  left: -110%;
  right: -110%;
  height: 150vh;
  /* ช่องกริดคิดเป็น px ไม่ใช่ vmax โดยตั้งใจ
     vmax ทำให้จอยิ่งใหญ่ช่องยิ่งใหญ่ตาม บนจอ 1900px ช่องละ 114px เส้นห่างกัน
     จนเกือบไม่เห็นว่ามีอะไร ซึ่งเป็นสาเหตุที่รอบก่อนดูเหมือนพื้นหลังว่างเปล่า */
  background-image:
    linear-gradient(to right, rgba(96, 184, 255, .24) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(96, 184, 255, .24) 1px, transparent 1px);
  background-size: 42px 42px;
  will-change: transform;
}

/* ไล่ให้จางหายตรงที่ใกล้ตาที่สุด ส่วนด้านเส้นขอบฟ้าปล่อยให้เส้นวิ่งเข้าไปเกือบสุด
   เพราะจุดที่เส้นบีบเข้าหากันคือจุดที่ตาอ่านว่า "ลึก" ถ้าตัดจางก่อนถึงตรงนั้น
   จะเหลือแค่ตารางเอียง ๆ ไม่ใช่พื้นที่ทอดไปไกล */
/* ด้านที่ติดเส้นขอบฟ้าต้องเป็นจุดหมุน ส่วนตัวระนาบต้องกางออกมา "ทางผู้ชม"
   ไม่ใช่ถอยห่างออกไป ถ้าวางกลับด้าน ระนาบทั้งผืนจะถูกบีบจนเหลือแถบแคบ ๆ
   ติดเส้นขอบฟ้า (วัดได้สูงแค่ 151px บนจอสูง 1000px) ซึ่งคือสาเหตุที่
   รอบก่อนมองไม่เห็นอะไรเลยนอกจากเส้นจาง ๆ ที่มุมจอ */
.gx-depth-floor,
.gx-depth-floor-far {
  bottom: 50%;
  transform-origin: 50% 100%;
  /* จางตรงขอบที่ใกล้ตาที่สุด (ฉายลงไปอยู่ขอบล่างของจอ) ส่วนฝั่งเส้นขอบฟ้า
     ปล่อยให้เส้นวิ่งเข้าไปจนบรรจบ เพราะตรงนั้นคือจุดที่ตาอ่านว่าลึก */
  -webkit-mask-image: linear-gradient(to bottom, transparent 1%, #000 16%, #000 100%);
  mask-image: linear-gradient(to bottom, transparent 1%, #000 16%, #000 100%);
}

.gx-depth-roof {
  top: 50%;
  transform-origin: 50% 0%;
  -webkit-mask-image: linear-gradient(to top, transparent 1%, #000 18%, #000 100%);
  mask-image: linear-gradient(to top, transparent 1%, #000 18%, #000 100%);
}

/* พื้นใกล้ — คมสุด เร็วสุด */
.gx-depth-floor {
  animation: gxDepthFloor 4s linear infinite;
}

/* พื้นไกล — ช่องถี่กว่า จางกว่า ช้ากว่า คือชั้นที่สร้างความรู้สึกว่ามีระยะ */
.gx-depth-floor-far {
  background-size: 21px 21px;
  opacity: .40;
  animation: gxDepthFloorFar 6s linear infinite;
}

.gx-depth-roof {
  opacity: .5;
  animation: gxDepthRoof 5s linear infinite;
}

/* เครื่องหมายลบใน rotateX คือสิ่งที่ทำให้พื้นอยู่ "ข้างล่าง" จริง ๆ
   ของเดิมเป็นบวก ระนาบจึงพลิกไปโผล่ครึ่งบนของจอ กลายเป็นเพดานทั้งคู่
   (วัด bounding box ได้ top -19 bottom 518 บนจอสูง 1000 คือครึ่งบนล้วน)

   เลื่อนเท่าความสูงของช่องกริดพอดี ภาพจึงวนกลับมาซ้อนตัวเองสนิท ไม่กระตุก */
@keyframes gxDepthFloor {
  from { transform: rotateX(-76deg) translate3d(0, 0, 0); }
  to   { transform: rotateX(-76deg) translate3d(0, 42px, 0); }
}

@keyframes gxDepthFloorFar {
  from { transform: rotateX(-80deg) translate3d(0, 0, 0); }
  to   { transform: rotateX(-80deg) translate3d(0, 21px, 0); }
}

@keyframes gxDepthRoof {
  from { transform: rotateX(76deg) translate3d(0, 0, 0); }
  to   { transform: rotateX(76deg) translate3d(0, -42px, 0); }
}

/* ── เส้นขอบฟ้าและฝุ่นแสง ──────────────────────────────────────────────────
   กริดสองฝั่งบีบเข้าหากันตรงกลางจอ แต่ตรงกลางเป็นที่ที่เส้นบางที่สุดพอดี
   จึงกลายเป็นช่องว่างกลางหน้าจอ ซึ่งเป็นตรงที่เนื้อหาส่วนใหญ่วางอยู่

   เส้นขอบฟ้าเติมแสงให้จุดที่เส้นไปบรรจบกัน ส่วนฝุ่นแสงลอยอยู่คนละระยะ
   เติมของให้ช่วงกลางที่กริดเอื้อมไม่ถึง และเป็นตัวที่ทำให้รู้สึกว่ามีพื้นที่
   ระหว่างตากับพื้น ไม่ใช่แค่ภาพแบนสองชั้น
   =========================================================================== */

.gx-depth::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 34vh;
  transform: translateY(-50%);
  background:
    radial-gradient(58% 100% at 50% 50%, rgba(38, 148, 250, .22), transparent 74%),
    linear-gradient(to bottom, transparent 44%, rgba(132, 204, 255, .14) 50%, transparent 56%);
  animation: gxHorizonBreathe 9s ease-in-out infinite alternate;
}

@keyframes gxHorizonBreathe {
  from { opacity: .72; transform: translateY(-50%) scaleY(.92); }
  to   { opacity: 1; transform: translateY(-50%) scaleY(1.1); }
}

.gx-depth-motes {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
}

.gx-depth-motes span {
  position: absolute;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(170, 222, 255, .95), rgba(70, 160, 255, 0) 68%);
  /* ระยะลึกเก็บไว้ในตัวแปร เพราะคีย์เฟรมต้องเขียน transform ทั้งก้อนใหม่
     ถ้าใส่ translateZ ไว้ในกฎนี้ตรง ๆ คีย์เฟรมจะเขียนทับจนความลึกหายหมด */
  --z: -120px;
  transform: translate3d(0, 0, var(--z));
  animation: gxMoteDrift 18s ease-in-out infinite alternate;
  will-change: transform, opacity;
}

/* แต่ละเม็ดอยู่คนละตำแหน่ง คนละระยะลึก และลอยคนละจังหวะ ถ้าเหมือนกันหมด
   ตาจะจับได้ทันทีว่าเป็นลูปเดียวกัน แล้วความรู้สึกว่าเป็นพื้นที่จริงจะหายไป
   (ค่า delay ติดลบ = เริ่มกลางลูป เม็ดทั้งหมดจึงไม่สว่างพร้อมกันตอนโหลดหน้า) */
.gx-depth-motes span:nth-child(1)  { left: 12%; top: 22%; --z: -180px; animation-duration: 21s; }
.gx-depth-motes span:nth-child(2)  { left: 27%; top: 64%; --z:  -60px; animation-duration: 16s; animation-delay: -4s; }
.gx-depth-motes span:nth-child(3)  { left: 41%; top: 38%; --z: -240px; animation-duration: 26s; animation-delay: -9s; }
.gx-depth-motes span:nth-child(4)  { left: 58%; top: 71%; --z: -120px; animation-duration: 19s; animation-delay: -2s; }
.gx-depth-motes span:nth-child(5)  { left: 73%; top: 29%; --z:  -40px; animation-duration: 15s; animation-delay: -7s; }
.gx-depth-motes span:nth-child(6)  { left: 86%; top: 56%; --z: -200px; animation-duration: 24s; animation-delay: -11s; }
.gx-depth-motes span:nth-child(7)  { left: 19%; top: 47%; --z: -300px; animation-duration: 29s; animation-delay: -5s; }
.gx-depth-motes span:nth-child(8)  { left: 49%; top: 17%; --z:  -90px; animation-duration: 17s; animation-delay: -13s; }
.gx-depth-motes span:nth-child(9)  { left: 65%; top: 44%; --z: -260px; animation-duration: 27s; animation-delay: -3s; }
.gx-depth-motes span:nth-child(10) { left: 34%; top: 83%; --z: -150px; animation-duration: 20s; animation-delay: -16s; }
.gx-depth-motes span:nth-child(11) { left: 92%; top: 36%; --z: -100px; animation-duration: 18s; animation-delay: -8s; }
.gx-depth-motes span:nth-child(12) { left:  6%; top: 68%; --z: -220px; animation-duration: 25s; animation-delay: -14s; }

@keyframes gxMoteDrift {
  from { transform: translate3d(0, 16px, var(--z)); opacity: .22; }
  to   { transform: translate3d(0, -18px, var(--z)); opacity: .9; }
}

/* ── คนที่ตั้งเครื่องว่าไม่เอาภาพเคลื่อนไหว ───────────────────────────────── */

/* ไม่ได้ซ่อนทิ้ง แค่หยุดให้นิ่ง หน้าเว็บจึงยังเป็นสีน้ำเงินและยังเห็นกริดลู่ลึก
   เหมือนกัน ต่างกันแค่ไม่ขยับ */
@media (prefers-reduced-motion: reduce) {
  body::before,
  body::after {
    animation: none;
    transform: none;
  }
  .gx-depth-floor { animation: none; transform: rotateX(-76deg); }
  .gx-depth-floor-far { animation: none; transform: rotateX(-80deg); }
  .gx-depth-roof { animation: none; transform: rotateX(76deg); }
  /* เส้นขอบฟ้าและฝุ่นแสงยังอยู่ครบ แค่หยุดนิ่ง ภาพที่เห็นจึงเหมือนกัน */
  .gx-depth::after { animation: none; opacity: .88; }
  .gx-depth-motes span { animation: none; opacity: .6; }
}

/* จอเล็กลดความเข้มลงหน่อย พื้นที่น้อยทำให้ก้อนแสงดูหนากว่าบนจอใหญ่
   และมือถือส่วนใหญ่สู้งานวาดพื้นที่ใหญ่ ๆ ได้น้อยกว่า */
@media (max-width: 760px) {
  body::before { opacity: .8; }
  body::after { opacity: .7; }
  /* ตัดระนาบไกลทิ้งบนมือถือ เป็นชั้นที่กินแรงวาดมากที่สุดแต่เห็นผลน้อยสุด
     เพราะจอแคบทำให้ระยะลู่สั้นจนแทบแยกไม่ออกจากระนาบใกล้ */
  .gx-depth-floor-far { display: none; }
  .gx-depth { perspective: 820px; }
}
