模块

卡牌/display:修订间差异

来自卡厄思梦境WIKI

律Rhyme留言 | 贡献
创建页面,内容为“local p = {} local function escFile(s) s = tostring(s or '') s = mw.text.trim(s) s = s:gsub('[%[%]%{%}%|]', '') return s end local function escText(s) return mw.text.encode(tostring(s or '')) end local function expandWikitext(s) if s == nil or s == '' then return '' end local ok, frame = pcall(mw.getCurrentFrame) if not ok or not frame then return tostring(s) end return frame:preprocess(tostring(s))…”
 
律Rhyme留言 | 贡献
无编辑摘要
标签已被回退
第12行: 第12行:
end
end


-- 确保模板与解析函数在内容中被展开
local function expandWikitext(s)
local function expandWikitext(s)
     if s == nil or s == '' then
     if s == nil or s == '' then
第23行: 第24行:
end
end


-- 稀有度统一
local function normalizeRarity(r)
local function normalizeRarity(r)
     local s = tostring(r or ''):gsub('%s+', '')
     local s = tostring(r or ''):gsub('%s+', '')
第28行: 第30行:
     if s == '白' then return '白' end
     if s == '白' then return '白' end
     if s == '蓝' then return '蓝' end
     if s == '蓝' then return '蓝' end
     if s == '橙' then return '橙' end
     if s == '橙' or s == '橙色' then return '橙' end
     if s == '彩' then return '彩' end
     if s == '彩' or s == '彩虹' then return '彩' end
     return nil
     return nil
end
end


-- 稀有度对应的标题背景条颜色
local function rarityBarColor(r)
local function rarityBarColor(r)
     local key = normalizeRarity(r) or '蓝'
     local key = normalizeRarity(r) or '蓝'
     local map = {
     local map = {
         ['白'] = 'rgba(239, 237, 237, 0.5)',
         ['白'] = 'rgba(239, 237, 237, 0.6)',
         ['蓝'] = 'rgba(119, 236, 254, 0.5)',
         ['蓝'] = 'rgba(119, 236, 254, 0.6)',
         ['橙'] = 'rgba(255, 200, 110, 0.5)',
         ['橙'] = 'rgba(255, 200, 110, 0.6)',
         ['彩'] = 'rgba(180, 125, 242, 0.5)',
         ['彩'] = 'rgba(180, 125, 242, 0.6)',
     }
     }
     return map[key] or map['蓝']
     return map[key] or map['蓝']
end
end


-- 稀有度对应的卡牌名称颜色
local function rarityNameColor(r)
local function rarityNameColor(r)
     local key = normalizeRarity(r) or '蓝'
     local key = normalizeRarity(r) or '蓝'
     local map = {
     local map = {
         ['白'] = '#cccccc',
         ['白'] = '#cccccc',
         ['蓝'] = '#75ebff',
         ['蓝'] = '#73ecfe',
         ['橙'] = '#ff5908',
         ['橙'] = '#ffc86e',
         ['彩'] = '#d07de6',
         ['彩'] = '#a37df7',
     }
     }
     return map[key] or map['蓝']
     return map[key] or map['蓝']
end
end


local function generateUniqueId(cardInfo)
-- 根据外框宽度返回标题背景条几何尺寸
    local timestamp = os.time()
local function getBarGeom(width)
    local random = math.random(1000, 9999)
     width = tonumber(width) or 160
     local base = (cardInfo.moduleName or '') .. '-' .. (cardInfo.cardName or '') .. (cardInfo.variantSuffix or '')
     if width <= 160 then
    local safeName = mw.uri.anchorEncode(base):gsub("%%", "-")
         return { top = 22, left = 5, w = 150, h = 8 }
    return "card-" .. safeName .. "-" .. timestamp .. "-" .. random
     elseif width >= 320 then
end
         return { top = 44, left = 5, w = 305, h = 16 }
 
local function apTextShadow(style)
     if style == 'red' then
         return 'text-shadow:0 0 10px #7a0e0e,0 0 20px #7a0e0e,0 0 30px #ff3030,0 0 40px #ff3030,0 0 50px #ff3030,0 0 60px #ff3030,0 0 70px #ff3030;'
     elseif style == 'green' then
         return 'text-shadow:0 0 10px #0e6f36,0 0 20px #0e6f36,0 0 30px #29ff85,0 0 40px #29ff85,0 0 50px #29ff85,0 0 60px #29ff85,0 0 70px #29ff85;'
    elseif style == 'blue' then
        return 'text-shadow:0 0 10px #132cbf,0 0 20px #132cbf,0 0 30px #4169ff,0 0 40px #4169ff,0 0 50px #4169ff,0 0 60px #4169ff,0 0 70px #4169ff;'
     else
     else
         return ''
         return { top = 33, left = 5, w = 230, h = 12 }
     end
     end
end
end


local function renderApDiv(content, top, left, fontSize, style)
-- 渲染标题背景条层级,art 之上,其余元素之下
    content = tostring(content or '')
local function renderRarityBar(info, width)
     local shadow = apTextShadow(style)
     local g = getBarGeom(width)
     local color = (style == 'gray') and '#cfcfcf' or 'white'
     local color = rarityBarColor(info.rarity)
     return string.format(
     return string.format(
         '<div style="position:absolute;z-index:10;top:%s;left:%s;font-family:number;font-size:%s;color:%s;%s">%s</div>',
         '<div style="position:absolute;z-index:1;top:%dpx;left:%dpx;width:%dpx;height:%dpx;background-color:%s"></div>',
         top, left, fontSize, color, shadow, content
         g.top, g.left, g.w, g.h, color
     )
     )
end
end


-- 仅渲染立绘层(最低层)
local function renderArtLayer(info, width)
    return '<div style="position: absolute; top: 0; left: 0; z-index:0;">[[File:' .. escFile(info.art) .. '|' .. width .. 'px|link=]]</div>'
end
-- 渲染覆盖层(横条之上)
local function renderOverlayLayers(info, width)
    local t = {}
    table.insert(t, '<div style="position: absolute; top: 0; left: 0; z-index:2;">[[File:card_黑色蒙版.png|' .. width .. 'px|link=]]</div>')
    table.insert(t, '<div style="position: absolute; top: 0; left: 0; z-index:3;">[[File:card_ego_' .. escFile(info.ego) .. '.png|' .. width .. 'px|link=]]</div>')
    table.insert(t, '<div style="position: absolute; top: 0; left: 0; z-index:4;">[[File:card_rarity_' .. escFile(info.rarity) .. '.png|' .. width .. 'px|link=]]</div>')
    table.insert(t, '<div style="position: absolute; top: 0; left: 0; z-index:5;">[[File:card_顶层蒙版.png|' .. width .. 'px|link=]]</div>')
    return table.concat(t, '')
end
-- 将 tokens 渲染为可调用模板的短标识
local function dictSpanFromTokens(tokens, color)
local function dictSpanFromTokens(tokens, color)
     if type(tokens) ~= 'table' or #tokens == 0 then
     if type(tokens) ~= 'table' or #tokens == 0 then
第107行: 第119行:
end
end


local function generateUniqueId(cardInfo)
    local timestamp = os.time()
    local random = math.random(1000, 9999)
    local base = (cardInfo.moduleName or '') .. '-' .. (cardInfo.cardName or '') .. (cardInfo.variantSuffix or '')
    local safeName = mw.uri.anchorEncode(base):gsub("%%", "-")
    return "card-" .. safeName .. "-" .. timestamp .. "-" .. random
end
-- AP 发光样式
local function apTextShadow(style)
    if style == 'red' then
        return 'text-shadow:0 0 10px #7a0e0e,0 0 20px #7a0e0e,0 0 30px #ff3030,0 0 40px #ff3030,0 0 50px #ff3030,0 0 60px #ff3030,0 0 70px #ff3030;'
    elseif style == 'green' then
        return 'text-shadow:0 0 10px #0e6f36,0 0 20px #0e6f36,0 0 30px #29ff85,0 0 40px #29ff85,0 0 50px #29ff85,0 0 60px #29ff85,0 0 70px #29ff85;'
    elseif style == 'blue' then
        return 'text-shadow:0 0 10px #132cbf,0 0 20px #132cbf,0 0 30px #4169ff,0 0 40px #4169ff,0 0 50px #4169ff,0 0 60px #4169ff,0 0 70px #4169ff;'
    else
        return '' -- gray: no glow
    end
end
local function renderApDiv(content, top, left, fontSize, style)
    content = tostring(content or '')
    local shadow = apTextShadow(style)
    local color = (style == 'gray') and '#cfcfcf' or 'white'
    return string.format(
        '<div style="position:absolute;z-index:10;top:%s;left:%s;font-family:number;font-size:%s;color:%s;%s">%s</div>',
        top, left, fontSize, color, shadow, content
    )
end
-- 单个机制卡片(固定 250px 宽度)
local function renderMechanismCard(title, desc)
local function renderMechanismCard(title, desc)
     title = escText(title or '')
     title = escText(title or '')
第113行: 第157行:
         d = '暂无详细说明'
         d = '暂无详细说明'
     end
     end
    -- 展开词典说明中的模板
     local body = expandWikitext(d)
     local body = expandWikitext(d)


     local dhtml = {}
     local dhtml = {}
     table.insert(dhtml, '<div class="mechanism-card" style="width: 250px;">')
     table.insert(dhtml, '<div class="mechanism-card" style="width: 250px;">')
     table.insert(dhtml, '<div style="width: 250px; height: 2px; background-color: #f2ba02;"></div>')
     table.insert(dhtml, '<div style="width: 266px; height: 2px; background-color: #f2ba02;"></div>')
     table.insert(dhtml, '<div style="width: 100%; background-color: #343434; color: white; padding: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.3);  line-height: 1.6;">')
     table.insert(dhtml, '<div style="width: 100%; background-color: #343434; color: white; padding: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.3);  line-height: 1.6;">')
     table.insert(dhtml, '<div style="font-weight: bold;">' .. title .. '</div>')
     table.insert(dhtml, '<div style="font-weight: bold;">' .. title .. '</div>')
第126行: 第171行:
end
end


-- 右侧词典说明容器
local function renderDictMechanisms(dictEntries)
local function renderDictMechanisms(dictEntries)
     if type(dictEntries) ~= 'table' or #dictEntries == 0 then return '' end
     if type(dictEntries) ~= 'table' or #dictEntries == 0 then return '' end


     local html = {}
     local html = {}
     table.insert(html, '<div class="dict-mechanisms" style="display:flex;flex-direction:column;align-items:flex-start;gap-right:0px;gap-left:15px;margin-left:10px;width:250px;flex:0 0 250px;overflow:visible;">')
    -- 固定宽度 250px
     table.insert(html, '<div class="dict-mechanisms" style="display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin-left:10px;width:250px;flex:0 0 250px;overflow:visible;">')
     for _, entry in ipairs(dictEntries) do
     for _, entry in ipairs(dictEntries) do
         table.insert(html, renderMechanismCard(entry.key, entry.desc))
         table.insert(html, renderMechanismCard(entry.key, entry.desc))
第138行: 第185行:
end
end


-- 渲染普通卡牌的立绘和覆盖层
function p.render(cardInfo, subCardInfo)
local function renderNormalCardLayers(info, width)
    local dictDisplay = dictSpanFromTokens(cardInfo.dictTokens, cardInfo.dictColor)
    local cardId = generateUniqueId(cardInfo)
     local html = {}
     local html = {}
    local barColor = rarityBarColor(info.rarity)
      
      
     -- 立绘层
     -- 渲染小卡片
     table.insert(html, '<div style="position:absolute;top:2px;left:15px;z-index:0;">[[File:' .. escFile(info.art) .. '|164px|link=]]</div>')
     table.insert(html, p.renderSmallCard(cardInfo, cardId, dictDisplay))
   
     -- 渲染模态框(单独输出)
     -- 黑色蒙版
     table.insert(html, p.renderModal(cardInfo, cardId, dictDisplay, subCardInfo))
    table.insert(html, '<div style="position:absolute;top:0px;left:3px;z-index:1;">[[File:card_黑色蒙版.png|179px|link=]]</div>')
   
    -- 标题背景条
     table.insert(html, '<div style="position:absolute;top:33px;left:15px;width:163px;height:10px;background:' .. barColor .. ';z-index:2;"></div>')
   
    -- EGO框架
    table.insert(html, '<div style="position:absolute;top:0px;left:2px;z-index:3;">[[File:card_ego_' .. escFile(info.ego) .. '.png|179px|link=]]</div>')
   
    -- 稀有度标识
    table.insert(html, '<div style="position:absolute;top:25px;left:1px;z-index:4;">[[File:card_rarity_' .. escFile(info.rarity) .. '.png|21px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:27px;right:0px;z-index:4;">[[File:card_rarity_' .. escFile(info.rarity) .. '_sub.png|10px|link=]]</div>')
   
    -- 能量线
    table.insert(html, '<div style="position:absolute;top:50px;left:20px;z-index:5;">[[File:energy_line_蓝.png|25px|link=]]</div>')
      
      
     return table.concat(html, '')
     return table.concat(html, '')
