massfront-playtest / src /styles /tutorial.css
CREATORJD's picture
Publish MASSFRONT web 1.33.98 (audit wave one) (part 5)
505c280 verified
Raw History Blame Contribute Delete
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!important}
.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!important}
/* 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!important;z-index:22!important;
outline:4px solid #ffe06b!important;outline-offset:4px!important;
box-shadow:0 0 0 4px rgba(255,214,70,.30),0 0 30px 9px rgba(255,202,50,.82)!important;
animation:keelTarget 1.05s ease-in-out infinite!important;
}
@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!important}
@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!important}
.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!important;height:28px!important;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!important}.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!important}
}
/* 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; }
}