
/* ===========================================================================================
   Hot / Cold palette -- ONE source of truth, shared by the Game Card hot/cold gauge and the
   Hot/Cold RTP list widget so both read the same way: hot = red, cold = blue. The RTP widget
   predates the gauge and had borrowed Bootstrap's success/danger (hot = green, cold = red, the
   usual stock-ticker up/down convention) -- standardized here so a player doesn't see the two
   features disagree about what colour "hot" is.
   =========================================================================================== */
:root {
	--wb-hot-color: #E4362A;
	--wb-cold-color: #3B82C4;
}

.flex-1 {
    flex: 1 1 0%;
}
.flex-2 {
    flex: 2 2 0%;
}
.flex-3 {
  flex: 3 3 0%;
}
.flex-auto {
    flex: 1 1 auto;
}

.right-0 {
	right: 0 !important;
}

.mt-auto {
	margin-top: auto;
}

.custom-html-content p {
	margin-top: .5rem;
	margin-bottom: .5rem;
}

.custom-html-content tbody, 
.custom-html-content tfoot, 
.custom-html-content tr, 
.custom-html-content td, 
.custom-html-content th {
    border-style: solid;
    border-width: 1px;
}

/***** SPLASH *****/

.splash-container {
	align-items: center;
    background-color: var(--bs-body-bg);
    display: flex;
    height: 100vh;
    justify-content: center;
    overscroll-behavior: contain;
    position: fixed;
    width: 100vw;
    z-index: 999999999999999;
}

.splash-container .splash-logo {
    animation: heartbeat 1s infinite;
    height: auto;
    width: 150px;
}

/* Loading-screen logo follows the live theme (data-bs-theme on <html>), like the header logo.
   Default/light shows the light logo; dark theme swaps to the dark logo. */
.splash-logo-dark { display: none; }
[data-bs-theme="dark"] .splash-logo-light { display: none; }
[data-bs-theme="dark"] .splash-logo-dark { display: inline-block; }

@keyframes heartbeat {
  0%   {transform: scale(1);}
  10%  {transform: scale(0.91);}
  17%  {transform: scale(0.98);}
  33% {transform: scale(0.87);}
  45% {transform: scale(1);}
}

/***** END: SPLASH *****/

/***** JACKPOT BOX *****/

.jackpot-box {
	--bs-card-bg: var(--bs-paper-bg);
	--bs-card-border-width: 0;
    --bs-card-border-color: var(--bs-border-color);
    --bs-card-box-shadow: var(--bs-box-shadow);
    
	display:flex;
	border-radius: 0.75rem;
	color: var(--bs-body-color);
	background-color : var(--bs-card-bg);
	border: var(--bs-card-border-width) solid var(--bs-card-border-color);
	box-shadow: var(--bs-card-box-shadow);
	height:149px;
	padding: 32px 0;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
    position: relative;
    overflow: hidden;
}

.jackpot-box .title-text {
	text-align: center;
    font-size: 1.125rem;
    font-style: normal;
    font-weight: 600;
    line-height: normal;
    z-index: 1;
}

.jackpot-box .currency-text {
	font-size: 24px;
    font-style: normal;
    font-weight: 800;
    line-height: normal;
    letter-spacing: .96px;
}

.jackpot-box .amount-text {
	font-size: 48px;
    font-style: normal;
    font-weight: 900;
    line-height: normal;
    letter-spacing: 1.92px;
}

.jackpot-box .accent-title-text {
	position: absolute;
    right: -15px;
    opacity: .05;
    bottom: 4px;
    font-size: 100px;
    font-style: normal;
    font-weight: 700;
    line-height: 60px;
    text-transform: uppercase;
}

[data-skin=bordered] .jackpot-box {
    --bs-card-box-shadow: 0px 0px 0px var(--bs-border-width) var(--bs-card-border-color);
    --bs-card-hover-box-shadow: 0px 0px 0px var(--bs-border-width) var(--bs-card-border-color);
}

/***** END: JACKPOT *****/

/***** FLEXBOX 2B 4S *****/

.flexbox-catelog {
	flex: 1 1 0%;
	border-radius: 0.75rem;
	color: var(--bs-body-color);
}

.flexbox2B4S-small {
	height: 8rem;
	padding: 0.5rem;
}

.flexbox2B4S-small .img-icon {
	top: 5%;
	left: 50%;
	height: 70%;
	transform: translateX(-50%);
	max-width: 100%;
}

.flexbox2B4S-small .title-text {
	display: none;
}

.flexbox2B4S-small .desc-text {
   	font-size: .875rem;
    line-height: 1.25rem;
   	bottom: .2rem;
   	display: block;
   	text-align: center;
   	width: 100%;
   	position: absolute;
}

.flexbox2B4S-big {
	padding: 1.25rem;
	height: 16rem;
}

.flexbox2B4S-big .img-icon {
	top: 0;
	right: 0;
	height: 100%;
	max-width: 100%;
}

.flexbox2B4S-big .title-text {
	display: flex;
	font-size: 1.5rem;
    line-height: 2rem;
    font-weight: 800;
	margin-left: .125rem;        
}

.flexbox2B4S-big .desc-text {
   	display: none;
}

/* On Mobile */
@media (max-width: 575.98px) { 
	
	.flexbox2B4S-small {
		height: 6rem;
	}
	
	.flexbox2B4S-small .desc-text {
		font-size: .775rem;
	   	line-height: 1.25rem;
	}

	.flexbox2B4S-big {
		height: 8rem;
		padding: 0.725rem;
	}
	
	.flexbox2B4S-big img {
		border-top-right-radius: 0.75rem;
		border-bottom-right-radius: 0.75rem;
	}
	
	.flexbox2B4S-big .title-text {
		font-size: .875rem;
	   	line-height: 1.25rem;
	}
	
}

/* On Desktop */
@media (min-width: 992px) {
	
	.flexbox-catelog img {
		border-top-right-radius: 0.75rem;
		border-bottom-right-radius: 0.75rem;
	}

	.flexbox2B4S-small {
		min-width: 40%;
	}
	
	.flexbox2B4S-small .img-icon {
		top: 0;
		right: 0;
		height: 100%;
		left: unset;
		transform: unset;
	}
	
	.flexbox2B4S-small.img-icon {
		min-width: 40%;
	}
	
	.flexbox2B4S-small .title-text {
		display: flex;
		font-size: 1.125rem;
	    line-height: 1.75rem;
	    font-weight: 800;
	    margin-left: .25rem;
	}
	
	.flexbox2B4S-small .desc-text {
	   	display: none;
	}
	
	.flexbox2B4S-big {
		padding: 1.25rem;
		height: unset;
	}
	
	.flexbox2B4S-big .title-text {
		display: flex;
		font-size: 1.5rem;
	    line-height: 2rem;
	    font-weight: 800;
		margin-left: .125rem;
	}
	
	.flexbox2B4S-big .desc-text {
	   	display: block;
		font-weight: 600;
		text-align: left;
		margin-top: auto;
		margin-bottom: .375rem;
		max-width: 15rem;
	}
		
}

.flexbox-catelog {
	--bs-card-bg: var(--bs-paper-bg);
	--bs-card-border-width: 0;
    --bs-card-border-color: var(--bs-border-color);
    --bs-card-box-shadow: var(--bs-box-shadow);
    
	background-color : var(--bs-card-bg);
	border: var(--bs-card-border-width) solid var(--bs-card-border-color);
	box-shadow: var(--bs-card-box-shadow);
}

[data-skin=bordered] .flexbox-catelog {
    --bs-card-box-shadow: 0px 0px 0px var(--bs-border-width) var(--bs-card-border-color);
    --bs-card-hover-box-shadow: 0px 0px 0px var(--bs-border-width) var(--bs-card-border-color);
}

/***** END: FLEXBOX 2B 4S *****/

/***** RTP LIST *****/

.rtp-list {
	display: flex;
	flex-direction: column;
	gap: 1rem;
}

.rtp-list-item {
	display: flex;
	flex-direction: row;
	align-items: center;
	padding: 0.5rem;
}

.rtp-list-item .icon {
	height: 48px;
	width: 48px;
	min-width: 48px;
	overflow: hidden;
	border: 2px solid transparent;
}

.rtp-list-item .indicator {
	right: 8px;
    top: 8px;
    position: absolute;
}

.rtp-list-item .text-content {
	text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
}

.rtp-list-item .text-content span {
	width: 100%;
    overflow: inherit;
    text-overflow: inherit;
}
   

/* Hot/cold colour for this widget's grid layout -- dedicated classes rather than Bootstrap's
   border-success/text-bg-success/text-success (green) and border-danger/text-bg-danger/
   text-danger (red) utilities the JS used to apply directly. Those utility classes are tied to
   --bs-success/--bs-danger, which mean actual success/error state everywhere else on the site
   (form validation, deposit status, banners) -- repurposing them for "hot" would have been a
   false semantic reuse, not just the wrong colour. Pulls from the shared --wb-hot-color/
   --wb-cold-color tokens defined at the top of this file, same as the Game Card gauge. */
.wb-hc-hot  { border-color: var(--wb-hot-color) !important; }
.wb-hc-cold { border-color: var(--wb-cold-color) !important; }
.wb-hc-badge.hot  { background-color: var(--wb-hot-color) !important; }
.wb-hc-badge.cold { background-color: var(--wb-cold-color) !important; }
.wb-hc-spin.hot  { color: var(--wb-hot-color) !important; }
.wb-hc-spin.cold { color: var(--wb-cold-color) !important; }

/***** END: RTP LIST *****/

/*
* MISCELLANEOUS
******************************************************************************/

.menu-icon {
    font-size: 1.0rem !important;
}

.misc-wrapper {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    text-align: center;
}

.dropdown-phone-prefix {
	overflow-y:auto; 
	max-height:30vh;
	max-width:20em;
}


.badge-user {
    display: inline-flex !important;
    justify-content: center !important;
    align-items: center !important;
    padding: 0.25rem !important;
    height: 1.25rem !important;
    font-size: 0.725rem !important;
}

.badge-user i {
    font-size: 0.725rem;
    block-size: 0.725rem;
}

.game-icon-image-wrapper {
  position: relative;
  width: 100%;
  /* Tile shape comes from the brand's chosen icon set, injected on <html> as --wb-game-icon-ratio.
     One line covers every grid that uses this frame; the fallback keeps every existing brand square
     when nothing is set, which is what they all are today. */
  aspect-ratio: var(--wb-game-icon-ratio, 1);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background-size: cover;
  background-position: center;
  background-color: rgba(127, 127, 127, .12); /* fallback fill when no blurhash is available yet */
}

/* Small avatars stay square whatever the site's tile ratio is. A 26-30px chip in a bet list or a
   ticker has no business being 3:4 -- it is an identifying thumbnail, not artwork -- and those boxes
   are hard-sized in pixels, so a tall ratio would squash the image rather than reshape the box.
   A deliberate exception, not an oversight. */
.game-icon-image-wrapper.wb-tile-square {
  aspect-ratio: 1;
}

/* When the game tile sits flush at the top of a .card (the card uses p-0, so the wrapper
   reaches the card edge), the wrapper's square top corners cover the card's rounded top --
   while the card body's transparent bottom lets the card's rounded bottom show through. That
   asymmetry (rounded bottom, square top) is fixed by matching the card's inner radius here.
   The wrapper already has overflow:hidden, so the image is clipped to the rounded corners. */
