@font-face{font-family:"CiaCia Sans";src:url("./font/CiaCia-Sans.woff2") format("woff2");font-display:block}
*{box-sizing:border-box}
[hidden]{display:none !important}   /* components.css의 display 선언이 UA의 [hidden]을 덮는 것을 막는다 */
html,body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--font-ui);font-weight:var(--fw-regular);font-size:var(--fs-16);line-height:var(--lh-normal)}
.cia{font-family:var(--font-cia);font-weight:500}
.center{text-align:center}
.top{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);padding:var(--sp-3) var(--sp-6);background:var(--surface);box-shadow:var(--sh-sm);position:sticky;top:0;z-index:var(--z-nav);flex-wrap:wrap}
.top__brand{display:flex;align-items:baseline;gap:var(--sp-3);font-weight:var(--fw-black);font-size:var(--fs-20);color:var(--brand-text)}
.top__brand .cia{font-size:var(--fs-24)}
.top__sub{color:var(--ink)}
.top__tools{display:flex;align-items:center;gap:var(--sp-4);flex-wrap:wrap}
.opt{display:flex;align-items:center;gap:6px;font-size:var(--fs-14);font-weight:var(--fw-medium);color:var(--ink-2)}
#app{max-width:1040px;margin:0 auto;padding:var(--sp-6) var(--sp-4) var(--sp-16)}
.view[hidden]{display:none}
.hero{margin-bottom:var(--sp-6)}
.hero h1{margin:0 0 var(--sp-3)}
.hero p{margin:0 0 var(--sp-2);max-width:68ch}
/* ── 코스 개요 (Screen 04) ── */
.kemaj{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--sp-4);margin-bottom:var(--sp-5)}
.kemaj__icon{width:56px;height:56px}
.kemaj__t{font-weight:var(--fw-black);color:var(--brand-text);margin-bottom:6px}
.kemaj__b .bar{margin-bottom:6px}
.kemaj__p{font-size:var(--fs-28);font-weight:var(--fw-black);color:var(--brand-text)}
.newletters{background:linear-gradient(180deg,var(--sky-100),var(--surface))}
.ltiles{display:flex;gap:var(--sp-3);flex-wrap:wrap;margin:var(--sp-3) 0}
.ltile{display:flex;flex-direction:column;align-items:center;gap:4px;min-width:92px;padding:var(--sp-3);
  background:var(--surface);border:2px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-sm)}
.ltile__g{font-size:var(--fs-42);line-height:1.1;color:var(--brand-text)}
.ltile__s{font-weight:var(--fw-black);color:var(--ink)}
.timeline{list-style:none;margin:var(--sp-3) 0 0;padding:0}
.tl{position:relative;display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--sp-4);padding-bottom:var(--sp-3)}
.tl::before{content:"";position:absolute;left:17px;top:36px;bottom:0;border-left:2px dashed var(--navy-200)}
.tl:last-child::before{display:none}
.tl__dot{width:36px;height:36px;border-radius:50%;background:var(--gray-100);border:2px solid var(--line-2);
  display:flex;align-items:center;justify-content:center;font-weight:var(--fw-black);color:var(--ink-3);z-index:1}
