merge: explain 48h lucky gift jackpot eligibility
This commit is contained in:
commit
17a94eaf94
@ -353,11 +353,21 @@ function luckyGiftConfigPayload(config = {}) {
|
||||
jackpot_spend_threshold_coins: numberValue(
|
||||
config.jackpot_spend_threshold_coins ?? config.jackpotSpendThresholdCoins,
|
||||
),
|
||||
jackpot_user_72h_rtp_max_percent: numberValue(
|
||||
config.jackpot_user_72h_rtp_max_percent ?? config.jackpotUser72hRTPMaxPercent,
|
||||
jackpot_user_48h_rtp_max_percent: numberValue(
|
||||
config.jackpot_user_48h_rtp_max_percent ??
|
||||
config.jackpotUser48hRTPMaxPercent ??
|
||||
config.jackpotUser48hRtpMaxPercent ??
|
||||
config.jackpot_user_72h_rtp_max_percent ??
|
||||
config.jackpotUser72hRTPMaxPercent ??
|
||||
config.jackpotUser72hRtpMaxPercent,
|
||||
),
|
||||
jackpot_user_day_rtp_max_percent: numberValue(
|
||||
config.jackpot_user_day_rtp_max_percent ?? config.jackpotUserDayRTPMaxPercent,
|
||||
jackpot_user_round_rtp_max_percent: numberValue(
|
||||
config.jackpot_user_round_rtp_max_percent ??
|
||||
config.jackpotUserRoundRTPMaxPercent ??
|
||||
config.jackpotUserRoundRtpMaxPercent ??
|
||||
config.jackpot_user_day_rtp_max_percent ??
|
||||
config.jackpotUserDayRTPMaxPercent ??
|
||||
config.jackpotUserDayRtpMaxPercent,
|
||||
),
|
||||
loss_streak_guarantee: numberValue(config.loss_streak_guarantee ?? config.lossStreakGuarantee),
|
||||
low_water_nonzero_factor_percent: numberValue(
|
||||
|
||||
@ -377,15 +377,15 @@ export function LuckyGiftConfigSections({ appOptions, form, isCreate, onChange }
|
||||
/>
|
||||
<NumberField
|
||||
form={form}
|
||||
label="用户当日返还触发线 (%)"
|
||||
name="jackpot_user_day_rtp_max_percent"
|
||||
label="用户本轮返还触发线 (%)"
|
||||
name="jackpot_user_round_rtp_max_percent"
|
||||
step="0.01"
|
||||
onChange={onChange}
|
||||
/>
|
||||
<NumberField
|
||||
form={form}
|
||||
label="用户近 72 小时返还触发线 (%)"
|
||||
name="jackpot_user_72h_rtp_max_percent"
|
||||
label="用户近 48 小时返还触发线 (%)"
|
||||
name="jackpot_user_48h_rtp_max_percent"
|
||||
step="0.01"
|
||||
onChange={onChange}
|
||||
/>
|
||||
@ -396,11 +396,13 @@ export function LuckyGiftConfigSections({ appOptions, form, isCreate, onChange }
|
||||
onChange={onChange}
|
||||
/>
|
||||
<NumberField
|
||||
disabled
|
||||
form={form}
|
||||
helperText="按应用奖池规则配置"
|
||||
label="用户日累计消费触发门槛(金币)"
|
||||
helperText="仅兼容历史配置,当前规则不参与大奖资格"
|
||||
label="用户日累计消费触发门槛(金币)— 已停用"
|
||||
name="jackpot_spend_threshold_coins"
|
||||
onChange={onChange}
|
||||
required={false}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
@ -473,28 +475,30 @@ function JackpotFlowSummary() {
|
||||
return (
|
||||
<div className="ops-jackpot-flow" aria-label="大奖产生方式">
|
||||
<div>
|
||||
<strong>1. 消费达标优先</strong>
|
||||
<span>当天累计消费每跨过一次门槛,就保存一次大奖资格;资格从下一抽开始使用。</span>
|
||||
<strong>1. 大盘先通过</strong>
|
||||
<span>本轮大盘 RTP 不高于全局触发线,才继续检查用户;等于触发线也可通过。</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong>2. 返还偏低补偿</strong>
|
||||
<span>没有待用资格时,整体、用户当天和近 72 小时平均返还都不高于触发线,才尝试大奖。</span>
|
||||
<strong>2. 用户两项都通过</strong>
|
||||
<span>用户本轮 RTP 和近 48 小时 RTP 都必须严格低于各自触发线,少一项都不能出大奖。</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong>3. 只从付得起的档位选</strong>
|
||||
<span>先剔除奖池或限额不足的倍率,再在剩余倍率中等机会选择;消费资格付不起时会保留。</span>
|
||||
<strong>3. 下次送礼尝试大奖</strong>
|
||||
<span>
|
||||
用户下次送礼时,先剔除奖池或限额付不起的倍率,再随机选择;没有可支付倍率就不出大奖,本轮资格也不会顺延或重复使用。
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function NumberField({ disabled = false, form, helperText, label, name, onChange, step = "1" }) {
|
||||
function NumberField({ disabled = false, form, helperText, label, name, onChange, required = true, step = "1" }) {
|
||||
return (
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
helperText={helperText}
|
||||
label={<LuckyGiftFieldLabel field={name} label={label} />}
|
||||
required
|
||||
required={required}
|
||||
size="small"
|
||||
slotProps={{ htmlInput: { inputMode: "decimal", min: 0, step } }}
|
||||
type="number"
|
||||
|
||||
@ -23,7 +23,7 @@ const FIELD_HELP = {
|
||||
enabled: {
|
||||
summary: "决定新版本发布后是否立即用于真实送礼。关闭时规则仍会保存,但不会触发幸运开奖。",
|
||||
adjust: "首次配置或大幅调整时可先保持停用,核对资金比例和上限后再启用。",
|
||||
constraint: "启用 dynamic_v3 前必须填完大奖消费门槛和所有返奖上限。",
|
||||
constraint: "启用 dynamic_v3 前必须填完三项大奖 RTP 触发线和所有返奖上限。",
|
||||
},
|
||||
target_rtp_percent: {
|
||||
summary: "表示基础奖档的配置目标。例如填 98,代表各阶段的“倍率 × 基础概率”预计返还约为 98%。",
|
||||
@ -54,9 +54,10 @@ const FIELD_HELP = {
|
||||
"按整数金币向下取整,且必须与钱包实际发给收礼对象的金币完全一致,否则 V3 会拒绝开奖;V2 不使用该比例开奖。",
|
||||
},
|
||||
settlement_window_wager: {
|
||||
summary: "V3 按实际消费金币累计一轮返还观察窗口;某一抽跨过门槛时仍归旧窗口,下一抽才进入新窗口。",
|
||||
adjust: "调大后更少重开窗口;调小后会更频繁清空全局窗口样本。V2 会先按礼物参考金额换算成窗口抽数。",
|
||||
constraint: "必须大于 0。新窗口还没有消费样本时,不会触发返还偏低补偿大奖。",
|
||||
summary:
|
||||
"V3 按实际消费金币累计一轮大盘 RTP;某一抽跨过门槛时仍归旧轮,下一抽才进入新轮。大盘结算并重置时,也会按完全相同的起止时间结算每个用户的本轮 RTP。",
|
||||
adjust: "调大后大盘和用户本轮 RTP 都会更久才结算;调小后两者都会更频繁结算。V2 会先按礼物参考金额换算成窗口抽数。",
|
||||
constraint: "必须大于 0。新一轮还没有消费样本时,不会触发返还偏低大奖。",
|
||||
},
|
||||
gift_price_reference: {
|
||||
summary: "V2 用它把累计消费换算成“折算次数”,同时计算用户阶段和每轮窗口的抽数;它不是礼物真实售价。",
|
||||
@ -117,34 +118,42 @@ const FIELD_HELP = {
|
||||
jackpot_multipliers: {
|
||||
summary: "列出大奖可能采用的倍数,例如 200、500、1000。实际奖励按本抽消费金额乘以倍数计算。",
|
||||
adjust: "增加或调高倍数会放大奖励金额和资金压力;删除倍数会减少可选大奖。",
|
||||
constraint: "用逗号分隔,必须都大于 1 且从小到大;系统会在所有付得起的大奖倍数中等机会选择一档。",
|
||||
constraint:
|
||||
"用逗号分隔,必须都大于 1 且从小到大;系统会在所有付得起的大奖倍数中等机会选择一档。这里的倍率不能再作为普通奖档设置正概率,否则配置无法发布。",
|
||||
},
|
||||
jackpot_global_rtp_max_percent: {
|
||||
summary: "当前 App、奖池、规则版本在本轮窗口内的平均返还不高于这条线时,才满足补偿大奖的全局条件。",
|
||||
summary:
|
||||
"系统每次达到结算流水后,会结束并重置一轮大盘 RTP。刚结算的本轮大盘 RTP 不高于这条线时,才继续检查用户的两项返还条件。",
|
||||
adjust: "调高会让补偿大奖更容易进入候选;调低会要求全局返还更低才触发。",
|
||||
constraint:
|
||||
"必须大于 0% 且不超过 100%。全局、用户当日和近 72 小时三项都必须有消费样本并全部通过,才会直接选择可支付大奖。",
|
||||
"必须大于 0% 且不超过 100%。大盘 RTP 等于本项配置值时可以通过;还必须同时满足用户本轮 RTP 严格低于本轮触发线、用户近 48 小时 RTP 严格低于长期触发线,且奖池和各项限额足够。闭窗资格只在用户下一次送礼时尝试一次,奖池或限额不足也不会顺延。",
|
||||
},
|
||||
jackpot_user_day_rtp_max_percent: {
|
||||
summary: "用户当天的平均返还不高于这条线时,才允许尝试补偿大奖。",
|
||||
adjust: "调高会让更多用户满足条件;调低会把大奖更集中给当天返还明显偏低的用户。",
|
||||
constraint: "按当前奖池的 UTC 自然日统计;没有消费样本时不触发。必须大于 0 且不能超过全局触发线。",
|
||||
jackpot_user_round_rtp_max_percent: {
|
||||
summary:
|
||||
"系统每次重置大盘 RTP 时,会按完全相同的起止时间结算这个用户的本轮 RTP。例如 9 点重置一次、10 点再次重置,10 点结算时就检查用户在 9 点到 10 点这一轮的总返奖 ÷ 总消费。",
|
||||
adjust: "调高会让更多本轮返还偏低的用户通过;调低会更严格。用户本轮 RTP 必须严格小于配置值,刚好等于也不通过。",
|
||||
constraint:
|
||||
"只统计当前 App、当前奖池和同一结算轮次内的实际消费与返奖;本轮没有消费样本时不通过。它必须与近 48 小时条件同时通过,不能只满足其中一项。",
|
||||
},
|
||||
jackpot_user_72h_rtp_max_percent: {
|
||||
summary: "用户最近连续 72 小时的平均返还不高于这条线时,才允许尝试补偿大奖。",
|
||||
adjust: "调高会放宽长期条件;调低会要求用户近三天整体返还更低。",
|
||||
constraint: "按当前奖池滚动 72 小时统计,不是三个本地自然日;没有消费样本时不触发,且不能超过全局触发线。",
|
||||
jackpot_user_48h_rtp_max_percent: {
|
||||
summary:
|
||||
"判断这个用户近 48 小时是否整体返还偏低。本轮结算时,用户注册已满 48 小时,系统才会把结算时点向前 48 小时内的返奖金币加总,再除以同期实际消费金币;同一 App、奖池下跨房间、主播和设备合并统计,结果严格低于这条线才通过。",
|
||||
adjust: "调高会更容易通过,调低会更严格;结果等于配置值也不通过。例如近 48 小时消费 10,000、返奖 9,500,RTP 为 95%,配置 96% 时通过;返奖 9,600、RTP 为 96% 时不通过。",
|
||||
constraint:
|
||||
"先看注册时间:注册未满 48 小时直接不通过;注册已满 48 小时后,不要求连续玩满 48 小时,只统计窗口内真实发生的消费和返奖。即使前 47 小时都没玩、最近只玩 5 分钟,也用这 5 分钟的数据计算;整段时间没有消费时不通过。它还必须与大盘条件、用户本轮条件同时通过,并受每日大奖次数、奖池余额和所有返奖上限限制。",
|
||||
},
|
||||
max_jackpot_hits_per_user_day: {
|
||||
summary: "限制同一用户在当前奖池的一个 UTC 自然日内最多真正拿到多少次大奖。",
|
||||
adjust: "调高允许同一用户一天获得更多大奖;调低会更早停止该用户当天的大奖,不保证转给其他用户。",
|
||||
constraint: "必须大于 0;达到次数后仍可参与普通奖档,尚未使用的消费资格会保留。",
|
||||
constraint:
|
||||
"必须大于 0;达到次数后,即使大盘、本轮和近 48 小时 RTP 都通过也不再出大奖,但仍可参与普通奖档;下一个 UTC 自然日重新累计。",
|
||||
},
|
||||
jackpot_spend_threshold_coins: {
|
||||
summary: "用户在当前奖池的同一 UTC 日内,每累计消费满一份门槛,就保存一个供后续抽奖使用的大奖资格。",
|
||||
adjust: "按各 App 奖池确认的金币口径填写;调高会要求消费更多才获得资格,调低会更频繁地产生资格。",
|
||||
summary:
|
||||
"这是旧规则按用户日累计消费保存独立大奖资格时使用的历史字段。当前规则已停用这条路径,保留数值只为读取和回传旧版本配置。",
|
||||
adjust: "当前不可编辑;无论原值是多少,都不会增加用户出大奖的机会。",
|
||||
constraint:
|
||||
"启用前必须大于 0,系统不会根据币价或充值记录自行猜额度;一笔消费可产生多个资格,资格从下一抽开始用,未能支付时不会丢失。",
|
||||
"当前大奖必须经过大盘条件,并同时满足用户本轮 RTP 与近 48 小时 RTP 两项条件;这个历史字段不能替代或绕过任何一项。",
|
||||
},
|
||||
max_single_payout: {
|
||||
summary: "限制一抽最多能返多少金币;超过这个金额的奖档当次不会发出。",
|
||||
|
||||
@ -11,8 +11,21 @@ import { DEFAULT_POOL_ID } from "./api.js";
|
||||
|
||||
const DYNAMIC_STRATEGY = "dynamic_v3";
|
||||
const PPM_SCALE = 1_000_000;
|
||||
const LEGACY_JACKPOT_RTP_MODE = "__legacy_jackpot_rtp_fields";
|
||||
const legacyJackpotRTPAliases = {
|
||||
jackpot_user_48h_rtp_max_percent: [
|
||||
"jackpot_user_72h_rtp_max_percent",
|
||||
"jackpotUser72hRTPMaxPercent",
|
||||
"jackpotUser72hRtpMaxPercent",
|
||||
],
|
||||
jackpot_user_round_rtp_max_percent: [
|
||||
"jackpot_user_day_rtp_max_percent",
|
||||
"jackpotUserDayRTPMaxPercent",
|
||||
"jackpotUserDayRtpMaxPercent",
|
||||
],
|
||||
};
|
||||
|
||||
// 只有跨 App 通用的算法参数才有默认值;用户日累计消费触发门槛和六维金额上限必须由运营按 App 奖池的金币口径填写,
|
||||
// 只有跨 App 通用的算法参数才有默认值;六维金额上限必须由运营按 App 奖池的金币口径填写,
|
||||
// 因而默认保持 0 且规则停用,避免把某个 App 的预算误发到其他 App。
|
||||
const dynamicDefaults = {
|
||||
anchor_daily_payout_cap: 0,
|
||||
@ -26,8 +39,8 @@ const dynamicDefaults = {
|
||||
jackpot_global_rtp_max_percent: 98,
|
||||
jackpot_multipliers: [200, 500, 1000],
|
||||
jackpot_spend_threshold_coins: 0,
|
||||
jackpot_user_72h_rtp_max_percent: 96,
|
||||
jackpot_user_day_rtp_max_percent: 96,
|
||||
jackpot_user_48h_rtp_max_percent: 96,
|
||||
jackpot_user_round_rtp_max_percent: 96,
|
||||
loss_streak_guarantee: 5,
|
||||
low_water_nonzero_factor_percent: 70,
|
||||
low_watermark_coins: 10_000_000,
|
||||
@ -55,8 +68,8 @@ const numericFields = [
|
||||
"initial_pool_coins",
|
||||
"jackpot_global_rtp_max_percent",
|
||||
"jackpot_spend_threshold_coins",
|
||||
"jackpot_user_72h_rtp_max_percent",
|
||||
"jackpot_user_day_rtp_max_percent",
|
||||
"jackpot_user_48h_rtp_max_percent",
|
||||
"jackpot_user_round_rtp_max_percent",
|
||||
"loss_streak_guarantee",
|
||||
"low_water_nonzero_factor_percent",
|
||||
"low_watermark_coins",
|
||||
@ -109,6 +122,12 @@ export function configToForm(config = {}) {
|
||||
stages: normalizeFormStages(config.stages, targetRTPPercent, strategyVersion),
|
||||
strategy_version: strategyVersion,
|
||||
};
|
||||
// 只在明确收到旧 day/72h 且缺少对应 canonical 字段时进入兼容模式。页面始终编辑 canonical 值,
|
||||
// 这个标记仅让纯函数保留旧对象形状;HTTP 层仍会归一成 round/48h 后再发送。
|
||||
form[LEGACY_JACKPOT_RTP_MODE] = Object.entries(legacyJackpotRTPAliases).some(
|
||||
([canonical, aliases]) =>
|
||||
!hasConfigValue(config, [canonical, snakeToCamel(canonical)]) && hasConfigValue(config, aliases),
|
||||
);
|
||||
for (const field of numericFields) {
|
||||
if (field === "target_rtp_percent") {
|
||||
form[field] = targetRTPPercent;
|
||||
@ -119,7 +138,14 @@ export function configToForm(config = {}) {
|
||||
form[field] = "0";
|
||||
continue;
|
||||
}
|
||||
form[field] = formConfigNumber(config, field, snakeToCamel(field), defaultNumber(field, strategyVersion));
|
||||
const legacyAliases = legacyJackpotRTPAliases[field] || [];
|
||||
form[field] = hasConfigValue(config, [field, snakeToCamel(field)])
|
||||
? formConfigNumber(config, field, snakeToCamel(field), defaultNumber(field, strategyVersion))
|
||||
: formNumber(firstConfigValue(config, legacyAliases) ?? defaultNumber(field, strategyVersion));
|
||||
}
|
||||
if (form[LEGACY_JACKPOT_RTP_MODE]) {
|
||||
form.jackpot_user_72h_rtp_max_percent = form.jackpot_user_48h_rtp_max_percent;
|
||||
form.jackpot_user_day_rtp_max_percent = form.jackpot_user_round_rtp_max_percent;
|
||||
}
|
||||
return form;
|
||||
}
|
||||
@ -156,6 +182,17 @@ export function formToConfig(config, form) {
|
||||
? 0
|
||||
: numberFromForm(form[field]);
|
||||
}
|
||||
if (form[LEGACY_JACKPOT_RTP_MODE]) {
|
||||
// 旧输入的纯函数 round-trip 保持原 shape,避免调用方只做本地比较时出现伪 diff;真正保存时
|
||||
// luckyGiftConfigPayload 会把这两个别名归一成 canonical HTTP 字段,绝不会双发两套字段。
|
||||
output.jackpot_user_72h_rtp_max_percent = output.jackpot_user_48h_rtp_max_percent;
|
||||
output.jackpot_user_day_rtp_max_percent = output.jackpot_user_round_rtp_max_percent;
|
||||
delete output.jackpot_user_48h_rtp_max_percent;
|
||||
delete output.jackpot_user_round_rtp_max_percent;
|
||||
} else {
|
||||
delete output.jackpot_user_72h_rtp_max_percent;
|
||||
delete output.jackpot_user_day_rtp_max_percent;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
@ -307,23 +344,24 @@ export function validateLuckyGiftForm(form) {
|
||||
if (number("jackpot_global_rtp_max_percent") <= 0 || number("jackpot_global_rtp_max_percent") > 100)
|
||||
errors.push("全局大奖 RTP 上限必须在 0%-100% 之间");
|
||||
if (
|
||||
number("jackpot_user_day_rtp_max_percent") <= 0 ||
|
||||
number("jackpot_user_day_rtp_max_percent") > number("jackpot_global_rtp_max_percent")
|
||||
number("jackpot_user_round_rtp_max_percent") <= 0 ||
|
||||
number("jackpot_user_round_rtp_max_percent") > number("jackpot_global_rtp_max_percent")
|
||||
)
|
||||
errors.push("用户每日 RTP 上限必须大于 0 且不超过全局上限");
|
||||
errors.push("用户本轮 RTP 触发线必须大于 0 且不超过全局上限");
|
||||
if (
|
||||
number("jackpot_user_72h_rtp_max_percent") <= 0 ||
|
||||
number("jackpot_user_72h_rtp_max_percent") > number("jackpot_global_rtp_max_percent")
|
||||
number("jackpot_user_48h_rtp_max_percent") <= 0 ||
|
||||
number("jackpot_user_48h_rtp_max_percent") > number("jackpot_global_rtp_max_percent")
|
||||
)
|
||||
errors.push("用户 72 小时 RTP 上限必须大于 0 且不超过全局上限");
|
||||
errors.push("用户 48 小时 RTP 触发线必须大于 0 且不超过全局上限");
|
||||
if (number("max_jackpot_hits_per_user_day") <= 0) errors.push("用户每日大奖次数必须大于 0");
|
||||
if (number("jackpot_spend_threshold_coins") < 0) errors.push("大奖消费门槛不能小于 0");
|
||||
if (form[LEGACY_JACKPOT_RTP_MODE] && form.enabled && number("jackpot_spend_threshold_coins") <= 0)
|
||||
errors.push("启用前必须填写用户日累计消费触发门槛(金币)");
|
||||
for (const [field, label] of payoutCapFields) {
|
||||
if (number(field) < 0) errors.push(`${label}不能小于 0`);
|
||||
}
|
||||
validateRechargeStages(form.stages || [], errors, form.enabled);
|
||||
if (form.enabled) {
|
||||
if (number("jackpot_spend_threshold_coins") <= 0) errors.push("启用前必须填写用户日累计消费触发门槛(金币)");
|
||||
for (const [field, label] of payoutCapFields) {
|
||||
if (number(field) <= 0) errors.push(`启用前必须填写${label}`);
|
||||
}
|
||||
@ -452,6 +490,17 @@ function formConfigNumber(config, snake, camel, fallback) {
|
||||
return formNumber(config[snake] ?? config[camel] ?? fallback);
|
||||
}
|
||||
|
||||
function firstConfigValue(config, keys) {
|
||||
for (const key of keys) {
|
||||
if (config[key] !== undefined && config[key] !== null) return config[key];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function hasConfigValue(config, keys) {
|
||||
return firstConfigValue(config, keys) !== undefined;
|
||||
}
|
||||
|
||||
function snakeToCamel(value) {
|
||||
return value.replace(/_([a-z0-9])/g, (_, letter) => letter.toUpperCase());
|
||||
}
|
||||
|
||||
@ -445,6 +445,35 @@ body {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.ops-jackpot-flow {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 1px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-control);
|
||||
background: var(--border);
|
||||
}
|
||||
|
||||
.ops-jackpot-flow > div {
|
||||
display: grid;
|
||||
align-content: start;
|
||||
gap: 4px;
|
||||
background: var(--bg-card-strong, #f8fafc);
|
||||
padding: var(--space-2) var(--space-3);
|
||||
}
|
||||
|
||||
.ops-jackpot-flow strong {
|
||||
color: var(--text-primary);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ops-jackpot-flow span {
|
||||
color: var(--text-secondary);
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.ops-field-label {
|
||||
display: inline-flex;
|
||||
min-width: 0;
|
||||
@ -896,6 +925,10 @@ body {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.ops-jackpot-flow {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.ops-stage-tabs {
|
||||
display: flex;
|
||||
max-width: 100vw;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user