:root {
  --saito-bg: #020a1d;
  --saito-bg-soft: #06162b;
  --saito-panel: rgba(4, 18, 44, 0.88);
  --saito-panel-light: rgba(17, 42, 70, 0.78);
  --saito-border: rgba(135, 164, 194, 0.35);
  --saito-cyan: #56c8ff;
  --saito-yellow: #ffba08;
  --saito-white: #f7f9ff;
  --saito-muted: #9da9bc;
  --saito-radius: 14px;
}

/* Admin-editable announcement ticker (Configuration > Alert Announcement
   Text) - sits above the navbar, scrolls away with the page rather than
   staying sticky, so it doesn't eat into scroll space permanently. Hidden
   entirely (see marquee-bar.js) whenever the admin leaves the text blank. */
.saito-marquee {
  width: 100%;
  overflow: hidden;
  position: relative;
  background: linear-gradient(90deg, #071a34, #0d2c52, #071a34);
  border-bottom: 1px solid rgba(86, 200, 255, 0.25);
  padding: 0.5rem 0;
}

/* A soft light sweep drifting across the bar behind the text - decorative
   only, so it's excluded from prefers-reduced-motion along with the rest. */
.saito-marquee::after {
  content: '';
  position: absolute;
  inset: 0;
  width: 40%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.07), transparent);
  animation: marqueeSweep 7s ease-in-out infinite;
  pointer-events: none;
}

.marquee-track {
  display: flex;
  align-items: center;
  width: max-content;
  /* Matches the height of a filled track (the logo is its tallest part), so
     the bar occupies its final height while still empty and the page doesn't
     shift when the announcement text arrives. */
  min-height: 22px;
  animation: scrollMarquee 22s linear infinite;
}

.marquee-track span.marquee-text {
  padding: 0 1rem;
  white-space: nowrap;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  /* Fallback for browsers without background-clip:text support (below) */
  color: var(--saito-yellow);
}

/* Animated rainbow gradient text, applied only where the browser can
   actually clip a background to the glyph shapes - otherwise the fallback
   solid yellow above stays in effect instead of invisible transparent text. */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
  .marquee-track span.marquee-text {
    background: linear-gradient(90deg, #ff6b6b, #ffba08, #06d6a0, #56c8ff, #c77dff, #ff6b6b);
    background-size: 300% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    animation: rainbowHue 6s linear infinite;
    will-change: filter;
  }
}

.marquee-logo {
  height: 22px;
  width: 22px;
  object-fit: contain;
  flex-shrink: 0;
  filter: drop-shadow(0 0 4px rgba(86, 200, 255, 0.35));
}

@keyframes scrollMarquee {
  0% { transform: translateX(0); }
  100% { transform: translateX(-25%); }
}

/* Cycles the rainbow through every hue. This used to slide the gradient with
   background-position, which repaints the text on the main thread every
   frame; a filter animation on its own layer is run by the GPU instead. */
@keyframes rainbowHue {
  from { filter: hue-rotate(0deg); }
  to   { filter: hue-rotate(360deg); }
}

@keyframes marqueeSweep {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}

@media (prefers-reduced-motion: reduce) {
  .marquee-track,
  .marquee-track span.marquee-text,
  .saito-marquee::after {
    animation: none;
  }
}

@media (max-width: 575.98px) {
  .marquee-track span.marquee-text {
    padding: 0 0.7rem;
    font-size: 0.74rem;
  }
  .marquee-track {
    min-height: 18px;
  }
  .marquee-logo {
    height: 18px;
    width: 18px;
  }
}

html {
  scroll-behavior: smooth;
  /* overflow-x on <body> alone doesn't reliably stop the document from
     growing - the marquee tracks (width: max-content) were still pushing the
     page ~60px wider than the viewport on phones. Clamping <html> too keeps
     the page from scrolling sideways. */
  overflow-x: hidden;
  max-width: 100%;
}