.card > a > .game-icon-image-wrapper,
.card > .game-icon-image-wrapper {
  border-top-left-radius: var(--bs-card-inner-border-radius);
  border-top-right-radius: var(--bs-card-inner-border-radius);
}
/* When the tile is the whole card (no .card-body below it -- recentlyPlayedT1, and the dense
   variants of carouselGamesT2 / gameCategoryTabsT1) round the bottom too, otherwise the square
   bottom would cover the card's rounded bottom -- the same problem, just flipped. */
.card > a:last-child > .game-icon-image-wrapper,
.card > .game-icon-image-wrapper:last-child {
  border-bottom-left-radius: var(--bs-card-inner-border-radius);
  border-bottom-right-radius: var(--bs-card-inner-border-radius);
}

.game-icon-image-wrapper img {
  display: block;
  width: 100%;
  height: 100%;
  /* contain, not width:100%/height:auto. Fitting to the WIDTH only works while the frame is never
     wider than the image is tall: in a 3:4 frame a square icon comes up short and letterboxes
     nicely, but in a 16:9 frame that same icon is TALLER than the frame and gets its top and bottom
     cropped off -- which on a game icon means slicing through the logo.

     `contain` fits inside whichever axis is tighter, so a default square icon letterboxes in every
     set shape and the blurhash background (see gameIconBg) fills the gap. Still never stretches,
     and still upscales a small icon to fill the frame the way width:100% did. */
  object-fit: contain;
}

/* Game-icon hover effect (per-brand setting, Common Settings > Game Icon Card > Hover effect).
   Body carries wb-hover-{effect}; default (no class / "none") = no hover interaction at all.
   Covers every game-icon tile shape site-wide: the standard grid wrapper (.game-icon-image-wrapper)
   plus the bento (carouselGamesT3), featured (featuredGameT1) and jackpot (infoJackpotT2) tiles --
   all already position:relative + overflow:hidden on their own tile element.

   Guarded behind (hover: hover) -- a touch device has no real hover, but mobile browsers SIMULATE
   :hover on the element you tapped and only clear it on the next tap elsewhere. Without this guard
   a player tapping a game to launch it would see that card left "stuck" mid-zoom/lift/pop, or with
   the overlay's play icon stuck visible, on top of double interaction (hover animation firing right
   before the tap's own navigation). (hover: hover) is true only for a real pointing device (mouse/
   trackpad); a touch-only phone or tablet gets none of this block, at any screen width. A
   touch-capable laptop with a mouse attached still gets it, which is correct -- the mouse can hover. */
@media (hover: hover) and (pointer: fine) {
body.wb-hover-zoom .game-icon-image-wrapper img,
body.wb-hover-zoom .wb-bento-tile img.wb-bento-img,
body.wb-hover-zoom .wb-featg-tile img,
body.wb-hover-zoom .wb-jp2-tile img { transition: transform .3s ease; }
body.wb-hover-zoom .game-icon-image-wrapper:hover img,
body.wb-hover-zoom .wb-bento-tile:hover img.wb-bento-img,
body.wb-hover-zoom .wb-featg-tile:hover img,
body.wb-hover-zoom .wb-jp2-tile:hover img { transform: scale(1.06); }

/* Lift + Pop move the WHOLE card (image, name, footer chips together), unlike Zoom/Overlay which
   stay image-only by request. The standard grid shape (.game-icon-image-wrapper) has real content
   below the image -- lifting only the image would leave the name/footer sitting still while the
   art moves away from it, which reads as broken. .wb-bento-tile/.wb-featg-tile/.wb-jp2-tile are
   already the WHOLE visual unit for their own layouts (the <a> itself, nothing below it) -- kept
   exactly as before.

   :has() scopes this to "a .card that contains a game icon wrapper", not the bare .card selector
   -- .card is used all over the site (login, payment, dashboard) and must stay untouched anywhere
   this feature doesn't apply. No border-radius/background override here: the card already carries
   its own via Bootstrap's --bs-card-border-radius (which the style-preset system in
   style-presets.css swaps per brand -- glass/luxe/brutal/clay), so it stays correct under every
   preset for free. */
body.wb-hover-lift .card:has(> a > .game-icon-image-wrapper),
body.wb-hover-lift .wb-bento-tile,
body.wb-hover-lift .wb-featg-tile,
body.wb-hover-lift .wb-jp2-tile { transition: transform .25s ease, box-shadow .25s ease; }
body.wb-hover-lift .card:has(> a > .game-icon-image-wrapper):hover,
body.wb-hover-lift .wb-bento-tile:hover,
body.wb-hover-lift .wb-featg-tile:hover,
body.wb-hover-lift .wb-jp2-tile:hover { transform: translateY(-5px); box-shadow: 0 10px 24px rgba(0,0,0,.18); }

body.wb-hover-pop .card:has(> a > .game-icon-image-wrapper),
body.wb-hover-pop .wb-bento-tile,
body.wb-hover-pop .wb-featg-tile,
body.wb-hover-pop .wb-jp2-tile { transition: transform .25s ease, box-shadow .25s ease; }
body.wb-hover-pop .card:has(> a > .game-icon-image-wrapper):hover,
body.wb-hover-pop .wb-bento-tile:hover,
body.wb-hover-pop .wb-featg-tile:hover,
body.wb-hover-pop .wb-jp2-tile:hover { transform: scale(1.09); box-shadow: 0 16px 34px rgba(0,0,0,.32); z-index: 3; position: relative; }

body.wb-hover-overlay .game-icon-image-wrapper::after,
body.wb-hover-overlay .wb-bento-tile::after,
body.wb-hover-overlay .wb-featg-tile::after,
body.wb-hover-overlay .wb-jp2-tile::after {
  content: ''; position: absolute; inset: 0; background: rgba(0,0,0,.45);
  opacity: 0; transition: opacity .25s ease; z-index: 4; pointer-events: none; border-radius: inherit;
}
body.wb-hover-overlay .game-icon-image-wrapper::before,
body.wb-hover-overlay .wb-bento-tile::before,
body.wb-hover-overlay .wb-featg-tile::before,
body.wb-hover-overlay .wb-jp2-tile::before {
  content: '\25B6'; position: absolute; top: 50%; left: 50%; transform: translate(-46%, -50%) scale(.8);
  width: 2.4rem; height: 2.4rem; line-height: 2.4rem; text-align: center; font-size: 1rem;
  background: rgba(255,255,255,.92); color: #111; border-radius: 50%;
  opacity: 0; transition: opacity .25s ease, transform .25s ease; z-index: 5; pointer-events: none;
}
body.wb-hover-overlay .game-icon-image-wrapper:hover::after,
body.wb-hover-overlay .wb-bento-tile:hover::after,
body.wb-hover-overlay .wb-featg-tile:hover::after,
body.wb-hover-overlay .wb-jp2-tile:hover::after { opacity: 1; }
body.wb-hover-overlay .game-icon-image-wrapper:hover::before,
body.wb-hover-overlay .wb-bento-tile:hover::before,
body.wb-hover-overlay .wb-featg-tile:hover::before,
body.wb-hover-overlay .wb-jp2-tile:hover::before { opacity: 1; transform: translate(-46%, -50%) scale(1); }
} /* @media (hover: hover) and (pointer: fine) */

/* ===========================================================================================
   Game Card (per-brand setting, Common Settings > Game Card; per-component override available).
   Markup is produced by gameCard() in js/main.jsp -- these rules and that function are one unit.

   The model is chips vs strips:
     * CHIPS (provider logo, Hot/New badge, RTP, player count) go in one of 7 slots -- 4 image
       corners + footer left/centre/right.
     * STRIPS (game name, hot/cold gauge) are full-width by nature and take a line of their own.

   A slot row is a 3-column grid rather than a flex space-between, which is what makes "centre"
   genuinely centred no matter how wide the left and right groups are, and what makes two chips
   in one slot compress instead of overlap. Nothing here can produce a broken layout, which is
   the whole point of placing by slot rather than by free left/centre/right alignment.

   Sized off the CARD's own width, not the viewport: card width depends on the grid's own column
   count (an operator can set 8 columns on a wide desktop screen, same as a phone's 2-column grid),
   which a plain @media (max-width) breakpoint has no way to see -- it only knows the viewport.
   container-type below turns the card itself into a query container so @container rules further
   down can react to how narrow THIS card actually rendered, regardless of screen size. Reuses the
   same :has() scoping the hover effects use, for the same reason -- .card is used everywhere on
   the site and only the game-card shape should establish this container. */
.card:has(> a > .game-icon-image-wrapper) { container-type: inline-size; container-name: wbgc; }

.wb-gc-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: .3rem; }
.wb-gc-row > .wb-gc-s { display: flex; align-items: center; gap: .3rem; min-width: 0; }
/* Align the CONTENT inside a full-width cell, never the cell itself. justify-self would size each
   cell to its content, and a child with a percentage width (the provider logo below 576px is
   width:45%) would then resolve that percentage against a box sized by the child -- which
   collapses or overflows. Cells stay stretched; only their contents move. */
.wb-gc-row > .wb-gc-s.l { justify-content: flex-start; }
.wb-gc-row > .wb-gc-s.c { justify-content: center; }
.wb-gc-row > .wb-gc-s.r { justify-content: flex-end; }

/* The footer row IS a Bootstrap .card-body -- the renderer emits `card-body px-2 py-1 wb-gc-row
   wb-gc-foot` together, so padding and card flex behaviour are exactly what every game card had
   before this panel existed. Only `display` is overridden, to the slot grid above; that works
   because custom.css loads after the theme, and px-2/py-1 keep winning on padding via !important.
   No rule of its own is needed here -- .wb-gc-foot is left as a hook for the GPA preview to match. */

/* Sizing for elements that live in a slot. The site-wide .game-icon-brand-image rule sizes the
   logo by PERCENTAGE on mobile, which only ever made sense when it was a direct child of a
   full-width flex row. In a slot it can land in any of seven places, including a small image
   corner, so inside a card row it is sized by height like every other chip. */
.wb-gc-row .game-icon-brand-image,
.wb-gc-ov .game-icon-brand-image { height: 18px; width: auto; max-width: 100%; object-fit: contain; }

/* Image overlay bands. The scrim is on the band itself, so it only appears when the band has
   something in it -- an empty corner leaves the artwork completely untouched. */
.wb-gc-ov { position: absolute; left: 0; right: 0; z-index: 3; padding: .35rem; display: grid; gap: .25rem; }
/* No scrim on the top band: every element that can land there (logo, badge, RTP, count) is a
   self-contained pill or logo with its own background/contrast, unlike the bottom band which also
   carries the game NAME -- plain text laid directly on artwork, which does need the scrim to stay
   readable regardless of what is underneath it. */
