feat(sasch40): authentic 3 sisters portraits, 9:16 responsive stage with medieval ornaments, and hotspot fixes

- Recreate 16-bit LucasArts portraits for Saskia, Maja, and Miriam matching real-life source photos
- Add 3 sisters showcase in Act II intro modal and golden portrait badges on goal platforms
- Fix Act III background scaling: lock scene to 9:16 aspect ratio with medieval ornamental side borders and corner brackets
- Ensure 100% full background visibility with zero cropping and lock hotspot buttons to image features across all screen sizes
- Fix cache issue by referencing schankraum_v5.jpg with cache buster query
- Re-position NAT button to feet (top: 70%) and Mario button to knees (top: 79%) to eliminate face occlusion
This commit is contained in:
Moritz Graf
2026-09-25 09:23:31 +02:00
parent 07fef4547c
commit 109d47d8d3
13 changed files with 304 additions and 48 deletions
@@ -580,10 +580,36 @@ function proceedToExpress() {
<template>
<div class="tavern-container">
<div class="scene-viewport">
<!-- Left Medieval Ornament Border -->
<div class="medieval-side-border border-left" aria-hidden="true">
<div class="ornament-column">
<span class="ornament-symbol">⚜️</span>
<span class="ornament-divider">✦</span>
<span class="ornament-symbol">👑</span>
<span class="ornament-divider">✦</span>
<span class="ornament-symbol">🍻</span>
<span class="ornament-divider">✦</span>
<span class="ornament-symbol">⚔️</span>
<span class="ornament-divider">✦</span>
<span class="ornament-symbol">🛡️</span>
<span class="ornament-divider">✦</span>
<span class="ornament-symbol">🌿</span>
<span class="ornament-divider">✦</span>
<span class="ornament-symbol">⚜️</span>
</div>
</div>
<!-- ================= 1. GASTSTUBE (SCHANKRAUM) ================= -->
<template v-if="currentRoom === 'schankraum'">
<img src="/assets/scenes/schankraum.jpg" alt="Gaststube Zum wummernden Ritter" class="tavern-bg" />
<!-- The 9:16 Scene Stage: whole image is 100% visible, zero cropping, hotspots locked to image -->
<div class="scene-stage">
<!-- 4 Golden Corner Ornaments -->
<div class="corner-ornament corner-tl"></div>
<div class="corner-ornament corner-tr"></div>
<div class="corner-ornament corner-bl"></div>
<div class="corner-ornament corner-br"></div>
<!-- ================= 1. GASTSTUBE (SCHANKRAUM) ================= -->
<template v-if="currentRoom === 'schankraum'">
<img src="/assets/scenes/schankraum_v5.jpg?v=5" alt="Gaststube Zum wummernden Ritter" class="tavern-bg" />
<!-- Verena on the wooden gallery -->
<button class="hotspot hotspot-verena" @click="openCharacterDialog('verena')">
@@ -767,9 +793,30 @@ function proceedToExpress() {
<span class="hotspot-badge glow-door">◀ Zurück in den Schankraum</span>
</button>
</template>
</div><!-- /.scene-stage -->
<!-- Bottom Scene Navigation & Duel -->
<div class="scene-bottom-nav">
<!-- Right Medieval Ornament Border -->
<div class="medieval-side-border border-right" aria-hidden="true">
<div class="ornament-column">
<span class="ornament-symbol">⚜️</span>
<span class="ornament-divider">✦</span>
<span class="ornament-symbol">👑</span>
<span class="ornament-divider">✦</span>
<span class="ornament-symbol">🍻</span>
<span class="ornament-divider">✦</span>
<span class="ornament-symbol">⚔️</span>
<span class="ornament-divider">✦</span>
<span class="ornament-symbol">🛡️</span>
<span class="ornament-divider">✦</span>
<span class="ornament-symbol">🌿</span>
<span class="ornament-divider">✦</span>
<span class="ornament-symbol">⚜️</span>
</div>
</div>
</div><!-- /.scene-viewport -->
<!-- Bottom Scene Navigation & Duel -->
<div class="scene-bottom-nav">
<!-- Room Title Badge -->
<div class="tavern-bar-title">
{{
@@ -840,7 +887,6 @@ function proceedToExpress() {
</button>
</div>
</div>
</div>
<!-- Monkey Island Dialog Modal -->
<div v-if="activeDialog" class="dialog-overlay" @click="activeDialog = null">
@@ -1192,27 +1238,110 @@ function proceedToExpress() {
<style scoped>
.tavern-container {
display: flex;
flex-direction: column;
position: relative;
width: 100%;
height: 100%;
background: #1a0f0a;
background: #100603;
overflow: hidden;
}
.scene-viewport {
position: relative;
flex: 1;
min-height: 0;
width: 100%;
height: 100%;
position: relative;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
background-color: #120703;
background-image:
radial-gradient(circle at 50% 50%, rgba(69, 26, 3, 0.45) 0%, rgba(10, 4, 1, 0.95) 100%),
repeating-linear-gradient(45deg, rgba(212, 175, 55, 0.05) 0, rgba(212, 175, 55, 0.05) 1px, transparent 0, transparent 20px),
repeating-linear-gradient(-45deg, rgba(212, 175, 55, 0.05) 0, rgba(212, 175, 55, 0.05) 1px, transparent 0, transparent 20px);
}
.scene-stage {
position: relative;
max-width: 100%;
max-height: 100%;
aspect-ratio: 9 / 16;
height: min(100%, calc(100vw * 16 / 9));
width: auto;
box-shadow:
0 0 0 2px #78350f,
0 0 0 4px #b45309,
0 0 20px rgba(0, 0, 0, 0.95),
0 0 16px rgba(245, 158, 11, 0.3);
border: 2px solid #b45309;
border-radius: 4px;
overflow: hidden;
flex-shrink: 0;
}
.tavern-bg {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
object-fit: fill;
image-rendering: pixelated;
image-rendering: crisp-edges;
}
/* Corner Ornaments on Scene Stage */
.corner-ornament {
position: absolute;
width: 14px;
height: 14px;
z-index: 14;
pointer-events: none;
}
.corner-tl { top: 3px; left: 3px; border-top: 2px solid #ffd700; border-left: 2px solid #ffd700; }
.corner-tr { top: 3px; right: 3px; border-top: 2px solid #ffd700; border-right: 2px solid #ffd700; }
.corner-bl { bottom: 3px; left: 3px; border-bottom: 2px solid #ffd700; border-left: 2px solid #ffd700; }
.corner-br { bottom: 3px; right: 3px; border-bottom: 2px solid #ffd700; border-right: 2px solid #ffd700; }
/* Side Medieval Ornament Borders */
.medieval-side-border {
flex: 1;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
min-width: 0;
overflow: hidden;
opacity: 0.85;
pointer-events: none;
user-select: none;
}
.ornament-column {
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
padding: 8px;
}
.ornament-symbol {
font-size: 16px;
filter: drop-shadow(0 0 4px rgba(255, 215, 0, 0.35));
}
.ornament-divider {
font-size: 9px;
color: #b45309;
text-shadow: 0 0 4px rgba(245, 158, 11, 0.5);
}
@media (max-width: 480px) {
.medieval-side-border {
display: none;
}
}
/* Hotspots with Avatar Thumbnails */
.hotspot {
position: absolute;
@@ -1327,8 +1456,8 @@ function proceedToExpress() {
/* 3. Marktplatz Hotspots */
.mario-container {
position: absolute;
top: 66%;
left: 70%;
top: 79%;
left: 76%;
z-index: 10;
}
@@ -1382,8 +1511,8 @@ function proceedToExpress() {
100% { opacity: 1; transform: scale(1.3); }
}
.hotspot-nat { top: 54%; left: 22%; }
.hotspot-door-back-gaststube { top: 74%; left: 20%; }
.hotspot-nat { top: 70%; left: 22%; }
.hotspot-door-back-gaststube { top: 82%; left: 16%; }
.hotspot-door-hinterland { top: 34%; left: 76%; }
/* 4. Hinterland Hotspots */
@@ -1443,10 +1572,9 @@ function proceedToExpress() {
/* Bottom Navigation */
.scene-bottom-nav {
position: absolute;
bottom: 0;
left: 0;
right: 0;
position: relative;
flex-shrink: 0;
width: 100%;
height: 94px;
background: linear-gradient(180deg, #451a03 0%, #26140b 100%);
border-top: 3px solid #b45309;