body {
  min-height: 100vh;
  /* `clip`, not `hidden`. `hidden` forces <body> to become its own scroll
     container on top of <html> (which is already one, above), so the page
     rendered TWO vertical scrollbars side by side - <html>'s at the viewport
     edge and <body>'s just inside it. `clip` still stops sideways scrolling
     but creates no scroll container, leaving a single scrollbar on <html>.
     Note `clip` is the one overflow value that may pair with a `visible`
     other axis, so overflow-y stays visible here rather than becoming auto. */
  overflow-x: clip;
  color: var(--saito-white);
  font-family: "Poppins", sans-serif;
  background:
    radial-gradient(circle at 15% 20%, rgba(0, 150, 215, 0.18), transparent 28rem),
    radial-gradient(circle at 82% 8%, rgba(18, 141, 202, 0.15), transparent 30rem),
    linear-gradient(135deg, #010718 0%, #061a31 48%, #02091d 100%);
}

/* Bootstrap's wide gutters (g-5 = 3rem) use negative row margins that exceed
   the container's padding on narrow screens, pushing the page ~13px wider
   than the viewport. Tighten them on phones. */
@media (max-width: 575.98px) {
  .row.g-5,
  .row.gy-5 {
    --bs-gutter-y: 1.5rem;
  }

  .row.g-5,
  .row.gx-5 {
    --bs-gutter-x: 1.25rem;
  }
}

body::before,
body::after {
  position: fixed;
  z-index: -1;
  width: 7px;
  height: 7px;
  content: "";
  border-radius: 50%;
  background: #fff2a5;
  box-shadow:
    15vw 10vh 10px 2px rgba(255, 238, 132, 0.75),
    78vw 7vh 10px 2px rgba(255, 238, 132, 0.75),
    90vw 38vh 10px 2px rgba(255, 238, 132, 0.6),
    8vw 68vh 10px 2px rgba(255, 238, 132, 0.65),
    63vw 82vh 10px 2px rgba(255, 238, 132, 0.6);
}

body::after {
  top: 45%;
  left: 45%;
  opacity: 0.7;
  transform: scale(0.7);
}

a {
  color: inherit;
}

/* No backdrop-filter: a live blur behind a sticky bar is recomputed on every
   scroll frame (and every frame of the rolling banner beneath it), which is
   what made scrolling stutter right after the page opened. A near-opaque
   background looks the same without that cost. */
.site-navbar {
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  background: rgba(2, 10, 29, 0.96);
}

.brand {
  display: inline-flex;
  gap: 0.6rem;
  align-items: center;
  color: var(--saito-yellow) !important;
  font-size: 1.1rem;
  font-weight: 600;
  text-decoration: none;
  letter-spacing: 0.01em;
}

.brand-mark {
  display: inline-grid;
  width: 1.7rem;
  height: 2rem;
  place-items: center;
  color: var(--saito-yellow);
  font-size: 1.75rem;
  font-weight: 700;
  font-style: italic;
  line-height: 1;
  transform: skew(-10deg);
}

.site-logo {
  height: 38px;
  width: auto;
  object-fit: contain;
  display: block;
}


.navbar .nav-link {
  position: relative;
  padding: 0.75rem 0.85rem !important;
  color: rgba(247, 249, 255, 0.85);
  font-size: 0.9rem;
  font-weight: 500;
}

.navbar .nav-link::after {
  position: absolute;
  right: 0.85rem;
  bottom: 0.3rem;
  left: 0.85rem;
  height: 2px;
  content: "";
  background: var(--saito-yellow);
  transform: scaleX(0);
  transition: transform 180ms ease;
}

.navbar .nav-link:hover,
.navbar .nav-link.active {
  color: #fff;
}

.navbar .nav-link:hover::after,
.navbar .nav-link.active::after {
  transform: scaleX(1);
}

/* ── Signed-in indicator (navbar auth widget) ──────────────────────────────
   Previously a signed-in user only got a bare 32px avatar, and the name was
   hidden entirely below 576px - leaving no clear signal that they were logged
   in. This gives the widget a chip treatment with a green presence dot. */
.signed-in-chip {
  display: inline-flex;
  gap: 0.15rem;
  align-items: center;
  padding: 0.25rem 0.7rem 0.25rem 0.3rem;
  border: 1px solid rgba(74, 222, 128, 0.35);
  border-radius: 999px;
  background: rgba(74, 222, 128, 0.08);
  transition: border-color 180ms ease, background 180ms ease;
}

.signed-in-chip:hover,
.signed-in-chip.show {
  border-color: rgba(74, 222, 128, 0.6);
  background: rgba(74, 222, 128, 0.14);
}

.signed-in-chip::after {
  margin-left: 0.15rem;
  color: var(--saito-muted);
}

.avatar-wrap {
  position: relative;
  display: inline-flex;
  flex-shrink: 0;
}

.online-dot {
  position: absolute;
  right: -1px;
  bottom: -1px;
  width: 10px;
  height: 10px;
  border: 2px solid #04121f;
  border-radius: 50%;
  background: #4ade80;
  box-shadow: 0 0 6px rgba(74, 222, 128, 0.8);
}

.signed-in-meta {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.15;
  text-align: left;
}

.signed-in-label {
  color: #4ade80;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.signed-in-name {
  max-width: 11ch;
  overflow: hidden;
  color: var(--saito-white);
  font-size: 0.8rem;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (min-width: 576px) {
  .signed-in-name {
    max-width: 16ch;
  }
}

.order-link {
  display: inline-flex;
  gap: 0.55rem;
  align-items: center;
  padding: 0.7rem 0.95rem;
  color: var(--saito-white);
  font-size: 0.86rem;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: 999px;
  transition: 180ms ease;
}

.order-link:hover {
  color: var(--saito-yellow);
  border-color: rgba(255, 186, 8, 0.4);
  background: rgba(255, 186, 8, 0.06);
}

.hero-section {
  padding: 2rem 0 1rem;
}

.hero-panel,
.process-panel,
.footer-panel,
.footer-bottom {
  overflow: hidden;
  border: 1px solid var(--saito-border);
  border-radius: var(--saito-radius);
  background: var(--saito-panel);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.28);
}

.hero-main {
  background: linear-gradient(115deg, #030a20 0%, #071a34 55%, #16344f 100%);
}

.hero-copy {
  position: relative;
  z-index: 2;
  padding: clamp(2.5rem, 6vw, 5.5rem);
}

.hero-kicker {
  color: var(--saito-yellow);
  font-size: 0.9rem;
  font-weight: 500;
}

.hero-copy h1 {
  max-width: 720px;
  margin-bottom: 1.25rem;
  font-size: clamp(2.2rem, 4vw, 4.1rem);
  font-weight: 600;
  line-height: 1.22;
  letter-spacing: -0.035em;
  text-shadow: 0 3px 18px rgba(79, 196, 255, 0.26);
}

.hero-description {
  color: var(--saito-muted);
  font-size: 0.9rem;
}

.carousel-dots {
  display: flex;
  gap: 0.65rem;
  justify-content: center;
  margin-top: 2.75rem;
}

.carousel-dots span {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.28);
}

.carousel-dots .active {
  background: #fff;
  box-shadow: 0 0 14px rgba(255, 255, 255, 0.7);
}

/* A belt of banners (1 or many, admin-managed) rolling sideways and wrapping
   seamlessly - same technique as .topup-banner-track. A fixed clamp() height
   (not aspect-ratio on the container) avoids the two dimensions fighting each
   other; each tile keeps the artwork's own 2:1 shape via its own aspect-ratio. */
.hero-media {
  position: relative;
  overflow: hidden;
  height: clamp(200px, 25vw, 420px);
  background-color: #030a18;
}

.banner-track {
  display: flex;
  /* JS renders the banner list twice back to back (see applyHomeBanners in
     saito.html), so translateX(-50%) always lands exactly one full set later
     regardless of how many banners there are - the loop is seamless whether
     there's 1 banner or 10. width:max-content lets the tiles size themselves. */
  width: max-content;
  height: 100%;
  animation: scrollBanner var(--banner-duration, 30s) linear infinite;
}

.banner-track img {
  height: 100%;
  aspect-ratio: 2 / 1;
  flex-shrink: 0;
  object-fit: contain;
  object-position: center;
  display: block;
}

@keyframes scrollBanner {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.hero-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(90deg, #071a34 0%, transparent 38%, rgba(0, 0, 0, 0.12) 100%);
}

.social-actions {
  position: absolute;
  top: 50%;
  right: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  transform: translateY(-50%);
}

.social-actions a {
  display: grid;
  width: 42px;
  height: 42px;
  place-items: center;
  color: #fff;
  font-size: 1.15rem;
  text-decoration: none;
  border: 1px solid rgba(255, 255, 255, 0.48);
  border-radius: 50%;
  /* Sits over the constantly rolling banner, so a backdrop blur here was
     re-rendered every animation frame; a solid tint reads the same. */
  background: rgba(2, 10, 29, 0.66);
  transition: 180ms ease;
}

.social-actions a:hover {
  color: var(--saito-yellow);
  border-color: var(--saito-yellow);
  transform: translateY(-2px);
}

.logo-strip {
  overflow: hidden;
  padding: 1.25rem;
  background: rgba(3, 15, 35, 0.95);
  display: flex;
  align-items: center;
  position: relative;
}

.logo-strip::before,
.logo-strip::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 80px;
  z-index: 2;
  pointer-events: none;
}

.logo-strip::before {
  left: 0;
  background: linear-gradient(to right, rgba(3, 15, 35, 0.95), transparent);
}

.logo-strip::after {
  right: 0;
  background: linear-gradient(to left, rgba(3, 15, 35, 0.95), transparent);
}

.logo-track {
  display: flex;
  gap: 0.65rem;
  width: max-content;
  animation: scrollLogos 25s linear infinite;
}

/* Scales continuously with viewport width instead of jumping between fixed
   sizes at a breakpoint, so it never looks oversized on a wide laptop screen
   the way a flat 76px did. */
.logo-item {
  display: block;
  width: clamp(44px, 6vw, 64px);
  height: clamp(44px, 6vw, 64px);          /* square, so square game art fills it without a crop */
  overflow: hidden;      /* clips the art to the rounded corners */
  border-radius: 10px;
  background: linear-gradient(145deg, rgba(20, 45, 73, 0.72), rgba(5, 18, 42, 0.72));
  flex-shrink: 0;
  text-decoration: none;
  cursor: pointer;
  border: 1px solid transparent;
  transition: transform 180ms ease, border-color 180ms ease, background 180ms ease;
}

.logo-item:hover {
  transform: translateY(-3px);
  border-color: rgba(86, 200, 255, 0.4);
  background: linear-gradient(145deg, rgba(30, 60, 95, 0.85), rgba(8, 24, 52, 0.85));
}

/* The art fills the whole tile. It used to be capped at 24px tall and blended
   into the background, which suited flat wordmark logos but left game artwork
   as a small picture floating in an empty box. */
.logo-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Phones (iPhone 5 through the largest current models all fall under
   575.98px) get one size smaller still, so several fit on a narrow screen
   at once instead of two or three. */
@media (max-width: 575.98px) {
  .logo-strip {
    padding: 0.5rem 0.35rem;
  }

  .logo-strip::before,
  .logo-strip::after {
    width: 22px;
  }

  .logo-track {
    gap: 0.4rem;
  }
}

@keyframes scrollLogos {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(-50%);
  }
}

.section-space {
  padding: 4.25rem 0 0;
}

.section-heading {
  margin-bottom: 1.75rem;
}

.section-heading h2,
.footer-panel h2 {
  margin-bottom: 0.45rem;
  font-size: clamp(1.3rem, 2vw, 1.75rem);
  font-weight: 600;
}

.section-heading p,
.footer-panel p {
  margin-bottom: 0;
  color: var(--saito-muted);
  font-size: 0.88rem;
}

.game-card {
  display: block;
  overflow: hidden;
  height: 100%;
  color: var(--saito-white);
  text-decoration: none;
  border: 1px solid rgba(137, 162, 190, 0.35);
  border-radius: 13px;
  background: rgba(2, 12, 34, 0.86);
  box-shadow: 0 16px 35px rgba(0, 0, 0, 0.18);
  transition: transform 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
}

.game-card img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  transition: transform 260ms ease;
}

.game-card span {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  min-height: 60px;
  padding: 0.85rem 0.7rem;
  overflow: hidden;
  font-size: 0.82rem;
  font-weight: 500;
  line-height: 1.3;
  text-align: center;
  text-overflow: ellipsis;
  white-space: normal;
  word-break: break-word;
}

.game-card:hover,
.game-card.active {
  color: #fff;
  border-color: var(--saito-cyan);
  box-shadow: 0 0 0 1px rgba(86, 200, 255, 0.2), 0 20px 45px rgba(0, 0, 0, 0.28);
  transform: translateY(-5px);
}

.game-card:hover img,
.game-card.active img {
  transform: scale(1.025);
}

.game-card.maintenance {
  position: relative;
  filter: grayscale(0.7) brightness(0.8);
  border-color: rgba(239, 68, 68, 0.4) !important;
}

.game-card.maintenance::before {
  content: "MAINTENANCE";
  position: absolute;
  top: 10px;
  right: 10px;
  background: #ef4444;
  color: #fff;
  font-size: 0.65rem;
  font-weight: 700;
  padding: 3px 8px;
  border-radius: 4px;
  letter-spacing: 0.05em;
  z-index: 10;
  box-shadow: 0 2px 8px rgba(239, 68, 68, 0.4);
}


.process-panel {
  padding: 1.25rem;
}

.process-step {
  padding: 2rem 1.4rem;
  text-align: center;
}

/* The four steps read as a single numbered journey rather than separate
   cards: a badge per stage, joined by a connecting line that runs across the
   row. The old vertical dividers cut that line, so they're gone. */
.process-marker {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1.1rem;
}

.process-line {
  flex: 1;
  height: 2px;
  background: linear-gradient(90deg, rgba(137, 162, 190, 0.05), rgba(137, 162, 190, 0.35));
}

.process-line-end {
  background: linear-gradient(90deg, rgba(137, 162, 190, 0.35), rgba(137, 162, 190, 0.05));
}

/* The journey starts at step 1 and ends at the last step - no dangling
   line before the first badge or after the last. */
.process-step:first-child .process-line-start,
.process-step:last-child .process-line-end {
  visibility: hidden;
}

.process-badge {
  display: grid;
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  place-items: center;
  color: var(--saito-yellow);
  font-size: 0.88rem;
  font-weight: 700;
  border: 1px solid rgba(255, 186, 8, 0.4);
  border-radius: 50%;
  background: rgba(255, 186, 8, 0.1);
  transition: transform 200ms ease, box-shadow 200ms ease;
}