end
end


-- 渲染状态异常卡牌的立绘和覆盖层(小)
function p.renderSmallCard(cardInfo, cardId, dictDisplay)
local function renderAbnormalCardLayersSmall(info)
     local html = {}
     local html = {}
     table.insert(html, '<div style="position:absolute;top:5px;left:5px;z-index:0;">[[File:' .. escFile(info.art) .. '|165px|link=]]</div>')
     local apDisplay = cardInfo.apText or ''
    table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:1;">[[File:card_状态异常_黑色蒙版.png|179px|link=]]</div>')
     local nameColor = rarityNameColor(cardInfo.rarity)
    table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:2;">[[File:card_ego_状态异常.png|179px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:50px;left:20px;z-index:5;">[[File:energy_line_蓝.png|25px|link=]]</div>')
    return table.concat(html, '')
end
 
-- 渲染状态异常卡牌的立绘和覆盖层(中)
local function renderAbnormalCardLayersMedium(info)
     local html = {}
    table.insert(html, '<div style="position:absolute;top:8px;left:8px;z-index:0;">[[File:' .. escFile(info.art) .. '|248px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:1px;left:3px;z-index:1;">[[File:card_状态异常_黑色蒙版.png|269px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:2;">[[File:card_ego_状态异常.png|269px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:80px;left:30px;z-index:5;">[[File:energy_line_蓝.png|38px|link=]]</div>')
    return table.concat(html, '')
end


-- 渲染状态异常卡牌的立绘和覆盖层(大)
     table.insert(html, '<div class="card-small-wrapper" data-card-id="' .. escText(cardId) .. '" style="display:inline-block;vertical-align:top;position:relative;width:160px;height:230px;overflow:hidden;cursor:pointer;">')
local function renderAbnormalCardLayersLarge(info)
    local html = {}
     table.insert(html, '<div style="position:absolute;top:10px;left:10px;z-index:0;">[[File:' .. escFile(info.art) .. '|330px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:1;">[[File:card_状态异常_黑色蒙版.png|358px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:2;">[[File:card_ego_状态异常.png|358px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:110px;left:40px;z-index:5;">[[File:energy_line_蓝.png|50px|link=]]</div>')
    return table.concat(html, '')
end


-- 渲染自我意识技能卡牌的立绘和覆盖层(小)
     table.insert(html, renderArtLayer(cardInfo, 160))
local function renderSkillCardLayersSmall(info)
     table.insert(html, renderRarityBar(cardInfo, 160))
    local html = {}
     table.insert(html, renderOverlayLayers(cardInfo, 160))
     table.insert(html, '<div style="position:absolute;top:0px;left:3px;z-index:0;">[[File:' .. escFile(info.art) .. '|164px|link=]]</div>')
     table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:1;">[[File:card_skill_黑色蒙版.png|169px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:2;">[[File:card_skill_ego_' .. escFile(info.ego) .. '.png|169px|link=]]</div>')
     table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:3;">[[File:card_skill_line.png|169px|link=]]</div>')
    return table.concat(html, '')
end


-- 渲染自我意识技能卡牌的立绘和覆盖层(中)
     table.insert(html, renderApDiv(apDisplay, '5px', '25px', '36px', cardInfo.apStyle or 'blue'))