.wb-gc-ov.t { top: 0; }
.wb-gc-ov.b { bottom: 0; padding-top: 1.1rem; background: linear-gradient(to top, rgba(0,0,0,.78), rgba(0,0,0,0)); }
/* pushed up so the bottom chips clear the gauge when the gauge is on the image */
.wb-gc-ov.b.up { bottom: 8px; }
.wb-gc-ov .wb-gc-rtp { background: rgba(0,0,0,.5); color: #fff; }
.wb-gc-ov .wb-gc-cnt { color: rgba(255,255,255,.94); }

/* Elements ------------------------------------------------------------------------------- */
.wb-gc-rtp {
  font-size: .7rem; font-weight: 600; line-height: 1; white-space: nowrap;
  padding: .18rem .3rem; border-radius: .25rem;
  color: var(--bs-primary); background: rgba(var(--bs-primary-rgb), .14);
  font-variant-numeric: tabular-nums;
}
.wb-gc-cnt { display: inline-flex; align-items: center; gap: .2rem; font-size: .7rem; line-height: 1; white-space: nowrap; font-variant-numeric: tabular-nums; }
/* "live dot" count style -- a pulsing dot instead of the icon pill */
.wb-gc-cnt.dot > i { width: 6px; height: 6px; border-radius: 50%; background: var(--bs-success); flex: 0 0 6px; box-shadow: 0 0 0 2px rgba(var(--bs-success-rgb), .25); }
.wb-gc-cnt.dot > b { color: var(--bs-success); font-weight: 600; }
@media (prefers-reduced-motion: no-preference) {
  .wb-gc-cnt.dot > i { animation: wbGcPulse 1.8s ease-in-out infinite; }
}
@keyframes wbGcPulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }

.wb-gc-badge {
  display: inline-flex; align-items: center; line-height: 1; white-space: nowrap;
  font-size: .62rem; font-weight: 700; letter-spacing: .04em;
  padding: .2rem .35rem; border-radius: .25rem; color: #fff;
  box-shadow: 0 2px 6px rgba(0,0,0,.35);
}
.wb-gc-badge.hot { background: var(--bs-danger); }
.wb-gc-badge.new { background: var(--bs-success); }

/* An operator-uploaded badge, inside a FIXED render box. Without this cap one client uploading
   an oversized image would wreck every card on their site -- the upload dialog cannot stop them,
   so the renderer does. */
.wb-gc-badge-img { height: 20px; width: auto; max-width: 64px; object-fit: contain; display: block; filter: drop-shadow(0 2px 4px rgba(0,0,0,.4)); }

/* Strips --------------------------------------------------------------------------------- */
.wb-gc-nm { font-size: .8rem; font-weight: 500; padding: 0 .1rem; margin-top: .2rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-gc-nm.c { text-align: center; }
/* on the image the name sits inside the bottom band's scrim, so it needs no scrim of its own */
.wb-gc-ov .wb-gc-nm { margin-top: 0; color: #fff; font-weight: 700; font-size: .78rem; text-shadow: 0 1px 2px rgba(0,0,0,.45); }

/* Cold/hot icons flank the bar in the footer placement (real horizontal room there); the on-image
   edge strip stays icon-less on purpose -- it is a thin, zero-padding sliver flush to the image's
   bottom corners, and a plain outline icon dropped straight onto arbitrary game art (no scrim
   behind it) is exactly the kind of element that can vanish against similarly-coloured artwork.
   Bar and glowing dot are shared between both placements. */
/* Bottom padding matters when the gauge is the LAST thing in the card -- with no chip placed in
   the footer row, the bar would otherwise sit flush against the card's own bottom edge. */
.wb-gc-heat { display: flex; align-items: center; gap: .3rem; padding: .3rem .35rem .3rem; }
.wb-gc-heat-ic { flex: 0 0 auto; font-size: .625rem; line-height: 1; }
.wb-gc-heat-ic.cold { color: var(--wb-cold-color); }
.wb-gc-heat-ic.hot  { color: var(--wb-hot-color); }
/* Two more steps down as the card itself narrows -- a dense grid (many columns) can make cards
   this small even on a wide desktop screen, which is why this keys off the card's own width via
   the wbgc container above rather than the viewport. */
@container wbgc (max-width: 140px) { .wb-gc-heat-ic { font-size: .5rem; } }
@container wbgc (max-width: 100px) { .wb-gc-heat-ic { font-size: .4375rem; } }

/* Cold -> hot spectrum: blue, green, yellow, orange, red -- a real gradient rather than the
   original 3-stop version, closer to a standard heat scale. Thicker than before per request. */
.wb-gc-heat-track { position: relative; flex: 1 1 auto; height: 8px; border-radius: 999px;
  background: linear-gradient(90deg, var(--wb-cold-color) 0%, #4FCB98 30%, #F5D76E 55%, #F0805A 75%, var(--wb-hot-color) 100%); }
.wb-gc-heat-mark { position: absolute; top: 50%; width: 13px; height: 13px; border-radius: 50%;
  background: #fff; border: 2px solid var(--bs-body-bg); transform: translate(-50%, -50%);
  box-shadow: 0 1px 3px rgba(0,0,0,.45); transition: box-shadow .2s ease; }
/* Glow tracks which end the marker is actually on: red near hot, blue near cold, no glow when the
   game is sitting at its own normal rate (the "Even" middle -- see wbGcHeatZone in main.jsp). */
.wb-gc-heat-mark.hot  { box-shadow: 0 1px 3px rgba(0,0,0,.45), 0 0 0 5px color-mix(in srgb, var(--wb-hot-color) 28%, transparent), 0 0 10px 4px color-mix(in srgb, var(--wb-hot-color) 45%, transparent); }
.wb-gc-heat-mark.cold { box-shadow: 0 1px 3px rgba(0,0,0,.45), 0 0 0 5px color-mix(in srgb, var(--wb-cold-color) 28%, transparent), 0 0 10px 4px color-mix(in srgb, var(--wb-cold-color) 45%, transparent); }
/* same gauge flush to the image's bottom edge -- costs zero card height, which is why it is the
   default placement; square ends because it spans the full width of the frame */
.wb-gc-gauge-img { position: absolute; left: 0; right: 0; bottom: 0; z-index: 4; height: 8px; }
.wb-gc-gauge-img .wb-gc-heat-track { border-radius: 0; height: 8px; }
.wb-gc-gauge-img .wb-gc-heat-mark { width: 12px; height: 12px; border-color: rgba(0,0,0,.55); }

/* Outside the card ------------------------------------------------------------------------
   The eighth placement: outside-left/centre/right for chips, "Outside card" for the name and
   gauge strips. The renderer cannot literally emit this row outside the .card element -- it
   returns the card's inner html and every call site owns the wrapper -- so "outside" is done
   by ending the card's PANEL at the artwork instead. Same result an operator is asking for,
   with no change to eleven call sites and no extra wrapper div slipped into grids that are
   counting their own children.

   :has() rather than a class on .card for the same reason the hover effects use it: the
   renderer has no way to reach the wrapper it did not write. Same 2023+ baseline already
   relied on by those rules and by the wbgc container query above.

   The panel goes whenever ANYTHING is placed outside, even with the footer row also in use --
   a panel that stops between two rows has no shape a card could take. Two rows then both read
   as outside content, still told apart by the footer keeping its card-body padding. */
.card:has(> .wb-gc-out) { background-color: transparent; border-color: transparent; box-shadow: none; }

/* With no panel behind it the artwork IS the card, so it rounds on all four corners. The rules
   further up only round the bottom when the wrapper is the card's last child, and it stops
   being that as soon as an outside row follows it. */
.card:has(> .wb-gc-out) > a > .game-icon-image-wrapper,
.card:has(> .wb-gc-out) > .game-icon-image-wrapper { border-radius: var(--bs-card-inner-border-radius); }

/* Lines up with the artwork's own edges rather than the footer's px-2 -- this row is not in a
   card body and should not be inset as though it were. */
.wb-gc-out { padding: .3rem .1rem 0; }
.wb-gc-out .wb-gc-nm { margin-top: 0; }
.wb-gc-out .wb-gc-heat { padding-left: 0; padding-right: 0; }
.wb-gc-out .wb-gc-out-row { padding: 0; }

/* Mobile: a 2-up card is roughly 160px wide, so four chips will not fit. Rather than a second
   set of settings to keep in sync, elements drop by priority -- RTP first, then the count's
   text, then the name -- so one configuration degrades sensibly instead of overflowing. */
@media (max-width: 575.98px) {
  .wb-gc-ov { padding: .25rem; }
  .wb-gc-ov.b { padding-top: .8rem; }
  .wb-gc-row .game-icon-brand-image,
  .wb-gc-ov .game-icon-brand-image { height: 15px; width: auto; }
  .wb-gc-rtp { font-size: .62rem; padding: .15rem .22rem; }
  .wb-gc-cnt { font-size: .62rem; }
  .wb-gc-badge { font-size: .55rem; padding: .15rem .25rem; }
  .wb-gc-badge-img { height: 16px; max-width: 48px; }
  .wb-gc-nm, .wb-gc-ov .wb-gc-nm { font-size: .7rem; }
}

.game-icon-brand-image {
	height:18px;
	width:auto;
}

@media (max-width: 575.98px) {
	.game-icon-brand-image {
		height:auto;
		width:45%;
	}
}

/* Fixed box for provider logos in carouselProviderT1 -- without this the <img> has no intrinsic
   size of its own, so it visibly resizes 3 times as it goes transparent-pixel -> blurhash (32x32
   square) -> real logo (its own aspect ratio). object-fit:contain keeps both the blur and the
   real image correctly proportioned inside the same stable box, so only the blur/sharp crossfade
   is visible -- no size jump. */
.wb-provider-logo {
	height: 44px;
	width: auto;
	max-width: 100%;
	object-fit: contain;
}


.custom-option.custom-option-icon .custom-option-body .custom-option-title {
    display: block;
    color: var(--bs-heading-color);
    font-size: 0.875rem;
    font-weight: 600;
    margin-block-end: 0.5rem;
}

/*
* CUSTOM SWIPER
******************************************************************************/

.swiper {
  width: 100%;
  height: 100%;
  /* height: 400px; */
}
.swiper .swiper-slide {
  text-align: center;
  font-size: 1.5rem;
  /* background-color: #ecebed; */
  background-position: center;
  background-size: cover;
}

#swiper-cbt1-gallery .gallery-top {
  width: 100%;
  aspect-ratio: 2000 / 525;
}
@media (max-width: 576px) {
  #swiper-cbt1-gallery .gallery-top {
    aspect-ratio: 1305 / 525;
  }
}

#swiper-cbt1-gallery.with-thumbs {
  height: 400px;
}
@media (max-width: 576px) {
  #swiper-cbt1-gallery.with-thumbs {
    height: 200px;
  }
}
#swiper-cbt1-gallery.with-thumbs .gallery-top {
  height: 80%;
  aspect-ratio: unset;
}

#swiper-cbt1-gallery .gallery-thumbs {
  height: 20%;
  box-sizing: border-box;
  padding: 10px 0;
}
#swiper-cbt1-gallery .gallery-thumbs .swiper-slide {
  width: 25%;
  height: 100%;
  opacity: 0.4;
  cursor: pointer;
}
#swiper-cbt1-gallery .gallery-thumbs .swiper-slide-thumb-active {
  opacity: 1;
}

.swiper-bigwin .swiper-slide {
  text-align: left;
  font-size: 0.8rem;
  color: var(--bs-card-color);
}

.swiper-games .swiper-slide {
  text-align: left;
  font-size: 1.0rem;
  color: var(--bs-card-color) !important;
}


/*
* Game
******************************************************************************/
.game-content {
	height: calc(100vh - 9.5rem);
    padding: 1rem 1rem;
    position: relative;
}