/* The final stage is the payoff - mark it as complete, in green. */
.process-step.is-final .process-badge {
  color: #4ade80;
  border-color: rgba(74, 222, 128, 0.45);
  background: rgba(74, 222, 128, 0.12);
  box-shadow: 0 0 14px rgba(74, 222, 128, 0.25);
}

.process-step:hover .process-badge {
  transform: scale(1.12);
  box-shadow: 0 0 16px rgba(255, 186, 8, 0.35);
}

.process-step.is-final:hover .process-badge {
  box-shadow: 0 0 18px rgba(74, 222, 128, 0.45);
}

.process-icon {
  display: block;
  margin-bottom: 1rem;
  color: #cbd6e7;
  font-size: 2.35rem;
}

.process-step h3 {
  margin-bottom: 0.8rem;
  font-size: 0.95rem;
  font-weight: 500;
}

.process-step p {
  margin: 0;
  color: #8795aa;
  font-size: 0.78rem;
  line-height: 1.8;
}

/* -- Footer -- */
.site-footer {
  position: relative;
  margin-top: 3rem;
  padding-bottom: 0;
  background: linear-gradient(180deg, rgba(2,10,29,0) 0%, #010a1d 60%);
}

.footer-glow-top {
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--saito-cyan), var(--saito-yellow), var(--saito-cyan), transparent);
  margin-bottom: 3rem;
  opacity: 0.7;
}

.footer-main {
  padding-bottom: 3rem;
}

.footer-logo-link {
  display: inline-block;
  margin-bottom: 1rem;
}

.footer-logo-img {
  height: 44px;
  width: auto;
  object-fit: contain;
}

.footer-desc {
  color: var(--saito-muted);
  font-size: 0.85rem;
  line-height: 1.8;
  margin-bottom: 1.5rem;
}

.footer-socials {
  display: flex;
  gap: 0.65rem;
}

.footer-payments {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 1.25rem;
}

.footer-payments-label {
  color: var(--saito-white);
  font-size: 1rem;
  font-weight: 800;
  margin-right: 0.35rem;
}

.footer-payments img {
  height: 20px;
  width: auto;
  object-fit: contain;
  border-radius: 6px;
}

.social-btn {
  display: grid;
  width: 40px;
  height: 40px;
  place-items: center;
  color: var(--saito-white);
  font-size: 1.1rem;
  text-decoration: none;
  border: 1px solid rgba(86, 200, 255, 0.25);
  border-radius: 50%;
  background: rgba(86, 200, 255, 0.07);
  transition: all 200ms ease;
}

.social-btn:hover {
  color: var(--saito-yellow);
  border-color: var(--saito-yellow);
  background: rgba(255, 186, 8, 0.1);
  transform: translateY(-3px);
  box-shadow: 0 6px 20px rgba(255, 186, 8, 0.2);
}

.footer-heading {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--saito-white);
  margin-bottom: 1.25rem;
  padding-bottom: 0.65rem;
  border-bottom: 1px solid rgba(86, 200, 255, 0.2);
}

.footer-links {
  list-style: none;
  padding: 0;
  margin: 0;
}

.footer-links li + li {
  margin-top: 0.6rem;
}

.footer-links a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--saito-muted);
  font-size: 0.85rem;
  text-decoration: none;
  transition: color 160ms ease, gap 160ms ease;
}

.footer-links a:hover {
  color: var(--saito-cyan);
  gap: 0.75rem;
}

/* Touch targets: footer and nav links were rendering ~19-20px tall, well
   under the ~44px comfortable-touch guideline. Give them real vertical hit
   area on touch devices without changing the desktop look. */
@media (hover: none) and (pointer: coarse) {
  .footer-links a,
  .footer-suggestions a {
    min-height: 40px;
    padding: 0.35rem 0;
  }

  .footer-links li + li {
    margin-top: 0.15rem;
  }

  .footer-bottom-nav a {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding: 0.35rem 0.5rem;
  }

  .btn,
  .btn-sm {
    min-height: 38px;
  }
}

.btn-back-home {
  /* Fixed at top, not bottom - the sticky checkout bar (shown once a
     package is picked) occupies the full-width bottom of the screen. */
  position: fixed;
  left: 1.25rem;
  top: 6.5rem;
  z-index: 1030;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 1.25rem;
  border-radius: 999px;
  border: 1px solid rgba(86, 200, 255, 0.35);
  background: rgba(4, 14, 34, 0.95);
  color: var(--saito-white);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  transition: all 180ms ease;
}

.btn-back-home:hover {
  color: var(--saito-bg);
  border-color: var(--saito-yellow);
  background: var(--saito-yellow);
  transform: translateY(-3px);
  box-shadow: 0 12px 28px rgba(255, 186, 8, 0.3);
}

@media (max-width: 575.98px) {
  .btn-back-home {
    left: 0.75rem;
    top: 5.5rem;
    padding: 0.6rem 1rem;
    font-size: 0.8rem;
  }
}

/* -- Skeleton loading placeholders -- */
.skeleton {
  position: relative;
  overflow: hidden;
  background: rgba(137, 162, 190, 0.12);
}

.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.08), transparent);
  animation: skeletonShimmer 1.6s ease-in-out infinite;
}

@keyframes skeletonShimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

/* Game card skeleton (matches .game-card layout: square image + label) */
.skeleton-game-card {
  border-radius: 13px;
  overflow: hidden;
  height: 100%;
  border: 1px solid rgba(137, 162, 190, 0.2);
}

.skeleton-game-card .skeleton-thumb {
  aspect-ratio: 1 / 1;
  width: 100%;
}

.skeleton-game-card .skeleton-label {
  height: 14px;
  margin: 1rem auto;
  width: 60%;
  border-radius: 4px;
}

/* Nominal/package card skeleton (matches the boxed .nominal-card layout) */
.skeleton-nominal-card {
  border-radius: 13px;
  overflow: hidden;
  border: 1px solid rgba(137, 162, 190, 0.2);
}

.skeleton-nominal-card .skeleton-thumb {
  aspect-ratio: 1 / 1;
  width: 100%;
}

.skeleton-nominal-card .skeleton-body {
  padding: 14px;
}

.skeleton-nominal-card .skeleton-line {
  height: 12px;
  border-radius: 4px;
  margin-bottom: 10px;
}

.skeleton-nominal-card .skeleton-line.w-60 { width: 60%; }
.skeleton-nominal-card .skeleton-line.w-40 { width: 40%; }
.skeleton-nominal-card .skeleton-btn {
  height: 34px;
  border-radius: 10px;
}

/* Generic block/line/circle skeleton primitives for forms and lists */
.skeleton-block {
  border-radius: 10px;
}

.skeleton-circle {
  border-radius: 50%;
}

#footerSuggestions {
  transition: opacity 300ms ease;
}

.footer-contact-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

.footer-contact-list li {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  color: var(--saito-muted);
  font-size: 0.83rem;
  line-height: 1.6;
}

.footer-contact-icon {
  display: grid;
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  place-items: center;
  color: var(--saito-cyan);
  font-size: 1rem;
  border: 1px solid rgba(86, 200, 255, 0.25);
  border-radius: 8px;
  background: rgba(86, 200, 255, 0.06);
}

.footer-bottom-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 0;
  border-top: 1px solid rgba(135, 164, 194, 0.15);
}

.footer-copy {
  color: var(--saito-muted);
  font-size: 0.78rem;
}

.footer-copy strong {
  color: var(--saito-yellow);
}

.footer-bottom-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
}

.footer-bottom-nav a {
  color: rgba(247, 249, 255, 0.65);
  font-size: 0.78rem;
  text-decoration: none;
  transition: color 160ms ease;
}

.footer-bottom-nav a:hover {
  color: var(--saito-yellow);
}


@media (max-width: 991.98px) {
  .site-navbar .navbar-collapse {
    margin-top: 0.9rem;
    padding: 1rem;
    border: 1px solid var(--saito-border);
    border-radius: 12px;
    background: rgba(3, 14, 36, 0.98);
  }

  .hero-copy {
    min-height: 430px;
  }

  .hero-overlay {
    background: linear-gradient(180deg, #071a34 0%, transparent 34%, rgba(0, 0, 0, 0.16) 100%);
  }
}

@media (max-width: 767.98px) {
  /* Logo strip scrolling layout is preserved on mobile */

  .section-space {
    padding-top: 3.25rem;
  }

  .footer-suggestions {
    padding-top: 1.5rem;
    padding-left: 0;
    border-top: 1px solid rgba(137, 162, 190, 0.24);
    border-left: 0;
  }

  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
  }
}

@media (max-width: 575.98px) {
  .hero-copy {
    min-height: 390px;
    padding: 2.2rem 1.4rem;
  }

  .game-grid {
    --bs-gutter-x: 0.9rem;
    --bs-gutter-y: 0.9rem;
  }

  .game-card span {
    min-height: 52px;
    padding: 0.95rem 0.35rem;
    font-size: 0.72rem;
  }

  .process-step + .process-step,

  .footer-bottom nav {
    gap: 0.8rem 1.2rem;
  }

  .nominal-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 0.75rem;
  }
}

