/* =====================================================================
   Design B — App UI  (Figma node 114-497 : Platform_B)
   로열블루 #1E51D6 · 3D 마스코트 · 컬러 라운드 카드 · 웨이브 헤더 · 라운드 폰트

   ※ 이 파일은 designB 전용이다. Design A 는 이 파일을 로드하지 않으므로
     여기서 무엇을 바꿔도 A 에는 영향이 없다.
     공용 파일(prototype/base.css · engine.js · flow-data.js)은 건드리지 않는다.
     base.css 기본값이 A(양피지·크림) 기준인 곳은 아래에서 B 팔레트로 덮는다.

   기준 프레임 : B_Intro 114-970 · B_Skill_list 114-1066 · B_Skill_selected 114-1230
                B_Topic_list 114-1393 · B_Game Intro 129-1572 · B_Game 162-14
                B_FP Intro 145-1673 · B_FP1 146-2041
   ===================================================================== */
:root{
  --primary:#1E51D6; --accent:#FFC531;
  --bg:#e9eefb; --ink:#22315e; --muted:#8a93b5;
  --hd-bg:#1E51D6; --line:#e4e9f6;
  --bubble-lio:#f2f5ff; --bubble-user:#dbe6ff;
  /* Figma B 는 전 화면 Nunito. (designB/index.html 이 Nunito 400~900 을 이미 로드)
     base.css 가 .passage/.ppara 등에 'Inter' 를 하드코딩한 곳은 아래 지문 섹션에서 따로 덮는다. */
  --font-head:'Nunito','Baloo 2',system-ui,sans-serif;
  --font-body:'Nunito','Inter',system-ui,sans-serif;

  /* Figma B_FP1 에서 뽑은 값 */
  --b-card-line:#e8ebf2;      /* 카드 얇은 회색 보더 */
  --b-text:#1f2530;           /* 지문·선택지 본문 (A보다 진하고 중성) */
  --b-chip:#e6eefb;           /* 키워드 하이라이트 칩 배경 */
  --b-mint:#e3f3ee;           /* Listen pill 배경 */
  --b-mint-line:#c3e4d8;
  --b-mint-ink:#12796a;
  --b-navy:#17203a;           /* QUESTION 보더·라벨 */
}
body{background:radial-gradient(1200px 600px at 50% -10%,#dfe8ff,#e9eefb)}

/* ── 유동 타이포 (B 전용) ──────────────────────────────────────────────
   base.css 는 reading(FP) 계열에만 유동 토큰(--fz-passage/bubble/q/choice/opt)을
   쓰고 intro · skill · topic · game · teach 는 px 고정이었다.
   그래서 태블릿·저해상도에서 화면은 줄어드는데 글자 크기는 그대로라 비율이 깨지고,
   저학년 가독성 하한도 없었다. FP 와 같은 방식(cqw 기반 clamp)으로 토큰을 추가한다.
   · 1cqw = #stage 폭의 1% (#stage 가 container-type:inline-size)
   · .device 는 aspect-ratio 1577/1072 고정이라 폭·높이에 함께 스케일된다
   · clamp 하한은 저학년 최소 가독 크기, 상한은 대형 화면 과대 방지 */
.device{
  --fz-hd-title: clamp(15px,   1.62cqw, 24px);   /* 헤더 우측 화면명 */
  --fz-hd-meta:  clamp(11.5px, 1.15cqw, 16px);   /* STEP · 스킬명 */
  --fz-intro:    clamp(17px,   2.05cqw, 30px);   /* 레거시 */
  /* Figma B_Topic_list 114:1488 — Medium 36 / ExtraBold 60 @ 1577 */
  --fz-topic-sub:  clamp(18px, 2.28cqw, 36px);
  --fz-topic-main: clamp(28px, 3.80cqw, 60px);
  /* 인트로 본문 : Figma B_Intro_cut2 실측 — 줄 피치 64/1400 = 4.571cqw,
     line-height 1.45 기준 폰트 3.15cqw. 기존 2.05cqw 는 54% 작았다. */
  --fz-introtxt: clamp(20px,   3.15cqw, 46px);   /* 인트로 본문 */
  /* Figma cut1 Button_go 실측 : pill 106px / 캡높이 ≈23px → 폰트 ≈2.3cqw.
     기존 1.85cqw 는 약 24% 작았다. */
  --fz-cta:      clamp(17px,   2.30cqw, 34px);   /* Let's Go 등 CTA */
  /* CTA 셰브론 원 — 버튼 높이와 분리 (축소 전 120×48% ≈ 58 유지) */
  --cta-chev:    clamp(40px, 4.8cqw, 58px);
  --fz-headline: clamp(22px,   3.30cqw, 48px);   /* skill 헤드라인 (2줄 · 확대) */
  --fz-title-md: clamp(16px,   1.90cqw, 26px);   /* 게임 제목 · 단어 카드 앞면 */
  /* 카드 라벨은 카드 폭이 곧 상자라서 px 하한을 크게 두면 저해상도에서 넘친다.
     하한을 낮추고(아래 overflow:hidden 과 함께) 카드 비율에 따라 줄어들게 둔다. */
  --fz-cardname: clamp(10px,   1.47cqw, 22px);   /* 스킬 · 토픽 카드 라벨 (Figma 실측) */
  --fz-ui:       clamp(13px,   1.35cqw, 18px);   /* 일반 UI 본문 */
  --fz-ui-sm:    clamp(11px,   1.05cqw, 14px);   /* 배지 · 캡션 */
  --fz-emoji:    clamp(20px,   2.30cqw, 32px);   /* 이모지 · 아이콘 글리프 */
}

/* 헤더 */
.hd-title{font-size:var(--fz-hd-title)}
.hd-pill,.hd-skill{font-size:var(--fz-hd-meta)}

/* 공용 소형 UI (KR 토글 · TTS · 배지 · 라벨) */
.kr,.tts,.ko-gloss,.note .muted,.td-extag,.wp-kr,.wp-ex{font-size:var(--fz-ui-sm)}
.qlabel{font-size:var(--fz-ui-sm)}
.choice .ckey,.choice .cbullet{font-size:var(--fz-ui-sm)}
.sysline span,.note,.et-label,.wordchip,.emoji-opt,
.actcard .ac-title,.actcard .ac-sub{font-family:var(--font-head);font-size:var(--fz-ui)}
.actcard .ac-title{font-weight:800}
.msgcard p{font-size:var(--fz-bubble)}
.think-bubble,.mi-ic,.eo-ic,.tcard .tc-emoji,.td-ic,
.ff-face .ff-emo,.msg .avatar.grad{font-size:var(--fz-emoji)}

/* 단어 팝업 · 단어 카드 */
.word-popup .wp-word,.td-w{font-size:var(--fz-title-md)}
.word-popup .wp-def,.word-popup .wp-ex,.td-def,.td-ex,.td-recap{font-size:var(--fz-ui)}
.word-popup .wp-kr{font-size:var(--fz-ui-sm)}
.wp-line,.wp-w{font-size:var(--fz-ui)}
.wp-front{font-size:var(--fz-title-md)}
.wp-def{font-size:var(--fz-ui-sm)}

/* 게임 · Detective · Explore */
.game-title{font-size:var(--fz-title-md)}
.game-round,.game-hint,.game-transition .msgcard p{font-size:var(--fz-ui)}
.det-clue-head{font-size:var(--fz-ui)}
.exi{font-size:var(--fz-ui)}

/* Quick Exit */
.qe-banner{font-size:var(--fz-ui)}

/* ── 헤더 : 로열블루 + 하단 웨이브 + Lio/SKILLCORE 락업 ──
   로고·웨이브는 CSS 근사가 아니라 Figma 에서 내려받은 실제 에셋을 쓴다.
   · IMAGE/b/logo_lockup.png  ← Figma 114:1155 "BI" PNG@4x 를 배경 네이비(#02195C)
     기준으로 언믹스해 투명 처리 (흰 Lio + 노란 별/호 + SKILLCORE 원본 그대로)
   · IMAGE/b/wave_header.svg  ← Figma 114:1149 "wav > Icon > Vector" 경로 원본 */
.hd{background:var(--primary);overflow:visible}
/* 물결 밴드 : 헤더 하단에 걸치는 띠 하나로 처리한다.
   ⚠ 파형은 헤더 밑선을 기준으로 위(crest)·아래(최심부) 양쪽으로 출렁인다.
     그래서 "헤더 아래에 파란 띠"만 깔거나 "헤더 안에 흰 물결"만 얹으면
     반대쪽 반이 비어 물결이 중간에 잘려 보인다.
     → 띠 전체에 헤더 블루를 깔고(아래 레이어), 그 위에 곡선 아래쪽이 본문색으로
       채워진 SVG 를 얹어(위 레이어) 경계가 통째로 파형이 되게 만든다.
   본문색은 화면마다 달라 --b-wave-img 로 교체한다 (기본 흰색 / skill 은 네이비).
   기준선 y=11.547 → 띠 높이의 38.5%(11.547/30) 지점이 헤더 밑선에 오도록 정렬.
   ⚠ 파란 레이어를 배경색(var(--primary))으로 깔면 띠의 마지막 서브픽셀 행에서
     파란색이 비쳐 헤더 밑에 얇은 라인(#D5DEF7)이 생긴다.
     → 파란 레이어를 높이 80% 그라디언트로 제한하고(곡선 최심부 77% 는 덮음),
       남은 20% 는 SVG 의 본문색 단색 구간이라 아래 페이지와 이음매 없이 붙는다. */
.hd::after{content:'';position:absolute;left:0;right:0;top:100%;height:auto;
  aspect-ratio:1577/30;transform:translateY(-38.5%);z-index:6;pointer-events:none;
  background:
    var(--b-wave-img,url("../IMAGE/b/wave_header.svg")) no-repeat top center,
    linear-gradient(var(--primary),var(--primary)) no-repeat top center;
  background-size:100% 100%, 100% 80%}
.layout-skill .hd::after{--b-wave-img:url("../IMAGE/b/wave_header_navy.svg")}

/* 텍스트로 흉내 낸 로고는 감추고 Figma 락업 이미지를 넣는다
   (마크업의 .hd-logo-img src 는 A 전용 에셋으로 하드코딩돼 있어 건드리지 않는다) */
.hd-logo-text{display:none}
.hd-brand{align-items:center;position:relative;z-index:7}
.hd-brand::before{content:'';display:block;
  height:clamp(30px,3.4cqw,42px);aspect-ratio:312/215;
  background:url("../IMAGE/b/logo_lockup.png") no-repeat left center;
  background-size:contain}
.hd-pill{color:#eaf0ff;font-weight:800}
.hd-skill{color:#b9c8f4}
.hd-title{color:#FFE169}

/* 헤더를 최상위로 : base 의 z-index:5 를 올려서 하단 물결이 어떤 화면에서도
   본문 패널에 가리지 않고 그대로 보이게 한다 (FP/reading 계열에서 특히 문제였음). */
.hd{z-index:30}

/* ── FP 콘텐츠 영역 : Design A 와 동일하게 (요청) ────────────────────────
   theme-a.css 345~375행의 reading 콘텐츠 규칙을 그대로 옮긴다.
   A 의 FP 영역은 크림톤이 아니라 중립 스킴이라 B 와 충돌하지 않는다
   — #E5EBF2 여백 + 흰 라운드 카드 + 네이비 QUESTION + 민트 Listen + 연블루 키워드 칩.
   버튼 컬러값은 요청대로 B(블루) 유지. strategy 컨테이너도 A 는 크림/골드라
   B 팔레트(연블루)로만 바꾸고 구조·간격·그림자는 A 와 동일하게 둔다.
   ※ 콘텐츠 배경은 흰색이다(요청). A 는 여백이 #E5EBF2 지만 B 는 순백을 쓰고,
     그래야 헤더의 흰 물결이 본문과 이음매 없이 이어진다.
     카드는 #e6eaf1 보더 + 옅은 그림자로 구분된다. */
.reading{background:#fff;padding:clamp(8px,1.5cqw,18px);gap:clamp(8px,1.5cqw,18px);
  box-sizing:border-box;min-height:0;overflow:hidden}
.reading .passage,
.reading .activity{background:#fff;border:1px solid #e6eaf1;border-radius:16px;
  box-shadow:0 4px 14px rgba(30,40,70,.06);margin:0}
.reading .passage{border-right:1px solid #e6eaf1}
/* base.css 가 .passage / .ppara / .qtext / .choice 등에 'Inter' 를 하드코딩해 두었다.
   Figma B 는 전 화면 Nunito 이므로 지문·질문·선택지까지 Nunito 로 덮는다. */
.reading .passage,
.reading .activity,
.ppara,.qtext,.choice,.msg .bubble,.listen-btn,
.menu-item,.et-label,.chatinput input,
.reading .activity .btn,.reading .btn{font-family:var(--font-body)}
/* Complete 배너 등 — base Inter 하드코딩 덮기 */
.reading .activity .actcard,
.reading .activity .actcard .ac-title,
.reading .activity .actcard .ac-sub{font-family:var(--font-head)}
.reading .activity .actcard .ac-title{font-weight:800}
/* 지문 : A 와 동일한 크기·행간 (이전엔 0.94배 축소 + 1.68 이라 A 보다 작았다) */
.ppara{color:#2b3550;font-size:var(--fz-passage);line-height:1.9}
.passage .kw{color:#33415e;background:#e7edf7;font-weight:600;
  border-radius:6px;padding:1px 6px;border-bottom:none}
/* ⚠ Explore 화면의 핵심어는 마크업이 class="kw kwbox" 다.
   base 의 .passage .kwbox 와 위 .passage .kw 가 특이도가 같아(0,2,0) 나중에 로드되는
   이 파일의 .kw 가 kwbox 를 덮어버려, A 와 달리 회청색 배경 + 어두운 글자로 나왔다.
   → A(= base 기본값)와 같게 되돌린다. 흰 배경 + 마젠타 2px 보더 + 마젠타 볼드. */
.passage .kwbox{background:#fff;border:2px solid #e24aa0;border-radius:8px;padding:0 4px;
  color:#c0247e;font-weight:700}
.passage .kwbox:hover,
.passage .kwbox.picked{background:#fff;box-shadow:0 2px 8px rgba(226,74,160,.22)}
/* Find & Flip 변형(연블루)도 base 값 유지 */
.findflip .passage .kwbox{background:#e3ecff;border:none;border-radius:6px;
  padding:1px 5px;color:#2b5bd0}
.listen-btn{background:#e6f4f1;border:none;color:#0f6d61;font-weight:500;
  border-radius:999px;padding:3px 8px}
.et-label{font-weight:800;letter-spacing:.5px;color:#1E2A4A;text-transform:uppercase;margin:2px 0}

/* 질문 / 선택지 : A 와 동일 */
.qbox{background:#fff;border:2px solid #26314f;border-radius:14px}
.qlabel{display:inline-block;background:#26314f;color:#fff;
  padding:3px 9px;border-radius:6px;letter-spacing:.5px;margin-bottom:7px}
.qtext{color:#26314f}
.choice{background:#fff;border:1.5px solid #E0E4EC;border-radius:14px;color:#2b3550;font-weight:500}
.choice:hover{background:#fff;border-color:#C5CDDA}
.choice .ckey{border:none;color:#2b3550;background:#F0F2F5;
  width:28px;height:28px;flex:0 0 28px;text-transform:uppercase}
.choice .cbullet{background:#eef2fb;color:#5a6785;border:none;
  width:28px;height:28px;flex:0 0 28px}

/* strategy : 구조·간격·그림자는 A 와 동일, 색만 B 팔레트 */
.reading .strategy{background:linear-gradient(180deg,#EDF3FF,#DCE6FB);border:1px solid #C9D8F7;
  border-radius:14px;gap:0;box-shadow:0 4px 14px rgba(30,60,140,.14);margin-top:14px}
.reading .strat-title{color:#1E2A4A;letter-spacing:.4px;margin-bottom:12px}
.reading .strat-item{color:#3A4560;background:#fff;border:none;border-radius:12px;
  padding:4px 10px;box-shadow:0 4px 14px rgba(30,40,70,.10)}
.reading .strat-item + .strat-item{margin-top:8px}
.reading .strat-item.on,.reading .strat-item.sel{border:none;
  box-shadow:0 6px 18px rgba(30,40,70,.16),0 0 0 2px rgba(38,49,79,.14)}

/* ── 말풍선 / 아바타 ── */
.msg .avatar{border:2px solid #fff;box-shadow:0 3px 8px rgba(30,81,214,.18)}
/* 대화창 LIO 아바타를 애니메이션으로 : IMAGE/b/lio_chat_face.webp
   — lio_sprite1(4×4, 524×502) 16프레임 전부. 윙크·미소·웃음이 이어진다.
   얼굴 폭 485~494(1.8%) 로 크기는 고정인데 bbox 중심이 x 30px · y 27px 흔들려
   프레임마다 중심을 맞췄다(정렬 후 인접 차이 평균 10.7).
   흰 원 박스 없이 얼굴만 보여야 하므로 박스는 얼굴이 잘리지 않는 크기(510×510)로 잡고
   base 의 흰 배경·원형 크롭·그림자와 theme-b 의 흰 테두리를 모두 해제했다.
   요소 크기는 48 → 54px : 얼굴이 박스의 0.892 만 차지하므로 이렇게 하면 화면상 얼굴
   크기가 기존 48px 원과 같아진다. flex-basis 도 함께 바꿔야 레이아웃이 밀리지 않는다.
   마크업이 공용 engine.js 의 <img src=lio_face2.png> 라 CSS 로 src 를 못 바꾼다 →
   content 로 1×1 투명 GIF 를 넣어 원본 비트맵만 지우고 배경에 시트를 깐다. */
.msg.lio .avatar{
  width:54px;height:54px;flex:0 0 54px;
  border:0;border-radius:0;box-shadow:none;
  content:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
  background:url("../IMAGE/b/lio_chat_face.webp") no-repeat 0% 0 / 1600% 100%;
  animation:bLioChat 1.9s steps(16,jump-none) infinite alternate}
@keyframes bLioChat{from{background-position:0% 0} to{background-position:100% 0}}
@media (prefers-reduced-motion:reduce){
  .msg.lio .avatar{animation:none}
}
/* 선택 상태 색 통일 : 단어 카드(.tcard.cur, base.css)가 주황(#F08A24)인데 선택지만 파랑
   (--primary)이라 B 안에서 색이 섞여 있었다. 주황으로 맞춘다. */
.choice.sel{border-color:#F08A24;box-shadow:0 0 0 3px rgba(240,138,36,.28)}
/* 메뉴형 보기(Entry Method·Something else 등)도 같은 주황으로. base 는 파란 배경+테두리다. */
.menu-item.sel{background:#fff7ee;border-color:#F08A24;box-shadow:0 0 0 3px rgba(240,138,36,.28)}
/* 기획서: 문장은 클릭 전 파란색 → 클릭 이후 초록색으로 전환된다.
   base 의 .sent.tapped 는 파랑(#cfe0ff)이라 '전환' 이 드러나지 않았다. */
.sent.clarify-live{background:#e6eefb}
.sent.tapped{background:#d9f2e4}
.msg .bubble{border-radius:18px}
.msg.lio .bubble{background:#eef2f8;border:none;color:#0a0a0a}
/* retry 말풍선(slide 19·46)도 일반 말풍선과 같은 색.
   base.css 의 분홍(#fff3f3 + 붉은 테두리)은 .msg.lio.retry 로 클래스가 하나 더 많아
   위 규칙보다 우선하므로, 같은 선택자로 덮어야 한다. theme-a 도 같은 처리를 해 두었다. */
.msg.lio.retry .bubble{background:#eef2f8;border:none}

/* ── 버튼 : 라운드, 굵게 ──
   그라데이션 세기를 파란 버튼 기준으로 통일한다. 위→아래 밝기 차이를 크게 주면
   저학년 화면에서 버튼이 무겁게 읽히므로 채널당 약 15~20 정도만 떨어뜨린다.
   navy·green 은 base 의 radial(끝 색 #121a2e / #165a3c)이 너무 어두워서
   같은 세기의 완만한 linear 로 바꾸고 전체 밝기를 올린다. */
.btn{border-radius:26px;box-shadow:0 4px 0 rgba(0,0,0,.06)}
.btn.primary{background:linear-gradient(180deg,#3E69E6,#2E58DC)}
.btn.navy{background:linear-gradient(180deg,#41547C,#33436A)}
.btn.green{background:linear-gradient(180deg,#33C079,#26A967)}
.btn.dark{background:linear-gradient(180deg,#2FB471,#26A063)}   /* green 과 같은 계열로 맞춤 */
.btn.purple{background:linear-gradient(180deg,#9366ff,#7C4DFF)}
.btn.orange{background:linear-gradient(180deg,#ffab3d,#F08A24)}
/* 전송(종이비행기) : base 주황 radial → B 파란 톤앤매너 */
.btn.btn-send,
.btn.primary.btn-send{
  background:radial-gradient(circle at 32% 28%,#5B84F5 0%,#3E69E6 48%,#2E58DC 100%);
  color:#fff}
/* Figma A_Intro_cut3 버튼 유지 */
.btn.figma-green{background:#009d54;border:4px solid #00763f;border-radius:50px;box-shadow:none;font-family:'Nunito',sans-serif;font-weight:900}
.btn.figma-navy{background:#1E2A4A;border:4px solid #18223c;border-radius:50px;box-shadow:none;font-family:'Nunito',sans-serif;font-weight:900}

/* ── 질문 / 선택지 : Figma B_FP1 ──
   QUESTION = 흰 배경 + 진한 네이비 2px 보더, 라벨은 네이비 solid pill */
.qbox{border-radius:14px;border:2px solid var(--b-navy);background:#fff}
.qlabel{display:inline-block;background:var(--b-navy);color:#fff;
  border-radius:5px;padding:3px 8px;letter-spacing:.09em;margin-bottom:7px}
.qtext{color:var(--b-text)}
/* 선택지 : 얇은 회색 보더 + 좌측 회색 원형 대문자 배지 */
.choice{border-radius:12px;border:1px solid var(--b-card-line);color:var(--b-text);font-weight:500}
.choice:hover{border-color:#c2d0f5}
.choice .ckey,.choice .cbullet{width:28px;height:28px;flex:0 0 28px;
  background:#f0f2f5;color:#6b7690;text-transform:uppercase;font-size:13px}

/* ── center / message ── */
.msgcard{border-radius:22px;background:#f5f8ff;border-color:#e0e8fb;box-shadow:0 8px 22px rgba(30,81,214,.06)}
.center-mascot.big{border:4px solid #fff;box-shadow:0 8px 24px rgba(30,81,214,.2)}

/* ── 인트로 (greeting / plan / fp2_intro) : Figma B_Intro_cut1·cut2 / Game Intro / FP Intro ──
   Figma 는 플랫 로열블루 #1C4BD6 + 하단 3겹 물결 + 좌상단 소형 로고 + 흰 pill 버튼,
   말풍선 없이 흰 텍스트가 배경 위에 바로 올라간다.
   .introseq 의 배경 일러스트는 flow-data(공용)의 inline style 이라 손대지 않고
   ::before 오버레이로 덮는다. (마스코트 z-index:3, 말풍선 z-index:2 는 위에 남는다) */
.scr-greeting .hd, .scr-greeting_cut3 .hd, .scr-plan .hd,
.scr-skill_video_intro .hd, .scr-game_intro .hd, .scr-fp1_intro .hd,
.scr-fp2_intro .hd, .scr-fp2_intro_cut2 .hd{display:none}
/* 배경 = 소형 로고(좌상단) + Figma 마스코트(좌측, 물결 위) + 하단 3겹 물결 + 플랫 블루.
   마스코트 크기·위치는 Figma 좌표 기준 : lio 프레임 673/1072 = 높이 62.8%,
   좌측 x=115/1577 ≈ 7.3% (cut2) · x=59/1577 ≈ 3.7% (Game/FP Intro) */
.introseq::before{content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    url("../IMAGE/b/wave_front.svg") repeat-x left bottom / 106.912% 31.25%,
    url("../IMAGE/b/wave_mid.svg")   repeat-x left bottom / 100% 31.25%,
    url("../IMAGE/b/wave_back.svg")  repeat-x left bottom / 100% 31.25%,
    /* 요청 : slide 6 의 lio 를 slide 5(splash)와 같은 크기·위치로 통일 */
    var(--b-intro-lio, none) no-repeat left 9.1% bottom 44% / auto 64%,
    /* LIO 발 밑 자연스러운 접지 그림자 */
    var(--b-intro-shadow, radial-gradient(ellipse 20% 5% at 23.5% 56%,
      rgba(6,18,52,.42) 0%, rgba(6,18,52,.22) 38%, transparent 72%)),
    var(--b-intro-bg,#1C4BD6)}

/* slide 6 (greeting cut2·cut3) : LIO 를 말하는 스프라이트로 교체.
   배경 레이어(--b-intro-lio)를 끄고 .introseq-scrim 을 호스트로 쓴다.
   발이 물결에 조금 가려지는 구성을 유지하려면 사자가 "파란 배경 위 · 물결 아래" 여야
   하는데 둘 다 ::before 한 레이어 안에 있다 → 파란 배경만 .introseq 로 내리고
   ::before 는 물결만 남긴다. inline background-image(공용 flow-data)는 !important 로 끈다.
   그림자도 끈다 — 원래는 배경 목록에서 사자 아래에 깔려 안 보였는데, 사자가 요소로
   빠지면 ::before 가 사자 위로 와서 몸통에 검은 얼룩으로 보인다. */
.scr-greeting .introseq,
.scr-greeting_cut3 .introseq,
.scr-plan .introseq,
.scr-skill_video_intro .introseq,
.scr-game_intro .introseq,
.scr-fp1_intro .introseq,
.scr-fp2_intro .introseq,
.scr-fp2_intro_cut2 .introseq{--b-intro-lio:none;--b-intro-shadow:none;--b-intro-bg:transparent;
  background-image:none !important;background-color:#1C4BD6}

/* IMAGE/b/lio_talk.webp — intro_sprite3(4×4, 456×550) 3행 4프레임.
   3행을 고른 이유 : 입이 닫힘 → 크게 벌림 → 벌림 → 살짝 순으로 실제 말하는 사이클이고,
   행 안에서 머리 크기가 일정하다(갈기 좌단 30~36 · 머리폭 233~239 · 코 y 231~234).
   행끼리는 머리 크기가 16% 까지 달라 섞으면 튄다. 시트 전체가 발밑 534 · 발중심 236 으로
   정합돼 있어 행 단위로 배율 하나만 적용하면 된다.
   크기·위치는 기존 cut2 렌더와 동일 : 머리-발 490.5px · 발밑 y645.9 · 발중심 x261.0.
   4프레임뿐이라 alternate 로 왕복시켜 되돌아오는 지점을 없앤다. */
.scr-greeting .introseq .introseq-scrim,
.scr-greeting_cut3 .introseq .introseq-scrim{display:block;inset:auto;
  /* 크기 기준은 slide 5 : 사자 머리-발 485.5px. slide 5·6 은 머리폭/머리-발 비율이
     0.501 / 0.503 으로 같아 머리-발을 맞추면 머리 크기도 그대로 맞는다.
     (기존 정지 에셋 cut2 의 머리에 맞추면 7% 커져 slide 5 와 어긋난다) */
  left:3.59%;top:19.22%;width:37.62%;aspect-ratio:430/519;z-index:0;pointer-events:none;
  background:url("../IMAGE/b/lio_talk.webp") no-repeat 0% 0 / 400% 100%;
  animation:bLioTalk .34s steps(4,jump-none) infinite alternate}
@keyframes bLioTalk{from{background-position:0% 0} to{background-position:100% 0}}
/* GO 말풍선 — cut2 안에 합쳐져 있던 것을 잘라낸 에셋(IMAGE/b/bubble_go.png · 146×142).
   slide 5 의 HI! 와 같은 방식으로 스프라이트 요소의 ::after 로 붙이고 둥둥 뜨게 한다.
   위치는 cut2 에서의 좌표를 호스트 기준으로 환산한 값이라 원래 자리와 같다. */
.scr-greeting .introseq .introseq-scrim::after,
.scr-greeting_cut3 .introseq .introseq-scrim::after{content:'';position:absolute;
  left:85.87%;top:13.81%;width:16.54%;aspect-ratio:97/94;
  background:url("../IMAGE/b/bubble_go.png?v=20260812") no-repeat center/contain;
  filter:drop-shadow(0 clamp(2px,.45cqw,7px) clamp(4px,.85cqw,13px) rgba(6,18,52,.32));
  animation:bBubbleFloat 2.4s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){
  .scr-greeting .introseq .introseq-scrim,
  .scr-greeting_cut3 .introseq .introseq-scrim,
  .scr-greeting .introseq .introseq-scrim::after,
  .scr-greeting_cut3 .introseq .introseq-scrim::after{animation:none}
}

/* slide 9 (Game_Intro) : LIO 를 주먹 쥐고 준비하는 스프라이트로.
   IMAGE/b/lio_game_idle.webp — game_sprite1(4×4, 414×566) 의 1-3 · 1-4 · 2-1 · 2-2.
   이 시트는 4포즈 × 4프레임 구조라(그룹 사이 프레임차 20~30, 그룹 안 2~9) 그룹을 섞으면
   고개 각도가 튄다. 이 4프레임은 갈기 좌단 60 · 머리폭 212 고정 · 코 x 165.9~170.4 로
   거의 붙어 있어 잔잔한 대기 동작이 된다. alternate 로 왕복.
   크기·위치는 기존 lio_intro_plan.png 렌더에서 역산 :
     머리-발 487.9px · 발밑 y644.5 · 발중심 x263.9 → width 32.26% · left 5.63% · bottom 14.93%.
   구조(파란 배경을 .introseq 로 내리고 ::before 는 물결만, 그림자 끄기)는 slide 6 과 동일. */
.scr-plan .introseq .introseq-scrim{display:block;inset:auto;
  /* 크기 기준은 slide 5 : 사자 머리-발 485.5px.
     이 시트는 머리폭/머리-발 비율이 0.451 로 slide 5(0.501)보다 작아 머리-발을 맞추면
     머리가 10% 작게 보이지만, 화면 간 크기 기준을 slide 5 로 통일하는 쪽을 택했다. */
  left:5.33%;bottom:14.91%;width:32.88%;aspect-ratio:414/566;z-index:0;pointer-events:none;
  background:url("../IMAGE/b/lio_game_idle.webp") no-repeat 0% 0 / 1600% 100%;
  animation:bLioGameIdle 2.4s steps(16,jump-none) infinite alternate}
@keyframes bLioGameIdle{from{background-position:0% 0} to{background-position:100% 0}}
/* slide 10 (Skill Video Intro) : 안락의자에서 팝콘 들고 보며 손 흔드는 LIO.
   IMAGE/b/lio_video_watch.webp — video_sprite(4×4, 462×540) 16프레임 전부, 원본 그대로.
   16프레임이 바닥 531 · 좌단 31 이 완전히 같고 스카프 중심도 130~135(4px)라 정규화가
   필요 없다(폭 401~428 · 높이 520~529 변동은 흔드는 앞발). 프레임차 3.0~23.7 · 평균 11.2.
   크기·위치는 slide 9 LIO 기준 : 전체 높이 485.5px 를 맞추고(배율 0.934), 의자 아래를
   같은 접지선(y644.5)에, 내용 왼쪽 끝을 같은 x(68.3px)에 뒀다.
   ⚠ 가로를 스카프 중심으로 맞추면 안 된다 — 이 시트는 스카프가 몸 왼쪽에 치우쳐 있어
     전체가 오른쪽으로 밀리고 팝콘이 본문 영역(x530~)을 침범한다. 왼쪽 끝 정렬이면
     내용이 x68~444 로 끝나 여유가 있다.
   → slide 9 · 10 · 12 · 14 에서 LIO 가 같은 접지선·같은 크기로 이어진다. */
.scr-skill_video_intro .introseq .introseq-scrim{display:block;inset:auto;
  left:3.48%;bottom:14.98%;width:38.17%;aspect-ratio:462/540;
  z-index:0;pointer-events:none;
  background:url("../IMAGE/b/lio_video_watch.webp") no-repeat 0% 0 / 1600% 100%;
  animation:bLioVideoWatch 2.4s steps(16,jump-none) infinite alternate}
@keyframes bLioVideoWatch{from{background-position:0% 0} to{background-position:100% 0}}
/* slide 12 (Game Intro) : 안락의자에서 컨트롤러 든 LIO.
   IMAGE/b/lio_game_play.webp — game_sprite(4×4, 534×524) 16프레임 전부, 원본 그대로.
   갱신본은 정합이 매우 좋다 : 우단 487 · 바닥 521 이 16프레임 전부 동일, 스카프 중심도
   286~287(1px). 좌단 2~77 · 높이 509~518 변동은 움직이는 꼬리와 앞발이다.
   프레임차 6.4~19.9 · 평균 12.5.
   크기·접지는 slide 9 LIO 기준(전체 높이 485.5px · 접지 y644.5, 배율 0.952).
   가로는 내용 왼쪽 끝을 slide 9 와 같은 x(68.3px)에 맞춘다 — 스카프 중심(1px 로 가장
   안정적)으로 맞추면 left 가 -0.78% 가 되어 사자가 화면 왼쪽 밖으로 밀린다.
   → 이 정렬이면 내용이 x68~514 로 끝나 본문(x530~) 앞에서 여유가 생긴다. */
.scr-game_intro .introseq .introseq-scrim{display:block;inset:auto;
  /* 요청 : 20px 더 왼쪽 (4.44% → 2.67%) */
  left:2.67%;bottom:15.71%;width:44.99%;aspect-ratio:534/524;
  z-index:0;pointer-events:none;
  background:url("../IMAGE/b/lio_game_play.webp") no-repeat 0% 0 / 1600% 100%;
  animation:bLioGamePlay 2.4s steps(16,jump-none) infinite alternate}
@keyframes bLioGamePlay{from{background-position:0% 0} to{background-position:100% 0}}
/* slide 14 (FP1 Intro) : 책과 연필 들고 서 있는 LIO.
   IMAGE/b/lio_fp1_book.webp — fp_sprite0(4×4, 456×550) 16프레임 전부, 원본 그대로.
   정합이 가장 좋은 시트다 : 발중심 238~240(1px) · 바닥 545~546(1px) · 상단 2~4(2px) ·
   높이 541~544(3px). 좌단 2~30 변동은 움직이는 꼬리다. 프레임차 1.8~24.0 · 평균 9.4.
   크기·위치는 slide 9 LIO 기준 : 전체 높이 485.5px · 접지 y644.5 (배율 0.897),
   가로는 발중심을 같은 x(263.9)에 맞췄다 — 이 시트는 발중심이 1px 로 고정이어서
   slide 9 과 같은 기준(발중심)을 그대로 쓸 수 있다. 내용은 x76~431 로 본문(530~) 앞에서 끝난다. */
.scr-fp1_intro .introseq .introseq-scrim{display:block;inset:auto;
  left:4.34%;bottom:15.49%;width:36.22%;aspect-ratio:456/550;
  z-index:0;pointer-events:none;
  background:url("../IMAGE/b/lio_fp1_book.webp") no-repeat 0% 0 / 1600% 100%;
  animation:bLioFp1Book 2.4s steps(16,jump-none) infinite alternate}
@keyframes bLioFp1Book{from{background-position:0% 0} to{background-position:100% 0}}
@media (prefers-reduced-motion:reduce){
  .scr-plan .introseq .introseq-scrim,
  .scr-fp1_intro .introseq .introseq-scrim,
  .scr-game_intro .introseq .introseq-scrim,
  .scr-skill_video_intro .introseq .introseq-scrim{animation:none}
}
/* plan 은 스프라이트(.introseq-scrim)로 바뀌어 배경 레이어를 쓰지 않는다.
   ⚠ 여기서 --b-intro-lio 를 다시 지정하면 위(.scr-plan .introseq{--b-intro-lio:none})와
     특이도가 같아 뒤가 이기고, 정지 이미지 + 스프라이트가 겹쳐 사자가 둘로 보인다. */
/* fp2_intro 도 스프라이트(.introseq-scrim)로 바뀌어 배경 레이어를 쓰지 않는다.
   ⚠ 여기서 --b-intro-lio 를 다시 지정하면 위 규칙과 특이도가 같아 뒤가 이기고
     정지 이미지 + 스프라이트가 겹쳐 사자가 둘로 보인다 (slide 9 에서 겪음). */

/* slide 35 (FP2_Intro cut1·cut2) : 책 보며 꼬리 흔드는 스프라이트.
   IMAGE/b/lio_fp_read.webp — fp_sprite1(4×4, 546×502) 16프레임 전부, 리샘플 없음.
   16프레임이 발밑 495 · 발중심 281~282 로 같고 몸높이 편차 1.6%, 프레임차도 3.7~17.7 로
   고르게 이어져 한 덩어리 애니메이션이다(좌측 폭 변동은 꼬리). alternate 로 왕복.
   머리폭/머리-발이 0.606 으로 기존 lio7.png(0.597)와 거의 같아 총 높이 기준으로 맞춰도
   머리 크기가 어긋나지 않는다.
   크기·위치는 기존 lio7 렌더(auto 54%)에서 역산 : 머리-발 412.1px · 발밑 y610.8 ·
   발중심 x273.8 → width 40.80% · left 3.16% · bottom 19.70%. */
.scr-fp2_intro .introseq .introseq-scrim,
.scr-fp2_intro_cut2 .introseq .introseq-scrim{display:block;inset:auto;
  left:3.16%;bottom:19.70%;width:40.80%;aspect-ratio:546/502;z-index:0;pointer-events:none;
  background:url("../IMAGE/b/lio_fp_read.webp") no-repeat 0% 0 / 1600% 100%;
  animation:bLioFpRead 2.6s steps(16,jump-none) infinite alternate}
@keyframes bLioFpRead{from{background-position:0% 0} to{background-position:100% 0}}
@media (prefers-reduced-motion:reduce){
  .scr-fp2_intro .introseq .introseq-scrim,
  .scr-fp2_intro_cut2 .introseq .introseq-scrim{animation:none}
}
/* lio7 : 책을 더 보이게 기본(64%)보다 살짝 축소 */
.scr-fp2_intro .introseq::before,
.scr-fp2_intro_cut2 .introseq::before{
  background-size:
    106.912% 31.25%,
    100% 31.25%,
    100% 31.25%,
    auto 54%,
    auto,
    auto}
/* cut2는 문장 1줄 + 버튼 → 텍스트를 조금 올려 버튼과 여유 확보 */
.scr-fp2_intro_cut2 .introseq .ib-layer{top:28%;bottom:22%}
/* slide 14 (FP1 Intro) 는 문장이 길어 기본 영역(top 32.9%)에서는 6줄이 되어 버튼
   (상단 y535px = 69.7%)과 겹친다 → 이 화면만 영역을 올리고 글자를 0.9배로 줄인다. */
.scr-fp1_intro .introseq .ib-layer{top:24%}
/* intro 본문 크기는 전 화면 공통(--fz-introtxt). 예전엔 이 화면만 0.9배로 줄였는데
   문구가 6줄이라 CTA 를 침범했기 때문이었다. 지금 문구는 원래 크기로도 들어간다. */
.introseq .introseq-scrim{display:none}
/* 좌상단 로고를 배경 스택에서 떼어 별도 레이어로 둔다 (::before 는 배경·물결·마스코트).
   slide 5 는 대형 로고가 우측 중앙에 있고, slide 6 에서 좌상단으로 축소·이동한다.
   두 화면이 한 흐름으로 읽히도록 slide 6 진입 시 slide 5 의 좌표·크기에서 시작한다.
   ※ 실제로 두 슬라이드를 한 페이지로 합치는 것은 engine.js/flow-data(공용) 소관이라
     여기서는 진입 애니메이션으로 연속감만 만든다. */
.introseq::after{content:'';position:absolute;inset:0;z-index:4;pointer-events:none;
  background:url("../IMAGE/b/logo_lockup.png") no-repeat left clamp(10px,2.283cqw,36px) top clamp(7px,1.268cqw,20px) / auto clamp(26px,3.54cqw,56px)}
.scr-greeting .introseq::after{animation:bLogoDock .9s cubic-bezier(.35,.05,.2,1) both}
@keyframes bLogoDock{
  from{background-position:left 79.5% top 42.1%; background-size:auto 25.4%}
  to  {background-position:left clamp(10px,2.283cqw,36px) top clamp(7px,1.268cqw,20px);
       background-size:auto clamp(26px,3.54cqw,56px)}
}
/* Figma : 말풍선 없이 흰 본문 텍스트. Maya=옐로, 스킬명=시안
   본문 블록은 마스코트 오른쪽 (Figma x=653/1577≈41%)
   ⚠ engine 의 layoutIntroSeq 는 말풍선을 하나씩 띄우고 지운다(A 인트로 시퀀스).
     그래서 B 는 대사가 한 줄씩 깜빡이다 사라져 화면이 비어 보였다.
     Figma cut2 / Game Intro / FP Intro 는 여러 줄이 한 번에 보이므로
     .ib 를 겹치지 않게 세로로 쌓고 항상 보이게 한다.
     (자동 전환 타이머는 engine.js 소관이라 그대로 남는다) */
/* 문장은 위에서부터 아래로 쌓인다. center 로 두면 문장이 추가될 때마다 이미 나온
   문장이 위로 밀려 올라가 읽는 흐름이 끊긴다 → flex-start 로 첫 줄 위치를 고정. */
.introseq .ib-layer{left:46.9%;right:8.6%;top:32.9%;bottom:12%;
  display:flex;flex-direction:column;justify-content:flex-start;gap:.45em}
.introseq .ib{position:static;left:auto;right:auto;top:auto;bottom:auto;
  max-width:100%}
/* engine 은 .show 를 붙였다 떼고 .done 을 붙인다 → 지나간 문장이 사라졌다.
   문장은 TTS 속도에 맞춰 하나씩 등장하고 그대로 남아야 하므로 두 상태 모두 노출한다. */
.introseq .ib.show,
.introseq .ib.done{opacity:1;transform:none}
/* Let's Go 버튼 : engine 이 인라인 style="display:none" 으로 감춰두고 마지막 문장이 끝나면
   style.display='' 로 지운다. 여기서 display 를 !important 로 주면 감춰둔 것까지 덮어써
   문장이 나오기 전부터 버튼이 보인다 → 인라인에 display 가 남아 있는 동안은 건드리지 않는다.
   (감춰진 상태 : style 에 display 가 있음 / 공개 상태 : engine 이 지워 없음) */
.introseq .introseq-next:not([style*="display"]){display:inline-flex!important}
.introseq .ib-bubble{background:transparent;box-shadow:none;color:#fff;padding:0}
.introseq .ib-bubble::after{display:none}
.introseq .ib-bubble .nm{color:#FFE169;font-weight:800}
.introseq .ib-bubble .lio-nm{font-weight:800;color:inherit}
.introseq .ib-bubble .mi{color:#3EE0D0;font-weight:800}
.introseq .ib-spk{color:#cfe0ff}
/* Quick Exit(slide 46) 도 intro 타입과 동일 블루 씬으로 통일 — 아래 .scr-quick_exit 참고 */
.quickexit .ib-bubble .nm{color:#FFE169;font-weight:800}
.quickexit .ib-bubble .mi{color:#3EE0D0;font-weight:800}
.introseq .ib-bubble,
.quickexit .ib-bubble{
  font-family:var(--font-body);
  font-size:var(--fz-introtxt);font-weight:600;line-height:1.45;
}
/* Let's Go! : Figma 는 흰 pill + 파란 셰브론 원, 위치 x60.1~81.6% / y67.8~78.8%.
   마크업 문구가 "Let's go! ▶"(flow-data, 공용)라 font-size:0 으로 감추고
   ::before 로 Figma 라벨을 그린다. 접근성 이름은 원문 그대로 남는다. */
/* plan / fp2_intro 는 flow-data 가 ctaImg 를 지정해 A 의 초록 Figma PNG(imgbtn)로
   렌더된다. B 는 Figma 대로 흰 pill 이어야 하므로 이미지를 감추고 같은 pill 로 통일한다. */
.introseq .introseq-next img{display:none}
.introseq .introseq-next,
.introseq .introseq-next.btn,
.introseq .introseq-next.btn.primary{
  /* 라벨 길이가 화면마다 달라(Let's Go! ~ Let's get started!) 왼쪽을 고정하면 오른쪽이
     들쭉날쭉해진다. 문구 중 가장 긴 문장의 끝(실측 89.9%)에 우측을 맞춘다 —
     폭이 auto 인 화면도 왼쪽으로 늘어나므로 모든 인트로에서 오른쪽 선이 같다. */
  position:absolute;right:10.1%;left:auto;bottom:21.2%;transform:none;
  width:21.5%;height:9.1%;min-height:0;
  padding:0 calc(var(--cta-chev) + clamp(8px,1cqw,13px)) 0 clamp(8px,1cqw,13px);
  box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;
  border-radius:999px;font-size:0;color:var(--primary);text-align:center;
  background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Ccircle cx='30' cy='30' r='30' fill='%23155DFC'/%3E%3Cpath d='M25.5 19.5L36 30L25.5 40.5' stroke='white' stroke-width='5.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right clamp(8px,1cqw,13px) center;
  background-size:var(--cta-chev) var(--cta-chev);
  box-shadow:0 10px 26px rgba(6,26,84,.24)}
.introseq .introseq-next::before{content:"Let's Go!";
  font-family:var(--font-head);font-weight:800;font-size:var(--fz-cta);letter-spacing:-.2px}
/* slide 9 (Game_Intro) 만 버튼 라벨이 다르다. 라벨은 flow-data 가 아니라 여기서 CSS 로
   그리므로(.introseq-next img 는 display:none) 화면별로 덮어쓴다.
   "Let's Go!"(9자) → "Let's get started!"(18자) 로 두 배가 되어 고정 폭 21.5% 에서는
   글자가 겹친다 → 이 화면만 내용에 맞춰 늘리고(오른쪽 끝·높이는 그대로) 줄바꿈을 막는다.
   좌우 여백을 같게 줘야 pill 안에서 글자가 가운데 온다(기본 규칙은 오른쪽에 셰브론 자리를
   비워두느라 좌우가 비대칭이다).
   ⚠ Design A 는 같은 버튼을 ctaImg(ui/btn_letsplay.png) 이미지로 그리므로 영향 없다. */
.scr-plan .introseq .introseq-next,
.scr-plan .introseq .introseq-next.btn,
.scr-plan .introseq .introseq-next.btn.primary,
.scr-skill_video_intro .introseq .introseq-next,
.scr-skill_video_intro .introseq .introseq-next.btn,
.scr-skill_video_intro .introseq .introseq-next.btn.primary,
.scr-game_intro .introseq .introseq-next,
.scr-game_intro .introseq .introseq-next.btn,
.scr-game_intro .introseq .introseq-next.btn.primary{
  width:auto;white-space:nowrap;left:auto;
  padding:0 calc(var(--cta-chev) + clamp(10px,1.4cqw,20px)) 0 clamp(20px,2.4cqw,34px)}
.scr-plan .introseq .introseq-next::before{content:"Let's get started!"}
.scr-skill_video_intro .introseq .introseq-next::before{content:"Let's watch!"}
.scr-game_intro .introseq .introseq-next::before{content:"Let's play!"}
.introseq .ib-spk{font-size:var(--fz-ui)}
.introseq .introseq-replay{bottom:5%;right:3%;font-size:var(--fz-ui-sm)}
.quickexit .ib-left{left:18%;top:11%}
.quickexit .ib-right{right:18%;top:24%}
.quickexit .ib-bubble{max-width:min(34vw,320px)}

/* ── Quick Exit (slide 46·49) : greeting/plan/fp2 와 동일 intro 블루 씬 ── */
.scr-quick_exit .hd,
.scr-post_skill_pick .hd{display:none}
.scr-quick_exit .quickexit.has-bg,
.scr-post_skill_pick .quickexit.has-bg{
  background:#1C4BD6 !important;background-image:none !important}
/* slide 46 LIO — 웅크렸다 두 팔 벌리며 폴짝 뛰는 스프라이트.
   IMAGE/b/lio_fp_cheer.webp — fp_sprite2 중 12장 (원본 436×618 리샘플·재배치 없이 그대로) :
     1-2 · 2-3 · 3-4  손을 모아 웅크린 준비 (발밑 615)
     2-2 · 4-4 · 3-3 · 2-4 · 4-2 · 2-1 · 4-3 · 3-1 · 3-2  팔을 벌리며 상승 (606 → 519)

   떨림 원인은 두 번 오진했다. ① 발 중앙으로 가로를 맞춘 것 — 다리를 벌리면 발 중앙이
   92px 끌려서 그 값으로 맞추는 바람에 몸을 최대 84px 밀어버렸다. ② 16장을 발 높이순으로만
   늘어놓은 것 — 스카프 중심으로 재보면 236~242(6px)라 시트는 정확히 정합돼 있고, 진짜
   문제는 순서였다. 높이순만으로는 머리 기울기가 무작위로 튀어 인접 프레임차가 57 까지 간다.
   → "발밑은 계속 올라가면서 인접 차이는 작은" 최장 경로를 DP 로 뽑았다.
     12장에서 인접 차이 최대 32.6(웅크림이 풀리며 팔이 벌어지는 실제 동작) · 평균 22.2 ·
     머리 중심 흔들림 최대 8px. 남은 4장(1-1 · 1-3 · 1-4 · 4-1)은 어디에 끼워도 이웃과의
     차이가 39~57 로 벌어져 다시 떨리므로 뺐다.
   ★ 떨림의 실제 원인은 순서가 아니라 '상승을 시트에 구워 넣은 것' 이었다. 발밑이
     617·616·616·607·583·575·549·535·525·523·522·521 로 3프레임 정지 → 25px 두 번 급등 →
     정점에선 1~2px. 1차 추세를 제거해도 잔차가 폭 29.8px(프레임당 최대 14px)이고,
     37.5ms/프레임이라 이게 진동으로 보였다.
     → 모든 프레임 발밑을 617 로 정렬해(편차 1px) 상승을 시트에서 빼고, 96px 은 아래
       bLioHop(translateY) 로 옮겼다. 자세는 steps 로 넘어가고 수직 이동만 보간되어
       완전히 매끄럽다. 프레임은 원본 칸 그대로라(가로 오프셋 0) 원본에서 다시 만들었다.
   폴짝 한 번이 0.9s (오르기 .45s + alternate 로 내려오기 .45s).
   가로는 스카프 중심(가장 안정적인 기준)을 기존 에셋에 맞췄고 머리-발은 slide 5 와 같은 485.5px. */
.scr-quick_exit .qe-scrim{display:block;inset:auto;
  left:2.41%;bottom:15.50%;width:39.60%;aspect-ratio:436/618;
  z-index:0;pointer-events:none;
  background:url("../IMAGE/b/lio_fp_cheer.webp") no-repeat 0% 0 / 1200% 100%;
  animation:bLioCheer 1s steps(12,jump-none) infinite alternate,
            bLioHop   1s ease-out          infinite alternate}
/* 앞 20% 는 지면에서 쉬는 박자. alternate 라 '상승 직전' 과 '착지 직후' 양쪽에 걸려
   실제 쉼은 0.40s 가 된다. 상승 0.80s(12프레임 → 66.7ms/프레임) · 한 번 뛰는 데 2.0s.
   전에는 0.45s·37.5ms/프레임에 쉼도 없어(다음으로 빠른 bLioTalk 가 85ms, 통상 118~162ms)
   끊임없이 튕기는 것이 떨림으로 읽혔다. */
@keyframes bLioCheer{0%,20%{background-position:0% 0} 100%{background-position:100% 0}}
/* 96px / 시트 높이 618px = 15.534%. translate 의 % 는 요소 자기 크기 기준이라
   해상도가 달라져도 어긋나지 않는다.
   ease-out : 뛰어오를수록 느려지는 실제 도약. alternate 로 되짚으면 내려올 때는
   반대로 가속(ease-in)이 되어 낙하가 자연스럽다. */
@keyframes bLioHop{0%,20%{transform:translateY(0)} 100%{transform:translateY(-15.534%)}}
/* 하트 말풍선 — 원래 lio_intro_fp2.png 안에 합쳐져 있던 것을 잘라낸 에셋
   (IMAGE/b/bubble_heart.png · 146×141, HI!/GO 와 같은 규격).
   전에는 프레임별 상승량을 top 키프레임(bHeartRide)에 손으로 넣어 사자를 따라 올라가게
   했지만, 이제 상승이 호스트의 translateY 라서 배경(사자)과 ::after(하트)가 함께 움직인다
   — 키프레임을 지웠고 둥둥 뜨는 bBubbleFloat 만 남는다.
   에셋에 그림자가 없어 알파 모양을 따르는 drop-shadow 를 준다. */
.scr-quick_exit .qe-scrim::after{content:'';position:absolute;
  left:85.18%;top:24.39%;width:15.91%;aspect-ratio:146/141;
  background:url("../IMAGE/b/bubble_heart.png") no-repeat center/contain;
  filter:drop-shadow(0 clamp(2px,.45cqw,7px) clamp(4px,.85cqw,13px) rgba(6,18,52,.32));
  animation:bBubbleFloat 2.4s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){
  .scr-quick_exit .qe-scrim,
  .scr-quick_exit .qe-scrim::after{animation:none}
}







.scr-quick_exit .quickexit::before,
.scr-post_skill_pick .quickexit::before{content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    url("../IMAGE/b/wave_front.svg") repeat-x left bottom / 106.912% 31.25%,
    url("../IMAGE/b/wave_mid.svg")   repeat-x left bottom / 100% 31.25%,
    url("../IMAGE/b/wave_back.svg")  repeat-x left bottom / 100% 31.25%,
    /* 하트 말풍선은 이 에셋 안에 합쳐져 있던 것을 떼어냈다(아래 .qe-scrim) — 여기서는
       말풍선을 지운 판을 쓴다. 말풍선만 따로 띄워야 그림자·둥둥을 줄 수 있다. */
    var(--b-qe-lio, url("../IMAGE/b/lio_intro_fp2_nobubble.png")) no-repeat left 9.1% bottom 44% / auto 64%,
    var(--b-qe-shadow, radial-gradient(ellipse 20% 5% at 23.5% 56%,
      rgba(6,18,52,.42) 0%, rgba(6,18,52,.22) 38%, transparent 72%)),
    var(--b-qe-bg,#1C4BD6)}
/* slide 49 (최종 종료 · 추가 학습 선택) : LIO 를 엄지 든 스프라이트로.
   IMAGE/b/lio_end_thumbs.webp — end_sprite1(4×4, 412×548) 의 1-2 · 1-1 · 2-1 · 1-4 · 1-3 (5프레임).
   이 시트는 16프레임 전부 발밑 526 고정이고, 이 5장은 갈기 좌단 30~31 · 머리폭 215~216 ·
   스카프 중심 183.5~184.5 로 완전히 고정이라 정규화 없이 원본 그대로 쓴다.
   2-2 부터는 머리폭이 198 로 꺾여(고개를 돌린다) 넣으면 튄다.
   프레임차가 25~47 로 큰 것은 1-1 · 1-2 의 반짝임(✨)과 갈기 디테일 때문이고 기하는
   고정이므로 떨림이 아니다 — 순서는 전체 조합을 다 계산해 차이 합이 최소인 것으로 잡았다.
   구조는 slide 46 과 동일 : 파란 배경을 .quickexit 로 내리고 ::before 는 물결만,
   접지 그림자는 끈다. 호스트는 B 에서 안 쓰는 .qe-scrim.
   크기 기준은 slide 5 : 사자 머리-발 485.5px. 가로는 스카프 중심을, 세로는 발밑을
   기존 lio5.png 렌더(발밑 644.7 · 스카프중심 238.5)에 맞췄다. */
.scr-post_skill_pick .quickexit{--b-qe-lio:none;--b-qe-shadow:none;--b-qe-bg:transparent;
  background-color:#1C4BD6}
.scr-post_skill_pick .qe-scrim{display:block;inset:auto;
  left:5.57%;bottom:13.44%;width:34.82%;aspect-ratio:412/548;
  z-index:0;pointer-events:none;
  background:url("../IMAGE/b/lio_end_thumbs.webp") no-repeat 0% 0 / 500% 100%;
  animation:bLioThumbs .60s steps(5,jump-none) infinite alternate}
@keyframes bLioThumbs{from{background-position:0% 0} to{background-position:100% 0}}
@media (prefers-reduced-motion:reduce){
  .scr-post_skill_pick .qe-scrim{animation:none}
}
/* slide 46 : LIO 를 환호 스프라이트로. 발이 물결에 조금 가려지는 구성을 유지하려면
   사자가 "파란 배경 위 · 물결 아래" 여야 하는데 둘 다 ::before 안에 있으므로
   파란 배경만 .quickexit 로 내리고 ::before 는 물결만 남긴다 (slide 6·9·35 와 동일).
   그림자도 끈다 — 사자가 요소로 빠지면 ::before 가 위로 와서 몸통에 얼룩으로 보인다. */
.scr-quick_exit .quickexit{--b-qe-lio:none;--b-qe-shadow:none;--b-qe-bg:transparent;
  background-color:#1C4BD6}
.scr-quick_exit .quickexit::after,
.scr-post_skill_pick .quickexit::after{content:'';position:absolute;inset:0;z-index:4;pointer-events:none;
  background:url("../IMAGE/b/logo_lockup.png") no-repeat left clamp(10px,2.283cqw,36px) top clamp(7px,1.268cqw,20px) / auto clamp(26px,3.54cqw,56px)}
/* 말풍선 제거 → 우측 흰 본문 (introseq 와 동일) */
.scr-quick_exit .quickexit .ib-layer,
.scr-post_skill_pick .quickexit .ib-layer{
  left:46.9%;right:8.6%;top:28%;bottom:34%;
  display:flex;flex-direction:column;justify-content:flex-start;gap:.45em;z-index:3}
.scr-quick_exit .quickexit .ib,
.scr-post_skill_pick .quickexit .ib{
  position:static !important;left:auto !important;right:auto !important;
  top:auto !important;bottom:auto !important;max-width:100%;transform:none}
.scr-quick_exit .quickexit .ib-bubble,
.scr-post_skill_pick .quickexit .ib-bubble{
  background:transparent;box-shadow:none;color:#fff;padding:0;max-width:none}
.scr-quick_exit .quickexit .ib-bubble::after,
.scr-post_skill_pick .quickexit .ib-bubble::after{display:none}
/* slide 46·49 : 우측 텍스트 그리드에 CTA 정렬 (49와 동일 pill 스타일) */
.scr-quick_exit .qe-cards,
.scr-post_skill_pick .qe-actions{
  z-index:5;left:46.9%;right:8.6%;width:auto;max-width:none;
  transform:none;justify-content:flex-start;
  display:flex;gap:clamp(10px,1.4cqw,16px);
  bottom:clamp(72px,14cqw,160px)}
.scr-quick_exit .quickexit .ib-layer,
.scr-post_skill_pick .quickexit .ib-layer{bottom:28%}
/* slide 46 cards → 49 CTA pill (영어 2줄 허용) */
.scr-quick_exit .qe-card{
  flex:1 1 0;border:none;border-radius:999px;cursor:pointer;
  min-height:clamp(64px,8.5cqw,112px);height:auto;
  padding:clamp(10px,1.2cqw,16px) calc(var(--cta-chev) + clamp(10px,1.2cqw,18px)) clamp(10px,1.2cqw,16px) clamp(12px,1.4cqw,20px);
  box-sizing:border-box;display:flex;align-items:center;justify-content:center;
  background-size:var(--cta-chev) var(--cta-chev);
  box-shadow:0 10px 26px rgba(6,26,84,.24);
  transition:box-shadow .18s}
.scr-quick_exit .qe-card .qe-sub{display:none}
.scr-quick_exit .qe-card .qe-title{
  font-family:var(--font-head);font-weight:800;font-size:clamp(14px,1.9cqw,28px);
  letter-spacing:-.2px;line-height:1.2;text-align:center;white-space:normal}
/* plain(정답 바로 확인) — Finish 톤 남색 */
.scr-quick_exit .qe-card.plain{
  color:#fff;
  background:#02195C url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Ccircle cx='30' cy='30' r='30' fill='white'/%3E%3Cpath d='M25.5 19.5L36 30L25.5 40.5' stroke='%2302195C' stroke-width='5.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right clamp(8px,1cqw,13px) center;
  background-size:var(--cta-chev) var(--cta-chev)}
.scr-quick_exit .qe-card.plain .qe-title{color:#fff}
/* primary(왜 틀렸는지) — Let's Go 톤 흰 */
.scr-quick_exit .qe-card.primary{
  color:var(--primary);
  background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Ccircle cx='30' cy='30' r='30' fill='%23155DFC'/%3E%3Cpath d='M25.5 19.5L36 30L25.5 40.5' stroke='white' stroke-width='5.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right clamp(8px,1cqw,13px) center;
  background-size:var(--cta-chev) var(--cta-chev);
  box-shadow:0 10px 26px rgba(6,26,84,.24)}
.scr-quick_exit .qe-card.primary .qe-title{color:var(--primary)}
.scr-quick_exit .qe-card:hover{animation:bChevNudge .9s ease-in-out infinite;
  box-shadow:0 14px 32px rgba(6,26,84,.32);transform:none}
@media (prefers-reduced-motion:reduce){
  .scr-quick_exit .qe-card:hover{animation:none}
}
/* slide 49 CTA : Another skill = Let's Go(흰 pill+파란 원), Finish = 남색 pill+흰 원 */
.scr-post_skill_pick .qe-imgbtn img{display:none}
.scr-post_skill_pick .qe-imgbtn{
  width:auto;flex:1 1 0;height:clamp(48px,6.3cqw,100px);
  min-height:0;min-width:0;border:none;cursor:pointer;
  padding:0 calc(var(--cta-chev) + clamp(8px,1cqw,13px)) 0 clamp(8px,1cqw,13px);
  box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;
  border-radius:999px;font-size:0;line-height:1;text-align:center;
  background-size:var(--cta-chev) var(--cta-chev);
  box-shadow:0 10px 26px rgba(6,26,84,.24);
  transition:box-shadow .18s}
.scr-post_skill_pick .qe-imgbtn::before{
  font-family:var(--font-head);font-weight:800;font-size:var(--fz-cta);
  letter-spacing:-.2px;line-height:1.2;white-space:nowrap}
/* Another skill — Let's Go 톤 */
.scr-post_skill_pick .qe-imgbtn:first-child{
  color:var(--primary);
  background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Ccircle cx='30' cy='30' r='30' fill='%23155DFC'/%3E%3Cpath d='M25.5 19.5L36 30L25.5 40.5' stroke='white' stroke-width='5.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right clamp(8px,1cqw,13px) center;
  background-size:var(--cta-chev) var(--cta-chev)}
.scr-post_skill_pick .qe-imgbtn:first-child::before{content:"Another skill";color:var(--primary)}
/* Finish — 짙은 남색 pill + 흰 원 + 남색 셰브론 */
.scr-post_skill_pick .qe-imgbtn:last-child{
  color:#fff;
  background:#02195C url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Ccircle cx='30' cy='30' r='30' fill='white'/%3E%3Cpath d='M25.5 19.5L36 30L25.5 40.5' stroke='%2302195C' stroke-width='5.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right clamp(8px,1cqw,13px) center;
  background-size:var(--cta-chev) var(--cta-chev)}
.scr-post_skill_pick .qe-imgbtn:last-child::before{content:"Finish";color:#fff}
.scr-post_skill_pick .qe-imgbtn:hover{animation:bChevNudge .9s ease-in-out infinite;
  box-shadow:0 14px 32px rgba(6,26,84,.32)}
@media (prefers-reduced-motion:reduce){
  .scr-post_skill_pick .qe-imgbtn:hover{animation:none}
}

/* ── skill 화면 : Figma B_Skill_list (114:1066) · B_Skill_selected (114:1230) ──
   배경 네이비 #02195C + 동심원(#1C4BD6 / #335DDA / #0F2564) + 최하단 물결 #2B5CE6.
   카드는 스킬별 solid 컬러 + 흰 점선 인셋 보더 + 흰 볼드 라벨. */
/* ⚠ .skill-mascot / .think-bubble / .skill-headline 은 마크업상 .skill-left 안에 있다.
   .skill-left 가 position:relative 라 절대배치 기준이 좁은 왼쪽 열(≈290px)이었고,
   그래서 헤드라인 width:46% 가 133px 밖에 안 되어 4줄로 접혔다.
   → .skill-left 를 static 으로 두어 기준을 .skillscreen(화면 전체)로 올린다. */
.skillscreen .skill-left{position:static}
/* 배경 원 파장 : Figma #component > light (247:1828) 원본(481×481 정사각).
   커질 때 옅어지고 작아질 때 진해지도록 크기와 투명도를 함께 움직여
   음파가 퍼져 사라지는 느낌을 준다. 카드 사이 5개 지점을 돌아다닌다. */
.skillscreen{position:relative;background:#02195C}
.skillscreen::before{content:'';position:absolute;z-index:0;pointer-events:none;
  width:34cqw;height:34cqw;left:30%;top:14%;transform:translate(-50%,-50%);
  background:url("../IMAGE/b/sonar.svg") no-repeat center / 100% 100%;
  animation:bSonar 15s ease-in-out infinite}
@keyframes bSonar{
  0%   {left:30%; top:14%; width:30cqw; height:30cqw; opacity:.95}
  20%  {left:64%; top:22%; width:46cqw; height:46cqw; opacity:.35}
  40%  {left:86%; top:56%; width:30cqw; height:30cqw; opacity:.95}
  60%  {left:56%; top:76%; width:46cqw; height:46cqw; opacity:.35}
  80%  {left:38%; top:44%; width:30cqw; height:30cqw; opacity:.95}
  100% {left:30%; top:14%; width:46cqw; height:46cqw; opacity:.35}
}
@media (prefers-reduced-motion:reduce){ .skillscreen::before{animation:none} }
/* Figma B_Skill_list 에는 헤더 바가 없다 (114:1066 은 light/skill_list/lio/wav/BI 만
   가지고 있고 AppBar 노드가 없음). 헤더를 숨기고 네이비 배경을 화면 위까지 이어지게 한 뒤
   좌상단에 BI 로고만 올린다. Figma 좌표 : BI (36,20) 78×55.83 → 높이 55.83/1577≈3.54cqw */
.layout-skill .hd{display:none}
/* 로고는 아래 ::after 에 물결과 함께 얹고, ::before 는 파장 전용으로 쓴다
   (배경 레이어는 개별 opacity 를 줄 수 없어, 투명도까지 애니메이션하려면
    전용 요소가 필요하다). */
/* 로고와 콘텐츠가 겹치지 않게 상단 여백 확보 (헤더가 없어진 만큼 높이는 오히려 넉넉해진다) */
.skillscreen{padding-top:clamp(46px,5.6cqw,88px)}
.skillscreen::after{content:'';position:absolute;inset:0;pointer-events:none;z-index:2;
  background:
    url("../IMAGE/b/logo_lockup.png") no-repeat left clamp(10px,2.283cqw,36px) top clamp(7px,1.268cqw,20px) / auto clamp(26px,3.54cqw,56px),
    url("../IMAGE/b/wave_skill.svg") no-repeat left bottom / 100% 4.8%}
/* 파도만 스킬카드(z1)·레인 transform 위로 — 로고는 skillscreen::after 유지 */
.layout-skill .skillscreen::after{
  background:url("../IMAGE/b/logo_lockup.png") no-repeat left clamp(10px,2.283cqw,36px) top clamp(7px,1.268cqw,20px) / auto clamp(26px,3.54cqw,56px)}
.layout-skill .skill-grid{position:relative;z-index:1}
.layout-skill .screen::after{content:'';position:absolute;left:0;right:0;bottom:0;
  height:4.8%;z-index:10;pointer-events:none;
  background:url("../IMAGE/b/wave_skill.svg") no-repeat left bottom / 100% 100%}
/* 헤드라인 : Figma 실측 (542,424) 373×104 → x 34.4~58.0% · y 39.6~49.3%.
   마스코트 오른쪽·카드 영역에 겹쳐 놓이는 구성이라 절대 배치하고 위로 올린다. */
.skill-headline{color:#fff;font-family:var(--font-head);font-weight:800;font-size:var(--fz-headline)}
/* ⚠ Figma 의 x34.4% 는 마스코트가 프레임 왼쪽(-1.5%~38.7%)에 있을 때 그 오른쪽 여백에
   해당한다. 프로토는 마스코트를 slide 5·6 과 같은 크기(64%)로 키워 오른쪽 끝이
   더 나오므로, 그대로 두면 얼굴 위에 글자가 얹힌다.
   → 마스코트 오른쪽 경계 밖으로 내보내고 세로 위치는 Figma 대로 둔다.
   말풍선(마스코트 이미지에 포함)도 가리지 않는다. */
/* 헤드라인은 LIO 위(좌상단 로고 아래)에 놓는다 */
/* 마크업은 "Let's find<br>your skill!" 이라 원래 2줄이다.
   폭이 좁아 4줄로 접혔던 것 → 폭을 넓히고 줄바꿈을 막아 정확히 2줄로 둔다. */
.skillscreen:not(.selected) .skill-headline{position:absolute;left:calc(3% + 40px);top:calc(8% + 20px);
  width:45%;max-width:45%;text-align:left;z-index:6;line-height:1.02;
  font-size:clamp(24px,3.6cqw,52px);
  text-shadow:0 3px 14px rgba(2,25,92,.65)}
.skillscreen:not(.selected) .skill-headline br{display:block}
.skillscreen:not(.selected) .skill-headline-l2{display:inline-block;margin-left:50px}
/* 카드 : flow-data 의 --sc 는 A 팔레트이므로 B 전용 --scB 로 덮는다 */
.skill-card{background:var(--scB,#3593FF);border:none;border-radius:20px;position:relative;z-index:1;cursor:pointer}
.skill-card::after{content:'';position:absolute;inset:7px;pointer-events:none;
  border:2px dashed rgba(255,255,255,.92);border-radius:13px}
.skill-card .sc-name{color:#fff;font-family:var(--font-head);font-weight:800;
  font-size:clamp(12px,1.72cqw,26px);line-height:1.12;overflow:hidden;
  text-align:center;padding:0 6%}
.skill-card.today,
.skill-card.pickable.on,
.skill-card.pickable.today{background:var(--scB,#3593FF);border-color:transparent;
  box-shadow:0 12px 28px rgba(0,0,0,.35)}
/* 배치 : Figma 는 masonry 가 아니라 4열 균일 그리드에 빈 칸을 둔 구성이다.
   실측 — 카드 0.152W × 0.298H(3:4), 열 피치 0.1675, 행 피치 0.321.
   Figma 는 프레임 밖으로 카드가 잘려 나가지만, 프로토는 10장이 모두 보이고
   클릭돼야 하므로 같은 4열 흩뿌림 배열을 화면 안에 담는다. */
/* 암시적 행이 auto 라 .skill-grid 의 height:100% 가 안 잡힌다 → 행을 minmax(0,1fr) 로 고정 */
.skillscreen{grid-template-columns:0.42fr 1fr;grid-auto-rows:minmax(0,1fr)}
/* 4행이 화면 안에 다 들어가야 하므로 행을 1fr 로 쪼개고 카드는 행 높이에 맞춘다
   (Figma 는 카드가 프레임 밖으로 잘리지만, 프로토는 10장 전부 보이고 클릭돼야 한다) */
/* 행 높이를 1fr/% 로 두면 .layout-skill .screen 이 display:block 이라 미정으로 남아
   카드가 아래로 넘친다. 디바이스 비율(1577/1072)이 고정이므로 cqw 로 못박는다.
   화면 높이 ≈ 68cqw, 헤더·패딩 제외 ≈ 58cqw → 4행 × 13.4cqw */
/* 카드 1.2배 : 13.4cqw → 16.08cqw.
   상단 padding 은 좌측(마스코트·헤드라인) 열이 로고를 피하려고 준 것이고
   그리드는 우측 열이라 로고와 겹치지 않는다 → 음수 마진으로 그 높이를 되돌려
   4행이 최대한 화면 안에 들어오게 한다. 그래도 남으면 Figma 처럼 위아래로 살짝
   잘리며 중앙 정렬된다(카드는 잘린 상태에서도 클릭 가능). */
.skill-grid{grid-template-columns:repeat(4,1fr);grid-template-rows:repeat(4,16.08cqw);
  gap:2.2cqw 1.2cqw;
  margin-top:calc(-1 * clamp(46px,5.6cqw,88px));
  height:calc(100% + clamp(46px,5.6cqw,88px));
  min-height:0;align-content:center;
  justify-items:center;align-items:center;overflow:visible}
.skill-card{height:100%;width:auto;max-width:100%;aspect-ratio:213/284;
  padding:8% 6% 6%;justify-content:center;gap:5%;overflow:hidden}
.skill-card .sc-icon{width:auto;height:46%;flex:0 0 auto}
/* 마스코트 : slide 5·6 과 같은 크기(높이 64%)로 키운다. Figma skill_list 의 lio 는
   (-23,259) 633×673 → 좌측 -1.5% / 아래 13.1% / 높이 62.8% 위치다.
   카드 위에 겹쳐도 무방하다는 요청에 따라 z-index 를 카드보다 위로 둔다. */
/* LIO 는 z-index:5 로 카드보다 위에 있지만, 폭이 245px 이고 left 9% 라
   오른쪽 끝(496px)이 그리드 시작(509px)에 13px 못 미쳐 실제로는 겹치지 않았다.
   → left 를 더 밀어 카드 첫 열과 확실히 겹치게 한다. */
/* LIO 폭은 높이에 비례(높이 64%일 때 약 24.7%)한다. 화면 왼쪽 끝에 두면서 카드와
   겹치려면 폭이 51% 이상이어야 해 불가능하므로, 카드 첫 열에 살짝 걸치는 위치로 둔다.
   (74%/left25% 는 첫·둘째 열을 다 덮어 카드가 가려졌다) */
/* 카드 첫 열(Main Ideas 등)에 몸만 살짝 걸치도록. left 음수는 왼쪽이 잘림 */
/* slide 7 LIO — 스킬을 찾는 동안 턱을 짚고 눈을 굴리는 스프라이트.
   IMAGE/b/skill_think.webp — skill_sprite1(4×4, 390×596) 16프레임 전부, 리샘플 없음.
   16프레임이 발밑 592 · 발중심 232 로 완전히 같고 머리 편차도 2%(머리폭 272~278 ·
   코 x 134~139) 라 그대로 쓸 수 있다. 루프 이음새(16→1)만 머리 차이 17.4 로 튀므로
   alternate 로 왕복시켜 되돌아오는 지점을 없앤다.
   프레임 390×596 은 원래 쓰던 lio2.png(387×598)와 사실상 같은 프레이밍이라 위치·크기가
   그대로 맞는다 — 사자 머리-발이 589/596 이라 높이만 66% → 66.45% 로 보정하면
   기존과 같은 504.3px 이 된다.
   마크업이 공용 engine.js 의 <img src=lio2.png> 라 CSS 로는 src 를 못 바꾼다.
   content 로 1×1 투명 GIF 를 넣어 원본 비트맵만 지우고 배경에 시트를 깐다.
   (content 를 바꾸면 고유 비율이 1:1 이 되므로 aspect-ratio 를 직접 줘야 한다) */
.skillscreen .skill-mascot{position:absolute;left:10%;bottom:9%;
  height:66.45%;width:auto;aspect-ratio:390/596;max-width:none;max-height:none;
  z-index:5;pointer-events:none;
  content:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
  background:url("../IMAGE/b/skill_think.webp") no-repeat 0% 0 / 1600% 100%;
  animation:bSkillThink 2.4s steps(16,jump-none) infinite alternate}
@keyframes bSkillThink{from{background-position:0% 0} to{background-position:100% 0}}
.skill-card[data-skill="0"]{grid-area:1/1}   /* Main Ideas */
.skill-card[data-skill="1"]{grid-area:1/3}   /* Facts: WH Question */
.skill-card[data-skill="2"]{grid-area:1/4}   /* Facts: True or Not True */
.skill-card[data-skill="3"]{grid-area:2/3}   /* Facts: Sentence Completion */
.skill-card[data-skill="4"]{grid-area:3/2}   /* Conclusions */
.skill-card[data-skill="5"]{grid-area:3/1}   /* Inferences */
.skill-card[data-skill="6"]{grid-area:3/3}   /* Cause & Effect */
.skill-card[data-skill="7"]{grid-area:3/4}   /* Characters */
.skill-card[data-skill="8"]{grid-area:4/1}   /* Author's Purpose */
.skill-card[data-skill="9"]{grid-area:4/4}   /* Literary Genres */

/* Figma Skill_list 카드 색 (SKILLS 배열 순서 = data-skill 인덱스) */
.skill-card[data-skill="0"]{--scB:#3593FF}   /* Main Ideas */
.skill-card[data-skill="1"]{--scB:#00BE5F}   /* Facts: WH Question */
.skill-card[data-skill="2"]{--scB:#FF9C7E}   /* Facts: True or Not True */
.skill-card[data-skill="3"]{--scB:#FFC72F}   /* Facts: Sentence Completion */
.skill-card[data-skill="4"]{--scB:#F46169}   /* Conclusions */
.skill-card[data-skill="5"]{--scB:#B078FF}   /* Inferences */
.skill-card[data-skill="6"]{--scB:#748CFF}   /* Cause & Effect */
.skill-card[data-skill="7"]{--scB:#FF974C}   /* Characters */
.skill-card[data-skill="8"]{--scB:#FF7CCF}   /* Author's Purpose */
.skill-card[data-skill="9"]{--scB:#4FC73F}   /* Literary Genres */

/* ── Skill_selected : Figma B_Skill_selected (114:1230) ──
   ⚠ 이 상태의 마크업은 engine.js 가 `skillscreen a-skill selected` 로 하드코딩해
     Design A 전용이고, flow-data 에도 대응 화면이 없어 B 에서는 도달하지 않는다
     (도달시키려면 공용 engine.js 수정 필요 → A 영향 때문에 하지 않음).
     그래도 렌더될 경우 Figma 대로 보이도록 a-skill 없는 선택자로 스타일만 준비해 둔다. */
.skillscreen.selected,
.skillscreen.found{background:#02195C}
/* 선택 시 배경 소나 원·뒤 카드 점선이 큰 카드 가장자리에서 하얀 원처럼 보임 → 숨김 */
.skillscreen.selected::before,
.skillscreen.found::before{content:none !important;display:none !important;animation:none !important;background:none !important}
.skillscreen.selected .think-bubble,
.skillscreen.found .think-bubble{display:none !important}
.skillscreen.selected .skill-grid .skill-card::after,
.skillscreen.found .skill-grid .skill-card::after{display:none !important}
.skillscreen.selected .skill-grid.dim,
.skillscreen.found .skill-grid.dim{opacity:.5;filter:blur(7px);pointer-events:none}
.skillscreen.selected .skill-mascot,
.skillscreen.found .skill-mascot{display:none}
.skillscreen.selected .skillsel-halo,
.skillscreen.found .skillsel-halo{display:none}          /* Figma B 는 후광 없음 */
/* Figma B_Skill_selected 실측 :
   대형 카드 폭 32.9% / 비율 519:638 · y 19.5~79.0%
   원래 배치는 [헤드라인·버튼]왼쪽 – LIO – 카드 였는데, 요청대로 헤드라인과 Let's Go 를
   LIO·카드의 '오른쪽' 으로 옮겼다. 오른쪽에 남은 자리가 13.7% 뿐이라 LIO 와 카드를
   함께 18.3% 왼쪽으로 밀어 자리를 만들었다 — 사자가 카드를 가리키는 겹침은 그대로다.
     LIO 박스 23.5→5.2% · 카드 중심 69.85→51.55% · 텍스트 left 71% */
.skillscreen.selected .skillsel-card,
.skillscreen.found .skillsel-card{position:absolute;left:51.55%;top:49.25%;
  transform:translate(-50%,-50%);z-index:3;pointer-events:none;
  width:32.9%;aspect-ratio:519/638;border-radius:26px;background:var(--scB,#3593FF);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2%;
  box-shadow:0 18px 40px rgba(0,0,0,.4);overflow:hidden}
.skillscreen.selected .skillsel-card::after,
.skillscreen.found .skillsel-card::after{content:'';position:absolute;inset:10px;
  border:2px dashed rgba(255,255,255,.92);border-radius:14px;pointer-events:none}
.skillscreen.selected .skillsel-card img,
.skillscreen.found .skillsel-card img{width:62%;height:auto;position:relative;z-index:1}
.skillscreen.selected .skillsel-card .sc-name,
.skillscreen.found .skillsel-card .sc-name{position:relative;z-index:1;color:#fff;
  font-family:var(--font-head);font-weight:800;font-size:clamp(28px,3.6cqw,56px);
  text-align:center;padding:0 6%;line-height:1.1}
/* 선택 완료 LIO — 검지를 들고 "찾았다" 하는 스프라이트.
   IMAGE/b/skill_found.webp — skill_sprite2(4×4, 468×562) 2-2 ~ 4-4 의 11프레임.
   오른쪽(선택된 카드)을 가리키는 동작이다. 16프레임 전부를 쓰면 2-1→2-2 에서 코 x 가
   한 번에 23.9px 튀어(183.0→159.1) 고개가 딸꾹질한다 — 그 앞만 잘라내면 2-2 부터는
   코 x 가 159.1→149.1→149.3→153.6→164.4→…→169.8 로 프레임당 최대 10.8px 씩
   매끄럽게 이어진다. 몸높이도 523~535(2.3%) 로 안정. alternate 로 왕복.
   사자 머리-발이 534/562 라 height 69.07% 로 올려 기존 lio6.png 와 같은 504px 로 맞춘다.
   src 교체가 안 되는 것은 .skill-mascot 과 같은 사정 — content 로 비트맵을 지운다. */
.skillscreen.selected .skillsel-mascot,
.skillscreen.found .skillsel-mascot{position:absolute;left:5.2%;top:49.25%;bottom:auto;
  /* 사자 머리-발 504px — 같은 slide 7 의 탐색 상태(.skill-mascot)와 같은 크기.
     기존 정지 에셋의 머리에 맞춰 74.48% 로 키웠던 것을 되돌렸다. */
  height:69.07%;width:auto;aspect-ratio:468/562;z-index:4;pointer-events:none;
  transform:translateY(-50%);
  content:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
  background:url("../IMAGE/b/skill_found.webp") no-repeat 0% 0 / 1100% 100%;
  animation:bSkillFound 1.10s steps(11,jump-none) infinite alternate}
@keyframes bSkillFound{from{background-position:0% 0} to{background-position:100% 0}}
@media (prefers-reduced-motion:reduce){
  .skillscreen .skill-mascot,
  .skillscreen.selected .skillsel-mascot,
  .skillscreen.found .skillsel-mascot{animation:none}
}
/* 헤드라인은 카드 오른쪽에 놓는다 (원래는 마스코트 왼쪽이었다) */
/* Figma 114:1305 "I found\n  your skill!" — 2줄, 둘째 줄 들여쓰기 */
.skillscreen.selected .skill-headline,
.skillscreen.found .skill-headline{position:absolute;left:71%;top:46.5%;
  max-width:26%;text-align:left;z-index:6;line-height:1.15}
.skillscreen.selected .skill-headline-l2,
.skillscreen.found .skill-headline-l2{display:inline-block;margin-left:1.2em}

/* Let's Go : Figma Button_go (258:1860) — 흰 pill + 파란 셰브론.
   크기는 프레임 대비 340×120 → w 21.6% · h 9.3% 그대로, 위치만 헤드라인과 같은
   오른쪽(left 71%)으로 옮겼다. */
.skillfound-overlay{position:absolute;inset:0;z-index:5;pointer-events:none}
.skillscreen.selected .skillsel-go,
.skillscreen.found .skillsel-go{
  position:absolute;left:71%;bottom:21.1%;z-index:7;pointer-events:auto;cursor:pointer;
  width:21.6%;height:9.3%;min-height:0;
  padding:0 calc(var(--cta-chev) + clamp(8px,1cqw,13px)) 0 clamp(8px,1cqw,13px);
  box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;border:none;
  border-radius:999px;font-size:0;color:var(--primary);text-align:center;
  background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Ccircle cx='30' cy='30' r='30' fill='%23155DFC'/%3E%3Cpath d='M25.5 19.5L36 30L25.5 40.5' stroke='white' stroke-width='5.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right clamp(8px,1cqw,13px) center;
  background-size:var(--cta-chev) var(--cta-chev);
  box-shadow:0 10px 26px rgba(6,26,84,.24);
  transition:box-shadow .18s}
.skillscreen.selected .skillsel-go::before,
.skillscreen.found .skillsel-go::before{content:"Let's Go!";
  font-family:var(--font-head);font-weight:800;font-size:var(--fz-cta);letter-spacing:-.2px}

/* ── game 화면 : Figma B_Game — 썸네일 풀블리드, 헤더·오버레이 없음 ── */
.scr-game .hd{display:none}
.gamescreen.b-game{
  position:absolute;inset:0;display:block;overflow:hidden;cursor:pointer;
  background:#0a3d6e;margin:0;padding:0;border:none;width:100%;height:100%}
.gamescreen.b-game::before{display:none}
.gamescreen.b-game .game-illust{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center;pointer-events:none;display:block}

/* (레거시 스plit 레이아웃용 — B 풀블리드에서는 미사용) */
.gamescreen{background:url("../IMAGE/b/game_bg.jpg") no-repeat center center / cover;
  position:relative}
.gamescreen::before{content:'';position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(2,25,92,.30),rgba(2,25,92,.55));pointer-events:none}
.gamescreen > *{position:relative;z-index:1}
.gamescreen .game-board{background:rgba(2,25,92,.80);border-radius:18px;margin:2.2%;
  padding:3% 3.4%;box-shadow:0 14px 34px rgba(0,0,0,.32)}
.gamescreen .game-board .game-title{color:#fff}
.gamescreen .game-board .game-round,
.gamescreen .game-board .game-hint{color:#c8d6ff}
.gamescreen .game-board .pcell{border-color:rgba(255,255,255,.35)}
.gamescreen .game-transition{background:transparent}
.gamescreen .game-transition .msgcard{background:#fff;border-color:#fff;
  box-shadow:0 14px 34px rgba(0,0,0,.28)}

/* ── topic 화면 : Figma B_Topic_list ──
   마스코트가 상단 중앙 → 헤드라인 → 카드 1×6 → 카드 밖 라벨 + 넓은 체크 pill */
.topic-lio{flex-direction:column;gap:clamp(4px,.6cqw,8px);text-align:center;max-width:min(96%,1200px)}
/* Figma lio_face 1: 120×132 — 원형 크롭/1:1 강제 해제.
   턱 괸 얼굴을 애니메이션으로 : IMAGE/b/lio_think_face.webp
   — lio_sprite2(4×4, 510×518) 16프레임 전부. 눈이 좌우로 움직이고 눈을 깜빡인다.
   폭 436~445(2.0%) · 높이 494~503(1.8%) 로 크기는 고정인데 bbox 중심 x 가 24px 흔들려
   프레임마다 중심을 맞춰 457×515 박스로 재배치했다(중심 정렬 후 인접 차이 평균 11.9).
   마크업이 공용 engine.js 의 <img src=lio_face.png> 라 CSS 로 src 를 못 바꾼다 →
   content 로 1×1 투명 GIF 를 넣어 원본 비트맵만 지우고 배경에 시트를 깐다.
   (content 를 바꾸면 고유 비율이 1:1 이 되므로 aspect-ratio 를 직접 준다)
   얼굴이 박스에서 차지하는 비율이 기존 에셋(0.995)보다 작으므로(0.969) 높이를 1.027배
   올려 화면상 얼굴 크기를 그대로 유지한다. */
.topic-lio img{
  width:auto;height:clamp(49px,8.60cqw,136px);
  aspect-ratio:457/515;border-radius:0;object-fit:contain;background:transparent;
  content:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
  background:url("../IMAGE/b/lio_think_face.webp") no-repeat 0% 0 / 1600% 100%;
  animation:bLioThink 1.9s steps(16,jump-none) infinite alternate}
@keyframes bLioThink{from{background-position:0% 0} to{background-position:100% 0}}
/* 자유대화 화면의 떠다니는 LIO 도 같은 에셋(lio_face.png)이라 함께 애니메이션.
   위치는 engine.js 가 left/top 으로 움직이므로 크기만 맞춘다(88px → 90px, 위와 같은 1.027배). */
.reading.freechat .floating-lio{
  width:auto;height:90px;aspect-ratio:457/515;object-fit:contain;
  content:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
  background:url("../IMAGE/b/lio_think_face.webp") no-repeat 0% 0 / 1600% 100%;
  animation:bLioThink 1.9s steps(16,jump-none) infinite alternate}
@media (prefers-reduced-motion:reduce){
  .topic-lio img,
  .reading.freechat .floating-lio{animation:none}
}
/* Figma 114:1488 — sub Medium 36 / main ExtraBold 60, leading 60, #1e2939 */
.topic-line{color:#1e2939;line-height:1;font-family:var(--font-head)}
.topic-line .tl-sub{
  display:block;font-size:var(--fz-topic-sub);font-weight:500;line-height:1.67}
.topic-line .tl-main{
  display:block;font-size:var(--fz-topic-main);font-weight:800;line-height:1}
.topic-line .nm{font-weight:inherit;color:inherit}
/* 카드가 고정 비율이므로 그리드가 남은 높이를 먹지 않게 flex:0 0 auto 로 되돌린다
   (base.css 는 flex:1 1 auto — 그대로 두면 위아래로 여백이 벌어진다) */
.topic-grid{grid-template-columns:repeat(6,1fr);grid-template-rows:auto;
  max-width:1180px;gap:clamp(6px,.9cqw,12px);
  flex:0 0 auto;margin-top:clamp(4px,1.2cqw,16px)}
/* 카드 배경·보더를 없애 이미지만 라운드로 떠 보이게 (Figma 는 라벨이 카드 밖) */
.topic-card{background:transparent;border-color:transparent;border-radius:20px;gap:6px;
  padding-bottom:0;height:auto}
/* Figma 카드 이미지 213×290 — 일러스트 + 세로 그라데이션 (B_Topic_list)
   1·6 #8EC5FF→#51A2FF / 2·4 #7BF1A8→#05DF72 / 3 #FDA5D5→#FB64B6 / 5 #FFB86A→#FF8904 */
.topic-card .tc-img{
  border-radius:20px;flex:0 0 auto;aspect-ratio:213/290;width:100%;
  background-color:var(--tc);
  background-image:var(--tc-img),linear-gradient(180deg,var(--tc-from),var(--tc-to));
  background-size:70%,auto;background-position:center,0 0;background-repeat:no-repeat;
  box-shadow:0 20px 25px -5px rgba(0,0,0,.10),0 8px 10px -6px rgba(0,0,0,.10)}
/* 카드별 광학 균형 — 기본 70%, 여백 많은 장은 키움 */
.topic-card:nth-child(2) .tc-img,
.topic-card:nth-child(3) .tc-img,
.topic-card:nth-child(4) .tc-img{background-size:80%,auto}
.topic-card:nth-child(1) .tc-img,
.topic-card:nth-child(6) .tc-img{background-size:88%,auto}
.topic-card:nth-child(5) .tc-img{background-size:98%,auto;background-position:58% center,0 0}
/* Figma 114:1496 — Nunito Black 24 / leading 32 / #1e2939 */
.topic-card .tc-name{
  font-family:var(--font-head);font-weight:900;
  font-size:clamp(14px,1.52cqw,24px);line-height:1.33;
  color:#1e2939;padding:clamp(4px,.8cqw,10px) 2px 0;overflow:visible;
  white-space:nowrap}
/* Figma Button 114:1497 — 73.5×44.6, off #D5D5D5+흰✓ / on #3262F0+노란✓ */
.topic-card .tc-check{
  width:clamp(44px,4.66cqw,74px);height:clamp(26px,2.83cqw,45px);
  border-radius:0;margin-bottom:clamp(2px,.4cqw,6px);
  background:url("../IMAGE/b/topic_check_off.svg") center / contain no-repeat;
  color:transparent;font-size:0;opacity:1}
.topic-card.on{border-color:transparent;box-shadow:none}
.topic-card.on .tc-img{box-shadow:0 8px 20px rgba(30,81,214,.28)}
.topic-card.on .tc-check{
  background:url("../IMAGE/b/topic_check_on.svg") center / contain no-repeat;
  color:transparent}

/* Continue : Let's Go 와 동일 구조, 색만 반전 (파란 pill + 흰 원 + 파란 셰브론)
   Figma Button_Continue 227:1814 — 340×120 / #155DFC */
.topicscreen .continue-btn,
.topicscreen .continue-btn.btn,
.topicscreen .continue-btn.btn.primary{
  width:clamp(180px,21.6cqw,340px);height:clamp(48px,6.3cqw,100px);
  min-height:0;margin-top:clamp(4px,1cqw,12px);
  padding:0 calc(var(--cta-chev) + clamp(8px,1cqw,13px)) 0 clamp(8px,1cqw,13px);
  box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;
  border:none;border-radius:999px;font-size:0;line-height:1;color:#fff;cursor:pointer;text-align:center;
  background:#155DFC url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Ccircle cx='30' cy='30' r='30' fill='white'/%3E%3Cpath d='M25.5 19.5L36 30L25.5 40.5' stroke='%23155DFC' stroke-width='5.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right clamp(8px,1cqw,13px) center;
  background-size:var(--cta-chev) var(--cta-chev);
  box-shadow:0 10px 26px rgba(6,26,84,.24);
  transition:box-shadow .18s, opacity .18s}
.topicscreen .continue-btn::before{content:"Continue";
  font-family:var(--font-head);font-weight:800;font-size:var(--fz-cta);letter-spacing:-.2px;color:#fff}
.topicscreen .continue-btn:disabled{opacity:.4;cursor:not-allowed;box-shadow:none}
.topicscreen .continue-btn:not(:disabled):hover{animation:bChevNudge .9s ease-in-out infinite;
  box-shadow:0 14px 32px rgba(6,26,84,.32)}
@media (prefers-reduced-motion:reduce){
  .topicscreen .continue-btn:not(:disabled):hover{animation:none}
}

/* ── word peek ── */
.wp-line{color:#22315e}

/* ── Teach / Game / Explore : base.css 기본값이 A(크림 #fffaf0 · 보더 #ecddc0)라
      파란 앱 UI 안에서 베이지로 떠 보인다 → B 팔레트로 교체 ── */
.mcard,
.mc-front,
.mc-front.word{background:#f2f5ff}
.mc-front{border-color:#d7e0fa;color:var(--b-text)}
.mc-front.word b{color:var(--b-text)}
.mc-back{background:var(--primary);color:#cfdcff;font-family:'Baloo 2','Nunito',sans-serif}
.det-card{background:#f2f5ff;border-color:#d7e0fa;color:var(--b-text)}
.det-clue-head{color:var(--b-navy)}
/* Detective 보드 판 : A는 크림 + 노란 점선 */
.det-board{background:#f8faff;border:1.5px dashed #cfdcfa}
.wp-front{background:#f2f5ff;border-color:#d7e0fa;color:var(--primary)}
.wp-front.alt,.wpcard.alt .wp-front{background:var(--b-mint);border-color:var(--b-mint-line);color:var(--b-mint-ink)}
/* Find & Flip 카드 앞면 : A는 크림 */
.ff-front{background:#f2f5ff;border-color:#d7e0fa}
.ff-front b{color:var(--b-text)}
/* Teach 단어카드 recap : A는 크림 + 갈색 텍스트 */
.td-recap{background:var(--b-mint);border:1px dashed var(--b-mint-line);color:#12655a}
.td-recap-ex{color:#2f7a6c}
/* Memory Hint : A는 주황, B는 액센트 옐로 + 진한 글자 */
.mem-hint{background:var(--accent);color:var(--b-navy)}
.mem-peek b{color:var(--accent)}
/* Quick Exit 상단 배너 : A는 크림 + 갈색 */
.qe-banner{background:#eaf0fd;border-color:#cfdcfa;color:#2c3f77}
.passage .xword:hover{background:#e6eefb}
.passage .xword.picked{background:#d7e0fa;border-bottom-color:var(--primary)}

/* ── quick exit ── */
.qe-card{border-radius:22px}

/* ── splash (진입 표지) : Figma B_Intro_cut1 (114:970) ──
   Figma : 플랫 #1C4BD6 + 동심원 + 손 든 마스코트(HI! 말풍선) + 대형 Lio SKILL CORE 락업
           + 흰 "Let's Go! ›" pill + 하단 3겹 물결.
   좌표는 cut1 렌더에서 실측한 화면 비율 : 마스코트 x6.6~41.9% y13.4~73.4%,
   로고 x59.6~82.2% y29.2~57.1%, 버튼 x60.1~81.6% y67.8~78.8%. */
.layout-splash .device{background:#1C4BD6}
/* 원형 파장은 아래 .splash-tap(링 호스트)으로 옮겼다 — 배경 그라디언트를 애니메이션하면
   매 프레임 화면 전체를 리페인트하지만 요소 + transform:scale 은 합성만으로 끝난다. */
.splash{background:#1C4BD6}
/* 기본 마크업의 작은 마스코트 + CSS 텍스트 로고 + "Tap to start" 는 감춘다
   (마크업·문구는 공용 engine.js 소관이라 손대지 않고 CSS 로만 대체) */
/* slide 5 LIO — 걸어들어와 정면을 보고 손을 흔드는 인트로 스프라이트.
   .splash-inner 를 스프라이트 호스트로 쓰고 자식(작은 마스코트·텍스트 로고)은 감춘다.

   시트 두 장. 프레임 박스는 420×497 로 공통, 교체 시 튀지 않는다.
   · IMAGE/b/lio_intro_walk.webp — 22프레임, 1회성
       0 ~ 3   걷기   intro_sprite1 1행 (완전 측면 · 다리 교차) → 2바퀴 루프
       4 ~ 15  전환   intro_sprite1 2~4행 (걸으면서 측면 → 정면으로 돌아섬)
       16~21   팔올림 intro_sprite2 4행 (팔이 아래에서 위로)
   · IMAGE/b/lio_intro_wave.webp — 12프레임, 무한 루프
       intro_sprite2 5~6행. 앞발이 좌우로 40px 왕복한다.
       반드시 alternate — 원본이 5-1 → 6-6 으로 갈수록 머리가 5px 왼쪽·위로 서서히
       밀려서(코 x 124.1→119.3 · y 185.8→182.6), 6-6 에서 5-1 로 되돌면 그게 한 번에
       튀어 고개가 딱꾹질하듯 보인다(머리 영역 프레임차 16.7 — 다른 구간의 2배).
       왕복시키면 되돌아오는 지점이 없어지고 양 끝에서 한 프레임 머무는 게 오히려
       손 흔들 때의 자연스러운 정점 멈춤이 된다.

   두 원본 시트는 프레임 크기(406×594 / 426×562)도 사자 크기도 달라(is2 는 1행→5행에서
   11% 축소) 정규화가 필요한데, 프레임마다 따로 정렬하면 안 된다 — 기준점이 흔드는 앞발에
   끌려 몸이 좌우로 밀린다. 시트 안에서 이미 서로 정합된 프레임을 그룹으로 묶고(걷기·전환
   16장 = is1 전체 / 팔올림·인사 18장 = is2 4~6행) 그룹마다 대표 프레임 하나로 배율·발밑·
   발중심을 정해 그룹 전체에 똑같이 적용했다. 두 그룹의 대표는 이음새 프레임(is1 4-4 ↔
   is2 4-1)으로 잡아 시트가 바뀌는 순간에도 튀지 않는다. 덕분에 원본의 걷기 반동은 남고
   인사 중 발 위치는 원본대로 고정된다(편차 0px).
   485px 는 화면에 뜨는 크기(화면 높이 64% = 491px)와 같은 값이다. 더 줄이면 확대되면서
   흐려지므로 줄이지 않는다 — 렌더 배율 1.013배, 사실상 1:1.

   크기·위치는 기존 LIO 와 동일 : 몸높이 = 화면 높이 64%, 발밑 = 0.8416,
   몸통 중심 285.6px → width 37.76% · left 5.64% · bottom 15.11%.
   z-index:1 — 파장(.splash-tap, z0) 위 · 물결(.splash::before, z2) 아래.
   z 를 안 주면 파장과 같은 층이 되고 DOM 순서상 파장이 LIO 를 덮어 뿌옇게 보인다. */
.splash .splash-inner{display:block;position:absolute;pointer-events:none;
  left:5.64%;bottom:15.11%;width:37.76%;aspect-ratio:421/505;z-index:1;
  background:url("../IMAGE/b/lio_intro_walk.webp") no-repeat 0% 0 / 2200% 100%;
  /* 구간별로 애니메이션을 나눠 걸고 delay 로 이어받는다. 뒤 구간은 fill:forwards 만 줘서
     (backwards 금지) 자기 delay 전에는 앞 구간을 덮지 않는다.
     steps(k) 는 마지막 프레임을 건너뛰고 프레임 경계에 걸치므로 전부 jump-none. */
  animation:
    bLioWalkIn 2.10s cubic-bezier(.16,.62,.36,1)      both,      /* 화면 밖 → 제자리 */
    bLioWalk   0.60s steps(4,jump-none)         0s  2 both,      /* 0~1.20s   걷기 ×2 */
    bLioTurn   0.90s steps(12,jump-none)    1.20s forwards,      /* 1.20~2.10s 돌아섬 */
    bLioRaise  0.42s steps(6,jump-none)     2.10s forwards,      /* 2.10~2.52s 팔올림 */
    bLioSheet  2.52s                            0s forwards,     /* 2.52s 에 시트 교체 */
    bLioWave   0.90s steps(12,jump-none)    2.52s infinite alternate}  /* 2.52s~ 인사 왕복 */
.splash .splash-inner > *{display:none}
/* 인사 시트는 keyframe 안에서만 참조되므로 교체되는 2.52s 에야 요청된다 → 첫 실행 때
   사자가 한 프레임 사라진다. content:url 로 미리 받아둔다(0 크기 · 투명이라 안 보인다). */
.splash .splash-inner::before{content:url("../IMAGE/b/lio_intro_wave.webp");
  position:absolute;width:0;height:0;overflow:hidden;opacity:0}
@keyframes bLioWalkIn{from{transform:translateX(-118%)} to{transform:translateX(0)}}
@keyframes bLioWalk {from{background-position:0% 0}        to{background-position:14.2857% 0}}
@keyframes bLioTurn {from{background-position:19.0476% 0}  to{background-position:71.4286% 0}}
@keyframes bLioRaise{from{background-position:76.1905% 0}  to{background-position:100% 0}}
/* 마지막 순간에 인사 시트로 바꾸고 프레임 수(12장)에 맞게 size 도 함께 */
@keyframes bLioSheet{
  0%,99.9%{background-image:url("../IMAGE/b/lio_intro_walk.webp");background-size:2200% 100%}
  100%    {background-image:url("../IMAGE/b/lio_intro_wave.webp");background-size:1200% 100%}
}
@keyframes bLioWave {from{background-position:0% 0} to{background-position:100% 0}}
/* HI! 말풍선 — 원래 lio_intro_cut1.png 안에 합쳐져 있던 것을 잘라낸 에셋(IMAGE/b/bubble_hi.png).
   .splash::before 배경 목록에 레이어로 끼우면 .splash 높이가 폭주해 레이아웃이 깨져서
   스프라이트 요소의 ::after 로 붙였다 — 사자와 함께 들어오고 위치 계산도 한 곳에서 끝난다.
   걷는 동안엔 숨기고 손을 들어 인사를 시작할 때 통 튀며 뜬 다음, 이어서 계속 둥둥 뜬다.
   위치는 사자 쪽으로 붙였다 — 든 앞발(박스 x376~408 · y77~) 위쪽 옆이라 살짝 겹치는데
   ::after 라 앞발 위로 그려져 말풍선이 앞에 있는 것처럼 보인다.
   폭은 커밋본과 같은 화면 폭 6.32%. */
.splash .splash-inner::after{content:'';position:absolute;left:88%;top:6%;
  width:16.74%;aspect-ratio:97/94;opacity:0;
  background:url("../IMAGE/b/bubble_hi.png?v=20260813") no-repeat center/contain;
  /* 에셋에 그림자가 구워져 있지 않다(반투명 픽셀 0) — 떠 있는 느낌이 안 나므로 넣는다.
     box-shadow 는 사각 박스를 따라가므로 알파 모양을 따르는 drop-shadow 를 쓴다. */
  filter:drop-shadow(0 clamp(2px,.45cqw,7px) clamp(4px,.85cqw,13px) rgba(6,18,52,.32));
  animation:bBubbleIn    .28s cubic-bezier(.2,1.4,.4,1) 2.46s forwards,
            bBubbleFloat 2.4s ease-in-out                2.74s infinite}
@keyframes bBubbleIn{from{opacity:0;transform:translateY(18%) scale(.7)}
                     to  {opacity:1;transform:none}}
/* 둥둥 — bBubbleIn 뒤에 이어받아 transform 을 계속 잡는다 (opacity 는 bBubbleIn 의 forwards 가 유지) */
@keyframes bBubbleFloat{
  0%,100%{transform:translateY(0)}
  50%    {transform:translateY(-13%)}
}
@media (prefers-reduced-motion:reduce){
  /* 움직임을 줄이면 걷기·전환을 생략하고 인사 시트 첫 프레임에서 시작한다 */
  .splash .splash-inner{animation:none;
    background-image:url("../IMAGE/b/lio_intro_wave.webp");background-size:1200% 100%}
  .splash .splash-inner::after{animation:none;opacity:1}
}
/* LIO 뒤 원형 파장 — 원래 .splash 배경의 3겹 원을 실제 요소로 옮긴 것.
   B 에서 쓰지 않는 "Tap to start ▶" 요소(.splash-tap · 공용 마크업)를 링 호스트로
   재사용한다. 문구는 font-size:0 으로 지운다. (A 는 theme-b.css 를 읽지 않아 영향 없음)

   원래 그라디언트는 circle at 24% 44% 의 반지름이 farthest-corner 거리(1130×768 에서
   960.4px)의 21 / 31 / 41% → 지름 403 / 595 / 788px = .splash 폭의 35.7 / 52.7 / 69.7%.
   cqw 는 #stage 기준이라 여기 쓰면 14% 커진다 — 컨테이닝 블록 % 로 잡아야 맞는다.
   호스트 박스는 가장 바깥 링보다 크게(83.6%) 잡는다 — 박스에 딱 맞추면 링이 커질 때
   background 가 박스 경계에서 직선으로 잘린다(x=665 에 세로 직선이 생겼다).
   안쪽 두 링은 호스트 대비 %(403.4/944.7 = 42.70, 595.5/944.7 = 63.03)로 잡는다. 호스트에는 translate 만 걸고 scale 은 걸지 않는다 —
   호스트를 키우면 자식 링까지 같이 커져서 스태거가 사라진다. 바깥 링만 background-size
   로 키우고 안쪽 둘은 transform:scale(합성) 로 돌린다.
   delay 로 안쪽 → 바깥쪽 순서로 부풀려 파장이 LIO 에서 퍼져나가듯 보이게 했다. */
.splash .splash-tap{display:block;position:absolute;left:24%;top:44%;bottom:auto;
  width:83.6%;aspect-ratio:1;font-size:0;color:transparent;z-index:0;pointer-events:none;
  transform:translate(-50%,-50%);
  /* closest-side 필수 — 기본값 farthest-corner 면 광선 길이가 박스 절반의 √2 배가 된다.
     closest-side 광선 = 박스 절반(472.3px) 이므로 반지름 393.8px = 83.36%. */
  background:radial-gradient(circle closest-side,
             rgba(255,255,255,.035) 0 83.36%,transparent 83.56%) no-repeat center / 100% 100%;
  animation:bRingOut 5.4s ease-in-out 1.1s infinite}
.splash .splash-tap::before,
.splash .splash-tap::after{content:'';position:absolute;left:50%;top:50%;
  aspect-ratio:1;border-radius:50%;
  transform:translate(-50%,-50%);
  animation:bRingIn 5.4s ease-in-out infinite}
.splash .splash-tap::before{width:42.70%;background:rgba(255,255,255,.055);animation-delay:0s}
.splash .splash-tap::after {width:63.03%;background:rgba(255,255,255,.045);animation-delay:.55s}
@keyframes bRingIn{
  0%,100%{transform:translate(-50%,-50%) scale(1);    opacity:1}
  50%    {transform:translate(-50%,-50%) scale(1.14); opacity:.5}
}
@keyframes bRingOut{
  0%,100%{background-size:100% 100%; opacity:1}
  50%    {background-size:114% 114%; opacity:.55}
}
@media (prefers-reduced-motion:reduce){
  .splash .splash-tap,
  .splash .splash-tap::before,
  .splash .splash-tap::after{animation:none}
}
/* 마스코트 · 대형 로고 · 하단 물결 = Figma 에셋
   ⚠ background-position 의 퍼센트는 컨테이너 기준이 아니라 (컨테이너 − 이미지) 기준
     오프셋이다. 즉 `left 59.1%` 는 "왼쪽에서 59.1% 지점"이 아니다.
     아래 값은 목표 좌표에서 역산한 것 — 눈대중으로 고치면 다시 어긋난다.
     목표(cut1 실측, 카드 대비 비율)
       마스코트 주황 영역 x0=0.066 y1=0.734 높이 0.600
       로고 BI 인스턴스   x0=0.596 y0=0.314 폭 0.241 높이 0.254 (219:1338 · 380×272) */
.splash::before{content:'';position:absolute;inset:0;z-index:2;pointer-events:none;
  background:
    url("../IMAGE/b/logo_lockup.png") no-repeat left 79.5% top 42.1% / auto 25.4%,
    url("../IMAGE/b/wave_front.svg") repeat-x left bottom / 106.912% 31.25%,
    url("../IMAGE/b/wave_mid.svg")   repeat-x left bottom / 100% 31.25%,
    url("../IMAGE/b/wave_back.svg")  repeat-x left bottom / 100% 31.25%,
    /* LIO 는 아래 .splash-inner 스프라이트가 담당한다.
       바닥 그림자는 뺐다 — 스프라이트 발밑(y83.4%)이 물결(y68.75%~) 뒤로 들어가
       물결 자체가 접지 역할을 하고, 예전 좌표(56%)의 그림자는 공중에 떠 보였다. */
    linear-gradient(transparent,transparent)}
/* Let's Go! pill : 장식용(탭 타깃은 .splash 전체) — 라벨을 Figma 문구로 표시 */
.splash::after{content:"Let's Go!";position:absolute;z-index:3;pointer-events:none;
  left:60.1%;top:67.8%;width:21.5%;height:9.1%;
  display:flex;align-items:center;justify-content:center;text-align:center;
  box-sizing:border-box;
  padding:0 calc(var(--cta-chev) + clamp(8px,1cqw,13px)) 0 clamp(8px,1cqw,13px);
  font-family:var(--font-head);font-weight:800;color:var(--primary);
  font-size:var(--fz-cta);letter-spacing:-.2px;
  border-radius:999px;
  background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Ccircle cx='30' cy='30' r='30' fill='%23155DFC'/%3E%3Cpath d='M25.5 19.5L36 30L25.5 40.5' stroke='white' stroke-width='5.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat;
  background-position:right clamp(8px,1cqw,13px) center;
  background-size:var(--cta-chev) var(--cta-chev);
  box-shadow:0 10px 26px rgba(6,26,84,.24)}

/* ── bottom nav : 요청에 따라 미사용 ──
   engine.js 는 layout==='topic' (slide 8) 에서만 이 pill 네비를 렌더한다.
   Figma B_Topic_list 에는 있지만 실제 동작이 없어 화면만 가리므로 B 에서 숨긴다.
   (마크업 제거는 공용 engine.js 소관이라 CSS 로만 감춘다) */
.bottom-nav{display:none}

/* ── 하단 물결 파도 인터랙션 ───────────────────────────────────────────
   bottom_wav 를 앞·중간·뒤 3겹(wave_front/mid/back)으로 분리해 각각 다른 방향·
   속도로 흘린다. 배경 레이어는 하나의 animation 으로만 움직일 수 있으므로
   background-position 목록 전체를 키프레임에 적어 두고, 물결 레이어만 값을 바꾼다.
   ⚠ 타일 폭을 컨테이너 폭(background-size:100%)으로 두면 위치 지정 영역이
     (컨테이너 - 이미지) = 0 이 되어 퍼센트 오프셋이 전부 0 으로 계산돼 움직이지 않는다.
     → 길이 단위로 이동시킨다. 1cqw = #stage 폭의 1% 이므로 100cqw 가 정확히 타일 한 칸.
   앞 +106.912cqw(자기 타일 1칸) / 중간 -200cqw / 뒤 +300cqw → 속도 1 : 2 : 3, 방향 교차. */
.splash::before{animation:bWaveSplash 26s linear infinite}
@keyframes bWaveSplash{
  from{background-position:
    left 79.5% top 42.1%,          /* 로고 (고정) */
    0 bottom, 0 bottom, 0 bottom,  /* 물결 */
    left 9.1% bottom 44%,          /* 마스코트 (고정) */
    23.5% 56%}                     /* 그림자 (고정) */
  to  {background-position:
    left 79.5% top 42.1%,
    106.912cqw bottom, -200cqw bottom, 300cqw bottom,
    left 9.1% bottom 44%,
    23.5% 56%}
}
.introseq::before,
.scr-quick_exit .quickexit::before,
.scr-post_skill_pick .quickexit::before{animation:bWaveIntro 26s linear infinite}
@keyframes bWaveIntro{
  from{background-position:
    0 bottom, 0 bottom, 0 bottom,  /* 물결 */
    left 9.1% bottom 44%,          /* 마스코트 */
    23.5% 56%,                     /* 그림자 */
    0 0}                           /* 블루 필 */
  to  {background-position:
    106.912cqw bottom, -200cqw bottom, 300cqw bottom,
    left 9.1% bottom 44%,
    23.5% 56%,
    0 0}
}
/* 모션 최소화를 원하는 사용자는 정지 */
@media (prefers-reduced-motion:reduce){
  .splash::before,.introseq::before,
  .scr-quick_exit .quickexit::before,
  .scr-post_skill_pick .quickexit::before{animation:none}
}

/* ── Let's Go 버튼 hover 인터랙션 ────────────────────────────────────────
   파란 셰브론 원이 좌우로 부드럽게 왕복한다. 셰브론은 배경 이미지 레이어이므로
   background-position 을 키프레임으로 흔든다. splash 의 pill 은 ::after 장식이라
   탭 타깃인 .splash 의 hover 로 구동한다. */
@keyframes bChevNudge{
  0%,100%{background-position:right clamp(8px,1cqw,13px) center}
  50%    {background-position:right clamp(0px,0.1cqw,3px)  center}
}
.introseq .introseq-next:hover,
.skillscreen.selected .skillsel-go:hover,
.skillscreen.found .skillsel-go:hover,
.splash:hover::after{animation:bChevNudge .9s ease-in-out infinite;
  box-shadow:0 14px 32px rgba(6,26,84,.32)}
.introseq .introseq-next{transition:box-shadow .18s}
@media (prefers-reduced-motion:reduce){
  .introseq .introseq-next:hover,
  .skillscreen.selected .skillsel-go:hover,
  .skillscreen.found .skillsel-go:hover,
  .splash:hover::after{animation:none}
}

/* ── skill 카드 : 세로 컬럼 무한 스크롤 ────────────────────────────────
   engine.js(B 전용 buildSkillLanesB)가 그리드를 세로 컬럼 트랙 4개로 재구성한다.
   각 트랙은 그리드 높이를 꽉 쓰고 overflow:hidden, 안에 그 컬럼의 카드 세트를
   여러 벌 이어 붙여 한 세트 높이(--set)만큼 돌린다 → 카드는 온전한 모양을 유지하며
   위/아래로 계속 흘러간다. 홀수 컬럼은 위로, 짝수 컬럼은 아래로 교차. */
/* .skillscreen → .skill-grid 의 높이 사슬이 확정되지 않아 height:100% 가 0 으로
   계산된다(앞서 행 높이에서도 같은 문제). 디바이스 비율이 고정이므로 cqw 로 못박는다.
   화면 높이 ≈ 68cqw, 상단 로고 여백을 감안해 트랙은 62cqw. */
/* ⚠ .skill-grid 에 justify-items:center 가 걸려 있어 트랙이 내용 크기로 줄어드는데,
   내부(.b-lane-inner)가 absolute 라 내재 폭이 없어 트랙 폭이 0 이 됐다.
   → b-laned 에서는 stretch 로 되돌리고 트랙 폭을 100% 로 명시한다. */
/* 트랙은 화면 높이를 꽉 쓴다. 디바이스 높이 = 100cqw/1.4711 ≈ 68cqw.
   .skillscreen 의 상·하 padding 은 좌측(마스코트) 열용이라 그리드에서는 음수 마진으로
   상쇄해 위아래 여백 없이 트랙이 끝까지 닿게 한다. */
.skill-grid.b-laned{display:grid;grid-template-columns:repeat(4,1fr);
  grid-template-rows:68cqw;gap:0 1.2cqw;align-content:start;
  justify-items:stretch;align-items:stretch;
  /* base 의 .skill-grid{padding:6px} 가 트랙을 6px 아래로 밀어 상단 여백을 만들었다 */
  padding:0;
  margin-top:calc(-1 * clamp(46px,5.6cqw,88px));
  margin-bottom:calc(-1 * clamp(8px,1.2cqw,12px));
  height:auto}
.b-lane{position:relative;width:100%;height:68cqw;min-height:0;overflow:hidden}
.b-lane-inner{position:absolute;left:0;right:0;top:0;display:flex;flex-direction:column;
  will-change:transform;backface-visibility:hidden;transform:translateZ(0)}
.b-lane-set{display:flex;flex-direction:column;gap:2.2cqw;flex:0 0 auto;
  padding-bottom:2.2cqw}                      /* 세트 사이 간격도 카드 간격과 같게 */
/* .skill-card 가 height:100% 라서 셀에 확정 높이가 없으면 0 이 된다 → 카드 높이 명시 */
.b-cell{height:19.8cqw;flex:0 0 auto;display:flex;align-items:center;justify-content:center}
.b-cell .skill-card{animation:none;height:100%;width:auto;max-height:100%}
/* base 의 .skill-card.today{transform:scale(1.06)} 때문에 Main Ideas 만 6% 커 보였다.
   트랙에서는 모든 카드 크기를 같게 맞춘다. */
.b-cell .skill-card.today{transform:none}
.b-lane-up   .b-lane-inner{animation:bLaneUp   var(--dur,16s) linear infinite}
.b-lane-down .b-lane-inner{animation:bLaneDown var(--dur,16s) linear infinite}
/* 같은 세트 2벌을 쌓고 한 세트 높이만큼만 이동한다 → 되돌아오는 순간 두 번째 벌이
   첫 벌 자리를 정확히 메워 이음매가 보이지 않고, 트랙이 비는 구간도 없다.
   1·3열은 위로(아래에서 올라옴), 2·4열은 아래로(위에서 내려옴). */
@keyframes bLaneUp  {from{transform:translate3d(0,0,0)}
                     to  {transform:translate3d(0,calc(-1 * var(--set)),0)}}
@keyframes bLaneDown{from{transform:translate3d(0,calc(-1 * var(--set)),0)}
                     to  {transform:translate3d(0,0,0)}}
/* 이동 거리(laneH + setH)가 컬럼마다 달라 체감 속도가 같도록 duration 을 맞춘다 */
.skill-grid.b-laned .b-lane:nth-child(1) .b-lane-inner{--dur:12s}   /* 카드 3장 · 위로 */
.skill-grid.b-laned .b-lane:nth-child(2) .b-lane-inner{--dur:9s}    /* 카드 1장 · 아래로 */
.skill-grid.b-laned .b-lane:nth-child(3) .b-lane-inner{--dur:11s}   /* 카드 2장 · 위로 */
.skill-grid.b-laned .b-lane:nth-child(4) .b-lane-inner{--dur:14s}   /* 카드 4장 · 아래로 */
/* 선택 상태에서는 흐름을 멈춘다 */
.skillscreen.selected .b-lane-inner{animation-play-state:paused}
@media (prefers-reduced-motion:reduce){ .b-lane-inner{animation:none} }

/* 선택 상태(B_Skill_selected) : 뒤 카드는 흐려지고 움직임도 멈춘다 */
.skillscreen.selected .skill-card{animation:none}
.skillscreen.selected .skill-grid.dim{opacity:.45;filter:blur(7px);pointer-events:none;
  transition:opacity .45s,filter .45s}

/* 물음표 말풍선 : base 는 .skill-left 기준 top30%/right16% 인데 마스코트를 절대배치로
   옮겼으므로 화면 기준으로 다시 잡는다. 요청대로 더 위·오른쪽으로. */
/* slide 6 의 GO 말풍선과 같은 크기로 (자체 렌더 실측 지름 6.81cqw) 사자 오른쪽에 띄운다.
   LIO 는 left 27% + 폭 약 25.5% → 오른쪽 끝 ≈52.5%. 그 바로 밖에 배치. */
/* 말풍선 : Figma #component > ic_question (250:1834) PNG@4x → IMAGE/b/ic_question.png
   (프레임 97×94, 크기는 Figma 기준 97/1577 = 6.15cqw) */
.skillscreen:not(.selected) .think-bubble{position:absolute;top:23%;left:38%;right:auto;
  width:clamp(44px,6.15cqw,92px);height:auto;aspect-ratio:97/94;
  background:url("../IMAGE/b/ic_question.png?v=20260812") no-repeat center / contain;
  border-radius:0;box-shadow:none;font-size:0;color:transparent;z-index:6;
  filter:drop-shadow(0 clamp(2px,.45cqw,7px) clamp(4px,.85cqw,13px) rgba(6,18,52,.32));
  /* slide 7 의 LIO 옆 ? 말풍선은 쓰지 않는다 (요청). 위치·크기 값은 기록으로 남겨 둔다 —
     별도 규칙으로 display:none 을 앞에 두면 여기 있는 display 에 덮이므로 이 값을 바꾼다. */
  display:none;padding:0;
  /* slide 5 의 HI! · slide 6 의 GO 말풍선과 같이 둥둥 뜨게 (같은 키프레임 재사용) */
  animation:bBubbleFloat 2.4s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){
  .skillscreen:not(.selected) .think-bubble{animation:none}
}

/* ── slide 16 정/오답 LIO 반응 (Design B) ─────────────────────────────────
   quiz-reaction.js 가 채점 순간 .device 안에 .quiz-reaction.quiz-o / .quiz-x 를 넣고,
   재생이 끝나면 스스로 지운다. 여기서는 그 요소의 크기·연출만 정의한다.

   가운데 크게 : 높이 62%(화면) · 좌우 중앙. 두 시트의 프레임 비율이 달라
   (quiz_o 436/572=0.762 · quiz_x 556/516=1.078) aspect-ratio 를 각각 준다.
   연출 : bQuizIn(튀어들어옴 .34s) → 스프라이트 16프레임 재생 → bQuizOut(줄며 사라짐 .40s).
   프레임 재생은 steps(16,jump-none) 1회 — alternate 를 쓰면 되감기처럼 보인다.
   z-index 는 지문·대화 위(60), 오버레이라 pointer-events:none 로 클릭을 막지 않는다. */
.quiz-reaction{position:absolute;left:50%;top:46%;height:62%;
  transform:translate(-50%,-50%);z-index:60;pointer-events:none;
  background-repeat:no-repeat;background-position:0% 0;
  filter:drop-shadow(0 clamp(6px,1.2cqw,18px) clamp(12px,2.4cqw,34px) rgba(6,18,52,.34));
  /* longhand 로 쓴 이유 : 프레임 재생 방향만 시트별로 다르고(아래 .quiz-x) 나머지는 같다.
     shorthand 로 쓰면 규칙 전체를 두 번 복사해야 한다.
     0 ─ bQuizIn .34s (튀어들어옴) → bQuizFrame 1.45s ×2 = 2.9s → bQuizOut .46s (3.24s~3.70s) */
  animation-name:bQuizIn,bQuizFrame,bQuizOut;
  animation-duration:.34s,1.45s,.46s;
  animation-delay:0s,.34s,3.24s;
  animation-timing-function:cubic-bezier(.2,1.5,.4,1),steps(16,jump-none),cubic-bezier(.4,0,.7,-.2);
  animation-iteration-count:1,2,1;
  animation-direction:normal;
  animation-fill-mode:both}
/* quiz_o : 16→1 프레임차가 인접 평균의 1.02배(22.1 vs 21.7)로 그대로 이어 붙여도 매끄럽다 */
.quiz-reaction.quiz-o{width:auto;aspect-ratio:436/572;
  background-image:url("../IMAGE/b/quiz_o.webp");background-size:1600% 100%}
/* quiz_x : 이음새가 평균의 1.99배(12.3 vs 6.2)라 그대로 반복하면 첫 프레임으로 튄다.
   되돌림(alternate)으로 재생하면 이음새를 지나지 않고, 웅크린 자세라 오히려 자연스럽다 */
.quiz-reaction.quiz-x{width:auto;aspect-ratio:556/516;
  background-image:url("../IMAGE/b/quiz_x.webp");background-size:1600% 100%;
  animation-direction:normal,alternate,normal}
@keyframes bQuizFrame{from{background-position:0% 0} to{background-position:100% 0}}
@keyframes bQuizIn{
  from{opacity:0;transform:translate(-50%,-50%) scale(.55)}
  to  {opacity:1;transform:translate(-50%,-50%) scale(1)}
}
@keyframes bQuizOut{
  from{opacity:1;transform:translate(-50%,-50%) scale(1)}
  to  {opacity:0;transform:translate(-50%,-52%) scale(.82)}
}

/* ── slide 16 오답 : LIO 뒤로 비가 내린다 ──────────────────────────────────
   quiz-reaction.js 가 오답일 때만 .quiz-rain 을 LIO 보다 먼저 넣는다.
   z-index 59 < LIO 60 이라 확실히 뒤에 깔린다(형제 요소로 둔 이유 — 가상요소를
   음수 z-index 로 내려도 부모의 배경, 즉 LIO 스프라이트보다 뒤로는 못 간다).

   빗줄기는 '세로 방향 띠 그라디언트 × 가로 방향 마스크' 로 만든다.
   띠만 쓰면 화면 폭 전체를 채운 가로줄이 되고, 마스크로 얇은 열만 남기면
   비로소 낱개 빗줄기가 된다. 낙하는 background-position 을 정확히 한 주기만큼
   내려 이어붙인다(레이어마다 주기가 달라 keyframes 도 따로 둔다).

   흰 줄만 쓰면 지문·대화 패널이 흰색이라 보이지 않는다. 그래서 host 에 짙은
   남색 wash 를 얇게 깔고 그 위에 흰 줄을 얹는다 — 비구름처럼 어두워지면서
   가운데 LIO 도 함께 도드라진다. pointer-events:none 이라 조작을 막지는 않는다. */
.quiz-rain{position:absolute;top:60px;left:0;right:0;height:64%;
  z-index:59;pointer-events:none;overflow:hidden;
  /* 아래로 갈수록 사라지게 — 띠 끝에서 빗줄기가 잘려 보이지 않게 한다.
     host 에 마스크를 걸면 가상요소까지 함께 페이드된다(host 자체 배경은 없다) */
  -webkit-mask-image:linear-gradient(180deg,#000 0 66%, transparent 100%);
          mask-image:linear-gradient(180deg,#000 0 66%, transparent 100%);
  animation:bRainIn .42s ease-out both, bRainOut .46s ease-in 3.24s both}
.quiz-rain::before,.quiz-rain::after{content:'';position:absolute;
  top:-60%;width:124%;height:220%;
  animation-timing-function:linear;animation-iteration-count:infinite}
/* 빗줄기 색 : 흰색을 쓰면 지문·대화 패널이 흰색이라 안 보인다. wash 를 깔지 않기로 했으니
   패널 위에서도 읽히는 청회색으로 칠한다.
   성기게 : 가로 간격을 27px → 86px(앞) · 19px → 112px(뒤) 로 벌려 confetti 밀도에 맞췄다.
   레이어도 각 1줄로 줄였다(전에는 레이어마다 2줄, 총 4줄).
   비는 사선이 아니라 위에서 아래로 곧게 떨어진다 — 두 레이어 모두 회전 없음. */
.quiz-rain::before{left:-12%;
  background-image:repeating-linear-gradient(180deg, rgba(74,105,180,.50) 0 18px, transparent 18px 104px);
  background-position:0 0;
  -webkit-mask-image:repeating-linear-gradient(90deg,#000 0 2px, transparent 2px 86px);
          mask-image:repeating-linear-gradient(90deg,#000 0 2px, transparent 2px 86px);
  animation-name:bRainFall1;animation-duration:.62s}
/* 뒤쪽은 각도·간격·속도를 달리하고 left 를 어긋나게 둬서 두 줄이 겹쳐 보이지 않게 한다 */
.quiz-rain::after{left:-6%;filter:blur(.5px);opacity:.8;
  background-image:repeating-linear-gradient(180deg, rgba(74,105,180,.34) 0 12px, transparent 12px 82px);
  background-position:0 0;
  -webkit-mask-image:repeating-linear-gradient(90deg,#000 0 1.5px, transparent 1.5px 112px);
          mask-image:repeating-linear-gradient(90deg,#000 0 1.5px, transparent 1.5px 112px);
  animation-name:bRainFall2;animation-duration:.44s}
@keyframes bRainFall1{to{background-position:0 104px}}
@keyframes bRainFall2{to{background-position:0 82px}}
@keyframes bRainIn{from{opacity:0} to{opacity:1}}
@keyframes bRainOut{from{opacity:1} to{opacity:0}}
@media (prefers-reduced-motion:reduce){
  /* 움직임을 줄이면 프레임 재생·낙하 없이 첫 모습만 잠깐 보여준다 */
  .quiz-reaction{animation:bQuizIn .2s both, bQuizOut .3s 2.2s both}
  .quiz-rain{animation:bRainIn .2s both, bRainOut .3s 2.2s both}
  .quiz-rain::before,.quiz-rain::after{animation:none}
}

/* ── slide 64 학습 종료 화면 ───────────────────────────────────────────────
   디자인은 slide 63(추가 학습 선택)을 styleAs 로 그대로 빌려 쓰고, 여기서 두 가지만 덮는다.
   1) 버튼이 하나뿐이라 63 의 :first-child/:last-child 라벨이 둘 다 걸린다 → 'Exit' 로.
   2) LIO 를 slide 5 의 손 흔드는 스프라이트로. 시트가 달라(421×505 vs 412×548) 렌더 높이가
      같아지도록 폭을 다시 잡았다 — 34.82%×(548/412)=46.31% 높이 → 46.31%×(421/505)=38.61% 폭.
      애니메이션은 slide 5 와 같은 0.90s · 12프레임 · alternate. */
/* 버튼은 slide 5 의 'Let's Go!' 와 같은 톤 — 흰 알약 + 파란 글자 + 파란 원형 셰브론.
   63 의 라벨/배경 규칙과 같은 형태(특정도 동일)로 두고 파일 뒤쪽에 둬서 순서로 이긴다.
   버튼이 하나뿐이라 flex:1 로 가로가 꽉 차므로 폭도 알약처럼 줄인다. */
.scr-session_end .qe-imgbtn:last-child{
  color:var(--primary);
  background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Ccircle cx='30' cy='30' r='30' fill='%23155DFC'/%3E%3Cpath d='M25.5 19.5L36 30L25.5 40.5' stroke='white' stroke-width='5.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right clamp(8px,1cqw,13px) center;
  background-size:var(--cta-chev) var(--cta-chev);
  flex:0 0 auto;min-width:clamp(180px,26cqw,340px)}
.scr-session_end .qe-imgbtn:last-child::before{content:"Exit";color:var(--primary)}
.scr-session_end .qe-actions{justify-content:flex-end}
.scr-session_end .qe-scrim{
  width:38.61%;aspect-ratio:421/505;
  background:url("../IMAGE/b/lio_intro_wave.webp") no-repeat 0% 0 / 1200% 100%;
  animation:bLioWaveEnd .90s steps(12,jump-none) infinite alternate}
@keyframes bLioWaveEnd{from{background-position:0% 0} to{background-position:100% 0}}
/* BYE! 말풍선 — Figma #component 의 ic_bye (355:360).
   내려받은 export 는 파란 배경이 합성돼 있어, 테두리에서 배경색을 따라 채워 바깥만 투명으로
   만들고 안쪽 원색은 그대로 남겼다(흰색 기준 언믹스만 쓰면 주황 글자가 옅어진다).
   위치·크기·그림자·둥둥 뜨는 연출은 slide 5 의 HI! 말풍선과 같은 방식. */
.scr-session_end .qe-scrim::after{content:'';position:absolute;left:84%;top:4%;
  width:17.5%;aspect-ratio:97/94;
  background:url("../IMAGE/b/bubble_bye.png?v=20260812") no-repeat center/contain;
  filter:drop-shadow(0 clamp(2px,.45cqw,7px) clamp(4px,.85cqw,13px) rgba(6,18,52,.32));
  animation:bBubbleFloat 2.4s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){
  .scr-session_end .qe-scrim{animation:none}
}

/* ── Listen 버튼 : 텍스트 없이 아이콘만 크게 ────────────────────────────────
   markup 은 engine.js 의 `<button class="listen-btn"><img class="ls-ic">Listen</button>` 로
   'Listen' 이 요소로 감싸여 있지 않은 순수 텍스트 노드다. 자식 선택자로는 못 숨기므로
   버튼의 font-size 를 0 으로 만들어 지운다. 아이콘 크기는 px 로 지정돼 있어 영향받지 않는다.
   공용 base.css 를 고치면 A 까지 바뀌므로 B 에서만 덮는다(C 는 theme-c.css 에 같은 규칙). */
.listen-btn{
  /* font-size:0 으로 텍스트를 지우면 인라인 요소의 베이스라인이 무너져 버튼이
     아래로 내려간다. inline-flex 로 아이콘을 가운데 두고, 버튼 자체를
     vertical-align:middle 로 주변 텍스트 줄 중앙에 맞춘다. */
  display:inline-flex; align-items:center; justify-content:center;
  vertical-align:middle;
  font-size:0; line-height:0;
  width:clamp(30px,3.2cqw,46px); height:clamp(30px,3.2cqw,46px);
  padding:0; border-radius:50%;
}
.listen-btn .ls-ic{
  width:clamp(20px,2.2cqw,32px); height:clamp(20px,2.2cqw,32px);
  margin-right:0; display:block;
}
/* 재생 중에는 markup 이 `<span class="ls-stop"></span>Stop` 으로 바뀐다(engine.js).
   base 의 .ls-stop 은 9px 사각형에 margin-right:5px 라, flex 중앙 정렬에서 그 여백만큼
   왼쪽으로 밀리고 스피커 아이콘(26px)에 비해 너무 작다. 여백을 없애고 키운다. */
.listen-btn .ls-stop{
  width:clamp(12px,1.3cqw,19px); height:clamp(12px,1.3cqw,19px);
  margin-right:0; border-radius:22%; flex:0 0 auto;
}
/* base 의 .listen-btn.playing 은 바깥쪽 2px 링(box-shadow:0 0 0 2px)이라
   재생 중 버튼이 사방 2px 씩(총 4px) 커 보인다. 안쪽 링으로 바꿔 크기를 같게 둔다. */
.listen-btn.playing{ box-shadow:inset 0 0 0 2px rgba(15,109,97,.35) }

/* KR 을 누르면 영문을 남기고 그 아래에 한글을 붙인다(engine 의 keepEn · 전체 화면).
   .tx-kr 은 원래 인라인이라 같은 줄에 이어 붙으므로 블록으로 떼어낸다. */
.tx-kr:not([hidden]){
  display:block;
  margin-top:.28em;
  color:#41527a;                 /* 영문보다 한 톤 눌러 구분 */
  /* 한글은 영문보다 정확히 2px 작게. 비율(.94em)로 두면 부모 글자 크기(말풍선 18.6 ·
     문제 19.4 · 보기 17.7px)마다 차이가 달라진다 — calc 로 고정한다. */
  font-size:calc(1em - 2px);
  line-height:1.35;
}
/* 한글 줄 끝의 닫기(X) — '닫기' 텍스트 버튼을 대신한다(engine 의 addKrClose).
   한글 요소 안에 들어가므로 문장 끝에 자연스럽게 따라붙는다. */
/* .kr 은 author 규칙에 display 가 있어 hidden 속성의 UA display:none 이 밀린다.
   병기 중에는 KR 버튼을 감춰야 하므로 명시적으로 이긴다. */
.kr[hidden]{ display:none !important }
.tx-kr .tx-kr-x{
  display:inline-flex; align-items:center; justify-content:center;
  /* Listen 버튼과 같은 크기 — 같은 clamp 값을 쓴다(.listen-btn 참고). */
  width:clamp(30px,3.2cqw,46px); height:clamp(30px,3.2cqw,46px);
  flex:0 0 auto; margin-left:clamp(4px,.5cqw,8px);
  /* 한글 텍스트 줄과 세로 중앙을 맞춘다. 고정 오프셋은 글자 크기가 바뀌면 어긋나므로
     middle 로 둔다 — 주변 텍스트의 중앙선에 붙는다. */
  vertical-align:middle;
  white-space:nowrap;
  padding:0; border:none; border-radius:50%;
  /* X 는 글리프(✕) 대신 SVG 로 그린다 — 굵기(stroke-width)와 둥근 끝(linecap:round)을
     폰트에 맡기지 않고 직접 정한다. 글리프는 font-size:0 으로 감춘다(aria-label 로 읽힌다). */
  background:#dfe6f3 no-repeat center / 46% 46%
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg stroke='%2341527a' stroke-width='3.6' stroke-linecap='round'%3E%3Cpath d='M6 6 L18 18'/%3E%3Cpath d='M18 6 L6 18'/%3E%3C/g%3E%3C/svg%3E");
  color:#41527a; font-size:clamp(15px,1.6cqw,23px); line-height:1; cursor:pointer;
  /* middle 은 라틴 x-height 중앙에 맞추는데 한글 글자는 그보다 살짝 위가 시각적 중앙이다.
     실측 1.5~1.8px 낮게 앉아 그만큼 올린다(em 이라 글자 크기에 따라 같이 움직인다). */
  position:relative; top:-.07em;
  transition:background-color .15s;
}
.tx-kr .tx-kr-x:hover{ background-color:#cfd8ea }
.tx-kr .tx-kr-x:focus-visible{ outline:2px solid var(--primary); outline-offset:1px }
/* 대화창의 스피커·KR 을 지문 Listen 버튼과 같은 원형 버튼으로 통일한다.
   기준(.listen-btn) : 지름 clamp(30px,3.2cqw,46px) · 배경 #e6f4f1 · 글자 #0f6d61 · 테두리 없음
   스피커는 <img> 라 padding 으로 원 안에 아이콘을 앉힌다(아이콘은 26px 로 Listen 과 같다). */
.activity .tts-ic{
  /* 대화창은 spk_bubble.svg(검정), 지문은 spk_listen.svg(청록)를 쓴다. 둘 다 파랑으로
     맞추려고 같은 그림의 파란 버전(spk_listen_blue.svg)으로 갈아 끼운다 — img 의 src 는
     공용 engine 이 정하므로 content 로 그려지는 이미지만 바꾼다(A 는 그대로다). */
  content:url("../IMAGE/ui/spk_listen_blue.svg");
  box-sizing:border-box;
  width:clamp(30px,3.2cqw,46px); height:clamp(30px,3.2cqw,46px);
  padding:clamp(5px,.5cqw,7px);
  background:#e6f4f1; border-radius:50%;
  flex:0 0 auto; margin-left:clamp(3px,.4cqw,6px);
  vertical-align:middle; cursor:pointer;
  /* 닫기 X 와 같은 보정 — middle 은 라틴 x-height 중앙에 맞아 한글 옆에서는 1.5px 낮게
     앉는다. em 이라 글자 크기와 함께 움직인다(img 는 부모 font-size 를 물려받는다). */
  position:relative; top:-.07em;
}
.activity .kr{
  box-sizing:border-box;
  display:inline-flex; align-items:center; justify-content:center;
  width:clamp(30px,3.2cqw,46px); height:clamp(30px,3.2cqw,46px);
  padding:0; margin-left:clamp(3px,.4cqw,6px);
  background:#e6f4f1; border:none; border-radius:50%;
  color:#0f6d61; font-weight:700;
  font-size:clamp(11px,1.15cqw,17px); line-height:1;
  vertical-align:middle;
  /* 스피커·X 와 같은 보정 — middle 만으로는 글자 잉크 중앙보다 1.7px 낮게 앉는다.
     KR 은 자체 글자 크기가 작아(약 13.6px) 같은 .07em 이면 보정이 부족하다.
     스피커와 같은 실제 픽셀(약 1.4px)이 되도록 .10em 을 쓴다. */
  position:relative; top:-.10em;
}
.activity .kr.on{ background:#0f6d61; color:#fff }

/* Listen · 대화창 스피커 · KR 버튼 색 — #e6f4f1 은 말풍선 배경(#f0f3fb)과 명도가 비슷해
   묻힌다. 배경을 한 단계 진하게 하고 테두리를 넣어 또렷하게 한다.
   아이콘은 <img>(SVG 파일)라 CSS color 가 듣지 않으므로 배경·테두리로 대비를 만든다.
   세 버튼을 함께 바꿔 앞서 맞춘 통일을 유지한다. */
.listen-btn,
.activity .tts-ic,
.activity .kr{
  background:#dde7ff;
  border:1.5px solid #8aa9ee;
  box-sizing:border-box;
}
.activity .kr{ color:#1b49c0; font-weight:800 }
.listen-btn{ color:#1b49c0 }          /* base 의 .ls-stop 은 currentColor 라 정지 사각형도 따라온다 */
.listen-btn:hover,
.activity .tts-ic:hover,
.activity .kr:hover{ background:#cbdaff }
/* 재생(정지 버튼) 상태는 KR 닫기 X 와 같은 색으로 — 배경 #dfe6f3 · 표시 #41527a.
   .ls-stop 은 base 에서 background:currentColor 라 color 만 주면 사각형도 따라온다. */
.listen-btn.playing,
.activity .tts-ic.playing,
.word-popup .wp-word .tts-ic.playing{
  background:#dfe6f3;
  border-color:transparent;      /* X 는 테두리가 없다 — 있으면 서로 달라 보인다 */
  color:#41527a;
  box-shadow:none;
}
/* 스피커의 정지 아이콘 — 지문 .ls-stop 과 같은 둥근 사각형(색은 X 와 동일 #41527a) */
.activity .tts-ic.playing,
.word-popup .wp-word .tts-ic.playing{
  content:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='6.5' y='6.5' width='11' height='11' rx='2.6' fill='%2341527a'/%3E%3C/svg%3E");
}
/* 아이콘도 파랑으로 — 원본 SVG 는 stroke #0F6D61 이라 같은 그림의 파란 버전을 쓴다 */
.listen-btn .ls-ic{ content:url("../IMAGE/ui/spk_listen_blue.svg") }
/* 상단 공통 헤더의 "STEP 2 Skill Core" 는 빼고 스킬 이름만 남긴다.
   구분선(|)도 함께 감춘다 — 안 그러면 선만 덩그러니 남는다.
   markup 은 공용 engine.js 라 A 까지 바뀌므로 여기서 감추기만 한다. */
.hd .hd-pill,
.hd .hd-divider{ display:none }
/* 헤더에 스킬 이름만 남았으므로 더 크고 또렷하게 — 흰색 + 한 단계 큰 글자.
   기본 --fz-hd-meta(11.5~16px)는 pill 과 나란히 놓던 때의 크기다. */
.hd .hd-skill{
  color:#fff;
  font-size:clamp(15px,1.55cqw,22px);
  font-weight:600;
}

/* LIO 말풍선이 연달아 나오면 첫 줄만 아바타를 보여준다.
   .lio-dup 은 engine 의 dedupeLioAvatars 가 붙인다 — 사이에 숨은 말풍선이 끼어 있어
   CSS 인접 선택자(+)로는 잘못 잡힌다(실측 33곳).
   display:none 을 주면 .msg 가 flex 라 말풍선이 왼쪽으로 붙어 위 줄과 어긋난다 —
   자리는 남기고 visibility 로만 감춘다. */
.msg.lio.lio-dup > .avatar{ visibility:hidden }

/* 단어 팝업에서 예문 줄을 뺀다(요청). KR 은 예문 대신 '뜻' 의 한글을 병기하는 버튼이
   되었다(engine 의 wp-kr 핸들러 · 대화창과 같은 방식).
   markup 은 공용 engine.js 라 지우지 않고 여기서 감추기만 한다 — A 는 그대로다.
   지문 하단 어휘 카드(.td-w 계열)의 예문은 건드리지 않는다. */
.word-popup .wp-ex{ display:none }

/* 팝업의 Listen · KR 도 대화창과 같은 원형 버튼으로. 팝업 배경이 어두워 같은 파랑을
   그대로 쓰면 잘 보인다(배경 #dde7ff · 테두리 #8aa9ee). 스피커 아이콘도 파란 버전으로. */
.word-popup .tts-ic{
  content:url("../IMAGE/ui/spk_listen_blue.svg");
  box-sizing:border-box;
  width:clamp(30px,3.2cqw,46px); height:clamp(30px,3.2cqw,46px);
  padding:clamp(5px,.5cqw,7px);
  background:#dde7ff; border:1.5px solid #8aa9ee; border-radius:50%;
  flex:0 0 auto; margin-left:clamp(3px,.4cqw,6px);
  vertical-align:middle; cursor:pointer;
  position:relative; top:-.07em;
}
/* base 의 .word-popup .wp-word .tts-ic{filter:invert(1) brightness(2)} 가 더 구체적이라
   파란 버튼이 반전돼 노랗게 나온다 — 같은 경로로 덮어 KR 과 같은 색을 지킨다. */
.word-popup .wp-word .tts-ic{ filter:none }
.word-popup .wp-kr{
  box-sizing:border-box;
  display:inline-flex; align-items:center; justify-content:center;
  width:clamp(30px,3.2cqw,46px); height:clamp(30px,3.2cqw,46px);
  padding:0; margin-left:0;                      /* 단어 줄의 flex gap 이 간격을 준다 */
  background:#dde7ff; border:1.5px solid #8aa9ee; border-radius:50%;
  color:#1b49c0; font-weight:800;
  font-size:clamp(11px,1.15cqw,17px); line-height:1;
  vertical-align:middle; cursor:pointer;
  position:relative; top:-.10em;
}
.word-popup .tts-ic:hover,
.word-popup .wp-kr:hover{ background:#cbdaff }
.word-popup .wp-kr[hidden]{ display:none !important }
/* 뜻 아래 한글 병기 — 팝업은 배경이 어두워 밝은 색으로 */
.word-popup .wp-def .tx-kr{ color:#cdd8f0 }
/* 단어 팝업을 2열 그리드로 — 1열은 이모지, 2열은 단어·뜻·KR.
   이모지를 단어 안에 두면 뜻 줄의 왼쪽이 이모지 폭만큼 어긋난다.
   .wp-close 는 absolute 라 그리드에 끼지 않는다.
   이모지가 없는 단어는 1열이 0폭이 되고 gap 도 이모지의 margin 이라 함께 사라진다. */
.word-popup{ display:grid; grid-template-columns:auto 1fr; align-content:start }
.word-popup > .wp-emo{
  /* 단어 + 뜻 두 줄을 합친 높이의 가운데에 놓는다 (두 행을 걸치므로 center 로 충분하다) */
  grid-column:1; grid-row:1 / span 2; align-self:center;
  margin-right:.5em; font-size:2.1em; line-height:1.05;
}
.word-popup .wp-word,
.word-popup .wp-def,
.word-popup .wp-ex{ grid-column:2 }
/* 단어 줄(.wp-word)은 flex + align-items:center 라 버튼을 flex 가 정렬한다.
   텍스트 옆에 놓일 때 쓰던 상대 이동값(top)이 남아 있으면 두 버튼이 서로 어긋난다
   (실측 4.72px). 여기서는 0 으로 두고, 간격도 다른 버튼들과 같은 값으로 맞춘다. */
.word-popup .wp-word{ gap:clamp(3px,.4cqw,6px) }
/* base 의 .wp-kr{margin-top:9px} 이 남아 있으면 flex 중앙 정렬에서 그 절반(4.5px)만큼
   내려간다 — 여백을 모두 0 으로 두고 간격은 .wp-word 의 gap 에 맡긴다. */
.word-popup .wp-word .tts-ic,
.word-popup .wp-word .wp-kr{ top:0; margin:0; vertical-align:baseline }