.game-content-overlay {
	position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    padding: var(--bs-card-img-overlay-padding);
    border-radius: var(--bs-card-inner-border-radius);
    background-color: #000000db;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

/*
* Chat Messenger
******************************************************************************/
.default-chat-box {
	z-index: 2147483000;
    position: fixed;
    bottom: 20px;
    right: 20px;
    transform-origin: right bottom;
    height: min(704px, 100% - 40px);
    min-height: 80px;
    width: 400px;
    max-height: 704px;
    box-shadow: rgba(0, 0, 0, 0.16) 0px 5px 40px;
    border-radius: 16px;
	overflow: hidden;
	background-color:#fff;
}

.default-chat-box.show {
	transition: width 200ms ease 0s, height 200ms ease 0s, max-height 200ms ease 0s, transform 300ms cubic-bezier(0, 1.2, 1, 1) 0s, opacity 83ms ease-out 0s;
	transform: scale(1);
    opacity: 1;
    pointer-events: all;
}

.default-chat-box.hide {
    transition: width 200ms ease 0s, height 200ms ease 0s, max-height 200ms ease 0s, transform 300ms cubic-bezier(0, 1.2, 1, 1) 0s, opacity 83ms ease-out 0s;
    transform: scale(0);
    opacity: 0;
    pointer-events: none;
}

.default-chat-box-header {
    position: absolute;
    height: 60px;
    min-height: 60px;
    width: 100%;
    padding: 20px;
}


/*
* Mobile bottom tab bar
******************************************************************************/
.tabbar {
    height: 4.5rem;
    z-index: 110;
    box-sizing: content-box;
    padding-bottom: 0rem;
    position: fixed;
    bottom: 0;
    left: 0;
    border-top-left-radius: 1rem;
    border-top-right-radius: 1rem;
    background-color: var(--bs-navbar-bg) !important;
}

.btnTab {
	display: flex;
	flex: 1 1 0%;
    align-items: center;
    justify-content: center;
    height: 3rem;
    padding-left: .5rem;
    padding-right: .5rem;
    cursor: pointer;
    border-radius: 0.375rem;
    border: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
    background: none;
    font-size: 0.75rem;
    line-height: 1rem;
    font-weight: 800;
}

/*
* Mobile Box Back Button
******************************************************************************/

.btn-back {
  --bs-btn-back-color: #2f2b3d;
  --bs-btn-back-bg: url("data:image/svg+xml,<svg  xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'  fill='none'  stroke='currentColor'  stroke-width='2'  stroke-linecap='round'  stroke-linejoin='round'  class='icon icon-tabler icons-tabler-outline icon-tabler-chevron-left'><path stroke='none' d='M0 0h24v24H0z' fill='none'/><path d='M15 6l-6 6l6 6' /></svg>");
  --bs-btn-back-opacity: 0.5;
  --bs-btn-back-hover-opacity: 0.75;
  --bs-btn-back-focus-shadow: none;
  --bs-btn-back-focus-opacity: 0.75;
  --bs-btn-back-disabled-opacity: 0.25;
  --bs-btn-back-white-filter: invert(1) grayscale(100%) brightness(200%);
  box-sizing: content-box;
  width: 0.65rem;
  height: 0.65rem;
  padding: 0.25em 0.25em;
  color: var(--bs-btn-back-color);
  background: transparent var(--bs-btn-back-bg) center/0.65rem auto no-repeat;
  border: 0;
  border-radius: 0.375rem;
  opacity: var(--bs-btn-back-opacity);
}
.btn-back:hover {
  color: var(--bs-btn-back-color);
  text-decoration: none;
  opacity: var(--bs-btn-back-hover-opacity);
}
.btn-back:focus {
  outline: 0;
  box-shadow: var(--bs-btn-back-focus-shadow);
  opacity: var(--bs-btn-back-focus-opacity);
}
.btn-back:disabled, .btn-back.disabled {
  pointer-events: none;
  user-select: none;
  opacity: var(--bs-btn-back-disabled-opacity);
}

.btn-back-white {
  filter: var(--bs-btn-back-white-filter);
}

[data-bs-theme=dark] .btn-back {
  filter: var(--bs-btn-back-white-filter);
}

.modal-header .btn-back {
  padding: calc(var(--bs-modal-header-padding-y) * 0.5) calc(var(--bs-modal-header-padding-x) * 0.5);
  margin: calc(-0.5 * var(--bs-modal-header-padding-y)) calc(-0.5 * var(--bs-modal-header-padding-x)) calc(-0.5 * var(--bs-modal-header-padding-y)) auto;
}

.modal .btn-back {
  padding: 0.614rem;
  background-color: var(--bs-body-bg);
  background-image: none;
  box-shadow: var(--bs-box-shadow-xs);
  filter: none;
  opacity: 1;
  transform: translate(23px, -25px);
  border-radius: 0.25rem;
  transition: all 0.23s ease 0.1s;
  /* For hover effect of back btn */
}

@media (prefers-reduced-motion: reduce) {
  .modal .btn-back {
    transition: none;
  }
}
.modal .btn-back:hover, .modal .btn-back:focus, .modal .btn-back:active {
  opacity: 1;
  outline: 0;
  transform: translate(20px, -20px);
}
:dir(rtl) .modal .btn-back:hover, :dir(rtl) .modal .btn-back:focus, :dir(rtl) .modal .btn-back:active {
  transform: translate(26px, -20px);
}
.modal .btn-back::before {
  display: block;
  background-color: var(--bs-secondary-color);
  block-size: 0.6875rem;
  content: "";
  inline-size: 0.6875rem;
  mask-image: url("data:image/svg+xml,<svg  xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'  fill='none'  stroke='currentColor'  stroke-width='2'  stroke-linecap='round'  stroke-linejoin='round'  class='icon icon-tabler icons-tabler-outline icon-tabler-chevron-left'><path stroke='none' d='M0 0h24v24H0z' fill='none'/><path d='M15 6l-6 6l6 6' /></svg>");
  mask-repeat: no-repeat;
  mask-size: 100% 100%;
}
.modal .modal-header .btn-back {
  position: absolute;
  inset-block-start: 1.5rem;
  inset-inline-start: 0.8125rem;
}
.modal .modal-dialog-scrollable .btn-back,
.modal .modal-fullscreen .btn-back, .modal.modal-top .btn-back {
 /*  box-shadow: none; */
  transform: translate(0, 0);
}
.modal .modal-dialog-scrollable .btn-back:hover,
.modal .modal-fullscreen .btn-back:hover, .modal.modal-top .btn-back:hover {
  transform: translate(0, 0);
}

.modal-mobile-box .modal-body {
  background-color: var(--bs-body-bg);
  padding-left: 1rem;
  padding-right:1rem;
  padding-top:1rem;
}

.modal-mobile-box .modal-header {
	padding: 0;
	height:3.5rem;
	align-items: center;
	justify-content: center;
}

.modal-mobile-box .modal-title {
	margin: 0;
	display: flex;
	align-items: center;
}

.modal-mobile-box .card-header {
	padding: 1rem;
	padding-block-start: 1rem !important;
}

.modal-mobile-box .card-body {
	padding: 1rem;
	padding-block-start: 1rem !important;
}

.btn-menu-m {
	justify-content: space-between;
}

/* ── Mobile navigation stack (mobileBox) ──────────────────────────────────────────────
   Single-live-panel model: only the TOP screen is ever attached to #mobileBox-container,
   so there are never duplicate ids or coexisting fragment scripts. The panel is absolutely
   positioned (fills the box, scrolls on its own); padding moves off the container onto the
   panel (id selector beats the .modal-mobile-box .modal-body rule above). */
#mobileBox-container {
	position: relative;
	overflow: hidden;
	padding: 0;
}
.mobile-screen {
	position: absolute;
	inset: 0;
	overflow-y: auto;
	overflow-x: hidden;   /* long-text safety net: the stack never scrolls sideways */
	-webkit-overflow-scrolling: touch;
	background-color: var(--bs-body-bg);
	padding: 1rem 1rem 1.5rem;
}
/* Long unbreakable strings (batch/promo names, dual-currency amounts, IPs, restriction lists)
   break instead of overflowing. Cards already ellipsize titles; this catches detail rows. */
.modal-mobile-box .mobile-screen .text-end,
.modal-mobile-box .mobile-screen p { overflow-wrap: anywhere; }

/* iOS-style push/pop slide. Two panels are attached only during a transition; the JS sets the
   start transform (no transition), forces a reflow, then enables .mb-anim + .mb-to so the slide
   animates. --enter = incoming from the right (push) / left (pop); --leave = the screen moving
   away. A soft left-edge shadow on the top-most moving panel sells the depth. */
.mobile-screen.mb-anim {
	transition: transform .32s cubic-bezier(0.32, 0.72, 0, 1);
	will-change: transform;
}
.mobile-screen.mb-enter      { transform: translateX(100%); }   /* push: incoming from right */
.mobile-screen.mb-leave-back { transform: translateX(0); }      /* push: outgoing parks left  */
.mobile-screen.mb-enter-back { transform: translateX(-30%); }   /* pop:  incoming from left   */
.mobile-screen.mb-leave-fwd  { transform: translateX(0); }      /* pop:  outgoing to the right */
.mobile-screen.mb-enter.mb-to,
.mobile-screen.mb-enter-back.mb-to { transform: translateX(0); }
.mobile-screen.mb-leave-back.mb-to { transform: translateX(-30%); }
.mobile-screen.mb-leave-fwd.mb-to  { transform: translateX(100%); }
.mobile-screen.mb-top-shadow { box-shadow: -8px 0 24px rgba(0, 0, 0, .18); }

@media (prefers-reduced-motion: reduce) {
	.mobile-screen.mb-anim { transition: none; }
}

/* ── Mobile "card table" ───────────────────────────────────────────────────────────────
   Inside the mobile fullscreen box, a .mb-cardtable DataTable restacks each row into a card:
   the header row is hidden and every cell becomes a label→value line (label from data-label,
   set by mbCardTableRow). Scoped to .modal-mobile-box so DESKTOP keeps the real scrolling table.
   Avoids the horizontal-scroll / cramped-nowrap problem on narrow screens. */