/* Dynamic Top-Up Page Styling.
   A belt of identical copies of the banner, rolling sideways and wrapping
   seamlessly - fills the full width by repeating rather than by stretching one
   copy edge to edge (which crops this artwork's title, since its "RAIDEN
   MARU" text runs down to the very bottom of the frame) or centring one copy
   with empty space either side (which read as bare padding).
   Each copy keeps the artwork's own 2:1 shape (object-fit: contain inside an
   aspect-locked box), so nothing is ever cropped, at any screen width.
   The belt is 8 copies wide. Seamless looping needs the shift-per-loop to be
   exactly one copy's width; a percentage transform is relative to the belt's
   OWN rendered width regardless of how that width was arrived at, so
   translateX(-12.5%) (= -100%/8) is exactly one copy's width whatever the
   copies' actual pixel size turns out to be, at every screen size. 8 copies
   comfortably outruns any real monitor width even at the shortest banner
   height, so the belt never runs out and leaves a gap.
   Height is a fluid strip (200px on a phone up to 420px on a wide monitor -
   never the 640px-at-1280px-wide size a strict 2:1 banner would be, which
   pushed the whole order form below the fold). */
.topup-banner {
  position: relative;
  width: 100%;
  height: clamp(200px, 25vw, 420px);
  overflow: hidden;
  background-color: #030a18; /* only visible for a flash while images first load */
  border-bottom: 1px solid var(--saito-border);
}

.topup-banner-track {
  display: flex;
  width: max-content;
  height: 100%;
  animation: scrollBannerBelt 30s linear infinite;
}

.topup-banner-img {
  height: 100%;
  aspect-ratio: 2 / 1;
  flex-shrink: 0;
  object-fit: contain;
  display: block;
}

@keyframes scrollBannerBelt {
  from { transform: translateX(0); }
  to   { transform: translateX(-12.5%); } /* -100%/8 - exactly one copy's width */
}


.topup-game-info-block {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.25rem;
}

@media (min-width: 576px) {
  .topup-game-info-block {
    flex-direction: row;
    align-items: center;
    gap: 1.5rem;
  }
}

/* Scales with the page instead of sitting at a fixed 90px, which was too
   large next to the title on a phone and never changed on any screen. */
.topup-game-logo {
  width: clamp(52px, 6.5vw, 76px);
  height: clamp(52px, 6.5vw, 76px);
  border-radius: clamp(10px, 1.3vw, 14px);
  object-fit: cover;
  border: 2px solid var(--saito-cyan);
  box-shadow: 0 0 15px rgba(86, 200, 255, 0.4);
  flex-shrink: 0;
}

.topup-game-title h1 {
  font-size: 1.4rem;
  font-weight: 700;
  margin-bottom: 0.25rem;
  color: var(--saito-white);
  line-height: 1.2;
}

@media (min-width: 768px) {
  .topup-game-title h1 {
    font-size: 2.2rem;
  }
}


/* The title sits under the banner rather than lifted across it. The old -50px
   / -80px overlap was designed for a banner that filled the width; now that the
   artwork is centred and always shown whole, the title landed on top of the
   picture instead of on empty backdrop. */
.topup-container {
  margin-top: 0.9rem;
  position: relative;
  z-index: 10;
  padding-top: 0;
  padding-bottom: 5rem;
}

.step-card {
  border: 1px solid var(--saito-border);
  border-radius: var(--saito-radius);
  background: var(--saito-panel);
  padding: 1.75rem;
  margin-bottom: 2rem;
  box-shadow: 0 15px 45px rgba(0, 0, 0, 0.2);
}

.step-header {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.5rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  padding-bottom: 1rem;
}

.step-number {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--saito-yellow);
  color: var(--saito-bg);
  font-weight: 700;
  font-size: 0.95rem;
}

.step-title {
  font-size: 1.15rem;
  font-weight: 600;
  margin: 0;
  color: var(--saito-white);
}

.form-control-custom {
  background: rgba(1, 10, 29, 0.6);
  border: 1px solid var(--saito-border);
  color: var(--saito-white) !important;
  border-radius: 10px;
  padding: 0.75rem 1rem;
  font-size: 0.9rem;
  transition: all 0.2s ease;
}

.form-control-custom:focus {
  background: rgba(1, 10, 29, 0.9);
  border-color: var(--saito-cyan);
  box-shadow: 0 0 10px rgba(86, 200, 255, 0.25);
  outline: none;
}

.form-control-custom::placeholder {
  color: var(--saito-muted);
}

.nominal-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
}

/* Compact package card (MLBB, PUBG, Free Fire and every non-Bloxfruit game).
   Same sky-blue palette as the boxed Bloxfruit cards so the whole store reads
   as one brand - the click-to-select buying flow is unchanged. */
.nominal-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  background:
    linear-gradient(135deg, rgba(86, 200, 255, 0.10) 0%, rgba(2, 12, 34, 0) 55%),
    rgba(4, 20, 44, 0.92);
  border: 1.5px solid rgba(86, 200, 255, 0.45);
  border-radius: 16px;
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.22), inset 0 1px 0 rgba(255, 255, 255, 0.05);
  transition: all 0.2s ease;
  user-select: none;
}

.nominal-card:hover {
  border-color: var(--saito-cyan);
  background:
    linear-gradient(135deg, rgba(86, 200, 255, 0.18) 0%, rgba(2, 12, 34, 0) 60%),
    rgba(6, 26, 54, 0.95);
  transform: translateY(-2px);
  box-shadow: 0 0 0 1px rgba(86, 200, 255, 0.35), 0 14px 32px rgba(0, 0, 0, 0.3),
              0 0 22px rgba(86, 200, 255, 0.18);
}

.nominal-card.selected {
  border-color: var(--saito-cyan);
  background:
    linear-gradient(135deg, rgba(86, 200, 255, 0.22) 0%, rgba(2, 12, 34, 0) 60%),
    rgba(6, 26, 54, 0.97);
  box-shadow: 0 0 0 2px var(--saito-cyan), 0 10px 28px rgba(86, 200, 255, 0.25);
}

/* The currency artwork is 300x300 but was rendering at 32px - about 10% of the
   card on desktop, which left the card looking empty. Scale it to the card
   instead of a fixed pixel size, with sensible bounds. */
.nominal-icon {
  width: 56px;
  height: 56px;
  max-width: 60%;
  object-fit: contain;
  margin-bottom: 0.6rem;
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.35));
}

@media (min-width: 768px) {
  .nominal-icon {
    width: 64px;
    height: 64px;
  }
}

.nominal-name {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--saito-white);
  text-align: center;
  margin-bottom: 0.25rem;
}

.nominal-price {
  font-size: 0.9rem;
  color: var(--saito-cyan);
  font-weight: 800;
  text-shadow: 0 0 14px rgba(86, 200, 255, 0.35);
}

/* The admin's own label for a package ("Bonus 10%", "Best value"), set per
   product in the admin panel.
   A ribbon across the bottom of the card: it reads as a banner on the product
   rather than another line of text competing with the amount and the price.
   Colours are the logo's own - cyan #75E5FE into blue #01A9FF - with dark navy
   text, which stays legible on that gradient where white would not.
   One line, so every card in a row keeps the same height. */
