Files

2433 lines
60 KiB
CSS
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Authentic LCARD & Multi-Era Star Trek Styling
* Includes TNG 24th Century, TOS Retro 23rd Century, and NX-01 Industrial themes.
*/
@import url('https://fonts.googleapis.com/css2?family=Antonio:wght@400;600;700&family=Share+Tech+Mono&display=swap');
:root {
/* TNG 24th Century LCARD Palette */
--lcars-orange: #ff9900;
--lcars-tangerine: #ff6600;
--lcars-amber: #cc6600;
--lcars-sand: #ffcc66;
--lcars-lavender: #cc99cc;
--lcars-violet: #9966cc;
--lcars-ice-blue: #99ccff;
--lcars-blue: #3366cc;
--lcars-red: #cc3333;
--lcars-crimson: #990000;
--lcars-bg: #000000;
--lcars-panel-bg: #0d0f14;
--lcars-font: 'Antonio', 'Arial Narrow', sans-serif;
--mono-font: 'Share Tech Mono', monospace;
/* Theme variables (Defaults to TNG) */
--primary-accent: var(--lcars-orange);
--secondary-accent: var(--lcars-lavender);
--tertiary-accent: var(--lcars-ice-blue);
--warning-accent: var(--lcars-red);
}
/* Wayfarer Era Palette */
body.theme-lcars-voyager {
--primary-accent: #3399cc;
--secondary-accent: #9999ff;
--tertiary-accent: #66cccc;
--warning-accent: #cc3333;
}
/* Defiance Combat Palette */
body.theme-lcars-defiant {
--primary-accent: #cc5500;
--secondary-accent: #aa3300;
--tertiary-accent: #dd8800;
--warning-accent: #ff0000;
}
/* Deep Space Nine Palette */
body.theme-lcars-ds9 {
--primary-accent: #997755;
--secondary-accent: #bb8844;
--tertiary-accent: #667788;
--warning-accent: #bb3322;
}
/* TOS Retro 23rd Century Palette */
body.theme-tos-retro {
--primary-accent: #ffcc00;
--secondary-accent: #0099ff;
--tertiary-accent: #cc0000;
--lcars-panel-bg: #15181c;
--lcars-font: 'Share Tech Mono', monospace;
}
/* NX Industrial Palette */
body.theme-nx-industrial {
--primary-accent: #33bbee;
--secondary-accent: #88aacc;
--tertiary-accent: #445566;
--lcars-panel-bg: #0e1217;
--lcars-font: 'Share Tech Mono', monospace;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
user-select: none;
}
body {
background-color: var(--lcars-bg);
color: #ffffff;
font-family: var(--lcars-font);
letter-spacing: 0.05em;
overflow-x: hidden;
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* Header & Frame */
.lcars-header {
display: flex;
align-items: stretch;
height: 64px;
background: transparent;
padding: 8px 16px 0 16px;
gap: 12px;
}
.lcars-elbow-left {
width: 180px;
background-color: var(--primary-accent);
border-top-left-radius: 32px;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 14px;
font-size: 1.25rem;
font-weight: 700;
color: #000000;
text-transform: uppercase;
}
.lcars-top-bar {
flex: 1;
background-color: var(--secondary-accent);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px;
font-size: 1.1rem;
font-weight: 700;
color: #000000;
text-transform: uppercase;
}
.lcars-pill-end {
width: 70px;
background-color: var(--tertiary-accent);
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}
/* Header Volume Dock */
.header-volume-dock {
display: flex;
align-items: center;
gap: 8px;
background: rgba(0, 0, 0, 0.25);
padding: 2px 10px;
border-radius: 12px;
}
.btn-header-mute {
background: #000000;
color: var(--secondary-accent);
border: 1px solid var(--secondary-accent);
border-radius: 8px;
padding: 2px 8px;
font-family: var(--lcars-font);
font-size: 0.8rem;
font-weight: 700;
cursor: pointer;
transition: all 0.15s;
}
.btn-header-mute:hover {
background: var(--secondary-accent);
color: #000;
}
.btn-header-mute.muted {
background: #ff0000;
color: #ffffff;
border-color: #ff0000;
}
.header-vol-val {
font-family: var(--mono-font);
font-size: 0.85rem;
color: #000;
font-weight: 700;
min-width: 32px;
}
/* Main Layout Grid */
.lcars-container {
display: grid;
grid-template-columns: 240px 1fr 300px;
gap: 16px;
padding: 16px;
flex: 1;
}
@media (max-width: 1080px) {
.lcars-container {
grid-template-columns: 220px 1fr;
}
.right-column {
grid-column: span 2;
}
}
@media (max-width: 768px) {
.lcars-container {
grid-template-columns: 1fr;
}
.lcars-elbow-left {
width: 100px;
font-size: 0.9rem;
}
}
/* Left Sidebar - Presets & Ship Selector */
.left-sidebar {
display: flex;
flex-direction: column;
gap: 10px;
}
.sidebar-heading {
background-color: var(--primary-accent);
color: #000;
padding: 6px 12px;
font-weight: 700;
font-size: 1rem;
text-transform: uppercase;
border-radius: 4px;
}
.preset-list {
display: flex;
flex-direction: column;
gap: 6px;
max-height: calc(100vh - 220px);
overflow-y: auto;
padding-right: 4px;
}
.preset-btn {
background-color: #1a1e27;
color: #e0e6ed;
border: 2px solid transparent;
padding: 10px 12px;
text-align: left;
font-family: var(--lcars-font);
font-size: 0.95rem;
font-weight: 600;
text-transform: uppercase;
border-radius: 0 16px 16px 0;
cursor: pointer;
transition: all 0.15s ease;
display: flex;
flex-direction: column;
gap: 2px;
}
.preset-btn:hover {
background-color: #272d3b;
border-left: 6px solid var(--primary-accent);
padding-left: 8px;
}
.preset-btn.active {
background-color: var(--primary-accent);
color: #000000;
font-weight: 700;
}
.preset-btn .ship-era-tag {
font-size: 0.7rem;
opacity: 0.75;
font-family: var(--mono-font);
}
/* Center Panel - Main Controls & Mixers */
.center-panel {
display: flex;
flex-direction: column;
gap: 16px;
}
.panel-card {
background-color: var(--lcars-panel-bg);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 8px;
padding: 16px;
display: flex;
flex-direction: column;
gap: 14px;
}
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid var(--primary-accent);
padding-bottom: 6px;
}
.panel-title {
font-size: 1.25rem;
font-weight: 700;
color: var(--primary-accent);
text-transform: uppercase;
}
.panel-sub {
font-family: var(--mono-font);
font-size: 0.85rem;
color: #8899aa;
}
/* Transport Controls Bar */
.transport-bar {
display: flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
}
.btn-lcars-large {
background-color: var(--primary-accent);
color: #000;
font-family: var(--lcars-font);
font-size: 1.3rem;
font-weight: 700;
padding: 12px 28px;
border: none;
border-radius: 24px;
cursor: pointer;
text-transform: uppercase;
transition: transform 0.1s, filter 0.15s;
display: inline-flex;
align-items: center;
gap: 8px;
}
.btn-lcars-large:hover {
filter: brightness(1.2);
}
.btn-lcars-large:active {
transform: scale(0.97);
}
.btn-lcars-large.playing {
background-color: #ff3333;
color: #fff;
}
/* Master Engage / Full Stop Play Button */
#btn-master-play {
background: #00cc66;
color: #000000;
box-shadow: 0 0 12px rgba(0, 204, 102, 0.45);
transition: transform 0.1s, filter 0.15s, background-color 0.2s, box-shadow 0.2s;
}
#btn-master-play:hover {
filter: brightness(1.2);
}
#btn-master-play.playing {
background: #ff3333;
color: #ffffff;
box-shadow: 0 0 14px rgba(255, 51, 51, 0.5);
}
#btn-master-play.engaging {
animation: lcars-engage-flash 0.35s infinite alternate ease-in-out;
}
#btn-master-play.stopping {
animation: lcars-stop-flash 0.35s infinite alternate ease-in-out;
}
@keyframes lcars-engage-flash {
0% {
background: #00cc66;
color: #000000;
box-shadow: 0 0 6px rgba(0, 204, 102, 0.4);
filter: brightness(0.95);
}
100% {
background: #33ff99;
color: #000000;
box-shadow: 0 0 24px rgba(0, 255, 136, 0.95);
filter: brightness(1.35);
}
}
@keyframes lcars-stop-flash {
0% {
background: #ff3333;
color: #ffffff;
box-shadow: 0 0 6px rgba(255, 51, 51, 0.4);
filter: brightness(0.95);
}
100% {
background: #ff6666;
color: #ffffff;
box-shadow: 0 0 24px rgba(255, 51, 51, 0.95);
filter: brightness(1.35);
}
}
/* Action Pill Buttons */
.pill-button-group {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.btn-lcars-pill {
background-color: var(--secondary-accent);
color: #000;
font-family: var(--lcars-font);
font-size: 0.95rem;
font-weight: 700;
padding: 8px 16px;
border: none;
border-radius: 14px;
cursor: pointer;
text-transform: uppercase;
transition: all 0.15s;
}
.btn-lcars-pill:hover {
filter: brightness(1.25);
}
.btn-lcars-pill.active-alert {
background-color: #ff0000 !important;
color: #ffffff !important;
animation: lcars-red-pulse 1s infinite alternate;
}
@keyframes lcars-red-pulse {
0% { box-shadow: 0 0 4px #ff0000; }
100% { box-shadow: 0 0 20px #ff0000; }
}
/* Dedicated Master Volume Console */
.master-volume-console {
background: rgba(255, 153, 0, 0.05);
border: 1px solid var(--primary-accent);
border-left: 6px solid var(--primary-accent);
border-radius: 6px;
padding: 12px 16px;
display: flex;
flex-direction: column;
gap: 10px;
}
.master-vol-top {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
.master-vol-title-group {
display: flex;
align-items: baseline;
gap: 10px;
}
.master-vol-tag {
font-family: var(--lcars-font);
font-size: 1.05rem;
font-weight: 700;
color: var(--primary-accent);
text-transform: uppercase;
}
.master-vol-readout {
font-family: var(--mono-font);
font-size: 1.4rem;
font-weight: 700;
color: #ffffff;
}
.master-vol-db {
font-family: var(--mono-font);
font-size: 0.85rem;
color: #00e6ff;
}
.master-vol-actions {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.btn-mute {
background-color: var(--primary-accent);
color: #000;
font-weight: 700;
min-width: 68px;
text-align: center;
}
.btn-mute.muted {
background-color: #ff0000 !important;
color: #ffffff !important;
box-shadow: 0 0 10px #ff0000;
}
.master-vol-presets {
display: flex;
gap: 4px;
}
.btn-vol-step {
background: #1e2430;
color: #a0b4cc;
border: 1px solid #334455;
border-radius: 4px;
padding: 4px 8px;
font-family: var(--mono-font);
font-size: 0.75rem;
cursor: pointer;
transition: all 0.1s;
}
.btn-vol-step:hover {
background: var(--primary-accent);
color: #000;
border-color: var(--primary-accent);
}
.btn-vol-step.active {
background: var(--primary-accent);
color: #000;
font-weight: bold;
}
/* Master Slider Row & Level Meter */
.master-slider-row {
display: flex;
align-items: center;
gap: 12px;
}
.vol-adj-btn {
width: 32px;
height: 32px;
background: #1b212c;
color: var(--primary-accent);
border: 1px solid var(--primary-accent);
border-radius: 50%;
font-family: var(--mono-font);
font-size: 1.2rem;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.1s;
flex-shrink: 0;
}
.vol-adj-btn:hover {
background: var(--primary-accent);
color: #000;
}
.vol-adj-btn:active {
transform: scale(0.92);
}
.slider-track-container {
flex: 1;
display: flex;
flex-direction: column;
gap: 6px;
}
.slider-master-large {
height: 12px !important;
border-radius: 6px !important;
background: #161b24 !important;
}
.slider-master-large::-webkit-slider-thumb {
width: 24px !important;
height: 24px !important;
background: var(--primary-accent) !important;
box-shadow: 0 0 10px rgba(255, 153, 0, 0.8) !important;
}
/* Segmented LED Volume Meter */
.vol-meter-leds {
display: flex;
gap: 3px;
height: 6px;
width: 100%;
}
.led-pip {
flex: 1;
background: #18202c;
border-radius: 1px;
transition: background 0.08s;
}
.led-pip.active:nth-child(-n+6) {
background: #00e6ff;
box-shadow: 0 0 4px #00e6ff;
}
.led-pip.active:nth-child(n+7):nth-child(-n+8) {
background: #ffcc00;
box-shadow: 0 0 4px #ffcc00;
}
.led-pip.active:nth-child(n+9) {
background: #ff3333;
box-shadow: 0 0 4px #ff3333;
}
/* Futuristic Noice Cancellation (FNC) */
.fnc-console{
margin-top:2px;padding:10px 12px;border:1px solid rgba(0,230,255,.26);
border-left:5px solid var(--tertiary-accent);border-radius:6px;
background:rgba(0,230,255,.035);display:flex;flex-direction:column;gap:8px;
}
.fnc-top{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}
.fnc-title-group{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}
.fnc-title{font-family:var(--lcars-font);font-weight:700;color:var(--tertiary-accent);letter-spacing:.08em}
.fnc-state{font-family:var(--mono-font);font-size:.72rem;color:#9fb4c9;letter-spacing:.08em}
.fnc-state.active{color:#00ff88;text-shadow:0 0 7px rgba(0,255,136,.45)}
.fnc-state.hold{color:#ffcc00}.fnc-state.recovering{color:#7dd3fc}.fnc-state.off{color:#778899}
.btn-fnc{background:#152333;color:var(--tertiary-accent);border:1px solid var(--tertiary-accent)}
.btn-fnc.enabled{background:var(--tertiary-accent);color:#000;box-shadow:0 0 10px color-mix(in srgb,var(--tertiary-accent) 55%,transparent)}
.fnc-level-row{display:grid;grid-template-columns:auto 1fr auto;gap:10px;align-items:center}
.fnc-level-label,.fnc-level-value{font-family:var(--mono-font);font-size:.72rem;color:#c7d5e5;white-space:nowrap}
.fnc-level-value{min-width:42px;text-align:right;color:var(--tertiary-accent)}
.fnc-detail{font-family:var(--mono-font);font-size:.61rem;line-height:1.35;color:#71869a;min-height:1.35em}
/* Multi-Channel Synthesizer Mixer */
.mixer-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 14px;
}
.channel-strip {
background: rgba(255, 255, 255, 0.03);
border-left: 4px solid var(--primary-accent);
padding: 12px;
border-radius: 0 8px 8px 0;
display: flex;
flex-direction: column;
gap: 10px;
}
.channel-header {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.95rem;
font-weight: 700;
color: var(--primary-accent);
text-transform: uppercase;
}
.control-row {
display: flex;
flex-direction: column;
gap: 4px;
}
.control-label {
display: flex;
justify-content: space-between;
font-family: var(--mono-font);
font-size: 0.75rem;
color: #a0b0c0;
}
/* Sliders */
input[type="range"] {
-webkit-appearance: none;
width: 100%;
height: 8px;
background: #202634;
border-radius: 4px;
outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 18px;
height: 18px;
border-radius: 50%;
background: var(--primary-accent);
cursor: pointer;
border: 2px solid #000;
box-shadow: 0 0 6px rgba(255, 153, 0, 0.5);
}
/* Right Sidebar - Worp Core & Diagnostic Monitor */
.right-column {
display: flex;
flex-direction: column;
gap: 16px;
}
.telemetry-triggers {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.btn-chirp {
background-color: #232b3b;
color: var(--tertiary-accent);
border: 1px solid var(--tertiary-accent);
border-radius: 6px;
padding: 8px;
font-family: var(--lcars-font);
font-size: 0.85rem;
font-weight: 600;
cursor: pointer;
text-transform: uppercase;
transition: all 0.1s;
}
.btn-chirp:hover {
background-color: var(--tertiary-accent);
color: #000;
}
.btn-chirp:active {
transform: scale(0.95);
}
/* Sleep Timer Display */
.timer-readout {
font-family: var(--mono-font);
font-size: 1.1rem;
color: #00e6ff;
text-align: center;
background: #131a26;
padding: 6px;
border-radius: 4px;
border: 1px solid rgba(0, 230, 255, 0.3);
}
/* Footer status bar */
.lcars-footer {
margin-top: auto;
padding: 8px 16px;
background-color: var(--primary-accent);
color: #000;
display: flex;
justify-content: space-between;
font-weight: 700;
font-size: 0.9rem;
text-transform: uppercase;
}
/**
* Canvas Visualizers & Diagnostic Displays CSS
*/
.visualizer-container {
display: flex;
flex-direction: column;
gap: 8px;
}
.canvas-wrapper {
position: relative;
width: 100%;
background-color: #080b10;
border: 1px solid rgba(255, 153, 0, 0.25);
border-radius: 6px;
overflow: hidden;
}
.canvas-wrapper canvas {
display: block;
width: 100%;
}
.spectrum-wrapper {
height: 140px;
}
.warp-core-wrapper {
height: 240px;
}
.canvas-label-overlay {
position: absolute;
top: 6px;
left: 8px;
font-family: var(--mono-font);
font-size: 0.7rem;
color: var(--primary-accent);
letter-spacing: 0.1em;
pointer-events: none;
background: rgba(0, 0, 0, 0.6);
padding: 2px 6px;
border-radius: 3px;
}
.diagnostic-stats {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
font-family: var(--mono-font);
font-size: 0.75rem;
}
.stat-box {
background: rgba(255, 255, 255, 0.04);
padding: 6px 8px;
border-left: 2px solid var(--secondary-accent);
display: flex;
flex-direction: column;
}
.stat-label {
color: #8899aa;
font-size: 0.65rem;
}
.stat-value {
color: #00e6ff;
font-weight: bold;
}
/**
* Whataverse (Doctor Who TARDIX) Aesthetic Stylesheet & Universe Switcher Dropdown
*/
/* Universe Switcher Dropdown */
.universe-selector-container {
position: relative;
display: inline-block;
cursor: pointer;
}
.universe-dropdown-menu {
display: none;
position: absolute;
top: 100%;
left: 0;
min-width: 220px;
background-color: #0b111a;
border: 2px solid var(--primary-accent);
border-radius: 0 0 12px 12px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.9);
z-index: 1000;
overflow: hidden;
}
.universe-dropdown-menu.show {
display: flex;
flex-direction: column;
}
.universe-item {
display: flex;
align-items: center;
gap: 10px;
padding: 12px 16px;
color: #ffffff;
font-family: var(--lcars-font);
font-size: 1rem;
font-weight: 700;
text-transform: uppercase;
background: transparent;
border: none;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
cursor: pointer;
text-align: left;
transition: all 0.15s ease;
}
.universe-item:hover {
background-color: var(--primary-accent);
color: #000000;
}
.universe-item.active {
background-color: rgba(255, 255, 255, 0.12);
border-left: 4px solid var(--primary-accent);
}
.universe-item .u-icon {
font-size: 1.2rem;
width: 24px;
text-align: center;
}
/* ==========================================================================
WHATAVERSE (TARDIX CONSOLE) THEME
========================================================================== */
body.theme-whataverse-tardix {
--tardix-blue: #003b6f;
--tardix-deep: #001f3f;
--tardix-cyan: #00e5ff;
--tardix-teal: #008080;
--tardix-amber: #d4af37;
--tardix-brass: #b8860b;
--tardix-roundel: #e0f2fe;
--primary-accent: var(--tardix-cyan);
--secondary-accent: var(--tardix-blue);
--tertiary-accent: var(--tardix-amber);
--warning-accent: #cc0000;
--lcars-bg: #030712;
--lcars-panel-bg: #070e1b;
--lcars-font: 'Share Tech Mono', monospace;
background-color: #030712;
background-image:
radial-gradient(circle at 50% 10%, rgba(0, 59, 111, 0.3) 0%, transparent 60%),
radial-gradient(circle at 10% 90%, rgba(0, 229, 255, 0.05) 0%, transparent 40%);
}
/* Header Styling for TARDIX Police Box */
body.theme-whataverse-tardix .lcars-elbow-left {
background: linear-gradient(135deg, #004a8b, #002244);
color: #ffffff;
border: 1px solid var(--tardix-cyan);
border-radius: 4px 4px 0 0;
box-shadow: 0 0 12px rgba(0, 229, 255, 0.3);
letter-spacing: 0.15em;
}
body.theme-whataverse-tardix .lcars-top-bar {
background: #001f3f;
color: #ffffff;
border: 1px solid rgba(0, 229, 255, 0.4);
border-radius: 4px;
}
body.theme-whataverse-tardix .header-vol-val {
color: var(--tardix-cyan);
}
body.theme-whataverse-tardix .lcars-pill-end {
background-color: var(--tardix-amber);
border-radius: 4px;
}
/* TARDIX Roundel Buttons & Cards */
body.theme-whataverse-tardix .sidebar-heading {
background: linear-gradient(90deg, #003b6f, #001f3f);
color: var(--tardix-cyan);
border-left: 4px solid var(--tardix-cyan);
letter-spacing: 0.1em;
}
body.theme-whataverse-tardix .preset-btn {
background: rgba(0, 59, 111, 0.2);
border: 1px solid rgba(0, 229, 255, 0.2);
border-radius: 8px;
color: #e2e8f0;
}
body.theme-whataverse-tardix .preset-btn:hover {
background: rgba(0, 229, 255, 0.15);
border-color: var(--tardix-cyan);
box-shadow: 0 0 8px rgba(0, 229, 255, 0.3);
}
body.theme-whataverse-tardix .preset-btn.active {
background: linear-gradient(135deg, #003b6f, #002244);
border: 1px solid var(--tardix-cyan);
color: #ffffff;
box-shadow: 0 0 15px rgba(0, 229, 255, 0.5);
}
/* Master Play Button for TARDIX */
body.theme-whataverse-tardix .btn-lcars-large {
background: linear-gradient(135deg, #00e5ff, #0088cc);
color: #000000;
border-radius: 8px;
box-shadow: 0 0 16px rgba(0, 229, 255, 0.4);
}
body.theme-whataverse-tardix .btn-lcars-large.playing {
background: linear-gradient(135deg, #d4af37, #996515);
color: #ffffff;
box-shadow: 0 0 20px rgba(212, 175, 55, 0.6);
}
/* Roundel Keypad Buttons */
body.theme-whataverse-tardix .btn-chirp {
background: radial-gradient(circle, rgba(0, 229, 255, 0.1) 0%, rgba(0, 31, 63, 0.4) 100%);
border: 1px solid rgba(0, 229, 255, 0.4);
border-radius: 20px;
color: #b0e0e6;
transition: all 0.2s;
}
body.theme-whataverse-tardix .btn-chirp:hover {
background: var(--tardix-cyan);
color: #000000;
box-shadow: 0 0 12px var(--tardix-cyan);
}
/* Cloister Chime Active Siren */
body.theme-whataverse-tardix .btn-lcars-pill.active-alert {
background-color: #ff3300 !important;
color: #ffffff !important;
animation: cloister-pulse 1.2s infinite alternate;
}
@keyframes cloister-pulse {
0% { box-shadow: 0 0 4px #ff3300; }
100% { box-shadow: 0 0 25px #ff3300; }
}
/* TARDIX Footer */
body.theme-whataverse-tardix .lcars-footer {
background: linear-gradient(90deg, #001f3f, #003b6f);
color: var(--tardix-cyan);
border-top: 1px solid rgba(0, 229, 255, 0.3);
}
/**
* Expanded Sci-Fi Universes Themes Stylesheet
* Custom visual aesthetics for: Industrial, Bioships, Retro Future, Military,
* Deep Space, Outlaw / Frontier, Space Stations, and Comedy / Adventure.
*/
/* ==========================================================================
1. INDUSTRIAL SPACE (Weylan-Yutaro, Firefly, Expanse, Mining Grit)
========================================================================== */
body.theme-industrial {
--primary-accent: #ffaa00;
--secondary-accent: #b45309;
--tertiary-accent: #d97706;
--warning-accent: #dc2626;
--lcars-bg: #0d0a07;
--lcars-panel-bg: #140f0a;
--lcars-font: 'Share Tech Mono', monospace;
background-color: #0d0a07;
background-image: repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.25) 2px, transparent 2px, transparent 4px);
}
body.theme-industrial .lcars-elbow-left {
background: linear-gradient(135deg, #b45309, #78350f);
color: #ffaa00;
border: 1px solid #ffaa00;
border-radius: 2px;
box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.8);
}
body.theme-industrial .lcars-top-bar {
background: #1e150d;
color: #ffaa00;
border-bottom: 2px solid #b45309;
}
body.theme-industrial .panel-card {
border: 1px solid #451a03;
border-left: 4px solid #b45309;
}
body.theme-industrial .preset-btn {
background: #1a120b;
border-left: 3px solid #78350f;
color: #fdba74;
}
body.theme-industrial .preset-btn.active {
background: #b45309;
color: #000000;
font-weight: bold;
}
/* ==========================================================================
2. BIOSHIPS (Living Starships, Moya, Lexx, Species 8675309)
========================================================================== */
body.theme-bioships {
--primary-accent: #10b981;
--secondary-accent: #8b5cf6;
--tertiary-accent: #065f46;
--warning-accent: #ef4444;
--lcars-bg: #021a12;
--lcars-panel-bg: #04271c;
--lcars-font: 'Antonio', sans-serif;
background-color: #021a12;
background-image: radial-gradient(circle at 50% 50%, rgba(139, 92, 246, 0.12) 0%, transparent 70%);
}
body.theme-bioships .lcars-elbow-left {
background: linear-gradient(135deg, #059669, #4c1d95);
color: #ffffff;
border-radius: 28px 0 28px 0;
box-shadow: 0 0 18px rgba(16, 185, 129, 0.4);
}
body.theme-bioships .lcars-top-bar {
background: #064e3b;
color: #a7f3d0;
border-radius: 0 16px 16px 0;
}
body.theme-bioships .panel-card {
border: 1px solid rgba(16, 185, 129, 0.25);
border-radius: 14px;
}
body.theme-bioships .preset-btn {
border-radius: 12px;
background: rgba(16, 185, 129, 0.08);
color: #d1fae5;
}
body.theme-bioships .preset-btn.active {
background: linear-gradient(90deg, #10b981, #7c3aed);
color: #000000;
font-weight: bold;
}
/* ==========================================================================
3. RETRO FUTURE (1950s1970s Golden Age, 2001, Jupiter 2)
========================================================================== */
body.theme-retrofuture {
--primary-accent: #22c55e;
--secondary-accent: #15803d;
--tertiary-accent: #86efac;
--warning-accent: #dc2626;
--lcars-bg: #03140a;
--lcars-panel-bg: #052212;
--lcars-font: 'Share Tech Mono', monospace;
background-color: #03140a;
}
body.theme-retrofuture .lcars-elbow-left {
background: #15803d;
color: #bbf7d0;
border-radius: 8px;
border: 2px solid #22c55e;
}
body.theme-retrofuture .lcars-top-bar {
background: #052e16;
color: #22c55e;
border: 1px solid #15803d;
}
body.theme-retrofuture .preset-btn {
background: #052914;
border: 1px solid #14532d;
color: #86efac;
}
body.theme-retrofuture .preset-btn.active {
background: #22c55e;
color: #000000;
box-shadow: 0 0 12px #22c55e;
}
/* ==========================================================================
4. MILITARY SPACE (Battlestar Galactica, Sulaco, Fleet Combat)
========================================================================== */
body.theme-military {
--primary-accent: #eab308;
--secondary-accent: #71717a;
--tertiary-accent: #ca8a04;
--warning-accent: #ef4444;
--lcars-bg: #09090b;
--lcars-panel-bg: #18181b;
--lcars-font: 'Share Tech Mono', monospace;
}
body.theme-military .lcars-elbow-left {
background: #27272a;
color: #eab308;
border: 2px solid #eab308;
border-radius: 0;
font-weight: 900;
}
body.theme-military .lcars-top-bar {
background: #18181b;
color: #fef08a;
border-bottom: 2px solid #eab308;
}
body.theme-military .panel-card {
border: 1px solid #3f3f46;
border-left: 4px solid #eab308;
}
body.theme-military .preset-btn {
background: #27272a;
border: 1px solid #3f3f46;
color: #e4e4e7;
border-radius: 2px;
}
body.theme-military .preset-btn.active {
background: #eab308;
color: #000000;
font-weight: bold;
}
/* ==========================================================================
5. DEEP SPACE (Generation Ships, Icarus II, Event Horizon)
========================================================================== */
body.theme-deepspace {
--primary-accent: #6366f1;
--secondary-accent: #312e81;
--tertiary-accent: #38bdf8;
--warning-accent: #f43f5e;
--lcars-bg: #030712;
--lcars-panel-bg: #0b0f19;
--lcars-font: 'Antonio', sans-serif;
background-image: radial-gradient(circle at 80% 20%, rgba(99, 102, 241, 0.15) 0%, transparent 60%);
}
body.theme-deepspace .lcars-elbow-left {
background: linear-gradient(135deg, #4338ca, #1e1b4b);
color: #e0e7ff;
border: 1px solid #6366f1;
}
body.theme-deepspace .lcars-top-bar {
background: #111827;
color: #818cf8;
}
body.theme-deepspace .preset-btn {
background: rgba(49, 46, 129, 0.25);
border: 1px solid rgba(99, 102, 241, 0.25);
color: #c7d2fe;
}
body.theme-deepspace .preset-btn.active {
background: #6366f1;
color: #ffffff;
box-shadow: 0 0 15px rgba(99, 102, 241, 0.6);
}
/* ==========================================================================
6. OUTLAW / FRONTIER (Cowboy Bebop, Outlaw Star, Milano, Betty)
========================================================================== */
body.theme-outlaw {
--primary-accent: #ec4899;
--secondary-accent: #f59e0b;
--tertiary-accent: #8b5cf6;
--warning-accent: #ef4444;
--lcars-bg: #0f0714;
--lcars-panel-bg: #1a0c23;
--lcars-font: 'Share Tech Mono', monospace;
}
body.theme-outlaw .lcars-elbow-left {
background: linear-gradient(135deg, #db2777, #9d174d);
color: #fef08a;
box-shadow: 0 0 14px rgba(236, 72, 153, 0.4);
}
body.theme-outlaw .lcars-top-bar {
background: #200d2d;
color: #f472b6;
border-bottom: 2px solid #ec4899;
}
body.theme-outlaw .preset-btn {
background: #261135;
border: 1px solid rgba(236, 72, 153, 0.3);
color: #fbcfe8;
}
body.theme-outlaw .preset-btn.active {
background: linear-gradient(90deg, #ec4899, #f59e0b);
color: #000000;
font-weight: bold;
}
/* ==========================================================================
7. SPACE STATIONS (Babylon 5, Moonbase Alpha, Sevastopol, Tycho)
========================================================================== */
body.theme-spacestations {
--primary-accent: #f97316;
--secondary-accent: #0284c7;
--tertiary-accent: #38bdf8;
--warning-accent: #dc2626;
--lcars-bg: #050b14;
--lcars-panel-bg: #0a1322;
--lcars-font: 'Share Tech Mono', monospace;
}
body.theme-spacestations .lcars-elbow-left {
background: #ea580c;
color: #000000;
border-radius: 4px;
}
body.theme-spacestations .lcars-top-bar {
background: #0f1e33;
color: #fdba74;
border-bottom: 2px solid #0284c7;
}
body.theme-spacestations .preset-btn {
background: #0e1b2e;
border-left: 3px solid #0284c7;
color: #bae6fd;
}
body.theme-spacestations .preset-btn.active {
background: #f97316;
color: #000000;
font-weight: bold;
}
/* ==========================================================================
8. COMEDY / ADVENTURE (The Orville, Heart of Gold, Spaceballs)
========================================================================== */
body.theme-comedy {
--primary-accent: #06b6d4;
--secondary-accent: #f43f5e;
--tertiary-accent: #fbbf24;
--warning-accent: #ef4444;
--lcars-bg: #0c0a21;
--lcars-panel-bg: #151233;
--lcars-font: 'Antonio', sans-serif;
background-image: radial-gradient(circle at 50% 10%, rgba(6, 182, 212, 0.2) 0%, transparent 60%);
}
body.theme-comedy .lcars-elbow-left {
background: linear-gradient(135deg, #06b6d4, #f43f5e);
color: #ffffff;
border-radius: 20px;
box-shadow: 0 0 16px rgba(6, 182, 212, 0.5);
}
body.theme-comedy .lcars-top-bar {
background: #1e1b4b;
color: #67e8f9;
}
body.theme-comedy .preset-btn {
background: rgba(6, 182, 212, 0.1);
border: 1px solid rgba(6, 182, 212, 0.3);
border-radius: 12px;
color: #cffafe;
}
body.theme-comedy .preset-btn.active {
background: linear-gradient(90deg, #06b6d4, #fbbf24);
color: #000000;
font-weight: bold;
}
/* ==========================================================================
OBSERVATION MODE
Passive casting / display view. Click anywhere to return.
========================================================================== */
.btn-observation {
background: transparent !important;
color: var(--primary-accent) !important;
border: 2px solid var(--primary-accent) !important;
}
.btn-observation:hover {
background: var(--primary-accent) !important;
color: #000 !important;
}
.observation-overlay {
position: fixed;
inset: 0;
z-index: 10000;
display: none;
background: #010308;
overflow: hidden;
cursor: default;
}
.observation-overlay.active {
display: block;
}
/* Layer 0 & 1: 60fps Deep Celestial Canvas */
.observation-canvas {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
z-index: 1;
pointer-events: none;
display: block;
}
.observation-stage {
position: absolute;
inset: 0;
z-index: 2;
overflow: hidden;
pointer-events: none;
}
.observation-stage svg {
width: 100%;
height: 100%;
display: block;
}
/* Allow 60fps dynamic celestial canvas to show through legacy SVG stage while preserving telemetry & HUDs.
NOTE (v2cs): this previously read `rect:first-child`, which never matched -- every renderer's
<defs> block is the true first child of the <svg>, so the background rect is actually the second
child (or, more robustly, simply the first element of its own tag type). That silently left an
opaque near-black rectangle sitting on z-index 2, directly over the canvas engine at z-index 1,
hiding almost everything the canvas draws for every theme. Fixed by matching on type instead of
position.
NOTE (v3co): the selector above is correct but was applied GLOBALLY, which uncovered the
shared canvas layer stack in nine themes simultaneously. It is now scoped behind
`.obs-canvas-on`, a class toggled in ObservationEngine.start() from the OBSERVATION_CANVAS
manifest. Themes declared canvas:false keep their opaque background rect -- their
OBSERVATION display is their own bespoke SVG art and nothing else. */
.observation-overlay.obs-canvas-on .observation-stage svg > rect:first-of-type {
display: none;
}
.observation-stage svg g[style*="obs-drift-left"],
.observation-stage svg g[style*="obs-drift-right"] {
display: none;
}
/* Space Stations Native Viewport respect & toggle */
.obs-station-bulkhead {
transition: opacity 0.4s ease;
}
.obs-station-frame {
transition: opacity 0.4s ease;
}
.obs-viewport-hidden .obs-station-bulkhead,
.obs-viewport-hidden .obs-station-frame {
opacity: 0;
}
/* Layer 2: Architectural Starship Viewport Framing */
.observation-viewport-frame {
position: absolute;
inset: 0;
z-index: 4;
pointer-events: none;
transition: opacity 0.4s ease;
overflow: hidden;
}
.observation-viewport-frame svg {
width: 100%;
height: 100%;
display: block;
}
.observation-viewport-frame.frame-hidden {
opacity: 0;
}
.observation-glass-sheen {
position: absolute;
inset: 0;
z-index: 5;
pointer-events: none;
background: linear-gradient(135deg, rgba(255,255,255,0.055) 0%, transparent 42%, rgba(255,255,255,0.02) 68%, transparent 100%);
}
.observation-scanlines {
position: absolute;
inset: 0;
z-index: 6;
pointer-events: none;
opacity: .14;
background: repeating-linear-gradient(
0deg,
rgba(255,255,255,.04) 0px,
rgba(255,255,255,.04) 1px,
transparent 1px,
transparent 4px
);
}
.observation-vignette {
position: absolute;
inset: 0;
z-index: 7;
pointer-events: none;
box-shadow: inset 0 0 16vw rgba(0,0,0,.82);
}
/* Layer 3: Emergency Alert Lighting Wash */
.observation-alert-wash {
position: absolute;
inset: 0;
z-index: 8;
pointer-events: none;
opacity: 0;
transition: opacity 0.45s ease;
}
.observation-alert-wash.alert-red {
opacity: 1;
background: radial-gradient(circle at center, rgba(255, 0, 0, 0.08) 0%, rgba(220, 20, 20, 0.35) 75%, rgba(120, 0, 0, 0.72) 100%);
animation: obsAlertStrobeRed 1.1s ease-in-out infinite alternate;
}
.observation-alert-wash.alert-yellow {
opacity: 1;
background: radial-gradient(circle at center, rgba(255, 180, 0, 0.06) 0%, rgba(220, 150, 20, 0.28) 75%, rgba(140, 80, 0, 0.6) 100%);
animation: obsAlertStrobeYellow 1.5s ease-in-out infinite alternate;
}
@keyframes obsAlertStrobeRed {
0% { opacity: 0.2; }
100% { opacity: 0.95; }
}
@keyframes obsAlertStrobeYellow {
0% { opacity: 0.25; }
100% { opacity: 0.85; }
}
/* Layer 4: Holographic LCARD HUD */
.observation-chrome {
position: absolute;
inset: 0;
z-index: 9;
pointer-events: none;
font-family: var(--mono-font);
color: #e8f4ff;
text-shadow: 0 0 8px rgba(255,255,255,0.18);
opacity: 1;
transition: opacity 0.5s ease;
}
.observation-topline {
position: absolute;
top: 3.2vh;
left: 3vw;
right: 3vw;
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 2rem;
pointer-events: none;
}
.observation-mode-label {
font-family: var(--lcars-font);
font-size: clamp(1rem, 1.6vw, 1.7rem);
letter-spacing: 0.22em;
font-weight: 700;
color: var(--primary-accent);
}
.observation-profile {
margin-top: .45rem;
font-size: clamp(.8rem, 1.05vw, 1.1rem);
letter-spacing: .08em;
color: rgba(235,245,255,.78);
}
.observation-status {
text-align: right;
font-size: clamp(.7rem, .9vw, .95rem);
letter-spacing: .1em;
line-height: 1.65;
color: rgba(235,245,255,.62);
}
.observation-waveform-container {
position: absolute;
bottom: 2.2vh;
left: 50%;
transform: translateX(-50%);
z-index: 9;
pointer-events: none;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
opacity: 0.82;
}
.observation-waveform-label {
font-family: var(--mono-font);
font-size: 0.65rem;
letter-spacing: 0.2em;
color: var(--tertiary-accent);
text-shadow: 0 0 6px rgba(0,0,0,0.9);
}
#observation-waveform-canvas {
width: clamp(240px, 32vw, 440px);
height: 24px;
border-radius: 4px;
}
/* Scrolling Universe-Specific Status Ticker */
.observation-ticker {
position: absolute;
top: 1.05vh;
left: 3vw;
right: 3vw;
z-index: 9;
display: flex;
align-items: center;
gap: 10px;
pointer-events: none;
opacity: 0.85;
}
.observation-ticker-label {
font-family: var(--lcars-font);
font-size: 0.62rem;
font-weight: 700;
letter-spacing: 0.18em;
color: #000;
background: var(--tertiary-accent, #99ccff);
padding: 2px 9px;
border-radius: 8px;
flex-shrink: 0;
white-space: nowrap;
}
.observation-ticker-track {
flex: 1;
min-width: 0;
overflow: hidden;
white-space: nowrap;
-webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 6%, #000 94%, transparent 100%);
mask-image: linear-gradient(90deg, transparent 0%, #000 6%, #000 94%, transparent 100%);
}
.observation-ticker-text {
display: inline-block;
font-family: var(--mono-font);
font-size: 0.7rem;
letter-spacing: 0.13em;
color: rgba(235,245,255,.7);
white-space: nowrap;
padding-left: 100%;
animation: obsTickerScroll 20s linear infinite;
}
@keyframes obsTickerScroll {
0% { transform: translateX(0); }
100% { transform: translateX(-100%); }
}
/* Auto-hiding in-observation dock */
.observation-control-dock {
position: absolute;
bottom: 2.5vh;
right: 2.5vw;
z-index: 12;
display: flex;
align-items: center;
gap: 8px;
background: rgba(8, 12, 22, 0.88);
backdrop-filter: blur(14px);
border: 1px solid color-mix(in srgb, var(--primary-accent) 65%, transparent);
box-shadow: 0 4px 28px rgba(0,0,0,0.8), inset 0 0 14px rgba(255,255,255,0.03);
border-radius: 20px;
padding: 6px 12px;
transition: opacity 0.35s ease, transform 0.35s ease;
opacity: 1;
}
.observation-control-dock.dock-autohide {
opacity: 0;
pointer-events: none;
transform: translateY(8px);
}
.obs-dock-btn {
background: rgba(0,0,0,0.55);
border: 1px solid color-mix(in srgb, var(--primary-accent) 55%, transparent);
color: #e2e8f0;
font-family: var(--lcars-font);
font-size: 0.82rem;
font-weight: 700;
letter-spacing: 0.08em;
padding: 5px 12px;
border-radius: 12px;
cursor: pointer;
transition: all 0.16s ease;
white-space: nowrap;
user-select: none;
}
.obs-dock-btn:hover {
background: var(--primary-accent);
color: #000;
box-shadow: 0 0 10px var(--primary-accent);
}
.obs-dock-btn.active {
background: var(--primary-accent);
color: #000;
border-color: var(--primary-accent);
box-shadow: 0 0 12px var(--primary-accent);
}
.obs-dock-btn.btn-alert-active {
background: #dc2626 !important;
color: #fff !important;
border-color: #f87171 !important;
box-shadow: 0 0 14px #dc2626 !important;
animation: obsBtnAlertPulse 0.9s ease-in-out infinite alternate;
}
.obs-dock-btn.obs-dock-close {
border-color: #f87171;
color: #fca5a5;
}
.obs-dock-btn.obs-dock-close:hover {
background: #dc2626;
color: #fff;
box-shadow: 0 0 12px #dc2626;
}
@keyframes obsBtnAlertPulse {
from { opacity: 0.75; }
to { opacity: 1; }
}
.obs-dock-select {
background: rgba(0,0,0,0.75);
border: 1px solid color-mix(in srgb, var(--tertiary-accent) 60%, transparent);
color: var(--tertiary-accent);
font-family: var(--mono-font);
font-size: 0.78rem;
padding: 5px 8px;
border-radius: 8px;
cursor: pointer;
max-width: 170px;
outline: none;
}
.obs-dock-select option {
background: #0d1117;
color: #e2e8f0;
}
.observation-return {
position: absolute;
bottom: 2.8vh;
left: 3vw;
padding: .45rem .9rem;
border: 1px solid color-mix(in srgb, var(--primary-accent) 55%, transparent);
border-radius: 999px;
background: rgba(0,0,0,.45);
backdrop-filter: blur(8px);
color: rgba(255,255,255,.78);
font-size: clamp(.65rem, .78vw, .82rem);
letter-spacing: .16em;
white-space: nowrap;
cursor: pointer;
z-index: 12;
transition: background 0.2s ease, color 0.2s ease, opacity 0.5s ease;
}
.observation-return:hover {
background: var(--primary-accent);
color: #000;
}
@keyframes obs-drift-left {
from { transform: translateX(0); }
to { transform: translateX(-160px); }
}
@keyframes obs-drift-right {
from { transform: translateX(-100px); }
to { transform: translateX(80px); }
}
@keyframes obs-pulse {
0%, 100% { opacity: .35; transform: scale(1); }
50% { opacity: 1; transform: scale(1.045); }
}
@keyframes obs-rotate {
to { transform: rotate(360deg); }
}
@keyframes obs-rotate-rev {
to { transform: rotate(-360deg); }
}
@keyframes obs-sweep {
0% { opacity: 0; transform: translateY(-8%); }
15% { opacity: .65; }
85% { opacity: .65; }
100% { opacity: 0; transform: translateY(108%); }
}
@keyframes obs-flicker {
0%, 95%, 100% { opacity: 1; }
96% { opacity: .35; }
97% { opacity: .9; }
98% { opacity: .2; }
}
@keyframes obs-blink {
0%, 44%, 100% { opacity: .2; }
45%, 70% { opacity: 1; }
}
@keyframes obs-breathe {
0%, 100% { transform: scale(.98); filter: brightness(.86); }
50% { transform: scale(1.04); filter: brightness(1.15); }
}
@keyframes obs-wave {
0% { stroke-dashoffset: 0; }
100% { stroke-dashoffset: -180; }
}
.obs-spin {
transform-box: fill-box;
transform-origin: center;
animation: obs-rotate 18s linear infinite;
}
.obs-spin-slow {
transform-box: fill-box;
transform-origin: center;
animation: obs-rotate 42s linear infinite;
}
.obs-spin-rev {
transform-box: fill-box;
transform-origin: center;
animation: obs-rotate-rev 28s linear infinite;
}
.obs-pulse {
transform-box: fill-box;
transform-origin: center;
animation: obs-pulse 3.8s ease-in-out infinite;
}
.obs-breathe {
transform-box: fill-box;
transform-origin: center;
animation: obs-breathe 5.5s ease-in-out infinite;
}
.obs-flicker {
animation: obs-flicker 8s steps(1,end) infinite;
}
.obs-blink {
animation: obs-blink 3.5s steps(1,end) infinite;
}
.obs-dashflow {
stroke-dasharray: 20 12;
animation: obs-wave 7s linear infinite;
}
/* OBSERVATION-specific theme tinting */
body.theme-whataverse-tardix .observation-overlay { background: #020817; }
body.theme-industrial .observation-overlay { background: #070706; }
body.theme-bioships .observation-overlay { background: #010b07; }
body.theme-retrofuture .observation-overlay { background: #010903; }
body.theme-military .observation-overlay { background: #050506; }
body.theme-deepspace .observation-overlay { background: #010207; }
body.theme-outlaw .observation-overlay { background: #09040c; }
body.theme-spacestations .observation-overlay { background: #02070d; }
body.theme-comedy .observation-overlay { background: #07061a; }
@media (prefers-reduced-motion: reduce) {
.observation-overlay * {
animation-duration: 1ms !important;
animation-iteration-count: 1 !important;
}
}
/* ==========================================================================
OBSERVATION ACTIVITY ENGINE
Generative transient visuals + richer ambient motion.
========================================================================== */
.observation-activity-control {
display: inline-flex;
align-items: center;
gap: 8px;
min-width: min(330px, 100%);
padding: 6px 10px;
border: 1px solid color-mix(in srgb, var(--primary-accent) 55%, transparent);
border-radius: 14px;
background: rgba(255,255,255,.025);
font-family: var(--mono-font);
}
.observation-activity-label {
color: var(--primary-accent);
font-size: .72rem;
font-weight: 700;
letter-spacing: .08em;
white-space: nowrap;
}
.observation-activity-control input[type="range"] {
flex: 1;
min-width: 90px;
height: 6px;
}
.observation-activity-value {
min-width: 38px;
text-align: right;
color: #dbeafe;
font-size: .75rem;
}
.observation-event-layer {
position: absolute;
inset: 0;
z-index: 3;
overflow: hidden;
pointer-events: none;
}
.obs-transient {
position: absolute;
inset: 0;
opacity: 0;
pointer-events: none;
animation: obs-transient-life var(--obs-life, 4.5s) ease-in-out forwards;
}
.obs-transient svg {
width: 100%;
height: 100%;
display: block;
}
@keyframes obs-transient-life {
0% { opacity: 0; }
8% { opacity: 1; }
78% { opacity: .92; }
100% { opacity: 0; }
}
@keyframes obs-transient-pop {
0% { transform: scale(.55); opacity: 0; }
22% { transform: scale(1.08); opacity: 1; }
100% { transform: scale(1); opacity: .2; }
}
@keyframes obs-transient-ring {
from { transform: scale(.15); opacity: .95; }
to { transform: scale(2.7); opacity: 0; }
}
@keyframes obs-slide-horizontal {
from { transform: translateX(-130px); }
to { transform: translateX(130px); }
}
@keyframes obs-slide-horizontal-wide {
from { transform: translateX(-520px); }
to { transform: translateX(520px); }
}
@keyframes obs-slide-vertical {
from { transform: translateY(-160px); }
to { transform: translateY(160px); }
}
@keyframes obs-soft-wobble {
0%,100% { transform: translate(0,0) rotate(0deg); }
25% { transform: translate(4px,-2px) rotate(.25deg); }
60% { transform: translate(-3px,3px) rotate(-.2deg); }
}
@keyframes obs-glow-cycle {
0%,100% { opacity: .18; }
50% { opacity: .88; }
}
@keyframes obs-drift-up {
from { transform: translateY(70px); opacity: 0; }
15% { opacity: .7; }
to { transform: translateY(-120px); opacity: 0; }
}
@keyframes obs-zoom-in {
from { transform: scale(.82); opacity: .15; }
to { transform: scale(1.16); opacity: .8; }
}
@keyframes obs-route-wander {
0%,100% { stroke-dashoffset: 0; opacity: .35; }
50% { stroke-dashoffset: -120; opacity: .9; }
}
@keyframes obs-planet-drift {
from { transform: translateX(-220px); }
to { transform: translateX(1900px); }
}
@keyframes obs-comet-drift {
from { transform: translate(-250px, 180px) rotate(-15deg); opacity: 0; }
10% { opacity: .8; }
85% { opacity: .65; }
to { transform: translate(1900px, -260px) rotate(-15deg); opacity: 0; }
}
@keyframes obs-camera-pan {
0%,100% { transform: translateX(-14px) scale(1.03); }
50% { transform: translateX(14px) scale(1.07); }
}
@keyframes obs-organic-undulate {
0%,100% { transform: scale(1, .97) skewX(-1deg); }
50% { transform: scale(1.035, 1.045) skewX(1deg); }
}
@keyframes obs-crt-jump {
0%,93%,100% { transform: translateY(0); opacity: 1; }
94% { transform: translateY(9px); opacity: .6; }
95% { transform: translateY(-5px); opacity: .85; }
96% { transform: translateY(2px); opacity: .35; }
}
/* ==========================================================================
INDUSTRIAL OBSERVATION — v13co
Video-feed artifacts and mechanical work cycles.
EVERY effect below is authored to live INSIDE a camera clip-path so it
can never bleed across the console the way the old full-screen sweep and
the free-floating steam blobs did.
========================================================================== */
/* Rolling horizontal sync bar — travels down ONE feed, not the screen. */
@keyframes obs-feed-roll {
0% { transform: translateY(-72px); }
100% { transform: translateY(292px); }
}
/* Occasional tracking tear: a couple of displaced scan blocks, then gone. */
@keyframes obs-feed-tear {
0%, 87%, 100% { opacity: 0; transform: translate(0, 120px); }
88% { opacity: .55; transform: translate(-11px, 74px); }
90% { opacity: .32; transform: translate(9px, 158px); }
92% { opacity: .48; transform: translate(-5px, 44px); }
94% { opacity: 0; transform: translate(0, 210px); }
}
/* Analogue grain: churn opacity only so the turbulence filter stays cached. */
@keyframes obs-feed-grain {
0%, 100% { opacity: .055; }
25% { opacity: .10; }
50% { opacity: .04; }
75% { opacity: .115; }
}
/* Automatic gain control hunting for exposure. */
@keyframes obs-feed-agc {
0%, 100% { opacity: 0; }
40% { opacity: .055; }
70% { opacity: .02; }
}
/* Active-feed selector; four cameras share this with negative delays. */
@keyframes obs-cam-focus {
0%, 21% { opacity: 1; }
23%, 100% { opacity: 0; }
}
/* --- CARGO BAY: gantry crane work cycle. Phases interlock on one clock. --- */
@keyframes obs-gantry-traverse {
0%, 18% { transform: translateX(0px); }
38%, 62% { transform: translateX(290px); }
82%, 100% { transform: translateX(0px); }
}
@keyframes obs-gantry-hoist {
0% { transform: translateY(0px); }
5% { transform: translateY(66px); }
11% { transform: translateY(66px); }
17% { transform: translateY(0px); }
40% { transform: translateY(0px); }
45% { transform: translateY(66px); }
53% { transform: translateY(66px); }
60% { transform: translateY(0px); }
100% { transform: translateY(0px); }
}
@keyframes obs-gantry-load {
0%, 11% { opacity: 0; }
13%, 45% { opacity: 1; }
53%, 100% { opacity: 0; }
}
@keyframes obs-gantry-taken {
0%, 10% { opacity: 1; }
13%, 96% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes obs-gantry-placed {
0%, 52% { opacity: 0; }
56%, 96% { opacity: 1; }
100% { opacity: 0; }
}
@keyframes obs-gantry-lamp {
0%, 16%, 62%, 100% { fill: #16a34a; }
19%, 38% { fill: #f59e0b; }
45%, 59% { fill: #f59e0b; }
}
@keyframes obs-bay-shudder {
0%, 46%, 52%, 100% { transform: translate(0, 0); }
47% { transform: translate(.9px, -.7px); }
49% { transform: translate(-.8px, .6px); }
51% { transform: translate(.5px, .4px); }
}
/* Rotating hazard beacon. Pivot comes from a zero-fill bbox anchor circle. */
@keyframes obs-beacon-sweep { to { transform: rotate(360deg); } }
@keyframes obs-beacon-flash {
0%, 100% { opacity: .16; }
50% { opacity: .95; }
}
/* Steam / vapour: rises from a vent and dissipates. Always inside a clip. */
@keyframes obs-vapour {
0% { transform: translate(0, 0) scale(.3); opacity: 0; }
18% { opacity: .34; }
60% { opacity: .16; }
100% { transform: translate(var(--vx, 12px), -94px) scale(1.9); opacity: 0; }
}
/* --- REACTOR PLANT --- */
@keyframes obs-core-breathe {
0%, 100% { transform: scale(.93); opacity: .55; }
50% { transform: scale(1.08); opacity: 1; }
}
@keyframes obs-rod-travel {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(11px); }
}
@keyframes obs-heat-shimmer {
0%, 100% { transform: translateY(0) scaleY(1); opacity: .14; }
50% { transform: translateY(-3px) scaleY(1.07); opacity: .3; }
}
@keyframes obs-needle-hunt {
0%, 100% { transform: rotate(-33deg); }
30% { transform: rotate(19deg); }
55% { transform: rotate(-9deg); }
78% { transform: rotate(30deg); }
}
@keyframes obs-pipe-flow { to { stroke-dashoffset: -240; } }
/* --- AIRLOCK --- */
@keyframes obs-dog-ring {
0%, 30% { transform: rotate(0deg); }
46%, 76% { transform: rotate(45deg); }
92%, 100% { transform: rotate(0deg); }
}
@keyframes obs-airlock-cycle {
0%, 24% { opacity: 1; }
26%, 100% { opacity: .1; }
}
/* --- MACHINE CORRIDOR --- */
@keyframes obs-lamp-fail {
0%, 61%, 100% { opacity: .85; }
62% { opacity: .1; }
63.5% { opacity: .72; }
65% { opacity: .08; }
67% { opacity: .8; }
70% { opacity: .22; }
72% { opacity: .82; }
}
@keyframes obs-drip {
0%, 72% { transform: translateY(0); opacity: 0; }
76% { opacity: .75; }
100% { transform: translateY(54px); opacity: 0; }
}
.obs-feed-roll { animation: obs-feed-roll 7.5s linear infinite; }
.obs-feed-grain { animation: obs-feed-grain .45s steps(2, end) infinite; }
.obs-feed-agc { animation: obs-feed-agc 9s ease-in-out infinite; }
.obs-feed-tear { animation: obs-feed-tear 13s linear infinite; }
.obs-cam-focus { animation: obs-cam-focus 32s linear infinite; }
.obs-beacon-sweep { transform-box: fill-box; transform-origin: center; animation: obs-beacon-sweep 3.4s linear infinite; }
.obs-beacon-flash { animation: obs-beacon-flash 1.7s ease-in-out infinite; }
.obs-pipe-flow { animation: obs-pipe-flow 4s linear infinite; }
.obs-heat-shimmer { transform-box: fill-box; transform-origin: bottom center; animation: obs-heat-shimmer 3.2s ease-in-out infinite; }
.obs-lamp-fail { animation: obs-lamp-fail 9s linear infinite; }
.obs-bay-shudder { animation: obs-bay-shudder 17s ease-in-out infinite; }
.obs-pivot { transform-box: fill-box; transform-origin: center; }
/* Functional link: the OBSERVATION activity slider drives plant output and
crane pace, so what you see tracks what the console says it is doing.
All six gantry animations share one clock so their phases stay locked. */
.observation-overlay {
--obs-activity: .6;
--obs-gantry-clock: calc(34s - var(--obs-activity, .6) * 14s);
}
.obs-core-load {
transform-box: fill-box;
transform-origin: center;
animation: obs-core-breathe calc(7.4s - var(--obs-activity, .6) * 4s) ease-in-out infinite;
}
.obs-core-halo { opacity: calc(.03 + var(--obs-activity, .6) * .16); }
@media (prefers-reduced-motion: reduce) {
.obs-feed-roll, .obs-feed-grain, .obs-feed-tear, .obs-feed-agc,
.obs-beacon-sweep, .obs-bay-shudder, .obs-lamp-fail { animation: none; }
}
.obs-ambient-wobble {
transform-box: fill-box;
transform-origin: center;
animation: obs-soft-wobble 8s ease-in-out infinite;
}
.obs-ambient-glow {
animation: obs-glow-cycle 5.5s ease-in-out infinite;
}
.obs-camera-pan {
transform-box: fill-box;
transform-origin: center;
animation: obs-camera-pan 14s ease-in-out infinite;
}
.obs-organic-undulate {
transform-box: fill-box;
transform-origin: center;
animation: obs-organic-undulate 7s ease-in-out infinite;
}
.obs-crt-jump {
animation: obs-crt-jump 11s steps(1,end) infinite;
}
.obs-route-wander {
animation: obs-route-wander 8s linear infinite;
}
/* OBSERVATION chrome remains above generative effects. */
.observation-chrome { z-index: 9; }
.observation-scanlines { z-index: 6; }
.observation-vignette { z-index: 7; }
@media (max-width: 820px) {
.observation-activity-control {
width: 100%;
}
}
/* ==========================================================================
LIVE OBSERVATION INSTRUMENTATION
Applies only to fantasy text inside the SVG observation visualization.
========================================================================== */
.observation-stage text.obs-live-instrument,
.observation-event-layer text.obs-live-instrument {
transition: opacity .12s linear;
}
.observation-stage text.obs-live-glitch,
.observation-event-layer text.obs-live-glitch {
opacity: .72;
}
/* ==========================================================================
OBSERVATION HUD PERSISTENCE
HUD HOLD on = profile/status/return chrome stays visible.
HUD HOLD off = chrome fades away over 30 seconds after OBSERVATION starts.
========================================================================== */
.observation-hud-control {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 10px;
border: 1px solid color-mix(in srgb, var(--primary-accent) 55%, transparent);
border-radius: 14px;
background: rgba(255,255,255,.025);
font-family: var(--mono-font);
white-space: nowrap;
}
.observation-hud-label {
color: var(--primary-accent);
font-size: .72rem;
font-weight: 700;
letter-spacing: .08em;
}
.observation-hud-control input[type="checkbox"] {
width: 18px;
height: 18px;
accent-color: var(--primary-accent);
cursor: pointer;
}
.observation-hud-state {
min-width: 34px;
color: #dbeafe;
font-size: .75rem;
text-align: right;
}
.observation-chrome {
opacity: 1;
transition: opacity 30s linear;
}
.observation-chrome.observation-hud-fade {
opacity: 0;
}
/* CLICK ANYWHERE TO RETURN always fades away over 30 seconds,
independently of the HUD HOLD setting. */
.observation-return {
opacity: 1;
transition: opacity 30s linear;
}
.observation-return.observation-return-fade {
opacity: 0;
}
/* ==========================================================================
OBSERVATION SCENE ENGINE
Persistent generative world layer. Unlike transient alerts, these entities
have lifecycles and move through the scene over time.
========================================================================== */
.observation-sim-layer {
position: absolute;
inset: 0;
z-index: 2;
overflow: hidden;
pointer-events: none;
}
.observation-sim-layer svg {
width: 100%;
height: 100%;
display: block;
}
.obs-scene-entity {
will-change: transform, opacity;
}
.obs-scene-soft {
filter: url(#obsSceneGlow);
}
@keyframes obs-scene-fan-spin {
to { transform: rotate(360deg); }
}
@keyframes obs-scene-breathe {
0%, 100% { opacity: .28; transform: scale(.96); }
50% { opacity: .72; transform: scale(1.06); }
}
@keyframes obs-scene-flicker {
0%, 92%, 100% { opacity: .72; }
93% { opacity: .28; }
94% { opacity: .86; }
96% { opacity: .42; }
}
.obs-scene-fan {
transform-box: fill-box;
transform-origin: center;
animation: obs-scene-fan-spin 5s linear infinite;
}
.obs-scene-breathe {
transform-box: fill-box;
transform-origin: center;
animation: obs-scene-breathe 6s ease-in-out infinite;
}
.obs-scene-flicker {
animation: obs-scene-flicker 10s steps(1,end) infinite;
}
/* === XZBT GENERATIVE EXPERIENCE / WEBLLM + KOKORO + MIDI + DETERMINISTIC FNC COMFORT FILTER v3.7 === */
.ai-experience-card .ai-status-line{display:flex;justify-content:space-between;gap:8px;align-items:center;margin-bottom:8px;font-family:var(--mono-font);font-size:.72rem;letter-spacing:.06em}
.ai-status-badge{padding:3px 7px;border:1px solid var(--primary-accent);border-radius:3px;color:var(--primary-accent);white-space:nowrap}
.ai-status-badge.ready{color:#00ff88;border-color:#00ff88}.ai-status-badge.busy{color:#ffcc00;border-color:#ffcc00}.ai-status-badge.error{color:#ff6666;border-color:#ff6666}
.ai-control-grid{display:grid;grid-template-columns:1fr 1fr;gap:7px;margin:8px 0}.ai-control-grid .span-2{grid-column:span 2}
.ai-experience-card select,.ai-experience-card input[type="range"]{width:100%;box-sizing:border-box}.ai-experience-card select{background:#05070a;color:var(--tertiary-accent);border:1px solid var(--secondary-accent);padding:6px;font-family:var(--mono-font);font-size:.72rem}
.ai-toggle-row{display:flex;align-items:center;gap:7px;font-family:var(--mono-font);font-size:.72rem;min-height:28px}
.ai-experience-output{min-height:54px;max-height:116px;overflow-y:auto;margin-top:8px;padding:8px;border-left:3px solid var(--primary-accent);background:rgba(0,0,0,.38);color:#dce7f7;font-family:var(--mono-font);font-size:.72rem;line-height:1.45}
.ai-progress{margin-top:6px;font-family:var(--mono-font);font-size:.66rem;color:var(--tertiary-accent);min-height:1.1em}
/* === XZBT v3.7: Watch Experience / TV / MIDI / Neural Speech / Deterministic FNC Comfort Filter === */
.watch-experience-wrap{display:flex;flex-direction:column;gap:3px;min-width:190px}
.watch-experience-wrap .btn-observation{font-weight:700;letter-spacing:.08em}
.watch-experience-help{font-family:var(--mono-font);font-size:.58rem;line-height:1.2;color:var(--tertiary-accent);opacity:.86;max-width:230px}
.ai-fixed-model{padding:7px;border:1px solid rgba(255,255,255,.18);background:rgba(0,0,0,.3);font-family:var(--mono-font);font-size:.68rem;line-height:1.45}
.ai-fixed-model b{color:var(--primary-accent)}
.ai-engine-row{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.ai-engine-chip{padding:6px;border:1px solid rgba(255,255,255,.16);font-family:var(--mono-font);font-size:.62rem}
.ai-engine-chip span{float:right;color:var(--tertiary-accent)}
.midi-card .midi-device-line{font-family:var(--mono-font);font-size:.67rem;line-height:1.35;margin:5px 0;color:var(--tertiary-accent)}
.midi-bindings{max-height:150px;overflow:auto;padding:6px;background:rgba(0,0,0,.28);font-family:var(--mono-font);font-size:.61rem;line-height:1.45;white-space:pre-wrap}
.midi-learn-active{outline:2px solid #ffcc00!important;box-shadow:0 0 12px rgba(255,204,0,.25)}
.tv-mode-card{font-family:var(--mono-font);font-size:.65rem}
.tv-mode-card select{width:100%;background:#05070a;color:var(--tertiary-accent);border:1px solid var(--secondary-accent);padding:6px;font-family:var(--mono-font)}
body.xzbt-tv-letterbox{background:#000}
/* Canonical 16:9 presentation viewport. Children continue using percentage/absolute geometry. */
body.xzbt-tv-aspect .observation-overlay{
width:min(100vw,calc(100vh * 16 / 9));
height:min(100vh,calc(100vw * 9 / 16));
top:50%;left:50%;right:auto;bottom:auto;
transform:translate(-50%,-50%);
box-shadow:0 0 0 100vmax #000;
}
body.xzbt-tv-aspect .observation-overlay:not(.active){display:none}
@media (max-width:700px){
.watch-experience-wrap{min-width:150px}.watch-experience-help{font-size:.54rem}
}