risum 모듈 — RISU modules[] — 기능 확장
조회 451 · 2025-11-29
참고함
{{char}}을 분석하는 TV Tropes 를 보자
챗챈 스코어:
불법 개조판
️
나무위키 모듈
INSPO v1
INSPO는 봇의 원형(Archetype), 클리셰(trope), 대중매체/현실 속 '서사적 쌍둥이' 들에 대한 간단한 레포트를 출력하는 모듈이에요.
그리고 그게 전부읾
사용법
1. 채팅방에서 INSPO 모듈을 활성화하세요
2. (권장사항) 프롬에서 OOC 모드를 켜세요
3. /INSPO 또는 /inspo라고 채팅을 보내세요
추천 모델
정보량이 방대한 제미니 프로 3.0
그러나 다른 모델도 일정 능지 이상이면 잘 나오긴 핢
리퀘스트가 메인 모델로 들어가니 주의하세요
참고사항
1. OAI 토크나이저 기준 678토큰짜리 지시가 들어갑니다. 그냥 모양 예쁘게 잡은 로어북일 뿐이라 토큰 절약하고 싶으면 지시만 따 와서 딸깍하면 됢,,,
프롬
OOC: Halting all roleplay. Based on the provided profile of {{char}}, perform a deep character analysis.
* Analysis Guidelines
1. Genre & Tone:
- Genre/Tone: Define the narrative setting and specific sub-genre.
- The Archetype: Define their classic role (e.g., The Reluctant Hero, The Femme Fatale) and explain how they fit or break this mold.
2. Tropes (Reference+Cross-check
tvtropes.org
):
- [CRITICAL: Use the EXACT, standardized trope names as they appear in the TV Tropes database headers to ensure valid linking. Avoid variations or unnecessary articles(e.g., use "Stepford Smiler", NOT "The Stepford Smiler").]
- The Essentials: Identify 3 tropes that best describe {{char}}. These should be the absolute most defining tropes if you had to summarize his entire existence with only three.
- The Subversion: Identify 1 trope that the character subverts or defies.
- The Nemesis: Identify 3 tropes that act as natural enemies or philosophical opposites to {{char}}. These represent the narrative forces, personality types, or ideologies that {{char}} would inevitably clash with.
3. Inspirations (Reference IMDb, Goodreads, MyAnimeList, Comic Vine, IBDB, IGDB, AllMusic, Wikipedia, TV Tropes, Fandom Wikis, PDB, Page Six, Vanity Fair, etc.):
- Identify 3 "Spiritual Successors" across all spectrums (Fiction, Mythology, History, Real Life Icons). Focus on matching the exact "vibe," controversy, or psychological profile.
* Output Rules
- Do NOT include Markdown headers, bolding, bullet points or any conversational text.
- Output ONLY the XML code and ensure all tags are correctly closed.
- For every <N> tag, append the probability (0.0–1.0) in parentheses to the name before the closing tag.
* XML Template
<GT><G>[Specific Genre & Sub-genre]: [Detailed Explanation]</G><A>[Archetype]: [Analysis]</A></GT><TR><E1><N>[Trope 1]</N><D>[Explanation]</D></E1><E2><N>[Trope 2]</N><D>[Explanation]</D></E2><E3><N>[Trope 3]</N><D>[Explanation]</D></E3><S><N>[Subverted Trope]</N><D>[Explanation]</D></S><NT1><N>[Nemesis 1]</N><D>[Explanation]</D></NT1><NT2><N>[Nemesis 2]</N><D>[Explanation]</D></NT2><NT3><N>[Nemesis 3]</N><D>[Explanation]</D></NT3></TR><IN><F1><N>[Character] ([Source])</N><M>[Medium]</M><C>[Analysis]</C></F1><F2><N>[Character] ([Source])</N><M>[Medium]</M><C>[Analysis]</C></F2><F3><N>[Character] ([Source])</N><M>[Medium]</M><C>[Analysis]</C></F3></IN>
2. 컨텍 있는 상태에서 넣어도 되지만 컨텍 오염은 일어나므로 채팅방 복제해서 진행하는 것을 권고
3. Tropes에 걸려 있는 링크들은 클릭하면 해당 trope의
tvtropes.org
페이지로 이동해요. 꽤 자주 없는 페이지로 이동하긴 하는데 이건 내가 어떻게 할 수가 없슮
4. 글자 줄줄 나오면 찐빠이니 리롤
5. 형식은 멀쩡한데 내용이 이상하다면 루아 교정식에 잘못 걸렸을 가능성있읆,,,
레포트 항목 소개
1. 장르적 배경과 원형 (Genre & Archetype): 봇 주변의 세계가 가지는 장르, 그리고 그 안에서 부여받은 원형(Archetype)을 분석해요.
2. 트로프 분석 (Tropes Analysis): TV Tropes를 바탕으로 캐릭터의 클리셰를 분석해요.
The Essentials: 캐릭터의 존재를 정의하는 가장 핵심적인 3가지 속성.
The Subversion: 캐릭터가 비틀어버린 클리셰. 오른쪽의 노란 버튼을 누르면 펼쳐져요.
The Nemesis: 캐릭터와 필연적으로 충돌할 수밖에 없는 상극의 이념이나 성격 유형.
3. 영적 계승자들 (Spiritual Successors): 신화, 역사, 대중매체를 통틀어 해당 캐릭터와 심리적 프로파일이나 무드가 일치하는 인물들을 찾아봐요.
예시
프로톤
모바일 레이아웃 테스트 안해봤는데 너무졸려서 내일핢
추가하고 싶은 기능: {{char}} -> {{user}}로 바꿔주는 토글, 찾아볼 매체 범위 입력할 수 있는 입력칸,,,봇의 원형(Archetype), 클리셰(trope), 대중매체 속 '서사적 쌍둥이' 들에 대한 간단한 레포트를 출력하는 모듈
{
"name": "📋 INSPO V1",
"description": "봇의 원형(Archetype), 클리셰(trope), 대중매체 속 '서사적 쌍둥이' 들에 대한 간단한 레포트를 출력하는 모듈",
"id": "9fd9a767-b41e-4725-9869-19b755343c16",
"hideIcon": false,
"lorebook": [],
"regex": [
{
"comment": "명령어 대문자",
"in": "/INSPO",
"out": "OOC: Halting all roleplay. Based on the provided profile of {{char}}, perform a deep character analysis.\n\n* Analysis Guidelines\n1. Genre & Tone:\n - Genre/Tone: Define the narrative setting and specific sub-genre.\n - The Archetype: Define their classic role (e.g., The Reluctant Hero, The Femme Fatale) and explain how they fit or break this mold.\n2. Tropes (Reference+Cross-check tvtropes.org):\n - [CRITICAL: Use the EXACT, standardized trope names as they appear in the TV Tropes database headers to ensure valid linking. Avoid variations or unnecessary articles(e.g., use \"Stepford Smiler\", NOT \"The Stepford Smiler\").]\n - The Essentials: Identify 3 tropes that best describe {{char}}. These should be the absolute most defining tropes if you had to summarize his entire existence with only three.\n - The Subversion: Identify 1 trope that the character subverts or defies.\n - The Nemesis: Identify 3 tropes that act as natural enemies or philosophical opposites to {{char}}. These represent the narrative forces, personality types, or ideologies that {{char}} would inevitably clash with.\n3. Inspirations (Reference IMDb, Goodreads, MyAnimeList, Comic Vine, IBDB, IGDB, AllMusic, Wikipedia, TV Tropes, Fandom Wikis, PDB, Page Six, Vanity Fair, etc.):\n - Identify 3 \"Spiritual Successors\" across all spectrums (Fiction, Mythology, History, Real Life Icons). Focus on matching the exact \"vibe,\" controversy, or psychological profile.\n\n* Output Rules\n- Do NOT include Markdown headers, bolding, bullet points or any conversational text.\n- Output ONLY the XML code and ensure all tags are correctly closed.\n- For every <N> tag, append the probability (0.0–1.0) in parentheses to the name before the closing tag.\n\n* XML Template\n<GT><G>[Specific Genre & Sub-genre]: [Detailed Explanation]</G><A>[Archetype]: [Analysis]</A></GT><TR><E1><N>[Trope 1]</N><D>[Explanation]</D></E1><E2><N>[Trope 2]</N><D>[Explanation]</D></E2><E3><N>[Trope 3]</N><D>[Explanation]</D></E3><S><N>[Subverted Trope]</N><D>[Explanation]</D></S><NT1><N>[Nemesis 1]</N><D>[Explanation]</D></NT1><NT2><N>[Nemesis 2]</N><D>[Explanation]</D></NT2><NT3><N>[Nemesis 3]</N><D>[Explanation]</D></NT3></TR><IN><F1><N>[Character] (Source)</N><M>[Medium]</M><C>[Analysis]</C></F1><F2><N>[Character] (Source)</N><M>[Medium]</M><C>[Analysis]</C></F2><F3><N>[Character] (Source)</N><M>[Medium]</M><C>[Analysis]</C></F3></IN>",
"type": "editprocess",
"ableFlag": false
},
{
"comment": "명령어 소문자",
"in": "/inspo",
"out": "OOC: Halting all roleplay. Based on the provided profile of {{char}}, perform a deep character analysis.\n\n* Analysis Guidelines\n1. Genre & Tone:\n - Genre/Tone: Define the narrative setting and specific sub-genre.\n - The Archetype: Define their classic role (e.g., The Reluctant Hero, The Femme Fatale) and explain how they fit or break this mold.\n2. Tropes (Reference+Cross-check tvtropes.org):\n - [CRITICAL: Use the EXACT, standardized trope names as they appear in the TV Tropes database headers to ensure valid linking. Avoid variations or unnecessary articles(e.g., use \"Stepford Smiler\", NOT \"The Stepford Smiler\").]\n - The Essentials: Identify 3 tropes that best describe {{char}}. These should be the absolute most defining tropes if you had to summarize his entire existence with only three.\n - The Subversion: Identify 1 trope that the character subverts or defies.\n - The Nemesis: Identify 3 tropes that act as natural enemies or philosophical opposites to {{char}}. These represent the narrative forces, personality types, or ideologies that {{char}} would inevitably clash with.\n3. Inspirations (Reference IMDb, Goodreads, MyAnimeList, Comic Vine, IBDB, IGDB, AllMusic, Wikipedia, TV Tropes, Fandom Wikis, PDB, Page Six, Vanity Fair, etc.):\n - Identify 3 \"Spiritual Successors\" across all spectrums (Fiction, Mythology, History, Real Life Icons). Focus on matching the exact \"vibe,\" controversy, or psychological profile.\n\n* Output Rules\n- Do NOT include Markdown headers, bolding, bullet points or any conversational text.\n- Output ONLY the XML code and ensure all tags are correctly closed.\n- For every <N> tag, append the probability (0.0–1.0) in parentheses to the name before the closing tag.\n\n* XML Template\n<GT><G>[Specific Genre & Sub-genre]: [Detailed Explanation]</G><A>[Archetype]: [Analysis]</A></GT><TR><E1><N>[Trope 1]</N><D>[Explanation]</D></E1><E2><N>[Trope 2]</N><D>[Explanation]</D></E2><E3><N>[Trope 3]</N><D>[Explanation]</D></E3><S><N>[Subverted Trope]</N><D>[Explanation]</D></S><NT1><N>[Nemesis 1]</N><D>[Explanation]</D></NT1><NT2><N>[Nemesis 2]</N><D>[Explanation]</D></NT2><NT3><N>[Nemesis 3]</N><D>[Explanation]</D></NT3></TR><IN><F1><N>[Character] (Source)</N><M>[Medium]</M><C>[Analysis]</C></F1><F2><N>[Character] (Source)</N><M>[Medium]</M><C>[Analysis]</C></F2><F3><N>[Character] (Source)</N><M>[Medium]</M><C>[Analysis]</C></F3></IN>",
"type": "editprocess",
"ableFlag": false
}
],
"trigger": [
{
"comment": "",
"type": "start",
"conditions": [],
"effect": [
{
"type": "triggerlua",
"code": "local function stripMarkdown(text)\n if not text then return \"\" end\n text = text:gsub(\"```%w*%s*\", \"\"):gsub(\"```\", \"\")\n text = text:gsub(\"<%?xml.-%?>\", \"\")\n return text:match(\"^%s*(.-)%s*$\")\nend\n\n-- [[ NEW HELPER FUNCTION ]] --\n-- Removes patterns like (0.99), (1.0), (0.1) from text\nlocal function stripScores(text)\n if not text or text == \"-\" or text == \"\" then return text end\n return text:gsub(\"%s*%(%s*%d+%.%d+%s*%)\", \"\")\nend\n\nlocal function cleanOuterBrackets(text)\n if not text or text == \"-\" or text == \"\" then return text end\n\n local function strip(s)\n if not s then return \"\" end\n local t = s:match(\"^%s*(.-)%s*$\")\n if t:sub(1, 1) == \"[\" and t:sub(-1) == \"]\" then\n return t:sub(2, -2)\n end\n return t\n end\n\n local colonIndex = text:find(\":\")\n\n if colonIndex then\n local leftPart = text:sub(1, colonIndex - 1)\n local rightPart = text:sub(colonIndex + 1)\n return strip(leftPart) .. \": \" .. strip(rightPart)\n else\n return strip(text)\n end\nend\n\nlocal function extractTag(text, tag)\n if not text or text == \"\" or text == \"-\" then return \"-\" end\n local lowerText = text:lower()\n local lowerTag = tag:lower()\n local s, e = lowerText:find(\"<%s*\" .. lowerTag .. \"[%s>]\")\n if not s then return \"-\" end\n local _, e_close = lowerText:find(\">\", s)\n if not e_close then return \"-\" end\n local endPattern = \"<%s*/%s*\" .. lowerTag .. \"%s*>\"\n local s2, _ = lowerText:find(endPattern, e_close + 1)\n if not s2 then return \"-\" end\n return text:sub(e_close + 1, s2 - 1)\nend\n\nlocal function parseNameAndSource(text)\n if not text or text == \"-\" or text == \"\" then return \"-\", nil end\n\n -- 1. Strip Scores (Reuse the helper)\n text = stripScores(text)\n\n -- 2. Standard parsing\n local name, source = text:match(\"^(.-)%s*([%(%[].-[%)%]])$\")\n if not name then \n name = text\n source = nil \n else\n source = source:gsub(\"^[%(%[]\", \"\"):gsub(\"[%)%]]$\", \"\")\n end\n name = name:gsub(\"%*\", \"\"):match(\"^%s*(.-)%s*$\")\n return cleanOuterBrackets(name), source\nend\n\nlocal function makeLink(text)\n if not text or text == \"\" or text == \"-\" then return text end\n local clean_text = text:gsub(\"[%[%]]\", \"\") \n local url_slug = clean_text:gsub(\"%s+\", \"\"):gsub(\"[^%w]\", \"\")\n return '<a href=\"https://tvtropes.org/pmwiki/pmwiki.php/Main/' .. url_slug .. '\" target=\"_blank\" style=\"text-decoration:none; color:#2c3e50; border-bottom:1px solid #ccc; font-weight:bold;\">' .. text .. '</a>'\nend\n\nlocal function formatSource(src)\n if src and src ~= \"\" then \n return '<span style=\"color:#7f8c8d; font-style:italic; font-size:0.9em;\"> from ' .. src .. '</span>' \n else \n return '' \n end\nend\n\nlocal function logActive()\n print(\">> [System] Inspo Module Active\")\nend\n\n-- =========================================================\n-- Main Logic\n-- =========================================================\n\nfunction onOutput(triggerId)\n logActive()\n \n local success, err = pcall(function()\n local rawContent = getCharacterLastMessage(triggerId)\n if not rawContent then return end\n local content = stripMarkdown(rawContent)\n\n if not content:lower():find(\"<%s*gt[%s>]\") then return end\n\n -- 1. Data Parsing\n local gt_block = extractTag(content, \"GT\")\n local genre = cleanOuterBrackets(extractTag(gt_block, \"G\"))\n \n -- [[ UPDATED: Strip scores from Archetype (A) ]]\n local archetype = cleanOuterBrackets(stripScores(extractTag(gt_block, \"A\")))\n \n local tr_block = extractTag(content, \"TR\")\n \n local function processTropeString(raw_str)\n if raw_str == \"-\" or raw_str == \"\" then return \"-\" end\n local parts = {}\n for part in string.gmatch(raw_str, \"[^/]+\") do\n local trimmed = cleanOuterBrackets(part)\n if trimmed and trimmed ~= \"\" then\n local name, source = parseNameAndSource(trimmed)\n local linkedName = makeLink(name)\n if source then\n table.insert(parts, linkedName .. \" (\" .. source .. \")\")\n else\n table.insert(parts, linkedName)\n end\n end\n end\n if #parts > 0 then return table.concat(parts, \" / \") else return \"-\" end\n end\n\n local function getTropeData(block_content)\n local raw_n = extractTag(block_content, \"N\")\n -- [[ UPDATED: Strip scores from Description (D) ]]\n local d = cleanOuterBrackets(stripScores(extractTag(block_content, \"D\")))\n return processTropeString(raw_n), d\n end\n \n local e1_n, e1_d = getTropeData(extractTag(tr_block, \"E1\"))\n local e2_n, e2_d = getTropeData(extractTag(tr_block, \"E2\"))\n local e3_n, e3_d = getTropeData(extractTag(tr_block, \"E3\"))\n \n local s_block = extractTag(tr_block, \"S\")\n local s_n = processTropeString(extractTag(s_block, \"N\"))\n -- [[ UPDATED: Strip scores from Subversion Description (D) ]]\n local s_d = cleanOuterBrackets(stripScores(extractTag(s_block, \"D\")))\n \n local nt1_n, nt1_d = getTropeData(extractTag(tr_block, \"NT1\"))\n local nt2_n, nt2_d = getTropeData(extractTag(tr_block, \"NT2\"))\n local nt3_n, nt3_d = getTropeData(extractTag(tr_block, \"NT3\"))\n\n local in_block = extractTag(content, \"IN\")\n local function getInfData(tag)\n local block = extractTag(in_block, tag)\n if block == \"-\" then return {n=\"-\", m=\"-\", c=\"-\", src=\"\"} end\n local raw = extractTag(block, \"N\")\n local n, src = parseNameAndSource(raw)\n return {\n n = n or \"-\", src = src or \"\",\n m = cleanOuterBrackets(extractTag(block, \"M\")),\n -- Note: \"C\" usually implies context/comment, but if you see scores here, \n -- you can wrap this in stripScores(...) too. I left it as is for now.\n c = cleanOuterBrackets(extractTag(block, \"C\"))\n }\n end\n\n local f1 = getInfData(\"F1\")\n local f2 = getInfData(\"F2\")\n local f3 = getInfData(\"F3\")\n \n local f1_src_html = formatSource(f1.src)\n local f2_src_html = formatSource(f2.src)\n local f3_src_html = formatSource(f3.src)\n\n -- -----------------------------------------------------\n -- Final Render HTML\n -- -----------------------------------------------------\n local html_card = table.concat({\n [[<div class=\"ra-report-card\">]],\n [[<div class=\"ra-report-header\">]],\n [[<div class=\"ra-header-text\">]],\n [[<div class=\"ra-confidential\">INSPO MODULE ANALYSIS</div>]],\n [[<div class=\"ra-subject\">SUBJECT: <span class=\"char-name\">{{char}}</span></div>]],\n [[</div>]],\n [[</div>]],\n\n [[<div class=\"ra-report-body\">]],\n -- Meta\n [[<div class=\"ra-meta-row\">]],\n [[<div class=\"ra-meta-card genre\">]],\n [[<div class=\"ra-meta-label\">GENRE</div>]],\n [[<div class=\"ra-meta-content\">]], genre, [[</div>]],\n [[</div>]],\n [[<div class=\"ra-meta-card archetype\">]],\n [[<div class=\"ra-meta-label\">ARCHETYPE</div>]],\n [[<div class=\"ra-meta-content\">]], archetype, [[</div>]],\n [[</div>]],\n [[</div>]],\n\n -- Split Row\n [[<div class=\"ra-split-row\">]],\n -- Core Tropes\n [[<div class=\"ra-col-half core\">]],\n [[<div class=\"ra-section-title core-title\">CORE TROPES</div>]],\n [[<div class=\"ra-item\">]], [[<div class=\"ra-item-head\">]], e1_n, [[</div>]], [[<div class=\"ra-item-desc\">]], e1_d, [[</div>]], [[</div>]],\n [[<div class=\"ra-item\">]], [[<div class=\"ra-item-head\">]], e2_n, [[</div>]], [[<div class=\"ra-item-desc\">]], e2_d, [[</div>]], [[</div>]],\n [[<div class=\"ra-item\">]], [[<div class=\"ra-item-head\">]], e3_n, [[</div>]], [[<div class=\"ra-item-desc\">]], e3_d, [[</div>]], [[</div>]],\n [[</div>]],\n \n [[<div class=\"ra-col-half nemesis\">]],\n [[<div class=\"ra-section-title nem-title\">NEMESIS / COUNTERS</div>]],\n [[<div class=\"ra-item\">]], [[<div class=\"ra-item-head\">]], nt1_n, [[</div>]], [[<div class=\"ra-item-desc\">]], nt1_d, [[</div>]], [[</div>]],\n [[<div class=\"ra-item\">]], [[<div class=\"ra-item-head\">]], nt2_n, [[</div>]], [[<div class=\"ra-item-desc\">]], nt2_d, [[</div>]], [[</div>]],\n [[<div class=\"ra-item\">]], [[<div class=\"ra-item-head\">]], nt3_n, [[</div>]], [[<div class=\"ra-item-desc\">]], nt3_d, [[</div>]], [[</div>]],\n [[</div>]],\n [[</div>]],\n\n -- Influences\n [[<div class=\"ra-section-block\">]],\n [[<div class=\"ra-section-title inf-title\">INFLUENCES & REFERENCES</div>]],\n [[<div class=\"ra-inf-list\">]],\n [[<div class=\"ra-inf-card\">]], [[<div class=\"ra-inf-meta\"><span class=\"medium-badge\">]], f1.m, [[</span>]], f1_src_html, [[</div>]], [[<div class=\"ra-item-head\">]], f1.n, [[</div>]], [[<div class=\"ra-item-desc\">]], f1.c, [[</div>]], [[</div>]],\n [[<div class=\"ra-inf-card\">]], [[<div class=\"ra-inf-meta\"><span class=\"medium-badge\">]], f2.m, [[</span>]], f2_src_html, [[</div>]], [[<div class=\"ra-item-head\">]], f2.n, [[</div>]], [[<div class=\"ra-item-desc\">]], f2.c, [[</div>]], [[</div>]],\n [[<div class=\"ra-inf-card\">]], [[<div class=\"ra-inf-meta\"><span class=\"medium-badge\">]], f3.m, [[</span>]], f3_src_html, [[</div>]], [[<div class=\"ra-item-head\">]], f3.n, [[</div>]], [[<div class=\"ra-item-desc\">]], f3.c, [[</div>]], [[</div>]],\n [[</div>]],\n [[</div>]],\n [[</div>]],\n\n -- Subversion (Sticky)\n [[<details class=\"ra-subversion-sticky\">]],\n [[<summary class=\"ra-sub-tab\">]], [[<span class=\"ra-tab-icon\">⚠</span>]], [[</summary>]],\n [[<div class=\"ra-sub-note\">]], [[<div class=\"ra-sub-title\">]], s_n, [[</div>]], [[<div class=\"ra-sub-desc\">]], s_d, [[</div>]], [[</div>]],\n [[</details>]],\n [[</div>]]\n })\n\n local chatLen = getChatLength(triggerId)\n setChat(triggerId, chatLen - 1, html_card)\n\n end)\n \n if not success then \n print(\"[InspoModule Error] \" .. tostring(err)) \n end\nend"
}
],
"lowLevelAccess": true
}
],
"lowLevelAccess": true,
"assets": [],
"backgroundEmbedding": "<style>\n/* --- Container --- */\n.ra-report-card {\n position: relative; \n font-family: 'Segoe UI', system-ui, sans-serif;\n background-color: #ffffff;\n color: #4a4a4a;\n border-radius: 8px;\n margin: 15px 0;\n box-shadow: 0 8px 24px rgba(0,0,0,0.08);\n overflow: hidden; /* Sticky note 처리를 위해 visible에서 hidden으로 변경 권장하나, 튀어나와야 한다면 visible 유지 */\n overflow: visible; \n max-width: 100%;\n border: 1px solid #eaeaea;\n}\n\n/* --- Header --- */\n.ra-report-header {\n background: linear-gradient(135deg, #2c3e50, #34495e);\n padding: 20px 25px;\n display: flex;\n align-items: center;\n border-radius: 8px 8px 0 0;\n}\n\n.ra-header-icon {\n width: 60px;\n height: 60px;\n margin-right: 20px;\n flex-shrink: 0;\n border-radius: 50%;\n overflow: hidden;\n border: 3px solid rgba(255,255,255,0.2);\n background: #fff;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.ra-header-icon img { width: 100%; height: 100%; object-fit: cover; }\n\n.ra-header-text { flex-grow: 1; }\n.ra-confidential { font-size: 0.75em; color: #bdc3c7; letter-spacing: 2px; font-weight: 600; text-transform: uppercase; }\n.ra-subject { font-size: 1.4em; color: #ecf0f1; font-weight: 300; margin-top: 4px; }\n.char-name { font-weight: 700; color: #fff; }\n\n/* --- Body Layout --- */\n.ra-report-body { padding: 25px; }\n\n/* 1. Meta Row (Genre | Archetype) - VERTICAL STACK */\n.ra-meta-row {\n display: flex;\n flex-direction: column; /* 무조건 세로 배치 */\n gap: 15px;\n margin-bottom: 25px;\n}\n\n.ra-meta-card {\n width: 100%; /* 전체 너비 사용 */\n padding: 15px 20px;\n border-radius: 6px;\n background: #f8f9fa;\n border-left-width: 5px;\n border-left-style: solid;\n display: flex;\n flex-direction: column;\n justify-content: center;\n box-sizing: border-box; /* 패딩 포함 너비 계산 */\n}\n\n/* Genre Box */\n.ra-meta-card.genre {\n background-color: #e8f5e9;\n border-left-color: #2ecc71;\n}\n/* Archetype Box */\n.ra-meta-card.archetype {\n background-color: #e3f2fd;\n border-left-color: #3498db;\n}\n\n.ra-meta-label {\n font-size: 0.75em;\n font-weight: 800;\n color: #7f8c8d;\n letter-spacing: 1px;\n margin-bottom: 5px;\n opacity: 0.8;\n}\n\n.ra-meta-content {\n font-size: 1.15em;\n font-weight: 700;\n color: #2c3e50;\n}\n\n/* 2. Split Row (Core Tropes | Nemesis) */\n.ra-split-row {\n display: flex;\n gap: 25px;\n margin-bottom: 25px;\n align-items: flex-start;\n}\n\n.ra-col-half { flex: 1; }\n\n.ra-section-title {\n font-size: 0.85em;\n font-weight: 800;\n color: #7f8c8d;\n border-bottom: 2px solid #ecf0f1;\n padding-bottom: 8px;\n margin-bottom: 15px;\n letter-spacing: 1px;\n}\n.core-title { color: #e67e22; border-color: #fce1c9; }\n.inf-title { color: #3498db; border-color: #d6eaf8; }\n.nem-title { color: #e74c3c; border-color: #fadbd8; }\n\n/* Items */\n.ra-item { margin-bottom: 12px; }\n.ra-item-head {\n font-weight: 700;\n color: #2c3e50;\n font-size: 1.05em;\n margin-bottom: 3px;\n}\n.ra-item-desc {\n font-size: 0.95em;\n color: #636e72;\n line-height: 1.4;\n}\n\n/* Nemesis Box */\n.ra-nemesis-box {\n background: #fff5f5;\n padding: 15px;\n border-radius: 6px;\n border-left: 4px solid #e74c3c;\n}\n.ra-item-inline {\n margin-bottom: 5px;\n font-size: 0.95em;\n color: #555;\n}\n\n/* 3. Influences (Vertical List) */\n.ra-section-block { margin-bottom: 10px; }\n.ra-inf-list {\n display: flex;\n flex-direction: column;\n gap: 15px;\n}\n\n.ra-inf-card {\n background: #fafafa;\n border: 1px solid #f1f1f1;\n border-radius: 6px;\n padding: 15px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.ra-inf-meta {\n font-size: 0.8em;\n margin-bottom: 8px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.medium-badge {\n background: #34495e;\n color: #fff;\n padding: 3px 8px;\n border-radius: 3px;\n font-weight: 600;\n font-size: 0.85em;\n}\n.source-text {\n color: #7f8c8d;\n font-style: italic;\n border-bottom: 1px solid #bdc3c7;\n}\n\n/* --- Subversion Sticky Note (Modified) --- */\n.ra-subversion-sticky {\n position: absolute;\n top: 60px;\n right: 0;\n z-index: 100;\n}\n\n.ra-sub-tab {\n list-style: none;\n background: #f1c40f;\n color: #7f6a00;\n /* 사이즈 축소 및 정사각형화 */\n width: 40px; \n height: 40px;\n border-radius: 8px 0 0 8px;\n cursor: pointer;\n font-weight: bold;\n \n /* Flex로 아이콘 중앙 정렬 */\n display: flex;\n justify-content: center;\n align-items: center;\n \n box-shadow: -2px 2px 5px rgba(0,0,0,0.1);\n border: 1px solid #e0b60b;\n border-right: none;\n \n position: absolute;\n right: 0;\n top: 0;\n \n /* 애니메이션 설정 */\n transform: translateX(0);\n transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275), background 0.2s;\n}\n\n/* Hover 시 튀어나오는 효과 */\n.ra-sub-tab:hover {\n transform: translateX(-8px); /* 왼쪽으로 툭 튀어나옴 */\n background: #f39c12;\n}\n\n.ra-sub-tab::-webkit-details-marker { display: none; }\n\n/* 탭 아이콘 스타일 */\n.ra-tab-icon { \n font-size: 1.5em; \n line-height: 1;\n margin: 0;\n}\n\n/* 내용 박스 */\n.ra-sub-note {\n position: absolute;\n right: 0;\n top: 0;\n width: 280px; /* 너비 살짝 조정 */\n background: #fff9c4;\n padding: 20px;\n box-shadow: -5px 5px 15px rgba(0,0,0,0.15);\n border-radius: 0 0 0 8px;\n border: 1px solid #e0b60b;\n display: none;\n z-index: 90;\n animation: slideIn 0.2s ease-out;\n}\n\n/* 열렸을 때 탭 위치 이동 */\n.ra-subversion-sticky[open] .ra-sub-tab {\n background: #e0b60b;\n right: 280px; /* 내용 박스 너비만큼 이동 */\n border-radius: 8px 0 0 8px;\n transform: translateX(0); /* 열리면 고정 */\n}\n\n.ra-subversion-sticky[open] .ra-sub-note {\n display: block;\n}\n\n.ra-sub-title {\n font-weight: 800;\n color: #d35400;\n margin-bottom: 8px;\n font-size: 1.1em;\n}\n.ra-sub-desc {\n font-size: 0.95em;\n line-height: 1.5;\n color: #5d4037;\n}\n\n@keyframes slideIn {\n from { opacity: 0; transform: translateX(20px); }\n to { opacity: 1; transform: translateX(0); }\n}\n\n/* Mobile Responsiveness */\n@media (max-width: 650px) {\n .ra-split-row { flex-direction: column; }\n .ra-col-half { width: 100%; }\n \n /* 모바일에서도 Subversion 위치 고정 (하단 이동 X) */\n .ra-subversion-sticky {\n position: absolute; /* 고정 */\n top: 100px;\n right: 0;\n margin-top: 0;\n }\n \n /* 모바일 탭 스타일 유지 */\n .ra-sub-tab {\n width: 40px;\n height: 40px;\n position: absolute;\n right: 0;\n }\n \n /* 모바일에서 내용 박스 스타일 */\n .ra-sub-note {\n width: 260px; /* 모바일 화면 고려하여 약간 축소 */\n }\n .ra-subversion-sticky[open] .ra-sub-tab {\n right: 260px;\n }\n}\n\n.trope-link {\n color: #2c3e50; \n text-decoration: none;\n border-bottom: 2px solid rgba(44, 62, 80, 0.2); \n transition: all 0.2s;\n font-weight: 700;\n}\n\n.trope-link:hover {\n color: #d35400; \n background-color: rgba(211, 84, 0, 0.1);\n border-bottom-color: #d35400;\n}\n</style>"
}