.nominal-note {
  align-self: stretch;              /* the card centres its children */
  margin: 0.75rem -1.25rem -1.25rem;/* bleed out through the card's padding */
  padding: 7px 10px;
  border-radius: 0 0 15px 15px;     /* sits inside the card's 16px corners */
  /* Deep logo blue so white text stays readable across the whole band, with
     the logo's bright cyan as the top edge. */
  background: linear-gradient(135deg, #0a6cff 0%, #0038b8 100%);
  border-top: 2px solid #75e5fe;
  color: #ffffff;
  font-size: 0.72rem;
  font-weight: 800;
  line-height: 1.35;
  letter-spacing: 0.02em;
  text-align: center;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nominal-card.selected .nominal-note {
  background: linear-gradient(135deg, #2f8bff 0%, #0b4ad6 100%);
}

.nominal-checkmark {
  position: absolute;
  top: 8px;
  right: 8px;
  color: var(--saito-cyan);
  font-size: 0.85rem;
  display: none;
}

.nominal-card.selected .nominal-checkmark {
  display: block;
}

/* -- Sectioned package grid --
   When a game has 2+ linked categories, #nominalGrid switches from a grid to
   a vertical stack of [heading, sub-grid] pairs. The sub-grids carry the same
   .nominal-grid class so every card rule below applies unchanged. */
.nominal-grid.sectioned {
  display: block;
}

/* Package search box */
.nominal-search {
  position: relative;
  margin-bottom: 0.9rem;
}

.nominal-search-icon {
  position: absolute;
  top: 50%;
  left: 0.95rem;
  color: var(--saito-muted);
  font-size: 0.9rem;
  transform: translateY(-50%);
  pointer-events: none;
}

.nominal-search-input {
  width: 100%;
  padding: 0.7rem 2.6rem;
  color: var(--saito-white);
  font-family: inherit;
  font-size: 0.9rem;
  border: 1px solid rgba(137, 162, 190, 0.35);
  border-radius: 999px;
  background: rgba(2, 12, 34, 0.75);
  transition: border-color 180ms ease, box-shadow 180ms ease;
}

.nominal-search-input::placeholder {
  color: var(--saito-muted);
}

.nominal-search-input:focus {
  outline: 0;
  border-color: var(--saito-cyan);
  box-shadow: 0 0 0 3px rgba(86, 200, 255, 0.15);
}

/* The native clear affordance duplicates our own button */
.nominal-search-input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.nominal-search-clear {
  position: absolute;
  top: 50%;
  right: 0.55rem;
  display: grid;
  width: 30px;
  height: 30px;
  place-items: center;
  color: var(--saito-muted);
  font-size: 0.8rem;
  border: 0;
  border-radius: 50%;
  background: transparent;
  transform: translateY(-50%);
  cursor: pointer;
  transition: color 160ms ease, background 160ms ease;
}

.nominal-search-clear:hover {
  color: var(--saito-white);
  background: rgba(255, 255, 255, 0.08);
}

.nominal-no-results {
  padding: 2rem 1rem;
  color: var(--saito-muted);
  font-size: 0.9rem;
  text-align: center;
}

.nominal-no-results i {
  font-size: 1.6rem;
  opacity: 0.5;
}

/* Quick-jump tabs above the grouped package grid */
.nominal-section-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.1rem;
}

.nominal-section-tab {
  display: inline-flex;
  gap: 0.45rem;
  align-items: center;
  padding: 0.5rem 1rem;
  color: var(--saito-muted);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  border: 1px solid rgba(137, 162, 190, 0.35);
  border-radius: 999px;
  background: rgba(2, 12, 34, 0.7);
  cursor: pointer;
  transition: color 180ms ease, border-color 180ms ease, background 180ms ease, transform 180ms ease;
}

.nominal-section-tab:hover {
  color: var(--saito-white);
  border-color: var(--saito-cyan);
  transform: translateY(-2px);
}

.nominal-section-tab.active {
  color: #04121f;
  border-color: var(--saito-yellow);
  background: linear-gradient(135deg, var(--saito-yellow), #ffd45e);
  box-shadow: 0 6px 18px rgba(255, 186, 8, 0.28);
}

.nominal-section-tab-count {
  padding: 0.05rem 0.45rem;
  font-size: 0.72rem;
  font-weight: 700;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.14);
}

.nominal-section-tab.active .nominal-section-tab-count {
  background: rgba(4, 18, 31, 0.22);
}

/* Section heading: a banded background rather than a bare underline, so each
   group reads as its own block. scroll-margin keeps the sticky navbar from
   covering it when a tab jumps here. */
.nominal-section-heading {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  margin: 0 0 0.9rem;
  padding: 0.55rem 0.7rem 0.55rem 1rem;
  scroll-margin-top: 90px;
  overflow: hidden;
  color: var(--saito-white);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  border: 1px solid rgba(137, 162, 190, 0.3);
  border-left: 3px solid var(--saito-yellow);
  border-radius: 10px;
  background:
    linear-gradient(90deg, rgba(255, 186, 8, 0.12) 0%, rgba(86, 200, 255, 0.06) 45%, rgba(2, 12, 34, 0) 100%),
    rgba(2, 12, 34, 0.75);
}

/* ── View Cart button (sticky checkout bar) ─────────────────────────────── */
.btn-view-cart {
  display: inline-flex;
  gap: 0.15rem;
  align-items: center;
  padding: 0.7rem 1.35rem;
  color: var(--saito-white);
  font-size: 0.95rem;
  font-weight: 700;
  white-space: nowrap;
  border: 1px solid rgba(137, 162, 190, 0.45);
  border-radius: 999px;
  background: rgba(2, 12, 34, 0.8);
  transition: color 180ms ease, border-color 180ms ease, background 180ms ease, transform 180ms ease;
}

.btn-view-cart:hover {
  color: #fff;
  border-color: var(--saito-cyan);
  background: rgba(9, 32, 62, 0.9);
  transform: translateY(-2px);
}

.view-cart-badge {
  min-width: 1.35rem;
  margin-left: 0.5rem;
  padding: 0.05rem 0.4rem;
  color: #04121f;
  font-size: 0.72rem;
  font-weight: 800;
  text-align: center;
  border-radius: 999px;
  background: var(--saito-yellow);
}

/* ── Cart viewer modal rows ─────────────────────────────────────────────── */
.cart-modal-row {
  display: flex;
  gap: 0.85rem;
  align-items: center;
  padding: 0.75rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}

.cart-modal-row:last-child {
  border-bottom: 0;
}

.cart-modal-thumb {
  width: 56px;
  height: 56px;
  flex-shrink: 0;
  object-fit: cover;
  border: 1px solid rgba(137, 162, 190, 0.3);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.04);
}

.cart-modal-info {
  flex: 1;
  min-width: 0;
}

.cart-modal-name {
  color: #f0faff;
  font-size: 0.92rem;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.cart-modal-unit {
  color: var(--saito-muted);
  font-size: 0.78rem;
}

.cart-modal-controls {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  align-items: flex-end;
  flex-shrink: 0;
}

.cart-qty-btn {
  width: 28px;
  height: 28px;
  padding: 0;
}

.cart-modal-line-total {
  color: var(--saito-yellow);
  font-size: 0.85rem;
  font-weight: 700;
}

@media (max-width: 420px) {
  .btn-view-cart {
    padding: 0.7rem 0.9rem;
    font-size: 0.85rem;
  }
}

/* Space between stacked sections in the "All" view (the first keeps its
   position directly under the tab row). */
.nominal-section-block + .nominal-section-block {
  margin-top: 1.75rem;
}

/* Cart line-item thumbnail (Bloxfruit "Your Cart" panel) */
.cart-item-thumb {
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  object-fit: cover;
  border: 1px solid rgba(137, 162, 190, 0.3);
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.04);
}

.nominal-section-count {
  padding: 0.1rem 0.5rem;
  color: var(--saito-yellow);
  font-size: 0.72rem;
  font-weight: 700;
  border: 1px solid rgba(255, 186, 8, 0.35);
  border-radius: 999px;
  background: rgba(255, 186, 8, 0.1);
}

/* "View" button on a section heading - narrows the page to that section.
   Only shown while the All tab is active (several sections on screen). */
.nominal-section-jump {
  display: inline-flex;
  gap: 0.1rem;
  align-items: center;
  margin-left: auto;
  padding: 0.25rem 0.5rem 0.25rem 0.7rem;
  color: var(--saito-cyan);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid rgba(86, 200, 255, 0.35);
  border-radius: 999px;
  background: rgba(86, 200, 255, 0.08);
  cursor: pointer;
  transition: color 160ms ease, border-color 160ms ease, background 160ms ease, transform 160ms ease;
}

.nominal-section-jump:hover {
  color: #fff;
  border-color: var(--saito-cyan);
  background: rgba(86, 200, 255, 0.2);
  transform: translateX(2px);
}

/* Touch devices: the button rendered 27px tall, under the ~32px comfortable
   tap minimum. Give it real hit area without changing the desktop look. */
@media (hover: none) and (pointer: coarse) {
  .nominal-section-jump {
    min-height: 34px;
    padding-top: 0.35rem;
    padding-bottom: 0.35rem;
  }
}

@media (max-width: 420px) {
  .nominal-section-jump {
    padding: 0.35rem 0.4rem 0.35rem 0.55rem;
    font-size: 0.72rem;
  }
}

.nominal-section-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
}

.nominal-section-grid.boxed {
  grid-template-columns: repeat(3, 1fr);
}

/* The boxed (Bloxfruit) cards need ~150px each to stay legible, so drop to
   2 columns on tablets and 1 on phones - at 3 columns a 375px screen was
   overflowing by ~326px. */
@media (max-width: 767.98px) {
  .nominal-grid.boxed,
  .nominal-section-grid.boxed {
    grid-template-columns: repeat(2, 1fr);
    gap: 0.75rem;
  }
}

@media (max-width: 575.98px) {
  .nominal-section-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 0.75rem;
  }
}

/* -- Boxed package-card style (Bloxfruit "Select Fruit" step ONLY -
   #nominalGrid gets the .boxed class from topup.html only when the active
   game slug is bloxfruit; every other game keeps the plain style above) -- */
/* Horizontal rows need more width than the old square tiles: two across on
   desktop, one per row on phones. */
.nominal-grid.boxed , .nominal-section-grid.boxed {
  grid-template-columns: repeat(2, 1fr);
  gap: 0.8rem;
}

/* Horizontal package rows in the logo's palette: sky-blue frame, deep-blue
   fill, name and price on the left, artwork on the right. */
.nominal-grid.boxed .nominal-card , .nominal-section-grid.boxed .nominal-card {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 0.9rem;
  background:
    linear-gradient(135deg, rgba(86, 200, 255, 0.10) 0%, rgba(2, 12, 34, 0) 55%),
    rgba(4, 20, 44, 0.92);
  border: 1.5px solid rgba(86, 200, 255, 0.45);
  border-radius: 16px;
  transition: transform 180ms ease, border-color 180ms ease, box-shadow 180ms ease, background 180ms ease;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.22), inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

.nominal-grid.boxed .nominal-card:hover , .nominal-section-grid.boxed .nominal-card:hover {
  border-color: var(--saito-cyan);
  background:
    linear-gradient(135deg, rgba(86, 200, 255, 0.18) 0%, rgba(2, 12, 34, 0) 60%),
    rgba(6, 26, 54, 0.95);
  transform: translateY(-3px);
  box-shadow: 0 0 0 1px rgba(86, 200, 255, 0.35), 0 14px 32px rgba(0, 0, 0, 0.3),
              0 0 22px rgba(86, 200, 255, 0.18);
}

