Spaces:
Running
Running
Download src/styles/tutorial.css from CREATORJD/massfront-playtest: direct link, hf CLI and curl.
- Browser
- Download file 29.2 kB
-
https://huggingface.co/spaces/CREATORJD/massfront-playtest/resolve/main/src/styles/tutorial.css
- Command line
-
hf download hf://spaces/CREATORJD/massfront-playtest/src/styles/tutorial.css
-
curl -L -o tutorial.css https://huggingface.co/spaces/CREATORJD/massfront-playtest/resolve/main/src/styles/tutorial.css
29.2 kB
| /* ============================================================================ | |
| TUTORIAL — KEEL, ship liaison intelligence | |
| ---------------------------------------------------------------------------- | |
| Visual family: same panel gradient, same border-image trick, same type | |
| ramp as the rest of the HUD (--panelG2, --fT/--fU, the bevelled border | |
| gradients in src/styles/ui.css's :root) — those custom properties cascade | |
| from :root regardless of which stylesheet declared them, so reusing them | |
| here keeps KEEL native to the HUD instead of a decal stuck on top of it. | |
| KEEL gets its own accent (cyan, --keelB below) so its panel reads as its | |
| own character rather than a reskinned dispatch or coach banner. | |
| Placement: docked centre, below the goal/hero/hive cluster (ends ~105px | |
| from the safe-area top once deployed) and below the native #toast's usual | |
| footprint (up to ~190px for a three-line message), so KEEL's line and a | |
| stock toast very rarely fight for the same pixels. Verified empirically | |
| against 412×900 screenshots — see docs/TUTORIAL.md. | |
| ============================================================================ */ | |
| :root{ | |
| --keelB:linear-gradient(160deg,#bdeeff 0%,#6fd0ff 26%,#0c3a52 58%,#1a6f99 80%,#bdeeff 100%); | |
| } | |
| /* ============================================================================ | |
| NEW-CAREER ORIENTATION | |
| ---------------------------------------------------------------------------- | |
| One calm decision surface over the approach view: arrival, optional basics, | |
| required faction commissioning, then Commander 1. It is intentionally not | |
| attached to START or the War Table, so the current main menu stays intact. | |
| ============================================================================ */ | |
| body.mfOnboardingOpen{overflow:hidden} | |
| #mfOnboardingChoice{ | |
| position:fixed;inset:0;z-index:2200;display:grid;place-items:center;overflow:auto; | |
| padding:max(12px,calc(var(--sat,0px) + 8px)) max(10px,env(safe-area-inset-right)) max(12px,calc(var(--sab,0px) + 8px)) max(10px,env(safe-area-inset-left)); | |
| box-sizing:border-box;color:#eefaff;font-family:var(--fU,system-ui,sans-serif); | |
| background:radial-gradient(circle at 72% 22%,rgba(68,164,204,.20),transparent 30%),linear-gradient(180deg,rgba(1,7,13,.92),rgba(2,10,16,.985)); | |
| } | |
| #mfOnboardingChoice[hidden]{display:none} | |
| .mfOnboardingFrame{ | |
| width:min(1120px,100%);min-height:min(760px,calc(100dvh - 28px));display:grid;grid-template-columns:minmax(280px,.78fr) minmax(520px,1.22fr); | |
| overflow:hidden;border:1px solid rgba(105,211,247,.35);border-radius:22px; | |
| background:#06121b;box-shadow:0 34px 110px rgba(0,0,0,.86),0 0 65px rgba(67,191,235,.10); | |
| } | |
| #mfOnboardingChoice[data-flow="default"] .mfOnboardingFrame{grid-template-columns:minmax(0,760px);min-height:0;width:min(760px,100%)} | |
| #mfOnboardingChoice[data-flow="default"] .mfOnboardingScene{display:none} | |
| .mfOnboardingScene{ | |
| position:relative;min-height:360px;overflow:hidden;padding:22px; | |
| background: | |
| radial-gradient(circle at 18% 17%,#dffaff 0 1px,transparent 2px),radial-gradient(circle at 76% 28%,#8ceaff 0 1px,transparent 2px), | |
| radial-gradient(circle at 31% 62%,#9ed9ed 0 1px,transparent 2px),radial-gradient(circle at 88% 73%,#fff 0 1px,transparent 2px), | |
| linear-gradient(150deg,#061626,#02070c 68%); | |
| } | |
| .mfOnboardingScene::before{content:"";position:absolute;inset:0;opacity:.26;background-image:linear-gradient(rgba(96,206,244,.08) 1px,transparent 1px),linear-gradient(90deg,rgba(96,206,244,.06) 1px,transparent 1px);background-size:42px 42px;mask-image:linear-gradient(to bottom,black,transparent 88%)} | |
| .mfOnboardingPlanet{position:absolute;left:15%;bottom:-9%;width:112%;aspect-ratio:1;border-radius:50%;background:radial-gradient(circle at 38% 31%,#c5e5e4 0 3%,#548aa1 19%,#203e56 45%,#071522 69%);box-shadow:-28px -22px 76px rgba(83,216,255,.24),0 0 0 2px rgba(141,230,255,.16)} | |
| .mfOnboardingPlanet::after{content:"";position:absolute;inset:-2%;border-radius:50%;border-top:2px solid rgba(162,238,255,.7);filter:blur(1px)} | |
| .mfOnboardingMoon{position:absolute;right:13%;top:20%;width:38px;height:38px;border-radius:50%;background:radial-gradient(circle at 38% 33%,#d5edf0,#506a76 72%);box-shadow:0 0 18px rgba(137,223,246,.15)} | |
| .mfOnboardingVector{position:absolute;left:20%;top:25%;width:56%;height:46%;border-top:1px solid rgba(101,225,255,.52);border-right:1px solid rgba(101,225,255,.3);transform:skew(-28deg) rotate(13deg)} | |
| .mfOnboardingVector::before{content:"";position:absolute;right:-5px;top:-5px;width:9px;height:9px;border:1px solid #95edff;background:#0a2736;transform:rotate(45deg);box-shadow:0 0 14px #5fe1ff} | |
| .mfOnboardingScene>b,.mfOnboardingScene>i{position:relative;z-index:2;display:block;font-family:var(--fT,system-ui);font-style:normal;letter-spacing:.15em} | |
| .mfOnboardingScene>b{color:#a9efff;font-size:10px}.mfOnboardingScene>i{margin-top:6px;color:#638797;font-size:8px} | |
| .mfOnboardingCard{min-width:0;background:linear-gradient(155deg,rgba(10,29,42,.99),rgba(3,12,19,.995) 62%)} | |
| .mfOnboardingHeader{display:flex;align-items:center;gap:12px;min-height:66px;padding:11px clamp(15px,3vw,28px);border-bottom:1px solid rgba(105,211,247,.18);background:rgba(7,24,34,.82)} | |
| .mfOnboardingKeel{position:relative;display:grid;place-items:center;width:40px;height:40px;flex:0 0 40px;border:1px solid rgba(105,224,255,.58);border-radius:50%;color:#c5f6ff;background:radial-gradient(circle,rgba(80,218,255,.22),transparent 68%);font:900 17px/1 var(--fT);box-shadow:0 0 17px rgba(73,213,255,.13)} | |
| .mfOnboardingHeader>span:last-child b,.mfOnboardingHeader>span:last-child small{display:block}.mfOnboardingHeader>span:last-child b{color:#baf3ff;font:900 12px/1 var(--fT);letter-spacing:.16em}.mfOnboardingHeader>span:last-child small{margin-top:5px;color:#7897a6;font:800 8px/1.2 var(--fT);letter-spacing:.12em} | |
| .mfOnboardingPath{display:grid;grid-template-columns:repeat(4,1fr);border-bottom:1px solid rgba(105,211,247,.14)} | |
| .mfOnboardingPath>span{position:relative;display:flex;align-items:center;justify-content:center;gap:6px;min-height:42px;padding:6px 4px;color:#58717e;font:800 7px/1.2 var(--fT);letter-spacing:.08em;text-align:center}.mfOnboardingPath>span:not(:last-child)::after{content:"";position:absolute;right:0;width:1px;height:18px;background:rgba(112,206,235,.13)} | |
| .mfOnboardingPath b{display:grid;place-items:center;width:19px;height:19px;border:1px solid #435e6a;border-radius:50%;font-size:7px}.mfOnboardingPath .done{color:#81a4b2}.mfOnboardingPath .done b{color:#8be8ff;border-color:#55b9d7}.mfOnboardingPath .on{color:#e6faff;background:linear-gradient(90deg,rgba(60,190,232,.11),transparent)}.mfOnboardingPath .on b{color:#eaffff;border-color:#70e3ff;background:#16495e;box-shadow:0 0 12px rgba(87,220,255,.2)} | |
| .mfOnboardingCard>main{padding:clamp(20px,3.5vw,35px)} | |
| .mfOnboardingEyebrow{color:#68dcff;font:900 9px/1.2 var(--fT);letter-spacing:.19em}.mfOnboardingCard h2{max-width:680px;margin:8px 0 8px;font:900 clamp(27px,4.5vw,48px)/1 var(--fT);letter-spacing:.012em}.mfOnboardingLead{max-width:690px;margin:0;color:#a7bdc8;font:600 11px/1.55 var(--fU)} | |
| .mfOnboardingTracks{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:20px 0 12px}.mfOnboardingTrack{min-width:0;padding:13px;border:1px solid rgba(104,186,217,.22);border-radius:11px;background:rgba(10,32,45,.63)}.mfOnboardingTrack.recommended{border-color:rgba(91,218,255,.48);background:linear-gradient(150deg,rgba(31,105,132,.30),rgba(7,28,40,.78))}.mfOnboardingTrack small,.mfOnboardingTrack b,.mfOnboardingTrack span{display:block}.mfOnboardingTrack small{color:#6ddfff;font:900 7px/1 var(--fT);letter-spacing:.14em}.mfOnboardingTrack b{margin-top:7px;color:#e9faff;font:900 12px/1.2 var(--fT);letter-spacing:.035em}.mfOnboardingTrack span{margin-top:6px;color:#91aab7;font:600 9px/1.45 var(--fU)} | |
| .mfOnboardingSteps{display:flex;flex-wrap:wrap;gap:5px;margin:0 0 18px}.mfOnboardingSteps span{padding:5px 7px;border:1px solid rgba(91,198,232,.24);border-radius:999px;color:#9bc8d8;background:rgba(22,74,93,.16);font:800 7px/1 var(--fT);letter-spacing:.06em} | |
| .mfOnboardingActions{display:grid;grid-template-columns:1.15fr 1fr;gap:9px}.mfOnboardingActions button{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;min-height:58px;padding:10px 14px;border:1px solid #6ce2ff;border-radius:9px;color:white;background:linear-gradient(180deg,#187a9d,#0c435b);box-shadow:inset 0 1px rgba(255,255,255,.12),0 7px 20px rgba(0,0,0,.28);font:900 10px/1.2 var(--fT);letter-spacing:.075em;text-align:left;touch-action:manipulation}.mfOnboardingActions button small{display:block;margin-bottom:5px;color:#a9edff;font-size:7px;letter-spacing:.14em}.mfOnboardingActions .quiet{border-color:#385765;color:#b8ccd5;background:#081923;box-shadow:none}.mfOnboardingActions .quiet small{color:#6f8d99}.mfOnboardingActions button:focus-visible{outline:2px solid #d7f8ff;outline-offset:3px}.mfOnboardingActions button:active{transform:translateY(1px);filter:brightness(1.15)} | |
| .mfOnboardingFoot{margin:12px 2px 0;color:#708996;font:700 8px/1.45 var(--fU);text-align:center} | |
| @media(max-width:860px){.mfOnboardingFrame{grid-template-columns:1fr;min-height:0}.mfOnboardingScene{min-height:190px}.mfOnboardingPlanet{left:35%;bottom:-115%;width:90%}.mfOnboardingMoon{top:18%;right:18%}.mfOnboardingVector{left:35%;top:30%;width:43%;height:55%}} | |
| @media(max-width:540px){#mfOnboardingChoice{place-items:start center}.mfOnboardingFrame{border-radius:15px}.mfOnboardingScene{min-height:132px;padding:14px}.mfOnboardingPlanet{left:39%;bottom:-150%;width:92%}.mfOnboardingMoon{width:25px;height:25px}.mfOnboardingHeader{min-height:58px;padding:9px 13px}.mfOnboardingKeel{width:36px;height:36px;flex-basis:36px}.mfOnboardingHeader>span:last-child small{font-size:7px}.mfOnboardingPath>span{font-size:0;min-height:38px}.mfOnboardingPath b{font-size:7px}.mfOnboardingCard>main{padding:19px 14px 15px}.mfOnboardingCard h2{font-size:30px}.mfOnboardingTracks,.mfOnboardingActions{grid-template-columns:1fr}.mfOnboardingTracks{gap:7px;margin-top:15px}.mfOnboardingTrack{padding:11px}.mfOnboardingSteps{margin-bottom:14px}.mfOnboardingActions button{min-height:60px}.mfOnboardingFoot{text-align:left}} | |
| @media(prefers-reduced-motion:reduce){.mfOnboardingActions button:active{transform:none}} | |
| #keelWrap{ | |
| position:absolute; left:50%; top:calc(var(--sat) + 204px); | |
| transform:translateX(-50%); | |
| width:min(90vw,380px); | |
| z-index:19; /* level with #coach — both are HUD-native narration, neither an overlay */ | |
| pointer-events:none; | |
| opacity:0; visibility:hidden; | |
| transition:opacity .28s ease; | |
| } | |
| #keelWrap.show{ opacity:1; visibility:visible; pointer-events:none; } | |
| #keelWrap.show #keelBar{ pointer-events:auto; } | |
| #keelBar{ | |
| display:flex; align-items:flex-start; gap:9px; | |
| border-radius:12px; padding:9px 10px 9px 9px; | |
| border:1px solid transparent; | |
| background:var(--panelG2) padding-box, var(--keelB) border-box; | |
| box-shadow:0 6px 20px rgba(0,0,0,.55); | |
| transition:opacity .3s ease, transform .2s ease; | |
| } | |
| #keelBar.resting{ opacity:.82; transform:scale(.99); } | |
| #keelBar.pulse{ animation:keelPulse .5s cubic-bezier(.2,.8,.3,1); } | |
| @keyframes keelPulse{ | |
| 0%{ transform:scale(.96); box-shadow:0 6px 20px rgba(0,0,0,.55), 0 0 0 0 rgba(120,220,255,.5); } | |
| 60%{ transform:scale(1.015); } | |
| 100%{ transform:scale(1); box-shadow:0 6px 20px rgba(0,0,0,.55), 0 0 0 8px rgba(120,220,255,0); } | |
| } | |
| /* ---------- KEEL: neutral UGA signal identity, never a faction portrait ---- */ | |
| #keelBadge{ position:relative; width:42px; height:42px; flex:0 0 42px; margin-top:1px; | |
| display:grid;place-items:center;border-radius:9px;background:radial-gradient(circle at 50% 46%,rgba(79,218,255,.22),transparent 58%),linear-gradient(145deg,#0b2a3a,#030b12); | |
| border:1px solid rgba(120,220,255,.78);box-shadow:0 0 12px rgba(70,190,245,.24);overflow:hidden; } | |
| #keelBadge::before{content:'K';position:relative;z-index:2;color:#bcefff;font:900 17px/1 var(--fT);letter-spacing:.04em;text-shadow:0 0 8px rgba(80,220,255,.8)} | |
| #keelBadge::after{content:'UGA';position:absolute;z-index:3;left:0;right:0;bottom:3px;color:#ffe079;font:900 5px/1 var(--fT);letter-spacing:.15em;text-align:center} | |
| #keelBadge .kr{ | |
| position:absolute; inset:4px; border-radius:50%; | |
| border:1.5px solid rgba(120,220,255,.55); | |
| } | |
| #keelBadge .kr2{ inset:10px; border-color:rgba(120,220,255,.85); } | |
| #keelBadge .kd{ | |
| position:absolute; left:50%; top:50%; width:5px; height:5px; margin:-2.5px 0 0 -2.5px; | |
| border-radius:50%; background:#bdeeff; box-shadow:0 0 6px 1px rgba(120,220,255,.9); | |
| } | |
| #keelBar.pulse #keelBadge .kr1{ animation:keelRing 1.1s ease-out; } | |
| #keelBar.pulse #keelBadge .kr2{ animation:keelRing 1.1s .12s ease-out; } | |
| @keyframes keelRing{ | |
| 0%{ transform:scale(.6); opacity:1; } | |
| 100%{ transform:scale(1.7); opacity:0; } | |
| } | |
| #keelBody{ flex:1 1 auto; min-width:0; } | |
| #keelHd{ display:flex; align-items:baseline; gap:7px; flex-wrap:wrap; } | |
| #keelName{ | |
| font-family:var(--fT); font-size:11.5px; font-weight:800; letter-spacing:.14em; | |
| color:#bdeeff; text-shadow:0 0 8px rgba(65,200,255,.5); | |
| } | |
| #keelStepTag{ | |
| font-family:var(--fT); font-size:9px; font-weight:700; letter-spacing:.1em; | |
| color:#7fa8c6; text-transform:uppercase; | |
| } | |
| #keelTxt{ | |
| margin-top:2px; font-size:12.5px; line-height:1.36; font-weight:600; color:#eaf7ff; | |
| } | |
| #keelProgress{ | |
| height:3px;margin-top:7px;border-radius:4px;overflow:hidden;background:rgba(4,12,20,.78); | |
| box-shadow:inset 0 0 0 1px rgba(120,205,242,.16); | |
| } | |
| #keelProgress i{ | |
| display:block;width:0;height:100%;border-radius:inherit; | |
| background:linear-gradient(90deg,#42c9ff,#ffe06b);box-shadow:0 0 7px rgba(88,205,255,.62); | |
| transition:width .3s ease; | |
| } | |
| #keelNext{ | |
| display:none;align-items:center;justify-content:center;min-width:92px;min-height:44px;margin-top:8px;padding:8px 15px; | |
| border-radius:8px;border:1px solid rgba(255,218,112,.75);color:#171104; | |
| background:linear-gradient(180deg,#fff0a8,#dca936);box-shadow:0 0 13px rgba(255,207,75,.28); | |
| font:900 9px/1 var(--fT);letter-spacing:.13em; | |
| } | |
| #keelSkip{ | |
| flex:0 0 auto; align-self:flex-start; | |
| /* Visual glyph is small; the tap target is not. 44px is the WCAG 2.5.5 | |
| floor — verified against the rendered box, not just the source, since | |
| box-sizing elsewhere in this codebase can make padding eat into a | |
| min-width instead of adding to it. */ | |
| min-width:52px; min-height:44px; margin:-9px -9px 0 0; | |
| display:flex; align-items:center; justify-content:center; | |
| border-radius:9px; border:none; background:transparent; color:#7fa8c6; | |
| font:800 9px/1 var(--fT);letter-spacing:.08em; | |
| box-sizing:border-box; | |
| } | |
| #keelSkip:active{ background:rgba(255,255,255,.08); color:#eaf7ff; } | |
| /* Reactive dialogue stays available during battle, but yields most of its | |
| height to the battlefield. The full line remains in the event feed and the | |
| card expands again as soon as combat heat falls. */ | |
| body.mfCombatHot #keelBar{align-items:center;gap:6px;padding:5px 7px;border-radius:9px} | |
| body.mfCombatHot #keelBadge{width:30px;height:30px;flex-basis:30px;margin:0} | |
| body.mfCombatHot #keelHd{flex-wrap:nowrap} | |
| body.mfCombatHot #keelName{font-size:9px} | |
| body.mfCombatHot #keelStepTag{display:none} | |
| body.mfCombatHot #keelTxt{margin:0;font-size:10px;line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} | |
| body.mfCombatHot #keelProgress,body.mfCombatHot #keelNext{display:none} | |
| /* Keep the destructive END / SKIP control finger-sized even as the card | |
| compacts during combat; shrinking only its visual copy saves the space. */ | |
| body.mfCombatHot #keelSkip{min-width:52px;min-height:44px;margin:-7px -7px -7px 0;font-size:8px} | |
| /* The guided target never receives input. It only makes the existing hit box | |
| visible, so the button/tab/card keeps its normal mobile interaction path. */ | |
| .keelFocus{ | |
| position:relative;z-index:22; | |
| outline:4px solid #ffe06b;outline-offset:4px; | |
| box-shadow:0 0 0 4px rgba(255,214,70,.30),0 0 30px 9px rgba(255,202,50,.82); | |
| animation:keelTarget 1.05s ease-in-out infinite; | |
| } | |
| @keyframes keelTarget{ | |
| 0%,100%{filter:brightness(1);} | |
| 50%{filter:brightness(1.38);} | |
| } | |
| #keelMapCue{ | |
| position:fixed;left:50%;top:50%;width:82px;height:82px;transform:translate(-50%,-50%);z-index:21; | |
| display:none;border:3px solid #ffe06b;border-radius:50%;pointer-events:none;box-sizing:border-box; | |
| box-shadow:0 0 0 7px rgba(255,215,72,.15),0 0 26px rgba(255,204,55,.72); | |
| animation:keelMapPulse 1.05s ease-in-out infinite; | |
| } | |
| #keelMapCue.show{display:block} | |
| #keelMapCue::before,#keelMapCue::after{content:'';position:absolute;background:#ffe06b;opacity:.9} | |
| #keelMapCue::before{width:2px;height:112px;left:37px;top:-18px} | |
| #keelMapCue::after{height:2px;width:112px;left:-18px;top:37px} | |
| #keelMapCue span{ | |
| position:absolute;left:50%;top:calc(100% + 10px);transform:translateX(-50%);min-width:108px;padding:5px 7px; | |
| border-radius:7px;background:rgba(10,15,22,.94);border:1px solid rgba(255,224,107,.75);color:#ffe891; | |
| text-align:center;white-space:nowrap;font:900 9px/1.2 var(--fT);letter-spacing:.08em; | |
| } | |
| #keelModeBadge{position:fixed;left:50%;top:calc(var(--sat) + 72px);transform:translateX(-50%);z-index:20;display:none; | |
| min-width:188px;padding:7px 10px;border:1px solid rgba(255,224,107,.72);border-radius:9px;text-align:center; | |
| background:linear-gradient(135deg,rgba(51,37,9,.96),rgba(8,21,31,.95));box-shadow:0 5px 18px rgba(0,0,0,.42),0 0 16px rgba(255,208,67,.16);pointer-events:none} | |
| #keelModeBadge.show{display:block}#keelModeBadge b,#keelModeBadge span{display:block;font-family:var(--fT);letter-spacing:.1em}#keelModeBadge b{color:#ffe792;font-size:9px}#keelModeBadge span{margin-top:3px;color:#a9d7ef;font-size:9px;font-weight:800} | |
| /* One coaching surface on a phone. STEP/TOTAL already lives in #keelBar, and | |
| ordinary command notices remain recorded in the notification log. Showing | |
| both duplicates above/below KEEL produced three stacked panels before the | |
| player could even see the unit being discussed. Emergency attack/wave rails | |
| are separate and remain available. */ | |
| body.trainingOperation #keelModeBadge,body.trainingOperation #toast{display:none} | |
| @keyframes keelMapPulse{0%,100%{transform:translate(-50%,-50%) scale(.92)}50%{transform:translate(-50%,-50%) scale(1.06)}} | |
| /* First-time entry point. PLAY remains a normal skirmish; this explicit card | |
| launches the fixed, protected training ruleset. */ | |
| #keelTrainingCallout{ | |
| width:min(88vw,360px);box-sizing:border-box;margin:15px auto 0;padding:9px;border-radius:12px;text-align:left; | |
| display:flex;align-items:center;gap:9px; | |
| border:1px solid rgba(255,216,86,.52);background:linear-gradient(180deg,rgba(43,35,15,.94),rgba(13,20,29,.97)); | |
| box-shadow:0 5px 18px rgba(0,0,0,.42),0 0 18px rgba(255,202,55,.1); | |
| } | |
| .ktMiniIdentity{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.ktMiniIdentity>img{width:38px;height:38px;object-fit:contain;flex:0 0 38px} | |
| .ktMiniIdentity>div{min-width:0}.ktMiniIdentity span,.ktMiniIdentity small{display:block;color:#ffe079;font:900 9px/1.1 var(--fT);letter-spacing:.12em} | |
| .ktMiniIdentity b{display:block;margin:3px 0;color:#fff;font:900 10px/1.1 var(--fT);letter-spacing:.06em}.ktMiniIdentity small{color:#83a5bd;letter-spacing:.08em} | |
| #keelTrainingCallout>button{ | |
| flex:0 0 98px;min-width:98px;min-height:48px;padding:8px;border-radius:8px;border:1px solid #ffe79a;color:#181203; | |
| background:linear-gradient(180deg,#fff1a8,#dda837);font:900 9px/1 var(--fT);letter-spacing:.07em; | |
| } | |
| #keelTrainingCallout+#startBtn{margin-top:10px} | |
| .keelTrainingOp{ | |
| --ktoAccent:#ffe079;position:relative;margin:0 0 13px;padding:0 12px 12px;border-radius:14px;text-align:left;overflow:hidden; | |
| border:1px solid rgba(255,215,80,.56);background:linear-gradient(155deg,rgba(53,39,11,.92),rgba(13,21,31,.98) 48%,rgba(8,27,40,.98)); | |
| box-shadow:0 8px 22px rgba(0,0,0,.35),inset 0 1px rgba(255,255,255,.04); | |
| } | |
| .keelTrainingOp::after{content:'';position:absolute;right:-65px;top:42px;width:210px;height:210px;border-radius:50%;pointer-events:none;background:radial-gradient(circle,rgba(75,194,255,.12),transparent 67%)} | |
| .keelTrainingOp.done{--ktoAccent:#8bf0b7;border-color:rgba(104,237,166,.48);background:linear-gradient(155deg,rgba(18,54,40,.82),rgba(10,23,27,.98) 52%,rgba(8,28,39,.98))} | |
| .keelTrainingOp.active{--ktoAccent:#76ddff;border-color:rgba(89,211,255,.68)} | |
| .ktoHead{height:38px;margin:0 -12px 10px;padding:0 12px;display:flex;align-items:center;justify-content:space-between;gap:8px;border-bottom:1px solid rgba(255,224,121,.21);background:rgba(4,12,19,.35)} | |
| .ktoHead span{color:var(--ktoAccent);font:900 9px/1 var(--fT);letter-spacing:.13em}.ktoHead b{padding:5px 7px;border:1px solid rgba(255,224,120,.48);border-radius:7px;color:var(--ktoAccent);font:900 9px/1 var(--fT);letter-spacing:.07em;background:rgba(0,0,0,.25)} | |
| .ktoHero{position:relative;z-index:1;display:grid;grid-template-columns:82px 1fr;gap:10px;align-items:center}.ktoPortrait{position:relative;width:82px;height:82px;border-radius:11px;overflow:hidden;border:1px solid rgba(117,214,255,.62);background:#07131e;box-shadow:0 0 15px rgba(66,190,247,.16)} | |
| .ktoPortrait>img{width:100%;height:100%;display:block;object-fit:cover}.ktoPortrait>span{position:absolute;right:4px;bottom:4px;width:34px;height:34px;display:flex;align-items:center;justify-content:center;border-radius:8px;background:rgba(3,12,20,.88);border:1px solid rgba(116,214,255,.48)} | |
| .ktoPortrait .facIc{width:28px;height:28px;object-fit:contain}.ktoIdentity{min-width:0}.ktoIdentity small{display:block;color:#77d8ff;font:900 9px/1 var(--fT);letter-spacing:.14em}.ktoIdentity>b{display:block;margin:4px 0;color:#fff;font:900 14px/1.05 var(--fT);letter-spacing:.07em}.ktoIdentity i{display:block;color:#d8ecf8;font:800 9px/1.2 var(--fT);font-style:normal}.ktoIdentity p{margin:5px 0 0;color:#91adbf;font-size:9px;line-height:1.35;font-weight:650} | |
| .ktoUgaPortrait{display:grid;place-items:center;background:radial-gradient(circle at 50% 42%,rgba(80,219,255,.2),transparent 44%),linear-gradient(145deg,#0a2638,#030b12);box-shadow:0 0 18px rgba(66,190,247,.2),inset 0 0 0 1px rgba(164,231,255,.1)} | |
| .ktoUgaPortrait::before,.ktoUgaPortrait::after{content:'';position:absolute;border:1px solid rgba(110,224,255,.42);border-radius:50%;transform:rotate(-24deg)} | |
| .ktoUgaPortrait::before{width:58px;height:58px}.ktoUgaPortrait::after{width:70px;height:28px;border-left-color:transparent;border-right-color:transparent} | |
| .ktoPortrait>span.ktoUgaSeal{position:relative;right:auto;bottom:auto;z-index:1;width:auto;height:auto;display:grid;gap:4px;padding:0;border:0;border-radius:0;background:none;text-align:center} | |
| .ktoUgaSeal b{color:#a9ecff;font:900 19px/1 var(--fT);letter-spacing:.16em;text-shadow:0 0 9px rgba(74,213,255,.7)}.ktoUgaSeal i{color:#ffe079;font:900 8px/1 var(--fT);font-style:normal;letter-spacing:.2em} | |
| .ktoTeach{position:relative;z-index:1;display:flex;flex-wrap:wrap;gap:5px;margin-top:10px}.ktoTeach span{flex:1 1 29%;min-width:82px;padding:6px 5px;border-radius:7px;text-align:center;color:#a9c8da;background:rgba(3,12,20,.55);border:1px solid rgba(116,167,200,.2);font:850 9px/1 var(--fT);letter-spacing:.06em} | |
| .ktoProgress{position:relative;z-index:1;margin-top:9px;padding:8px 9px;border-radius:9px;background:rgba(3,11,18,.58);border:1px solid rgba(119,177,212,.22)}.ktoProgress>div:first-child{display:flex;align-items:center;justify-content:space-between}.ktoProgress span{color:#8aa9bf;font:900 9px/1 var(--fT);letter-spacing:.11em}.ktoProgress b{color:var(--ktoAccent);font:900 10px/1 var(--fT)} | |
| .ktoProgressTrack{height:5px;margin-top:6px;border-radius:5px;overflow:hidden;background:#07121d}.ktoProgressTrack i{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,#2bb9ef,var(--ktoAccent));box-shadow:0 0 8px var(--ktoAccent)}.ktoProgress small{display:block;margin-top:5px;color:#809aad;font-size:9px;line-height:1.25;font-weight:700} | |
| .ktoFacts{position:relative;z-index:1;display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:8px}.ktoFacts div{padding:6px 3px;border-radius:8px;text-align:center;background:rgba(5,15,23,.62);border:1px solid rgba(110,167,200,.2)}.ktoFacts b,.ktoFacts span{display:block}.ktoFacts b{color:#eaf8ff;font:900 9px/1 var(--fT)}.ktoFacts span{margin-top:3px;color:#7998ad;font:800 9px/1 var(--fT);letter-spacing:.06em} | |
| .ktoAction{position:relative;z-index:1;width:100%;min-height:50px;margin-top:9px;padding:9px;border-radius:9px;border:1px solid rgba(255,232,144,.82);color:#171204;background:linear-gradient(180deg,#fff0a1,#d5a42e);box-shadow:0 0 14px rgba(255,207,69,.16);font:900 9px/1 var(--fT);letter-spacing:.09em}.keelTrainingOp.done .ktoAction{border-color:rgba(139,240,183,.7);background:linear-gradient(180deg,#b8f5d1,#58bf88)} | |
| @media (max-width:380px){ | |
| #keelWrap{ top:calc(var(--sat) + 196px); width:92vw; } | |
| #keelTxt{ font-size:12px; } | |
| #keelTrainingCallout{width:94vw}.ktMiniIdentity>img{display:none}#keelTrainingCallout>button{flex-basis:92px;min-width:92px} | |
| .keelTrainingOp{padding-left:10px;padding-right:10px}.ktoHead{margin-left:-10px;margin-right:-10px;padding-left:10px;padding-right:10px}.ktoHero{grid-template-columns:72px 1fr}.ktoPortrait{width:72px;height:76px}.ktoTeach span{min-width:76px} | |
| } | |
| @media (prefers-reduced-motion:reduce){ | |
| #keelWrap{ transition:none; } | |
| #keelBar{ transition:none; } | |
| #keelBar.pulse{ animation:none; } | |
| #keelBar.pulse #keelBadge .kr1,#keelBar.pulse #keelBadge .kr2{ animation:none; } | |
| #keelProgress i{transition:none} | |
| .keelFocus,#keelMapCue{animation:none} | |
| } | |
| /* SKIP vs END. The same button leaves guidance (harmless) or abandons a | |
| training match (destructive). Only the destructive state is dressed as | |
| destructive — a bordered amber chip rather than a transparent 9px hint. */ | |
| #keelSkip.keelSkipEnd{ | |
| background:rgba(255,150,60,.14); border:1px solid rgba(255,170,80,.55); | |
| color:#ffcf9a; letter-spacing:.10em; | |
| } | |
| #keelSkip.keelSkipEnd:active{ background:rgba(255,150,60,.30); color:#fff; } | |
| /* ============================================================================ | |
| WAR TABLE PRIMER — src/warprimer.js | |
| ---------------------------------------------------------------------------- | |
| The card lives INSIDE the active .mfStagePanel rather than floating over it, | |
| so there is deliberately no position/z-index/pointer-events here: it is a | |
| block in the stage's own flow and inherits that panel's scrolling. It reuses | |
| --panelG2 and the HUD type ramp for the same reason KEEL does, but takes the | |
| war table's own amber-gold accent instead of KEEL's cyan — this is table | |
| chrome, not the ship talking. | |
| ============================================================================ */ | |
| .wtpCard{ | |
| display:block; margin:0 0 12px; padding:11px 13px 10px; | |
| background:var(--panelG2,linear-gradient(160deg,rgba(14,22,30,.94),rgba(8,13,19,.96))); | |
| border:1px solid rgba(255,196,110,.34); border-radius:10px; | |
| box-shadow:inset 0 1px 0 rgba(255,220,160,.14),0 6px 18px rgba(0,0,0,.42); | |
| } | |
| .wtpCard>header{ | |
| display:flex; align-items:baseline; justify-content:space-between; gap:10px; | |
| margin-bottom:6px; | |
| } | |
| .wtpCard>header>span{ | |
| font:600 10px/1 var(--fU,system-ui); letter-spacing:.14em; color:#ffc86e; | |
| } | |
| .wtpCard>header>b{ | |
| font:700 10px/1 var(--fU,system-ui); letter-spacing:.1em; color:rgba(232,240,248,.78); | |
| white-space:nowrap; | |
| } | |
| .wtpCard>p{ | |
| margin:0 0 9px; font:600 12.5px/1.35 var(--fU,system-ui); color:rgba(232,240,248,.90); | |
| } | |
| .wtpFoot{ display:flex; align-items:center; justify-content:space-between; gap:10px; } | |
| /* The route echoes the stage stepper at the top of the screen so the card and | |
| the nav agree on where the player is, without the card scrolling that nav | |
| out of view being a problem. */ | |
| .wtpFoot>i{ | |
| display:flex; align-items:center; gap:4px; flex-wrap:wrap; font-style:normal; | |
| font:600 9.5px/1.2 var(--fU,system-ui); letter-spacing:.08em; color:rgba(232,240,248,.62); | |
| } | |
| .wtpFoot>i>u{ text-decoration:none; color:rgba(232,240,248,.42); } | |
| .wtpFoot>i>em{ font-style:normal; } | |
| .wtpFoot>i>em.past{ color:rgba(255,200,110,.78); } | |
| .wtpFoot>i>em.on{ color:#ffc86e; } | |
| .wtpDone{ | |
| flex:0 0 auto; min-height:44px; min-width:44px; padding:0 14px; | |
| background:rgba(255,196,110,.13); border:1px solid rgba(255,196,110,.44); | |
| border-radius:7px; color:#ffd79a; | |
| font:700 11px/1 var(--fU,system-ui); letter-spacing:.12em; | |
| } | |
| .wtpDone:active{ background:rgba(255,196,110,.30); color:#fff; } | |
| .wtpSkip{ | |
| flex:0 0 auto; min-height:44px; padding:0 10px; | |
| background:transparent; border:0; color:rgba(232,240,248,.78); | |
| font:700 10px/1 var(--fU,system-ui); letter-spacing:.12em; | |
| } | |
| .wtpSkip:active{ color:#fff; } | |
| .wtpCard.wtpLast{ border-color:rgba(150,255,190,.36); } | |
| .wtpCard.wtpLast>header>span,.wtpCard.wtpLast .wtpFoot>i>em.on{ color:#9fffc4; } | |
| .wtpCard.wtpLast .wtpDone{ | |
| background:rgba(120,255,180,.13); border-color:rgba(150,255,190,.46); color:#bfffd9; | |
| } | |
| @media (max-width:430px){ | |
| .wtpCard{ padding:9px 10px 9px; } | |
| .wtpFoot{ display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px; } | |
| .wtpDone,.wtpSkip{ min-width:0;width:100%;padding:0 6px; } | |
| .wtpDone:only-child{ grid-column:1/-1; } | |
| } | |