diff --git a/index.js b/index.js index b75cc5e..68864a1 100644 --- a/index.js +++ b/index.js @@ -41,7 +41,7 @@ let extensionSettings = { }, // Saved position for mobile FAB button userStats: { health: 100, - sustenance: 100, + satiety: 100, energy: 100, hygiene: 100, arousal: 0, @@ -177,7 +177,7 @@ function loadChatData() { // Reset to defaults if no data exists extensionSettings.userStats = { health: 100, - sustenance: 100, + satiety: 100, energy: 100, hygiene: 100, arousal: 0, @@ -1211,7 +1211,7 @@ function setupSettingsPopup() { // Reset stats to defaults and re-render extensionSettings.userStats = { health: 100, - sustenance: 100, + satiety: 100, energy: 100, hygiene: 100, arousal: 0, @@ -2231,7 +2231,7 @@ function generateTrackerInstructions(includeHtmlPrompt = true, includeContinuati // Only add tracker instructions if at least one tracker is enabled if (hasAnyTrackers) { // Universal instruction header - instructions += `\nYou must start your response with an appropriate update to the trackers in EXACTLY the same format as below, enclosed in separate Markdown code fences. Replace X with proper numbers and placeholders in [brackets] with in-world details ${userName} perceives about the current scene and the present characters. Consider the last trackers in the conversation (if they exist). Manage them accordingly; raise, lower, change, or keep the values unchanged based on the user's actions, the passage of time, and logical consequences:\n`; + instructions += `\nYou must start your response with an appropriate update to the trackers in EXACTLY the same format as below, enclosed in separate Markdown code fences. Replace X with proper numbers and placeholders in [brackets] with in-world details ${userName} perceives about the current scene and the present characters. Consider the last trackers in the conversation (if they exist). Manage them accordingly and realistically; raise, lower, change, or keep the values unchanged based on the user's actions, the passage of time, and logical consequences:\n`; // Add format specifications for each enabled tracker if (extensionSettings.showUserStats) { @@ -2239,7 +2239,7 @@ function generateTrackerInstructions(includeHtmlPrompt = true, includeContinuati instructions += `${userName}'s Stats\n`; instructions += '---\n'; instructions += '- Health: X%\n'; - instructions += '- Sustenance: X%\n'; + instructions += '- Satiety: X%\n'; instructions += '- Energy: X%\n'; instructions += '- Hygiene: X%\n'; instructions += '- Arousal: X%\n'; @@ -2319,7 +2319,7 @@ function generateContextualSummary() { const stats = extensionSettings.userStats; // console.log('[RPG Companion] Building stats summary with:', stats); summary += `${userName}'s Stats:\n`; - summary += `Condition: Health ${stats.health}%, Sustenance ${stats.sustenance}%, Energy ${stats.energy}%, Hygiene ${stats.hygiene}%, Arousal ${stats.arousal}% | ${stats.mood} ${stats.conditions}\n`; + summary += `Condition: Health ${stats.health}%, Satiety ${stats.satiety}%, Energy ${stats.energy}%, Hygiene ${stats.hygiene}%, Arousal ${stats.arousal}% | ${stats.mood} ${stats.conditions}\n`; if (stats.inventory && stats.inventory !== 'None') { summary += `Inventory: ${stats.inventory}\n`; } @@ -2675,7 +2675,7 @@ function parseUserStats(statsText) { try { // Extract percentages and mood/conditions const healthMatch = statsText.match(/Health:\s*(\d+)%/); - const sustenanceMatch = statsText.match(/Sustenance:\s*(\d+)%/); + const satietyMatch = statsText.match(/Satiety:\s*(\d+)%/); const energyMatch = statsText.match(/Energy:\s*(\d+)%/); const hygieneMatch = statsText.match(/Hygiene:\s*(\d+)%/); const arousalMatch = statsText.match(/Arousal:\s*(\d+)%/); @@ -2701,7 +2701,7 @@ function parseUserStats(statsText) { const inventoryMatch = statsText.match(/Inventory:\s*(.+)/i); if (healthMatch) extensionSettings.userStats.health = parseInt(healthMatch[1]); - if (sustenanceMatch) extensionSettings.userStats.sustenance = parseInt(sustenanceMatch[1]); + if (satietyMatch) extensionSettings.userStats.satiety = parseInt(satietyMatch[1]); if (energyMatch) extensionSettings.userStats.energy = parseInt(energyMatch[1]); if (hygieneMatch) extensionSettings.userStats.hygiene = parseInt(hygieneMatch[1]); if (arousalMatch) extensionSettings.userStats.arousal = parseInt(arousalMatch[1]); @@ -2735,11 +2735,20 @@ function renderUserStats() { // Initialize lastGeneratedData.userStats if it doesn't exist if (!lastGeneratedData.userStats) { - lastGeneratedData.userStats = `Health: ${stats.health}%\nSustenance: ${stats.sustenance}%\nEnergy: ${stats.energy}%\nHygiene: ${stats.hygiene}%\nArousal: ${stats.arousal}%\n${stats.mood}: ${stats.conditions}\nInventory: ${stats.inventory}`; + lastGeneratedData.userStats = `Health: ${stats.health}%\nSatiety: ${stats.satiety}%\nEnergy: ${stats.energy}%\nHygiene: ${stats.hygiene}%\nArousal: ${stats.arousal}%\n${stats.mood}: ${stats.conditions}\nInventory: ${stats.inventory}`; } - // Get user portrait - const userPortrait = getThumbnailUrl('persona', user_avatar); + // Get user portrait - handle both default-user and custom persona folders + let userPortrait = 'img/user-default.png'; // fallback + if (user_avatar) { + // Try to get the thumbnail, but have a fallback + try { + userPortrait = getThumbnailUrl('persona', user_avatar) || 'img/user-default.png'; + } catch (e) { + console.warn('[RPG Companion] Could not load user avatar, using default', e); + userPortrait = 'img/user-default.png'; + } + } // Create gradient from low to high color const gradient = `linear-gradient(to right, ${extensionSettings.statBarColorLow}, ${extensionSettings.statBarColorHigh})`; @@ -2765,11 +2774,11 @@ function renderUserStats() {
- Sustenance: + Satiety:
-
+
- ${stats.sustenance}% + ${stats.satiety}%
@@ -2882,7 +2891,7 @@ function renderUserStats() { lastGeneratedData.userStats = ''; } // Regenerate the userStats text with updated value - const statsText = `Health: ${extensionSettings.userStats.health}%\nSustenance: ${extensionSettings.userStats.sustenance}%\nEnergy: ${extensionSettings.userStats.energy}%\nHygiene: ${extensionSettings.userStats.hygiene}%\nArousal: ${extensionSettings.userStats.arousal}%\n${extensionSettings.userStats.mood}: ${extensionSettings.userStats.conditions}\nInventory: ${extensionSettings.userStats.inventory}`; + const statsText = `Health: ${extensionSettings.userStats.health}%\nSatiety: ${extensionSettings.userStats.satiety}%\nEnergy: ${extensionSettings.userStats.energy}%\nHygiene: ${extensionSettings.userStats.hygiene}%\nArousal: ${extensionSettings.userStats.arousal}%\n${extensionSettings.userStats.mood}: ${extensionSettings.userStats.conditions}\nInventory: ${extensionSettings.userStats.inventory}`; lastGeneratedData.userStats = statsText; saveSettings(); @@ -2899,7 +2908,7 @@ function renderUserStats() { extensionSettings.userStats.inventory = value || 'None'; // Update lastGeneratedData - const statsText = `Health: ${extensionSettings.userStats.health}%\nSustenance: ${extensionSettings.userStats.sustenance}%\nEnergy: ${extensionSettings.userStats.energy}%\nHygiene: ${extensionSettings.userStats.hygiene}%\nArousal: ${extensionSettings.userStats.arousal}%\n${extensionSettings.userStats.mood}: ${extensionSettings.userStats.conditions}\nInventory: ${extensionSettings.userStats.inventory}`; + const statsText = `Health: ${extensionSettings.userStats.health}%\nSatiety: ${extensionSettings.userStats.satiety}%\nEnergy: ${extensionSettings.userStats.energy}%\nHygiene: ${extensionSettings.userStats.hygiene}%\nArousal: ${extensionSettings.userStats.arousal}%\n${extensionSettings.userStats.mood}: ${extensionSettings.userStats.conditions}\nInventory: ${extensionSettings.userStats.inventory}`; lastGeneratedData.userStats = statsText; saveSettings(); @@ -2913,7 +2922,7 @@ function renderUserStats() { extensionSettings.userStats.mood = value || '😐'; // Update lastGeneratedData - const statsText = `Health: ${extensionSettings.userStats.health}%\nSustenance: ${extensionSettings.userStats.sustenance}%\nEnergy: ${extensionSettings.userStats.energy}%\nHygiene: ${extensionSettings.userStats.hygiene}%\nArousal: ${extensionSettings.userStats.arousal}%\n${extensionSettings.userStats.mood}: ${extensionSettings.userStats.conditions}\nInventory: ${extensionSettings.userStats.inventory}`; + const statsText = `Health: ${extensionSettings.userStats.health}%\nSatiety: ${extensionSettings.userStats.satiety}%\nEnergy: ${extensionSettings.userStats.energy}%\nHygiene: ${extensionSettings.userStats.hygiene}%\nArousal: ${extensionSettings.userStats.arousal}%\n${extensionSettings.userStats.mood}: ${extensionSettings.userStats.conditions}\nInventory: ${extensionSettings.userStats.inventory}`; lastGeneratedData.userStats = statsText; saveSettings(); @@ -2926,7 +2935,7 @@ function renderUserStats() { extensionSettings.userStats.conditions = value || 'None'; // Update lastGeneratedData - const statsText = `Health: ${extensionSettings.userStats.health}%\nSustenance: ${extensionSettings.userStats.sustenance}%\nEnergy: ${extensionSettings.userStats.energy}%\nHygiene: ${extensionSettings.userStats.hygiene}%\nArousal: ${extensionSettings.userStats.arousal}%\n${extensionSettings.userStats.mood}: ${extensionSettings.userStats.conditions}\nInventory: ${extensionSettings.userStats.inventory}`; + const statsText = `Health: ${extensionSettings.userStats.health}%\nSatiety: ${extensionSettings.userStats.satiety}%\nEnergy: ${extensionSettings.userStats.energy}%\nHygiene: ${extensionSettings.userStats.hygiene}%\nArousal: ${extensionSettings.userStats.arousal}%\n${extensionSettings.userStats.mood}: ${extensionSettings.userStats.conditions}\nInventory: ${extensionSettings.userStats.inventory}`; lastGeneratedData.userStats = statsText; saveSettings(); @@ -4076,13 +4085,21 @@ function createThoughtPanel($message, thoughtsArray) { /** * Event handler for when generation is about to start (TOGETHER MODE). * Injects RPG tracking prompt into the generation. + * @param {string} type - Generation type + * @param {object} data - Generation data including quietImage flag */ -function onGenerationStarted() { +function onGenerationStarted(type, data) { // console.log('[RPG Companion] onGenerationStarted called'); // console.log('[RPG Companion] enabled:', extensionSettings.enabled); // console.log('[RPG Companion] generationMode:', extensionSettings.generationMode); // console.log('[RPG Companion] ⚡ EVENT: onGenerationStarted - lastActionWasSwipe =', lastActionWasSwipe, '| isGenerating =', isGenerating); + // Skip tracker injection for image generation requests + if (data?.quietImage) { + // console.log('[RPG Companion] Detected image generation (quietImage=true), skipping tracker injection'); + return; + } + if (!extensionSettings.enabled) { return; } @@ -4130,6 +4147,20 @@ function onGenerationStarted() { } } + // For TOGETHER mode: Check if we need to commit extension data + // Same logic as separate mode - commit on new messages, keep existing data on swipes + if (extensionSettings.generationMode === 'together') { + if (!lastActionWasSwipe) { + // User sent a new message - commit lastGeneratedData before generation + // console.log('[RPG Companion] 📝 TOGETHER MODE COMMIT: New message - committing lastGeneratedData'); + committedTrackerData.userStats = lastGeneratedData.userStats; + committedTrackerData.infoBox = lastGeneratedData.infoBox; + committedTrackerData.characterThoughts = lastGeneratedData.characterThoughts; + } else { + // console.log('[RPG Companion] 🔄 TOGETHER MODE SWIPE: Using existing committedTrackerData (no commit)'); + } + } + // Use the committed tracker data as source for generation // console.log('[RPG Companion] Using committedTrackerData for generation'); // console.log('[RPG Companion] committedTrackerData.userStats:', committedTrackerData.userStats); @@ -4558,6 +4589,30 @@ async function ensureHtmlCleaningRegex() { } } +/** + * Update the persona avatar image when user switches personas + */ +function updatePersonaAvatar() { + const portraitImg = document.querySelector('.rpg-user-portrait'); + if (!portraitImg) return; + + // Get current user_avatar from context instead of using imported value + const context = getContext(); + const currentUserAvatar = context.user_avatar || user_avatar; + + let userPortrait = 'img/user-default.png'; + if (currentUserAvatar) { + try { + userPortrait = getThumbnailUrl('persona', currentUserAvatar) || 'img/user-default.png'; + } catch (e) { + console.warn('[RPG Companion] Could not load user avatar, using default', e); + userPortrait = 'img/user-default.png'; + } + } + + portraitImg.src = userPortrait; +} + /** * Main initialization function. */ @@ -4577,9 +4632,13 @@ jQuery(async () => { eventSource.on(event_types.MESSAGE_SENT, onMessageSent); eventSource.on(event_types.GENERATION_STARTED, onGenerationStarted); eventSource.on(event_types.MESSAGE_RECEIVED, onMessageReceived); - eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, onMessageReceived); + // Removed CHARACTER_MESSAGE_RENDERED to prevent race condition with cleaned messages eventSource.on(event_types.CHAT_CHANGED, onCharacterChanged); eventSource.on(event_types.MESSAGE_SWIPED, onMessageSwiped); + // Update persona avatar when user switches personas or chat changes + eventSource.on(event_types.CHAT_CHANGED, updatePersonaAvatar); + eventSource.on(event_types.USER_MESSAGE_RENDERED, updatePersonaAvatar); + eventSource.on(event_types.SETTINGS_UPDATED, updatePersonaAvatar); // console.log('[RPG Companion] Extension loaded successfully'); } catch (error) { diff --git a/style.css b/style.css index eaeddfa..87d9e15 100644 --- a/style.css +++ b/style.css @@ -88,7 +88,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { justify-content: center; z-index: 10001; transition: all 0.3s ease; - font-size: 1rem; + font-size: 1.5vw; box-shadow: 0 0 10px var(--rpg-shadow); pointer-events: auto; } @@ -209,11 +209,11 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-panel.rpg-position-top .rpg-stats-title { - font-size: 0.875rem; + font-size: 1.3vw; } .rpg-panel.rpg-position-top .rpg-mood { - font-size: 0.688rem; + font-size: 1vw; padding: 0.375em; } @@ -223,7 +223,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-panel.rpg-position-top .rpg-classic-stats-title { - font-size: 0.688rem; + font-size: 1vw; margin-bottom: 0.5em; } @@ -236,11 +236,11 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-panel.rpg-position-top .rpg-classic-stat-label { - font-size: 0.562rem; + font-size: 0.85vw; } .rpg-panel.rpg-position-top .rpg-classic-stat-value { - font-size: 0.875rem; + font-size: 1.3vw; } /* ============================================ @@ -329,12 +329,12 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-panel.rpg-position-top .rpg-classic-stat-btn { padding: 0.125em; - font-size: 0.75rem; + font-size: 1.1vw; } .rpg-panel.rpg-position-top .rpg-info-content, .rpg-panel.rpg-position-top .rpg-thoughts-content { - font-size: 0.75rem; + font-size: 1.1vw; max-height: 9.375rem; } @@ -399,7 +399,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-panel-header h3 { margin: 0; - font-size: 1.125rem; + font-size: 1.7vw; font-weight: bold; display: flex; align-items: center; @@ -432,7 +432,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { background: var(--rpg-accent); border-radius: 0.75em; color: var(--rpg-highlight); - font-size: 0.875rem; + font-size: 1.3vw; font-weight: bold; animation: pulseGlow 1.5s ease-in-out infinite; flex-shrink: 0; @@ -459,7 +459,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { background: rgba(0, 0, 0, 0.3); border-radius: 0.5em; border: 2px solid var(--rpg-border); - font-size: 0.688rem; + font-size: 1vw; font-weight: bold; color: var(--rpg-text); cursor: pointer; @@ -475,7 +475,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-dice-display i { color: var(--rpg-highlight); - font-size: 0.875rem; + font-size: 1.3vw; } /* Clear dice roll button */ @@ -484,7 +484,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { border: 1px solid rgba(255, 0, 0, 0.4); border-radius: 0.25em; color: #ff6b6b; - font-size: 1rem; + font-size: 1.5vw; font-weight: bold; width: 1.25rem; height: 1.25rem; @@ -639,7 +639,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-inventory-items { - font-size: clamp(5px, 1vh, 7px); + font-size: clamp(5px, 1vw, 7px); color: var(--rpg-text); line-height: 1.3; overflow-y: auto; @@ -746,7 +746,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-stat-label { min-width: 4.062rem; - font-size: clamp(7px, 1.1vh, 8px); + font-size: clamp(7px, 1.1vw, 8px); font-weight: 600; text-align: left; color: var(--rpg-text); @@ -776,7 +776,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-stat-value { color: #fff; - font-size: clamp(7px, 1.1vh, 8px); + font-size: clamp(7px, 1.1vw, 8px); font-weight: bold; min-width: 1.875rem; text-align: right; @@ -797,7 +797,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { transform: translateY(-50%); z-index: 2; min-width: auto; - font-size: clamp(7px, 1.1vh, 9px); + font-size: clamp(7px, 1.1vw, 9px); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9); } @@ -814,7 +814,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { transform: translateY(-50%); z-index: 2; min-width: auto; - font-size: clamp(7px, 1.1vh, 9px); + font-size: clamp(7px, 1.1vw, 9px); } } @@ -824,7 +824,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { display: flex; align-items: center; gap: 0.375em; - font-size: clamp(6px, 1vh, 8px); + font-size: clamp(6px, 1vw, 8px); padding: clamp(4px, 0.6vh, 6px) 0.375em; background: rgba(0, 0, 0, 0.3); border-radius: 0.25em; @@ -833,7 +833,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-mood-emoji { - font-size: clamp(12px, 1.8vh, 16px); + font-size: clamp(12px, 1.8vw, 16px); flex-shrink: 0; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.5)); } @@ -856,7 +856,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-classic-stats-title { text-align: center; - font-size: 0.562rem; + font-size: 0.85vw; font-weight: bold; text-transform: uppercase; letter-spacing: 0.037em; @@ -890,7 +890,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-classic-stat-label { - font-size: clamp(6px, 0.8vh, 7px); + font-size: clamp(6px, 0.8vw, 7px); font-weight: bold; text-transform: uppercase; letter-spacing: 0.006em; @@ -900,7 +900,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-classic-stat-value { - font-size: clamp(10px, 1.2vh, 12px); + font-size: clamp(10px, 1.2vw, 12px); font-weight: bold; color: var(--rpg-highlight); text-align: center; @@ -925,7 +925,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { border: 1px solid var(--rpg-border); border-radius: 2px; color: var(--rpg-text); - font-size: clamp(9px, 1.1vh, 12px); + font-size: clamp(9px, 1.1vw, 12px); font-weight: bold; cursor: pointer; transition: all 0.2s ease; @@ -952,7 +952,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { ============================================ */ .rpg-info-header { - font-size: 0.875rem; + font-size: 1.3vw; font-weight: bold; margin-bottom: 0.625em; color: var(--rpg-highlight); @@ -961,7 +961,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-info-content { - font-size: 0.75rem; + font-size: 1.1vw; line-height: 1.5; text-align: left; flex: 1; @@ -1053,7 +1053,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-calendar-top { background: var(--rpg-highlight); color: var(--rpg-bg); - font-size: clamp(5px, 1vh, 7px); + font-size: clamp(5px, 1vw, 7px); font-weight: bold; padding: 0.125em 0.375em; border-radius: 3px 3px 0 0; @@ -1064,7 +1064,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-calendar-day { background: rgba(255, 255, 255, 0.1); color: var(--rpg-text); - font-size: clamp(14px, 2.5vh, 20px); + font-size: clamp(14px, 2.5vw, 20px); font-weight: bold; padding: 0.25em; width: 100%; @@ -1078,7 +1078,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-calendar-year { - font-size: clamp(5px, 0.8vh, 6px); + font-size: clamp(5px, 0.8vw, 6px); color: var(--rpg-text); opacity: 0.7; margin-top: 0.062em; @@ -1086,21 +1086,24 @@ body:has(.rpg-panel.rpg-position-left) #sheld { /* Weather Widget Icon */ .rpg-weather-icon { - font-size: clamp(20px, 4vh, 28px); + font-size: clamp(18px, 3.5vw, 24px); filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.5)); + flex-shrink: 0; } .rpg-weather-forecast { - font-size: clamp(5px, 0.9vh, 7px); + font-size: clamp(5px, 0.8vw, 6px); text-align: center; margin: 0; font-weight: 600; text-transform: uppercase; letter-spacing: 0.013em; opacity: 0.85; - line-height: 1; + line-height: 1.1; word-wrap: break-word; max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; } .rpg-weather-forecast.rpg-editable { @@ -1152,7 +1155,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-temp-value { - font-size: clamp(6px, 1.2vh, 8px); + font-size: clamp(6px, 1.2vw, 8px); font-weight: bold; color: var(--rpg-text); text-align: center; @@ -1215,7 +1218,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-time-value { - font-size: clamp(6px, 1.1vh, 8px); + font-size: clamp(6px, 1.1vw, 8px); font-weight: bold; color: var(--rpg-text); } @@ -1246,7 +1249,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-map-marker { - font-size: 1rem; + font-size: 1.5vw; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8)); animation: markerPulse 2s ease-in-out infinite; } @@ -1257,7 +1260,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-location-text { - font-size: clamp(7px, 1.2vh, 8px); + font-size: clamp(7px, 1.2vw, 8px); font-weight: bold; color: var(--rpg-text); text-align: center; @@ -1296,7 +1299,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-char-emoji { - font-size: clamp(14px, 2.5vh, 18px); + font-size: clamp(14px, 2.5vw, 18px); flex-shrink: 0; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.5)); } @@ -1307,14 +1310,14 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-char-name { - font-size: clamp(8px, 1.5vh, 10px); + font-size: clamp(8px, 1.5vw, 10px); font-weight: bold; color: var(--rpg-highlight); margin-bottom: 0.062em; } .rpg-char-traits { - font-size: clamp(7px, 1.3vh, 9px); + font-size: clamp(7px, 1.3vw, 9px); color: var(--rpg-text); opacity: 0.8; line-height: 1.2; @@ -1347,7 +1350,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-thoughts-header { - font-size: 0.875rem; + font-size: 1.3vw; font-weight: bold; margin-bottom: 0.625em; color: var(--rpg-highlight); @@ -1440,7 +1443,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-thought-name { font-weight: bold; color: var(--rpg-highlight); - font-size: clamp(8px, 1.5vh, 10px); + font-size: clamp(8px, 1.5vw, 10px); margin-bottom: 0.188em; text-transform: uppercase; letter-spacing: 0.031em; @@ -1452,7 +1455,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-thought-text { - font-size: clamp(9px, 1.6vh, 11px); + font-size: clamp(9px, 1.6vw, 11px); font-style: italic; line-height: 1.3; color: var(--rpg-text); @@ -1488,7 +1491,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { display: flex; align-items: flex-start; gap: 0.5em; - font-size: 0.75rem; + font-size: 1.1vw; font-style: italic; line-height: 1.4; } @@ -1541,7 +1544,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { display: flex; align-items: center; justify-content: center; - font-size: clamp(8px, 1.2vh, 12px); + font-size: clamp(8px, 1.2vw, 12px); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); } @@ -1564,14 +1567,14 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-character-emoji { - font-size: clamp(12px, 2vh, 16px); + font-size: clamp(12px, 2vw, 16px); flex-shrink: 0; } .rpg-character-name { font-weight: bold; color: var(--rpg-highlight); - font-size: clamp(9px, 1.5vh, 12px); + font-size: clamp(9px, 1.5vw, 12px); text-transform: uppercase; letter-spacing: 0.031em; white-space: nowrap; /* Prevent name from wrapping */ @@ -1581,7 +1584,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { /* Character traits/status line */ .rpg-character-traits { - font-size: clamp(8px, 1.3vh, 10px); + font-size: clamp(8px, 1.3vw, 10px); color: var(--rpg-text); opacity: 0.8; line-height: 1.3; @@ -1602,14 +1605,14 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-placeholder-text { - font-size: clamp(10px, 1.6vh, 14px); + font-size: clamp(10px, 1.6vw, 14px); color: var(--rpg-text); font-weight: bold; margin-bottom: clamp(4px, 0.6vh, 6px); } .rpg-placeholder-hint { - font-size: clamp(8px, 1.2vh, 10px); + font-size: clamp(8px, 1.2vw, 10px); color: var(--rpg-text); opacity: 0.7; font-style: italic; @@ -1651,7 +1654,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { color: var(--rpg-text); padding: clamp(3px, 0.6vh, 6px) clamp(6px, 1.2vh, 12px); border-radius: clamp(3px, 0.6vh, 6px); - font-size: clamp(7px, 1.2vh, 10px); + font-size: clamp(7px, 1.2vw, 10px); cursor: pointer; display: flex; align-items: center; @@ -1671,7 +1674,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-edit-button i { - font-size: clamp(7px, 1.2vh, 10px); + font-size: clamp(7px, 1.2vw, 10px); } /* Removed emoji icon styling - no longer needed */ @@ -1693,7 +1696,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { display: flex; align-items: center; gap: 0.375em; - font-size: 0.75rem; + font-size: 1.1vw; } .rpg-settings summary:hover { @@ -1716,7 +1719,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-setting-row label { display: block; margin-bottom: 0.188em; - font-size: 0.688rem; + font-size: 1vw; } .rpg-setting-row input[type="number"] { @@ -1726,14 +1729,14 @@ body:has(.rpg-panel.rpg-position-left) #sheld { border-radius: 3px; background: rgba(0, 0, 0, 0.3); color: inherit; - font-size: 0.688rem; + font-size: 1vw; } .rpg-setting-row small { display: block; margin-top: 0.188em; color: #888; - font-size: 0.625rem; + font-size: 0.95vw; } #rpg-manual-update { @@ -1744,7 +1747,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { align-items: center; justify-content: center; gap: 0.375em; - font-size: 0.75rem; + font-size: 1.1vw; } /* Responsive adjustments */ @@ -1755,7 +1758,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-stat-label { min-width: 5rem; - font-size: 0.75rem; + font-size: 1.1vw; } } @@ -1819,7 +1822,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-settings-group h4 { margin: 0 0 0.75em 0; - font-size: 1rem; + font-size: 1.5vw; color: var(--rpg-highlight); display: flex; align-items: center; @@ -1833,7 +1836,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-setting-row label { display: block; margin-bottom: 0.375em; - font-size: 0.812rem; + font-size: 1.2vw; font-weight: 600; } @@ -1845,7 +1848,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { border-radius: 0.375em; background: var(--rpg-bg); color: var(--rpg-text); - font-size: 0.875rem; + font-size: 1.3vw; transition: all 0.3s ease; } @@ -1875,7 +1878,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { display: block; margin-top: 0.25em; color: #999; - font-size: 0.688rem; + font-size: 1vw; font-style: italic; } @@ -1907,7 +1910,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { border: 2px solid var(--rpg-border); border-radius: 0.625em; color: var(--rpg-text); - font-size: 0.938rem; + font-size: 1.4vw; font-weight: bold; cursor: pointer; display: flex; @@ -1937,7 +1940,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { border: 2px solid rgba(220, 53, 69, 0.5); border-radius: 0.5em; color: #ff6b6b; - font-size: 0.812rem; + font-size: 1.2vw; font-weight: 600; cursor: pointer; display: flex; @@ -2053,7 +2056,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-panel[data-theme="fantasy"] .rpg-divider::after { content: '❦'; - font-size: 1rem; + font-size: 1.5vw; } .rpg-panel[data-theme="fantasy"] .rpg-thoughts-content::before { @@ -2141,7 +2144,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-stats-title { - font-size: 1rem; + font-size: 1.5vw; } } @@ -2582,7 +2585,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { border: 2px solid var(--rpg-highlight); border-radius: 0.5em; color: var(--rpg-text); - font-size: 0.75rem; + font-size: 1.1vw; font-weight: 600; cursor: pointer; transition: all 0.3s ease; @@ -2618,7 +2621,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { border: 2px solid var(--rpg-border); border-radius: 0.5em; color: var(--rpg-text); - font-size: 0.75rem; + font-size: 1.1vw; font-weight: 600; cursor: pointer; transition: all 0.3s ease; @@ -2741,7 +2744,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { background: transparent; border: none; color: var(--rpg-text); - font-size: 1.5rem; + font-size: 2.2vw; cursor: pointer; padding: 0.5rem; min-width: 44px; @@ -2858,7 +2861,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { background: var(--rpg-highlight, #e94560); color: white; border: 2px solid var(--rpg-bg, rgba(30, 30, 50, 0.95)); - font-size: 1.125rem; + font-size: 1.7vw; line-height: 1; cursor: pointer; display: flex; @@ -2886,7 +2889,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { display: flex; align-items: center; justify-content: center; - font-size: 1.25rem; + font-size: 1.85vw; cursor: pointer; animation: thoughtIconPulse 2s ease-in-out infinite; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5); @@ -3002,13 +3005,13 @@ body:has(.rpg-panel.rpg-position-left) #sheld { background: var(--rpg-accent, rgba(50, 50, 70, 0.8)); border: 1px solid var(--rpg-highlight, #e94560); border-radius: clamp(6px, 1vh, 8px); - font-size: clamp(16px, 2vh, 20px); + font-size: clamp(16px, 2vw, 20px); } /* Thought content on the right */ .rpg-thought-content { flex: 1; - font-size: clamp(10px, 1.4vh, 12px); + font-size: clamp(10px, 1.4vw, 12px); line-height: 1.5; color: var(--rpg-text, #eaeaea); font-style: italic; @@ -3124,7 +3127,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-thought-content { - font-size: clamp(9px, 1.2vh, 11px); + font-size: clamp(9px, 1.2vw, 11px); } } @@ -3146,7 +3149,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { background: var(--SmartThemeBlurTintColor); border: 2px solid var(--SmartThemeBorderColor); color: var(--rpg-text, #ecf0f1); - font-size: 1.25rem; + font-size: 1.85vw; cursor: grab; z-index: 10002; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); @@ -3721,7 +3724,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld { right: 0.938rem; width: 3.25rem; height: 3.25rem; - font-size: 1.375rem; + font-size: 2vw; } } @@ -3737,6 +3740,6 @@ body:has(.rpg-panel.rpg-position-left) #sheld { .rpg-thought-close { min-width: 2.75rem; min-height: 2.75rem; - font-size: 1.5rem; + font-size: 2.2vw; } }