.nominal-grid.boxed .nominal-card.selected , .nominal-section-grid.boxed .nominal-card.selected {
  border-color: var(--saito-cyan);
  background:
    linear-gradient(135deg, rgba(86, 200, 255, 0.22) 0%, rgba(2, 12, 34, 0) 60%),
    rgba(6, 26, 54, 0.97);
  box-shadow: 0 0 0 2px var(--saito-cyan), 0 10px 28px rgba(86, 200, 255, 0.25);
}

.nominal-image-wrap {
  position: relative;
  background: rgba(17, 42, 70, 0.6);
  padding: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 13px 13px 0 0;
}

.nominal-instant-badge {
  position: absolute;
  top: 12px;
  left: 12px;
  background: rgba(52, 211, 153, 0.15);
  color: #34d399;
  border: 1px solid rgba(52, 211, 153, 0.3);
  font-weight: 600;
  font-size: 0.68rem;
  padding: 4px 10px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  gap: 4px;
}

/* Artwork sits on the right of the row (source order puts it first). */
.nominal-grid.boxed .nominal-image-wrap , .nominal-section-grid.boxed .nominal-image-wrap {
  order: 2;
  position: relative;
  width: 62px;
  height: 62px;
  flex-shrink: 0;
  padding: 0;
  border-radius: 12px;
  background: transparent;
}

.nominal-grid.boxed .nominal-icon , .nominal-section-grid.boxed .nominal-icon {
  width: 62px;
  max-width: 62px;
  height: 62px;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  border-radius: 12px;
  margin-bottom: 0;
}

.nominal-grid.boxed .nominal-body , .nominal-section-grid.boxed .nominal-body {
  order: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  padding: 0;
}

.nominal-body {
  padding: 14px 14px 16px;
  display: flex;
  flex-direction: column;
}

.nominal-grid.boxed .nominal-name , .nominal-section-grid.boxed .nominal-name {
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--saito-white);
  text-align: left;
  margin-bottom: 3px;
  letter-spacing: 0.01em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Price in the logo's sky blue rather than yellow, so the card reads as one
   brand family. */
.nominal-grid.boxed .nominal-price , .nominal-section-grid.boxed .nominal-price {
  font-size: 1.15rem;
  color: var(--saito-cyan);
  font-weight: 800;
  text-align: left;
  margin-bottom: 8px;
  text-shadow: 0 0 14px rgba(86, 200, 255, 0.35);
}

/* The horizontal (boxed) card is a grid of text column + thumbnail, so the
   ribbon spans both to sit along the card's own bottom edge. */
.nominal-grid.boxed .nominal-note ,
.nominal-section-grid.boxed .nominal-note {
  grid-column: 1 / -1;
  /* The thumbnail and body carry their own `order`, so the ribbon needs a
     higher one or it lands in the first cell, at the top of the card. */
  order: 3;
  align-self: end;
  margin: 0.7rem -0.9rem -0.85rem;  /* bleed out through the card's padding */
  border-radius: 0 0 15px 15px;
  text-align: center;
}

/* In the horizontal layout the badge sat on top of the 62px thumbnail, so it
   now sits inline above the name (moved into .nominal-body in the markup). */
.nominal-grid.boxed .nominal-instant-badge ,
.nominal-section-grid.boxed .nominal-instant-badge {
  position: static;
  top: auto;
  left: auto;
  align-self: flex-start;
  margin-bottom: 5px;
}

.nominal-select-btn {
  width: 100%;
  background: var(--saito-yellow);
  border: none;
  color: var(--saito-bg);
  font-weight: 700;
  font-size: 0.82rem;
  padding: 9px 6px;
  border-radius: 10px;
  pointer-events: none;
  margin-top: auto;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nominal-grid.boxed .nominal-card.selected .nominal-select-btn , .nominal-section-grid.boxed .nominal-card.selected .nominal-select-btn {
  background: var(--saito-cyan);
}

/* Solid sky-blue button, matching the logo's fill. */
.nominal-cart-btn {
  width: 100%;
  background: linear-gradient(135deg, var(--saito-cyan), #2fa8e0);
  border: 0;
  color: #04121f;
  font-weight: 700;
  font-size: 0.78rem;
  padding: 8px 6px;
  border-radius: 10px;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  box-shadow: 0 4px 12px rgba(86, 200, 255, 0.25);
  transition: all 150ms ease;
}

.nominal-cart-btn:hover {
  background: linear-gradient(135deg, #7ad6ff, var(--saito-cyan));
  box-shadow: 0 6px 18px rgba(86, 200, 255, 0.4);
  transform: translateY(-1px);
}

@media (max-width: 767.98px) {
  .nominal-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 0.75rem;
  }

  .nominal-grid.boxed {
    gap: 0.7rem;
  }

  .nominal-grid.boxed .nominal-body, 
  .nominal-section-grid.boxed .nominal-body {
    padding: 10px 10px 12px;
  }

  .nominal-grid.boxed .nominal-name, 
  .nominal-section-grid.boxed .nominal-name {
    font-size: 0.8rem;
  }

  .nominal-grid.boxed .nominal-price, 
  .nominal-section-grid.boxed .nominal-price {
    font-size: 0.95rem;
    margin-bottom: 8px;
  }

  .nominal-grid.boxed .nominal-select-btn, 
  .nominal-section-grid.boxed .nominal-select-btn {
    font-size: 0.72rem;
    padding: 8px 4px;
  }

  .nominal-grid.boxed .nominal-instant-badge, 
  .nominal-section-grid.boxed .nominal-instant-badge {
    font-size: 0.6rem;
    padding: 3px 8px;
    top: 8px;
    left: 8px;
  }
}

/* Phones: two columns at common 375-430px widths. The card itself switches
   from the horizontal image-right layout (.nominal-grid.boxed .nominal-card
   above, built for a full-width row) to a stacked image-on-top layout here -
   at half the row's width, "Permanent Dragon" etc. has nowhere to go beside
   a 46px thumbnail, but gets the card's (near) full width to itself below
   the image instead. */
@media (max-width: 480px) {
  .nominal-grid.boxed,
  .nominal-section-grid.boxed {
    grid-template-columns: repeat(2, 1fr);
    gap: 0.6rem;
  }

  .nominal-grid.boxed .nominal-card,
  .nominal-section-grid.boxed .nominal-card {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: center;
    padding: 0.65rem 0.5rem;
    gap: 0.35rem;
  }

  .nominal-grid.boxed .nominal-image-wrap,
  .nominal-section-grid.boxed .nominal-image-wrap {
    order: 1;
    width: 56px;
    height: 56px;
  }

  .nominal-grid.boxed .nominal-icon,
  .nominal-section-grid.boxed .nominal-icon {
    width: 56px;
    max-width: 56px;
    height: 56px;
  }

  .nominal-grid.boxed .nominal-body,
  .nominal-section-grid.boxed .nominal-body {
    order: 2;
    align-items: center;
    width: 100%;
  }

  .nominal-grid.boxed .nominal-instant-badge,
  .nominal-section-grid.boxed .nominal-instant-badge {
    align-self: center;
  }

  .nominal-grid.boxed .nominal-name,
  .nominal-section-grid.boxed .nominal-name {
    font-size: 0.78rem;
    text-align: center;
    -webkit-line-clamp: 2;
  }

  .nominal-grid.boxed .nominal-price,
  .nominal-section-grid.boxed .nominal-price {
    font-size: 0.92rem;
    text-align: center;
    margin-bottom: 6px;
  }

  .nominal-grid.boxed .nominal-select-btn,
  .nominal-section-grid.boxed .nominal-select-btn,
  .nominal-grid.boxed .nominal-cart-btn,
  .nominal-section-grid.boxed .nominal-cart-btn {
    font-size: 0.7rem;
    padding: 7px 4px;
    white-space: normal;
  }
}

.nominal-card.disabled,
.payment-card.disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}


.payment-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.payment-card {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.25rem;
  background: rgba(17, 42, 70, 0.3);
  border: 1px solid var(--saito-border);
  border-radius: 12px;
  cursor: pointer;
  transition: all 0.2s ease;
  user-select: none;
}

.payment-card:hover {
  border-color: var(--saito-cyan);
  background: rgba(17, 42, 70, 0.6);
}

.payment-card.selected {
  border-color: var(--saito-yellow);
  background: rgba(255, 186, 8, 0.08);
  box-shadow: 0 0 0 1px var(--saito-yellow);
}

.payment-info {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.payment-logo {
  /* ABA brand guideline (v2.11, "Voice"): logo minimum height is 40px. */
  height: 40px;
  max-width: 100px;
  object-fit: contain;
}

/* Name over tagline, so the method reads as a title with a short explanation
   underneath rather than one cramped line. */
.payment-text {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}

.payment-name {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--saito-white);
}

.payment-note {
  font-size: 0.78rem;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.55);
  line-height: 1.3;
}

.payment-price {
  font-size: 0.9rem;
  color: var(--saito-yellow);
  font-weight: 600;
}

.payment-radio {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--saito-border);
  transition: all 0.2s ease;
}

.payment-card.selected .payment-radio {
  border-color: var(--saito-yellow);
  background: var(--saito-yellow);
}