.modal-mobile-box .mb-cardtable thead { display: none; }
.modal-mobile-box .mb-cardtable,
.modal-mobile-box .mb-cardtable tbody,
.modal-mobile-box .mb-cardtable tr,
.modal-mobile-box .mb-cardtable td { display: block; width: 100%; }
.modal-mobile-box .mb-cardtable tr {
	border: 1px solid var(--bs-border-color);
	border-radius: .5rem;
	padding: .35rem .85rem;
	margin-bottom: .75rem;
	background: var(--bs-paper-bg, #fff);
}
.modal-mobile-box .mb-cardtable td {
	display: flex; justify-content: space-between; align-items: center; gap: 1rem;
	padding: .4rem 0; border: 0 !important; white-space: normal; text-align: right; min-width: 0;
}
.modal-mobile-box .mb-cardtable td::before {
	content: attr(data-label);
	font-weight: 600; color: var(--bs-secondary-color); text-align: left; flex-shrink: 0;
}
.modal-mobile-box .mb-cardtable td:last-child { justify-content: flex-end; padding-top: .6rem; }
.modal-mobile-box .mb-cardtable td:last-child::before { content: none; }
/* DataTables adds a sizing wrapper; keep it from forcing horizontal scroll in card mode */
.modal-mobile-box .mb-cardtable + .dataTables_scrollBody,
.modal-mobile-box .dataTables_scrollBody .mb-cardtable { overflow: visible !important; }

/* Rich mobile cards (transactions / bet-history / rollover): the page's DataTable createdRow
   rebuilds each row into a designed .mbcard. .mbcard-table just strips the table layout so the
   card fills the row full-width. Scoped to .modal-mobile-box → desktop keeps the real table. */
.modal-mobile-box .mbcard-table thead { display: none; }
.modal-mobile-box .mbcard-table,
.modal-mobile-box .mbcard-table tbody,
.modal-mobile-box .mbcard-table tr,
.modal-mobile-box .mbcard-table td { display: block; width: 100%; }
.modal-mobile-box .mbcard-table td { padding: 0 !important; border: 0 !important; white-space: normal; }
.modal-mobile-box .mbcard-table tr { background: transparent; }
/* DataTables 2.x renders an empty top layout row (page-length + search, both disabled here) and an
   mt-2 above the table — dead gap on mobile. Drop the empty top row and the table row's top margin. */
.modal-mobile-box .dt-container > .row:first-child:not(.dt-layout-table) { display: none; }
.modal-mobile-box .dt-container .dt-layout-table { margin-top: 0 !important; }
.mbcard {
	display: flex; align-items: center; gap: .7rem;
	padding: .7rem .8rem; margin-bottom: .5rem;
	border: 1px solid var(--bs-border-color); border-radius: .65rem;
	background: var(--bs-paper-bg, #fff); cursor: pointer;
}
.mbcard:active { background: var(--bs-secondary-bg, #f5f5f5); }
.mbcard-icon {
	flex-shrink: 0; width: 38px; height: 38px; border-radius: .5rem;
	display: inline-flex; align-items: center; justify-content: center; font-size: 1.05rem;
}
.mbcard-main { flex: 1 1 auto; min-width: 0; }
.mbcard-l1 { display: flex; justify-content: space-between; align-items: center; gap: .5rem; }
.mbcard-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.mbcard-status { flex-shrink: 0; font-size: 1.15rem; line-height: 1; display: inline-flex; }
.mbcard-sub { font-size: .8rem; color: var(--bs-secondary-color); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: .05rem; }
.mbcard-amt { font-weight: 700; margin-top: .2rem; }        /* own line → long / FX / IDR amounts wrap here, never collide with the title */
.mbcard-amt .mbcard-fx { font-weight: 400; font-size: .85em; color: var(--bs-secondary-color); white-space: nowrap; }
.mbcard-chev { color: var(--bs-secondary-color); flex-shrink: 0; align-self: center; }
/* Claim variant: a column card (icon+title+amount row on top, progress/claim button below). */
.mbcard-claim { flex-direction: column; align-items: stretch; gap: 0; cursor: default; }
.mbcard-claim .mbcard-row { display: flex; align-items: center; gap: .7rem; width: 100%; }
.mbcard-claim .mbcard-extra { margin-top: .6rem; }

/* ── Phase 4: touch-target sweep ─────────────────────────────────────────────────────
   Guarantee a ~40-44px tappable box for the small icon controls the mobile audit flagged,
   without visibly enlarging the glyphs (the hit area grows, not the icon). */
.modal-mobile-box .modal-header .btn-back { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; min-width: 0; min-height: 0; padding: 0; }
.modal-mobile-box .modal-header .btn-back::before { block-size: 1.2rem; inline-size: 1.2rem; }   /* larger, centered chevron */
.modal-mobile-box .input-group-text.cursor-pointer { min-width: 44px; justify-content: center; }
.modal-mobile-box .btn-sm { min-height: 36px; }
.mbcard-chev { font-size: 1.15rem; padding: .45rem; margin: -.35rem; }   /* expand hit area, no layout shift */
#header-deposit-button > .btn { min-width: 40px; min-height: 40px; display: inline-flex; align-items: center; justify-content: center; }

/* Header: balance amount + deposit "+" joined into one connected pill. */
.header-balance-group { display: inline-flex; align-items: stretch; height: 38px; border: 1px solid var(--bs-border-color); border-radius: .5rem; overflow: hidden; }
.header-balance-amt { display: inline-flex; align-items: center; padding: 0 .7rem; font-weight: 600; color: var(--bs-body-color); background: var(--bs-body-bg); white-space: nowrap; text-decoration: none; }
.header-balance-plus { display: inline-flex; align-items: center; justify-content: center; width: 40px; background: var(--bs-primary); color: var(--bs-primary-contrast, #fff); text-decoration: none; font-size: 1.1rem; }
.header-balance-plus:hover, .header-balance-plus:focus { color: var(--bs-primary-contrast, #fff); opacity: .92; }
.header-balance-amt { max-width: 44vw; overflow: hidden; text-overflow: ellipsis; }   /* long IDR balance never overflows the header */

/* Bell + avatar as pressable rounded-square buttons, same 38px height as the balance pill. */
.header-sq-btn { display: inline-flex !important; align-items: center; justify-content: center; width: 38px; height: 38px; padding: 0 !important; border-radius: .5rem; border: 1px solid var(--bs-border-color); background: var(--bs-body-bg); color: var(--bs-body-color); position: relative; }
.header-sq-btn > i { font-size: 1.2rem; }
.header-sq-btn .avatar { width: 100%; height: 100%; }
.header-sq-btn .avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: .4rem !important; }
.header-sq-btn .badge-notifications { top: -4px; right: -4px; }
/* Avatar: fully rounded (circle), same 38px height — the bell stays a rounded square. */
#header-user .header-sq-btn { border-radius: 50%; }
#header-user .header-sq-btn .avatar img { border-radius: 50% !important; }

/* ── Phase 4: bottom-sheet primitive ─────────────────────────────────────────────────
   Slides up from the bottom for quick decisions / small inputs (OTP, pickers, info, bonus
   T&C) — the counterpart to the full-screen push. Dim backdrop, grabber, drag-to-dismiss. */
.mb-sheet-host { position: fixed; inset: 0; z-index: 1200; }   /* above the fullscreen mobileBox modal (~1090) */
.mb-sheet-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,.45); opacity: 0; transition: opacity .25s ease; }
.mb-sheet-host.mb-sheet-open .mb-sheet-backdrop { opacity: 1; }
.mb-sheet {
	position: absolute; left: 0; right: 0; bottom: 0; max-height: 88vh;
	display: flex; flex-direction: column; overflow: hidden;   /* header fixed; only the body scrolls */
	background: var(--bs-paper-bg, #fff); border-radius: 1.1rem 1.1rem 0 0;
	padding: 0 1.15rem calc(1.15rem + env(safe-area-inset-bottom, 0px));
	transform: translateY(100%); transition: transform .3s cubic-bezier(.32,.72,0,1);
	box-shadow: 0 -8px 28px rgba(0,0,0,.16);
	color: var(--bs-body-color);
}
.mb-sheet-host.mb-sheet-open .mb-sheet { transform: translateY(0); }
/* Fixed header (grabber + always-visible close × + title); the body scrolls below it. */
.mb-sheet-top { position: relative; flex-shrink: 0; min-height: 1.4rem; }
.mb-sheet-grabber { width: 40px; height: 4px; border-radius: 2px; background: var(--bs-secondary-bg, #d5d5db); margin: .4rem auto .3rem; }
.mb-sheet-close { position: absolute; top: -.1rem; right: -.3rem; border: 0; background: transparent; color: var(--bs-secondary-color); font-size: 1.7rem; line-height: 1; padding: .2rem .5rem; }
.mb-sheet-header { flex-shrink: 0; padding: .1rem 0 .6rem; }
.mb-sheet-title { font-weight: 600; margin: 0; }
.mb-sheet-body { flex: 1 1 auto; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; overflow-wrap: anywhere; padding-bottom: .25rem; }
/* Client-authored rich HTML (bonus/promo T&C from the localization editor) in a sheet: paragraphs
   and long strings wrap so the sheet never scrolls sideways, but a wide TABLE keeps its natural
   column widths and scrolls WITHIN its own container — only the table scrolls, never the whole
   sheet, and it never clamps into crushed columns. mbSheet.wrapTables() strips the editor's
   width / table-layout (the cause of the clamp) and tags each table .mb-rich-table.
   width:max-content → size to content (overflow → scroll) when wide; min-width:100% → fill the
   sheet when small; cell max-width caps a runaway long-text cell so it wraps instead of exploding. */
.mb-table-scroll { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; margin-bottom: .5rem; }
.mb-rich-table { width: max-content; min-width: 100%; max-width: none; }
.mb-rich-table td, .mb-rich-table th { max-width: 72vw; white-space: normal; overflow-wrap: anywhere; }
/* Bare (unstyled) client tables get a sane default look; any client inline styles still win. */
.mb-rich-table:not([border]) td, .mb-rich-table:not([border]) th { padding: .4rem .6rem; border: 1px solid var(--bs-border-color, #d9dee3); }
.mb-sheet-body img { max-width: 100%; height: auto; }
/* A moved modal body brings its own close button — redundant in a sheet (grabber/backdrop/drag close it). */
.mb-sheet-body > .btn-close, .mb-sheet-body .modal-body > .btn-close { display: none; }
@media (prefers-reduced-motion: reduce) { .mb-sheet-backdrop, .mb-sheet { transition: none; } }

/* Skeleton placeholder shown inside a freshly-pushed panel while its fragment loads, so a
   push feels instant instead of blank. Grey shimmer reads correctly on light + dark themes. */
.mb-skeleton { padding: .25rem 0; }

/* Modal close button: core.css's default .modal .btn-close carries transform: translate(23px,-25px)
   as a "floating chip" effect -- stacked on top of .modal-header .btn-close's own absolute
   positioning, it shoves the button up-right past the modal's rounded corner, outside the frame.
   The theme already ships a clean "inside the frame" variant for .modal-fullscreen /
   .modal-dialog-scrollable / .modal-top (zeroes the same transform) -- apply it to every modal
   so the close button sits inside the frame consistently everywhere, not just those types. */
.modal .btn-close {
	box-shadow: none;
	transform: translate(0, 0);
}
.modal .btn-close:hover,
.modal .btn-close:focus,
.modal .btn-close:active {
	transform: translate(0, 0);
}
.mb-sk-line, .mb-sk-card {
	border-radius: .375rem;
	background: linear-gradient(90deg, rgba(128,128,128,.15) 25%, rgba(128,128,128,.28) 37%, rgba(128,128,128,.15) 63%);
	background-size: 400% 100%;
	animation: mb-shimmer 1.4s ease infinite;
}
.mb-sk-line { height: .85rem; margin-bottom: .75rem; width: 100%; }
.mb-sk-card { height: 120px; margin-bottom: 1rem; }
@keyframes mb-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
@media (prefers-reduced-motion: reduce) { .mb-sk-line, .mb-sk-card { animation: none; } }

/*
* demo.css
* File include item demo only specific css only
******************************************************************************/

.app-brand-logo {
    display: none;
    flex-grow: 0;
    flex-shrink: 0;
    overflow: hidden;
    min-height: 1px;
}

@media (min-width: 1200px) {
    .layout-menu-collapsed:not(.layout-menu-hover):not(.layout-menu-offcanvas):not(.layout-menu-fixed-offcanvas) .app-brand-logo {
        display: block;
    }
}

.menu .app-brand.demo {
  height: 64px;
}

.app-brand-logo.demo svg {
  width: 34px;
  height: 24px;
}

.app-brand-text.demo {
  font-size: 1.375rem;
}

/* Side-navbar layout: make the top scrim follow the operator's background colour.
   core.css paints this 4.75rem blur strip from rgba(var(--bs-body-bg-rgb), ..). The index shells
   override --bs-body-bg (a hex) but there is no way to derive the "r, g, b" triplet from it in
   EL, so --bs-body-bg-rgb keeps core.css's hard-coded stock value (248,247,250 light /
   37,41,60 dark). The strip therefore stayed the default colour while the rest of the page
   changed -- and since it sits at z-index 1001 across the full width behind the navbar, that
   stale band is the first thing you look at, which is why the layout read as "not changing".
   Same selector as core.css, re-declared here (custom.css loads after it) with color-mix on the
   hex var directly, so no triplet is needed. Horizontal is untouched: core.css scopes the scrim
   to :not(.layout-horizontal). */
.layout-navbar-fixed .layout-wrapper:not(.layout-horizontal) .layout-page::before {
  background: linear-gradient(180deg,
    color-mix(in sRGB, var(--bs-body-bg) 70%, transparent) 44%,
    color-mix(in sRGB, var(--bs-body-bg) 43%, transparent) 73%,
    transparent);
}

/* ! For .layout-navbar-fixed added fix padding top to .layout-page */
/* Default navbar */
.layout-navbar-fixed .layout-wrapper:not(.layout-without-menu) .layout-page {
  padding-top: 64px !important;
}
.layout-navbar-fixed .layout-wrapper:not(.layout-horizontal):not(.layout-without-menu) .layout-page {
  padding-top: 72px !important;
}
/* Horizontal layout: clear the fixed .menu-horizontal that sits under the navbar.
   core.css does this with an adjacent-sibling selector (.menu-horizontal + [class*=container-]).
   The nav mega-menu panel, its <style> and its <script> now sit between the menu and
   #app-container, so that selector stopped matching and the menu row covered the top of the page.
   Same rule, general sibling combinator, so intervening markup no longer breaks it.
   Skipped when the brand has no nav items: that bar is hidden below, so reserving a row for it
   would leave an empty gap under the navbar instead. */
.layout-menu-fixed:not(.layout-navbar-hidden) .layout-horizontal .layout-page .menu-horizontal:not(.wb-menu-empty) ~ [class*=container-] {
  padding-block-start: 5.4rem !important;
}
/* No nav items = nothing to show. Kept in the DOM, taken out of the layout. */
.menu-horizontal.wb-menu-empty {
  display: none;
}
/* Navbar page z-index issue solution */
.content-wrapper .navbar {
  z-index: auto;
}

/*
* Content
******************************************************************************/

.demo-blocks > * {
  display: block !important;
}

.demo-inline-spacing > * {
  margin: 1rem 0.375rem 0 0 !important;
}

/* ? .demo-vertical-spacing class is used to have vertical margins between elements. To remove margin-top from the first-child, use .demo-only-element class with .demo-vertical-spacing class. For example, we have used this class in forms-input-groups.html file. */
.demo-vertical-spacing > * {
  margin-top: 1rem !important;
  margin-bottom: 0 !important;
}
.demo-vertical-spacing.demo-only-element > :first-child {
  margin-top: 0 !important;
}

.demo-vertical-spacing-lg > * {
  margin-top: 1.875rem !important;
  margin-bottom: 0 !important;
}
.demo-vertical-spacing-lg.demo-only-element > :first-child {
  margin-top: 0 !important;
}

.demo-vertical-spacing-xl > * {
  margin-top: 5rem !important;
  margin-bottom: 0 !important;
}
.demo-vertical-spacing-xl.demo-only-element > :first-child {
  margin-top: 0 !important;
}

/* Dropdown buttons going out of small screens */
@media (max-width: 576px) {
  #dropdown-variation-demo .btn-group .text-truncate {
    width: 254px;
    position: relative;
  }
  #dropdown-variation-demo .btn-group .text-truncate::after {
    position: absolute;
    top: 45%;
    right: 0.65rem;
  }
}

/*
* Layout demo
******************************************************************************/

.layout-demo-wrapper {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -ms-flex-direction: column;
  flex-direction: column;
  margin-top: 1rem;
}
.layout-demo-placeholder img {
  width: 900px;
}
.layout-demo-info {
  text-align: center;
  margin-top: 1rem;
}

/*
* Launch Box
******************************************************************************/

/* Portrait: use max-width */
@media (orientation: portrait) and (max-width: 600px) {
  .game-content-icon {
    height: 15rem;
  }
}

/* Landscape: use max-height */
@media (orientation: landscape) and (max-height: 500px) {
  .game-content-icon {
    height: 5rem;
  }
}

/*
* Game List
******************************************************************************/


/*
* CLAIM REWARD PANEL (.cr-*)
******************************************************************************/

/* ── Keyframes ── */
@keyframes cr-card-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes cr-shimmer {
  0%, 100% { opacity: 0.4; }
  50%       { opacity: 1; }
}
@keyframes cr-pulse-dot {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%       { opacity: 0.45; transform: scale(0.65); }
}

/* ── Tab bar ── */
.cr-tabs {
  display: flex;
  gap: 4px;
  padding: 5px;
  border-radius: 14px;
  background: rgba(0,0,0,0.04);
  border: 1px solid rgba(0,0,0,0.07);
  width: fit-content;
  margin-bottom: 24px;
  flex-wrap: wrap;
}
[data-bs-theme="dark"] .cr-tabs {
  background: rgba(255,255,255,0.04);
  border-color: rgba(255,255,255,0.07);
}
.cr-tab-btn {
  padding: 8px 18px;
  border-radius: 10px;
  border: none;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  color: var(--bs-secondary-color);
  background: transparent;
  transition: all 0.25s ease;
  display: flex;
  align-items: center;
  gap: 6px;
}
.cr-tab-btn:not(.active):hover {
  background: rgba(var(--bs-primary-rgb), 0.07);
  color: var(--bs-primary);
}
.cr-tab-btn.active {
  background: var(--bs-primary);
  color: var(--bs-primary-contrast, #fff);
  box-shadow: 0 4px 16px rgba(var(--bs-primary-rgb), 0.38);
}
.cr-tab-badge {
  font-size: 10px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 20px;
  background: rgba(255,255,255,0.24);
  line-height: 1.5;
}

/* ── Base reward card ── */
.cr-card {
  background: var(--bs-card-bg);
  border: 1px solid var(--bs-card-border-color);
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
  border-radius: 20px;
  padding: 22px 20px;
  margin-bottom: 14px;
  position: relative;
  overflow: hidden;
  transition: border-color 0.3s ease, box-shadow 0.3s ease, transform 0.25s ease;
  animation: cr-card-in 0.4s ease both;
}
.cr-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 36px rgba(var(--bs-primary-rgb), 0.10);
  border-color: rgba(var(--bs-primary-rgb), 0.28);
}

/* Locked variant */
.cr-card.cr-locked {
  --bs-card-border-color: rgba(var(--bs-warning-rgb), 0.45);
}
.cr-card.cr-locked:hover {
  --bs-card-border-color: rgba(var(--bs-warning-rgb), 0.65);
  box-shadow: 0 8px 36px rgba(var(--bs-warning-rgb), 0.10);
}

/* Ready variant */
.cr-card.cr-ready {
  --bs-card-border-color: rgba(var(--bs-success-rgb), 0.45);
}
.cr-card.cr-ready:hover {
  --bs-card-border-color: rgba(var(--bs-success-rgb), 0.65);
  box-shadow: 0 8px 36px rgba(var(--bs-success-rgb), 0.10);
}

/* ── Card internals ── */
.cr-type-badge {
  font-size: 10.5px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 6px;
  background: rgba(var(--bs-primary-rgb), 0.12);
  color: var(--bs-primary);
  border: 1px solid rgba(var(--bs-primary-rgb), 0.22);
  letter-spacing: 0.2px;
}
.cr-ticket-id {
  font-size: 11px;
  opacity: 0.8;
}
.cr-amount-row {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin: 6px 0 4px;
}
.cr-currency {
  font-size: 13px;
  font-weight: 500;
}
.cr-amount {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -0.6px;
  line-height: 1;
  color: var(--bs-body-color);
}
.cr-amount.cr-amount-ready  { color: var(--bs-success); }
.cr-amount.cr-amount-locked { color: var(--bs-body-color); }
.cr-expiry {
  font-size: 11.5px;
  display: flex;
  align-items: center;
  gap: 5px;
}
.cr-expiry.cr-urgent { color: var(--bs-danger);  font-weight: 600; }
.cr-expiry.cr-soon   { color: var(--bs-warning); font-weight: 600; }

/* Status badge */
.cr-status-badge {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 10px;
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
  flex-shrink: 0;
}
.cr-status-badge.cr-s-locked {
  background: rgba(249,115,22,0.10);
  color: #f97316;
  border: 1px solid rgba(249,115,22,0.22);
}
.cr-status-badge.cr-s-ready {
  background: rgba(var(--bs-success-rgb), 0.10);
  color: var(--bs-success);
  border: 1px solid rgba(var(--bs-success-rgb), 0.22);
}
.cr-status-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
  animation: cr-pulse-dot 2s ease-in-out infinite;
}
.cr-status-dot.cr-fast { animation-duration: 0.9s; }

/* ── Divider ── */
.cr-divider {
  height: 1px;
  background: rgba(0,0,0,0.07);
  margin: 14px 0;
}
[data-bs-theme="dark"] .cr-divider {
  background: rgba(255,255,255,0.07);
}

/* ── Progress bar ── */
.cr-progress-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}
.cr-progress-label {
  font-size: 11.5px;
}
.cr-progress-vals {
  font-size: 11px;
  display: flex;
  align-items: center;
}
.cr-progress-cur  { font-weight: 600; }
.cr-progress-sep  { opacity: 0.4; margin: 0 3px; }
.cr-progress-tot  { opacity: 0.7; }
.cr-progress-cur.cr-cur-locked { color: #f97316; }
.cr-progress-cur.cr-cur-ready  { color: var(--bs-success); }

.cr-progress-track {
  height: 8px;
  background: rgba(0,0,0,0.07);
  border-radius: 20px;
  overflow: hidden;
}
[data-bs-theme="dark"] .cr-progress-track {
  background: rgba(255,255,255,0.06);
}
.cr-progress-fill {
  height: 100%;
  border-radius: 20px;
  width: 0%;
  position: relative;
  transition: width 1.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.cr-progress-fill.cr-fill-locked {
  background: linear-gradient(90deg, #f97316, #ffb347, #ffd96a);
  box-shadow: 0 0 10px rgba(249,115,22,0.38);
}
.cr-progress-fill.cr-fill-locked::after {
  content: '';
  position: absolute; right: 0; top: 0; bottom: 0; width: 20px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.35));
  animation: cr-shimmer 2s ease-in-out infinite;
}
.cr-progress-fill.cr-fill-ready {
  background: var(--bs-primary);
  box-shadow: 0 0 10px rgba(var(--bs-primary-rgb), 0.35);
}
.cr-progress-pct {
  font-size: 10px;
  font-weight: 600;
  text-align: right;
  margin-top: 4px;
}
.cr-progress-pct.cr-locked-pct { color: #f97316; }
.cr-progress-pct.cr-ready-pct  { color: var(--bs-primary); }

/* ── Unlock hint box ── */
.cr-unlock-hint {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
  padding: 10px 14px;
  background: rgba(249,115,22,0.05);
  border: 1px solid rgba(249,115,22,0.12);
  border-radius: 10px;
}
[data-bs-theme="dark"] .cr-unlock-hint {
  background: rgba(249,115,22,0.07);
  border-color: rgba(249,115,22,0.15);
}
.cr-unlock-label {
  font-size: 11.5px;
  display: flex;
  align-items: center;
  gap: 5px;
}
.cr-unlock-remaining {
  font-size: 12px;
  font-weight: 700;
  color: #f97316;
  white-space: nowrap;
}

/* ── Claim buttons ── */
.cr-claim-btn {
  width: 100%;
  margin-top: 16px;
  padding: 12px;
  border-radius: 12px;
  border: none;
  font-size: 13px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  letter-spacing: 0.2px;
  transition: all 0.3s ease;
}
.cr-claim-btn.cr-btn-ready {
  background: var(--bs-primary);
  color: var(--bs-primary-contrast, #fff);
  cursor: pointer;
  box-shadow: 0 4px 20px rgba(var(--bs-primary-rgb), 0.30);
}
.cr-claim-btn.cr-btn-ready:hover {
  box-shadow: 0 6px 28px rgba(var(--bs-primary-rgb), 0.48);
  transform: translateY(-1px);
}
.cr-claim-btn.cr-btn-locked {
  background: rgba(0,0,0,0.04);
  border: 1px solid rgba(0,0,0,0.07);
  cursor: not-allowed;
  opacity: 0.75;
}
[data-bs-theme="dark"] .cr-claim-btn.cr-btn-locked {
  background: rgba(255,255,255,0.04);
  border-color: rgba(255,255,255,0.07);
}

/* ── History items ── */
.cr-history-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 13px 16px;
  background: rgba(255,255,255,0.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255,255,255,0.75);
  border-radius: 14px;
  margin-bottom: 8px;
  animation: cr-card-in 0.4s ease both;
  transition: filter 0.2s ease;
  gap: 12px;
}
[data-bs-theme="dark"] .cr-history-item {
  background: rgba(255,255,255,0.035);
  border-color: rgba(255,255,255,0.07);
}
.cr-history-item:hover { filter: brightness(1.04); }
.cr-history-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--bs-body-color);
}
.cr-history-date {
  font-size: 11px;
  margin-top: 3px;
}
.cr-history-amount {
  font-size: 14px;
  font-weight: 700;
}
.cr-history-amount.cr-claimed { color: var(--bs-success); }
.cr-history-amount.cr-expired { }
.cr-history-badge {
  font-size: 10px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 6px;
  margin-top: 4px;
  display: inline-block;
}
.cr-history-badge.cr-b-claimed {
  background: rgba(var(--bs-success-rgb), 0.10);
  color: var(--bs-success);
  border: 1px solid rgba(var(--bs-success-rgb), 0.20);
}
.cr-history-badge.cr-b-expired {
  background: rgba(var(--bs-danger-rgb), 0.08);
  color: var(--bs-danger);
  border: 1px solid rgba(var(--bs-danger-rgb), 0.15);
}

/* ── Show more button ── */
.cr-show-more-btn {
  width: 100%;
  padding: 10px;
  margin-top: 4px;
  background: transparent;
  border: 1px solid rgba(var(--bs-primary-rgb), 0.25);
  border-radius: 10px;
  color: var(--bs-primary);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s ease;
}
.cr-show-more-btn:hover {
  background: rgba(var(--bs-primary-rgb), 0.06);
  border-color: rgba(var(--bs-primary-rgb), 0.45);
}

/* ── Empty state ── */
.cr-empty {
  text-align: center;
  padding: 40px 20px;
  font-size: 13px;
}
.cr-empty-icon {
  font-size: 32px;
  display: block;
  margin-bottom: 10px;
  opacity: 0.35;
}

/* ── Section label ── */
.cr-section-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  opacity: 0.7;
  margin-bottom: 16px;
}

/* ── VIP Portal (vip-portal.jsp) ── */
.vipp-tier-icon {
  width: 52px; height: 52px; border-radius: 14px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.vipp-tier-icon img { width: 100%; height: 100%; object-fit: contain; }
.vipp-tier-icon-fallback { font-size: 24px; }
.vipp-perk-icon {
  width: 40px; height: 40px; border-radius: 10px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.vipp-perk-icon img { width: 100%; height: 100%; object-fit: contain; }
.vipp-benefit-icon {
  width: 28px; height: 28px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
.vipp-progress { height: 8px; border-radius: 99px; overflow: hidden; background: var(--bs-tertiary-bg, #f0f0f0); }
.vipp-progress-bar { height: 100%; border-radius: 99px; transition: width .8s ease; }
.vipp-section-head {
  font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  display: flex; align-items: center; gap: 8px; margin-bottom: 1rem;
}
.vipp-month-chip {
  display: flex; justify-content: space-between;
  padding: 8px 12px; border-radius: 10px;
  background: var(--bs-tertiary-bg, #f0f0f0);
}
.vipp-manual-block {
  padding: 12px 14px; border-radius: 10px;
  border-left: 3px solid var(--bs-primary);
  background: var(--bs-tertiary-bg, #f0f0f0);
}
.vipp-manual-block .vipp-row { display: flex; justify-content: space-between; padding: 3px 0; }
.vipp-greeting-open {
  width: 44px; height: 44px; border-radius: 12px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(var(--bs-primary-rgb, 105,108,255), .12);
  border: 1px solid rgba(var(--bs-primary-rgb, 105,108,255), .3);
  color: var(--bs-primary); cursor: pointer; transition: all .2s;
}
.vipp-greeting-open:hover { background: var(--bs-primary); color: var(--bs-primary-contrast, #fff); }
.vipp-level-card { position: relative; overflow: hidden; }
.vipp-level-card-bg {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(60% 100% at 0% 0%, rgba(var(--bs-primary-rgb, 105,108,255), .08), transparent 70%);
  border-radius: inherit;
}
.vipp-warn-banner {
  margin-top: .75rem; padding: 10px 12px;
  display: flex; align-items: center; gap: 8px;
  background: rgba(245,158,11,.1);
  border: 1px solid rgba(245,158,11,.3);
  border-radius: .75rem;
  color: #F59E0B;
}
.vipp-perk-row {
  padding: .875rem 1.25rem;
  display: flex; align-items: center; gap: .875rem;
}
.vipp-perk-row + .vipp-perk-row { border-top: 1px solid var(--bs-border-color, #e0e0e0); }
.vipp-perk-content { flex: 1; min-width: 0; }
.vipp-section-label {
  font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  display: flex; align-items: center; gap: 8px; margin: 1.25rem 0 .75rem;
}
.vipp-lock-hint {
  font-weight: 400; text-transform: none; letter-spacing: 0;
  color: var(--bs-secondary-color); display: flex; align-items: center; gap: 4px;
}
.vipp-tier-accordion { position: relative; }
.vipp-tier-accordion .accordion-item.vipp-tier-current {
  border-color: var(--bs-primary) !important;
  box-shadow: 0 0 0 1px var(--bs-primary), 0 4px 16px rgba(var(--bs-primary-rgb, 105,108,255), .2);
}

/* ── TARGET mode progress cards ── */
.vipp-target-card {
  padding: .75rem; border-radius: .75rem;
  background: rgba(var(--bs-body-color-rgb, 33,37,41), .04);
  border: 1px solid var(--bs-border-color);
}
.vipp-target-card-label {
  font-size: 10px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--bs-secondary-color); margin-bottom: 4px;
}
.vipp-target-card-value { font-size: 15px; font-weight: 600; margin-bottom: 6px; }
.vipp-target-card-hint  { font-size: 10.5px; color: var(--bs-secondary-color); margin-top: 4px; }

/* ── Tier group header badge (upcoming perks) ── */
.vipp-tier-badge {
  background: rgba(var(--bs-secondary-rgb, 108,117,125), .12);
  color: var(--bs-secondary-color);
  font-size: 10px; font-weight: 600;
}

/* ── Modal: current-tier sub-label ── */
.vipp-current-tier-label { font-size: 11px; }

/*
* AFFILIATE / REFER-A-FRIEND (.aff-*)  -- component: affiliateT1.jsp
* Visual emphasis layer. Everything keys off --bs-primary / --bs-primary-rgb so each
* white-label brand keeps its own accent (no hardcoded colors). Scoped to .aff-component.
******************************************************************************/

.aff-component .aff-hero {
	position: relative;
	overflow: hidden;
	border: 1px solid rgba(var(--bs-primary-rgb), .25);
	background:
		radial-gradient(120% 150% at 88% 15%, rgba(var(--bs-primary-rgb), .30), transparent 60%),
		linear-gradient(135deg, rgba(var(--bs-primary-rgb), .16), rgba(var(--bs-primary-rgb), .02));
}
.aff-component .aff-hero .card-body { padding: 2.5rem 2.25rem; }
.aff-component .aff-hero-title { font-size: clamp(1.6rem, 3.4vw, 2.6rem); line-height: 1.1; }
.aff-component .aff-hero-rate {
	font-size: clamp(1.5rem, 3.2vw, 2.35rem);
	font-weight: 800;
	line-height: 1.15;
	color: var(--bs-primary);
	text-shadow: 0 0 26px rgba(var(--bs-primary-rgb), .45);
	letter-spacing: .3px;
}
.aff-component .aff-cta-main {
	font-size: 1.05rem;
	padding: .72rem 2.1rem;
	box-shadow: 0 8px 24px rgba(var(--bs-primary-rgb), .38);
}
.aff-component .aff-benefit-card { transition: transform .15s ease, box-shadow .15s ease; }
.aff-component .aff-benefit-card:hover { transform: translateY(-3px); box-shadow: 0 12px 30px rgba(0,0,0,.28); }
.aff-component .aff-benefit-value {
	font-weight: 800;
	color: var(--bs-primary);
	text-shadow: 0 0 16px rgba(var(--bs-primary-rgb), .35);
}
.aff-component .aff-benefit-head { font-size: 1.35rem; line-height: 1.2; }
.aff-component .aff-benefit-eyebrow {
	font-size: .7rem; font-weight: 700; letter-spacing: .8px; text-transform: uppercase;
	color: var(--bs-secondary-color); margin-bottom: .15rem;
}
.aff-component .aff-bcard .aff-benefit-value { display: block; font-size: 1.9rem; line-height: 1.1; margin-bottom: .25rem; }

/* Rules & Benefits modal (View Details / Terms) - deep-link section highlight. */
.affplan-sec { scroll-margin-top: .5rem; border-radius: .375rem; }
.affplan-flash { animation: affplan-flash 1.2s ease; }
@keyframes affplan-flash {
	0%, 100% { box-shadow: 0 0 0 0 rgba(var(--bs-primary-rgb), 0); }
	30% { box-shadow: 0 0 0 .22rem rgba(var(--bs-primary-rgb), .4); }
}

/* ---- Rules & Benefits modal: each section as a distinct accented card ---- */
.affplan .affplan-card { border: 1px solid rgba(var(--bs-body-color-rgb), .12); border-left-width: 4px;
	border-radius: .6rem; overflow: hidden; background: var(--bs-body-bg); }
.affplan .affplan-card-head { display: flex; justify-content: space-between; align-items: center; gap: .5rem;
	padding: .7rem 1rem; background: rgba(var(--bs-body-color-rgb), .035);
	border-bottom: 1px solid rgba(var(--bs-body-color-rgb), .08); }
.affplan .affplan-card-icon { display: inline-flex; align-items: center; justify-content: center;
	width: 1.7rem; height: 1.7rem; border-radius: .4rem; font-weight: 800; font-size: .9rem;
	margin-right: .55rem; color: var(--bs-primary-contrast, #fff); flex: 0 0 auto; }
.affplan .affplan-card-title { font-weight: 700; font-size: 1rem; display: flex; align-items: center; }
.affplan .affplan-card-val { font-size: .8rem; font-weight: 700; white-space: nowrap; }
.affplan .affplan-card-body { padding: 1rem 1.1rem; }
.affplan .affplan-card-body > p:first-child { margin-top: -.15rem; }
/* per-benefit accent (border + icon tile + title colour) */
.affplan .affplan-accent-primary   { border-left-color: var(--bs-primary); }
.affplan .affplan-accent-primary   .affplan-card-icon { background: var(--bs-primary); }
.affplan .affplan-accent-primary   .affplan-card-title { color: var(--bs-primary); }
.affplan .affplan-accent-info      { border-left-color: var(--bs-info); }
.affplan .affplan-accent-info      .affplan-card-icon { background: var(--bs-info); }
.affplan .affplan-accent-info      .affplan-card-title { color: var(--bs-info); }
.affplan .affplan-accent-success   { border-left-color: var(--bs-success); }
.affplan .affplan-accent-success   .affplan-card-icon { background: var(--bs-success); }
.affplan .affplan-accent-success   .affplan-card-title { color: var(--bs-success); }
.affplan .affplan-accent-warning   { border-left-color: var(--bs-warning); }
.affplan .affplan-accent-warning   .affplan-card-icon { background: var(--bs-warning); color: #3a2a00; }
.affplan .affplan-accent-warning   .affplan-card-title { color: #b3850b; }
.affplan .affplan-accent-secondary { border-left-color: var(--bs-secondary); }
.affplan .affplan-accent-secondary .affplan-card-icon { background: var(--bs-secondary); }
.affplan .affplan-accent-secondary .affplan-card-title { color: var(--bs-secondary-color, var(--bs-secondary)); }
/* sub-headings inside a section read as quiet labels above each table/ladder */
.affplan .affplan-sublabel { font-weight: 700; font-size: .8rem; letter-spacing: .02em;
	text-transform: uppercase; color: var(--bs-secondary-color); margin-bottom: .35rem; }

/* ---- Rules & Benefits modal: rich content (mirrors AffiliateAdmin plan.jsp), theme-adaptive ---- */
.affplan .affplan-formula { border: 1px solid rgba(var(--bs-body-color-rgb), .12); border-radius: .5rem;
	padding: .85rem 1rem; margin-bottom: 1rem; background: rgba(var(--bs-body-color-rgb), .03); }
.affplan .affplan-formula code { color: var(--bs-primary); background: rgba(var(--bs-primary-rgb), .08);
	padding: .1rem .4rem; border-radius: .3rem; font-size: .85rem; }
.affplan table.affplan-tbl { font-size: .85rem; }
.affplan table.affplan-tbl > :not(caption) > * > * { border-color: rgba(var(--bs-body-color-rgb), .12); }
.affplan .affplan-chip { display: inline-block; margin: 0 .25rem .25rem 0; }

/* qualification checklist - CSS checkmark (no icon-font dependency) */
.affplan .affplan-check { list-style: none; padding-left: 0; margin-bottom: .5rem; }
.affplan .affplan-check li { position: relative; padding: .2rem 0 .2rem 1.6rem; }
.affplan .affplan-check li::before { content: ''; position: absolute; left: .35rem; top: .45rem;
	width: .42rem; height: .78rem; border: solid #28c76f; border-width: 0 .14rem .14rem 0; transform: rotate(45deg); }

/* milestone reward ladder */
.affplan .ms-ladder { border-left: 3px solid rgba(var(--bs-body-color-rgb), .15); margin-left: .6rem; padding-left: 1rem; }
.affplan .ms-step { position: relative; padding: .35rem 0 .75rem 0; }
.affplan .ms-step::before { content: ''; position: absolute; left: -1.45rem; top: .55rem; width: .8rem; height: .8rem;
	border-radius: 50%; background: rgba(var(--bs-body-color-rgb), .2); }

/* settle summary box */
.affplan .affplan-settle { background: rgba(var(--bs-body-color-rgb), .04); border-radius: .45rem; padding: .8rem 1rem; }
.affplan .affplan-settle .pos { color: #28c76f; font-weight: 600; }
.affplan .affplan-settle .neg { color: #ff4d4f; font-weight: 600; }

/* sub-affiliate revenue-share org chart */
.affplan .sa-tree { overflow-x: auto; padding: .5rem 0 1rem; }
.affplan .sa-col { display: flex; flex-direction: column; align-items: center; }
.affplan .sa-row { display: flex; justify-content: center; gap: 1.25rem; align-items: flex-start; flex-wrap: nowrap; }
.affplan .sa-connector { width: 2px; height: 16px; background: rgba(var(--bs-body-color-rgb), .2); margin: .1rem 0; }
.affplan .sa-edge { font-size: .72rem; line-height: 1.2; color: var(--bs-secondary-color); text-align: center; margin: .35rem 0; max-width: 200px; }
.affplan .sa-box { border: 1px solid rgba(var(--bs-primary-rgb), .55); border-radius: .55rem;
	background: rgba(var(--bs-primary-rgb), .04); padding: .55rem .85rem; min-width: 195px; text-align: center; }
.affplan .sa-box.sa-root { border-color: var(--bs-primary); background: rgba(var(--bs-primary-rgb), .1); }
.affplan .sa-box.neg { border-color: rgba(255,77,79,.7); background: rgba(255,77,79,.07); }
.affplan .sa-box.greyed { opacity: .5; }
.affplan .sa-box .sa-name { font-weight: 700; margin-bottom: .3rem; font-size: .85rem; }
.affplan .sa-box .sa-line { font-size: .8rem; }
.affplan .sa-box .sa-total { font-weight: 600; border-top: 1px solid rgba(var(--bs-body-color-rgb), .12);
	margin-top: .3rem; padding-top: .25rem; font-size: .82rem; }
.affplan .pos { color: #28c76f; }
.affplan .neg { color: #ff4d4f; }

/* payout icon row + glossary */
.affplan .affplan-icon-row .col { text-align: center; }
.affplan .affplan-icon-row i { font-size: 1.5rem; opacity: .7; }
.affplan .affplan-gloss dt { font-weight: 600; }
.aff-component .aff-details { font-weight: 600; }
.aff-component .aff-ticker-label { font-size: .72rem; letter-spacing: .8px; font-weight: 700; }
.aff-component .aff-ticker-total {
	font-size: 1.7rem; font-weight: 800; color: var(--bs-primary);
	text-shadow: 0 0 18px rgba(var(--bs-primary-rgb), .35);
}
.aff-component .aff-hero-img { max-height: 280px; filter: drop-shadow(0 12px 30px rgba(0,0,0,.35)); }

/* Soft, translucent inset surface - just enough to box content, adapts to theme instead of
   the heavy bg-body-tertiary (which renders near-black on these brand themes). */
.aff-component .aff-inset {
	background: rgba(0, 0, 0, .035);
	border: 1px solid rgba(0, 0, 0, .07);
}
[data-bs-theme="dark"] .aff-component .aff-inset {
	background: rgba(255, 255, 255, .045);
	border: 1px solid rgba(255, 255, 255, .08);
}

/* Affiliate-card stat tiles (Total Earned / Registrations / Estimated Pending / Available). */
.aff-component .aff-stat { transition: transform .15s ease, box-shadow .15s ease; }
.aff-component .aff-stat:hover { transform: translateY(-3px); box-shadow: 0 10px 26px rgba(0,0,0,.22); }
.aff-component .aff-stat-icon {
	display: block;
	font-size: 1.6rem;
	color: var(--bs-primary);
	margin-bottom: .35rem;
}
.aff-component .aff-stat-value { font-size: 1.35rem; font-weight: 800; line-height: 1.1; }

/* ── P4.5 per-section spacing ──────────────────────────────────────────────
   Extra vertical padding a page author can add around any component/section
   from the Web Builder ("Section settings > Spacing"). Absent = no wrapper at
   all (existing pages unchanged). Values scale down a touch on mobile so a
   "Large" gap doesn't dominate a phone screen. */
.wb-space-sm { padding-top: .75rem; padding-bottom: .75rem; }
.wb-space-md { padding-top: 2rem;   padding-bottom: 2rem; }
.wb-space-lg { padding-top: 4rem;   padding-bottom: 4rem; }
@media (max-width: 767.98px) {
	.wb-space-sm { padding-top: .5rem;   padding-bottom: .5rem; }
	.wb-space-md { padding-top: 1.25rem; padding-bottom: 1.25rem; }
	.wb-space-lg { padding-top: 2.25rem; padding-bottom: 2.25rem; }
}

/* ── P5 F2 section design (background + entrance animation) ─────────────────
   A "section shell" a page author can give any component from the Web Builder
   ("Section settings > Background / Animation"). The background is an inline
   style on .wb-section-shell; an optional dark overlay sits above it and the
   content rides above the overlay in .wb-section-inner. Absent design = no
   shell class at all (existing pages unchanged). */
.wb-section-shell { position: relative; }
.wb-bg-overlay { position: absolute; inset: 0; background: #000; z-index: 0; pointer-events: none; }
.wb-section-inner { position: relative; z-index: 1; }

/* Entrance animations. JS adds .wb-anim-armed (initial hidden state) then .in when the
   section scrolls into view; without JS the content simply stays visible. Speed via the
   --wb-anim-d custom property. prefers-reduced-motion disables the motion entirely. */
.wb-anim-armed { transition: opacity var(--wb-anim-d, .6s) ease-out, transform var(--wb-anim-d, .6s) ease-out; }
/* will-change only while the reveal is pending -- it creates a new stacking context, which
   permanently traps any modal nested inside the section (its backdrop is appended to <body>
   and paints above the trapped subtree regardless of the modal's own z-index). Drop it the
   moment .in lands so sections settle back into normal body stacking after they've animated in. */
.wb-anim-armed:not(.in) { will-change: opacity, transform; }
.wb-anim-armed.wb-anim-fadeup { opacity: 0; transform: translateY(24px); }
.wb-anim-armed.wb-anim-zoomin { opacity: 0; transform: scale(.9); }
.wb-anim-armed.wb-anim-slidel { opacity: 0; transform: translateX(-28px); }
.wb-anim-armed.wb-anim-slider { opacity: 0; transform: translateX(28px); }
.wb-anim-armed.in { opacity: 1 !important; transform: none !important; }
.wb-anim-fast { --wb-anim-d: .4s; }
.wb-anim-slow { --wb-anim-d: .9s; }
@media (prefers-reduced-motion: reduce) {
	.wb-anim-armed { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* ---- Text on the accent colour ----------------------------------------------------------------
   The template picks black or white per accent colour (--bs-primary-contrast, set at page load by
   helpers.js) for its buttons and the active menu item, but a handful of components were left with
   a hard white -- so on a light accent (e.g. orange) their labels stayed white and unreadable while
   everything else turned black. Point them at the same variable. ------------------------------- */
.nav-pills { --bs-nav-pills-link-active-color: var(--bs-primary-contrast); }
.pagination { --bs-pagination-active-color: var(--bs-primary-contrast); }
.progress { --bs-progress-bar-color: var(--bs-primary-contrast); }
.badge.bg-primary { color: var(--bs-primary-contrast) !important; }
.custom-popover .popover-header { color: var(--bs-primary-contrast); }
/* any element painted with the accent utility, so its text follows too */
.bg-primary { color: var(--bs-primary-contrast); }