.tl.is-done .tl__dot{background:var(--ok);border-color:var(--ok);color:#fff}
.tl.is-current .tl__dot{background:var(--brand);border-color:var(--brand);color:#fff}
.tl__card{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto auto;align-items:center;gap:var(--sp-3);
  padding:var(--sp-3) var(--sp-4);border:1px solid var(--line);border-radius:var(--r-lg);background:var(--surface);
  text-decoration:none;color:var(--ink)}
.tl__card:hover{border-color:var(--teal-300);background:var(--brand-soft)}
.tl.is-current .tl__card{border-color:var(--brand);box-shadow:var(--sh-sm)}
.tl__badge{background:var(--green-500);color:#fff;border-radius:var(--r-pill);padding:2px 10px;font-weight:var(--fw-black);font-size:var(--fs-13)}
.tl.is-current .tl__badge{background:var(--brand)}
.tl__b{display:flex;flex-direction:column;gap:2px;min-width:0}
.tl__t{font-weight:var(--fw-bold)}
.tl__stars{color:var(--accent);white-space:nowrap}
.tl__go{color:var(--ink-3);font-size:var(--fs-24)}

/* ── 획 조합 (Screen 12) ── */
.how{position:relative;background:linear-gradient(180deg,var(--sky-100),var(--surface));padding-top:var(--sp-8)}
.how__tag{position:absolute;top:var(--sp-4);left:var(--sp-5)}
.how__rows{display:flex;flex-direction:column;gap:var(--sp-3)}
.how__row{display:grid;grid-template-columns:auto auto auto minmax(0,1fr);align-items:center;gap:var(--sp-4);
  background:var(--surface);border-radius:var(--r-lg);padding:var(--sp-3) var(--sp-4)}
.how__keys{display:inline-flex;align-items:center;gap:6px}
.how__plus{color:var(--ink-3);font-weight:var(--fw-black)}
.how__arrow{color:var(--brand);font-size:var(--fs-24);font-weight:var(--fw-black)}
.how__out{display:flex;align-items:center;justify-content:center;width:56px;height:56px;border-radius:var(--r-md);
  background:var(--brand-soft);border:2px solid var(--teal-300);font-size:var(--fs-34);color:var(--brand-text)}
.how__text{display:flex;flex-direction:column;gap:2px;min-width:0}
.queue{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:var(--sp-3)}
.qtile{padding:8px 12px;border:2px solid var(--line);border-radius:var(--r-md);background:var(--cream-100);font-size:var(--fs-20)}
.qtile.is-done{background:var(--ok-soft);border-color:var(--ok);color:var(--green-700)}
.qtile.is-cur{background:#fff;border-color:var(--sky-500);box-shadow:0 0 0 3px rgba(30,136,229,.2)}
.qarrow{color:var(--ink-3)}
.combo-keys{display:flex;gap:6px;flex-wrap:wrap;justify-content:center;margin:var(--sp-3) 0}
.ckey{min-width:38px;padding:6px 10px;border:2px solid var(--navy-200);border-bottom-width:4px;border-radius:8px;
  background:#fff;font-family:var(--font-mono);font-weight:700;text-align:center;color:var(--ink-3)}
.ckey.is-done{background:var(--ok-soft);border-color:var(--ok);color:var(--green-700)}
.ckey.is-cur{border-color:var(--sky-500);color:var(--ink);box-shadow:0 0 0 3px rgba(30,136,229,.2)}

/* ── 속도 테스트·진행 (Screen 13·15) ── */
.bar--time{margin:var(--sp-4) 0 0;height:8px}
.levels{display:flex;flex-direction:column;gap:var(--sp-3);margin-top:var(--sp-3)}
.lvrow{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--sp-4);
  padding:var(--sp-3);border:1px solid var(--line);border-radius:var(--r-lg)}
.lvrow.is-current{border-color:var(--brand);background:var(--brand-soft)}
.lvrow.is-done{border-color:var(--ok);background:var(--ok-soft)}
.lvrow__t{font-weight:var(--fw-bold);margin-bottom:6px}
.lvrow__b .bar{margin-bottom:6px}
.lvrow__p{font-size:var(--fs-20);font-weight:var(--fw-black);color:var(--brand-text);font-variant-numeric:tabular-nums}

/* ── 손 도해 (어느 손가락으로 누르는가) ── */
/* 자판 위에 겹치는 손 (handoverlay.js) — samples/ 참고 이미지 설계.
   손이 키를 가리면 안 되므로 반투명하게 두고, 눌러야 할 손가락만 진하게 만든다. */
.kb-stage{position:relative;display:inline-block}
.hov{position:absolute;left:0;top:0;pointer-events:none;overflow:visible}
.hov__palms{filter:drop-shadow(0 3px 6px rgba(18,50,92,.13))}
.hov__palm{fill:#F7FAFB;stroke:var(--navy-200);stroke-width:1.4;opacity:.94}
.hov__finger{fill:var(--gray-100);stroke:var(--navy-200);stroke-width:1.2;opacity:.86;
  transition:opacity var(--dur-fast),fill var(--dur-fast),stroke var(--dur-fast)}
.hov__tip{fill:none;stroke:var(--gray-400);stroke-width:1.8;opacity:.3;
  transition:stroke var(--dur-fast),opacity var(--dur-fast),stroke-width var(--dur-fast)}
.hov__badge{fill:#fff;stroke:var(--navy-200);stroke-width:1.2;opacity:.9;
  transition:fill var(--dur-fast),stroke var(--dur-fast)}
.hov__num{fill:var(--navy-700);opacity:.85;font-weight:800;pointer-events:none;
  transition:fill var(--dur-fast),opacity var(--dur-fast)}
.hov__f--f1 .hov__finger{fill:#FDECEC;stroke:#E88F8F} .hov__f--f2 .hov__finger{fill:#FDF0E2;stroke:#E0B36B}
.hov__f--f3 .hov__finger{fill:#FDF7DC;stroke:#DCC65C} .hov__f--f4 .hov__finger{fill:#E8F6EC;stroke:#7FC796}
.hov__f--f5 .hov__finger{fill:#E4F5F7;stroke:#6EC8D4} .hov__f--f6 .hov__finger{fill:#EEF6FB;stroke:#9FC8E2}
.hov__f--f7 .hov__finger{fill:#F1ECFA;stroke:#B0A0DE} .hov__f--f8 .hov__finger{fill:#FBECF6;stroke:#DB9FC8}
/* 엄지는 손등과 같은 색이다 — 다른 색을 주면 손 위에 얹힌 조각처럼 보인다.
   스페이스를 누를 때만 다른 손가락처럼 밝아진다. */
.hov__f--th .hov__finger{fill:#F7FAFB;stroke:var(--navy-200)}
/* 지금 눌러야 할 손가락 */
.hov__f.is-on .hov__finger{opacity:.82;fill:#BFEAF0;stroke-width:2.4;stroke:var(--teal-900);
  filter:drop-shadow(0 2px 7px rgba(3,145,164,.45))}
.hov__f.is-on .hov__tip{stroke:var(--brand);stroke-width:3.4;opacity:1}
.hov__f.is-on .hov__badge{fill:var(--brand);stroke:var(--teal-900)}
.hov__f.is-on .hov__num{fill:#fff;opacity:1}
/* 시프트를 함께 누르는 반대쪽 새끼손가락 */
.hov__f.is-shift .hov__finger{opacity:.82;fill:#FBE3B4;stroke-width:2.4;stroke:var(--amber-700);
  filter:drop-shadow(0 2px 7px rgba(214,158,46,.45))}
.hov__f.is-shift .hov__tip{stroke:var(--amber-700);stroke-width:3.4;opacity:1}
.hov__f.is-shift .hov__badge{fill:var(--accent);stroke:var(--amber-700)}
.hov__f.is-shift .hov__num{fill:var(--navy-900);opacity:1}
@media (prefers-reduced-motion:reduce){.hov__finger,.hov__tip,.hov__num{transition:none}}
.hands{display:flex;align-items:flex-end;justify-content:center;gap:var(--sp-6);flex-wrap:wrap}
.hand{width:150px;height:auto;overflow:visible}
.hand--l{transform:scaleX(-1)}
.hand__palm{fill:var(--gray-100);stroke:var(--navy-200);stroke-width:2}
.fg__r{fill:var(--gray-50);stroke:var(--navy-200);stroke-width:2;transition:fill var(--dur-fast),stroke var(--dur-fast)}
.hand__k{font-family:var(--font-mono);font-size:15px;font-weight:700;fill:var(--ink-3)}
.hand--l .hand__k{transform:scaleX(-1);transform-origin:center;transform-box:fill-box}
.fg--f1 .fg__r{fill:#FDECEC;stroke:#F2B8B8} .fg--f2 .fg__r{fill:#FDF0E2;stroke:#F0CFA0}
.fg--f3 .fg__r{fill:#FDF7DC;stroke:#EBD98A} .fg--f4 .fg__r{fill:#E8F6EC;stroke:#A8DCB8}
.fg--f5 .fg__r{fill:#E4F5F7;stroke:#9EDCE4} .fg--f6 .fg__r{fill:#EEF6FB;stroke:#CFE4F1}
.fg--f7 .fg__r{fill:#F1ECFA;stroke:#CFC2EB} .fg--f8 .fg__r{fill:#FBECF6;stroke:#E9BEDD}
.fg--th .fg__r{fill:var(--gray-200);stroke:var(--gray-300)}
.fg.is-on .fg__r{fill:var(--brand);stroke:var(--teal-900);stroke-width:3;filter:drop-shadow(0 0 8px rgba(3,145,164,.55))}
.fg.is-on .hand__k{fill:#fff}
.fg.is-shift .fg__r{fill:var(--accent);stroke:var(--amber-700);stroke-width:3}
.fg.is-shift .hand__k{fill:var(--navy-900)}
.hands__cap{width:100%;text-align:center;margin:var(--sp-2) 0 0;font-weight:var(--fw-black);color:var(--brand-text);min-height:1.4em}
.hands--sm .hand{width:96px}
.hands--sm .hands__cap{font-size:var(--fs-13)}

/* ── 손가락·자판 안내 (Screen 06·16) ── */
.key--zone{--kh:52px}
.key--f1{background:#FDECEC;border-color:#F2B8B8} .key--f2{background:#FDF0E2;border-color:#F0CFA0}
.key--f3{background:#FDF7DC;border-color:#EBD98A} .key--f4{background:#E8F6EC;border-color:#A8DCB8}
.key--f5{background:#E4F5F7;border-color:#9EDCE4} .key--f6{background:#EEF6FB;border-color:#CFE4F1}
.key--f7{background:#F1ECFA;border-color:#CFC2EB} .key--f8{background:#FBECF6;border-color:#E9BEDD}
.key--none{background:var(--gray-100)}
.key--zone.is-home{box-shadow:inset 0 -4px 0 var(--brand),var(--sh-key)}
.key--zone.is-home::after{content:"·";position:absolute;bottom:0;left:50%;transform:translateX(-50%);
  color:var(--brand);font-weight:900;font-size:20px;line-height:1}
.legend{display:flex;flex-wrap:wrap;gap:var(--sp-3) var(--sp-5);margin-top:var(--sp-4)}
.legend--sm{gap:var(--sp-2) var(--sp-4)}
.lg{display:inline-flex;align-items:center;gap:8px;font-size:var(--fs-14);font-weight:var(--fw-bold);color:var(--ink-2)}
.lg .t-small{color:var(--ink-3);font-family:var(--font-mono)}
.sw{width:18px;height:18px;border-radius:5px;border:2px solid var(--line-2);flex:none}
.sw--f1{background:#FDECEC;border-color:#F2B8B8} .sw--f2{background:#FDF0E2;border-color:#F0CFA0}
.sw--f3{background:#FDF7DC;border-color:#EBD98A} .sw--f4{background:#E8F6EC;border-color:#A8DCB8}
.sw--f5{background:#E4F5F7;border-color:#9EDCE4} .sw--f6{background:#EEF6FB;border-color:#CFE4F1}
.sw--f7{background:#F1ECFA;border-color:#CFC2EB} .sw--f8{background:#FBECF6;border-color:#E9BEDD}
.sw--l{background:var(--jamo-l-soft);border-color:var(--jamo-l)} .sw--b{background:var(--jamo-b-soft);border-color:var(--jamo-b)}
.sw--q{background:var(--jamo-q-soft);border-color:var(--jamo-q)} .sw--vowel{background:var(--key-vowel);border-color:var(--key-vowel-line)}
.sw--moved{background:var(--surface);border-style:dashed} .sw--unused{background:var(--key-unused)}
.combos{display:flex;flex-wrap:wrap;gap:var(--sp-3);margin:var(--sp-3) 0 var(--sp-5)}
.combo{display:inline-flex;align-items:center;gap:8px;padding:var(--sp-2) var(--sp-4);border:2px solid var(--line);
  border-radius:var(--r-pill);background:var(--surface)}
.combo.is-proposed{border-style:dashed;border-color:var(--amber-500);background:var(--amber-100)}
.combo__op{color:var(--ink-3);font-weight:var(--fw-black)}
.combo__out{font-size:var(--fs-24);color:var(--brand-text)}
.drill{text-align:center;padding:var(--sp-4) 0}
.drill__q{display:flex;flex-direction:column;align-items:center;gap:var(--sp-2)}
.drill__glyph{font-size:96px;line-height:1.1;color:var(--brand-text)}
#drill-fb{min-height:1.5em}
#drill-fb .ok{color:var(--green-700);font-weight:var(--fw-black)}
#drill-fb .bad{color:var(--red-700);font-weight:var(--fw-black)}

/* ── 프로필 (K-3 · 목업 Screen 02) ── */
.who{display:inline-flex;align-items:center;gap:8px;height:40px;padding:0 14px 0 6px;border:2px solid var(--line);
  border-radius:var(--r-pill);background:var(--surface);font-weight:var(--fw-bold);color:var(--ink);
  text-decoration:none;white-space:nowrap;flex:none}
.who:hover{border-color:var(--teal-300)}
.pdot{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:50%;
  font-weight:var(--fw-black);font-size:var(--fs-14);color:#fff;flex:none}
.pdot--teal{background:var(--teal-500)} .pdot--rose{background:var(--orange-500)} .pdot--violet{background:var(--violet-500)}
.pdot--amber{background:var(--amber-500)} .pdot--green{background:var(--green-500)} .pdot--sky{background:var(--sky-500)}
.kindbar{margin-bottom:var(--sp-5)}
.profiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:var(--sp-4);margin-bottom:var(--sp-6)}
.pcard{position:relative;display:flex;flex-direction:column;align-items:center;gap:6px;padding:var(--sp-6) var(--sp-4);
  border:2px solid var(--line);border-radius:var(--r-2xl);background:var(--surface);cursor:pointer;font:inherit;
  box-shadow:var(--sh-sm)}
.pcard:hover{transform:translateY(-2px);box-shadow:var(--sh-md)}
.pcard.is-active{border-color:var(--brand);box-shadow:0 0 0 4px var(--brand-soft),var(--sh-md)}
.pcard--teal{background:var(--teal-100)} .pcard--rose{background:#FDECE6} .pcard--violet{background:var(--violet-100)}
.pcard--amber{background:var(--amber-100)} .pcard--green{background:var(--green-100)} .pcard--sky{background:var(--sky-100)}
.pcard--new{border-style:dashed;background:var(--surface-2)}
.pcard__av{display:flex;align-items:center;justify-content:center;width:88px;height:88px;border-radius:50%;
  background:#fff;border:4px solid rgba(255,255,255,.85);box-shadow:var(--sh-sm);
  font-size:var(--fs-42);font-weight:var(--fw-black);color:var(--brand-text)}
.pcard__name{font-size:var(--fs-20);font-weight:var(--fw-black);color:var(--ink)}
.pcard__lv{font-size:var(--fs-14);font-weight:var(--fw-bold);color:var(--brand-text)}
.pcard__streak{font-size:var(--fs-13);color:var(--ink-2)}
.pcard__badge{position:absolute;top:10px;right:12px;min-width:28px;height:28px;border-radius:50%;background:var(--surface);
  border:2px solid var(--accent);color:var(--accent-text);font-weight:var(--fw-black);font-size:var(--fs-13);
  display:flex;align-items:center;justify-content:center}
.nowrap{white-space:nowrap}

/* ── 수료 인증서 (T-1) ── */
.form{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:var(--sp-3);margin:var(--sp-4) 0}
.form label{display:flex;flex-direction:column;gap:4px;font-weight:var(--fw-bold);color:var(--ink-2)}
.form__wide{grid-column:1/-1}
.warn-note{color:var(--amber-700);font-weight:var(--fw-bold)}
.crit{margin-top:var(--sp-4)} .crit summary{cursor:pointer}
#check .ok{color:var(--green-700);font-weight:var(--fw-black)}
#check .bad{color:var(--red-700);font-weight:var(--fw-black)}

.sert{max-width:1000px;margin:var(--sp-6) auto 0}
.sert__frame{position:relative;overflow:hidden;background:var(--surface);border:3px solid var(--brand);
  border-radius:var(--r-2xl);padding:var(--sp-10) var(--sp-12) var(--sp-8);box-shadow:var(--sh-lg);
  background-image:linear-gradient(180deg,var(--cream-50),#fff 30%)}
.sert__frame::before{content:"";position:absolute;inset:10px;border:1px solid var(--teal-300);border-radius:var(--r-xl);pointer-events:none}
.sert__head{display:flex;align-items:center;gap:var(--sp-5);margin-bottom:var(--sp-8)}
.sert__logo{width:110px;height:auto;flex:none}
.sert__kicker{margin:0;font-size:var(--fs-13);font-weight:var(--fw-black);letter-spacing:var(--ls-caps);
  text-transform:uppercase;color:var(--brand-text)}
.sert__title{margin:2px 0 4px;font-size:var(--fs-28);font-weight:var(--fw-black);color:var(--ink)}
.sert__sub{margin:0;color:var(--ink-2);font-size:var(--fs-14)}
.sert__lead{margin:0;color:var(--ink-2);text-align:center}
.sert__name{margin:var(--sp-2) 0 var(--sp-4);text-align:center;font-size:var(--fs-52);font-weight:var(--fw-black);
  color:var(--brand-text);line-height:1.15;word-break:keep-all}
.sert__body{margin:0 auto var(--sp-6);max-width:62ch;text-align:center;line-height:var(--lh-loose)}
.sert__stats{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-3);margin-bottom:var(--sp-8)}
.sert__stat{text-align:center;background:var(--surface-2);border-radius:var(--r-md);padding:var(--sp-3)}
.sert__k{display:block;font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--ink-3);
  letter-spacing:var(--ls-caps);text-transform:uppercase}
.sert__v{display:block;font-size:var(--fs-24);font-weight:var(--fw-black);color:var(--ink);font-variant-numeric:tabular-nums}
.sert__foot{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--sp-6)}
.sert__sign{flex:1;min-width:0;padding-bottom:var(--sp-2)}
.sert__line{height:0;border-top:2px solid var(--ink-3);max-width:280px;margin-bottom:6px}
.sert__issuer{margin:0;font-weight:var(--fw-black)}
.sert__sponsor{margin:2px 0 0;color:var(--ink-2);font-size:var(--fs-14)}
.sert__qr{text-align:center;flex:none}
.sert__qr canvas{width:150px;height:150px;image-rendering:pixelated}
.sert__no{margin:4px 0 0;font-family:var(--font-mono);font-weight:700;font-size:var(--fs-14)}
.sert__qrnote{margin:2px 0 0;font-size:var(--fs-11);color:var(--ink-3);max-width:180px}
.sert__island{position:absolute;left:24px;bottom:12px;width:150px;height:auto;opacity:.22;pointer-events:none;z-index:0}
.sert__foot{position:relative;z-index:1}

/* 수료증 인쇄 — **A4 한 장에 정확히** 담아야 한다.
   화면용 간격 그대로 두면 액자가 한 장보다 길어져 발급처·QR 이 둘째 장으로 넘어갔다(2026-08-29).
   높이를 인쇄 영역에 못박고, 남는 자리는 아래쪽(sert__foot)이 흡수하게 한다. */
@media print{
  @page{size:A4 landscape;margin:10mm}
  /* `#app>.card` 를 여기서 숨기지 않는다. 수료증 화면만 생각하고 넣은 규칙이었는데,
     내용이 카드로 이루어진 다른 화면(자판 배열표 `papan.html`, 교사 화면 `guru.html`)은
     인쇄하면 **빈 종이**가 나왔다. 숨길 것은 각 화면이 `.noprint` 로 직접 표시한다 —
     수료증 화면의 입력 카드에는 이미 붙어 있다. */
  .noprint,.top,.side,.tabbar,.subnav,.toast-anchor{display:none!important}
  /* 셸은 화면용 고정 틀이다(`body.has-shell{height:100vh;overflow:hidden}`). 인쇄에서 그대로
     두면 100vh 가 종이가 아니라 화면 높이로 잡혀 문서가 0.5mm 남고, 그 반 밀리미터가
     **빈 둘째 장**이 된다. 인쇄에서는 틀을 푼다. */
  html,body{background:#fff;height:auto;min-height:0;overflow:visible}
  body.has-shell,body.has-side{height:auto;overflow:visible;display:block}
  .main,main{height:auto;min-height:0;overflow:visible}
  #app{padding:0;max-width:none}
  /* `#app > * + *{margin-top:var(--sp-5)}` (카드 사이 간격)이 **특이도가 더 높아** 이 줄을
     이겼다. 그 20px 이 그대로 남아 190mm 액자가 190mm 인쇄 영역을 5.3mm 넘겼고, 수료증이
     두 장으로 나왔다. 인쇄에서는 카드 간격 규칙 자체가 필요 없으므로 통째로 지운다. */
  #app > *{margin-top:0}
  #app > .sert{margin:0;max-width:none}
  .sert__frame{
    box-shadow:none;border-width:2px;padding:9mm 12mm;
    height:190mm;                       /* A4 가로 210mm − 위아래 여백 10mm */
    display:flex;flex-direction:column;
    break-inside:avoid;page-break-inside:avoid;
  }
  .sert__frame::before{inset:5px}
  .sert__head{margin-bottom:5mm}
  .sert__logo{width:88px}
  .sert__name{font-size:34pt;margin:2mm 0 3mm}
  .sert__body{margin-bottom:4mm}
  .sert__stats{margin-bottom:5mm}
  .sert__foot{margin-top:auto}          /* 남는 세로 공간을 흡수해 바닥에 붙는다 */
  .sert__qr canvas{width:96px;height:96px}
  /* 장식 섬이 발급처 글자 뒤에 깔려 읽기 어려워진다 — 확인하는 사람이 보는 부분이라 인쇄에선 뺀다 */
  .sert__island{display:none}
}

/* ── 교사 대시보드 (목업 Screen 21 / K-1) ── */
/* 교사 화면(guru·ekspor)도 앱 틀과 같게: 왼쪽 기둥·머리말 고정, 안쪽만 스크롤 */
body.has-side{display:grid;grid-template-columns:248px minmax(0,1fr);height:100vh;overflow:hidden}
body.has-side > .main{min-height:0;overflow:hidden}
body.has-side > .main > .top{flex:none}
body.has-side > .main > main{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain}
/* `#app` 은 `max-width` + `margin:0 auto` 로 가운데를 잡는데, 셸이 그것을 **세로 flex 의 항목**으로
   만들면서 그 auto 여백이 `stretch` 를 눌러 버렸다. 그러면 칸이 내용 최대 너비로 쪼그라든다
   (긴 글이 있는 쪽은 우연히 넓어 보였고, 게임처럼 격자만 있는 쪽에서 349px 로 줄었다).
   `width:100%` 를 주면 늘어난 뒤 `max-width` 가 잡고 auto 여백이 가운데로 놓는다. */
body.has-side > .main > main,body.has-shell > .main > main{width:100%}
.side{background:var(--surface);border-right:1px solid var(--line);padding:var(--sp-5) var(--sp-4);
  display:flex;flex-direction:column;gap:var(--sp-5);position:sticky;top:0;height:100vh;overflow:hidden}
.side__brand img{width:150px;height:auto;display:block}
.side__nav{display:flex;flex-direction:column;gap:4px}
.side__item{display:flex;align-items:center;gap:var(--sp-3);padding:12px 14px;border:0;border-radius:var(--r-md);
  background:none;font:inherit;font-weight:var(--fw-bold);color:var(--ink-2);cursor:pointer;text-align:left}
.side__item:hover{background:var(--brand-soft)}
.side__item.is-active{background:var(--brand);color:#fff}
.side__note{margin-top:auto;background:var(--sky-100);border-radius:var(--r-lg);padding:var(--sp-3);text-align:center}
.side__note img{width:100%;height:auto;margin-bottom:var(--sp-2)}
.side__note p{margin:0;color:var(--brand-text)}
/* 목업 데스크톱-16x9 왼쪽 기둥 맨 아래 장식. 사이드바 좌우 여백을 무시하고 끝까지 채운다. */
.side__art{display:block;width:calc(100% + var(--sp-4) * 2);max-width:none;height:auto;flex:none;
  margin:var(--sp-3) calc(var(--sp-4) * -1) calc(var(--sp-5) * -1);pointer-events:none;
  /* 화면이 낮으면 목업처럼 아래가 잘려 나간다(.side 가 overflow:hidden). 잎사귀가 잘리는 건 의도한 모습이다.
     다만 마스코트 얼굴까지 밀리지 않도록 여백 카드를 먼저 줄인다. */
  align-self:flex-end}
/* 인용 카드는 위의 1100px 이상 규칙에서 다룬다(높이 1000px 이하면 감춘다).
   좁은 화면에서는 `.side` 가 가로로 눕고 카드와 마스코트가 모두 빠진다. */
.main{min-width:0;display:flex;flex-direction:column}
.main #app{max-width:1180px}
.greet--slim{align-items:center;margin-bottom:var(--sp-4)}
.greet--slim .mascot{width:120px}
.greet--slim .bubble{margin-bottom:var(--sp-4);font-size:var(--fs-14)}
.import{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-5);flex-wrap:wrap;margin-bottom:var(--sp-5);
  border-left:5px solid var(--info)}
.import h2{margin:0 0 var(--sp-2)} .import p{margin:0;max-width:70ch}
.import__act{display:flex;gap:var(--sp-2);flex-wrap:wrap;align-items:center}
.import label.btn{cursor:pointer}
.statcards--5{grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.grid2{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);gap:var(--sp-4);margin-top:var(--sp-4)}
.tablewrap{overflow-x:auto}
.tbl{width:100%;border-collapse:collapse;font-size:var(--fs-14)}
.tbl th{text-align:left;font-size:var(--fs-12);letter-spacing:var(--ls-caps);text-transform:uppercase;color:var(--ink-3);
  padding:0 var(--sp-3) var(--sp-2);border-bottom:1px solid var(--line);white-space:nowrap}
.tbl td{padding:var(--sp-3);border-bottom:1px solid var(--line);vertical-align:middle}
.tbl tr:last-child td{border-bottom:0}
.tbl__name{display:flex;align-items:center;gap:var(--sp-2);font-weight:var(--fw-bold);white-space:nowrap}
.tbl__name img{width:34px;height:34px;border-radius:50%;border:2px solid var(--accent);object-fit:cover}
.mini{display:flex;align-items:center;gap:8px}
.mini__bar{display:inline-block;width:76px;height:8px;border-radius:var(--r-pill);background:var(--gray-200);overflow:hidden}
.mini__bar i{display:block;height:100%;background:var(--brand)}
.chart{display:flex;align-items:flex-end;gap:var(--sp-3);height:180px;margin:var(--sp-4) 0 var(--sp-2)}
.chart__col{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;height:100%;gap:4px}
.chart__bar{width:60%;min-height:4px;border-radius:6px 6px 0 0;background:var(--brand)}
.chart__n{font-size:var(--fs-13);font-weight:var(--fw-black);color:var(--ink-2)}
.chart__d{font-size:var(--fs-12);color:var(--ink-3)}
@media (max-width:960px){body.has-side{grid-template-columns:1fr;height:auto;overflow:visible}body.has-side > .main,body.has-side > .main > main{overflow:visible;min-height:0}.side{position:static;height:auto;flex-direction:row;align-items:center;overflow-x:auto}
  .side__note,.side__art{display:none}.side__nav{flex-direction:row}.grid2{grid-template-columns:1fr}}

/* ── 목업 자리표시 요소 (기능 미구현) ── */
.soon{position:relative}
.soon::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none}
/* 언어 고르개. 예전에는 설정 쪽으로 가는 링크를 `cursor:default;opacity:.75` 로 꺼진 것처럼
   칠해 두었는데, `▾` 는 차림표를 약속하므로 눌러도 안 바뀐다는 신고가 나왔다(2026-08-30).
   이제 `<details>` 다 — 만드는 곳은 `i18n.js` 의 `mountLangChip()` 한 곳뿐이다. */
.lang{position:relative;display:inline-block}
.lang__sum{display:inline-flex;align-items:center;gap:6px;height:40px;padding:0 14px;
  border:2px solid var(--line);border-radius:var(--r-pill);background:var(--surface);
  font-weight:var(--fw-bold);color:var(--ink);font-size:var(--fs-14);white-space:nowrap;
  cursor:pointer;list-style:none;user-select:none}
.lang__sum::-webkit-details-marker{display:none}
.lang__sum:hover{border-color:var(--brand-soft);background:var(--surface-2)}
.lang[open] .lang__sum{border-color:var(--brand);color:var(--brand-text)}
.lang__v{color:var(--ink-3);font-size:var(--fs-12)}
.lang__menu{position:absolute;right:0;top:calc(100% + 6px);z-index:60;min-width:236px;
  padding:var(--sp-2);display:flex;flex-direction:column;gap:2px;box-shadow:var(--sh-lg)}
.lang__head{margin:var(--sp-1) var(--sp-2) var(--sp-2);color:var(--ink-2)}
.lang__opt{display:flex;align-items:center;gap:var(--sp-2);width:100%;padding:10px 12px;
  border:0;border-radius:var(--r-sm);background:transparent;font:inherit;font-size:var(--fs-14);
  font-weight:var(--fw-bold);text-align:left;color:var(--ink);cursor:pointer;text-decoration:none}
.lang__opt:hover{background:var(--surface-2)}
.lang__opt.is-on{background:var(--brand-soft);color:var(--brand-text)}
.lang__opt--link{font-weight:var(--fw-regular);color:var(--ink-2);border-top:1px solid var(--line);
  border-radius:0 0 var(--r-sm) var(--r-sm);margin-top:var(--sp-1);padding-top:12px}
.lang__tick{margin-left:auto;color:var(--brand)}
.lang__flag{font-size:18px;line-height:1}
/* `index.html`·`guru.html` 은 칩을 손으로 적어 두었다. `mountLangChip()` 이 곧 `<details>` 로
   바꾸지만, 그 사이 한 프레임 동안은 이 모습이어야 민둥한 글씨로 번쩍이지 않는다. */
a.lang{display:inline-flex;align-items:center;gap:6px;height:40px;padding:0 14px;
  border:2px solid var(--line);border-radius:var(--r-pill);background:var(--surface);
  font-weight:var(--fw-bold);color:var(--ink);font-size:var(--fs-14);white-space:nowrap;
  text-decoration:none}
@media (max-width:560px){ .lang__menu{right:auto;left:0} }
.iconbtn{position:relative;width:40px;height:40px;border-radius:50%;border:2px solid var(--line);background:var(--surface);
  font-size:18px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;flex:none}
.iconbtn--sm{width:28px;height:28px;font-size:14px;border-width:1px}
.iconbtn__badge{position:absolute;top:-4px;right:-4px;min-width:20px;height:20px;border-radius:var(--r-pill);
  background:var(--err);color:#fff;font-size:11px;font-weight:var(--fw-black);display:flex;align-items:center;justify-content:center;padding:0 5px}
.avatar{width:44px;height:44px;border-radius:50%;border:3px solid var(--accent);background:var(--amber-100);
  padding:0;overflow:hidden;cursor:pointer;flex:none}
.avatar img{width:100%;height:100%;object-fit:cover;display:block}
button.soon,.lang.soon{opacity:.65}
button.soon:hover,.lang.soon:hover{opacity:1}

/* 연습 화면 장면 카드 (목업 Screen 09) */
.scene{position:relative;overflow:hidden;border-radius:var(--r-xl);padding:var(--sp-5) var(--sp-6) 104px;
  background:linear-gradient(180deg,var(--sky-100) 0%,var(--sky-100) 55%,var(--teal-100) 100%);
  text-align:center;margin-bottom:var(--sp-4);min-height:230px}
.scene__listen{position:relative;z-index:3;display:inline-flex;margin:0 auto var(--sp-4)}
.scene__listenwrap{position:relative;z-index:3}
.scene .target{position:relative;z-index:3;text-align:center;display:inline-block;max-width:100%;
  background:var(--surface);border:2px solid #fff;border-radius:var(--r-lg);padding:var(--sp-3) var(--sp-6);
  box-shadow:var(--sh-sm)}
.scene .target .seg{background:none!important;box-shadow:none!important;text-decoration:none!important}
.scene .target .seg.pending{color:var(--ink-2)}
.scene__say{position:relative;z-index:3;display:flex;align-items:center;justify-content:center;gap:8px;
  margin-top:var(--sp-3);color:var(--ink-2);font-size:var(--fs-18)}
.scene__island{position:absolute;left:50%;bottom:0;transform:translateX(-50%);width:min(64%,300px);height:auto;opacity:.85;z-index:1}
.scene__leaf{display:none}   /* 자산 추출 품질이 나빠 쓰지 않는다 (04-디자인/자산 INDEX.md 경고) */
.scene::before{content:"";position:absolute;left:0;right:0;bottom:0;height:58px;z-index:0;
  background:radial-gradient(120% 100% at 50% 100%, var(--teal-100) 0%, transparent 70%)}
.scene--plain{background:none;padding:0;text-align:left;margin-bottom:0;min-height:0}
.scene--plain::before{display:none}
.scene--plain .target{text-align:left;display:block;background:none;border:0;padding:0;box-shadow:none}
.scene--plain .target .seg{background:revert!important;box-shadow:revert!important;text-decoration:revert!important}
.scene--plain .scene__island,.scene--plain .scene__leaf,.scene--plain .scene__listen,.scene--plain .scene__say{display:none}

/* ── 브랜드·홈 (목업 Screen 03) ── */
.top{gap:var(--sp-3);padding:var(--sp-2) var(--sp-5);flex-wrap:nowrap}
.top__brand{text-decoration:none;flex:none;display:flex;align-items:center;gap:var(--sp-3)}
.top__logo{height:42px;width:85px;flex:none;object-fit:contain}
.top__sub{white-space:nowrap;font-size:var(--fs-16)}
.top__tools{flex:1;justify-content:flex-end;gap:var(--sp-2);flex-wrap:nowrap;overflow-x:auto}
/* 도구 줄은 좁은 화면에서 도구가 넘칠 때 가로로 구른다(`overflow-x:auto`). 그런데 한 축이 auto 면
   나머지 축의 `visible` 도 auto 가 되므로 **세로도 잘린다** — 높이 40px 짜리 줄 안에서 182px·371px
   짜리 차림표(언어 칩·톱니바퀴)가 통째로 잘려 나갔다. 눌러도 아무 일이 없어 보여 «언어를 바꿀 수
   없다»는 신고가 나왔다(2026-08-30). 차림표만 화면 기준 `fixed` 로 꺼내 잘리는 틀을 빠져나온다.
   자리는 `shell.js` 의 `mountTopMenus()` 가 잡는다 — 사용자 지정 속성이 없으면 머리말 오른쪽 아래에
   떨어지므로, 자리잡기가 못 돌아도 차림표는 보인다. */
.top__tools .lang__menu,.top__tools .settings__menu{position:fixed;
  top:var(--menu-top,60px);left:var(--menu-left,auto);right:var(--menu-right,12px)}
.settings{position:relative;flex:none}
.settings>summary{list-style:none;cursor:pointer;font-size:var(--fs-18)}
.settings>summary::-webkit-details-marker{display:none}
.settings__menu{position:absolute;right:0;top:calc(100% + 8px);width:290px;z-index:var(--z-sheet);
  display:flex;flex-direction:column;gap:var(--sp-3);padding:var(--sp-4)}
.settings__menu h3{margin:0}
.greet{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:var(--sp-4);margin-bottom:var(--sp-6)}
.greet__text h1{margin:0 0 var(--sp-1)}
.greet__text p{margin:0 0 var(--sp-1)}
.greet__mascot{display:flex;align-items:flex-end;gap:var(--sp-2)}
.mascot{width:150px;height:auto;flex:none}
.mascot--lg{width:190px}
.bubble{position:relative;background:var(--surface);border:2px solid var(--teal-300);border-radius:var(--r-xl);
  padding:var(--sp-3) var(--sp-4);margin:0 0 var(--sp-6);max-width:240px;font-weight:var(--fw-bold);color:var(--brand-text)}
.bubble::after{content:"";position:absolute;right:-11px;bottom:16px;width:16px;height:16px;background:var(--surface);
  border-right:2px solid var(--teal-300);border-bottom:2px solid var(--teal-300);transform:rotate(-45deg)}

.hero-lesson{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--sp-5);align-items:center;
  background:linear-gradient(135deg,var(--sky-100),var(--teal-100));margin-bottom:var(--sp-5)}
.hero-lesson h2{margin:var(--sp-2) 0 var(--sp-1)}
.hero-lesson p{margin:0 0 var(--sp-4);color:var(--ink-2)}
.hero-lesson__art{width:64px;height:auto;opacity:.9}
.progress{margin-bottom:var(--sp-5);max-width:520px}
.progress__head{display:flex;justify-content:space-between;font-size:var(--fs-14);font-weight:var(--fw-bold);color:var(--brand-text);margin-bottom:6px}
.bar{height:12px;border-radius:var(--r-pill);background:#fff;overflow:hidden;box-shadow:inset 0 1px 3px rgba(18,50,92,.12)}
.bar__fill{height:100%;background:var(--brand);border-radius:var(--r-pill);transition:width var(--dur-slow) var(--ease)}

.statcards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--sp-3);margin-bottom:var(--sp-5)}
.statcards--4{grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.statc{display:flex;align-items:center;gap:var(--sp-3);min-width:0;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-lg);padding:var(--sp-4)}
.statc__icon{width:48px;height:48px;flex:none;border-radius:50%;padding:6px}
.statc--warm .statc__icon{background:var(--amber-100)} .statc--gold .statc__icon{background:var(--cream-200)}
.statc--cool .statc__icon{background:var(--sky-100)}
.statc__k{font-size:var(--fs-13);font-weight:var(--fw-bold);color:var(--ink-2)}
.statc__v{white-space:nowrap;font-size:var(--fs-28);font-weight:var(--fw-black);line-height:1.1;color:var(--ink);font-variant-numeric:tabular-nums}
.statc__v small{font-size:var(--fs-16);font-weight:var(--fw-bold);color:var(--ink-2)}
.statc__cap{font-size:var(--fs-13);font-weight:var(--fw-bold);color:var(--brand-text)}

.path__head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin-bottom:var(--sp-4)}
.path__head h2{margin:0}
.path__row{display:flex;gap:var(--sp-4);flex-wrap:wrap}
.node{display:flex;flex-direction:column;align-items:center;gap:4px;background:none;border:0;cursor:pointer;font:inherit;padding:0}
.node__ring{width:60px;height:60px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:var(--gray-100);border:3px solid var(--line-2);font-weight:var(--fw-black);color:var(--ink-3);font-size:var(--fs-18)}
.node.is-current .node__ring{background:var(--brand-soft);border-color:var(--brand);color:var(--brand-text)}
.node.is-done .node__ring{background:var(--ok-soft);border-color:var(--ok);color:var(--green-700)}
.node:hover .node__ring{transform:translateY(-2px)}
.node__n{font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--ink-2)}
.node__s{font-size:var(--fs-12);color:var(--accent)}

/* ── 연습 화면 (목업 Screen 09) ── */
.prac-head__sp{flex:1}
.prac-head__t{display:flex;flex-direction:column;gap:2px;min-width:0}
.prac-head__t h2{margin:0}
.prac-head__t .t-small{color:var(--ink-3)}
.prac-head .lencana{background:var(--violet-500);color:#fff;min-width:34px;height:26px;font-size:var(--fs-13)}
.tiles{display:flex;gap:var(--sp-3);flex-wrap:wrap;margin:var(--sp-4) 0;min-height:96px}
.tile{display:flex;align-items:center;justify-content:center;min-width:88px;height:96px;padding:0 8px;
  border:2px dashed var(--navy-200);border-radius:var(--r-lg);background:var(--surface-2);
  font-size:var(--fs-42);line-height:1;color:var(--ink-3);position:relative}
.tile.is-done{border-style:solid;border-color:var(--ok);background:var(--ok-soft);color:var(--green-700)}
.tile.is-done::after{content:"✓";position:absolute;right:-8px;top:-8px;width:24px;height:24px;border-radius:50%;
  background:var(--ok);color:#fff;font-size:14px;display:flex;align-items:center;justify-content:center}
.tile.is-bad{border-style:solid;border-color:var(--err);background:var(--err-soft);color:var(--red-700)}
.tile.is-cur{border-style:solid;border-color:var(--sky-500);background:#fff;color:var(--ink);box-shadow:0 0 0 4px rgba(30,136,229,.2)}
.steps3{display:flex;align-items:center;gap:var(--sp-3);margin-top:var(--sp-5);padding-top:var(--sp-4);border-top:1px solid var(--line)}
.steps3__c{display:flex;flex-direction:column;align-items:center;gap:4px;min-width:72px}
.steps3__k{font-size:var(--fs-13);font-weight:var(--fw-bold);color:var(--ink-3)}
.steps3__v{width:36px;height:36px;border-radius:50%;background:var(--gray-100);color:var(--ink-2);
  display:flex;align-items:center;justify-content:center;font-weight:var(--fw-black);font-variant-numeric:tabular-nums}
.steps3__v.is-done{background:var(--ok);color:#fff} .steps3__v.is-cur{background:var(--brand);color:#fff}
.steps3__line{flex:1;height:0;border-top:3px dotted var(--navy-200)}

/* ── 결과 화면 (목업 Screen 14) ── */
.result{max-width:900px;text-align:left}
.result__hero{display:flex;align-items:center;gap:var(--sp-5);margin-bottom:var(--sp-6);flex-wrap:wrap}
.result__hero h2{margin:0 0 var(--sp-2)}
.result__hero p{margin:0 0 var(--sp-2);color:var(--ink-2)}
.stars{display:flex;gap:4px;font-size:var(--fs-34);line-height:1}
.star{color:var(--navy-200)} .star.is-on{color:var(--accent)}
.reward{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;margin:var(--sp-4) 0 var(--sp-2)}
.reward__xp,.reward__st{display:inline-flex;align-items:center;height:34px;padding:0 14px;border-radius:var(--r-pill);
  font-weight:var(--fw-black);background:var(--brand);color:#fff}
.reward__st{background:var(--accent);color:var(--navy-900)}
.result .difficult{margin:0}
.result__btns{justify-content:flex-start}

/* ── 전자책(E-1~E-4) ── */
.book-card{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--sp-6);align-items:start;margin-bottom:var(--sp-6)}
/* 표지 그림이 오기 전(또는 못 올 때)에는 초록 바탕의 ᄙ 이 자리를 지킨다 */
.book-cover{position:relative;overflow:hidden;width:168px;height:230px;border-radius:var(--r-md);
  background:linear-gradient(160deg,var(--teal-500),var(--teal-900));
  color:#fff;font-size:86px;display:flex;align-items:center;justify-content:center;box-shadow:var(--sh-md);flex:none}
.book-cover__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
@media (max-width:720px){.book-cover{width:132px;height:181px}}
.book-meta h1{margin:0 0 var(--sp-1)}
.book-meta p{margin:0 0 var(--sp-2)}
.book-langs{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin:var(--sp-3) 0}
.toc{margin:var(--sp-3) 0 0;padding-left:1.4em}
.toc li{margin-bottom:var(--sp-2)}
.toc__item{display:flex;flex-direction:column;gap:2px;width:100%;text-align:left;background:none;border:0;padding:var(--sp-2) var(--sp-3);
  border-radius:var(--r-sm);cursor:pointer;font:inherit;color:var(--ink)}
.toc__item:hover{background:var(--brand-soft)}
.toc__item .cia{font-size:var(--fs-20)}

.reader-bar{position:sticky;top:64px;z-index:10;margin-bottom:var(--sp-4);padding:var(--sp-3) var(--sp-5)}
.reader-bar__row{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap}
.reader-bar__row+.reader-bar__row{margin-top:var(--sp-3)}
.reader-bar select{max-width:340px}
.reader-bar input[type=search]{flex:1;min-width:180px}
.reader-bar label{display:flex;align-items:center;gap:8px;color:var(--ink-2);font-weight:var(--fw-bold)}
.segbar{display:inline-flex;border:2px solid var(--line);border-radius:var(--r-pill);overflow:hidden;flex-wrap:wrap}
.segbar__btn{border:0;background:var(--surface);font:inherit;font-size:var(--fs-14);font-weight:var(--fw-bold);color:var(--ink-2);
  padding:8px 14px;cursor:pointer}
.segbar__btn+.segbar__btn{border-left:1px solid var(--line)}
.segbar__btn.is-active{background:var(--brand);color:#fff}

.reader{--read-size:26px;line-height:1.9}
.reader__head{margin-bottom:var(--sp-6);padding-bottom:var(--sp-4);border-bottom:1px solid var(--line)}
.reader__head h1{font-size:calc(var(--read-size)*1.3);margin:0 0 var(--sp-1);line-height:1.4}
.reader__head p{margin:0;color:var(--ink-2)}
.par{margin-bottom:var(--sp-5)}
.par__cia{font-family:var(--font-cia);font-size:var(--read-size);line-height:1.9;word-break:keep-all;overflow-wrap:anywhere}
.par__rom{color:var(--ink-3);font-size:calc(var(--read-size)*.58);line-height:1.6;margin-top:4px;overflow-wrap:anywhere}
.par__tr{font-size:calc(var(--read-size)*.72);line-height:1.8;margin:0 0 var(--sp-4)}
.sent{border-radius:4px;padding:0 2px}
.sent__btn{border:0;background:var(--brand-soft);border-radius:6px;cursor:pointer;color:var(--brand-text);
  font-size:calc(var(--read-size)*.5);line-height:1;padding:3px 5px;margin-left:3px;vertical-align:middle;opacity:.55}
.sent:hover .sent__btn,.sent__btn:focus-visible{opacity:1;background:var(--brand);color:#fff}
.sent__btn:hover{transform:translateY(-1px)}
.hit{background:var(--warn-soft);box-shadow:inset 0 -2px 0 var(--warn)}
.illust{margin:var(--sp-6) 0;text-align:center}
.illust img{max-width:100%;height:auto;border-radius:var(--r-md);box-shadow:var(--sh-md)}
.illust figcaption{margin-top:var(--sp-2);color:var(--ink-3)}
.par-cols{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--sp-5)}
.par-cols .cia{font-family:var(--font-cia);font-size:calc(var(--read-size)*.72);line-height:1.8}
.par-cols p{margin:0 0 var(--sp-3);font-size:calc(var(--read-size)*.6);line-height:1.7}
.reader-nav{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin-top:var(--sp-5)}

/* ── 자모표(R-1) ── */
.filters{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin:var(--sp-4) 0 var(--sp-2)}
.letters{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));gap:var(--sp-3);margin-bottom:var(--sp-6)}
.letters--sm{grid-template-columns:repeat(auto-fill,minmax(230px,1fr));margin:var(--sp-4) 0 0}
.letter{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:var(--sp-4);
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--sp-4) var(--sp-5)}
.letter.is-pending{border-style:dashed;border-color:var(--amber-500);background:var(--amber-100)}
.letter__glyph{font-size:56px;line-height:1.1;color:var(--brand-text);min-width:1.2em;text-align:center}
.letter--sm .letter__glyph{font-size:40px}
.letter__body{min-width:0}
.letter__sound{font-size:var(--fs-18);display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.letter__keys{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin:var(--sp-2) 0}
.letter__count{color:var(--ink-3)}
.letter__ex{list-style:none;padding:0;margin:var(--sp-2) 0 0}
.letter__ex li{margin-bottom:2px;overflow-wrap:anywhere}
.letter__ex .cia{font-size:var(--fs-20);margin-right:6px}
.letter__note{color:var(--ink-2);margin-top:var(--sp-2)}
.letter__audio{margin-top:var(--sp-3)}
.letter .pill{margin-top:var(--sp-2)}

/* ── 변환기(R-2) ── */
.alih__head{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;margin-bottom:var(--sp-4)}
.alih__head h1{margin:0}
.input--area{height:auto;min-height:96px;padding:var(--sp-3) var(--sp-4);width:100%;line-height:1.6;resize:vertical}
.input--area.cia{font-family:var(--font-cia);font-size:var(--fs-24)}
.editor--out{min-height:96px;margin:var(--sp-2) 0 var(--sp-3)}
.marked{padding:var(--sp-3) var(--sp-4);background:var(--surface-2);border-radius:var(--r-sm);font-family:var(--font-mono);
  font-size:var(--fs-15);line-height:2;overflow-wrap:anywhere;margin-bottom:var(--sp-3);min-height:2.4em}
.mk{border-radius:4px;padding:1px 3px}
.mk--warn{background:var(--warn-soft);box-shadow:inset 0 -2px 0 var(--warn)}
.mk--err{background:var(--err-soft);box-shadow:inset 0 -2px 0 var(--err)}
.mk--info{background:var(--info-soft);box-shadow:inset 0 -2px 0 var(--info)}
.notes{list-style:none;padding:0;margin:0}
.note{display:flex;gap:var(--sp-3);align-items:flex-start;padding:var(--sp-2) 0;border-bottom:1px solid var(--line);line-height:var(--lh-normal)}
.note .pill{flex:none}

/* ── 오류 제보(R-3) ── */
.report{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-3);margin:var(--sp-4) 0}
.report label{display:flex;flex-direction:column;gap:4px;font-weight:var(--fw-bold);color:var(--ink-2)}
.report .input{width:100%}
.report__wide{grid-column:1/-1}
.reports{list-style:none;padding:0;margin:var(--sp-3) 0 0}
.report__item{display:grid;grid-template-columns:1fr auto;gap:var(--sp-2) var(--sp-3);align-items:center;padding:var(--sp-3) 0;border-bottom:1px solid var(--line)}
.report__item .t-small{grid-column:1}
.report__item button{grid-row:1/3;grid-column:2}

/* ── 웹 입력기(I-3) ── */
.editor{min-height:180px;padding:var(--sp-4) var(--sp-5);border:2px solid var(--line-2);border-radius:var(--r-md);background:var(--surface-2);
  font-size:var(--fs-34);line-height:1.6;white-space:pre-wrap;overflow-wrap:anywhere;cursor:text;margin:var(--sp-4) 0 var(--sp-3)}
.editor:focus{outline:none;border-color:var(--brand);box-shadow:var(--focus-ring)}
.editor--sm{min-height:72px;font-size:var(--fs-28)}
.ime-bar{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;margin-bottom:var(--sp-6)}
.ime-bar .t-small{color:var(--ink-3)}
#copied{color:var(--green-700);font-weight:var(--fw-bold)}
.roman--box{background:var(--info-soft);border-radius:var(--r-sm);padding:var(--sp-3) var(--sp-4);margin:var(--sp-2) 0 var(--sp-3);min-height:2.2em}
.mono{font-family:var(--font-mono);font-size:.95em}

/* ── 설치 안내(I-1·I-2) ── */
.tabs{display:flex;gap:var(--sp-2);margin:0 0 var(--sp-4);flex-wrap:wrap}
.tab{height:44px;padding:0 var(--sp-5);border:2px solid var(--line);border-radius:var(--r-pill);background:var(--surface);
  font:inherit;font-weight:var(--fw-bold);color:var(--ink-2);cursor:pointer}
.tab:hover{border-color:var(--teal-300)}
.tab.is-active{background:var(--brand);border-color:var(--brand);color:#fff}
.notice{background:var(--warn-soft);border-left:5px solid var(--warn);border-radius:var(--r-sm);padding:var(--sp-3) var(--sp-4);margin-top:var(--sp-4)}
/* 설치 안내의 번호 목록. components.css 의 `.steps`(가로 단계 표시기)와 이름이 겹치면
   display:flex 를 물려받아 한 줄로 눕는다 — 그래서 `.langkah`. */
.langkah{margin:0;padding-left:1.4em}
.langkah li{margin-bottom:var(--sp-4);line-height:var(--lh-loose)}
.langkah code,.notice code{font-family:var(--font-mono);font-size:.9em;background:var(--gray-100);padding:2px 6px;border-radius:5px}
.shot{margin:var(--sp-3) 0 0;padding:var(--sp-6) var(--sp-4);border:2px dashed var(--navy-200);border-radius:var(--r-md);
  background:var(--surface-2);color:var(--ink-3);font-size:var(--fs-13);font-weight:var(--fw-bold);text-align:center}
.shot::before{content:"📷 ";}

/* ── 기기 진단(I-4) ── */
.checks{list-style:none;padding:0;margin:var(--sp-4) 0 0}
.check{display:flex;align-items:flex-start;gap:var(--sp-3);padding:var(--sp-3) 0;border-bottom:1px solid var(--line)}
.check__label{font-weight:var(--fw-bold)}
.check__fix{color:var(--red-700);margin-top:2px}
.check .pill{flex:none;min-width:96px;justify-content:center}
.t-small.ok{color:var(--green-700);font-weight:var(--fw-bold)}
.t-small.bad{color:var(--red-700);font-weight:var(--fw-bold)}

.consent{max-width:640px;width:calc(100% - 32px);border:0;border-radius:var(--r-xl);padding:var(--sp-8);background:var(--surface);color:var(--ink);box-shadow:var(--sh-lg)}
.consent::backdrop{background:rgba(18,50,92,.45)}
.consent h2{margin:0 0 var(--sp-3)}
.consent h3{margin:var(--sp-5) 0 var(--sp-2)}
.consent p,.consent ul{margin:0 0 var(--sp-2)}
.consent ul{padding-left:1.2em}
.consent li{margin-bottom:4px}
.consent__btns{display:flex;gap:var(--sp-3);justify-content:flex-end;margin-top:var(--sp-6)}
.research{margin-bottom:var(--sp-6);border-left:5px solid var(--info)}
.research h2{margin:0 0 var(--sp-2)}
.research p{margin:0 0 var(--sp-4);max-width:78ch}
.research__row{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap}
.research__row label{display:flex;flex-direction:column;gap:4px;color:var(--ink-2);font-weight:var(--fw-bold)}
.input{height:40px;padding:0 12px;border:2px solid var(--line-2);border-radius:var(--r-sm);background:var(--surface);font:inherit;font-size:var(--fs-15);color:var(--ink);min-width:160px}
.input:focus{outline:none;border-color:var(--brand);box-shadow:var(--focus-ring)}
.course{margin-bottom:var(--sp-6)}
.course__head{display:flex;align-items:baseline;gap:var(--sp-3);margin:0 0 var(--sp-3)}
.course__head .lencana{background:var(--brand);color:#fff;font-weight:var(--fw-black)}
.course__desc{color:var(--ink-2);font-size:var(--fs-14)}
.lesson{display:grid;grid-template-columns:auto 1fr auto auto;align-items:center;gap:var(--sp-4);padding:var(--sp-3) var(--sp-5);background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);margin-bottom:var(--sp-2)}
.lesson__title{font-weight:var(--fw-bold)}
.lesson__meta{font-size:var(--fs-13);color:var(--ink-3)}
.lesson__best{font-size:var(--fs-14);color:var(--ink-2);text-align:right;min-width:110px}
.lesson__best.is-pass{color:var(--green-700);font-weight:var(--fw-bold)}
.prac-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--sp-3);gap:var(--sp-3);flex-wrap:wrap}
.prac-card{margin-bottom:var(--sp-5)}
.target{font-size:var(--fs-42);line-height:1.6;letter-spacing:.02em;word-break:keep-all;overflow-wrap:anywhere;min-height:1.6em}
.target .seg{padding:0 1px;border-radius:4px;transition:background var(--dur-fast)}
.target .seg.ok{color:var(--green-700)}
.target .seg.bad{color:var(--red-700);background:var(--err-soft);text-decoration:underline wavy var(--err)}
.target .seg.cur{background:var(--brand-soft);box-shadow:inset 0 -3px 0 var(--brand)}
.target .seg.pending{color:var(--ink-3)}
.roman{font-family:var(--font-mono);color:var(--ink-2);font-size:var(--fs-15);margin:var(--sp-1) 0 var(--sp-4);overflow-wrap:anywhere}
.input-line{display:flex;align-items:center;min-height:56px;padding:var(--sp-2) var(--sp-4);border:2px solid var(--line-2);border-radius:var(--r-md);background:var(--surface-2);font-size:var(--fs-28);line-height:1.5;overflow-wrap:anywhere}
.caret{display:inline-block;width:2px;height:1.2em;background:var(--brand);margin-left:2px;animation:blink 1s steps(1) infinite}
@keyframes blink{50%{opacity:0}}
.hint{margin-top:var(--sp-2);min-height:1.4em}
.hint .kbd{margin:0 2px}
.kbd{display:inline-block;min-width:1.6em;padding:0 .4em;border:1px solid var(--navy-200);border-bottom-width:3px;border-radius:6px;background:#fff;font-family:var(--font-mono);font-weight:700;text-align:center;color:var(--ink)}
.metrics{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-3);margin-top:var(--sp-5);padding-top:var(--sp-4);border-top:1px solid var(--line)}
.metric{text-align:center}
.metric__v{font-size:var(--fs-28);font-weight:var(--fw-black);color:var(--brand-text);font-variant-numeric:tabular-nums}
.metric__k{font-size:var(--fs-13);color:var(--ink-3);font-weight:var(--fw-bold);letter-spacing:var(--ls-caps);text-transform:uppercase}
.metrics--lg .metric__v{font-size:var(--fs-42)}
.char-panel{text-align:center;padding:var(--sp-4) 0 var(--sp-2)}
.char-panel__glyph{font-size:120px;line-height:1.1;color:var(--brand-text)}
.char-panel__key{margin-top:var(--sp-3);font-size:var(--fs-18)}
.char-panel__key .kbd{font-size:var(--fs-24);min-width:2em}
.char-panel.is-ok .char-panel__glyph{color:var(--green-700)}
.char-panel.is-bad .char-panel__glyph{color:var(--red-700);animation:shake .3s var(--ease)}
.kb-wrap{display:flex;justify-content:center;overflow-x:auto;padding:var(--sp-2) 0}
.kb-wrap--hands{align-items:center;gap:var(--sp-5);flex-wrap:wrap}
/* 키캡·자판은 디자인시스템 components.css 를 그대로 쓰고, 크기와 추가 키만 여기서 정한다.
   (.keyboard .key 처럼 특정도를 높이면 .key--l/--b/--q 색이 죽는다) */
.keyboard{--kh:52px;--kfs:20px}
.key--sp{min-width:calc(var(--kh)*5)}
.key--bs{min-width:calc(var(--kh)*1.6)}
.key--shiftw{min-width:calc(var(--kh)*1.6)}
.toast-anchor{position:fixed;left:50%;bottom:28px;transform:translateX(-50%);z-index:var(--z-toast)}   /* 토스트 외형은 디자인시스템 .toast 사용 */
.result{max-width:640px;margin:0 auto;text-align:center}
.result h2{margin:0 0 var(--sp-4)}
.result h3{margin:var(--sp-6) 0 var(--sp-2)}
.difficult{list-style:none;padding:0;margin:0 auto;max-width:360px}
.difficult li{display:flex;justify-content:space-between;align-items:center;padding:var(--sp-2) var(--sp-3);border-bottom:1px solid var(--line)}
.difficult .cia{font-size:var(--fs-28)}
.result__btns{display:flex;gap:var(--sp-3);justify-content:center;margin-top:var(--sp-6);flex-wrap:wrap}
@media (max-width:720px){.greet{grid-template-columns:1fr}.greet__mascot{display:none}.statcards,.statcards--4{grid-template-columns:repeat(2,1fr)}.hero-lesson{grid-template-columns:1fr}.hero-lesson__art{display:none}.result__hero{flex-direction:column;text-align:center}.tile{min-width:64px;height:72px;font-size:var(--fs-28)}.book-card{grid-template-columns:1fr}.par-cols{grid-template-columns:1fr}.reader-bar{position:static}.report{grid-template-columns:1fr}.letters{grid-template-columns:1fr}.keyboard{--kh:38px;--kfs:15px}.target{font-size:var(--fs-24)}.metrics{grid-template-columns:repeat(2,1fr)}.lesson{grid-template-columns:1fr auto}.lesson__meta,.lesson__best{grid-column:1/-1}}

/* ── 녹음 화면 (rekam.html) ─────────────────────────────────────────────
   현지에서 교사·화자가 쓰는 화면이다. 단추는 크게, 지금 무엇을 읽어야 하는지 한눈에. */
.rec__form{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--sp-3);margin:var(--sp-4) 0}
.fld{display:flex;flex-direction:column;gap:var(--sp-1)}
.fld>span{font-size:var(--fs-13);font-weight:var(--fw-bold);color:var(--navy-700)}
.fld input{font:inherit;font-size:var(--fs-15);padding:var(--sp-2) var(--sp-3);border:2px solid var(--navy-200);
  border-radius:var(--r-md);background:#fff;color:var(--navy-900)}
.fld input:focus{outline:none;border-color:var(--brand)}
.rec__head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin-bottom:var(--sp-3)}
.prog{height:10px;background:var(--gray-200);border-radius:999px;overflow:hidden;margin:var(--sp-2) 0}
.prog__bar{height:100%;width:0;background:var(--brand);border-radius:999px;transition:width var(--dur-base)}
.rec__top{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3)}
.pill--muted{background:var(--gray-200);color:var(--navy-700)}
.rec__text{font-size:72px;line-height:1.25;text-align:center;margin:var(--sp-4) 0 0;color:var(--navy-900);word-break:break-word}
.rec__text--sm{font-size:30px;line-height:1.5}
.rec__rom{text-align:center;font-size:var(--fs-20);color:var(--brand-text);font-weight:var(--fw-bold);margin:var(--sp-1) 0 var(--sp-2)}
.rec__ctrl{display:flex;align-items:center;justify-content:center;gap:var(--sp-3);margin:var(--sp-4) 0 var(--sp-2);flex-wrap:wrap}
.rec__ctrl2{display:flex;align-items:center;justify-content:center;gap:var(--sp-2);flex-wrap:wrap}
.rec__hint{text-align:center;min-height:1.4em}
#btn-rec{min-width:190px;font-size:var(--fs-20);padding:var(--sp-3) var(--sp-5)}
#btn-rec.is-rec{background:var(--danger,#D7263D);border-color:var(--danger,#D7263D);animation:recpulse 1.1s ease-in-out infinite}
@keyframes recpulse{0%,100%{box-shadow:0 0 0 0 rgba(215,38,61,.45)}50%{box-shadow:0 0 0 12px rgba(215,38,61,0)}}
@media (prefers-reduced-motion:reduce){#btn-rec.is-rec{animation:none}}
.rec__strip{display:flex;gap:var(--sp-2);overflow-x:auto;padding:var(--sp-2) 0}
.rec__chip{flex:0 0 auto;min-width:56px;padding:var(--sp-2);border:2px solid var(--navy-200);border-radius:var(--r-md);
  background:#fff;cursor:pointer;font:inherit;font-size:var(--fs-20);color:var(--navy-900)}
.rec__chip.is-done{background:#E8F6EC;border-color:#7FC796}
.rec__chip.is-cur{border-color:var(--brand);box-shadow:0 0 0 3px rgba(3,145,164,.2)}

/* ── 소개 화면 (tentang.html) ─────────────────────────────────────────── */
.kv{display:grid;grid-template-columns:minmax(120px,auto) 1fr;gap:var(--sp-2) var(--sp-4);margin:var(--sp-3) 0}
.kv dt{color:var(--navy-500,var(--navy-700))}
.kv dd{margin:0}
.lic{display:flex;flex-direction:column;gap:var(--sp-3);margin:var(--sp-4) 0}
.lic__row{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--sp-4);
  padding:var(--sp-3);border:1.5px solid var(--navy-200);border-radius:var(--r-md);background:#fff}
.lic__row p{margin:var(--sp-1) 0 0}
.lic__row>div:last-child{flex:0 0 auto}
.opt--link{display:block;padding:var(--sp-2) 0;color:var(--brand-text);font-weight:var(--fw-bold);text-decoration:none}
.opt--link:hover{text-decoration:underline}

/* ── 특수 3자 (khusus.html) ────────────────────────────────────────────── */
.khus{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--sp-4);margin:var(--sp-4) 0}
.khus__card{background:#fff;border:2px solid var(--navy-200);border-radius:var(--r-lg);padding:var(--sp-4);text-align:center}
.khus__glyph{font-size:76px;line-height:1.15;color:var(--brand-text)}
.khus__sound{font-size:var(--fs-20);font-weight:var(--fw-black);color:var(--navy-700)}
.khus__key{margin:var(--sp-2) 0 0}
.khus__ex{margin:var(--sp-3) 0 var(--sp-1);text-align:left}
.khus__ex ul{list-style:none;margin:var(--sp-1) 0 0;padding:0}
.khus__ex li{display:flex;gap:var(--sp-2);align-items:baseline;padding:2px 0}
.khus__dots{display:flex;gap:6px;justify-content:center;margin:var(--sp-3) 0 0;flex-wrap:wrap}
.khus__dot{width:10px;height:10px;border-radius:999px;background:var(--gray-300)}
.khus__dot.is-done{background:var(--brand)}
.khus__dot.is-cur{background:var(--accent);box-shadow:0 0 0 3px rgba(214,158,46,.25)}

/* ── 음절 조합 (susun.html) ────────────────────────────────────────────── */
.susun__top{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3)}
.susun__eq{display:flex;align-items:center;justify-content:center;gap:var(--sp-3);flex-wrap:wrap;margin:var(--sp-5) 0}
.susun__slot{display:flex;flex-direction:column;align-items:center;gap:var(--sp-1);min-width:104px;padding:var(--sp-3);
  border:2px dashed var(--navy-200);border-radius:var(--r-lg);background:#fff;transition:border-color var(--dur-fast),box-shadow var(--dur-fast)}
.susun__slot.is-on{border-style:solid;border-color:var(--brand);box-shadow:0 0 0 4px rgba(3,145,164,.15)}
.susun__slot--res{border-color:var(--accent)}
.susun__slot--res.is-on{border-color:var(--amber-700);box-shadow:0 0 0 4px rgba(214,158,46,.2)}
.susun__ch{font-size:56px;line-height:1.2;color:var(--navy-900);min-height:1.2em}
.susun__op{font-size:var(--fs-24);font-weight:var(--fw-black);color:var(--navy-500,var(--navy-700))}
.susun__read{text-align:center;font-size:var(--fs-20);margin:var(--sp-2) 0;min-height:1.6em}
.susun__ctrl{display:flex;gap:var(--sp-2);justify-content:center;flex-wrap:wrap;margin-top:var(--sp-3)}
/* 카드 사이 간격 — 디자인 시스템의 `.card` 는 아래 여백을 갖지 않는다. 블록마다 각자 넣는 구조라
   화면 14개에서 카드가 맞붙어 한 덩어리로 보였다(2026-08-30, screen_audit.py 가 잡았다).
   여기서 한 번에 준다. 인접 형제 여백은 겹쳐지므로(margin collapsing) 이미 아래 여백을 가진
   블록(.statcards 등)과 겹쳐도 두 배가 되지 않는다. */
#app > * + *,
#app > .view > * + *{margin-top:var(--sp-5)}   /* 연습 화면은 카드가 .view 안에 있다 */

/* 단추가 넷이다. flex 로 두면 마지막 하나가 남은 줄을 통째로 늘여 잡아 여백이 어색해진다(2026-08-30).
   격자로 두면 줄이 바뀌어도 칸 너비가 같아 마지막 단추만 커지는 일이 없다. */
.start__row{display:grid;grid-template-columns:repeat(auto-fit,minmax(215px,1fr));
  gap:var(--sp-3);margin-top:var(--sp-3)}
.start__row .btn{justify-content:center;text-align:center}
/* 이름이 길어 한 줄에 안 들어간다 — 글자를 위, 이름을 아래로 쌓는다 */
.start__btn{display:flex;flex-direction:column;align-items:center;gap:2px;
  white-space:normal;line-height:1.35;height:auto;padding:var(--sp-3) var(--sp-3)}
.start__g{font-size:var(--fs-20);line-height:1.2}

/* ── PUA 변환기 (pua.html) ─────────────────────────────────────────────── */
.pua__io{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:var(--sp-4);margin:var(--sp-3) 0}
.pua__col{display:flex;flex-direction:column;gap:var(--sp-2)}
.pua__head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-2)}
/* font 축약을 쓰면 font-family 까지 덮어써서 .cia 글꼴이 죽는다 — 옛한글이 조합되지 않는다 */
.pua__ta{font-size:var(--fs-17);line-height:1.7;padding:var(--sp-3);border:2px solid var(--navy-200);
  border-radius:var(--r-md);background:#fff;color:var(--navy-900);resize:vertical;width:100%}
.pua__ta:focus{outline:none;border-color:var(--brand)}
.pua__ta[readonly]{background:var(--gray-50,#F7FAFB)}
.pua__btns{display:flex;gap:var(--sp-2);flex-wrap:wrap}
.pua__run{display:flex;align-items:center;gap:var(--sp-4);flex-wrap:wrap;margin-top:var(--sp-2)}
.pua__msg{padding:var(--sp-3);border-radius:var(--r-md);margin:var(--sp-2) 0;border-left:4px solid}
.pua__msg--ok{background:#E8F6EC;border-color:#4C9E68}
.pua__msg--warn{background:#FDF7DC;border-color:#D69E2E}
.pua__msg--bad{background:#FDECEC;border-color:#D7263D}

/* ── 첫 화면 (awal.html) ───────────────────────────────────────────────── */
.lead{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);gap:var(--sp-6);align-items:center}
.lead__h{font-size:clamp(28px,4.2vw,46px);line-height:1.15;margin:var(--sp-3) 0;color:var(--navy-900);text-wrap:balance}
.lead__p{max-width:56ch}
.lead__cta{display:flex;gap:var(--sp-3);flex-wrap:wrap;margin:var(--sp-5) 0 var(--sp-4)}
.lead__badges{display:flex;gap:var(--sp-2) var(--sp-4);flex-wrap:wrap;list-style:none;margin:0;padding:0;
  font-size:var(--fs-14);color:var(--navy-700);font-weight:var(--fw-bold)}
.lead__badges li::before{content:"✓ ";color:var(--brand)}
.lead__art{display:flex;align-items:center;justify-content:center}
.lead__art .cia{font-size:clamp(90px,15vw,190px);line-height:1;color:var(--brand);
  text-shadow:0 6px 22px rgba(3,145,164,.18)}
@media (max-width:760px){.lead{grid-template-columns:1fr}.lead__art{order:-1}}
.lead__three{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--sp-4);margin:var(--sp-4) 0}
.three{text-align:center;padding:var(--sp-4);border:2px solid var(--navy-200);border-radius:var(--r-lg);background:#fff}
.three__g{font-size:64px;line-height:1.15;color:var(--brand-text)}
.three__s{font-size:var(--fs-20);font-weight:var(--fw-black);color:var(--navy-700);margin-bottom:var(--sp-2)}
.lead__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:var(--sp-4);margin-top:var(--sp-4)}
.feat{display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-4);border:2px solid var(--navy-200);
  border-radius:var(--r-lg);background:#fff;text-decoration:none;color:inherit;transition:border-color var(--dur-fast),transform var(--dur-fast)}
.feat:hover{border-color:var(--brand);transform:translateY(-2px)}
.feat__i{font-size:26px}
.feat__t{font-weight:var(--fw-black);color:var(--brand-text)}
.lead__foot{background:var(--gray-50,#F7FAFB)}
@media (prefers-reduced-motion:reduce){.feat:hover{transform:none}}

/* ── 로그인·가입 (masuk.html) ──────────────────────────────────────────── */
.masuk__list{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:var(--sp-3);margin-top:var(--sp-3)}
.masuk__who{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3);border:2px solid var(--navy-200);
  border-radius:var(--r-lg);background:#fff;cursor:pointer;font:inherit;text-align:left;
  transition:border-color var(--dur-fast)}
.masuk__who:hover{border-color:var(--brand)}
.masuk__n{font-weight:var(--fw-black);color:var(--navy-900);flex:1}
.masuk__pin{display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap;margin:var(--sp-3) 0}
.masuk__pin input{font:inherit;font-size:var(--fs-24);letter-spacing:.4em;width:9ch;text-align:center;
  padding:var(--sp-2) var(--sp-3);border:2px solid var(--navy-200);border-radius:var(--r-md);background:#fff}
.masuk__pin input:focus{outline:none;border-color:var(--brand)}
.fld select{font:inherit;font-size:var(--fs-15);padding:var(--sp-2) var(--sp-3);border:2px solid var(--navy-200);
  border-radius:var(--r-md);background:#fff;color:var(--navy-900)}

/* ── 섬 지도 (peta.html) ───────────────────────────────────────────────── */
.peta{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:var(--sp-4);margin:var(--sp-4) 0}
.peta__stop{position:relative}
.peta__card{display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-4);border:2px solid var(--navy-200);
  border-radius:var(--r-lg);background:#fff;text-decoration:none;color:inherit;height:100%;
  transition:border-color var(--dur-fast),transform var(--dur-fast)}
a.peta__card:hover{border-color:var(--brand);transform:translateY(-2px)}
.peta__i{font-size:34px;line-height:1}
.peta__n{font-weight:var(--fw-black);color:var(--brand-text)}
.peta__d{min-height:2.6em}
.peta__bar{display:block;height:8px;background:var(--gray-200);border-radius:999px;overflow:hidden;margin:var(--sp-1) 0}
.peta__bar>span{display:block;height:100%;background:var(--brand);border-radius:999px}
.peta__stop.is-clear .peta__card{border-color:#7FC796;background:#F4FBF6}
.peta__stop.is-clear .peta__bar>span{background:#4C9E68}
.peta__stop.is-lock .peta__card{opacity:.55;background:var(--gray-100)}
@media (prefers-reduced-motion:reduce){a.peta__card:hover{transform:none}}

/* ── 이야기 연습 (cerita.html) — 목업 모바일 012·027 ──────────────────── */
.cer__title{display:flex;align-items:flex-start;gap:var(--sp-4);margin:var(--sp-4) 0 var(--sp-3)}
.cer__title>div:nth-child(2){flex:1}
.cer__mascot{display:flex;align-items:center;gap:var(--sp-2);flex:0 0 auto}
.cer__mascot .mascot{width:120px;height:auto}
.cer__mascot--sm .mascot{width:96px}
@media (max-width:720px){.cer__mascot{display:none}.cer__mascot--sm{display:flex}}
.cer__hero{display:flex;align-items:center;gap:var(--sp-4);flex-wrap:wrap}
.cer__thumb{width:150px;height:96px;object-fit:cover;border-radius:var(--r-lg);flex:0 0 auto}
.cer__heroBody{flex:1;min-width:200px}
.cer__pick{font:inherit;font-size:var(--fs-14);padding:4px var(--sp-2);border:2px solid var(--navy-200);
  border-radius:var(--r-md);background:#fff;margin-bottom:var(--sp-2);max-width:100%}
.cer__bar{height:10px;background:var(--gray-200);border-radius:999px;overflow:hidden;margin:var(--sp-2) 0}
.cer__bar>span{display:block;height:100%;width:0;background:var(--brand);border-radius:999px;transition:width var(--dur-base)}
.cer__play{flex:0 0 auto}
/* 통계 카드 — 목업 027 의 색 띠 4개 */
.cer__stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--sp-3);margin:var(--sp-4) 0}
.cer__stat{display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto auto;gap:2px var(--sp-2);
  align-items:center;padding:var(--sp-3);border-radius:var(--r-lg);border:2px solid transparent}
.cer__stat img,.cer__i{grid-row:1/3;width:28px;height:28px;font-size:20px;display:flex;align-items:center;justify-content:center;
  border-radius:999px}
.cer__k{font-size:var(--fs-13);font-weight:var(--fw-bold);color:var(--navy-700)}
.cer__v{grid-column:2;font-size:var(--fs-24);font-weight:var(--fw-black);color:var(--navy-900);line-height:1.1}
.cer__c{grid-column:1/3;font-size:var(--fs-13);font-weight:var(--fw-bold)}
.cer__stat--b{background:#EEF6FB;border-color:#CFE4F1}.cer__stat--b .cer__c{color:#2B6CB0}
.cer__stat--g{background:#E8F6EC;border-color:#A8DCB8}.cer__stat--g .cer__c{color:#2F7D4F}
.cer__stat--r{background:#FDECEC;border-color:#F2B8B8}.cer__stat--r .cer__c{color:#C53030}
.cer__stat--r .cer__i{background:#E05252;color:#fff}
.cer__stat--a{background:#FDF7DC;border-color:#EBD98A}.cer__stat--a .cer__c{color:#975A16}
/* 본문 + 사이드 */
.cer__main{display:grid;grid-template-columns:minmax(0,1fr) minmax(220px,280px);gap:var(--sp-4);align-items:start}
@media (max-width:860px){.cer__main{grid-template-columns:1fr}}
.cer__opt{display:flex;justify-content:flex-end}
.cer__opt .opt{gap:var(--sp-2)}
.cer__line .cia{white-space:pre-wrap}
.cer__line{font-size:var(--fs-20);line-height:1.9;margin:0 0 var(--sp-2);padding:var(--sp-2) var(--sp-3);border-radius:var(--r-md)}
.cer__line.is-done{opacity:.5}
.cer__line.is-cur{background:#FDF6DE;box-shadow:inset 3px 0 0 var(--accent)}
.cer__rom{display:block;color:var(--navy-500,var(--navy-700));margin-top:2px}
.cer__art{width:100%;max-width:420px;border-radius:var(--r-lg);margin-top:var(--sp-3)}
.cer__side{display:flex;flex-direction:column;gap:var(--sp-4)}
.cer__quest{text-align:center}
.cer__chest{font-size:44px;line-height:1.2}
.cer__stars{font-size:26px;letter-spacing:4px;margin:var(--sp-2) 0}
.cer__star{color:var(--gray-300)}
.cer__star.is-on{color:var(--accent)}
.cer__next{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);flex-wrap:wrap;margin:var(--sp-5) 0}

/* ── 입력 모드 전환 (mode.html) — 목업 모바일 030 ─────────────────────── */
.mode__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:var(--sp-3)}
.mode__card{position:relative;display:flex;flex-direction:column;align-items:center;gap:var(--sp-1);
  padding:var(--sp-4) var(--sp-3);border:2px solid var(--navy-200);border-radius:var(--r-lg);background:#fff;
  cursor:pointer;font:inherit;text-align:center;transition:border-color var(--dur-fast),box-shadow var(--dur-fast)}
.mode__card:hover:not([disabled]){border-color:var(--brand)}
.mode__card.is-on{border-color:var(--brand);background:#F2FBFC;box-shadow:0 0 0 3px rgba(3,145,164,.15)}
.mode__card[disabled]{opacity:.55;cursor:not-allowed}
.mode__tick{position:absolute;top:-10px;right:-10px;width:28px;height:28px;border-radius:999px;background:var(--brand);
  color:#fff;display:flex;align-items:center;justify-content:center;font-weight:var(--fw-black)}
.mode__ic img{width:56px;height:56px;object-fit:contain}
.mode__glyph{display:flex;align-items:center;justify-content:center;width:56px;height:56px;border-radius:999px;
  font-size:22px;font-weight:var(--fw-black)}
.mode__glyph--ko{background:#DDF1F6;color:var(--brand-text)}
.mode__glyph--en{background:#EDE7FA;color:#6B46C1}
.mode__n{font-weight:var(--fw-black);color:var(--navy-900)}
.mode__try{display:flex;align-items:center;gap:var(--sp-4);flex-wrap:wrap;background:#F2FAFC}
.mode__tryBody{flex:1;min-width:240px}
.mode__inwrap{position:relative;margin:var(--sp-2) 0}
.mode__in{min-height:56px;font-size:var(--fs-24);padding:var(--sp-3) 44px var(--sp-3) var(--sp-3);
  border:2px solid var(--navy-200);border-radius:var(--r-md);background:#fff;color:var(--navy-900);
  white-space:pre-wrap;word-break:break-word}
.mode__in:focus{outline:none;border-color:var(--brand)}
.mode__clear{position:absolute;right:8px;top:50%;transform:translateY(-50%)}
.mode__art{width:180px;height:auto;border-radius:var(--r-lg)}
.mode__special{background:#FEFAEC}
.mode__keys{display:flex;gap:var(--sp-3);flex-wrap:wrap;margin-top:var(--sp-3)}
.mode__key{display:flex;flex-direction:column;align-items:center;gap:2px;padding:var(--sp-3) var(--sp-4);
  background:#fff;border:2px solid #EBD98A;border-radius:var(--r-lg);min-width:96px}
.mode__kc{width:32px;height:32px;border-radius:999px;background:#FDF0E2;color:#975A16;font-weight:var(--fw-black);
  display:flex;align-items:center;justify-content:center}
.mode__arrow{color:var(--navy-500,var(--navy-700))}
.mode__kg{font-size:28px;color:var(--brand-text)}
.mode__reward{position:relative;background:#F6FBF7}
.mode__rewards{display:flex;gap:var(--sp-5);flex-wrap:wrap;margin-top:var(--sp-3)}
.mode__reward1{display:flex;flex-direction:column;gap:2px}
.mode__ric{font-size:26px}
.mode__chest{position:absolute;right:var(--sp-5);bottom:var(--sp-4);font-size:46px}
.mode__cta{display:flex;align-items:center;justify-content:center;gap:var(--sp-2);width:100%;margin:var(--sp-5) 0}

/* ── 설정 (pengaturan.html) — 목업 모바일 029 ─────────────────────────── */
.set__cols{display:grid;grid-template-columns:minmax(0,1fr) minmax(230px,300px);gap:var(--sp-4);align-items:start}
@media (max-width:900px){.set__cols{grid-template-columns:1fr}}
.set__main{display:flex;flex-direction:column;gap:var(--sp-4)}
.set__side{display:flex;flex-direction:column;gap:var(--sp-4)}
.set__list{display:flex;flex-direction:column;margin-top:var(--sp-2)}
.set__row{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) 0;
  border-bottom:1px solid var(--gray-200);text-decoration:none;color:inherit}
.set__row:last-child{border-bottom:0}
a.set__row:hover .set__txt b{color:var(--brand-text)}
.set__row.is-soon{opacity:.6}
.set__ic{flex:0 0 auto;width:40px;height:40px;border-radius:var(--r-md);display:flex;align-items:center;
  justify-content:center;font-size:19px;font-weight:var(--fw-black);background:var(--gray-100);color:var(--navy-700)}
.set__ic.g{background:#E8F6EC;color:#2F7D4F} .set__ic.b{background:#EEF6FB;color:#2B6CB0}
.set__ic.a{background:#FDF7DC;color:#975A16} .set__ic.v{background:#F1ECFA;color:#6B46C1}
.set__ic.t{background:#E4F5F7;color:var(--brand-text)} .set__ic.p{background:#FBECF6;color:#B83280}
.set__ic.o{background:#FDF0E2;color:#C05621}
.set__txt{flex:1;display:flex;flex-direction:column;gap:1px;min-width:0}
.set__val{color:var(--brand-text);font-weight:var(--fw-bold);font-size:var(--fs-14)}
.set__ch{color:var(--gray-400);font-size:var(--fs-20)}
.set__sw{position:relative;display:inline-block;width:48px;height:28px;flex:0 0 auto}
.set__sw input{position:absolute;opacity:0;width:100%;height:100%;margin:0;cursor:pointer}
.set__sw span{position:absolute;inset:0;border-radius:999px;background:var(--gray-300);transition:background var(--dur-fast)}
.set__sw span::after{content:"";position:absolute;top:3px;left:3px;width:22px;height:22px;border-radius:999px;
  background:#fff;transition:transform var(--dur-fast);box-shadow:0 1px 3px rgba(0,0,0,.2)}
.set__sw input:checked + span{background:var(--brand)}
.set__sw input:checked + span::after{transform:translateX(20px)}
.set__sw input:focus-visible + span{box-shadow:0 0 0 3px rgba(3,145,164,.35)}
.set__big{text-align:center;background:#F2FAFC}
.set__aa{font-weight:var(--fw-black);color:var(--brand-text);line-height:1.1;margin:var(--sp-2) 0}
.set__sizes{display:flex;gap:var(--sp-2);justify-content:center;flex-wrap:wrap;margin-top:var(--sp-2)}
.set__keys{background:#F6FBF7}
.set__help{background:#FEFAEC;text-align:center}
.set__help .mascot{width:120px;height:auto}

/* ── 오프라인 (luring.html) — 목업 모바일 032 ─────────────────────────── */
.lur__head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin:var(--sp-4) 0 var(--sp-2)}
.lur__head h1{margin:0;text-align:center;flex:1}
.lur__pill{display:block;text-align:center;margin:0 auto var(--sp-4)}
.lur__hero{display:flex;align-items:center;gap:var(--sp-4);flex-wrap:wrap;background:#EAF6FA}
.lur__heroBody{flex:1;min-width:240px}
.lur__accent{color:var(--brand-text)}
.lur__badges{display:flex;gap:var(--sp-4);flex-wrap:wrap;list-style:none;padding:0;margin:var(--sp-3) 0 0;
  font-size:var(--fs-14);font-weight:var(--fw-bold);color:var(--navy-700)}
.lur__list{display:flex;flex-direction:column}
.lur__item{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) 0;border-bottom:1px solid var(--gray-200);flex-wrap:wrap}
.lur__item:last-child{border-bottom:0}
.lur__ic{width:44px;height:44px;border-radius:var(--r-md);background:var(--gray-100);display:flex;
  align-items:center;justify-content:center;font-size:20px;font-weight:var(--fw-black);flex:0 0 auto}
.lur__txt{flex:1;display:flex;flex-direction:column;min-width:140px}
.lur__size{font-weight:var(--fw-black);color:var(--navy-900);font-variant-numeric:tabular-nums}
.lur__st{font-weight:var(--fw-bold);font-size:var(--fs-14);min-width:130px}
.lur__st.is-ok{color:#2F7D4F} .lur__st.is-wait{color:var(--gray-500,var(--navy-700))}
.lur__sum{background:#F2FAFC}
.lur__sumRow{display:flex;gap:var(--sp-5);flex-wrap:wrap;margin:var(--sp-3) 0}
.lur__sumRow>div{display:flex;flex-direction:column}
.lur__cta{display:block;width:100%;margin:var(--sp-3) 0}
.lur__tip{background:#FEFAEC}

/* ── 내보내기 센터 (ekspor.html) — 목업 데스크톱 006 ──────────────────── */
.eks__head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--sp-4);flex-wrap:wrap;margin:var(--sp-4) 0}
.eks__filters{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:var(--sp-3)}
.eks__dates{display:flex;align-items:center;gap:var(--sp-2)}
.eks__dates input{font:inherit;font-size:var(--fs-14);padding:var(--sp-2);border:2px solid var(--navy-200);
  border-radius:var(--r-md);background:#fff;min-width:0;flex:1}
.eks__types{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:var(--sp-3);margin:var(--sp-4) 0 var(--sp-2)}
.eks__type{position:relative;display:flex;flex-direction:column;align-items:flex-start;gap:var(--sp-2);
  padding:var(--sp-4);border:2px solid var(--navy-200);border-radius:var(--r-lg);background:#fff;
  cursor:pointer;font:inherit;text-align:left;transition:border-color var(--dur-fast)}
.eks__type:hover{border-color:var(--brand)}
.eks__type.is-on{border-color:var(--brand);background:#F5FBFC}
.eks__check{position:absolute;top:var(--sp-3);right:var(--sp-3);width:24px;height:24px;border-radius:6px;
  border:2px solid var(--navy-200);background:#fff;display:flex;align-items:center;justify-content:center;
  color:#fff;font-weight:var(--fw-black)}
.eks__type.is-on .eks__check{background:var(--brand);border-color:var(--brand)}
.eks__tn{font-weight:var(--fw-black);color:var(--navy-900)}
.eks__note{margin:0 0 var(--sp-4)}
.eks__cols{display:grid;grid-template-columns:minmax(0,1fr) minmax(230px,300px);gap:var(--sp-4);align-items:start}
@media (max-width:900px){.eks__cols{grid-template-columns:1fr}}
.eks__side{display:flex;flex-direction:column;gap:var(--sp-4)}
.eks__privacy{background:#F2FAFC}
.eks__pv{list-style:none;padding:0;margin:var(--sp-3) 0 0;display:flex;flex-direction:column;gap:var(--sp-2);
  font-size:var(--fs-14);color:var(--navy-700)}
/* 큰 단추 안에 설명을 넣으면 기본 .btn 의 정렬과 부딪혀 글자가 겹친다 — 세로로 쌓고 높이를 준다 */
.eks__go{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;width:100%;
  height:auto;padding:var(--sp-4);line-height:1.3}
.eks__go .t-small{display:block;font-weight:var(--fw-bold);opacity:.9}

/* ── 강의 모드 (ajar.html, T-3) — 프로젝터용 ──────────────────────────────
   뒤에서 보는 사람이 기준이다. 글자를 키우고 장식은 걷어낸다. */
body.ajar{background:var(--bg);min-height:100vh;display:flex;flex-direction:column}
.ajar__bar{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);flex-wrap:wrap;
  padding:var(--sp-3) var(--sp-5);background:var(--surface);border-bottom:1px solid var(--line)}
.ajar__brand{font-size:var(--fs-14);color:var(--ink-2)}
.ajar__ctrl{display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap}
.ajar__stage{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:var(--sp-4);padding:var(--sp-5);max-width:1400px;margin:0 auto;width:100%}
.ajar__now{text-align:center;width:100%}
.ajar__label{margin:0 0 var(--sp-3);font-size:var(--fs-20);color:var(--ink-2)}
.ajar__eq{display:flex;align-items:center;justify-content:center;gap:var(--sp-3);flex-wrap:wrap}
.ajar__slot{display:flex;flex-direction:column;align-items:center;gap:4px;min-width:120px;
  padding:var(--sp-3) var(--sp-4);border:3px dashed var(--navy-200);border-radius:var(--r-lg);background:var(--surface)}
.ajar__slot.is-on{border-style:solid;border-color:var(--brand);box-shadow:0 0 0 5px rgba(3,145,164,.15)}
.ajar__slot--res{border-color:var(--accent)}
.ajar__slot--res.is-on{border-color:var(--amber-700);box-shadow:0 0 0 5px rgba(214,158,46,.2)}
.ajar__slotk{font-size:var(--fs-13);font-weight:var(--fw-bold);color:var(--ink-3);text-transform:uppercase;
  letter-spacing:var(--ls-caps)}
.ajar__slotv{font-size:64px;line-height:1.15;color:var(--ink)}
.ajar__op{font-size:34px;font-weight:var(--fw-black);color:var(--ink-3)}
.ajar__rom{margin:var(--sp-3) 0 0;font-size:var(--fs-24);color:var(--brand-text);min-height:1.4em}
.ajar__out{width:100%;text-align:center}
.ajar__text{font-size:56px;line-height:1.4;min-height:1.4em;color:var(--ink);word-break:break-word}
.ajar__kb{width:100%;display:flex;justify-content:center;overflow-x:auto}
.ajar__cap{text-align:center;font-size:var(--fs-20);font-weight:var(--fw-black);color:var(--brand-text);min-height:1.4em;margin:0}
/* 글자 크기 두 단계 — 교실 크기에 맞춘다 */
body.ajar.is-lg .ajar__slotv{font-size:88px} body.ajar.is-lg .ajar__text{font-size:76px}
body.ajar.is-lg .ajar__rom{font-size:var(--fs-28)} body.ajar.is-lg .ajar__op{font-size:46px}
body.ajar.is-xl .ajar__slotv{font-size:120px} body.ajar.is-xl .ajar__text{font-size:104px}
body.ajar.is-xl .ajar__rom{font-size:var(--fs-34)} body.ajar.is-xl .ajar__op{font-size:60px}
body.ajar.is-xl .ajar__label{font-size:var(--fs-24)}
body.ajar:fullscreen .ajar__bar{opacity:.35;transition:opacity var(--dur-fast)}
body.ajar:fullscreen .ajar__bar:hover{opacity:1}
@media (max-width:860px){.ajar__slotv{font-size:44px}.ajar__text{font-size:36px}}

/* ── 열대 장식 (deco.js) — 목업이 모든 화면에서 공유하는 배경 ──────────── */
.deco{position:fixed;inset:0;pointer-events:none;z-index:0;overflow:hidden}
.deco svg{position:absolute;opacity:.82}
.deco__leaf--tl{left:-38px;top:-24px;width:132px;transform:rotate(-24deg)}
.deco__leaf--tr{right:-44px;top:64px;width:118px;transform:rotate(158deg)}
.deco__leaf--bl{left:-34px;bottom:-34px;width:140px;transform:rotate(22deg)}
.deco__flower--tr{right:40px;top:214px;width:60px;opacity:.78}
.deco__star{right:64px;bottom:70px;width:54px;opacity:.72;transform:rotate(-14deg)}
/* 배경 장식(.deco) 위로 올린다. `.side` 는 여기서 뺀다 — 이 규칙이 뒤에 와서
   `.side{position:sticky}` 를 relative 로 덮었고, 그래서 왼쪽 기둥이 스크롤과 함께 밀려 올라갔다. */
#app,main{position:relative;z-index:1}
/* 머리말은 **본문보다 위**여야 한다. 위 규칙에 `.top` 을 같이 묶어 두었더니 `z-index:1` 이 되어
   `.top{z-index:var(--z-nav)}`(맨 위 규칙)를 덮었고, 같은 층에서는 나중에 오는 `main` 이 이긴다 —
   그래서 머리말에서 펼친 차림표(언어·설정)가 본문 그림 밑으로 들어가 가려졌다(2026-08-30).
   `position` 은 건드리지 않는다(지금 화면들은 붙지 않는 머리말을 전제로 짜여 있다). */
.top{position:relative;z-index:var(--z-nav)}
.side{z-index:2}
@media (max-width:900px){.deco__leaf--tr,.deco__flower--tr,.deco__star{display:none}}
@media (max-width:620px){.deco{display:none}}
@media print{.deco{display:none!important}}
@media (prefers-reduced-motion:no-preference){
  .deco svg{transition:opacity var(--dur-slow)}
}
/* 마스코트 + 말풍선 (deco.js) — 목업처럼 제목 옆에 선다 */
.mascot-wrap{display:flex;align-items:center;justify-content:flex-end;gap:var(--sp-2);
  margin:0 0 var(--sp-2);pointer-events:none}
.mascot-wrap .mascot{width:132px;height:auto}
.mascot-wrap .bubble{max-width:280px}
@media (max-width:760px){.mascot-wrap{display:none}}

/* 머리말의 개발용 부제(`· 자모표 (R-1)`)는 한국어다. 학습자 화면에 한국어를 두지 않는다는
   원칙에 어긋나므로 기본으로 숨기고, 개발 중에만 보이게 한다: 주소에 `?dev=1` 을 붙이면 켜진다. */
.top__sub .t-small{display:none}
html[data-dev] .top__sub .t-small{display:inline}

/* ── 데스크톱 기본 틀 (shell.js) — 목업 데스크톱-16x9/001 ─────────────────
   넓은 화면에서만 켠다. 좁은 화면은 지금의 상단 내비가 낫다(현지는 휴대전화가 많다). */
.side--app{display:none}
@media (min-width:1100px){
  /* 왼쪽 기둥과 머리말은 **고정**이고 안쪽 내용만 스크롤한다.
     창 높이에 맞춰 틀을 잡고(overflow:hidden), 스크롤은 `main` 하나가 맡는다. */
  body.has-shell{display:grid;grid-template-columns:236px minmax(0,1fr);height:100vh;overflow:hidden}
  .side--app{display:flex}
  body.has-shell > .main{min-width:0;min-height:0;display:flex;flex-direction:column;overflow:hidden}
  body.has-shell > .main > .top{flex:none}
  body.has-shell > .main > main{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain}
  /* 머리말은 **흰 띠 그대로 둔다** — 교사 화면(guru)과 같은 틀이어야 한다.
     투명하게 지우고 제목까지 감췄더니 셸이 붙은 쪽만 다른 제품처럼 보였다.
     로고만 뺀다(사이드바가 이미 보여 준다). 쪽 링크도 뺀다 — 사이드바가 그 자리를 맡는다. */
  body.has-shell .top__tools > a.btn{display:none}
  body.has-shell .top__logo{display:none}
  body.has-shell .top__brand{pointer-events:none}
  body.has-shell .deco{left:236px}
}
/* 왼쪽 기둥의 항목은 밑줄을 긋지 않는다. `.side--app`(shell.js) 에만 걸어 두었더니
   손으로 쓴 사이드바(ekspor)의 <a> 항목만 밑줄이 그어져 다른 화면처럼 보였다.
   guru 는 <button> 이라 우연히 멀쩡했다 — 우연에 기대면 안 된다. */
.side__item{text-decoration:none}
.side__brand{text-decoration:none}

/* ── 배지 (badges.js) — 목업 데스크톱-16x9/006 ─────────────────────────── */
.lencana__count{margin:0 0 var(--sp-3)}
.lencanas{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--sp-3)}
.lencana{text-align:center;padding:var(--sp-4) var(--sp-3);border:2px solid var(--gray-200);border-radius:var(--r-lg);
  background:var(--gray-100);opacity:.62;transition:opacity var(--dur-fast),border-color var(--dur-fast)}
.lencana.is-on{opacity:1;background:#fff;border-color:var(--brand)}
.lencana__ic{width:64px;height:64px;margin:0 auto var(--sp-2);display:flex;align-items:center;justify-content:center;
  border-radius:999px;background:var(--gray-200);font-size:30px}
.lencana.is-on .lencana__ic{background:#E4F5F7}
.lencana.is-on.lencana--g .lencana__ic{background:#E8F6EC}
.lencana.is-on.lencana--a .lencana__ic{background:#FDF7DC}
.lencana.is-on.lencana--r .lencana__ic{background:#FDECEC}
.lencana.is-on.lencana--b .lencana__ic{background:#EEF6FB}
.lencana__ic img{width:64px;height:64px;object-fit:contain}
.lencana__n{font-weight:var(--fw-black);color:var(--navy-900)}
.lencana.is-on .lencana__n{color:var(--brand-text)}

/* ── 풍경 띠 (목업 데스크톱-16x9/002·005·007 의 소개 배너) ─────────────
   components.css 의 `.banner`(알림 줄)와 이름이 겹치면 안 되므로 `.pemandangan`.
   하늘·바다는 SVG, 양옆 잎사귀와 섬은 목업에서 잘라낸 그림(pemandangan.js 참고). */
.pemandangan{position:relative;overflow:hidden;border-radius:var(--r-lg);
  min-height:200px;display:flex;align-items:center;isolation:isolate;
  box-shadow:var(--sh-sm);border:1px solid var(--line);
  --pd-sky1:#DCF1FB;--pd-sky2:#FFFFFF;--pd-sea1:#8FD8F2;--pd-sea2:#2FA6CB;
  --pd-sand:#F7EAD0;--pd-hill:#A9CEE2}
.pemandangan--hutan{--pd-sky1:#E1F3E6;--pd-sea1:#9BD9B0;--pd-sea2:#3F9E6E;--pd-hill:#A8CDB4}
.pemandangan--senja{--pd-sky1:#FFE0BE;--pd-sea1:#F6BE96;--pd-sea2:#DB7B52;--pd-hill:#E4B296}
.pemandangan--laut{--pd-sky1:#D2ECFB;--pd-sea1:#79CFEC;--pd-sea2:#1E8DB6}
.pemandangan__scene{position:absolute;inset:0;width:100%;height:100%;z-index:0}
/* 양옆 잎사귀 — SVG 밖에 두어야 넓은 화면에서 잘려 나가지 않는다.
   안쪽 모서리는 부드럽게 지워 배경 그라데이션과 이어 붙인다. */
.pemandangan__flora{position:absolute;bottom:0;z-index:1;height:100%;width:auto;max-width:124px;
  object-fit:cover;pointer-events:none;user-select:none}
.pemandangan__flora--l{left:0;-webkit-mask-image:linear-gradient(90deg,#000 52%,transparent);
  mask-image:linear-gradient(90deg,#000 52%,transparent)}
.pemandangan__flora--r{right:0;-webkit-mask-image:linear-gradient(270deg,#000 40%,transparent);
  mask-image:linear-gradient(270deg,#000 40%,transparent)}
.pemandangan__islet{position:absolute;right:19%;bottom:22%;z-index:1;width:150px;height:auto;
  opacity:.92;pointer-events:none}
/* 글자가 잎사귀 위에 얹히면 읽기 어렵다 — 본문 뒤에만 옅은 흰 막을 깐다 */
.pemandangan__body{position:relative;z-index:3;padding:var(--sp-6) var(--sp-6) var(--sp-6) var(--sp-8);
  max-width:60ch;
  background:linear-gradient(100deg,rgba(255,255,255,.30) 0%,rgba(255,255,255,.84) 12%,
    rgba(255,255,255,.80) 55%,rgba(255,255,255,.26) 84%,transparent 100%)}
.pemandangan__body > *{margin:0}
.pemandangan__body > * + *{margin-top:var(--sp-2)}
.pemandangan__eyebrow{font-size:var(--fs-13);font-weight:var(--fw-black);letter-spacing:.08em;
  text-transform:uppercase;color:var(--teal-700)}
.pemandangan__title{font-family:var(--font-ui);font-size:var(--fs-28);line-height:1.15;
  font-weight:var(--fw-black);color:var(--ink);text-shadow:0 2px 0 rgba(255,255,255,.7)}
.pemandangan__sub{font-size:var(--fs-16);color:var(--ink);max-width:44ch;
  text-shadow:0 1px 0 rgba(255,255,255,.75)}
.pemandangan__chips{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin-top:var(--sp-3)}
.pemandangan__chips .hpill{background:rgba(255,255,255,.9);border:1px solid rgba(255,255,255,.95);
  box-shadow:var(--sh-sm)}
.pemandangan__otter{position:absolute;right:var(--sp-5);bottom:0;z-index:2;
  width:186px;height:auto;pointer-events:none;
  filter:drop-shadow(0 6px 10px rgba(20,60,70,.18))}
@media (max-width:1100px){ .pemandangan__islet{right:8%;width:132px} }
@media (max-width:900px){
  .pemandangan{min-height:0}
  .pemandangan__body{padding:var(--sp-5);max-width:none}
  .pemandangan__title{font-size:var(--fs-24)}
  .pemandangan__otter{width:112px;right:var(--sp-2)}
  .pemandangan__islet{display:none}
}
@media (max-width:560px){ .pemandangan__otter,.pemandangan__flora--r{display:none} }
@media print{ .pemandangan__scene,.pemandangan__otter,.pemandangan__flora,.pemandangan__islet{display:none}
  .pemandangan{min-height:0;box-shadow:none} }

/* ── 축하 카드 (목업 데스크톱-16x9/009) ─────────────────────────── */
.raya{border:0;padding:0;background:transparent;max-width:min(94vw,380px);width:100%;
  overflow:visible;--raya-band:var(--teal-500)}
.raya--t{--raya-band:var(--teal-500)}
.raya--v{--raya-band:#7E6BC4}
.raya--o{--raya-band:var(--orange-500)}
.raya::backdrop{background:rgba(16,44,52,.5)}
.raya::after{content:"";position:absolute;inset:0;z-index:-1;border-radius:var(--r-xl);
  background:var(--surface);box-shadow:var(--sh-lg);border:1px solid var(--line)}
.raya > *{position:relative}
.raya__ribbon{margin:0;transform:translateY(-14px);align-self:center;
  background:var(--raya-band);color:#fff;font-weight:var(--fw-black);font-size:var(--fs-16);
  text-align:center;padding:9px 26px;border-radius:var(--r-pill);
  box-shadow:0 3px 0 rgba(0,0,0,.12);width:max-content;max-width:92%;margin-inline:auto}
.raya{display:flex;flex-direction:column;align-items:center;text-align:center;
  padding:0 var(--sp-6) var(--sp-6);gap:var(--sp-3)}
/* 목업 009 처럼 마스코트는 왼쪽, 상징(별·메달)은 오른쪽에 나란히 — 겹치면 얼굴이 가린다 */
.raya__art{display:flex;align-items:flex-end;justify-content:center;gap:var(--sp-2);
  min-height:104px;margin-top:calc(var(--sp-2) * -1)}
.raya__otter{width:124px;height:auto}
.raya__emblem{flex:none;margin-bottom:10px;width:76px;height:76px;border-radius:50%;
  display:grid;place-items:center;font-size:38px;line-height:1;
  background:radial-gradient(circle at 34% 30%,#FFF0BC,#FFCF5C 62%,#F0A93A);
  border:4px solid #fff;box-shadow:var(--sh-md)}
.raya__title{margin:0;font-size:var(--fs-24);font-weight:var(--fw-black);color:var(--ink)}
.raya__sub{margin:0;font-size:var(--fs-15);color:var(--ink-2);max-width:32ch}
.raya__gainlead{margin:0;font-size:var(--fs-13);color:var(--ink-3);font-weight:var(--fw-bold)}
.raya__gains{display:flex;gap:var(--sp-3);justify-content:center;flex-wrap:wrap}
.raya__gains:empty{display:none}
.raya__gain{display:inline-flex;align-items:center;gap:6px;font-weight:var(--fw-black);
  font-size:var(--fs-16);color:var(--ink)}
.raya__gk{display:grid;place-items:center;min-width:30px;height:30px;padding:0 7px;
  border-radius:9px;background:var(--brand-soft);color:var(--brand-text);font-size:var(--fs-12)}
.raya__confetti{position:absolute;inset:-8px 0 auto;height:150px;overflow:hidden;
  pointer-events:none;border-radius:var(--r-xl) var(--r-xl) 0 0}
.raya__confetti i{position:absolute;top:-14px;left:var(--x);width:8px;height:12px;border-radius:2px;
  transform:rotate(var(--r));animation:raya-fall 1.5s var(--d) ease-in forwards;opacity:0}
@keyframes raya-fall{
  0%{opacity:0;transform:translateY(-10px) rotate(var(--r))}
  12%{opacity:1}
  100%{opacity:0;transform:translateY(150px) rotate(calc(var(--r) + 260deg))}}
@media (prefers-reduced-motion:reduce){ .raya__confetti{display:none} }

/* ── 단계형 손가락 연습 (A-3, jari.html) ─────────────────────────── */
.tahaps{list-style:none;margin:var(--sp-4) 0 0;padding:0;display:flex;flex-direction:column;gap:var(--sp-2)}
.tahap{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--sp-4);
  padding:var(--sp-3) var(--sp-4);border:1px solid var(--line);border-radius:var(--r-lg);background:var(--surface)}
.tahap.is-done{border-color:var(--green-500);background:var(--ok-soft)}
.tahap.is-locked{opacity:.6}
.tahap__no{display:grid;place-items:center;width:36px;height:36px;border-radius:50%;flex:none;
  background:var(--brand-soft);color:var(--brand-text);font-weight:var(--fw-black)}
.tahap.is-done .tahap__no{background:var(--green-500);color:#fff}
.tahap__n{font-weight:var(--fw-black)}
.tahap__k{display:flex;flex-wrap:wrap;gap:4px;margin-top:4px}
.tahap__head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--sp-4)}
.tahap__head h2{margin:var(--sp-1) 0}
.tahap__head p{margin:0}
.jari-target{display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px var(--sp-5);align-items:center;
  justify-content:center;margin:var(--sp-5) auto;padding:var(--sp-5) var(--sp-6);width:max-content;max-width:100%;
  border-radius:var(--r-lg);background:var(--surface-tint);border:1px solid var(--line)}
.jari-target__glyph{grid-row:1/4;font-size:var(--fs-52);line-height:1;color:var(--brand-text)}
.jari-target__rom{font-size:var(--fs-20);color:var(--ink-2)}
.jari-target__key .kbd{font-size:var(--fs-18)}
.jari-target__finger{font-size:var(--fs-14);color:var(--ink-3)}
@media (max-width:720px){
  .tahap{grid-template-columns:auto minmax(0,1fr);row-gap:var(--sp-2)}
  .tahap > .btn,.tahap > .pill{grid-column:2}
  .jari-target{padding:var(--sp-4)}
  .jari-target__glyph{font-size:var(--fs-42)}
}

/* ── 연습 중 예외 상태 안내 (deteksi.js — State 02 · State 09) ───── */
.dtk{align-items:flex-start;gap:var(--sp-3);margin-bottom:var(--sp-4);line-height:var(--lh-normal)}
.dtk__t{flex:1;min-width:0;font-weight:var(--fw-medium)}
.dtk .btn{flex:none}
.dtk__x{flex:none;width:32px;height:32px;font-size:var(--fs-14);background:transparent;border:0;color:inherit}

/* ── 학생 상세 (Screen 22, siswa.html) ────────────────────────────── */
.siswa__head{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--sp-4)}
.siswa__ava{width:72px;height:72px;border-radius:50%;flex:none}
.siswa__id p{margin:0}
.siswa__id h1{margin:2px 0}
.siswa__nav{display:flex;gap:var(--sp-2)}
.siswa__levels{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:var(--sp-3);margin-top:var(--sp-3)}
.lvchip{border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--sp-3);background:var(--surface);
  display:flex;flex-direction:column;gap:2px;opacity:.55}
.lvchip.is-on{opacity:1;border-color:var(--brand);background:var(--brand-soft)}
.lvchip b{font-size:var(--fs-18);color:var(--brand-text)}
.lvchip span{font-size:var(--fs-13)}
.lvchip small{font-size:var(--fs-12);color:var(--ink-3)}
.siswa__cal{display:grid;grid-template-columns:repeat(28,1fr);gap:4px;margin-top:var(--sp-3);max-width:560px}
.cal__d{aspect-ratio:1;border-radius:3px;background:var(--gray-100);border:1px solid var(--line)}
.cal__d.is-on{background:var(--brand);border-color:var(--brand)}
@media (max-width:720px){
  .siswa__head{grid-template-columns:auto minmax(0,1fr)}
  .siswa__nav{grid-column:1/-1}
  .siswa__cal{grid-template-columns:repeat(14,1fr)}
}
/* 설정 줄의 고르개. `.input` 이 `width:100%` 라, flex 줄에서 기준 폭이 줄 전체가 되어
   설명 글이 한 단어씩 줄바꿈되는 좁은 기둥으로 밀렸다(고르개가 784px 중 720px 을 먹었다).
   내용만큼만 차지하게 못 박는다. */
.set__pick{flex:0 0 auto;width:auto;min-width:180px;max-width:min(240px,50%);
  height:40px;padding:0 var(--sp-3)}
@media (max-width:520px){
  /* 좁은 화면에서는 설명 아래로 내려 한 줄을 통째로 쓴다 */
  .set__row:has(.set__pick){flex-wrap:wrap}
  .set__pick{max-width:none;width:100%;flex:1 0 100%}
}

/* ── 준비 화면 (State 01 · 목업 태블릿-4x3/003) ─────────────────── */
.siap{position:fixed;inset:0;z-index:var(--z-modal);display:grid;place-items:center;
  padding:var(--sp-5);background:var(--bg);overflow:auto;transition:opacity var(--dur-base) var(--ease)}
.siap.is-gone{opacity:0;pointer-events:none}
.siap__box{width:min(760px,100%);background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-xl);box-shadow:var(--sh-md);padding:var(--sp-6)}
.siap__head{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:var(--sp-4)}
.siap__title{margin:0;font-size:var(--fs-28);font-weight:var(--fw-black);color:var(--ink)}
.siap__sub{margin:var(--sp-2) 0 0;color:var(--ink-2)}
.siap__otter{width:140px;height:auto}
.siap__steps{list-style:none;margin:var(--sp-5) 0 0;padding:0;display:flex;flex-direction:column;gap:2px}
.siap__step{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--sp-3);
  padding:10px var(--sp-3);border-radius:var(--r-md)}
.siap__step.is-now{background:var(--brand-soft)}
.siap__no{display:grid;place-items:center;width:28px;height:28px;border-radius:50%;flex:none;
  background:var(--gray-200);color:var(--ink-3);font-size:var(--fs-13);font-weight:var(--fw-black)}
.siap__step.is-now .siap__no{background:var(--brand);color:#fff}
.siap__step.is-done .siap__no{background:var(--green-500);color:#fff;font-size:0}
.siap__step.is-done .siap__no::after{content:"✓";font-size:var(--fs-14)}
.siap__n{font-weight:var(--fw-bold)}
.siap__step.is-done .siap__n{color:var(--ink-2)}
.siap__s{font-size:var(--fs-13);color:var(--ink-3)}
.siap__step.is-now .siap__s{color:var(--brand-text);font-weight:var(--fw-bold)}
.siap__diag{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--sp-2);
  margin-top:var(--sp-5)}
.siap__d{display:flex;align-items:center;gap:var(--sp-2);padding:10px;border-radius:var(--r-md);
  border:1px solid var(--line);background:var(--surface-2)}
.siap__d span{display:flex;flex-direction:column;min-width:0}
.siap__d b{font-size:var(--fs-13)}
.siap__d .t-small{color:var(--ink-3)}
.siap__d.is-ok .t-small{color:var(--green-700)}
.siap__d.is-bad .t-small{color:var(--amber-700)}
.siap__di{font-size:var(--fs-18);flex:none}
.siap__note{margin:var(--sp-5) 0 0}
.siap__acts{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin-top:var(--sp-4)}
@media (max-width:720px){
  .siap__head{grid-template-columns:1fr}
  .siap__otter{display:none}
  .siap__box{padding:var(--sp-4)}
}
@media (prefers-reduced-motion:reduce){ .siap{transition:none} }

/* 뼈대는 실제로 그려질 자리를 잡아 준다(State 01 보조 · keadaan.js) */
[aria-busy="true"] .skel{margin:0}
.letters[aria-busy="true"]{display:grid}

/* ── 지금 어떤 자판인가 (Screen 18) ─────────────────────────────── */
.mode-now__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:var(--sp-3);
  margin:var(--sp-4) 0 var(--sp-3)}
.mode-now__c{display:flex;gap:var(--sp-3);padding:var(--sp-3);border-radius:var(--r-lg);
  border:1px solid var(--line);background:var(--surface-2)}
.mode-now__c.is-ok{border-color:var(--green-500);background:var(--ok-soft)}
.mode-now__c.is-bad{border-color:var(--amber-500,var(--warn));background:var(--warn-soft)}
.mode-now__i{font-size:var(--fs-20);flex:none}
.mode-now__k{font-size:var(--fs-13);color:var(--ink-3)}
.mode-now__v{font-weight:var(--fw-black)}
.jalur{gap:var(--sp-5)}

/* ── 학급 코드 (C-1, kelas.js) ──────────────────────────────────── */
.kelas__form{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:var(--sp-3);
  margin:var(--sp-4) 0}
.field{display:flex;flex-direction:column;gap:6px}
.field__l{font-size:var(--fs-13);font-weight:var(--fw-bold);color:var(--ink-3)}
.kelas__out{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--sp-5);align-items:center;
  padding:var(--sp-4);border-radius:var(--r-lg);background:var(--brand-soft)}
.kelas__code{margin:2px 0 6px;font-size:var(--fs-42);font-weight:var(--fw-black);letter-spacing:.06em;
  color:var(--brand-text);font-variant-numeric:tabular-nums}
.kelas__qr{margin:0;text-align:center}
.kelas__qr canvas{background:#fff;border-radius:var(--r-md);padding:6px}
.kelas__qr figcaption{margin-top:4px;max-width:170px}
@media (max-width:720px){ .kelas__out{grid-template-columns:1fr} .kelas__code{font-size:var(--fs-34)} }
@media print{
  body.has-shell .side,.top,.tabpane[hidden]{display:none}
  .kelas__code{font-size:64pt}
}

/* ── 학급 코드 카드 (C-2) ───────────────────────────────────────── */
.kelas-card{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:var(--sp-4)}
.kelas-card__b > *{margin:0}
.kelas-card__b > * + *{margin-top:var(--sp-2)}
.kelas-card__row{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin-top:var(--sp-3)}
.kelas-card__code{width:180px;font-size:var(--fs-24);font-weight:var(--fw-black);letter-spacing:.08em;
  text-align:center;font-variant-numeric:tabular-nums}
.kelas-card__act{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin-top:var(--sp-3)}
.kelas-card__art{width:120px;height:auto}
@media (max-width:720px){ .kelas-card{grid-template-columns:1fr} .kelas-card__art{display:none} }

/* ── Composer Debug (dev.html) ──────────────────────────────────── */
.dev__bar{display:flex;flex-wrap:wrap;gap:var(--sp-2);align-items:center;margin-bottom:var(--sp-4)}
.dev__now{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:var(--sp-2);
  margin-bottom:var(--sp-4)}
.dev__cell{display:flex;flex-direction:column;gap:2px;padding:var(--sp-3);border-radius:var(--r-md);
  background:var(--surface-2);border:1px solid var(--line)}
.dev__k{font-size:var(--fs-12);color:var(--ink-3);font-weight:var(--fw-bold)}
.dev__v{font-size:var(--fs-20);font-family:var(--font-mono)}
.dev__v.cia{font-family:var(--font-cia)}
.dev__out{min-height:84px;padding:var(--sp-4);border:2px solid var(--line);border-radius:var(--r-lg);
  background:var(--surface);font-size:var(--fs-34);line-height:1.4;cursor:text;word-break:break-all}
.dev__out:focus{outline:none;border-color:var(--brand);box-shadow:var(--focus-ring)}
.dev__composing{background:var(--brand-soft);border-radius:4px}
.dev__caret{display:inline-block;width:2px;height:1em;background:var(--brand);vertical-align:-.12em;
  animation:dev-blink 1s steps(1) infinite}
@keyframes dev-blink{50%{opacity:0}}
.dev__codes{margin-top:var(--sp-2);font-size:var(--fs-12);color:var(--ink-3);word-break:break-all}
@media (prefers-reduced-motion:reduce){ .dev__caret{animation:none} }

/* ── 로마자 병기 규격 (D-2, ejaan.html) ─────────────────────────── */
.ej__dirs{gap:var(--sp-5)}
.ej__dir > *{margin:0}
.ej__dir > * + *{margin-top:var(--sp-2)}
.ej__h{margin:var(--sp-5) 0 var(--sp-2)}
.ej__map{display:grid;grid-template-columns:repeat(auto-fill,minmax(112px,1fr));gap:var(--sp-2)}
.ej__c{display:flex;flex-direction:column;align-items:center;gap:2px;text-align:center;
  padding:var(--sp-3) 6px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface)}
.ej__c.is-zero{opacity:.6;border-style:dashed}
.ej__j{font-size:var(--fs-28);line-height:1.1;color:var(--brand-text)}
.ej__l{font-size:var(--fs-16);font-weight:var(--fw-black)}
.ej__c .t-small{line-height:1.3}
.ej__in{width:100%;font-size:var(--fs-24);line-height:1.6;resize:vertical}
.ej__res{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:var(--sp-4);
  margin-top:var(--sp-4)}
.ej__res > div > p{margin:0}
.ej__latin{font-size:var(--fs-18);word-break:break-word}
.ej__back{font-size:var(--fs-20);word-break:break-word}

@media print{
  /* 인쇄는 흐르는 문서다 — 틀을 고정하면 첫 화면만 나온다 */
  body.has-shell,body.has-side{height:auto;overflow:visible;display:block}
  body.has-shell > .main,body.has-side > .main,
  body.has-shell > .main > main,body.has-side > .main > main{overflow:visible;height:auto}
}

/* ── 목업의 그림 꾸밈을 화면에 옮긴 것 ────────────────────────────────
   목업(데스크톱-16x10/025 등)은 그림 위에 글을 얹는데, 구현은 글자 카드만 쌓여 있었다.
   틀은 그대로 두고 **그림이 들어갈 자리**만 되살린다. */

/* 인사 띠 — `.pemandangan` 위에 이름과 흰 알약 세 개 */
.sambut{margin-bottom:var(--sp-6)}
.sambut__chips{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin-top:var(--sp-4)}
.sambut__c{display:inline-flex;align-items:baseline;gap:6px;padding:8px 14px;border-radius:var(--r-lg);
  background:rgba(255,255,255,.92);box-shadow:var(--sh-sm);color:var(--ink)}
.sambut__ic{font-size:var(--fs-16);align-self:center}
.sambut__c b{font-size:var(--fs-20);font-weight:var(--fw-black);font-variant-numeric:tabular-nums}
.sambut__k{font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--ink-2)}
.sambut__note{color:var(--ink-2)}
@media (max-width:700px){
  .sambut__c{padding:6px 10px}
  .sambut__c b{font-size:var(--fs-16)}
}

/* 빠른 실행 타일 — 목업의 «Quick Actions» 색 동그라미 */
.aksi__row{display:grid;grid-template-columns:repeat(auto-fit,minmax(178px,1fr));
  gap:var(--sp-3);margin-top:var(--sp-4)}
.aksi{display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;
  padding:var(--sp-4) var(--sp-3);border-radius:var(--r-lg);background:var(--surface);
  border:1px solid var(--line);text-decoration:none;color:var(--ink);
  transition:transform var(--dur,.15s) ease,box-shadow var(--dur,.15s) ease}
.aksi:hover{transform:translateY(-2px);box-shadow:var(--sh-md);border-color:var(--brand-soft)}
.aksi__ic{display:grid;place-items:center;width:64px;height:64px;border-radius:50%;
  font-size:26px;background:var(--brand-soft);color:var(--brand-text);margin-bottom:var(--sp-1)}
.aksi__ic--cia{font-size:17px;font-weight:var(--fw-bold);line-height:1}
.aksi--g .aksi__ic{background:var(--green-100);color:var(--green-700)}
.aksi--b .aksi__ic{background:var(--sky-100);color:var(--sky-700)}
.aksi--a .aksi__ic{background:var(--amber-100);color:var(--amber-700)}
.aksi--v .aksi__ic{background:var(--violet-100);color:var(--violet-700)}
.aksi--t .aksi__ic{background:var(--teal-100);color:var(--teal-700)}
.aksi--r .aksi__ic{background:var(--red-100);color:var(--red-700)}
.aksi__t{font-weight:var(--fw-bold);line-height:1.25}
.aksi__d{font-size:var(--fs-12);color:var(--ink-2);line-height:1.35}

/* 사이드바 바닥 카드 — 글만 있던 것을 그림 카드로 (shell.js 의 SIDE_SCENE) */
.side__note{position:relative;overflow:hidden;padding:0;min-height:104px;
  display:flex;align-items:flex-end}
.side__note__s{position:absolute;inset:0;width:100%;height:100%;display:block}
.side__note p{position:relative;z-index:1;width:100%;margin:0;
  padding:var(--sp-3) var(--sp-3) var(--sp-3);color:var(--ink);font-weight:var(--fw-bold);
  background:linear-gradient(to top,rgba(255,255,255,.94),rgba(255,255,255,.72) 60%,transparent)}

/* ── Hujan Kata (게임) ────────────────────────────────────────────────
   목업의 게임 화면 배치를 그대로 옮긴다: 왼쪽 지표 기둥 · 가운데 무대(배경 위로 낱말이 떨어진다)
   · 오른쪽 대기 낱말 · 아래 현재 낱말과 자판 · 오른쪽 판 · 맨 아래 상태줄.
   `.hjn__*` 로 접두하는 이유는 components.css 와 이름이 겹치지 않게 하기 위해서다. */
/* 게임은 목업처럼 넓게 쓴다 — `#app` 의 기본 폭(1040)으로는 무대가 좁아진다 */
#app.hjn{max-width:1400px}
.hjn{display:flex;flex-direction:column;gap:var(--sp-4);min-height:0}
.hjn__wrap{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:var(--sp-4);align-items:start}

/* 배경 — 단계마다 갈린다(latar.js). 서로 겹쳤다가 앞엣것이 사라진다. */
.latar{position:absolute;inset:0;z-index:0;background:var(--sky-100)}
.latar__lapis{position:absolute;inset:0;opacity:0;transition:opacity .8s ease}
.latar__lapis.is-on{opacity:1}
.latar__svg{width:100%;height:100%;display:block}
/* 그린 그림이 있으면 SVG 밑그림 위로 겹친다(latar.js FOTO 참고) */
.latar__foto{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity .6s ease}
.latar__foto.is-on{opacity:1}
@keyframes lt-hanyut{from{transform:translateX(-30px)}to{transform:translateX(30px)}}
@keyframes lt-kelip{0%,100%{opacity:.25}50%{opacity:1}}
@keyframes lt-naik{from{transform:translateY(20px);opacity:.15}to{transform:translateY(-60px);opacity:.5}}
.lt-awan{animation:lt-hanyut 26s ease-in-out infinite alternate}
.lt-kabut{animation:lt-hanyut 34s ease-in-out infinite alternate-reverse}
.lt-asap{animation:lt-naik 9s ease-in infinite}
.lt-bintang circle,.lt-kunang circle{animation:lt-kelip 4s ease-in-out infinite}
.lt-kunang circle:nth-child(2n){animation-duration:6s}
.lt-bintang circle:nth-child(3n){animation-duration:7s}
.lt-gelembung circle{animation:lt-naik 12s linear infinite}
.lt-gelembung circle:nth-child(2n){animation-duration:17s}

/* 무대 */
.hjn__stage{position:relative;overflow:hidden;border-radius:var(--r-xl);
  min-height:520px;height:min(74vh,720px);box-shadow:var(--sh-lg);
  --hjn-warna:var(--lt-warna,var(--teal-700))}
.hjn__field{position:absolute;left:186px;right:176px;top:74px;bottom:348px;z-index:1;pointer-events:none}
.hjn__tanah{position:absolute;left:186px;right:176px;bottom:348px;height:4px;z-index:1;border-radius:2px;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.75),transparent);transition:background .3s}
.hjn__tanah.is-kena{background:var(--red-500);box-shadow:0 0 18px var(--red-500)}
.hjn__tanah.is-perisai{background:var(--sky-500);box-shadow:0 0 18px var(--sky-500)}

/* 떨어지는 낱말 */
.hjn__kata{position:absolute;top:0;left:50%;transform:translate3d(-50%,0,0);
  display:flex;flex-direction:column;align-items:center;gap:2px;padding:var(--sp-2) var(--sp-4);
  background:rgba(255,255,255,.94);border-radius:var(--r-pill);box-shadow:var(--sh-md);
  border:2px solid transparent;white-space:nowrap;transition:border-color .15s,box-shadow .15s}
.hjn__kata.is-target{border-color:var(--brand);box-shadow:0 0 0 4px rgba(3,145,164,.18),var(--sh-md)}
.hjn__kata__c{font-family:var(--font-cia);font-size:var(--fs-24);font-weight:var(--fw-bold);
  color:var(--ink);line-height:1.1}
.hjn__kata__c .is-done{color:var(--brand)}
.hjn__kata__c .is-now{color:var(--brand);border-bottom:3px solid var(--accent)}
.hjn__kata__r{font-size:var(--fs-12);color:var(--ink-2)}
.hjn__kata.is-bersih{animation:hjn-pop .4s ease forwards}
.hjn__kata.is-jatuh{animation:hjn-pecah .4s ease forwards}
@keyframes hjn-pop{to{transform:translate3d(-50%,-24px,0) scale(1.25);opacity:0}}
@keyframes hjn-pecah{to{transform:translate3d(-50%,14px,0) scale(.8);opacity:0;filter:saturate(.2)}}

/* 겹쳐 놓는 판들 — 목업의 반투명 흰 카드 */
.hjn__kiri,.hjn__antre,.hjn__jam,.hjn__atas,.hjn__now,.hjn__bawah{position:absolute;z-index:2}
.hjn__kiri{left:var(--sp-3);top:var(--sp-3);width:164px;display:flex;flex-direction:column;gap:var(--sp-2)}
.hjn__kartu,.hjn__aku,.hjn__jam,.hjn__antre,.hjn__samping,.hjn__now{
  background:rgba(255,255,255,.92);border-radius:var(--r-lg);box-shadow:var(--sh-md);
  padding:var(--sp-3);backdrop-filter:blur(6px)}
.hjn__aku{display:flex;align-items:center;gap:var(--sp-2);padding:var(--sp-2) var(--sp-3);border-radius:var(--r-pill)}
.hjn__aku img{border-radius:var(--r-pill);background:var(--brand-soft)}
.hjn__k{margin:0;font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--ink-2);
  letter-spacing:.04em;text-transform:uppercase}
.hjn__v{margin:2px 0 0;font-size:var(--fs-24);font-weight:var(--fw-black);color:var(--hjn-warna);
  font-variant-numeric:tabular-nums;line-height:1}
.hjn__v--xp{color:var(--sky-700);font-size:var(--fs-20)}
.hjn__n{margin:0;font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--green-700)}
.hjn__kartu--combo .hjn__v{color:var(--cta-2)}
.hjn__nyawa{margin:0;font-size:var(--fs-16);letter-spacing:2px}
.hjn__hati{filter:grayscale(1);opacity:.5}
.hjn__hati.is-on{filter:none;opacity:1}

.hjn__atas{top:var(--sp-3);left:50%;transform:translateX(-50%);width:min(42%,420px);text-align:center}
.hjn__tempat{margin:0 0 var(--sp-1);font-size:var(--fs-14);font-weight:var(--fw-black);color:#fff;
  text-shadow:0 2px 8px rgba(0,0,0,.45)}
.hjn__bar{position:relative;height:22px;border-radius:var(--r-pill);overflow:hidden;
  background:rgba(255,255,255,.45);box-shadow:inset 0 0 0 2px rgba(255,255,255,.7)}
.hjn__bar__f{height:100%;width:0;border-radius:var(--r-pill);transition:width .3s ease;
  background:linear-gradient(90deg,var(--amber-500),var(--cta-2))}
.hjn__bar__t{position:absolute;inset:0;display:grid;place-items:center;font-size:var(--fs-12);
  font-weight:var(--fw-black);color:var(--ink);text-shadow:0 1px 2px rgba(255,255,255,.8)}

.hjn__jam{top:var(--sp-3);right:var(--sp-3);text-align:center;min-width:96px}
.hjn__jam__v{margin:0;font-size:var(--fs-24);font-weight:var(--fw-black);color:var(--cta-2);
  font-variant-numeric:tabular-nums}
.hjn__jam .hjn__k{text-align:center}

.hjn__antre{right:var(--sp-3);top:120px;width:158px}
.hjn__antre__l{list-style:none;margin:var(--sp-2) 0 0;padding:0;display:flex;flex-direction:column;gap:var(--sp-1)}
.hjn__antre__i{display:flex;flex-direction:column;align-items:center;gap:0;padding:var(--sp-1) var(--sp-2);
  background:var(--gray-100);border-radius:var(--r-pill)}
.hjn__antre__i .cia{font-family:var(--font-cia);font-weight:var(--fw-bold);color:var(--ink)}
.hjn__antre__i.is-next{background:#fff;box-shadow:var(--sh-sm);outline:2px solid var(--brand-soft)}

/* 지금 치는 낱말 — 목업 가운데 아래의 큰 흰 판 */
.hjn__now{left:50%;transform:translateX(-50%);bottom:240px;width:min(560px,64%);text-align:center;
  padding:var(--sp-3) var(--sp-4)}
.hjn__now.is-salah{animation:hjn-getar .26s ease}
@keyframes hjn-getar{25%{transform:translate(-52%,0)}75%{transform:translate(-48%,0)}}
.hjn__now__head{display:flex;align-items:center;justify-content:center;gap:var(--sp-3)}
.hjn__now__cia{font-family:var(--font-cia);font-size:var(--fs-34);font-weight:var(--fw-black);
  color:var(--ink);line-height:1.1}
.hjn__now__cia .is-done{color:var(--brand)}
.hjn__now__cia .is-now{color:var(--brand);border-bottom:4px solid var(--accent)}
.hjn__now__rom{margin:0;font-size:var(--fs-14);color:var(--ink-2)}
.hjn__pips{display:flex;justify-content:center;gap:4px;margin:var(--sp-2) 0 var(--sp-1);flex-wrap:wrap}
.hjn__pip{width:20px;height:8px;border-radius:var(--r-pill);background:var(--gray-200)}
.hjn__pip.is-on{background:var(--green-500)}
.hjn__now__n{margin:0;color:var(--ink-2)}

/* 아래 세 칸 — 정확도 · 자판 · 위험 */
.hjn__bawah{left:var(--sp-3);right:var(--sp-3);bottom:10px;
  display:grid;grid-template-columns:164px minmax(0,1fr) 164px;gap:var(--sp-3);align-items:end}
.hjn__papan{background:rgba(255,255,255,.92);border-radius:var(--r-lg);box-shadow:var(--sh-md);
  padding:var(--sp-2) var(--sp-3) var(--sp-3);backdrop-filter:blur(6px)}
.hjn__pesan{margin:0 0 var(--sp-2);text-align:center;font-size:var(--fs-14);font-weight:var(--fw-bold);
  color:var(--ink-2);min-height:1.4em}
.hjn__pesan.is-ok{color:var(--green-700)}
.hjn__pesan.is-bad{color:var(--red-700)}
.hjn__akur,.hjn__bahaya__t{margin:var(--sp-1) 0;font-size:var(--fs-24);font-weight:var(--fw-black);
  color:var(--hjn-warna);font-variant-numeric:tabular-nums}
.hjn__bahaya__t{font-family:var(--font-cia);font-size:var(--fs-20);color:var(--red-700)}
.hjn__mini{height:8px;border-radius:var(--r-pill);background:var(--gray-200);overflow:hidden}
.hjn__mini__f{height:100%;width:100%;background:var(--brand);transition:width .2s}
.hjn__mini--bahaya .hjn__mini__f{width:0;background:var(--amber-500)}
.hjn__mini--bahaya .hjn__mini__f.is-gawat{background:var(--red-500)}
.hjn__samping p.t-small{margin:var(--sp-1) 0 0}
/* 무대 안에서는 자판을 작게 — 목업처럼 낱말이 떨어질 자리를 남겨야 한다.
   **색을 건드리지 않고 크기 변수만** 바꾼다: `.keyboard .key{background:…}` 처럼 쓰면
   components.css 의 `.key--l/--b/--q` 색이 죽는다(이미 한 번 겪었다). */
.hjn__papan .key{--kh:38px;--kfs:15px}
.hjn__papan .keyboard{gap:4px;padding:8px;box-shadow:none}
.hjn__papan .keyboard__row{gap:4px}

/* 무대 덮개 — 시작 · 단계 · 끝 */
.hjn__tirai{position:absolute;inset:0;z-index:3;display:grid;place-items:center;
  background:rgba(8,40,58,.55);backdrop-filter:blur(3px);padding:var(--sp-4)}
.hjn__tirai__k{background:var(--surface);border-radius:var(--r-xl);box-shadow:var(--sh-lg);
  padding:var(--sp-6);max-width:520px;text-align:center;animation:hjn-masuk .28s ease}
@keyframes hjn-masuk{from{transform:translateY(14px) scale(.97);opacity:0}}
.hjn__tirai__k h2{margin:var(--sp-1) 0}
.hjn__tirai__k p{margin:var(--sp-2) 0}
.hjn__naik{color:var(--ink)}
.hjn__habis__l{list-style:none;margin:var(--sp-4) 0;padding:0;display:flex;flex-direction:column;gap:var(--sp-2)}
.hjn__habis__l li{display:flex;justify-content:space-between;gap:var(--sp-4);
  padding:var(--sp-2) var(--sp-3);background:var(--surface-2);border-radius:var(--r-sm)}
.hjn__habis__b{display:flex;flex-wrap:wrap;gap:var(--sp-2);justify-content:center;margin-top:var(--sp-4)}

/* 오른쪽 판 */
.hjn__sisi{display:flex;flex-direction:column;gap:var(--sp-4)}
.hjn__sisi .card{margin:0}
.hjn__hadiah__g{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-2);margin-top:var(--sp-3);text-align:center}
.hjn__hadiah__i{display:flex;flex-direction:column;align-items:center;gap:2px;padding:var(--sp-2);
  background:var(--surface-2);border-radius:var(--r-md)}
.hjn__hadiah__i b{font-size:var(--fs-18);color:var(--ink)}
.hjn__hadiah__ic{display:grid;place-items:center;width:44px;height:44px;border-radius:var(--r-pill);
  font-weight:var(--fw-black);font-size:var(--fs-14);color:#fff}
.hjn__hadiah__ic--xp{background:var(--sky-500)}
.hjn__hadiah__ic--kata{background:var(--amber-500)}
.hjn__kv{list-style:none;margin:var(--sp-3) 0;padding:0;display:flex;flex-direction:column;gap:var(--sp-2)}
.hjn__kv li{display:flex;justify-content:space-between;gap:var(--sp-3)}
.hjn__kv b{font-variant-numeric:tabular-nums}
.hjn__tip{display:flex;gap:var(--sp-3);align-items:center}
.hjn__tip img{flex:none}
.hjn__tip p{margin:0}
.hjn__kuat{display:flex;flex-direction:column;gap:var(--sp-2);margin:var(--sp-3) 0}
.hjn__kuat__b{display:grid;grid-template-columns:36px 1fr auto auto;align-items:center;gap:var(--sp-2);
  padding:var(--sp-2);border:2px solid var(--line);border-radius:var(--r-md);background:var(--surface);
  font:inherit;text-align:left;cursor:pointer;opacity:.55}
.hjn__kuat__b.is-on{opacity:1;border-color:var(--brand-soft);background:var(--brand-soft)}
.hjn__kuat__b[disabled]{cursor:default}
.hjn__kuat__ic{font-size:var(--fs-20);text-align:center}
.hjn__kuat__n{font-weight:var(--fw-bold);color:var(--ink)}
.hjn__kuat__x{font-weight:var(--fw-black);color:var(--brand-text);font-variant-numeric:tabular-nums}

/* 맨 아래 상태줄 */
.hjn__status{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--sh-sm);padding:var(--sp-2) var(--sp-4)}
.hjn__lv{display:grid;place-items:center;width:34px;height:34px;border-radius:var(--r-pill);
  background:var(--brand);color:#fff;font-weight:var(--fw-black)}
.hjn__status__t{font-weight:var(--fw-bold);color:var(--ink)}
.hjn__status__bar{flex:1 1 120px;max-width:240px}
.hjn__status__s{display:flex;align-items:center;gap:4px;color:var(--ink-2)}
.hjn__status__s b{color:var(--ink);font-variant-numeric:tabular-nums}
.hjn__keluar{margin-left:auto}

@media (max-width:1240px){
  .hjn__wrap{grid-template-columns:minmax(0,1fr)}
  .hjn__sisi{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
}
@media (max-width:900px){
  .hjn__stage{height:auto;min-height:0;display:flex;flex-direction:column;gap:var(--sp-3);
    padding:var(--sp-3);background:var(--surface)}
  .hjn__kiri,.hjn__antre,.hjn__jam,.hjn__atas,.hjn__now,.hjn__bawah,.hjn__field,.hjn__tanah{position:static;transform:none}
  .hjn__field{height:44vh;min-height:220px;position:relative;order:2}
  .hjn__tanah{height:4px;background:var(--navy-100);order:3}
  .hjn__kiri{width:auto;flex-direction:row;flex-wrap:wrap;order:1}
  .hjn__kiri > *{flex:1 1 96px}
  .hjn__atas{width:auto;order:0}
  .hjn__tempat{color:var(--ink);text-shadow:none}
  .hjn__jam{order:0}
  .hjn__antre{width:auto;order:5}
  .hjn__antre__l{flex-direction:row;flex-wrap:wrap}
  .hjn__now{width:auto;order:4}
  .hjn__bawah{grid-template-columns:1fr;order:6}
  /* 좁은 화면에서는 무대가 세로로 쌓이므로 배경을 절대 위치에서 흐름 안으로 돌린다.
     높이를 0 으로 두었더니 새로 그린 배경 열 장을 **현장 기기(휴대전화)에서는 아무도 못 봤다**.
     16:9 띠로 남겨 낱말이 떨어지는 자리 뒤에 그림이 보이게 한다(2026-08-30). */
  .latar{border-radius:var(--r-lg);inset:auto;position:relative;height:auto;aspect-ratio:16/9;overflow:hidden}
  .hjn__status{font-size:var(--fs-13)}
}
/* 휴대전화 — 낱말이 떨어지는 게임은 **한 화면에 들어와야 한다.** 스크롤하면서 칠 수는 없다.
   900px 규칙은 조각을 전부 세로로 쌓는데, 390px 화면에서 그러면 무대만 1,686px 이 된다
   (배경 띠 290 + 점수 96 + 시계 87 + 대기열 114 + 아래 판 505 …). 화면 «밖으로 나간» 것이
   아니라 화면이 그만큼 길어진 것이다.
   그래서 여기서는 데스크톱과 같은 방식으로 되돌린다: 배경은 무대 전체에 깔고, 손이 닿아야
   하는 것(떨어지는 자리 · 지금 낱말 · 자판)만 남기고 나머지는 접는다.
   위의 900px 규칙과 **같은 폭**을 쓴다 — 세로로 쌓는 배치는 태블릿에서도 못 논다.
   뒤에 오므로 겹치는 선언은 이쪽이 이긴다. */
@media (max-width:900px) {
  /* 노는 동안에는 구역 내비가 자리만 차지한다(49px). 감춰서 무대에 돌려 준다 —
     머리말의 ⚙ 차림표로 어디로든 갈 수 있다. */
  body:has(.hjn__stage) .subnav{display:none}
  body:has(.hjn__stage) main{padding-top:var(--sp-3)}
  .hjn__stage{height:calc(100dvh - 124px);min-height:420px;padding:var(--sp-2);gap:var(--sp-2)}
  /* 배경을 따로 띠로 만들지 않는다 — 그만큼 세로가 길어진다. 무대 전체에 깔면 공짜다. */
  .latar{position:absolute;inset:0;width:100%;height:100%;aspect-ratio:auto;
    border-radius:var(--r-xl);z-index:0}
  /* z-index 를 주려면 자리잡기가 필요하지만, `relative` 로 두면 데스크톱의 `left:12px` ·
     `left:50%` 가 **되살아난다** — 점수 줄이 오른쪽으로 삐져나가고 «지금 낱말» 이 화면 밖으로
     반쯤 밀려났다. 그래서 좌표를 함께 지운다. */
  .hjn__atas,.hjn__jam,.hjn__kiri,.hjn__field,.hjn__tanah,.hjn__now,.hjn__bawah{
    position:relative;z-index:1;left:auto;right:auto;top:auto;bottom:auto}
  /* 세로 예산이 전부다. 자판 232px 과 떨어지는 자리가 먼저고, 나머지는 그 사이에 눌러 담는다.
     장소 이름은 배경 그림이 이미 말해 주므로 뺀다. 마스코트 그림도 뺀다 — 점수 줄이 96px 이던
     이유가 그 그림이었다. */
  .hjn__atas{display:none}
  .hjn__kiri{order:0;flex-direction:row;flex-wrap:nowrap;gap:var(--sp-1);width:auto;align-items:stretch}
  .hjn__kiri > *{flex:1 1 0;min-width:0;overflow:hidden;padding:2px var(--sp-2);text-align:center}
  .hjn__aku img,.hjn__aku .mascot{display:none}
  .hjn__kiri .hjn__k{font-size:10px}
  .hjn__kiri .hjn__v,.hjn__aku__hati{font-size:var(--fs-16);line-height:1.15}
  /* 시계는 제 줄을 하나 더 쓰지 않도록 한 줄로 만든다 */
  .hjn__jam{order:1;display:flex;align-items:baseline;justify-content:center;gap:var(--sp-2);
    padding:2px var(--sp-2);min-width:0}
  .hjn__jam__v{font-size:var(--fs-18);line-height:1.2}
  .hjn__jam .hjn__k{font-size:10px}
  .hjn__field{order:2;flex:1 1 auto;height:auto;min-height:96px}
  .hjn__tanah{order:3}
  .hjn__now{order:4;padding:var(--sp-1) var(--sp-2)}
  .hjn__now__cia{font-size:var(--fs-24)}
  .hjn__now .t-small{display:none}                 /* 안내문은 첫 판에서만 필요하다 */
  /* 대기열과 옆 안내는 노는 동안 손이 닿지 않아도 되는 정보다. 자판이 먼저다. */
  .hjn__antre{display:none}
  .hjn__samping{display:none}
  .hjn__bawah{order:5;display:block}
  .hjn__papan{margin:0}
}
/* 세로가 짧은 기기(가로로 눕힌 휴대전화, 작은 태블릿) — 떨어지는 자리를 더 줄일 수는 없으니
   자판 쪽을 줄인다. 손가락이 닿아야 하므로 32px 아래로는 내리지 않는다. */
@media (max-width:900px) and (max-height:700px) {
  .hjn__papan .key{--kh:32px;--kfs:13px}
  .hjn__papan .keyboard{gap:3px;padding:6px}
  .hjn__papan .keyboard__row{gap:3px}
  .hjn__field{min-height:72px}
  .hjn__now{padding:0 var(--sp-2)}
}
@media (prefers-reduced-motion:reduce){
  .lt-awan,.lt-kabut,.lt-asap,.lt-bintang circle,.lt-kunang circle,.lt-gelembung circle{animation:none}
  .hjn__kata.is-bersih,.hjn__kata.is-jatuh,.hjn__tirai__k{animation:none}
}

/* ── 게임 준비 화면 (목업 데스크톱-16x9/010) ───────────────────────── */
.pmn__jejak{margin:0 0 var(--sp-4);color:var(--ink-2);font-size:var(--fs-14)}
.pmn__jejak a{color:var(--brand-text)}
.pmn__kolom{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:var(--sp-5);align-items:start}
.pmn__utama,.pmn__sisi{display:flex;flex-direction:column;gap:var(--sp-4)}
.pmn__utama .card,.pmn__sisi .card{margin:0}
.pmn__dua{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:var(--sp-4)}

.pmn__hero{position:relative;overflow:hidden;border-radius:var(--r-xl);min-height:250px;
  box-shadow:var(--sh-md);display:flex;align-items:center}
.pmn__hero__latar{position:absolute;inset:0;z-index:0}
.pmn__hero__b{position:relative;z-index:2;padding:var(--sp-6);max-width:min(60ch,62%)}
.pmn__hero__eyebrow{margin:0 0 var(--sp-1);font-size:var(--fs-13);font-weight:var(--fw-black);
  letter-spacing:.08em;text-transform:uppercase;color:var(--brand-text)}
.pmn__hero__t{margin:0;font-size:var(--fs-42);font-weight:var(--fw-black);line-height:1.1;color:var(--ink)}
.pmn__hero__s{margin:var(--sp-2) 0 0;color:var(--ink);font-size:var(--fs-16);
  text-shadow:0 1px 8px rgba(255,255,255,.75)}
.pmn__hero__otter{position:absolute;right:var(--sp-5);bottom:0;z-index:2;width:180px;height:auto}

.pmn__fakta{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--sp-2);
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--sp-4);box-shadow:var(--sh-sm)}
.pmn__f{display:flex;flex-direction:column;align-items:center;text-align:center;gap:2px}
.pmn__f__ic{font-size:var(--fs-20)}
.pmn__f__k{font-size:var(--fs-12);font-weight:var(--fw-bold);color:var(--ink-2);
  letter-spacing:.04em;text-transform:uppercase}
.pmn__f__v{font-size:var(--fs-20);font-weight:var(--fw-black);color:var(--brand-text);
  font-variant-numeric:tabular-nums}

.pmn__no{display:inline-grid;place-items:center;width:26px;height:26px;border-radius:50%;
  background:var(--brand);color:#fff;font-size:var(--fs-14);font-weight:var(--fw-black);
  margin-right:var(--sp-2);vertical-align:middle}
.pmn__blok h2{margin:0 0 var(--sp-3)}
.pmn__pilih{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:var(--sp-3)}
.pmn__pilih--kecil{grid-template-columns:repeat(auto-fit,minmax(110px,1fr))}
.pmn__opt{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:var(--sp-4);
  border:2px solid var(--line);border-radius:var(--r-lg);background:var(--surface);
  font:inherit;text-align:left;color:var(--ink);cursor:pointer}
.pmn__opt:hover{border-color:var(--brand-soft)}
.pmn__opt.is-on{border-color:var(--brand);background:var(--brand-soft)}
.pmn__opt--kecil{align-items:center;text-align:center;padding:var(--sp-3)}
.pmn__opt__ic{font-size:var(--fs-24)}
.pmn__k{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-2) 0}
.pmn__k.is-off{opacity:.45}
.pmn__k span span{display:block}
.pmn__k__ic{display:grid;place-items:center;width:40px;height:40px;flex:none;border-radius:50%;
  background:var(--sky-100);font-size:var(--fs-18)}
.pmn__akses{display:flex;flex-direction:column;gap:var(--sp-2);margin-top:var(--sp-3)}
.pmn__sw{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);
  padding:var(--sp-3);border:1px solid var(--line);border-radius:var(--r-md);cursor:pointer}
.pmn__sw span span{display:block;color:var(--ink-2)}
.pmn__pratinjau{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));
  gap:var(--sp-3);margin-top:var(--sp-3)}
.pmn__pv{margin:0}
.pmn__pv__l{position:relative;aspect-ratio:14/10;border-radius:var(--r-md);overflow:hidden;
  box-shadow:var(--sh-sm)}
/* 미리보기가 열 장이라 움직임까지 열 벌 돌리면 느린 기기에서 눈에 띄게 버벅인다 */
.pmn__pv__l .lt-awan,.pmn__pv__l .lt-kabut,.pmn__pv__l .lt-asap,
.pmn__pv__l .lt-bintang circle,.pmn__pv__l .lt-kunang circle,
.pmn__pv__l .lt-gelembung circle{animation:none}
.pmn__pv figcaption{margin-top:6px;font-size:var(--fs-12);color:var(--ink-2)}
.pmn__pv figcaption b{color:var(--brand-text)}
.pmn__mulai{text-align:center}
.pmn__mulai .t-small{margin-top:var(--sp-2);color:var(--ink-2)}
.pmn__hadiah{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp-2);margin-top:var(--sp-3)}
.pmn__h{display:flex;align-items:center;gap:var(--sp-2);padding:var(--sp-3);
  background:var(--surface-2);border-radius:var(--r-md)}
.pmn__h span span{display:block}
.pmn__h b{font-size:var(--fs-18);font-variant-numeric:tabular-nums}
.pmn__h__ic{display:grid;place-items:center;width:36px;height:36px;flex:none;border-radius:50%;
  background:#fff;font-size:var(--fs-13);font-weight:var(--fw-black)}
.pmn__h--xp .pmn__h__ic{background:var(--sky-500);color:#fff}
.pmn__h--bintang .pmn__h__ic{background:var(--amber-100)}
.pmn__h--api .pmn__h__ic{background:var(--red-100)}
.pmn__h--lv .pmn__h__ic{background:var(--brand);color:#fff}
@media (max-width:1100px){
  .pmn__kolom{grid-template-columns:minmax(0,1fr)}
  .pmn__hero__otter{display:none}
  .pmn__hero__b{max-width:none}
}

/* ── 순위표 ───────────────────────────────────────────────────────── */
.prg{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:var(--sp-5);align-items:start}
.prg__utama,.prg__sisi{display:flex;flex-direction:column;gap:var(--sp-5)}
.prg__utama .card,.prg__sisi .card{margin:0}
.prg__head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);flex-wrap:wrap}
.prg__l{list-style:none;margin:var(--sp-3) 0 0;padding:0;display:flex;flex-direction:column;gap:var(--sp-2)}
.prg__r{display:grid;grid-template-columns:36px 34px minmax(0,1fr) auto auto auto;align-items:center;
  gap:var(--sp-3);padding:var(--sp-2) var(--sp-3);border-radius:var(--r-md);background:var(--surface-2)}
.prg__r--atas{background:var(--amber-100)}
.prg__r.is-aku{outline:2px solid var(--brand);background:var(--brand-soft)}
.prg__r--kosong{grid-template-columns:36px minmax(0,1fr);background:transparent;
  border:1px dashed var(--line);color:var(--ink-3)}
.prg__no{font-size:var(--fs-18);font-weight:var(--fw-black);color:var(--ink-2);text-align:center}
.prg__av{display:grid;place-items:center;width:34px;height:34px;border-radius:var(--r-pill);
  background:var(--brand);color:#fff;font-weight:var(--fw-black)}
.prg__nama{display:flex;flex-direction:column;min-width:0}
.prg__nama b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.prg__chip{white-space:nowrap;color:var(--ink-2)}
.prg__skor{font-size:var(--fs-20);font-weight:var(--fw-black);color:var(--brand-text);
  font-variant-numeric:tabular-nums;text-align:right}
.prg__misi{display:flex;flex-direction:column;gap:var(--sp-3);margin-top:var(--sp-3)}
.prg__m{display:grid;grid-template-columns:40px minmax(0,1fr) auto;align-items:center;gap:var(--sp-3);
  padding:var(--sp-3);border-radius:var(--r-md);background:var(--surface-2)}
.prg__m.is-on{background:var(--green-100)}
.prg__m__i{font-size:var(--fs-20);text-align:center}
.prg__m__t{margin:0 0 var(--sp-1);font-weight:var(--fw-bold);color:var(--ink)}
.prg__m__v{font-variant-numeric:tabular-nums;color:var(--ink-2)}
.prg__sumber li{margin-bottom:var(--sp-2)}
.prg__guru{display:flex;flex-direction:column;gap:var(--sp-2);margin:var(--sp-3) 0}
@media (max-width:1100px){
  .prg{grid-template-columns:minmax(0,1fr)}
  .prg__r{grid-template-columns:30px 30px minmax(0,1fr) auto;gap:var(--sp-2)}
  .prg__r .prg__chip{display:none}
}

/* ── 휴대전화 아래 탭줄 (shell.js 의 `mountTabbar`) ──────────────────────
   사이드바는 1100px 이상 전용이라 그 아래에는 **전역 차림표가 아예 없었다** —
   쪽마다 손으로 쓴 머리말 링크(index 15개 … masuk 1개)가 유일한 길이었고,
   대부분의 쪽에서 지도·게임으로 갈 수 없었다. 현장 기기는 휴대전화가 많다(2026-08-30).
   사이드바와 **같은 배열**(shell.js 의 `NAV`)에서 나오므로 둘이 갈릴 수 없다. */
.tabbar{position:fixed;left:0;right:0;bottom:0;z-index:var(--z-nav);display:flex;align-items:stretch;
  background:var(--surface);border-top:1px solid var(--line);
  padding-bottom:env(safe-area-inset-bottom);box-shadow:0 -2px 12px rgba(0,0,0,.06)}
.tabbar__i{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:2px;padding:7px 2px 8px;text-decoration:none;color:var(--ink-3);font-weight:600}
.tabbar__ic{font-size:19px;line-height:1}
.tabbar__t{font-size:11px;line-height:1.25;text-align:center;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tabbar__i.is-active{color:var(--brand)}
.tabbar__i:focus-visible{outline:2px solid var(--brand);outline-offset:-3px;border-radius:6px}
/* 탭줄이 마지막 카드를 가리지 않게 자리를 비운다. 교사 화면(has-side)은 본문만 스크롤하므로
   본문 안쪽에 넣는다 — body 에 넣으면 고정 틀이 밀린다. */
body.has-tabbar:not(.has-side){padding-bottom:calc(58px + env(safe-area-inset-bottom))}
body.has-tabbar.has-side > .main > main{padding-bottom:calc(58px + env(safe-area-inset-bottom))}
@media (min-width:1100px){
  .tabbar{display:none}
  body.has-tabbar:not(.has-side){padding-bottom:0}
  body.has-tabbar.has-side > .main > main{padding-bottom:0}
}
@media print{ .tabbar{display:none!important} body.has-tabbar{padding-bottom:0} }

/* ── 받아쓰기 모드 (app.js 의 `tulis`) ──────────────────────────────────
   정음을 가리고 라틴 표기를 문제로 삼는다. 그러니 로마자가 **보조 표기가 아니라
   문제 자체**가 되므로 크게 세운다. 모든 연습이 «보고 따라치기» 라 표기 능력을
   한 번도 묻지 않았다(2026-08-30). */
.roman.is-prompt{font-size:var(--fs-28);font-weight:700;color:var(--ink);letter-spacing:.01em;text-align:center}
.scene.is-tulis .target{opacity:.85}
.scene.is-tulis .scene__say{visibility:hidden}   /* /rom/ 을 두 번 보여 주지 않는다 */

/* ── 복습 카드 (ulang.js) ──────────────────────────────────────────── */
.ulang-card{display:grid;grid-template-columns:1fr auto;gap:var(--sp-4);align-items:center}
/* 연습 화면의 `.tile`(88×96, 점선)을 여기서 쓰면 «빈 칸» 처럼 보인다 — 여기 글자는
   채워야 할 자리가 아니라 **이미 정해진 결과**다. 따로 작은 칩으로 둔다. */
.ul__huruf{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin-top:var(--sp-3)}
.ul__h{display:inline-flex;align-items:center;justify-content:center;min-width:40px;height:40px;
  padding:0 8px;border-radius:var(--r-md);background:var(--warn-soft,var(--surface-2));
  border:1px solid var(--line);font-size:var(--fs-24);line-height:1;color:var(--ink)}
@media (max-width:720px){ .ulang-card{grid-template-columns:1fr} }


/* ── 구역 목차 · 사이드바 갈래 · «Lainnya» 시트 (shell.js) ───────────────
   차림표를 줄이면서 쪽마다의 손수 링크를 걷어냈더니 **가로 이동이 끊겼다** —
   자모표에서 전자 변환으로, 자판 안내에서 설치 안내로 갈 길이 사라졌고
   `ejaan.html` 은 한동안 어디서도 닿을 수 없었다(2026-08-30).
   그래서 «줄인 차림표 + 구역 목차» 두 층으로 둔다. 셋 다 `SEKSI` 배열 하나에서 나온다. */

/* 구역 목차 — 본문 맨 위의 칩 줄 */
.subnav{position:relative;z-index:1;display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap;
  margin:0 0 var(--sp-5);padding-bottom:var(--sp-3);border-bottom:1px solid var(--line)}
.subnav__k{font-size:var(--fs-12);font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);margin-right:var(--sp-2)}
.subnav__i{display:inline-flex;align-items:center;padding:5px 12px;border-radius:999px;
  border:1px solid var(--line);background:var(--surface);color:var(--ink-2);
  font-size:var(--fs-14);font-weight:600;text-decoration:none;white-space:nowrap}
.subnav__i:hover{border-color:var(--brand);color:var(--brand)}
.subnav__i.is-active{background:var(--brand);border-color:var(--brand);color:var(--ink-on-brand)}
@media print{ .subnav{display:none} }

/* 사이드바 갈래 이름 — 아홉 줄이 한 덩어리로 보이지 않게 */
.side__grup{margin:var(--sp-4) 0 var(--sp-1);padding:0 var(--sp-3);
  font-size:var(--fs-11,11px);font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.side__nav > .side__grup:first-child{margin-top:0}

/* «Lainnya» 시트 — 탭줄에 못 담은 구역과 그 화면 전부 */
.lain{position:fixed;inset:0;z-index:var(--z-sheet);display:flex;align-items:flex-end}
.lain__bg{position:absolute;inset:0;background:rgba(10,43,49,.45)}
.lain__box{position:relative;width:100%;max-height:78vh;overflow-y:auto;
  border-radius:var(--r-lg) var(--r-lg) 0 0;margin:0;
  padding-bottom:calc(58px + var(--sp-5) + env(safe-area-inset-bottom))}
.lain__head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin-bottom:var(--sp-3)}
.lain__head h2{margin:0}
.lain__s{padding:var(--sp-3) 0;border-top:1px solid var(--line)}
.lain__t{display:inline-flex;align-items:center;gap:var(--sp-2);font-weight:700;color:var(--ink);
  text-decoration:none;font-size:var(--fs-16)}
.lain__l{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin-top:var(--sp-2)}
.lain__i{display:inline-flex;padding:5px 12px;border-radius:999px;border:1px solid var(--line);
  background:var(--surface-2);color:var(--ink-2);font-size:var(--fs-14);text-decoration:none}
.lain__i.is-active{background:var(--brand);border-color:var(--brand);color:var(--ink-on-brand)}
html.lain-open,html.lain-open body{overflow:hidden}
@media (min-width:1100px){ .lain{display:none} }

/* ── 복구 코드 (sync.js · masuk.html) ────────────────────────────────────
   익명 신원만으로는 계정이 브라우저 저장소만큼만 오래 산다. 옮겨 적을 코드이므로
   글자를 크고 넓게, 숫자와 글자가 헷갈리지 않게 고정폭으로 둔다. */
.kode-box{margin-top:var(--sp-5);padding:var(--sp-4);border:2px dashed var(--brand);
  border-radius:var(--r-lg);background:var(--brand-soft,var(--surface-2))}
.kode-box h3{margin:0 0 var(--sp-2)}
.kode{font-family:var(--font-mono,ui-monospace,monospace);font-size:var(--fs-32);font-weight:700;
  letter-spacing:.12em;color:var(--brand-text,var(--ink));margin:var(--sp-3) 0;text-align:center;
  user-select:all;word-break:break-all}
.kode-input{font-family:var(--font-mono,ui-monospace,monospace);letter-spacing:.08em;text-transform:uppercase;max-width:15em}
@media (max-width:560px){ .kode{font-size:var(--fs-24)} }

/* 축하 카드가 최상위 레이어를 놓치더라도 본문 뒤로 가라앉지 않게 한다.
   `main` 은 `position:relative;z-index:1` 이라 쌓임 맥락을 만든다 — 모달이 아닌 채로 열린
   `<dialog>` 는 그 아래에 깔려, 카드와 카드 사이로만 비쳐 보였다(2026-08-30 신고).
   모달일 때는 이 값이 쓰이지 않는다(최상위 레이어는 z-index 를 보지 않는다). 그물일 뿐이다. */
.raya{z-index:var(--z-sheet)}

/* ── 설치형 입력기 내려받기 (pasang.html) ────────────────────────────────
   파일은 하나이고 Windows·macOS 가 갈리지 않는다 — 갈리는 것은 안내뿐이라
   내려받기는 갈래 위에 한 번만 둔다. 체크섬을 보이는 이유는 이 파일이 교실에서
   USB 로 돌아다니기 때문이다(받은 것이 우리가 만든 그것인지 대조할 수단). */
.unduh{display:grid;grid-template-columns:1fr auto;gap:var(--sp-4);align-items:center}
.unduh__a{display:flex;flex-direction:column;gap:var(--sp-2);align-items:stretch}
.unduh__sha{font-size:var(--fs-12);word-break:break-all;color:var(--ink-3)}
.unduh__note{grid-column:1/-1;margin:0;color:var(--ink-3)}
@media (max-width:720px){ .unduh{grid-template-columns:1fr} }

/* ── 연습 화면을 화면 높이에 맞춘다 ──────────────────────────────────────
   노트북(높이 949px)에서 자판 아래쪽이 **262px 잘려 있었다** — 글자와 자판을
   한 화면에서 같이 볼 수 없으면 타자 연습이 성립하지 않는다.
   재 보니 낭비는 몇 군데에 몰려 있었다: `.scene` 의 아래 여백 104px(섬 그림 자리),
   목표 글자의 줄 높이 1.6, 빈 타일 줄의 96px, 그리고 진행·계기 줄의 여백.
   **너비가 아니라 높이로 가른다** — 낮은 화면이 문제이지 좁은 화면이 아니다. */
@media (max-height: 980px) {
  /* 섬 그림은 장식이다. 그 자리를 비워 두느라 104px 을 쓰고 있었다. */
  /* `.scene` 는 `min-height:230px` 로 고정돼 있어, 내용이 193px 뿐인데도 230px 을 썼다.
     섬 그림을 감춘 마당에 자리를 비워 둘 이유가 없다. */
  .scene{padding:var(--sp-3) var(--sp-4);min-height:0}
  .scene__say{margin-top:var(--sp-1)}
  .scene__listenwrap{margin-bottom:var(--sp-1)}
  .scene__listen{padding:4px 12px}
  .scene__island{display:none}
  .target{line-height:1.25;min-height:1.25em}
  .roman{margin:0 0 var(--sp-2)}
  .tiles{margin:var(--sp-3) 0;min-height:0}
  .tile{height:76px;min-width:72px;font-size:var(--fs-32)}
  .hint{margin-top:var(--sp-1)}
  /* 진행 줄은 세로로 쌓여 있어 한 줄에 73px 을 썼다. 눕히면 26px 이면 된다 —
     정보는 그대로 두고 자리만 줄인다(머리말의 «1 / 23» 과 중복이라 지우고 싶었지만,
     목업이 정한 요소다). */
  .steps3{margin-top:var(--sp-2);padding-top:var(--sp-2)}
  .steps3__c{flex-direction:row;gap:var(--sp-2);min-width:0}
  .steps3__v{width:26px;height:26px;font-size:var(--fs-13)}
  .steps3__k{font-size:var(--fs-12)}
  .metrics{margin-top:var(--sp-2);padding-top:var(--sp-2)}
  .metric__v{font-size:var(--fs-24)}
  .prac-card{margin-bottom:var(--sp-3);padding:var(--sp-4)}
  /* 자판이 마지막 한 줄만 걸쳐 잘리는 것을 없앤다 — 손가락 도해가 잘리면 안내가 반쪽이 된다. */
  .keyboard{--kh:36px}
}
/* 더 낮은 화면(태블릿 가로·작은 노트북)에서는 자판 자체도 한 단 줄인다. */
@media (max-height: 820px) {
  .scene{padding:var(--sp-3) var(--sp-4)}
  .target{font-size:var(--fs-32)}
  .tile{height:64px;min-width:60px;font-size:var(--fs-24)}
  .keyboard{--kh:34px;--kfs:14px}
  .steps3{display:none}          /* 진행은 머리말의 «n / m» 이 이미 말한다 */
}

/* ── 사이드바 마스코트를 배경으로 ────────────────────────────────────────
   지금까지는 flex 흐름의 마지막 항목이라 **메뉴 개수에 따라 위치가 밀렸고**,
   `.side` 의 `overflow:hidden` 에 얼굴까지 잘렸다(2026-08-30 신고).
   차림표가 아홉 줄로 늘어난 뒤로 특히 심해졌다.
   흐름에서 빼내 기둥 바닥에 붙이면, 메뉴가 몇 줄이든 늘 같은 자리에 있는다.
   사이드바는 1100px 이상에서만 세로 기둥이므로 그 안에서만 바꾼다 —
   좁은 화면에서 `.side` 는 가로로 눕는다(교사 화면의 옛 배치). */
@media (min-width:1100px) {
  /* 기둥을 세 덩이로 나눈다: 상표(고정) · 차림표(**여기가 스크롤**) · 아래 장식(고정).
     예전에는 그림을 150px 띠에 `object-fit:cover` 로 **잘라** 넣었는데, 원본이 232×254 라
     아래 42% 가 통째로 날아갔다 — 마스코트의 다리가 잘린 채로 배포돼 있었다.
     이제 자르지 않는다. 대신 차림표가 안에서 스크롤한다: 차림표가 몇 줄로 늘어나든
     마스코트는 늘 바닥에 온전히 남는다(그게 «메뉴 목록과 상관없이» 의 뜻이다).
     기둥 전체가 스크롤하면 안 된다 — 그러면 그림이 스크롤과 함께 떠내려간다. */
  .side{display:flex;flex-direction:column;padding-bottom:0;overflow:hidden}
  .side__brand,.side__note{flex:0 0 auto}
  .side__nav{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain}
  /* 기둥 **끝까지** 채운다. 좌우 여백(--sp-4)을 음수 여백으로 되물리고 바닥에 붙인다 —
     가운데에 작게 띄워 두면 그림 둘레에 흰 자리가 생겨 «떠 있는» 것처럼 보인다.
     자리가 모자라면 `flex-shrink` 로 줄되 **위에서만** 잘린다(`object-position:bottom`):
     잎사귀와 발은 남고, 아쉬우면 든 손이 먼저 잘린다. 아래를 자르는 것과는 다른 이야기다. */
  .side__art{position:static;flex:0 1 auto;min-height:96px;align-self:stretch;
    width:calc(100% + var(--sp-4) * 2);max-width:none;height:auto;
    margin:0 calc(var(--sp-4) * -1);object-fit:cover;object-position:center bottom}
}
/* 자리를 다투는 것은 넷이다: 상표 · 차림표(12줄) · 인용 카드 · 마스코트.
   1000px 이하 높이(웬만한 노트북)에서는 다 들어가지 않는다. 밀려나는 순서는
   **장식 먼저, 기능은 나중**이다 — 인용 카드를 먼저 감추고 마스코트를 줄여
   차림표 열두 줄이 스크롤 없이 다 보이게 한다. */
@media (min-width:1100px) and (max-height:1000px) {
  .side__note{display:none}
  /* 줄 간격을 줄여 열두 줄이 스크롤 없이 들어오게 한다. 줄이지 않으면 «Beranda» 가 위로
     밀려 나가 첫 화면으로 돌아가는 길이 안 보인다 — 장식보다 이쪽이 먼저다. */
  .side__item{padding:8px 14px}
  .side__nav{gap:2px}
  .side__grup{margin:var(--sp-3) 0 0}
}
@media (min-width:1100px) and (max-height:760px) {
  /* 아주 낮은 화면 — 그림이 차지할 최소 높이를 더 낮춘다. 폭은 줄이지 않는다:
     좁히면 다시 둘레에 흰 자리가 생긴다. 줄어드는 만큼 위에서 잘린다. */
  .side__art{min-height:72px}
}
/* 그래도 모자라면 차림표가 안에서 스크롤한다. 잘린 것처럼 보이지 않게 아래를 흐린다 —
   스크롤할 수 있다는 표시가 없으면 «메뉴가 사라졌다» 로 읽힌다. */
@media (min-width:1100px) {
  .side__nav{
    mask-image:linear-gradient(to bottom, #000 calc(100% - 18px), transparent);
    -webkit-mask-image:linear-gradient(to bottom, #000 calc(100% - 18px), transparent);
    scrollbar-width:thin}
  .side__nav:not(:hover){scrollbar-color:transparent transparent}
}

/* I-2 «글자가 안 붙는다» — 데스크톱에서 앱의 글꼴이 옛한글을 조합하지 않을 때의 안내 */
.gab__font{margin:0;padding-left:1.2em}
.gab__contoh{display:grid;grid-template-columns:auto 1fr;gap:var(--sp-2) var(--sp-4);align-items:baseline;
  margin:var(--sp-4) 0;padding:var(--sp-4);border-radius:var(--r-md);background:var(--surface-2)}
.gab__contoh p{margin:0}
.gab__contoh .cia{font-size:var(--fs-24)}
.gab__font li + li{margin-top:var(--sp-2)}
.unduh--font{padding:var(--sp-4);border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--surface-2);margin:var(--sp-4) 0}
@media (max-width:640px){.unduh--font{grid-template-columns:1fr}}

/* 아바타 얼굴 — 시트(`assets/wajah-<열>x<행>.webp`) 한 칸. 주소와 배경 크기는 `avatar.js` 가
   CSS 변수로 넘긴다: 격자를 두 곳에 적으면 언젠가 갈린다. 시트가 실제로 받아진 뒤에만 덮는다 —
   담기지 않은 자산이라 없을 수 있고, 그때는 밑에 있는 «색+첫 글자» 가 그대로 보인다. */
[data-wajah] .pdot.wajah,
[data-wajah] .wajah{color:transparent;background-image:var(--wajah-url);background-size:var(--wajah-size);background-position:var(--bx,0%) var(--by,0%);
  background-repeat:no-repeat}
/* 고르기 판 — 얼굴 100개. 손가락으로 고르므로 칸을 44px 아래로 내리지 않는다. */
.wajah-pilih{display:grid;grid-template-columns:repeat(auto-fill,minmax(48px,1fr));gap:var(--sp-2);
  max-height:44vh;overflow-y:auto;padding:var(--sp-2);border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--surface-2)}
.wajah-pilih button{aspect-ratio:1;border:2px solid transparent;border-radius:50%;padding:0;cursor:pointer;
  background:var(--amber-100);color:var(--ink-2);font:inherit;font-weight:800}
[data-wajah] .wajah-pilih button{color:transparent;background-image:var(--wajah-url);background-size:var(--wajah-size);background-position:var(--bx,0%) var(--by,0%);background-repeat:no-repeat}
.wajah-pilih button[aria-pressed="true"]{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent)}
.wajah-pilih button:focus-visible{outline:3px solid var(--accent);outline-offset:2px}

/* ── 첫 화면(awal.html) 개편 — 시안: 04-디자인/자산/랜딩/ ────────────────
   그림은 배경으로 깔고 글과 단추는 살아 있는 요소로 얹는다. 시안에 구워진 글씨를 그대로
   쓰면 번역도 안 되고 눌리지도 않는다. 타일의 글자는 **실제 자모**를 CiaCia Sans 로 찍는다 —
   시안 그림의 낱자는 자모 흉내였다. */
/* 그림은 **배경**이다 — 액자에 넣지 않는다. 오른쪽에 붙이고 왼쪽 가장자리를 마스크로 흐려
   배경에 녹인다: 그림의 왼쪽 끝이 구름·파도·바위라 그라데이션으로는 이어 붙지 않는다.
   `cover` 는 쓰지 않는다 — 가로로 긴 칸에서는 위아래를 잘라 마스코트의 머리가 날아간다.
   높이에 맞춰(`auto 100%`) 온전히 두고, 남는 왼쪽은 하늘·모래 톤의 옅은 그라데이션이 채운다. */
.lead{position:relative;overflow:hidden;display:flex;align-items:center;
  min-height:320px;
  background:linear-gradient(150deg,#EAF7FE 0%,#F5FBFD 48%,#FBF5E9 100%)}
/* 글 칸은 단추 셋이 **한 줄**에 들어갈 만큼은 준다. 좁히면 단추가 세 줄로 접히고,
   그만큼 카드가 길어지면서 높이에 맞춰 그린 그림이 거인처럼 커진다. */
.lead__body{position:relative;z-index:1;flex:1 1 520px;max-width:min(52%,560px)}
.lead__art{position:absolute;inset:0 0 0 auto;width:min(52%,620px);pointer-events:none;
  background:url(assets/awal-hero.webp) right center/auto 100% no-repeat;
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 32%);
          mask-image:linear-gradient(90deg,transparent 0,#000 32%)}
@media (max-width:900px){
  /* 좁은 화면에서는 글 위에 띠로 얹는다. 흐리는 방향도 아래쪽으로 바꾼다. */
  .lead{display:flex;flex-direction:column;padding-top:150px}
  .lead__body{max-width:none}
  .lead__art{inset:0 0 auto 0;width:100%;height:190px;background-position:center top;
    background-size:cover;
    -webkit-mask-image:linear-gradient(180deg,#000 60%,transparent 100%);
            mask-image:linear-gradient(180deg,#000 60%,transparent 100%)}
}

.mulai{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:var(--sp-3);
  margin-top:var(--sp-3)}
.mulai__k{display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-3);
  border:1px solid var(--line);border-radius:var(--r-lg);background:var(--surface);
  text-decoration:none;color:inherit;transition:box-shadow var(--dur-fast),transform var(--dur-fast)}
.mulai__k:hover{box-shadow:var(--sh-md);transform:translateY(-2px)}
.mulai__g{display:flex;align-items:center;justify-content:center;gap:var(--sp-2);
  height:104px;border-radius:var(--r-md);background:var(--surface-2);overflow:hidden}
.mulai__g img{width:100%;height:100%;object-fit:cover;display:block;background:#fff}
.mulai__g--ubin{background:linear-gradient(180deg,#F4FAFF,#EAF4FF)}
.mulai__g--hujan{position:relative;flex-direction:column;gap:2px;padding-top:var(--sp-1);
  background:linear-gradient(180deg,#EFF7FF,#E3F0FB)}
.mulai__g--hujan .awan{width:auto;height:46px;display:block}
.mulai__g--hujan .ubin{width:26px;height:26px;font-size:var(--fs-14)}
.mulai__g--hujan{display:grid;grid-template-columns:repeat(3,auto);grid-template-rows:auto auto;
  place-items:center;gap:var(--sp-1)}
.mulai__g--hujan .awan{grid-column:1/-1}
.mulai__t{font-weight:var(--fw-bold);color:var(--ink)}
.mulai__d{color:var(--ink-2)}

/* 낱자 타일 — 시안의 둥근 사각형을 CSS 로 다시 그린다(글자가 진짜여야 하므로) */
.ubin{display:inline-flex;align-items:center;justify-content:center;width:38px;height:44px;
  border-radius:10px;box-shadow:0 2px 0 rgba(16,44,52,.12);font-size:var(--fs-20)}
.ubin .cia{font-family:var(--font-cia);font-weight:var(--fw-bold)}
.ubin--t{background:#CDEDF2;color:var(--brand-text)}
.ubin--a{background:#FCE9BE;color:#8A5A12}
.ubin--h{background:#D6EFD8;color:#2F6B41}
.ubin--b{background:#D8E6FB;color:#274C86}
.ubin__panah{color:var(--ink-2);font-weight:var(--fw-black)}

.awal__duo{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-4);align-items:start}
.awal__duo > .card{margin:0}
@media (max-width:860px){.awal__duo{grid-template-columns:1fr}}
.kode-kelas__f{display:flex;gap:var(--sp-2);margin-top:var(--sp-2)}
.kode-kelas__f .input{flex:1 1 auto;min-width:0;letter-spacing:.14em;font-variant-numeric:tabular-nums}
.kode-kelas__f .btn{flex:0 0 auto}

/* ── 첫 화면의 «무엇을 쓸 수 있나» 아홉 칸 (시안: 04-디자인/자산/랜딩) ─────
   아이콘 배지·제목·화살표가 **같은 색**을 쓰고 카드 바탕만 옅게 깐다.
   시안의 삽화는 넣지 않았다 — 시안 자체가 카드당 330px 이라 2× 화면에서 뭉갠다.
   그림이 필요하면 낱장으로 다시 받아야 한다(카드 크롭은 이미 한 번 실패했다). */
.lead__grid{grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}
.feat{position:relative;gap:var(--sp-2);padding:var(--sp-4);padding-bottom:58px;
  border:1px solid var(--line);border-radius:var(--r-lg);background:var(--feat-bg,var(--surface));
  transition:box-shadow var(--dur-fast),transform var(--dur-fast)}
.feat:hover{box-shadow:var(--sh-md);transform:translateY(-2px)}
.feat__i{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;
  border-radius:50%;background:var(--feat-c,var(--brand));color:#fff;font-size:20px;line-height:1}
.feat__t{font-weight:var(--fw-black);color:var(--feat-c,var(--brand-text))}
.feat__d{color:var(--ink-2)}
.feat__go{position:absolute;right:var(--sp-4);bottom:var(--sp-3);
  display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;
  border-radius:50%;background:var(--feat-c,var(--brand));color:#fff;font-weight:var(--fw-black)}
.feat--t{--feat-c:#0E8C9E;--feat-bg:#F2FAFB}
.feat--o{--feat-c:#E1701A;--feat-bg:#FDF6EF}
.feat--b{--feat-c:#2B6CB0;--feat-bg:#F1F6FC}
.feat--v{--feat-c:#6B46C1;--feat-bg:#F6F3FD}
.feat--g{--feat-c:#2F7D4F;--feat-bg:#F1FAF3}
.feat--s{--feat-c:#1F7FA8;--feat-bg:#F0F8FC}
.feat--r{--feat-c:#C2385F;--feat-bg:#FDF2F5}
.feat--a{--feat-c:#B07408;--feat-bg:#FDF8EC}

/* 첫 화면 아래쪽 «약속» 셋 (시안 하단 띠) */
.janji{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:var(--sp-4)}
.janji__i{display:flex;gap:var(--sp-3);align-items:flex-start}
.janji__i p{margin:2px 0 0;color:var(--ink-2)}
.janji__ic{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;
  width:44px;height:44px;border-radius:var(--r-md);font-size:22px}
.janji__ic--b{background:#EEF6FB} .janji__ic--t{background:#E4F5F7} .janji__ic--g{background:#E8F6EC}
/* 삽화는 **카드 배경**이다 — 가운데에 작게 놓으면 둘레에 흰 자리가 생겨 초라해 보인다.
   시안처럼 오른쪽 아래에 크게 깔고 모서리 밖으로 살짝 흘려 보낸다.
   원본이 흰 바탕이라 `multiply` 로 카드 색에 녹인다(투명 PNG 를 따로 만들 필요가 없다).
   글은 그 위에 오되, 왼쪽 위로 옅은 막을 깔아 읽는 데 지장이 없게 한다. */
.feat{overflow:hidden;min-height:230px}
.feat__art{position:absolute;right:-10px;bottom:-10px;width:66%;height:auto;max-width:none;
  mix-blend-mode:multiply;pointer-events:none;z-index:0}
.feat::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:linear-gradient(155deg,var(--feat-bg,var(--surface)) 0%,
    var(--feat-bg,var(--surface)) 46%,transparent 82%)}
/* 화살표는 **절대 위치 그대로** 둔다 — 여기서 `relative` 를 주면 오른쪽 아래 고정이 풀려
   글 사이로 끼어든다(실제로 그렇게 됐다). 나머지만 그림 위로 올린다. */
.feat__i,.feat__t,.feat__d{position:relative;z-index:1}
.feat__go{z-index:1}
.feat__d{max-width:78%}
@media (prefers-reduced-motion:reduce){.feat:hover{transform:none}}