.payment-card.selected .payment-radio::after {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--saito-bg);
}

.checkout-panel {
  position: sticky;
  top: 90px;
  border: 1px solid var(--saito-border);
  border-radius: var(--saito-radius);
  background: var(--saito-panel);
  padding: 1.75rem;
  box-shadow: 0 15px 45px rgba(0, 0, 0, 0.2);
}

.checkout-title {
  font-size: 1.2rem;
  font-weight: 600;
  margin-bottom: 1.25rem;
  color: var(--saito-white);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  padding-bottom: 0.75rem;
}

.checkout-row {
  display: flex;
  justify-content: space-between;
  font-size: 0.85rem;
  margin-bottom: 0.75rem;
  color: var(--saito-muted);
}

.checkout-row.total {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--saito-white);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  padding-top: 0.75rem;
  margin-top: 0.75rem;
  margin-bottom: 1.5rem;
}

.checkout-value {
  color: var(--saito-white);
  font-weight: 500;
}

.checkout-row.total .checkout-value {
  color: var(--saito-yellow);
}

.btn-checkout {
  width: 100%;
  padding: 0.85rem;
  border-radius: 10px;
  background: var(--saito-yellow);
  color: var(--saito-bg);
  border: none;
  font-weight: 600;
  font-size: 0.95rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  transition: all 0.2s ease;
  box-shadow: 0 5px 15px rgba(255, 186, 8, 0.2);
}

.btn-checkout:hover {
  background: #ffcc00;
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(255, 186, 8, 0.35);
}

