/* Logo-only launch opening. Faction dossier/contact-sheet art is intentionally restricted to the codex and never used as a splash. */ .mfTitleReveal{position:fixed;inset:0;z-index:950;display:grid;grid-template-rows:auto 1fr auto;overflow:hidden;isolation:isolate; padding:max(14px,calc(var(--sat) + 12px)) max(16px,calc(var(--sar) + 14px)) max(16px,calc(var(--sab) + 12px)) max(16px,calc(var(--sal) + 14px)); color:#edf8ff;background:#02060c;opacity:0;transform:scale(1.025);transition:opacity .28s ease,transform .7s cubic-bezier(.16,.8,.2,1);touch-action:manipulation} .mfTitleReveal[hidden]{display:none!important}.mfTitleReveal.open{opacity:1;transform:none} .mfTitleBackdrop{position:absolute;inset:0;z-index:-1;overflow:hidden;background: radial-gradient(circle at 50% 47%,rgba(41,141,213,.16),transparent 23%), radial-gradient(ellipse at 50% 105%,rgba(255,199,83,.08),transparent 43%), linear-gradient(180deg,#02050a,#06101b 52%,#02050a)} .mfTitleBackdrop::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,rgba(0,0,0,.36),transparent 30%,transparent 70%,rgba(0,0,0,.36));box-shadow:inset 0 0 120px rgba(0,0,0,.75)} .mfTitleGrid{position:absolute;inset:-10%;opacity:.2;background-image: linear-gradient(rgba(92,190,255,.08) 1px,transparent 1px),linear-gradient(90deg,rgba(92,190,255,.07) 1px,transparent 1px); background-size:42px 42px;transform:perspective(520px) rotateX(63deg) translateY(29%);mask-image:linear-gradient(180deg,transparent 16%,#000 64%,transparent)} .mfTitleSweep{position:absolute;inset:-35% -20%;background:linear-gradient(103deg,transparent 45%,rgba(118,213,255,.11) 50%,transparent 55%);animation:mfTitleSweep 3.4s ease-in-out infinite} @keyframes mfTitleSweep{from{transform:translateX(-28%)}to{transform:translateX(28%)}} .mfTitleTop{display:flex;justify-content:space-between;align-items:center;width:min(100%,920px);margin:0 auto} .mfTitleBuild{display:flex;align-items:center;color:#b9cddd;font:800 10px/1 var(--fT);letter-spacing:.12em} .mfTitleBuild span{padding:8px 10px;border:1px solid rgba(116,181,220,.28);border-radius:7px;background:rgba(8,20,34,.62)} .mfTitleSkip{min-width:54px;min-height:48px;padding:0 12px;border:1px solid rgba(158,200,226,.34);border-radius:11px;color:#dcedf8;background:rgba(5,13,23,.78);font:800 10px/1 var(--fT);letter-spacing:.12em} .mfTitleSkip span{color:#ffd46e;margin-left:4px}.mfTitleSkip:active{transform:scale(.96)} .mfTitleCenter{align-self:center;justify-self:center;width:min(100%,900px);text-align:center;animation:mfTitleCenterIn .9s cubic-bezier(.16,.8,.2,1) both} @keyframes mfTitleCenterIn{from{opacity:0;transform:translateY(18px) scale(.96);filter:blur(8px)}to{opacity:1;transform:none;filter:none}} .mfTitleArt{display:block; width:min(100%,860px); height:auto; max-height:min(37vh,340px); margin:0 auto;filter:drop-shadow(0 16px 30px rgba(0,0,0,.88)); object-fit:contain; object-position:center; animation:mfTitleArtIn 1.15s cubic-bezier(.16,.8,.2,1) both} .mfTitleFallback{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:130px;margin:0 auto;padding:18px;color:#eaf5ff;text-align:center;text-shadow:0 5px 16px #000}.mfTitleFallback b{font:900 clamp(42px,12vw,106px)/.84 var(--fT);letter-spacing:.04em;color:#eef5f8;-webkit-text-stroke:1px #587184}.mfTitleFallback span{margin-top:14px;color:#92c8e5;font:800 clamp(9px,1.5vw,13px)/1 var(--fT);letter-spacing:.25em} #menuBrand.mfTitleFallback{width:min(86vw,430px);min-height:102px;margin:6px auto 2px}.mfTitleFallback#menuBrand b{font-size:clamp(31px,8.5vw,55px)}.mfTitleFallback#menuBrand span{margin-top:9px;font-size:9px;letter-spacing:.17em} @keyframes mfTitleArtIn{0%{opacity:0;transform:translateY(10px) scale(.96);filter:blur(7px)}58%{opacity:1}100%{transform:none;filter:drop-shadow(0 16px 30px rgba(0,0,0,.88))}} .mfTitleStatus{display:inline-flex;align-items:center;gap:8px;margin-top:25px;color:#91aabd;font:700 9px/1 var(--fU);letter-spacing:.19em} .mfTitleStatus span{width:7px;height:7px;border-radius:50%;background:#6ed6ff;box-shadow:0 0 12px #6ed6ff;animation:mfTitlePulse 1.25s ease-in-out infinite} @keyframes mfTitlePulse{50%{opacity:.3;transform:scale(.72)}} .mfTitleBottom{width:min(100%,460px);margin:0 auto}.mfTitleStart{width:100%;min-height:56px;border:1px solid #fff1bb;border-radius:12px;color:#1b1101;background:linear-gradient(180deg,#fff0af,#e9bb52 47%,#bd8730 53%,#f2cd70);box-shadow:0 10px 34px rgba(0,0,0,.55),0 0 22px rgba(255,212,110,.2);font:900 14px/1 var(--fT);letter-spacing:.14em} .mfTitleStart span{font-size:12px;margin-right:8px}.mfTitleStart:active{transform:scale(.98);filter:brightness(1.08)} body.mfIntroOpen{overflow:hidden} @media(max-width:640px){.mfTitleCenter{width:100%}.mfTitleArt{width:100%}.mfTitleStatus{margin-top:19px;font-size:9px;letter-spacing:.12em}} @media(max-height:520px){.mfTitleCenter{width:min(78vw,620px)}.mfTitleStatus{margin-top:12px}.mfTitleStart{min-height:48px}} @media(prefers-reduced-motion:reduce){.mfTitleReveal,.mfTitleCenter,.mfTitleArt,.mfTitleSweep,.mfTitleStatus span{animation:none!important;transition:none!important;transform:none!important;filter:none!important}.mfTitleReveal.open{opacity:1}} /* The launch title owns the first painted frame. #mfBootCover (declared in index.html's body markup, so it survives the OTA body swap) is opaque from the first paint; the front-end overlays also stay hidden until the reveal is dismissed and intro.js sets body.mfIntroDone. The cover is dropped by intro.js (removeChild), NOT by a body.mfIntroDone rule — a stale class persisted across an OTA body.innerHTML swap must not expose the menu before the new reveal. Mirrors index.html's critical inline