Apply artifact room panel theme with kid-friendly Egyptian styling.

Warm stone-and-gold UI, Cinzel typography, and Ted artifact-room copy replace the generic digital lock look.
This commit is contained in:
2026-06-11 09:25:25 -04:00
parent 32a0331e8b
commit c810efd8e5
5 changed files with 279 additions and 124 deletions
+8 -1
View File
@@ -4,7 +4,14 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Egyptian Escape Room — Digital Lock</title> <meta name="theme-color" content="#1a1510" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Cinzel:wght@600;700&family=Source+Sans+3:wght@400;600;700&display=swap"
rel="stylesheet"
/>
<title>Ted's Egyptian Escape Room — Artifact Room Door</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
+5 -1
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 333 B

+181 -65
View File
@@ -1,28 +1,137 @@
.lock-app { /* Sarcophagus control panel — warm adventure tone, kid-friendly */
.sarcophagus-scene {
position: relative;
width: min(100%, 56rem);
margin: 0 auto;
padding: 0 1rem;
}
.sarcophagus-scene--celebrating::before {
content: '';
position: fixed;
inset: 0;
z-index: 0;
pointer-events: none;
background: radial-gradient(
ellipse 70% 60% at 50% 45%,
rgba(255, 210, 120, 0.22) 0%,
rgba(255, 180, 80, 0.08) 45%,
transparent 70%
);
animation: torch-glow 2s ease-in-out;
}
@keyframes torch-glow {
0% {
opacity: 0;
}
35% {
opacity: 1;
}
100% {
opacity: 0.6;
}
}
.sarcophagus-panel {
position: relative;
z-index: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
gap: 1.5rem; gap: 1.5rem;
width: min(100%, 56rem); padding: 2rem 1.25rem 2.5rem;
margin: 0 auto; background:
padding: 2rem 1rem 3rem; linear-gradient(180deg, rgba(255, 255, 255, 0.03) 0%, transparent 12%),
linear-gradient(180deg, #3d3428 0%, #2d2419 55%, #252018 100%);
border: 3px solid #5c4d38;
border-radius: 1rem;
box-shadow:
inset 0 0 0 1px rgba(232, 197, 71, 0.3),
inset 0 2px 28px rgba(0, 0, 0, 0.35),
0 16px 48px rgba(0, 0, 0, 0.45);
}
.sarcophagus-panel--opening {
animation: panel-unlock 1.8s ease-in-out;
}
@keyframes panel-unlock {
0%,
100% {
box-shadow:
inset 0 0 0 1px rgba(232, 197, 71, 0.3),
inset 0 2px 28px rgba(0, 0, 0, 0.35),
0 16px 48px rgba(0, 0, 0, 0.45);
}
40%,
70% {
box-shadow:
inset 0 0 0 2px rgba(232, 197, 71, 0.65),
inset 0 0 40px rgba(232, 197, 71, 0.12),
0 0 32px rgba(232, 197, 71, 0.25),
0 16px 48px rgba(0, 0, 0, 0.45);
}
}
.panel-corner {
position: absolute;
font-size: 1.1rem;
color: rgba(201, 162, 39, 0.45);
line-height: 1;
user-select: none;
pointer-events: none;
}
.panel-corner--tl {
top: 0.65rem;
left: 0.85rem;
}
.panel-corner--tr {
top: 0.65rem;
right: 0.85rem;
}
.panel-corner--bl {
bottom: 0.65rem;
left: 0.85rem;
}
.panel-corner--br {
bottom: 0.65rem;
right: 0.85rem;
} }
.lock-header { .lock-header {
text-align: center; text-align: center;
width: 100%;
} }
.lock-header h1 { .lock-header h1 {
margin: 0 0 0.35rem; margin: 0 0 0.5rem;
font-size: clamp(1.75rem, 5vw, 2.25rem); font-family: Cinzel, Georgia, 'Times New Roman', serif;
font-size: clamp(1.5rem, 4.5vw, 2rem);
font-weight: 700; font-weight: 700;
letter-spacing: 0.04em; letter-spacing: 0.06em;
color: #e8c547;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
} }
.lock-subtitle { .lock-subtitle {
margin: 0; margin: 0;
color: #9ca3af; color: #c9b896;
font-size: 0.95rem; font-size: clamp(0.78rem, 1.45vw, 0.95rem);
line-height: 1.45;
white-space: nowrap;
}
@media (max-width: 26rem) {
.lock-subtitle {
white-space: normal;
font-size: 0.88rem;
}
} }
.lock-grid { .lock-grid {
@@ -32,7 +141,8 @@
gap: 0.65rem; gap: 0.65rem;
width: 100%; width: 100%;
overflow-x: auto; overflow-x: auto;
padding-bottom: 0.25rem; padding: 0.25rem 0.15rem 0.35rem;
scrollbar-color: #5c4d38 transparent;
} }
.lock-slot { .lock-slot {
@@ -51,27 +161,37 @@
width: clamp(2.5rem, 5vw, 3.25rem); width: clamp(2.5rem, 5vw, 3.25rem);
height: clamp(2.5rem, 5vw, 3.25rem); height: clamp(2.5rem, 5vw, 3.25rem);
border-radius: 50%; border-radius: 50%;
border: 2px solid rgba(255, 255, 255, 0.25); border: 3px solid #c9a227;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4); box-shadow:
0 0 0 2px rgba(26, 21, 16, 0.85),
0 3px 10px rgba(0, 0, 0, 0.4),
inset 0 2px 6px rgba(255, 255, 255, 0.18);
} }
.lock-input { .lock-input {
width: 100%; width: 100%;
min-width: 0; min-width: 0;
padding: 0.65rem 0.25rem; padding: 0.65rem 0.25rem;
font-family: 'Source Sans 3', system-ui, sans-serif;
font-size: clamp(1.1rem, 2.5vw, 1.5rem); font-size: clamp(1.1rem, 2.5vw, 1.5rem);
font-weight: 600; font-weight: 700;
text-align: center; text-align: center;
color: #f3f4f6; color: #f4e4bc;
background: #1f2937; background: linear-gradient(180deg, #2a2218 0%, #1f1a14 100%);
border: 2px solid #374151; border: 2px solid #4a3f32;
border-radius: 0.5rem; border-radius: 0.5rem;
outline: none; outline: none;
transition: border-color 0.15s; box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.35);
transition:
border-color 0.15s,
box-shadow 0.15s;
} }
.lock-input:focus { .lock-input:focus {
border-color: #6b7280; border-color: #e8c547;
box-shadow:
inset 0 2px 6px rgba(0, 0, 0, 0.35),
0 0 0 3px rgba(232, 197, 71, 0.22);
} }
.lock-input:disabled { .lock-input:disabled {
@@ -81,11 +201,12 @@
.lock-error { .lock-error {
margin: 0; margin: 0;
padding: 0.65rem 1.25rem; padding: 0.65rem 1.25rem;
font-size: 1.1rem; font-size: 1.05rem;
font-weight: 600; font-weight: 600;
color: #fecaca; color: #fef3c7;
background: #7f1d1d; text-align: center;
border: 1px solid #b91c1c; background: rgba(92, 68, 28, 0.75);
border: 1px solid rgba(201, 162, 39, 0.55);
border-radius: 0.5rem; border-radius: 0.5rem;
animation: error-pop 0.25s ease-out; animation: error-pop 0.25s ease-out;
} }
@@ -102,28 +223,40 @@
} }
.unlock-btn { .unlock-btn {
margin-top: 0.5rem; margin-top: 0.25rem;
padding: 1rem 3rem; padding: 1rem 2.75rem;
font-size: 1.25rem; font-family: Cinzel, Georgia, serif;
font-size: 1.1rem;
font-weight: 700; font-weight: 700;
letter-spacing: 0.12em; letter-spacing: 0.14em;
color: #111827; color: #1a1510;
background: linear-gradient(180deg, #fbbf24 0%, #d97706 100%); background: linear-gradient(180deg, #e8c547 0%, #c9a227 48%, #a8841a 100%);
border: none; border: 2px solid #f4e4bc;
border-radius: 0.5rem; border-radius: 0.5rem;
cursor: pointer; cursor: pointer;
box-shadow: 0 4px 0 #92400e, 0 6px 16px rgba(0, 0, 0, 0.35); box-shadow:
transition: transform 0.1s, box-shadow 0.1s; 0 4px 0 #7a6318,
0 8px 20px rgba(0, 0, 0, 0.35),
inset 0 1px 0 rgba(255, 255, 255, 0.35);
transition:
transform 0.1s,
box-shadow 0.1s;
} }
.unlock-btn:hover:not(:disabled) { .unlock-btn:hover:not(:disabled) {
transform: translateY(-1px); transform: translateY(-1px);
box-shadow: 0 5px 0 #92400e, 0 8px 20px rgba(0, 0, 0, 0.4); box-shadow:
0 5px 0 #7a6318,
0 10px 24px rgba(0, 0, 0, 0.4),
inset 0 1px 0 rgba(255, 255, 255, 0.35);
} }
.unlock-btn:active:not(:disabled) { .unlock-btn:active:not(:disabled) {
transform: translateY(2px); transform: translateY(2px);
box-shadow: 0 2px 0 #92400e, 0 4px 12px rgba(0, 0, 0, 0.3); box-shadow:
0 2px 0 #7a6318,
0 4px 12px rgba(0, 0, 0, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.25);
} }
.unlock-btn:disabled { .unlock-btn:disabled {
@@ -160,41 +293,24 @@
} }
} }
.lock-opening { .panel-opening-msg {
position: relative; margin: 0;
width: 5rem; font-family: Cinzel, Georgia, serif;
height: 5rem; font-size: 1.05rem;
margin-top: 0.5rem; font-weight: 600;
letter-spacing: 0.05em;
color: #e8c547;
animation: opening-pulse 1.2s ease-in-out infinite;
} }
.lock-body { @keyframes opening-pulse {
position: absolute; 0%,
bottom: 0; 100% {
left: 50%; opacity: 0.75;
width: 3.5rem;
height: 3rem;
background: linear-gradient(180deg, #9ca3af 0%, #4b5563 100%);
border-radius: 0.35rem;
transform: translateX(-50%);
box-shadow: inset 0 2px 4px rgba(255, 255, 255, 0.3);
} }
50% {
.lock-shackle { opacity: 1;
position: absolute;
top: 0.25rem;
left: 50%;
width: 2.5rem;
height: 2.5rem;
border: 0.45rem solid #9ca3af;
border-bottom: none;
border-radius: 2rem 2rem 0 0;
transform: translateX(-50%);
transition: transform 0.6s ease-out, opacity 0.6s;
} }
.lock-shackle--open {
transform: translateX(-50%) rotate(-28deg) translateY(-0.35rem);
opacity: 0.85;
} }
.video-screen { .video-screen {
@@ -203,7 +319,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background: #000; background: #0f0d0a;
z-index: 100; z-index: 100;
} }
+34 -12
View File
@@ -72,18 +72,22 @@ export function DigitalLock() {
const duration = 2000; const duration = 2000;
const end = Date.now() + duration; const end = Date.now() + duration;
const confettiColors = ['#e8c547', '#c9a227', '#f4e4bc', '#d4a84b'];
const frame = () => { const frame = () => {
confetti({ confetti({
particleCount: 4, particleCount: 4,
angle: 60, angle: 60,
spread: 55, spread: 55,
origin: { x: 0, y: 0.7 }, origin: { x: 0, y: 0.7 },
colors: confettiColors,
}); });
confetti({ confetti({
particleCount: 4, particleCount: 4,
angle: 120, angle: 120,
spread: 55, spread: 55,
origin: { x: 1, y: 0.7 }, origin: { x: 1, y: 0.7 },
colors: confettiColors,
}); });
if (Date.now() < end) { if (Date.now() < end) {
requestAnimationFrame(frame); requestAnimationFrame(frame);
@@ -98,14 +102,32 @@ export function DigitalLock() {
return <UnlockVideo src={mediaConfig.unlockVideoUrl} />; return <UnlockVideo src={mediaConfig.unlockVideoUrl} />;
} }
const isCelebrating = phase === 'celebrating';
return ( return (
<div className={`lock-app ${phase === 'celebrating' ? 'lock-app--celebrating' : ''}`}> <div className={`sarcophagus-scene ${isCelebrating ? 'sarcophagus-scene--celebrating' : ''}`}>
<div className={`sarcophagus-panel ${isCelebrating ? 'sarcophagus-panel--opening' : ''}`}>
<span className="panel-corner panel-corner--tl" aria-hidden="true">
</span>
<span className="panel-corner panel-corner--tr" aria-hidden="true">
</span>
<span className="panel-corner panel-corner--bl" aria-hidden="true">
</span>
<span className="panel-corner panel-corner--br" aria-hidden="true">
</span>
<header className="lock-header"> <header className="lock-header">
<h1>Digital Lock</h1> <h1>Artifact Room Door</h1>
<p className="lock-subtitle">Enter the code from each colored puzzle</p> <p className="lock-subtitle">
Enter each colored answer help Ted leave the artifact room!
</p>
</header> </header>
<div className="lock-grid" role="group" aria-label="Lock code inputs"> <div className="lock-grid" role="group" aria-label="Artifact room door code inputs">
{LOCK_SLOTS.map((slot, index) => ( {LOCK_SLOTS.map((slot, index) => (
<label key={slot.color} className="lock-slot"> <label key={slot.color} className="lock-slot">
<span <span
@@ -127,7 +149,7 @@ export function DigitalLock() {
onChange={(e) => handleChange(index, e.target.value)} onChange={(e) => handleChange(index, e.target.value)}
onKeyDown={(e) => handleKeyDown(index, e)} onKeyDown={(e) => handleKeyDown(index, e)}
disabled={phase !== 'locked'} disabled={phase !== 'locked'}
aria-label={`Puzzle ${index + 1} code`} aria-label={`Colored clue ${index + 1} answer`}
/> />
</label> </label>
))} ))}
@@ -135,7 +157,7 @@ export function DigitalLock() {
{showError && ( {showError && (
<p className="lock-error" role="alert"> <p className="lock-error" role="alert">
Incorrect Code! That code didn&apos;t open the door check your answers and try again!
</p> </p>
)} )}
@@ -145,15 +167,15 @@ export function DigitalLock() {
onClick={handleUnlock} onClick={handleUnlock}
disabled={phase !== 'locked'} disabled={phase !== 'locked'}
> >
UNLOCK OPEN DOOR
</button> </button>
{phase === 'celebrating' && ( {isCelebrating && (
<div className="lock-opening" aria-hidden="true"> <p className="panel-opening-msg" aria-live="polite">
<div className="lock-shackle lock-shackle--open" /> The door is opening!
<div className="lock-body" /> </p>
</div>
)} )}
</div> </div>
</div>
); );
} }
+9 -3
View File
@@ -12,10 +12,15 @@ body,
} }
body { body {
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-family: 'Source Sans 3', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
line-height: 1.5; line-height: 1.5;
color: #f3f4f6; color: #f4e4bc;
background: #111827; background-color: #1a1510;
background-image:
radial-gradient(ellipse 80% 50% at 15% 20%, rgba(201, 162, 39, 0.07) 0%, transparent 55%),
radial-gradient(ellipse 60% 40% at 85% 75%, rgba(201, 162, 39, 0.05) 0%, transparent 50%),
radial-gradient(circle at 50% 0%, rgba(61, 52, 40, 0.6) 0%, transparent 45%),
linear-gradient(165deg, #1a1510 0%, #2a2218 42%, #1c1814 100%);
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
} }
@@ -24,4 +29,5 @@ body {
justify-content: center; justify-content: center;
align-items: flex-start; align-items: flex-start;
min-height: 100dvh; min-height: 100dvh;
padding: 1rem 0 2rem;
} }