.btn-checkout:disabled {
  background: rgba(255, 255, 255, 0.1);
  color: rgba(255, 255, 255, 0.3);
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* Modal styling matching dark premium theme */
.modal-custom .modal-content {
  background: #04122c;
  border: 1px solid var(--saito-border);
  border-radius: var(--saito-radius);
  color: var(--saito-white);
}

.modal-custom .modal-header {
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.modal-custom .modal-footer {
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.modal-custom .close-btn {
  color: var(--saito-white);
  opacity: 0.7;
}

.modal-custom .close-btn:hover {
  opacity: 1;
}

/* ===========================================
   ANIMATION SYSTEM
=========================================== */

/* -- Keyframes -- */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(40px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes fadeInLeft {
  from { opacity: 0; transform: translateX(-40px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes fadeInRight {
  from { opacity: 0; transform: translateX(40px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes scaleIn {
  from { opacity: 0; transform: scale(0.85); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes glowPulse {
  0%, 100% { box-shadow: 0 0 8px rgba(86,200,255,0.3); }
  50%       { box-shadow: 0 0 28px rgba(86,200,255,0.75), 0 0 50px rgba(86,200,255,0.25); }
}
@keyframes glowPulseYellow {
  0%, 100% { box-shadow: 0 0 8px rgba(255,186,8,0.3); }
  50%       { box-shadow: 0 0 28px rgba(255,186,8,0.75), 0 0 50px rgba(255,186,8,0.2); }
}
@keyframes float {
  0%, 100% { transform: translateY(0px); }
  50%       { transform: translateY(-9px); }
}
@keyframes shimmer {
  0%   { background-position: -200% center; }
  100% { background-position: 200% center; }
}
@keyframes pageReveal {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes navbarDrop {
  from { opacity: 0; transform: translateY(-100%); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes borderGlow {
  0%, 100% { border-color: rgba(86,200,255,0.3); }
  50%       { border-color: rgba(86,200,255,1); }
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* -- Page load -- */
main {
  animation: pageReveal 0.7s ease both;
}
.site-navbar {
  animation: navbarDrop 0.5s ease both;
}

/* -- Scroll-reveal -- */
.reveal {
  opacity: 0;
  transition: opacity 0.65s ease, transform 0.65s ease;
}
.reveal.from-up    { transform: translateY(40px); }
.reveal.from-left  { transform: translateX(-50px); }
.reveal.from-right { transform: translateX(50px); }
.reveal.from-scale { transform: scale(0.88); }
.reveal.visible {
  opacity: 1;
  transform: none;
}
.reveal.delay-1 { transition-delay: 0.1s; }
.reveal.delay-2 { transition-delay: 0.2s; }
.reveal.delay-3 { transition-delay: 0.3s; }
.reveal.delay-4 { transition-delay: 0.4s; }
.reveal.delay-5 { transition-delay: 0.5s; }
.reveal.delay-6 { transition-delay: 0.6s; }

/* Entrance for content that renders AFTER page load - package grids, product
   cards, contact cards - where the elements don't exist yet at page-load
   time for the IntersectionObserver above to have caught them. Plays once,
   automatically, the moment each card is painted. Stagger is set per-card via
   an inline animation-delay (see the JS that builds each card), since these
   grids are rebuilt dynamically and a fixed set of :nth-child rules can't
   track how many cards end up in them. */
@keyframes cardPopIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
.card-pop-in {
  animation: cardPopIn 0.35s ease both;
}

/* Top-up page: the three form steps and the summary panel cascade in one
   after another instead of all appearing at once with the rest of <main>. */
.topup-game-info-block,
.step-card,
.checkout-panel {
  animation: cardPopIn 0.5s ease both;
}
.step-card:nth-child(1) { animation-delay: 0.08s; }
.step-card:nth-child(2) { animation-delay: 0.16s; }
.step-card:nth-child(3) { animation-delay: 0.24s; }
.step-card:nth-child(4) { animation-delay: 0.24s; }
.checkout-panel { animation-delay: 0.2s; }

/* -- Persistent glow / float --
   These pulse and shimmer forever. Animating box-shadow or background-position
   makes the browser repaint on the main thread every single frame, and while
   even one of them runs it never goes idle - measured at ~74% of the main
   thread on the homepage, which is what made scrolling catch for a moment.
   The same looks are now drawn once on their own layer and animated with
   opacity or transform only, which the GPU runs without the main thread. */
@keyframes glowLayerPulse {
  0%, 100% { opacity: 0; }
  50%      { opacity: 1; }
}

@keyframes shimmerSlide {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* The panel clips its own children (overflow: hidden), so its glow layer sits
   on the wrapper directly behind it instead, sized to the panel's box. */
.hero-section > .container {
  position: relative;
}

.hero-section > .container::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--bs-gutter-x, 1.5rem) * 0.5);
  right: calc(var(--bs-gutter-x, 1.5rem) * 0.5);
  border-radius: var(--saito-radius);
  box-shadow: 0 0 28px rgba(86, 200, 255, 0.75), 0 0 50px rgba(86, 200, 255, 0.25);
  opacity: 0;
  pointer-events: none;
  will-change: opacity;
  animation: glowLayerPulse 4.5s ease-in-out infinite;
}

.hero-panel {
  position: relative;
  z-index: 1;
  box-shadow: 0 0 8px rgba(86, 200, 255, 0.3);
}
/* Phones: the steps stacked one per row at ~212px each, so this short
   four-item section ran 894px - over a full screen of scrolling. Two per row
   with tighter padding and smaller icons brings it back to a glanceable block. */
@media (max-width: 575.98px) {
  .process-panel {
    padding: 0.75rem;
  }

  .process-step {
    flex: 0 0 50%;
    max-width: 50%;
    padding: 1.1rem 0.7rem;
  }

  /* Rebuild the dividers for a 2-column grid: a left border on the right-hand
     column, a top border on the second row. */

  .process-icon {
    margin-bottom: 0.55rem;
    font-size: 1.6rem;
  }

  .process-marker {
    margin-bottom: 0.7rem;
  }

  .process-badge {
    width: 26px;
    height: 26px;
    font-size: 0.75rem;
  }

  .process-step h3 {
    margin-bottom: 0.4rem;
    font-size: 0.82rem;
  }

  .process-step p {
    font-size: 0.7rem;
    line-height: 1.5;
  }
}

.process-icon {
  animation: float 3s ease-in-out infinite;
}
.process-step:nth-child(2) .process-icon { animation-delay: 0.4s; }
.process-step:nth-child(3) .process-icon { animation-delay: 0.8s; }
.process-step:nth-child(4) .process-icon { animation-delay: 1.2s; }
/* Same gradient tiles and speed as before: a strip twice as long as one tile
   repeat, slid left by exactly one tile per loop. */
.footer-glow-top {
  position: relative;
  overflow: hidden;
  background: none;
}

.footer-glow-top::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 400%;
  height: 100%;
  background: linear-gradient(90deg, transparent, var(--saito-cyan), var(--saito-yellow), var(--saito-cyan), transparent) 0 0 / 50% 100% repeat-x;
  will-change: transform;
  animation: shimmerSlide 1.75s linear infinite;
}

.footer-contact-icon {
  position: relative;
  box-shadow: 0 0 8px rgba(86, 200, 255, 0.3);
}

.footer-contact-icon::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 0 28px rgba(86, 200, 255, 0.75), 0 0 50px rgba(86, 200, 255, 0.25);
  opacity: 0;
  pointer-events: none;
  will-change: opacity;
  animation: glowLayerPulse 3s ease-in-out infinite;
}
.footer-contact-list li:nth-child(2) .footer-contact-icon::after { animation-delay: 1s; }
.footer-contact-list li:nth-child(3) .footer-contact-icon::after { animation-delay: 2s; }

/* While a scroll is in progress (scroll-hover-guard.js), nothing re-styles for
   hover as cards slide under the pointer; hover returns once scrolling stops. */
html.is-scrolling body {
  pointer-events: none;
}

/* -- Game card hover bounce -- */
.game-card {
  transition: transform 0.3s cubic-bezier(0.34,1.56,0.64,1),
              border-color 0.3s ease,
              box-shadow 0.3s ease !important;
}
.game-card:hover {
  transform: translateY(-8px) scale(1.04) !important;
}

/* -- Nominal cards -- */
.nominal-card {
  transition: transform 0.25s cubic-bezier(0.34,1.56,0.64,1),
              border-color 0.25s ease,
              box-shadow 0.25s ease !important;
}
.nominal-card:hover {
  transform: translateY(-5px) scale(1.04) !important;
}
/* The selected package's border used to pulse by animating border-color,
   repainting the card every frame for as long as it stayed selected. The
   border now rests at the dim end of that pulse and a full-strength ring on
   its own layer fades in and out over it - same look, GPU-animated. */
.nominal-card.selected,
.nominal-grid.boxed .nominal-card.selected,
.nominal-section-grid.boxed .nominal-card.selected {
  border-color: rgba(86, 200, 255, 0.3);
}

.nominal-card.selected::after {
  content: "";
  position: absolute;
  inset: -1.5px;
  border: 1.5px solid rgba(86, 200, 255, 1);
  border-radius: inherit;
  opacity: 0;
  pointer-events: none;
  will-change: opacity;
  animation: glowLayerPulse 1.5s ease-in-out infinite;
}

/* -- Social btn hover glow -- */
.social-btn:hover {
  animation: glowPulseYellow 1.5s ease-in-out infinite;
  transform: translateY(-3px) !important;
}

/* -- Section heading animated underline -- */
.section-heading {
  text-align: center;
}
.section-heading h2 {
  position: relative;
  display: inline-block;
}
.section-heading h2::after {
  content: '';
  position: absolute;
  bottom: -6px; left: 50%; transform: translateX(-50%);
  width: 0; height: 3px;
  background: linear-gradient(90deg, var(--saito-cyan), var(--saito-yellow));
  border-radius: 2px;
  transition: width 0.8s cubic-bezier(0.34,1.56,0.64,1) 0.3s;
}
.section-heading.visible h2::after {
  width: 80%;
}

/* -- Scroll progress bar -- */
/* The bar's moving shimmer: same gradient, tile and speed as the old
   background-position animation, slid with transform instead of repainted. */
#scroll-progress::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 400%;
  height: 100%;
  background: linear-gradient(90deg, var(--saito-cyan), var(--saito-yellow), var(--saito-cyan)) 0 0 / 50% 100% repeat-x;
  animation: shimmerSlide 1s linear infinite;
}

/* Full width, scaled with transform rather than resized: changing `width`
   forced a page re-layout on every scroll tick, a transform does not. */
#scroll-progress {
  position: fixed;
  top: 0; left: 0;
  height: 3px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left center;
  will-change: transform;
  overflow: hidden;
  z-index: 9999;
  box-shadow: 0 0 12px rgba(86,200,255,0.8);
  transition: transform 0.12s linear;
}

/* -- High Contrast Color Overrides -- */
.text-muted,
.text-secondary,
.dropdown-menu-dark .dropdown-header,
.dropdown-menu-dark .dropdown-header div,
.dropdown-header {
  color: #aebfd6 !important; /* Bright high-contrast light blue/grey */
  opacity: 1 !important;
}

.form-control::placeholder {
  color: rgba(247, 249, 255, 0.6) !important;
}

.dropdown-menu-dark .dropdown-item {
  color: var(--saito-white) !important;
  font-weight: 500;
  transition: all 0.15s ease;
}

.dropdown-menu-dark .dropdown-item:hover {
  background-color: var(--saito-panel-light) !important;
  color: var(--saito-cyan) !important;
}

.text-muted-light {
  color: #d1dfef !important;
}

/* Category Badge Pills */
.badge-pill {
  display: inline-flex;
  align-items: center;
  padding: 0.35rem 0.85rem;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--saito-white) !important;
  background: rgba(17, 42, 70, 0.4);
  border: 1px solid rgba(135, 164, 194, 0.3);
  border-radius: 50px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  user-select: none;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: border-color 0.2s ease, background 0.2s ease;
}

.badge-pill:hover {
  background: rgba(17, 42, 70, 0.6);
  border-color: rgba(135, 164, 194, 0.6);
}

/* "Verified" trust mark next to the game title, in the logo's own colours -
   bright cyan #75E5FE on a blue #01A9FF wash - so it stands out from the plain
   grey labels beside it while still looking part of the brand. */
.badge-pill.badge-verified {
  color: #75e5fe !important;
  background: rgba(1, 169, 255, 0.16);
  border-color: rgba(117, 229, 254, 0.45);
}

.badge-pill.badge-verified:hover {
  background: rgba(1, 169, 255, 0.28);
  border-color: rgba(117, 229, 254, 0.75);
}

.badge-pill i {
  font-size: 0.85rem;
  line-height: 1;
}

/* Premium Search Box Styling */
.search-box {
  position: relative;
  display: flex;
  align-items: center;
  background: rgba(17, 42, 70, 0.4);
  border: 1px solid var(--saito-border);
  border-radius: 30px;
  padding: 0 1.25rem;
  transition: all 0.3s ease;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}

.search-box:focus-within {
  border-color: var(--saito-cyan);
  box-shadow: 0 0 15px rgba(86, 200, 255, 0.25);
  background: rgba(17, 42, 70, 0.6);
}

.search-icon {
  color: var(--saito-muted);
  font-size: 1.1rem;
  margin-right: 0.75rem;
}

.search-input {
  background: transparent !important;
  border: none !important;
  color: var(--saito-white) !important;
  padding: 0.8rem 0 !important;
  font-size: 0.95rem;
  font-weight: 500;
  box-shadow: none !important;
  width: 100%;
}

.search-input::placeholder {
  color: rgba(247, 249, 255, 0.5) !important;
}

.btn-clear {
  background: none;
  border: none;
  color: var(--saito-muted);
  padding: 0;
  cursor: pointer;
  margin-left: 0.5rem;
  transition: color 0.2s ease;
}

.btn-clear:hover {
  color: var(--saito-cyan);
}

/* Sticky Bottom Checkout Bar Styling */
.sticky-checkout-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: #061126;
  border-top: 1px solid rgba(135, 164, 194, 0.25);
  box-shadow: 0 -8px 25px rgba(0, 0, 0, 0.5);
  z-index: 999;
  transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.3s ease;
  animation: slideUpBar 0.4s cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes slideUpBar {
  from { transform: translateY(100%); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

.checkout-bar-details {
  display: flex;
  flex-direction: column;
}

.checkout-bar-total {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--saito-white);
}

.checkout-bar-product {
  font-size: 0.82rem;
  color: #8c9eb9;
}

.btn-pay-now {
  background: linear-gradient(135deg, var(--saito-cyan) 0%, #0096d7 100%) !important;
  color: var(--saito-bg) !important;
  font-weight: 700 !important;
  font-size: 0.95rem !important;
  padding: 0.7rem 1.8rem !important;
  border-radius: 30px !important;
  border: none !important;
  transition: all 0.25s ease !important;
  box-shadow: 0 4px 15px rgba(86, 200, 255, 0.3);
}

.btn-pay-now:hover {
  background: linear-gradient(135deg, #70d5ff 0%, #00a8f3 100%) !important;
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(86, 200, 255, 0.5);
}

.btn-pay-now:active {
  transform: translateY(0);
}

body:has(.sticky-checkout-bar:not(.d-none)) {
  padding-bottom: 90px;
}

/* Override underline direction for left-aligned section headings */
.section-heading.text-start h2::after {
  left: 0;
  transform: none;
}

/* Ensure text legibility over original color header banners */
.topup-game-info-block h1 {
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.9) !important;
}
.topup-game-info-block p {
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.8) !important;
}

/* Scrollbars. Left unstyled, these render in the OS default light grey,
   which on this dark storefront reads as a bright white stripe down the
   right edge of every page. Styled here rather than via `color-scheme:dark`
   because that would also restyle every form control on the site. */
* {
  scrollbar-width: thin;                                  /* Firefox */
  scrollbar-color: rgba(135, 164, 194, 0.45) transparent; /* thumb, track */
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: rgba(135, 164, 194, 0.35);
  border-radius: 10px;
  /* Inset the thumb from the track edges without needing a wider bar. */
  border: 2px solid transparent;
  background-clip: content-box;
}

::-webkit-scrollbar-thumb:hover {
  background: rgba(86, 200, 255, 0.55);
  background-clip: content-box;
}

::-webkit-scrollbar-corner {
  background: transparent;
}

/* Saito logo as the mouse cursor (mouse users only - phones have no cursor).
   Text fields keep the normal text caret so typing still feels right. */
@media (pointer: fine) {
  html, body { cursor: url('/img/logo/cursor.png') 6 6, auto; }
  a, button, [role="button"], label, select, summary,
  input[type="button"], input[type="submit"], input[type="checkbox"], input[type="radio"] {
    cursor: url('/img/logo/cursor.png') 6 6, pointer;
  }
}


