Files
SciFi-XZBT/js/observation-bezels.js
T
2026-09-03 21:09:32 -07:00

271 lines
17 KiB
JavaScript

/**
* Procedural SVG Viewport Frames & Bezels for Observation Mode
*/
window.ObservationBezels = {
getViewportFrameSvg(universeId, presetId, engine) {
if (universeId === 'spacestations') {
// Space Stations has its own authentic native station viewport in observationStage!
return '';
}
if (universeId === 'starfleet') {
let era = 'tng';
const preset = (typeof StarshipPresets !== 'undefined' && presetId) ? StarshipPresets[presetId] : null;
if (preset && preset.era) era = preset.era;
if (era === 'tos') {
// TOS Original Series - hexagonal bridge viewscreen bezel
return `
<svg viewBox="0 0 1600 900" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="tosMetal" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#2b2118"/>
<stop offset="50%" stop-color="#171310"/>
<stop offset="100%" stop-color="#0a0806"/>
</linearGradient>
</defs>
<path d="M0,0 H1600 V70 L1350,190 H250 L0,70 Z" fill="url(#tosMetal)" stroke="#f59e0b" stroke-width="3"/>
<path d="M0,900 H1600 V830 L1350,710 H250 L0,830 Z" fill="url(#tosMetal)" stroke="#f59e0b" stroke-width="3"/>
<path d="M0,0 V900 H130 L170,710 V190 L130,0 Z" fill="url(#tosMetal)" stroke="#f59e0b" stroke-width="3"/>
<path d="M1600,0 V900 H1470 L1430,710 V190 L1470,0 Z" fill="url(#tosMetal)" stroke="#f59e0b" stroke-width="3"/>
${(engine ? engine.showPillars : false) ? `
<rect x="530" y="195" width="30" height="515" fill="#171310" stroke="#dc2626" stroke-width="2.5" opacity="0.9"/>
<rect x="1040" y="195" width="30" height="515" fill="#171310" stroke="#dc2626" stroke-width="2.5" opacity="0.9"/>
` : ''}
<text x="800" y="865" text-anchor="middle" fill="#f59e0b" font-family="'Share Tech Mono', monospace" font-size="16" letter-spacing="4">U.S.S. ENTERPRISE NCC-1701 // BRIDGE VIEWSCREEN</text>
</svg>
`;
}
if (era === 'voyager') {
// Voyager Intrepid Class - sleeker rounded modern arch, cyan accent
return `
<svg viewBox="0 0 1600 900" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="voyMetal" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#0f2027"/>
<stop offset="50%" stop-color="#0a1418"/>
<stop offset="100%" stop-color="#050a0c"/>
</linearGradient>
</defs>
<path d="M0,0 H1600 V70 Q800,130 0,70 Z" fill="url(#voyMetal)" stroke="#22d3ee" stroke-width="3"/>
<path d="M0,900 H1600 V830 Q800,770 0,830 Z" fill="url(#voyMetal)" stroke="#22d3ee" stroke-width="3"/>
<path d="M0,0 V900 H80 Q110,450 80,0 Z" fill="url(#voyMetal)"/>
<path d="M1600,0 V900 H1520 Q1490,450 1520,0 Z" fill="url(#voyMetal)"/>
${(engine ? engine.showPillars : false) ? `
<path d="M525,90 L535,800 L515,800 L505,90 Z" fill="#0a1418" stroke="#22d3ee" stroke-width="2" opacity="0.9"/>
<path d="M1075,90 L1065,800 L1085,800 L1095,90 Z" fill="#0a1418" stroke="#22d3ee" stroke-width="2" opacity="0.9"/>
` : ''}
<g transform="translate(500, 838)">
<rect x="0" y="0" width="600" height="20" rx="10" fill="#22d3ee" opacity="0.85"/>
<text x="300" y="15" text-anchor="middle" fill="#000" font-family="'Antonio', sans-serif" font-weight="700" font-size="12" letter-spacing="3">USS VOYAGER // BRIDGE VIEWPORT</text>
</g>
</svg>
`;
}
if (era === 'ds9') {
// Defiant Class / DS9 Ops - angular, aggressive warship framing
return `
<svg viewBox="0 0 1600 900" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="defMetal" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#1c1410"/>
<stop offset="50%" stop-color="#0c0806"/>
<stop offset="100%" stop-color="#1c1410"/>
</linearGradient>
</defs>
<path d="M0,0 H1600 V60 L1300,170 H300 L0,60 Z" fill="url(#defMetal)" stroke="#f97316" stroke-width="3"/>
<path d="M0,900 H1600 V840 L1300,730 H300 L0,840 Z" fill="url(#defMetal)" stroke="#f97316" stroke-width="3"/>
<path d="M0,0 V900 H150 L190,730 V170 L150,0 Z" fill="url(#defMetal)" stroke="#f97316" stroke-width="3"/>
<path d="M1600,0 V900 H1450 L1410,730 V170 L1450,0 Z" fill="url(#defMetal)" stroke="#f97316" stroke-width="3"/>
<text x="800" y="865" text-anchor="middle" fill="#f97316" font-family="'Share Tech Mono', monospace" font-size="16" letter-spacing="4">USS DEFIANT // TACTICAL BRIDGE VIEWPORT</text>
</svg>
`;
}
if (era === 'nx') {
// Enterprise NX-01 - early, industrial, submarine-like bulkhead
return `
<svg viewBox="0 0 1600 900" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="nxMetal" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#1c1917"/>
<stop offset="50%" stop-color="#0c0a09"/>
<stop offset="100%" stop-color="#1c1917"/>
</linearGradient>
</defs>
<path d="M0,0 H1600 V110 L1420,175 H180 L0,110 Z" fill="url(#nxMetal)" stroke="#a16207" stroke-width="3"/>
<path d="M0,900 H1600 V790 L1420,725 H180 L0,790 Z" fill="url(#nxMetal)" stroke="#a16207" stroke-width="3"/>
<path d="M0,0 V900 H120 L150,725 V175 L120,0 Z" fill="url(#nxMetal)" stroke="#a16207" stroke-width="3"/>
<path d="M1600,0 V900 H1480 L1450,725 V175 L1480,0 Z" fill="url(#nxMetal)" stroke="#a16207" stroke-width="3"/>
<text x="800" y="865" text-anchor="middle" fill="#a16207" font-family="'Share Tech Mono', monospace" font-size="16" letter-spacing="4">ENTERPRISE NX-01 // COMMAND BRIDGE VIEWPORT</text>
</svg>
`;
}
// era === 'tng' (or unrecognized) falls through to the default Ten Forward arch below.
}
if (universeId === 'industrial' || universeId === 'outlaw') {
// Heavy Industrial Reinforced Bulkhead & Riveted Blast Shutter Framing
return `
<svg viewBox="0 0 1600 900" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="indMetal" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#1c1917"/>
<stop offset="50%" stop-color="#0c0a09"/>
<stop offset="100%" stop-color="#1c1917"/>
</linearGradient>
</defs>
<!-- Outer Reinforced Rim -->
<path d="M0,0 H1600 V100 L1460,160 H140 L0,100 Z" fill="url(#indMetal)" stroke="#b45309" stroke-width="3"/>
<path d="M0,900 H1600 V800 L1460,740 H140 L0,800 Z" fill="url(#indMetal)" stroke="#b45309" stroke-width="3"/>
<path d="M0,0 V900 H110 L140,740 V160 L110,0 Z" fill="url(#indMetal)" stroke="#b45309" stroke-width="3"/>
<path d="M1600,0 V900 H1490 L1460,740 V160 L1490,0 Z" fill="url(#indMetal)" stroke="#b45309" stroke-width="3"/>
${(engine ? engine.showPillars : false) ? `
<!-- Vertical Heavy Structural Mullions -->
<rect x="530" y="160" width="34" height="580" fill="#292524" stroke="#78350f" stroke-width="3"/>
<rect x="1036" y="160" width="34" height="580" fill="#292524" stroke="#78350f" stroke-width="3"/>
` : ''}
<!-- Hazard Stripes on Lower Sill -->
<g opacity="0.6">
<rect x="220" y="755" width="1160" height="14" fill="#f59e0b"/>
<path d="M230,755 L250,769 M270,755 L290,769 M310,755 L330,769 M350,755 L370,769 M390,755 L410,769 M430,755 L450,769 M470,755 L490,769 M510,755 L530,769" stroke="#000" stroke-width="6"/>
</g>
<text x="800" y="865" text-anchor="middle" fill="#d97706" font-family="'Share Tech Mono', monospace" font-size="16" letter-spacing="4">HEAVY INDUSTRIAL VIEWPORT // DECK 04 CARGO GANTRY</text>
</svg>
`;
}
if (universeId === 'whoniverse') {
// Gallifreyan Observatory Roundel Viewing Portal / TARDIS Frame
// Console era (classic/revival/modern) tints the rings and label.
let era = 'revival';
const wUniverse = (typeof UniverseRegistry !== 'undefined') ? UniverseRegistry['whoniverse'] : null;
const preset = (wUniverse && wUniverse.presets && presetId) ? wUniverse.presets[presetId] : null;
if (preset && preset.era) era = preset.era;
let ringA = '#d4af37', ringB = '#00e5ff', dash = '16 12', labelColor = '#d4af37';
let label = 'T.A.R.D.I.S. TEMPORAL VORTEX OBSERVATION PORTAL';
if (era === 'classic') {
ringA = '#b45309'; ringB = '#f5deb3'; dash = '22 10'; labelColor = '#f5deb3';
label = 'TYPE 40 CLASSIC CONSOLE // TEMPORAL VIEWPORT';
} else if (era === 'modern') {
ringA = '#e2e8f0'; ringB = '#94a3b8'; dash = '4 6'; labelColor = '#e2e8f0';
label = 'INFINITE WHITE // TEMPORAL OBSERVATION PORTAL';
}
return `
<svg viewBox="0 0 1600 900" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<!-- Circular Astrolabe Arch Frame -->
<path d="M0,0 H1600 V900 H0 Z M800,450 m-680,0 a680,410 0 1,0 1360,0 a680,410 0 1,0 -1360,0" fill="#030712" fill-rule="evenodd" stroke="${ringB}" stroke-width="4"/>
<!-- Gallifreyan Circular Inscriptions -->
<ellipse cx="800" cy="450" rx="690" ry="420" fill="none" stroke="${ringA}" stroke-width="3" stroke-dasharray="${dash}"/>
<ellipse cx="800" cy="450" rx="715" ry="440" fill="none" stroke="${ringB}" stroke-width="1.5" opacity="0.6"/>
<text x="800" y="875" text-anchor="middle" fill="${labelColor}" font-family="'Share Tech Mono', monospace" font-size="17" letter-spacing="4">${label}</text>
</svg>
`;
}
if (universeId === 'deepspace') {
// Terok Nor / DS9 Arched Station Viewport overlooking Docking Pylons
return `
<svg viewBox="0 0 1600 900" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0,0 H1600 V120 Q800,190 0,120 Z" fill="#0d1117" stroke="#38bdf8" stroke-width="3"/>
<path d="M0,900 H1600 V780 Q800,720 0,780 Z" fill="#0d1117" stroke="#38bdf8" stroke-width="3"/>
<path d="M0,0 V900 H140 L160,780 Q180,450 160,120 L140,0 Z" fill="#0d1117" stroke="#38bdf8" stroke-width="3"/>
<path d="M1600,0 V900 H1460 L1440,780 Q1420,450 1440,120 L1460,0 Z" fill="#0d1117" stroke="#38bdf8" stroke-width="3"/>
${(engine ? engine.showPillars : false) ? `
<!-- Exterior Docking Ring Structure visible outside -->
<path d="M180,520 L420,410 L440,430 L180,560 Z" fill="#1e293b" opacity="0.6" stroke="#38bdf8" stroke-width="2"/>
<path d="M1420,520 L1180,410 L1160,430 L1420,560 Z" fill="#1e293b" opacity="0.6" stroke="#38bdf8" stroke-width="2"/>
` : ''}
<text x="800" y="860" text-anchor="middle" fill="#38bdf8" font-family="'Share Tech Mono', monospace" font-size="16" letter-spacing="3">DEEP SPACE STATION // PROMENADE OBSERVATION DECK</text>
</svg>
`;
}
if (universeId === 'bioships' || universeId === 'retrofuture' || universeId === 'military' || universeId === 'comedy') {
// These four universes previously had no case here at all and silently fell through
// to the Starfleet default below, which hardcodes "USS ENTERPRISE" into the plaque --
// showing the wrong ship name in every one of these themes' Observation view.
// Fix: reuse the same bulkhead shape (it already themes correctly via the CSS
// accent variables set per universe), but pull the REAL ship/deck name for the
// plaque text from this universe's own preset data, same source the header uses.
const universe = UniverseRegistry[universeId];
const preset = (universe && universe.presets && presetId) ? universe.presets[presetId] : null;
const plaqueText = preset
? `${preset.name.toUpperCase()} // OBSERVATION DECK`
: `${universe ? universe.name : universeId.toUpperCase()} // OBSERVATION DECK`;
return `
<svg viewBox="0 0 1600 900" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="genBulkhead" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#1e222d"/>
<stop offset="50%" stop-color="#10141e"/>
<stop offset="100%" stop-color="#0a0d14"/>
</linearGradient>
</defs>
<path d="M0,0 H1600 V80 Q800,150 0,80 Z" fill="url(#genBulkhead)" stroke="var(--primary-accent, #ff9900)" stroke-width="3"/>
<path d="M0,900 H1600 V810 Q800,740 0,810 Z" fill="url(#genBulkhead)" stroke="var(--secondary-accent, #cc99cc)" stroke-width="3"/>
<path d="M0,0 V900 H90 Q120,450 90,0 Z" fill="url(#genBulkhead)"/>
<path d="M1600,0 V900 H1510 Q1480,450 1510,0 Z" fill="url(#genBulkhead)"/>
${(engine ? engine.showPillars : false) ? `
<path d="M510,95 L535,95 L545,765 L500,765 Z" fill="#151922" stroke="var(--tertiary-accent, #99ccff)" stroke-width="2.5" opacity="0.95"/>
<path d="M1090,95 L1065,95 L1055,765 L1100,765 Z" fill="#151922" stroke="var(--tertiary-accent, #99ccff)" stroke-width="2.5" opacity="0.95"/>
` : ''}
<g transform="translate(480, 830)">
<rect x="0" y="0" width="640" height="24" rx="12" fill="var(--primary-accent, #ff9900)" opacity="0.85"/>
<text x="320" y="17" text-anchor="middle" fill="#000" font-family="'Antonio', sans-serif" font-weight="700" font-size="14" letter-spacing="3">${plaqueText}</text>
</g>
</svg>
`;
}
// Default: Iconic Starfleet Ten Forward / Galaxy-Class Observation Lounge
return `
<svg viewBox="0 0 1600 900" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="sfBulkhead" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#1e222d"/>
<stop offset="50%" stop-color="#10141e"/>
<stop offset="100%" stop-color="#0a0d14"/>
</linearGradient>
</defs>
<!-- Top Arched Bulkhead Canopy -->
<path d="M0,0 H1600 V80 Q800,150 0,80 Z" fill="url(#sfBulkhead)" stroke="var(--primary-accent, #ff9900)" stroke-width="3"/>
<!-- Bottom Curved Padded Console Sill -->
<path d="M0,900 H1600 V810 Q800,740 0,810 Z" fill="url(#sfBulkhead)" stroke="var(--secondary-accent, #cc99cc)" stroke-width="3"/>
<!-- Side Bulkheads -->
<path d="M0,0 V900 H90 Q120,450 90,0 Z" fill="url(#sfBulkhead)"/>
<path d="M1600,0 V900 H1510 Q1480,450 1510,0 Z" fill="url(#sfBulkhead)"/>
${(engine ? engine.showPillars : false) ? `
<!-- Vertical Architectural Tapered Mullions dividing into 3 bays -->
<path d="M510,95 L535,95 L545,765 L500,765 Z" fill="#151922" stroke="var(--tertiary-accent, #99ccff)" stroke-width="2.5" opacity="0.95"/>
<path d="M1090,95 L1065,95 L1055,765 L1100,765 Z" fill="#151922" stroke="var(--tertiary-accent, #99ccff)" stroke-width="2.5" opacity="0.95"/>
` : ''}
<!-- Authentic LCARS Display Bar along lower sill -->
<g transform="translate(480, 830)">
<rect x="0" y="0" width="640" height="24" rx="12" fill="var(--primary-accent, #ff9900)" opacity="0.85"/>
<text x="320" y="17" text-anchor="middle" fill="#000" font-family="'Antonio', sans-serif" font-weight="700" font-size="14" letter-spacing="3">USS ENTERPRISE // OBSERVATION LOUNGE // DECK 10 FORWARD</text>
</g>
</svg>
`;
}
};