local function renderSkillCardLayersMedium(info)
     table.insert(html, renderApDiv('', '23px', '23px', '32px', cardInfo.apStyle or 'blue'))
    local html = {}
     table.insert(html, '<div style="position:absolute;top:0px;left:5px;z-index:0;">[[File:' .. escFile(info.art) .. '|246px|link=]]</div>')
     table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:1;">[[File:card_skill_黑色蒙版.png|254px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:2;">[[File:card_skill_ego_' .. escFile(info.ego) .. '.png|254px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:3;">[[File:card_skill_line.png|254px|link=]]</div>')
    return table.concat(html, '')
end


-- 渲染自我意识技能卡牌的立绘和覆盖层(大)
     table.insert(html, '<div style="position:absolute;z-index:10;top:12px;left:50px;color:' .. nameColor .. ';font-size:18px">' .. escText(cardInfo.displayTitleShort or cardInfo.displayTitle or cardInfo.cardName) .. '</div>')
local function renderSkillCardLayersLarge(info)
    local html = {}
     table.insert(html, '<div style="position:absolute;top:0px;left:6px;z-index:0;">[[File:' .. escFile(info.art) .. '|328px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:2px;left:0px;z-index:1;">[[File:card_skill_黑色蒙版.png|338px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:2;">[[File:card_skill_ego_' .. escFile(info.ego) .. '.png|338px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:3;">[[File:card_skill_line.png|338px|link=]]</div>')
    return table.concat(html, '')
end


function p.render(cardInfo, subCardInfo)
    table.insert(html, '<div style="position:absolute;z-index:10;top:33px;left:49px;">[[File:card_type_' .. escFile(cardInfo.cardType) .. '.png|18px|link=]]</div>')
    local dictDisplay = dictSpanFromTokens(cardInfo.dictTokens, cardInfo.dictColor)
     table.insert(html, '<div style="position:absolute;z-index:10;top:32px;left:67px;font-size:14px;color:white">' .. escText(cardInfo.cardType) .. '</div>')
    local cardId = generateUniqueId(cardInfo)
    local html = {}
    table.insert(html, p.renderSmallCard(cardInfo, cardId, dictDisplay))
     table.insert(html, p.renderLargeCard(cardInfo, cardId, dictDisplay, subCardInfo))
    return table.concat(html, '')
end


function p.renderSmallCard(cardInfo, cardId, dictDisplay)
     table.insert(html, '<div style="position:absolute;z-index:10;top:110px;left:20px;width:130px;height:115px;color:white;text-align:center;font-size:13px;line-height:15px;">')
    local html = {}
    local smallContent = expandWikitext((dictDisplay or '') .. (cardInfo.desc or ''))
    local apDisplay = cardInfo.apText or ''
    table.insert(html, '<div class="scroll-text"><div class="scroll-text-content">' .. smallContent .. '</div></div>')
    local nameColor = rarityNameColor(cardInfo.rarity)
    table.insert(html, '</div>')
    local isAbnormal = (cardInfo.cardType == "状态异常")
     table.insert(html, '</div>')
    local isSkill = (cardInfo.group == "自我意识技能")
   
     if isSkill then
        -- 自我意识技能小卡牌
        table.insert(html, '<div class="card-small-wrapper" data-card-id="' .. escText(cardId) .. '" style="display:inline-block;vertical-align:top;position:relative;width:169px;height:260px;overflow:hidden;cursor:pointer;">')
        table.insert(html, renderSkillCardLayersSmall(cardInfo))
       
        -- 标题
        table.insert(html, '<div style="position:absolute;top:90px;left:24px;z-index:10;font-size:16px;color:white">' .. escText(cardInfo.displayTitle or cardInfo.cardName) .. '</div>')
       
        -- 类型图标和文字
        table.insert(html, '<div style="position:absolute;top:110px;left:22px;z-index:10;">[[File:icon_tp_skill_type_awaken.png|20px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;top:111px;left:42px;z-index:10;font-size:13px;color:white">自我意识技能</div>')
       
        -- 分隔线
        table.insert(html, '<div style="position:absolute;top:132px;left:22px;width:141px;height:1px;background-color:rgba(255,255,255);z-index:10;"></div>')
       
        -- AP显示
        local apNum = tonumber(apDisplay) or 0
        table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:10;">[[File:card_skill_ap_' .. apNum .. '.png|169px|link=]]</div>')
       
        -- 描述
        table.insert(html, '<div style="position:absolute;top:137px;left:22px;width:140px;height:105px;color:white;text-align:left;font-size:13px;line-height:15px;z-index:10;">')
        local smallContent = expandWikitext((dictDisplay or '') .. (cardInfo.desc or ''))
        table.insert(html, '<div><div>' .. smallContent .. '</div></div>')
        table.insert(html, '</div>')
       
    elseif isAbnormal then
        -- 状态异常小卡牌
        table.insert(html, '<div class="card-small-wrapper" data-card-id="' .. escText(cardId) .. '" style="display:inline-block;vertical-align:top;position:relative;width:179px;height:265px;overflow:hidden;cursor:pointer;">')
        table.insert(html, renderAbnormalCardLayersSmall(cardInfo))
       
        table.insert(html, renderApDiv(apDisplay, '15px', '25px', '38px', cardInfo.apStyle or 'blue'))
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:20px;left:50px;width:115px;font-size:22px;color:' .. nameColor .. '">' .. escText(cardInfo.displayTitleShort or cardInfo.displayTitle or cardInfo.cardName) .. '</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:44px;left:48px;">[[File:card_type_' .. escFile(cardInfo.cardType) .. '.png|16px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:48px;left:66px;font-size:12px;color:white">状态异常</div>')
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:140px;left:12px;width:155px;height:110px;color:white;text-align:center;font-size:13px;line-height:15px; display: flex; align-items: center; justify-content: center;">')
        local smallContent = expandWikitext((dictDisplay or '') .. (cardInfo.desc or ''))
        table.insert(html, '<div class="scroll-text"><div class="scroll-text-content">' .. smallContent .. '</div></div>')
        table.insert(html, '</div>')
       
     else
        -- 普通小卡牌
        table.insert(html, '<div class="card-small-wrapper" data-card-id="' .. escText(cardId) .. '" style="display:inline-block;vertical-align:top;position:relative;width:183px;height:257px;overflow:hidden;cursor:pointer;">')
        table.insert(html, renderNormalCardLayers(cardInfo, 183))
       
        table.insert(html, renderApDiv(apDisplay, '15px', '25px', '38px', cardInfo.apStyle or 'blue'))
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:20px;left:50px;width:115px;font-size:22px;color:' .. nameColor .. '">' .. escText(cardInfo.displayTitleShort or cardInfo.displayTitle or cardInfo.cardName) .. '</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:44px;left:48px;">[[File:card_type_' .. escFile(cardInfo.cardType) .. '.png|16px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:48px;left:66px;font-size:12px;color:white">' .. escText(cardInfo.cardType) .. '</div>')
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:140px;left:20px;width:155px;height:110px;color:white;text-align:center;font-size:13px;line-height:15px; display: flex; align-items: center; justify-content: center;">')
        local smallContent = expandWikitext((dictDisplay or '') .. (cardInfo.desc or ''))
        table.insert(html, '<div class="scroll-text"><div class="scroll-text-content">' .. smallContent .. '</div></div>')
        table.insert(html, '</div>')
    end
      
      
    table.insert(html, '</div>')
     return table.concat(html, '')
     return table.concat(html, '')
end
end


function p.renderLargeCard(cardInfo, cardId, dictDisplay, subCardInfos)
-- 新增:独立的模态框渲染函数
function p.renderModal(cardInfo, cardId, dictDisplay, subCardInfos)
     local html = {}
     local html = {}
     local apDisplay = cardInfo.apText or ''
     local apDisplay = cardInfo.apText or ''
     local nameColor = rarityNameColor(cardInfo.rarity)
     local nameColor = rarityNameColor(cardInfo.rarity)
    local isAbnormal = (cardInfo.cardType == "状态异常")
    local isSkill = (cardInfo.group == "自我意识技能")


     table.insert(html, '<div id="' .. escText(cardId) .. '-modal" class="card-modal" style="display:none;position:fixed;z-index:9999;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.8);">')
     table.insert(html, '<div id="' .. escText(cardId) .. '-modal" class="card-modal" style="display:none;position:fixed;z-index:9999;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.8);">')
第316行: 第238行:


     table.insert(html, '<div class="card-modal-inner" style="height:100vh;display:flex;align-items:center;justify-content:center;">')
     table.insert(html, '<div class="card-modal-inner" style="height:100vh;display:flex;align-items:center;justify-content:center;">')
     table.insert(html, '<div class="original-card-view" style="display:flex;align-items:flex-start;justify-content:center;gap-right:0px;gap-left:15px;flex-wrap:wrap;">')
     table.insert(html, '<div class="original-card-view" style="display:flex;align-items:flex-start;justify-content:center;gap:10px;flex-wrap:wrap;">')


     -- 左侧:衍生卡牌
     -- 左侧:衍生卡牌
     if subCardInfos and #subCardInfos > 0 then
     if subCardInfos and #subCardInfos > 0 then
         table.insert(html, '<div class="ocv-col-left" style="display:flex;flex-direction:column;align-items:center;margin-right:30px; max-width:240px;">')
         table.insert(html, '<div class="ocv-col-left" style="display:flex;flex-direction:column;align-items:center;gap:10px;max-width:240px;">')
         table.insert(html, p.renderSubCard(subCardInfos[1]))
         table.insert(html, p.renderSubCard(subCardInfos[1]))
         if #subCardInfos > 1 then
         if #subCardInfos > 1 then
第328行: 第250行:
     end
     end


     -- 中间:放大卡片
     -- 中间:放大卡片
     if isSkill then
     table.insert(html, '<div class="ocv-col-center" style="display:flex;flex-direction:column;align-items:center;gap:10px;max-width:320px;">')
        -- 自我意识技能大卡牌
    table.insert(html, '<div style="display:inline-block;vertical-align:top;position:relative;width:320px;height:460px;overflow:hidden;">')
        table.insert(html, '<div class="ocv-col-center" style="display:flex;flex-direction:column;align-items:center;gap-right:0px;gap-left:15px;max-width:338px;">')
    table.insert(html, renderArtLayer(cardInfo, 320))
        table.insert(html, '<div style="display:inline-block;vertical-align:top;position:relative;width:338px;height:510px;overflow:hidden;">')
    table.insert(html, renderRarityBar(cardInfo, 320))
        table.insert(html, renderSkillCardLayersLarge(cardInfo))
    table.insert(html, renderOverlayLayers(cardInfo, 320))
       
 
        table.insert(html, '<div style="position:absolute;top:180px;left:48px;z-index:10;font-size:32px;color:white">' .. escText(cardInfo.displayTitle or cardInfo.cardName) .. '</div>')
     table.insert(html, renderApDiv(apDisplay, '18px', '45px', '58px', cardInfo.apStyle or 'blue'))
        table.insert(html, '<div style="position:absolute;top:223px;left:44px;z-index:10;">[[File:icon_tp_skill_type_awaken.png|40px|link=]]</div>')
     table.insert(html, renderApDiv('__', '48px', '40px', '32px', cardInfo.apStyle or 'blue'))
        table.insert(html, '<div style="position:absolute;top:222px;left:84px;z-index:10;font-size:26px;color:white">自我意识技能</div>')
 
        table.insert(html, '<div style="position:absolute;top:264px;left:44px;width:282px;height:2px;background-color:rgba(255,255,255);z-index:10;"></div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:28px;left:80px;color:' .. nameColor .. ';font-size:32px">' .. escText(cardInfo.displayTitleShort or cardInfo.displayTitle or cardInfo.cardName) .. '</div>')
       
 
        local apNum = tonumber(apDisplay) or 0
    table.insert(html, '<div style="position:absolute;z-index:10;top:68px;left:79px;">[[File:card_type_' .. escFile(cardInfo.cardType) .. '.png|24px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:10;">[[File:card_skill_ap_' .. apNum .. '.png|338px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:65px;left:105px;font-size:20px;color:white">' .. escText(cardInfo.cardType) .. '</div>')
       
    table.insert(html, '<div style="position:absolute;z-index:10;top:250px;left:30px;width:300px;height:210px;color:white;text-align:center;font-size:28px;line-height:30px;">')
        table.insert(html, '<div style="position:absolute;top:270px;left:43px;width:285px;height:220px;color:white;text-align:left;font-size:26px;line-height:30px;z-index:10;">')
    local largeContent = expandWikitext((dictDisplay or '') .. (cardInfo.desc or ''))
        local largeContent = expandWikitext((dictDisplay or '') .. (cardInfo.desc or ''))
    table.insert(html, '<div class="scroll-text" style="width:280px;height:200px"><div class="scroll-text-content">' .. largeContent .. '</div></div>')
        table.insert(html, '<div><div>' .. largeContent .. '</div></div>')
    table.insert(html, '</div>')
        table.insert(html, '</div>')
    table.insert(html, '</div>')
        table.insert(html, '</div>')
       
     elseif isAbnormal then
        -- 状态异常大卡牌
        table.insert(html, '<div class="ocv-col-center" style="display:flex;flex-direction:column;align-items:center;gap-right:0px;gap-left:15px;max-width:358px;">')
        table.insert(html, '<div style="display:inline-block;vertical-align:top;position:relative;width:358px;height:524px;overflow:hidden;">')
        table.insert(html, renderAbnormalCardLayersLarge(cardInfo))
       
        table.insert(html, renderApDiv(apDisplay, '30px', '50px', '76px', cardInfo.apStyle or 'blue'))
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:40px;left:100px;width:230px;font-size:44px;color:' .. nameColor .. '">' .. escText(cardInfo.displayTitleShort or cardInfo.displayTitle or cardInfo.cardName) .. '</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:95px;left:96px;">[[File:card_type_' .. escFile(cardInfo.cardType) .. '.png|32px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:94px;left:132px;font-size:24px;color:white">状态异常</div>')
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:280px;left:24px;width:310px;height:220px;color:white;text-align:center;font-size:26px;line-height:30px;">')
        local largeContent = expandWikitext((dictDisplay or '') .. (cardInfo.desc or ''))
        table.insert(html, '<div class="scroll-text" style="width:310px;height:220px"><div class="scroll-text-content">' .. largeContent .. '</div></div>')
        table.insert(html, '</div>')
        table.insert(html, '</div>')
       
     else
        -- 普通放大卡牌
        table.insert(html, '<div class="ocv-col-center" style="display:flex;flex-direction:column;align-items:center;gap-right:0px;gap-left:15px;max-width:366px;">')
        table.insert(html, '<div style="display:inline-block;vertical-align:top;position:relative;width:366px;height:514px;overflow:hidden;">')
       
        -- 立绘层
        table.insert(html, '<div style="position:absolute;top:4px;left:29px;z-index:0;">[[File:' .. escFile(cardInfo.art) .. '|328px|link=]]</div>')
       
        -- 黑色蒙版
        table.insert(html, '<div style="position:absolute;top:2px;left:5px;z-index:1;">[[File:card_黑色蒙版.png|358px|link=]]</div>')
       
        -- 标题背景条
        local barColor = rarityBarColor(cardInfo.rarity)
        table.insert(html, '<div style="position:absolute;top:66px;left:30px;width:326px;height:20px;background:' .. barColor .. ';z-index:2;"></div>')
       
        -- EGO框架
        table.insert(html, '<div style="position:absolute;top:0px;left:4px;z-index:3;">[[File:card_ego_' .. escFile(cardInfo.ego) .. '.png|358px|link=]]</div>')
       
        -- 稀有度标识
        table.insert(html, '<div style="position:absolute;top:50px;left:2px;z-index:4;">[[File:card_rarity_' .. escFile(cardInfo.rarity) .. '.png|42px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;top:54px;right:0px;z-index:4;">[[File:card_rarity_' .. escFile(cardInfo.rarity) .. '_sub.png|20px|link=]]</div>')
       
        -- 能量线
        table.insert(html, '<div style="position:absolute;top:110px;left:40px;z-index:5;">[[File:energy_line_蓝.png|50px|link=]]</div>')
       
        -- AP显示
        table.insert(html, renderApDiv(apDisplay, '30px', '50px', '76px', cardInfo.apStyle or 'blue'))
       
        -- 卡牌名称
        table.insert(html, '<div style="position:absolute;z-index:10;top:40px;left:100px;width:230px;font-size:44px;color:' .. nameColor .. '">' .. escText(cardInfo.displayTitleShort or cardInfo.displayTitle or cardInfo.cardName) .. '</div>')
       
        -- 类型图标和文字
        table.insert(html, '<div style="position:absolute;z-index:10;top:96px;left:96px;">[[File:card_type_' .. escFile(cardInfo.cardType) .. '.png|32px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:95px;left:132px;font-size:24px;color:white">' .. escText(cardInfo.cardType) .. '</div>')
       
        -- 描述文本
        table.insert(html, '<div style="position:absolute;z-index:10;top:280px;left:40px;width:310px;height:220px;color:white;text-align:center;font-size:26px;line-height:30px; display: flex; align-items: center; justify-content: center;">')
        local largeContent = expandWikitext((dictDisplay or '') .. (cardInfo.desc or ''))
        table.insert(html, '<div class="scroll-text" ><div class="scroll-text-content">' .. largeContent .. '</div></div>')
        table.insert(html, '</div>')
        table.insert(html, '</div>')
    end


    -- 灵光一闪和神光一闪按钮
     if cardInfo.hasInspiration or cardInfo.hasGodInspiration then
     if cardInfo.hasInspiration or cardInfo.hasGodInspiration then
         table.insert(html, '<div class="variant-buttons" style="display:flex;gap:15px;align-items:center;justify-content:center;flex-wrap:wrap;">')
         table.insert(html, '<div class="variant-buttons" style="display:flex;gap:10px;align-items:center;justify-content:center;flex-wrap:wrap;">')
         if cardInfo.hasInspiration then
         if cardInfo.hasInspiration then
             table.insert(html, '<div class="inspiration-button" style="display:inline-block;padding:10px 10px;background:linear-gradient(135deg,#6fd8fe 0%,#4da6cc 100%);color:white;font-size:18px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">灵光一闪</div>')
             table.insert(html, '<div class="inspiration-button" style="display:inline-block;padding:10px 10px;background:linear-gradient(135deg,#6fd8fe 0%,#4da6cc 100%);color:white;font-size:18px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">灵光一闪</div>')
第423行: 第282行:
     table.insert(html, '</div>') -- 结束中间列
     table.insert(html, '</div>') -- 结束中间列


     -- 右侧:词典机制说明
     -- 右侧:词典机制说明
     table.insert(html, '<div class="ocv-col-right" style="display:flex;flex-direction:column;align-items:flex-start;gap-right:0px;gap-left:15px;max-width:250px;">')
     table.insert(html, '<div class="ocv-col-right" style="display:flex;flex-direction:column;align-items:flex-start;gap:10px;max-width:250px;">')
     table.insert(html, renderDictMechanisms(cardInfo.dictEntries))
     table.insert(html, renderDictMechanisms(cardInfo.dictEntries))
     table.insert(html, '</div>')
     table.insert(html, '</div>')
第440行: 第299行:
         table.insert(html, '<div class="back-to-card-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回卡牌</div>')
         table.insert(html, '<div class="back-to-card-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回卡牌</div>')
         table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">灵光一闪</div>')
         table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">灵光一闪</div>')
         table.insert(html, '<div class="inspiration-cards-wrapper" style="display:flex;gap-right:0px;gap-left:15px;justify-content:center;flex-wrap:wrap;max-width:90vw;align-items:flex-start;">')
         table.insert(html, '<div class="inspiration-cards-wrapper" style="display:flex;gap:10px;justify-content:center;flex-wrap:wrap;max-width:90vw;align-items:flex-start;">')
         for i, variantInfo in ipairs(cardInfo.inspirationVariants) do
         for i, variantInfo in ipairs(cardInfo.inspirationVariants) do
             table.insert(html, p.renderInspirationVariant(variantInfo, i))
             table.insert(html, p.renderInspirationVariant(variantInfo, i))
第459行: 第318行:


     if cardInfo.hasGodInspiration and cardInfo.godInspirationGroups and cardInfo.godInspirationGroupOrder then
     if cardInfo.hasGodInspiration and cardInfo.godInspirationGroups and cardInfo.godInspirationGroupOrder then
         table.insert(html, '<div class="god-inspiration-view" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;flex-direction:column;align-items:center;justify-content:flex-start;padding-top:60px;">')
         table.insert(html, '<div class="god-inspiration-view" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;flex-direction:column;align-items:center;justify-content:flex-start;">')
         table.insert(html, '<div class="back-to-card-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回卡牌</div>')
         table.insert(html, '<div class="back-to-card-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回卡牌</div>')
         table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">神光一闪</div>')
         table.insert(html, '<div style="color:white;font-size:24px;margin-top: 24px;">神光一闪</div>')
   
         for _, groupName in ipairs(cardInfo.godInspirationGroupOrder) do
        -- 第一行:前三组,每组3张卡牌
             local groupList = cardInfo.godInspirationGroups[groupName]
        local firstRowGroups = {}
            if groupList and #groupList > 0 then
         for i = 1, math.min(3, #cardInfo.godInspirationGroupOrder) do
                table.insert(html, '<div style="color:#ffd36a;font-size:20px;margin:8px 0;">' .. escText(groupName) .. '</div>')
             table.insert(firstRowGroups, cardInfo.godInspirationGroupOrder[i])
                 table.insert(html, '<div class="god-inspiration-row" style="display:flex;gap:10px;justify-content:center;flex-wrap:nowrap;max-width:90vw;">')
        end
                for _, variantInfo in ipairs(groupList) do
   
                    table.insert(html, p.renderGodVariantCard(variantInfo))
        if #firstRowGroups > 0 then
            table.insert(html, '<div class="god-inspiration-row-1" style="display:flex;gap:30px;justify-content:center;margin-bottom:30px;flex-wrap:nowrap;">')
            for _, groupName in ipairs(firstRowGroups) do
                local groupList = cardInfo.godInspirationGroups[groupName]
                if groupList and #groupList > 0 then
                    table.insert(html, '<div class="god-group" style="display:flex;flex-direction:column;align-items:center;">')
                    table.insert(html, '<div style="color:#ffd36a;font-size:18px;margin-bottom:10px;">' .. escText(groupName) .. '</div>')
                    table.insert(html, '<div style="display:flex;gap:10px;justify-content:center;">')
                    for _, variantInfo in ipairs(groupList) do
                        table.insert(html, p.renderGodVariantCardSmall(variantInfo))
                    end
                    table.insert(html, '</div>')
                    table.insert(html, '</div>')
                 end
            end
            table.insert(html, '</div>')
        end
   
        -- 第二行:后两组,每组3张卡牌
        local secondRowGroups = {}
        for i = 4, math.min(5, #cardInfo.godInspirationGroupOrder) do
            table.insert(secondRowGroups, cardInfo.godInspirationGroupOrder[i])
        end
   
        if #secondRowGroups > 0 then
            table.insert(html, '<div class="god-inspiration-row-2" style="display:flex;gap:30px;justify-content:center;flex-wrap:nowrap;">')
            for _, groupName in ipairs(secondRowGroups) do
                local groupList = cardInfo.godInspirationGroups[groupName]
                if groupList and #groupList > 0 then
                    table.insert(html, '<div class="god-group" style="display:flex;flex-direction:column;align-items:center;">')
                    table.insert(html, '<div style="color:#ffd36a;font-size:18px;margin-bottom:10px;">' .. escText(groupName) .. '</div>')
                    table.insert(html, '<div style="display:flex;gap:10px;justify-content:center;">')
                    for _, variantInfo in ipairs(groupList) do
                        table.insert(html, p.renderGodVariantCardSmall(variantInfo))
                    end
                    table.insert(html, '</div>')
                    table.insert(html, '</div>')
                 end
                 end
                table.insert(html, '</div>')
             end
             end
            table.insert(html, '</div>')
         end
         end
   
         table.insert(html, '</div>')
         table.insert(html, '</div>')
     end
     end


        table.insert(html, '</div>')
    table.insert(html, '</div>') -- card-modal
        table.insert(html, '</div>')
    return table.concat(html, '')
        return table.concat(html, '')
end
    end


function p.renderSubcardsView(subCardInfos)
function p.renderSubcardsView(subCardInfos)
第524行: 第344行:
     table.insert(html, '<div class="back-to-card-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回所有衍生</div>')
     table.insert(html, '<div class="back-to-card-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回所有衍生</div>')
     table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">衍生卡牌</div>')
     table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">衍生卡牌</div>')
     table.insert(html, '<div class="subcards-wrapper" style="display:flex;gap-right:0px;gap-left:15px;justify-content:center;flex-wrap:wrap;max-width:90vw;">')
     table.insert(html, '<div class="subcards-wrapper" style="display:flex;gap:10px;justify-content:center;flex-wrap:wrap;max-width:90vw;">')
     for i, subCardInfo in ipairs(subCardInfos) do
     for i, subCardInfo in ipairs(subCardInfos) do
         table.insert(html, '<div style="display:flex;flex-direction:column;align-items:center;gap-right:0px;gap-left:15px;">')
         table.insert(html, '<div style="display:flex;flex-direction:column;align-items:center;gap:10px;">')
         table.insert(html, p.renderSubCard(subCardInfo))
         table.insert(html, p.renderSubCard(subCardInfo))
         if subCardInfo.subCards and #subCardInfo.subCards > 0 then
         if subCardInfo.subCards and #subCardInfo.subCards > 0 then
第548行: 第368行:
     table.insert(html, '<div class="back-to-subcards-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回所有衍生</div>')
     table.insert(html, '<div class="back-to-subcards-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回所有衍生</div>')
     table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">' .. escText(parentCardInfo.displayTitle or parentCardInfo.cardName) .. ' 的衍生卡牌</div>')
     table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">' .. escText(parentCardInfo.displayTitle or parentCardInfo.cardName) .. ' 的衍生卡牌</div>')
     table.insert(html, '<div class="nested-subcards-wrapper" style="display:flex;gap-right:0px;gap-left:15px;justify-content:center;flex-wrap:wrap;max-width:90vw;">')
     table.insert(html, '<div class="nested-subcards-wrapper" style="display:flex;gap:10px;justify-content:center;flex-wrap:wrap;max-width:90vw;">')
     for _, nestedCardInfo in ipairs(parentCardInfo.subCards) do
     for _, nestedCardInfo in ipairs(parentCardInfo.subCards) do
         table.insert(html, '<div style="display:flex;flex-direction:column;align-items:center;gap-right:0px;gap-left:15px;">')
         table.insert(html, '<div style="display:flex;flex-direction:column;align-items:center;gap:10px;">')
         table.insert(html, p.renderSubCard(nestedCardInfo))
         table.insert(html, p.renderSubCard(nestedCardInfo))
         table.insert(html, '</div>')
         table.insert(html, '</div>')
第564行: 第384行:
     local apDisplay = variantInfo.apText or ''
     local apDisplay = variantInfo.apText or ''
     local nameColor = rarityNameColor(variantInfo.rarity)
     local nameColor = rarityNameColor(variantInfo.rarity)
    local isAbnormal = (variantInfo.cardType == "状态异常")
    local isSkill = (variantInfo.group == "自我意识技能")


     table.insert(html, '<div class="inspiration-variant" style="display:flex;flex-direction:column;align-items:center;gap:8px;width:270px;">')
     table.insert(html, '<div class="inspiration-variant" style="display:flex;flex-direction:column;align-items:center;gap:8px;width:240px;">')
      
     table.insert(html, '<div class="inspiration-variant-card" style="display:inline-block;vertical-align:top;position:relative;width:240px;height:345px;overflow:hidden;">')
    if isSkill then
 
        -- 自我意识技能中卡牌
    table.insert(html, renderArtLayer(variantInfo, 240))
        table.insert(html, '<div class="inspiration-variant-card" style="display:inline-block;vertical-align:top;position:relative;width:254px;height:390px;overflow:hidden;">')
    table.insert(html, renderRarityBar(variantInfo, 240))
        table.insert(html, renderSkillCardLayersMedium(variantInfo))
    table.insert(html, renderOverlayLayers(variantInfo, 240))
       
 
        table.insert(html, '<div style="position:absolute;top:135px;left:36px;z-index:10;font-size:24px;color:white">' .. escText(variantInfo.displayTitle or variantInfo.cardName) .. '</div>')
     table.insert(html, renderApDiv(apDisplay, '8px', '31px', '54px', variantInfo.apStyle or 'blue'))
        table.insert(html, '<div style="position:absolute;top:162px;left:33px;z-index:10;">[[File:icon_tp_skill_type_awaken.png|30px|link=]]</div>')
     table.insert(html, renderApDiv('', '46px', '32px', '32px', variantInfo.apStyle or 'blue'))
        table.insert(html, '<div style="position:absolute;top:167px;left:63px;z-index:10;font-size:20px;color:white">自我意识技能</div>')
 
        table.insert(html, '<div style="position:absolute;top:198px;left:33px;width:212px;height:2px;background-color:rgba(255,255,255);z-index:10;"></div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:18px;left:64px;color:' .. nameColor .. ';font-size:24px">' .. escText(variantInfo.displayTitleShort or variantInfo.displayTitle or variantInfo.cardName) .. '</div>')
       
 
        local apNum = tonumber(apDisplay) or 0
    table.insert(html, '<div style="position:absolute;z-index:10;top:50px;left:63px;">[[File:card_type_' .. escFile(variantInfo.cardType) .. '.png|24px]]</div>')
        table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:10;">[[File:card_skill_ap_' .. apNum .. '.png|254px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:49px;left:90px;font-size:20px;color:white">' .. escText(variantInfo.cardType) .. '</div>')
       
    table.insert(html, '<div style="position:absolute;z-index:10;top:165px;left:20px;width:220px;height:175px;color:white;text-align:center;font-size:18px;line-height:20px;">')
        table.insert(html, '<div style="position:absolute;top:210px;left:30px;width:218px;height:158px;color:white;text-align:center;font-size:20px;line-height:23px;z-index:10;">')
    local inspContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
        local inspContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
    table.insert(html, '<div class="scroll-text" style="width:212px;height:170px"><div class="scroll-text-content">' .. inspContent .. '</div></div>')
        table.insert(html, '<div class="scroll-text" style="width:218px;height:158px"><div class="scroll-text-content">' .. inspContent .. '</div></div>')
    table.insert(html, '</div>')
        table.insert(html, '</div>')
    table.insert(html, '</div>')
        table.insert(html, '</div>')
       
     elseif isAbnormal then
        -- 状态异常中卡牌
        table.insert(html, '<div class="inspiration-variant-card" style="display:inline-block;vertical-align:top;position:relative;width:269px;height:395px;overflow:hidden;">')
        table.insert(html, renderAbnormalCardLayersMedium(variantInfo))
       
        table.insert(html, renderApDiv(apDisplay, '23px', '38px', '57px', variantInfo.apStyle or 'blue'))
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:30px;left:75px;width:173px;font-size:32px;color:' .. nameColor .. '">' .. escText(variantInfo.displayTitleShort or variantInfo.displayTitle or variantInfo.cardName) .. '</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:72px;left:72px;">[[File:card_type_' .. escFile(variantInfo.cardType) .. '.png|24px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:71px;left:99px;font-size:18px;color:white">状态异常</div>')
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:210px;left:18px;width:233px;height:165px;color:white;text-align:center;font-size:20px;line-height:23px;">')
        local inspContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
        table.insert(html, '<div class="scroll-text" style="width:233px;height:165px"><div class="scroll-text-content">' .. inspContent .. '</div></div>')
        table.insert(html, '</div>')
        table.insert(html, '</div>')
       
     else
        -- 普通中卡牌
        table.insert(html, '<div class="inspiration-variant-card" style="display:inline-block;vertical-align:top;position:relative;width:275px;height:386px;overflow:hidden;">')
       
        -- 立绘层
        table.insert(html, '<div style="position:absolute;top:3px;left:22px;z-index:0;">[[File:' .. escFile(variantInfo.art) .. '|246px|link=]]</div>')
       
        -- 黑色蒙版
        table.insert(html, '<div style="position:absolute;top:1px;left:3px;z-index:1;">[[File:card_黑色蒙版.png|269px|link=]]</div>')
       
        -- 标题背景条
        local barColor = rarityBarColor(variantInfo.rarity)
        table.insert(html, '<div style="position:absolute;top:50px;left:23px;width:245px;height:15px;background:' .. barColor .. ';z-index:2;"></div>')
       
        -- EGO框架
        table.insert(html, '<div style="position:absolute;top:0px;left:3px;z-index:3;">[[File:card_ego_' .. escFile(variantInfo.ego) .. '.png|269px|link=]]</div>')
       
        -- 稀有度标识
        table.insert(html, '<div style="position:absolute;top:38px;left:2px;z-index:4;">[[File:card_rarity_' .. escFile(variantInfo.rarity) .. '.png|32px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;top:41px;right:0px;z-index:4;">[[File:card_rarity_' .. escFile(variantInfo.rarity) .. '_sub.png|15px|link=]]</div>')
       
        -- 能量线
        table.insert(html, '<div style="position:absolute;top:80px;left:30px;z-index:5;">[[File:energy_line_蓝.png|38px|link=]]</div>')
       
        -- AP显示
        table.insert(html, renderApDiv(apDisplay, '23px', '38px', '57px', variantInfo.apStyle or 'blue'))
       
        -- 卡牌名称
        table.insert(html, '<div style="position:absolute;z-index:10;top:32px;left:75px;width:173px;font-size:32px;color:' .. nameColor .. '">' .. escText(variantInfo.displayTitleShort or variantInfo.displayTitle or variantInfo.cardName) .. '</div>')
       
        -- 类型图标和文字
        table.insert(html, '<div style="position:absolute;z-index:10;top:72px;left:72px;">[[File:card_type_' .. escFile(variantInfo.cardType) .. '.png|24px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:72px;left:99px;font-size:18px;color:white">' .. escText(variantInfo.cardType) .. '</div>')
       
        -- 描述文本
        table.insert(html, '<div style="position:absolute;z-index:10;top:210px;left:30px;width:233px;height:165px;color:white;text-align:center;font-size:20px;line-height:23px;">')
        local inspContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
        table.insert(html, '<div class="scroll-text" style="width:233px;height:165px"><div class="scroll-text-content">' .. inspContent .. '</div></div>')
        table.insert(html, '</div>')
        table.insert(html, '</div>')
    end


     if variantInfo.subCards and #variantInfo.subCards > 0 then
     if variantInfo.subCards and #variantInfo.subCards > 0 then
         table.insert(html, '<div class="inspiration-subcards-button" data-variant-index="' .. index .. '" style="display:inline-block;padding:10px 20px;background:linear-gradient(135deg,#ffa500 0%,#cc8400 100%);color:white;font-size:15px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">查看衍生卡牌</div>')
         table.insert(html, '<div class="inspiration-subcards-button" data-variant-index="' .. index .. '" style="display:inline-block;padding:10px 20px;background:linear-gradient(135deg,#6fd8fe 0%,#4da6cc 100%);color:white;font-size:15px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">查看衍生卡牌</div>')
     end
     end


第660行: 第418行:
     table.insert(html, '<div class="back-to-inspiration-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回灵光一闪</div>')
     table.insert(html, '<div class="back-to-inspiration-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回灵光一闪</div>')
     table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">' .. escText(variantInfo.displayTitle or variantInfo.cardName) .. '的衍生卡牌</div>')
     table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">' .. escText(variantInfo.displayTitle or variantInfo.cardName) .. '的衍生卡牌</div>')
     table.insert(html, '<div class="inspiration-subcards-wrapper" style="display:flex;gap-right:0px;gap-left:15px;justify-content:center;flex-wrap:wrap;max-width:90vw;">')
     table.insert(html, '<div class="inspiration-subcards-wrapper" style="display:flex;gap:10px;justify-content:center;flex-wrap:wrap;max-width:90vw;">')
     for j, subCardInfo in ipairs(variantInfo.subCards) do
     for j, subCardInfo in ipairs(variantInfo.subCards) do
         table.insert(html, '<div style="display:flex;flex-direction:column;align-items:center;gap-right:0px;gap-left:15px;">')
         table.insert(html, '<div style="display:flex;flex-direction:column;align-items:center;gap:10px;">')
         table.insert(html, p.renderSubCard(subCardInfo))
         table.insert(html, p.renderSubCard(subCardInfo))
         if subCardInfo.subCards and #subCardInfo.subCards > 0 then
         if subCardInfo.subCards and #subCardInfo.subCards > 0 then
第679行: 第437行:
     table.insert(html, '<div class="back-to-inspiration-subcards-button" data-variant-index="' .. variantIndex .. '" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回灵光一闪的衍生</div>')
     table.insert(html, '<div class="back-to-inspiration-subcards-button" data-variant-index="' .. variantIndex .. '" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回灵光一闪的衍生</div>')
     table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">' .. escText(parentSubCardInfo.displayTitle or parentSubCardInfo.cardName) .. ' 的衍生卡牌</div>')
     table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">' .. escText(parentSubCardInfo.displayTitle or parentSubCardInfo.cardName) .. ' 的衍生卡牌</div>')
     table.insert(html, '<div class="inspiration-nested-subcards-wrapper" style="display:flex;gap-right:0px;gap-left:15px;justify-content:center;flex-wrap:wrap;max-width:90vw;">')
     table.insert(html, '<div class="inspiration-nested-subcards-wrapper" style="display:flex;gap:10px;justify-content:center;flex-wrap:wrap;max-width:90vw;">')
     for _, nestedCardInfo in ipairs(parentSubCardInfo.subCards or {}) do
     for _, nestedCardInfo in ipairs(parentSubCardInfo.subCards or {}) do
         table.insert(html, '<div style="display:flex;flex-direction:column;align-items:center;gap-right:0px;gap-left:15px;">')
         table.insert(html, '<div style="display:flex;flex-direction:column;align-items:center;gap:10px;">')
         table.insert(html, p.renderSubCard(nestedCardInfo))
         table.insert(html, p.renderSubCard(nestedCardInfo))
         table.insert(html, '</div>')
         table.insert(html, '</div>')
第695行: 第453行:
     local apDisplay = variantInfo.apText or ''
     local apDisplay = variantInfo.apText or ''
     local nameColor = rarityNameColor(variantInfo.rarity)
     local nameColor = rarityNameColor(variantInfo.rarity)
    local isAbnormal = (variantInfo.cardType == "状态异常")
 
    local isSkill = (variantInfo.group == "自我意识技能")
     table.insert(html, '<div class="god-variant-card" style="display:inline-block;vertical-align:top;position:relative;width:240px;height:345px;overflow:hidden;">')
   
 
     if isSkill then
    table.insert(html, renderArtLayer(variantInfo, 240))
        -- 自我意识技能中卡牌
    table.insert(html, renderRarityBar(variantInfo, 240))
        table.insert(html, '<div class="god-variant-card" style="display:inline-block;vertical-align:top;position:relative;width:254px;height:390px;overflow:hidden;">')
    table.insert(html, renderOverlayLayers(variantInfo, 240))
        table.insert(html, renderSkillCardLayersMedium(variantInfo))
 
       
     table.insert(html, renderApDiv(apDisplay, '8px', '31px', '54px', variantInfo.apStyle or 'blue'))
        table.insert(html, '<div style="position:absolute;top:135px;left:36px;z-index:10;font-size:24px;color:white">' .. escText(variantInfo.displayTitle or variantInfo.cardName) .. '</div>')
     table.insert(html, renderApDiv('', '46px', '32px', '32px', variantInfo.apStyle or 'blue'))
        table.insert(html, '<div style="position:absolute;top:162px;left:33px;z-index:10;">[[File:icon_tp_skill_type_awaken.png|30px|link=]]</div>')
 
        table.insert(html, '<div style="position:absolute;top:167px;left:63px;z-index:10;font-size:20px;color:white">自我意识技能</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:18px;left:64px;color:' .. nameColor .. ';font-size:24px">' .. escText(variantInfo.displayTitleShort or variantInfo.displayTitle or variantInfo.cardName) .. '</div>')
        table.insert(html, '<div style="position:absolute;top:198px;left:33px;width:212px;height:2px;background-color:rgba(255,255,255);z-index:10;"></div>')
 
       
    table.insert(html, '<div style="position:absolute;z-index:10;top:50px;left:63px;">[[File:card_type_' .. escFile(variantInfo.cardType) .. '.png|24px]]</div>')
        local apNum = tonumber(apDisplay) or 0
    table.insert(html, '<div style="position:absolute;z-index:10;top:49px;left:90px;font-size:20px;color:white">' .. escText(variantInfo.cardType) .. '</div>')
        table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:10;">[[File:card_skill_ap_' .. apNum .. '.png|254px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:165px;left:20px;width:220px;height:175px;color:white;text-align:center;font-size:18px;line-height:20px;">')
       
    local godContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
        table.insert(html, '<div style="position:absolute;top:210px;left:30px;width:218px;height:158px;color:white;text-align:center;font-size:20px;line-height:23px;z-index:10;">')
    table.insert(html, '<div class="scroll-text" style="width:212px;height:170px"><div class="scroll-text-content">' .. godContent .. '</div></div>')
        local godContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
    table.insert(html, '</div>')
        table.insert(html, '<div class="scroll-text" style="width:218px;height:158px"><div class="scroll-text-content">' .. godContent .. '</div></div>')
    table.insert(html, '</div>')
        table.insert(html, '</div>')
        table.insert(html, '</div>')
       
     elseif isAbnormal then
        -- 状态异常中卡牌
        table.insert(html, '<div class="god-variant-card" style="display:inline-block;vertical-align:top;position:relative;width:269px;height:395px;overflow:hidden;">')
        table.insert(html, renderAbnormalCardLayersMedium(variantInfo))
       
        table.insert(html, renderApDiv(apDisplay, '23px', '38px', '57px', variantInfo.apStyle or 'blue'))
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:30px;left:75px;width:173px;font-size:32px;color:' .. nameColor .. '">' .. escText(variantInfo.displayTitleShort or variantInfo.displayTitle or variantInfo.cardName) .. '</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:72px;left:72px;">[[File:card_type_' .. escFile(variantInfo.cardType) .. '.png|24px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:71px;left:99px;font-size:18px;color:white">状态异常</div>')
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:210px;left:18px;width:233px;height:165px;color:white;text-align:center;font-size:20px;line-height:23px;">')
        local godContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
        table.insert(html, '<div class="scroll-text" style="width:233px;height:165px"><div class="scroll-text-content">' .. godContent .. '</div></div>')
        table.insert(html, '</div>')
        table.insert(html, '</div>')
       
     else
        -- 普通中卡牌
        table.insert(html, '<div class="god-variant-card" style="display:inline-block;vertical-align:top;position:relative;width:275px;height:386px;overflow:hidden;">')
       
        -- 立绘层
        table.insert(html, '<div style="position:absolute;top:3px;left:22px;z-index:0;">[[File:' .. escFile(variantInfo.art) .. '|246px|link=]]</div>')
       
        -- 黑色蒙版
        table.insert(html, '<div style="position:absolute;top:0px;left:5px;z-index:1;">[[File:card_黑色蒙版.png|269px|link=]]</div>')
       
        -- 标题背景条
        local barColor = rarityBarColor(variantInfo.rarity)
        table.insert(html, '<div style="position:absolute;top:50px;left:23px;width:245px;height:15px;background:' .. barColor .. ';z-index:2;"></div>')
       
        -- EGO框架
        table.insert(html, '<div style="position:absolute;top:0px;left:3px;z-index:3;">[[File:card_ego_' .. escFile(variantInfo.ego) .. '.png|269px|link=]]</div>')
       
        -- 稀有度标识
        table.insert(html, '<div style="position:absolute;top:38px;left:2px;z-index:4;">[[File:card_rarity_' .. escFile(variantInfo.rarity) .. '.png|32px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;top:41px;right:0px;z-index:4;">[[File:card_rarity_' .. escFile(variantInfo.rarity) .. '_sub.png|15px|link=]]</div>')
       
        -- 能量线
        table.insert(html, '<div style="position:absolute;top:80px;left:30px;z-index:5;">[[File:energy_line_蓝.png|38px|link=]]</div>')
       
        -- AP显示
        table.insert(html, renderApDiv(apDisplay, '23px', '38px', '57px', variantInfo.apStyle or 'blue'))
       
        -- 卡牌名称
        table.insert(html, '<div style="position:absolute;z-index:10;top:32px;left:75px;width:173px;font-size:32px;color:' .. nameColor .. '">' .. escText(variantInfo.displayTitleShort or variantInfo.displayTitle or variantInfo.cardName) .. '</div>')
       
        -- 类型图标和文字
        table.insert(html, '<div style="position:absolute;z-index:10;top:72px;left:72px;">[[File:card_type_' .. escFile(variantInfo.cardType) .. '.png|24px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:72px;left:99px;font-size:18px;color:white">' .. escText(variantInfo.cardType) .. '</div>')
       
        -- 描述文本
        table.insert(html, '<div style="position:absolute;z-index:10;top:210px;left:30px;width:233px;height:165px;color:white;text-align:center;font-size:20px;line-height:23px;">')
        local godContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
        table.insert(html, '<div class="scroll-text" style="width:233px;height:165px"><div class="scroll-text-content">' .. godContent .. '</div></div>')
        table.insert(html, '</div>')
        table.insert(html, '</div>')
    end
   
     return table.concat(html, '')
     return table.concat(html, '')
end
end
第784行: 第480行:
     local apDisplay = subCardInfo.apText or ''
     local apDisplay = subCardInfo.apText or ''
     local nameColor = rarityNameColor(subCardInfo.rarity)
     local nameColor = rarityNameColor(subCardInfo.rarity)
    local isAbnormal = (subCardInfo.cardType == "状态异常")
    local isSkill = (subCardInfo.group == "自我意识技能")


     if isSkill then
     table.insert(html, '<div style="display:inline-block;vertical-align:top;position:relative;width:240px;height:345px;overflow:hidden;">')
        -- 自我意识技能中卡牌
 
        table.insert(html, '<div style="display:inline-block;vertical-align:top;position:relative;width:254px;height:390px;overflow:hidden;">')
    table.insert(html, renderArtLayer(subCardInfo, 240))
        table.insert(html, renderSkillCardLayersMedium(subCardInfo))
    table.insert(html, renderRarityBar(subCardInfo, 240))
       
    table.insert(html, renderOverlayLayers(subCardInfo, 240))
        table.insert(html, '<div style="position:absolute;top:135px;left:36px;z-index:10;font-size:24px;color:white">' .. escText(subCardInfo.displayTitle or subCardInfo.cardName) .. '</div>')
 
        table.insert(html, '<div style="position:absolute;top:162px;left:33px;z-index:10;">[[File:icon_tp_skill_type_awaken.png|30px|link=]]</div>')
     table.insert(html, renderApDiv(apDisplay, '8px', '31px', '54px', subCardInfo.apStyle or 'blue'))
        table.insert(html, '<div style="position:absolute;top:167px;left:63px;z-index:10;font-size:20px;color:white">自我意识技能</div>')
     table.insert(html, renderApDiv('', '46px', '32px', '38px', subCardInfo.apStyle or 'blue'))
        table.insert(html, '<div style="position:absolute;top:198px;left:33px;width:212px;height:2px;background-color:rgba(255,255,255);z-index:10;"></div>')
 
       
    table.insert(html, '<div style="position:absolute;z-index:10;top:18px;left:64px;color:' .. nameColor .. ';font-size:24px">' .. escText(subCardInfo.displayTitleShort or subCardInfo.displayTitle or subCardInfo.cardName) .. '</div>')
        local apNum = tonumber(apDisplay) or 0
        table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:10;">[[File:card_skill_ap_' .. apNum .. '.png|254px|link=]]</div>')
       
        table.insert(html, '<div style="position:absolute;top:210px;left:30px;width:218px;height:158px;color:white;text-align:center;font-size:20px;line-height:23px;z-index:10;">')
        local subContent = expandWikitext((dictDisplay or '') .. (subCardInfo.desc or ''))
        table.insert(html, '<div class="scroll-text" style="width:218px;height:158px"><div class="scroll-text-content">' .. subContent .. '</div></div>')
        table.insert(html, '</div>')
        table.insert(html, '</div>')
       
     elseif isAbnormal then
        -- 状态异常中卡牌
        table.insert(html, '<div style="display:inline-block;vertical-align:top;position:relative;width:269px;height:395px;overflow:hidden;">')
        table.insert(html, renderAbnormalCardLayersMedium(subCardInfo))
       
        table.insert(html, renderApDiv(apDisplay, '23px', '38px', '57px', subCardInfo.apStyle or 'blue'))
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:30px;left:75px;width:173px;font-size:32px;color:' .. nameColor .. '">' .. escText(subCardInfo.displayTitleShort or subCardInfo.displayTitle or subCardInfo.cardName) .. '</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:72px;left:72px;">[[File:card_type_' .. escFile(subCardInfo.cardType) .. '.png|24px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:71px;left:99px;font-size:18px;color:white">状态异常</div>')
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:210px;left:18px;width:233px;height:165px;color:white;text-align:center;font-size:20px;line-height:23px;">')
        local subContent = expandWikitext((dictDisplay or '') .. (subCardInfo.desc or ''))
        table.insert(html, '<div class="scroll-text" style="width:233px;height:165px"><div class="scroll-text-content">' .. subContent .. '</div></div>')
        table.insert(html, '</div>')
        table.insert(html, '</div>')
       
     else
        -- 普通中卡牌
        table.insert(html, '<div style="display:inline-block;vertical-align:top;position:relative;width:275px;height:386px;overflow:hidden;">')
       
        -- 立绘层
        table.insert(html, '<div style="position:absolute;top:3px;left:22px;z-index:0;">[[File:' .. escFile(subCardInfo.art) .. '|246px|link=]]</div>')
       
        -- 黑色蒙版
        table.insert(html, '<div style="position:absolute;top:0px;left:5px;z-index:1;">[[File:card_黑色蒙版.png|269px|link=]]</div>')
       
        -- 标题背景条
        local barColor = rarityBarColor(subCardInfo.rarity)
        table.insert(html, '<div style="position:absolute;top:50px;left:23px;width:245px;height:15px;background:' .. barColor .. ';z-index:2;"></div>')
       
        -- EGO框架
        table.insert(html, '<div style="position:absolute;top:0px;left:3px;z-index:3;">[[File:card_ego_' .. escFile(subCardInfo.ego) .. '.png|269px|link=]]</div>')
       
        -- 稀有度标识
        table.insert(html, '<div style="position:absolute;top:38px;left:2px;z-index:4;">[[File:card_rarity_' .. escFile(subCardInfo.rarity) .. '.png|32px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;top:41px;right:0px;z-index:4;">[[File:card_rarity_' .. escFile(subCardInfo.rarity) .. '_sub.png|15px|link=]]</div>')
       
        -- 能量线
        table.insert(html, '<div style="position:absolute;top:80px;left:30px;z-index:5;">[[File:energy_line_蓝.png|38px|link=]]</div>')
       
        -- AP显示
        table.insert(html, renderApDiv(apDisplay, '23px', '38px', '57px', subCardInfo.apStyle or 'blue'))
       
        -- 卡牌名称
        table.insert(html, '<div style="position:absolute;z-index:10;top:32px;left:75px;width:173px;font-size:32px;color:' .. nameColor .. '">' .. escText(subCardInfo.displayTitleShort or subCardInfo.displayTitle or subCardInfo.cardName) .. '</div>')
       
        -- 类型图标和文字
        table.insert(html, '<div style="position:absolute;z-index:10;top:72px;left:72px;">[[File:card_type_' .. escFile(subCardInfo.cardType) .. '.png|24px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:72px;left:99px;font-size:18px;color:white">' .. escText(subCardInfo.cardType) .. '</div>')
       
        -- 描述文本
        table.insert(html, '<div style="position:absolute;z-index:10;top:210px;left:30px;width:233px;height:165px;color:white;text-align:center;font-size:20px;line-height:23px;">')
        local subContent = expandWikitext((dictDisplay or '') .. (subCardInfo.desc or ''))
        table.insert(html, '<div class="scroll-text" style="width:233px;height:165px"><div class="scroll-text-content">' .. subContent .. '</div></div>')
        table.insert(html, '</div>')
        table.insert(html, '</div>')
    end
   
    return table.concat(html, '')
end


function p.renderGodVariantCardSmall(variantInfo)
     table.insert(html, '<div style="position:absolute;z-index:10;top:50px;left:63px;">[[File:card_type_' .. escFile(subCardInfo.cardType) .. '.png|24px]]</div>')
    local html = {}
     table.insert(html, '<div style="position:absolute;z-index:10;top:49px;left:90px;font-size:20px;color:white">' .. escText(subCardInfo.cardType) .. '</div>')
     local dictDisplay = dictSpanFromTokens(variantInfo.dictTokens, variantInfo.dictColor)
    table.insert(html, '<div style="position:absolute;z-index:10;top:165px;left:20px;width:220px;height:175px;color:white;text-align:center;font-size:18px;line-height:20px;">')
    local apDisplay = variantInfo.apText or ''
    local subContent = expandWikitext((dictDisplay or '') .. (subCardInfo.desc or ''))
    local nameColor = rarityNameColor(variantInfo.rarity)
    table.insert(html, '<div class="scroll-text" style="width:212px;height:170px"><div class="scroll-text-content">' .. subContent .. '</div></div>')
    local isAbnormal = (variantInfo.cardType == "状态异常")
    table.insert(html, '</div>')
    local isSkill = (variantInfo.group == "自我意识技能")
   
    if isSkill then
        -- 自我意识技能小卡牌
        table.insert(html, '<div class="god-variant-card-small" style="display:inline-block;vertical-align:top;position:relative;width:169px;height:260px;overflow:hidden;">')
        table.insert(html, renderSkillCardLayersSmall(variantInfo))
       
        table.insert(html, '<div style="position:absolute;top:90px;left:24px;z-index:10;font-size:16px;color:white">' .. escText(variantInfo.displayTitle or variantInfo.cardName) .. '</div>')
        table.insert(html, '<div style="position:absolute;top:110px;left:22px;z-index:10;">[[File:icon_tp_skill_type_awaken.png|20px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;top:111px;left:42px;z-index:10;font-size:13px;color:white">自我意识技能</div>')
        table.insert(html, '<div style="position:absolute;top:132px;left:22px;width:141px;height:1px;background-color:rgba(255,255,255);z-index:10;"></div>')
       
        local apNum = tonumber(apDisplay) or 0
        table.insert(html, '<div style="position:absolute;top:0px;left:0px;z-index:10;">[[File:card_skill_ap_' .. apNum .. '.png|169px|link=]]</div>')
       
        table.insert(html, '<div style="position:absolute;top:137px;left:22px;width:140px;height:105px;color:white;text-align:left;font-size:13px;line-height:15px;z-index:10;">')
        local smallContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
        table.insert(html, '<div><div>' .. smallContent .. '</div></div>')
        table.insert(html, '</div>')
       
     elseif isAbnormal then
        -- 状态异常小卡牌
        table.insert(html, '<div class="god-variant-card-small" style="display:inline-block;vertical-align:top;position:relative;width:179px;height:265px;overflow:hidden;">')
        table.insert(html, renderAbnormalCardLayersSmall(variantInfo))
       
        table.insert(html, renderApDiv(apDisplay, '15px', '25px', '38px', variantInfo.apStyle or 'blue'))
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:20px;left:50px;width:115px;font-size:22px;color:' .. nameColor .. '">' .. escText(variantInfo.displayTitleShort or variantInfo.displayTitle or variantInfo.cardName) .. '</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:44px;left:48px;">[[File:card_type_' .. escFile(variantInfo.cardType) .. '.png|16px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:48px;left:66px;font-size:12px;color:white">状态异常</div>')
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:140px;left:12px;width:155px;height:110px;color:white;text-align:center;font-size:13px;line-height:15px; display: flex; align-items: center; justify-content: center;">')
        local smallContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
        table.insert(html, '<div class="scroll-text"><div class="scroll-text-content">' .. smallContent .. '</div></div>')
        table.insert(html, '</div>')
       
    else
        -- 普通小卡牌
        table.insert(html, '<div class="god-variant-card-small" style="display:inline-block;vertical-align:top;position:relative;width:183px;height:257px;overflow:hidden;">')
        table.insert(html, renderNormalCardLayers(variantInfo, 183))
       
        table.insert(html, renderApDiv(apDisplay, '15px', '25px', '38px', variantInfo.apStyle or 'blue'))
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:20px;left:50px;width:115px;font-size:22px;color:' .. nameColor .. '">' .. escText(variantInfo.displayTitleShort or variantInfo.displayTitle or variantInfo.cardName) .. '</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:44px;left:48px;">[[File:card_type_' .. escFile(variantInfo.cardType) .. '.png|16px|link=]]</div>')
        table.insert(html, '<div style="position:absolute;z-index:10;top:48px;left:66px;font-size:12px;color:white">' .. escText(variantInfo.cardType) .. '</div>')
       
        table.insert(html, '<div style="position:absolute;z-index:10;top:140px;left:20px;width:155px;height:110px;color:white;text-align:center;font-size:13px;line-height:15px; display: flex; align-items: center; justify-content: center;">')
        local smallContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
        table.insert(html, '<div class="scroll-text"><div class="scroll-text-content">' .. smallContent .. '</div></div>')
        table.insert(html, '</div>')
    end
   
     table.insert(html, '</div>')
     table.insert(html, '</div>')
     return table.concat(html, '')
     return table.concat(html, '')

2025年10月15日 (三) 20:24的版本

此模块的文档可以在模块:卡牌/display/doc创建

local p = {}

local function escFile(s)
    s = tostring(s or '')
    s = mw.text.trim(s)
    s = s:gsub('[%[%]%{%}%|]', '')
    return s
end

local function escText(s)
    return mw.text.encode(tostring(s or ''))
end

-- 确保模板与解析函数在内容中被展开
local function expandWikitext(s)
    if s == nil or s == '' then
        return ''
    end
    local ok, frame = pcall(mw.getCurrentFrame)
    if not ok or not frame then
        return tostring(s)
    end
    return frame:preprocess(tostring(s))
end

-- 稀有度统一
local function normalizeRarity(r)
    local s = tostring(r or ''):gsub('%s+', '')
    if s == '' then return nil end
    if s == '白' then return '白' end
    if s == '蓝' then return '蓝' end
    if s == '橙' or s == '橙色' then return '橙' end
    if s == '彩' or s == '彩虹' then return '彩' end
    return nil
end

-- 稀有度对应的标题背景条颜色
local function rarityBarColor(r)
    local key = normalizeRarity(r) or '蓝'
    local map = {
        ['白'] = 'rgba(239, 237, 237, 0.6)',
        ['蓝'] = 'rgba(119, 236, 254, 0.6)',
        ['橙'] = 'rgba(255, 200, 110, 0.6)',
        ['彩'] = 'rgba(180, 125, 242, 0.6)',
    }
    return map[key] or map['蓝']
end

-- 稀有度对应的卡牌名称颜色
local function rarityNameColor(r)
    local key = normalizeRarity(r) or '蓝'
    local map = {
        ['白'] = '#cccccc',
        ['蓝'] = '#73ecfe',
        ['橙'] = '#ffc86e',
        ['彩'] = '#a37df7',
    }
    return map[key] or map['蓝']
end

-- 根据外框宽度返回标题背景条几何尺寸
local function getBarGeom(width)
    width = tonumber(width) or 160
    if width <= 160 then
        return { top = 22, left = 5, w = 150, h = 8 }
    elseif width >= 320 then
        return { top = 44, left = 5, w = 305, h = 16 }
    else
        return { top = 33, left = 5, w = 230, h = 12 }
    end
end

-- 渲染标题背景条层级,art 之上,其余元素之下
local function renderRarityBar(info, width)
    local g = getBarGeom(width)
    local color = rarityBarColor(info.rarity)
    return string.format(
        '<div style="position:absolute;z-index:1;top:%dpx;left:%dpx;width:%dpx;height:%dpx;background-color:%s"></div>',
        g.top, g.left, g.w, g.h, color
    )
end

-- 仅渲染立绘层(最低层)
local function renderArtLayer(info, width)
    return '<div style="position: absolute; top: 0; left: 0; z-index:0;">[[File:' .. escFile(info.art) .. '|' .. width .. 'px|link=]]</div>'
end

-- 渲染覆盖层(横条之上)
local function renderOverlayLayers(info, width)
    local t = {}
    table.insert(t, '<div style="position: absolute; top: 0; left: 0; z-index:2;">[[File:card_黑色蒙版.png|' .. width .. 'px|link=]]</div>')
    table.insert(t, '<div style="position: absolute; top: 0; left: 0; z-index:3;">[[File:card_ego_' .. escFile(info.ego) .. '.png|' .. width .. 'px|link=]]</div>')
    table.insert(t, '<div style="position: absolute; top: 0; left: 0; z-index:4;">[[File:card_rarity_' .. escFile(info.rarity) .. '.png|' .. width .. 'px|link=]]</div>')
    table.insert(t, '<div style="position: absolute; top: 0; left: 0; z-index:5;">[[File:card_顶层蒙版.png|' .. width .. 'px|link=]]</div>')
    return table.concat(t, '')
end

-- 将 tokens 渲染为可调用模板的短标识
local function dictSpanFromTokens(tokens, color)
    if type(tokens) ~= 'table' or #tokens == 0 then
        return ''
    end
    local parts = {}
    for _, t in ipairs(tokens) do
        local key = mw.text.trim(t or '')
        if key ~= '' then
            table.insert(parts, '{{词典|' .. key .. '}}')
        end
    end
    if #parts == 0 then return '' end

    local colorMap = {
        default = '#f2ba02',
        green = '#22bb66'
    }
    local c = colorMap[color or 'default'] or colorMap.default

    return '<span style="color: ' .. c .. '">[' .. table.concat(parts, '/') .. ']</span><br>'
end

local function generateUniqueId(cardInfo)
    local timestamp = os.time()
    local random = math.random(1000, 9999)
    local base = (cardInfo.moduleName or '') .. '-' .. (cardInfo.cardName or '') .. (cardInfo.variantSuffix or '')
    local safeName = mw.uri.anchorEncode(base):gsub("%%", "-")
    return "card-" .. safeName .. "-" .. timestamp .. "-" .. random
end

-- AP 发光样式
local function apTextShadow(style)
    if style == 'red' then
        return 'text-shadow:0 0 10px #7a0e0e,0 0 20px #7a0e0e,0 0 30px #ff3030,0 0 40px #ff3030,0 0 50px #ff3030,0 0 60px #ff3030,0 0 70px #ff3030;'
    elseif style == 'green' then
        return 'text-shadow:0 0 10px #0e6f36,0 0 20px #0e6f36,0 0 30px #29ff85,0 0 40px #29ff85,0 0 50px #29ff85,0 0 60px #29ff85,0 0 70px #29ff85;'
    elseif style == 'blue' then
        return 'text-shadow:0 0 10px #132cbf,0 0 20px #132cbf,0 0 30px #4169ff,0 0 40px #4169ff,0 0 50px #4169ff,0 0 60px #4169ff,0 0 70px #4169ff;'
    else
        return '' -- gray: no glow
    end
end

local function renderApDiv(content, top, left, fontSize, style)
    content = tostring(content or '')
    local shadow = apTextShadow(style)
    local color = (style == 'gray') and '#cfcfcf' or 'white'
    return string.format(
        '<div style="position:absolute;z-index:10;top:%s;left:%s;font-family:number;font-size:%s;color:%s;%s">%s</div>',
        top, left, fontSize, color, shadow, content
    )
end

-- 单个机制卡片(固定 250px 宽度)
local function renderMechanismCard(title, desc)
    title = escText(title or '')
    local d = tostring(desc or '')
    if d == '' then
        d = '暂无详细说明'
    end
    -- 展开词典说明中的模板
    local body = expandWikitext(d)

    local dhtml = {}
    table.insert(dhtml, '<div class="mechanism-card" style="width: 250px;">')
    table.insert(dhtml, '<div style="width: 266px; height: 2px; background-color: #f2ba02;"></div>')
    table.insert(dhtml, '<div style="width: 100%; background-color: #343434; color: white; padding: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.3);  line-height: 1.6;">')
    table.insert(dhtml, '<div style="font-weight: bold;">' .. title .. '</div>')
    table.insert(dhtml, '<div>' .. body .. '</div>')
    table.insert(dhtml, '</div>')
    table.insert(dhtml, '</div>')
    return table.concat(dhtml, '')
end

-- 右侧词典说明容器
local function renderDictMechanisms(dictEntries)
    if type(dictEntries) ~= 'table' or #dictEntries == 0 then return '' end

    local html = {}
    -- 固定宽度 250px
    table.insert(html, '<div class="dict-mechanisms" style="display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin-left:10px;width:250px;flex:0 0 250px;overflow:visible;">')
    for _, entry in ipairs(dictEntries) do
        table.insert(html, renderMechanismCard(entry.key, entry.desc))
    end
    table.insert(html, '</div>')
    return table.concat(html, '')
end

function p.render(cardInfo, subCardInfo)
    local dictDisplay = dictSpanFromTokens(cardInfo.dictTokens, cardInfo.dictColor)
    local cardId = generateUniqueId(cardInfo)
    local html = {}
    
    -- 渲染小卡片
    table.insert(html, p.renderSmallCard(cardInfo, cardId, dictDisplay))
    -- 渲染模态框(单独输出)
    table.insert(html, p.renderModal(cardInfo, cardId, dictDisplay, subCardInfo))
    
    return table.concat(html, '')
end

function p.renderSmallCard(cardInfo, cardId, dictDisplay)
    local html = {}
    local apDisplay = cardInfo.apText or ''
    local nameColor = rarityNameColor(cardInfo.rarity)

    table.insert(html, '<div class="card-small-wrapper" data-card-id="' .. escText(cardId) .. '" style="display:inline-block;vertical-align:top;position:relative;width:160px;height:230px;overflow:hidden;cursor:pointer;">')

    table.insert(html, renderArtLayer(cardInfo, 160))
    table.insert(html, renderRarityBar(cardInfo, 160))
    table.insert(html, renderOverlayLayers(cardInfo, 160))

    table.insert(html, renderApDiv(apDisplay, '5px', '25px', '36px', cardInfo.apStyle or 'blue'))
    table.insert(html, renderApDiv('—', '23px', '23px', '32px', cardInfo.apStyle or 'blue'))

    table.insert(html, '<div style="position:absolute;z-index:10;top:12px;left:50px;color:' .. nameColor .. ';font-size:18px">' .. escText(cardInfo.displayTitleShort or cardInfo.displayTitle or cardInfo.cardName) .. '</div>')

    table.insert(html, '<div style="position:absolute;z-index:10;top:33px;left:49px;">[[File:card_type_' .. escFile(cardInfo.cardType) .. '.png|18px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:32px;left:67px;font-size:14px;color:white">' .. escText(cardInfo.cardType) .. '</div>')

    table.insert(html, '<div style="position:absolute;z-index:10;top:110px;left:20px;width:130px;height:115px;color:white;text-align:center;font-size:13px;line-height:15px;">')
    local smallContent = expandWikitext((dictDisplay or '') .. (cardInfo.desc or ''))
    table.insert(html, '<div class="scroll-text"><div class="scroll-text-content">' .. smallContent .. '</div></div>')
    table.insert(html, '</div>')
    table.insert(html, '</div>')
    
    return table.concat(html, '')
end

-- 新增:独立的模态框渲染函数
function p.renderModal(cardInfo, cardId, dictDisplay, subCardInfos)
    local html = {}
    local apDisplay = cardInfo.apText or ''
    local nameColor = rarityNameColor(cardInfo.rarity)

    table.insert(html, '<div id="' .. escText(cardId) .. '-modal" class="card-modal" style="display:none;position:fixed;z-index:9999;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.8);">')
    table.insert(html, '<div class="modal-close-button" style="position:fixed;top:20px;right:20px;z-index:10001;width:40px;height:40px;background:rgba(255,255,255,0.2);border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all 0.3s;">')
    table.insert(html, '<span style="color:white;font-size:24px;line-height:1;">×</span>')
    table.insert(html, '</div>')

    table.insert(html, '<div class="card-modal-inner" style="height:100vh;display:flex;align-items:center;justify-content:center;">')
    table.insert(html, '<div class="original-card-view" style="display:flex;align-items:flex-start;justify-content:center;gap:10px;flex-wrap:wrap;">')

    -- 左侧:衍生卡牌
    if subCardInfos and #subCardInfos > 0 then
        table.insert(html, '<div class="ocv-col-left" style="display:flex;flex-direction:column;align-items:center;gap:10px;max-width:240px;">')
        table.insert(html, p.renderSubCard(subCardInfos[1]))
        if #subCardInfos > 1 then
            table.insert(html, '<div class="subcards-button" style="display:inline-block;padding:10px 10px;background:linear-gradient(135deg,#6fd8fe 0%,#4da6cc 100%);color:white;font-size:18px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">查看所有衍生卡牌</div>')
        end
        table.insert(html, '</div>')
    end

    -- 中间:放大卡片
    table.insert(html, '<div class="ocv-col-center" style="display:flex;flex-direction:column;align-items:center;gap:10px;max-width:320px;">')
    table.insert(html, '<div style="display:inline-block;vertical-align:top;position:relative;width:320px;height:460px;overflow:hidden;">')
    table.insert(html, renderArtLayer(cardInfo, 320))
    table.insert(html, renderRarityBar(cardInfo, 320))
    table.insert(html, renderOverlayLayers(cardInfo, 320))

    table.insert(html, renderApDiv(apDisplay, '18px', '45px', '58px', cardInfo.apStyle or 'blue'))
    table.insert(html, renderApDiv('__', '48px', '40px', '32px', cardInfo.apStyle or 'blue'))

    table.insert(html, '<div style="position:absolute;z-index:10;top:28px;left:80px;color:' .. nameColor .. ';font-size:32px">' .. escText(cardInfo.displayTitleShort or cardInfo.displayTitle or cardInfo.cardName) .. '</div>')

    table.insert(html, '<div style="position:absolute;z-index:10;top:68px;left:79px;">[[File:card_type_' .. escFile(cardInfo.cardType) .. '.png|24px|link=]]</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:65px;left:105px;font-size:20px;color:white">' .. escText(cardInfo.cardType) .. '</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:250px;left:30px;width:300px;height:210px;color:white;text-align:center;font-size:28px;line-height:30px;">')
    local largeContent = expandWikitext((dictDisplay or '') .. (cardInfo.desc or ''))
    table.insert(html, '<div class="scroll-text" style="width:280px;height:200px"><div class="scroll-text-content">' .. largeContent .. '</div></div>')
    table.insert(html, '</div>')
    table.insert(html, '</div>')

    if cardInfo.hasInspiration or cardInfo.hasGodInspiration then
        table.insert(html, '<div class="variant-buttons" style="display:flex;gap:10px;align-items:center;justify-content:center;flex-wrap:wrap;">')
        if cardInfo.hasInspiration then
            table.insert(html, '<div class="inspiration-button" style="display:inline-block;padding:10px 10px;background:linear-gradient(135deg,#6fd8fe 0%,#4da6cc 100%);color:white;font-size:18px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">灵光一闪</div>')
        end
        if cardInfo.hasGodInspiration then
            table.insert(html, '<div class="god-inspiration-button" style="display:inline-block;padding:10px 10px;background:linear-gradient(135deg,#ffd36a 0%,#e6a600 100%);color:white;font-size:18px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">神光一闪</div>')
        end
        table.insert(html, '</div>')
    end
    table.insert(html, '</div>') -- 结束中间列

    -- 右侧:词典机制说明
    table.insert(html, '<div class="ocv-col-right" style="display:flex;flex-direction:column;align-items:flex-start;gap:10px;max-width:250px;">')
    table.insert(html, renderDictMechanisms(cardInfo.dictEntries))
    table.insert(html, '</div>')

    table.insert(html, '</div>') -- original-card-view
    table.insert(html, '</div>') -- card-modal-inner

    -- 其他视图
    if subCardInfos and #subCardInfos > 1 then
        table.insert(html, p.renderSubcardsView(subCardInfos))
    end

    if cardInfo.hasInspiration and cardInfo.inspirationVariants then
        table.insert(html, '<div class="inspiration-view" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;flex-direction:column;align-items:center;justify-content:center;">')
        table.insert(html, '<div class="back-to-card-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回卡牌</div>')
        table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">灵光一闪</div>')
        table.insert(html, '<div class="inspiration-cards-wrapper" style="display:flex;gap:10px;justify-content:center;flex-wrap:wrap;max-width:90vw;align-items:flex-start;">')
        for i, variantInfo in ipairs(cardInfo.inspirationVariants) do
            table.insert(html, p.renderInspirationVariant(variantInfo, i))
        end
        table.insert(html, '</div>')
        table.insert(html, '</div>')
        for i, variantInfo in ipairs(cardInfo.inspirationVariants) do
            if variantInfo.subCards and #variantInfo.subCards > 0 then
                table.insert(html, p.renderInspirationSubcardsView(variantInfo, i))
                for j, subCardInfo in ipairs(variantInfo.subCards) do
                    if subCardInfo.subCards and #subCardInfo.subCards > 0 then
                        table.insert(html, p.renderInspirationNestedSubcardsView(variantInfo, i, subCardInfo, j))
                    end
                end
            end
        end
    end

    if cardInfo.hasGodInspiration and cardInfo.godInspirationGroups and cardInfo.godInspirationGroupOrder then
        table.insert(html, '<div class="god-inspiration-view" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;flex-direction:column;align-items:center;justify-content:flex-start;">')
        table.insert(html, '<div class="back-to-card-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回卡牌</div>')
        table.insert(html, '<div style="color:white;font-size:24px;margin-top: 24px;">神光一闪</div>')
        for _, groupName in ipairs(cardInfo.godInspirationGroupOrder) do
            local groupList = cardInfo.godInspirationGroups[groupName]
            if groupList and #groupList > 0 then
                table.insert(html, '<div style="color:#ffd36a;font-size:20px;margin:8px 0;">' .. escText(groupName) .. '</div>')
                table.insert(html, '<div class="god-inspiration-row" style="display:flex;gap:10px;justify-content:center;flex-wrap:nowrap;max-width:90vw;">')
                for _, variantInfo in ipairs(groupList) do
                    table.insert(html, p.renderGodVariantCard(variantInfo))
                end
                table.insert(html, '</div>')
            end
        end
        table.insert(html, '</div>')
    end

    table.insert(html, '</div>') -- card-modal
    return table.concat(html, '')
end

function p.renderSubcardsView(subCardInfos)
    local html = {}
    table.insert(html, '<div class="subcards-view" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;flex-direction:column;align-items:center;justify-content:center;">')
    table.insert(html, '<div class="back-to-card-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回所有衍生</div>')
    table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">衍生卡牌</div>')
    table.insert(html, '<div class="subcards-wrapper" style="display:flex;gap:10px;justify-content:center;flex-wrap:wrap;max-width:90vw;">')
    for i, subCardInfo in ipairs(subCardInfos) do
        table.insert(html, '<div style="display:flex;flex-direction:column;align-items:center;gap:10px;">')
        table.insert(html, p.renderSubCard(subCardInfo))
        if subCardInfo.subCards and #subCardInfo.subCards > 0 then
            table.insert(html, '<div class="view-nested-subcards-button" data-subcard-index="' .. i .. '" style="display:inline-block;padding:10px 20px;background:linear-gradient(135deg,#ffa500 0%,#cc8400 100%);color:white;font-size:15px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">查看衍生卡牌</div>')
        end
        table.insert(html, '</div>')
    end
    table.insert(html, '</div>')
    table.insert(html, '</div>')
    for i, subCardInfo in ipairs(subCardInfos) do
        if subCardInfo.subCards and #subCardInfo.subCards > 0 then
            table.insert(html, p.renderNestedSubcardsView(subCardInfo, i))
        end
    end
    return table.concat(html, '')
end

function p.renderNestedSubcardsView(parentCardInfo, parentIndex)
    local html = {}
    table.insert(html, '<div class="nested-subcards-view" data-subcard-index="' .. parentIndex .. '" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;flex-direction:column;align-items:center;justify-content:center;">')
    table.insert(html, '<div class="back-to-subcards-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回所有衍生</div>')
    table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">' .. escText(parentCardInfo.displayTitle or parentCardInfo.cardName) .. ' 的衍生卡牌</div>')
    table.insert(html, '<div class="nested-subcards-wrapper" style="display:flex;gap:10px;justify-content:center;flex-wrap:wrap;max-width:90vw;">')
    for _, nestedCardInfo in ipairs(parentCardInfo.subCards) do
        table.insert(html, '<div style="display:flex;flex-direction:column;align-items:center;gap:10px;">')
        table.insert(html, p.renderSubCard(nestedCardInfo))
        table.insert(html, '</div>')
    end
    table.insert(html, '</div>')
    table.insert(html, '</div>')
    return table.concat(html, '')
end

function p.renderInspirationVariant(variantInfo, index)
    local html = {}
    local dictDisplay = dictSpanFromTokens(variantInfo.dictTokens, variantInfo.dictColor)
    local apDisplay = variantInfo.apText or ''
    local nameColor = rarityNameColor(variantInfo.rarity)

    table.insert(html, '<div class="inspiration-variant" style="display:flex;flex-direction:column;align-items:center;gap:8px;width:240px;">')
    table.insert(html, '<div class="inspiration-variant-card" style="display:inline-block;vertical-align:top;position:relative;width:240px;height:345px;overflow:hidden;">')

    table.insert(html, renderArtLayer(variantInfo, 240))
    table.insert(html, renderRarityBar(variantInfo, 240))
    table.insert(html, renderOverlayLayers(variantInfo, 240))

    table.insert(html, renderApDiv(apDisplay, '8px', '31px', '54px', variantInfo.apStyle or 'blue'))
    table.insert(html, renderApDiv('—', '46px', '32px', '32px', variantInfo.apStyle or 'blue'))

    table.insert(html, '<div style="position:absolute;z-index:10;top:18px;left:64px;color:' .. nameColor .. ';font-size:24px">' .. escText(variantInfo.displayTitleShort or variantInfo.displayTitle or variantInfo.cardName) .. '</div>')

    table.insert(html, '<div style="position:absolute;z-index:10;top:50px;left:63px;">[[File:card_type_' .. escFile(variantInfo.cardType) .. '.png|24px]]</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:49px;left:90px;font-size:20px;color:white">' .. escText(variantInfo.cardType) .. '</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:165px;left:20px;width:220px;height:175px;color:white;text-align:center;font-size:18px;line-height:20px;">')
    local inspContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
    table.insert(html, '<div class="scroll-text" style="width:212px;height:170px"><div class="scroll-text-content">' .. inspContent .. '</div></div>')
    table.insert(html, '</div>')
    table.insert(html, '</div>')

    if variantInfo.subCards and #variantInfo.subCards > 0 then
        table.insert(html, '<div class="inspiration-subcards-button" data-variant-index="' .. index .. '" style="display:inline-block;padding:10px 20px;background:linear-gradient(135deg,#6fd8fe 0%,#4da6cc 100%);color:white;font-size:15px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">查看衍生卡牌</div>')
    end

    table.insert(html, '</div>')
    return table.concat(html, '')
end

function p.renderInspirationSubcardsView(variantInfo, index)
    local html = {}
    table.insert(html, '<div class="inspiration-subcards-view" data-variant-index="' .. index .. '" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;flex-direction:column;align-items:center;justify-content:center;">')
    table.insert(html, '<div class="back-to-inspiration-button" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回灵光一闪</div>')
    table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">' .. escText(variantInfo.displayTitle or variantInfo.cardName) .. '的衍生卡牌</div>')
    table.insert(html, '<div class="inspiration-subcards-wrapper" style="display:flex;gap:10px;justify-content:center;flex-wrap:wrap;max-width:90vw;">')
    for j, subCardInfo in ipairs(variantInfo.subCards) do
        table.insert(html, '<div style="display:flex;flex-direction:column;align-items:center;gap:10px;">')
        table.insert(html, p.renderSubCard(subCardInfo))
        if subCardInfo.subCards and #subCardInfo.subCards > 0 then
            table.insert(html, '<div class="view-inspiration-nested-subcards-button" data-variant-index="' .. index .. '" data-subcard-index="' .. j .. '" style="display:inline-block;padding:10px 20px;background:linear-gradient(135deg,#ffa500 0%,#cc8400 100%);color:white;font-size:15px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">查看衍生卡牌</div>')
        end
        table.insert(html, '</div>')
    end
    table.insert(html, '</div>')
    table.insert(html, '</div>')
    return table.concat(html, '')
end

function p.renderInspirationNestedSubcardsView(variantInfo, variantIndex, parentSubCardInfo, parentSubIndex)
    local html = {}
    table.insert(html, '<div class="inspiration-nested-subcards-view" data-variant-index="' .. variantIndex .. '" data-subcard-index="' .. parentSubIndex .. '" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;flex-direction:column;align-items:center;justify-content:center;">')
    table.insert(html, '<div class="back-to-inspiration-subcards-button" data-variant-index="' .. variantIndex .. '" style="position:fixed;top:20px;left:20px;z-index:10001;padding:10px 25px;background:linear-gradient(135deg,#ff6b6b 0%,#cc5555 100%);color:white;font-size:16px;font-weight:bold;border-radius:8px;cursor:pointer;box-shadow:0 4px 6px rgba(0,0,0,0.3);transition:all 0.3s;user-select:none;">← 返回灵光一闪的衍生</div>')
    table.insert(html, '<div style="color:white;font-size:24px;margin-bottom:20px;">' .. escText(parentSubCardInfo.displayTitle or parentSubCardInfo.cardName) .. ' 的衍生卡牌</div>')
    table.insert(html, '<div class="inspiration-nested-subcards-wrapper" style="display:flex;gap:10px;justify-content:center;flex-wrap:wrap;max-width:90vw;">')
    for _, nestedCardInfo in ipairs(parentSubCardInfo.subCards or {}) do
        table.insert(html, '<div style="display:flex;flex-direction:column;align-items:center;gap:10px;">')
        table.insert(html, p.renderSubCard(nestedCardInfo))
        table.insert(html, '</div>')
    end
    table.insert(html, '</div>')
    table.insert(html, '</div>')
    return table.concat(html, '')
end

function p.renderGodVariantCard(variantInfo)
    local html = {}
    local dictDisplay = dictSpanFromTokens(variantInfo.dictTokens, variantInfo.dictColor)
    local apDisplay = variantInfo.apText or ''
    local nameColor = rarityNameColor(variantInfo.rarity)

    table.insert(html, '<div class="god-variant-card" style="display:inline-block;vertical-align:top;position:relative;width:240px;height:345px;overflow:hidden;">')

    table.insert(html, renderArtLayer(variantInfo, 240))
    table.insert(html, renderRarityBar(variantInfo, 240))
    table.insert(html, renderOverlayLayers(variantInfo, 240))

    table.insert(html, renderApDiv(apDisplay, '8px', '31px', '54px', variantInfo.apStyle or 'blue'))
    table.insert(html, renderApDiv('—', '46px', '32px', '32px', variantInfo.apStyle or 'blue'))

    table.insert(html, '<div style="position:absolute;z-index:10;top:18px;left:64px;color:' .. nameColor .. ';font-size:24px">' .. escText(variantInfo.displayTitleShort or variantInfo.displayTitle or variantInfo.cardName) .. '</div>')

    table.insert(html, '<div style="position:absolute;z-index:10;top:50px;left:63px;">[[File:card_type_' .. escFile(variantInfo.cardType) .. '.png|24px]]</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:49px;left:90px;font-size:20px;color:white">' .. escText(variantInfo.cardType) .. '</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:165px;left:20px;width:220px;height:175px;color:white;text-align:center;font-size:18px;line-height:20px;">')
    local godContent = expandWikitext((dictDisplay or '') .. (variantInfo.desc or ''))
    table.insert(html, '<div class="scroll-text" style="width:212px;height:170px"><div class="scroll-text-content">' .. godContent .. '</div></div>')
    table.insert(html, '</div>')
    table.insert(html, '</div>')
    return table.concat(html, '')
end

function p.renderSubCard(subCardInfo)
    local html = {}
    local dictDisplay = dictSpanFromTokens(subCardInfo.dictTokens, subCardInfo.dictColor)
    local apDisplay = subCardInfo.apText or ''
    local nameColor = rarityNameColor(subCardInfo.rarity)

    table.insert(html, '<div style="display:inline-block;vertical-align:top;position:relative;width:240px;height:345px;overflow:hidden;">')

    table.insert(html, renderArtLayer(subCardInfo, 240))
    table.insert(html, renderRarityBar(subCardInfo, 240))
    table.insert(html, renderOverlayLayers(subCardInfo, 240))

    table.insert(html, renderApDiv(apDisplay, '8px', '31px', '54px', subCardInfo.apStyle or 'blue'))
    table.insert(html, renderApDiv('—', '46px', '32px', '38px', subCardInfo.apStyle or 'blue'))

    table.insert(html, '<div style="position:absolute;z-index:10;top:18px;left:64px;color:' .. nameColor .. ';font-size:24px">' .. escText(subCardInfo.displayTitleShort or subCardInfo.displayTitle or subCardInfo.cardName) .. '</div>')

    table.insert(html, '<div style="position:absolute;z-index:10;top:50px;left:63px;">[[File:card_type_' .. escFile(subCardInfo.cardType) .. '.png|24px]]</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:49px;left:90px;font-size:20px;color:white">' .. escText(subCardInfo.cardType) .. '</div>')
    table.insert(html, '<div style="position:absolute;z-index:10;top:165px;left:20px;width:220px;height:175px;color:white;text-align:center;font-size:18px;line-height:20px;">')
    local subContent = expandWikitext((dictDisplay or '') .. (subCardInfo.desc or ''))
    table.insert(html, '<div class="scroll-text" style="width:212px;height:170px"><div class="scroll-text-content">' .. subContent .. '</div></div>')
    table.insert(html, '</div>')
    table.insert(html, '</div>')
    return table.concat(html, '')
end

return p