/* Haeyo Korean — v2 spec layer (2026-10-23). The rules that make the system buildable and maintainable, after the owner's
   comparison with a commerce design-system guide: one type scale, two-and-a-half line heights, one spacing scale, equal heights
   for every form control, six states, 4.5:1 contrast, empty/error states, one of each overlay. Load after v2.css (mocks) or
   v2site.css (site). Nothing here changes the look; it fixes the numbers. Mobile first. */
:root{
  /* type scale · 9 steps + the two poster sizes (clamp). Nothing a learner reads is under 12px. */
  --fs-12:12px; --fs-14:14px; --fs-16:16px; --fs-18:18px; --fs-20:20px; --fs-24:24px; --fs-32:32px; --fs-40:40px; --fs-48:48px;
  --fs-poster:clamp(34px,9vw,92px); --fs-glyph:clamp(96px,32vw,240px);
  /* line heights · 120 (titles, English, one-liners) · 140 (Korean titles, short runs) · 160 (Korean body) */
  --lh-tight:1.2; --lh-snug:1.4; --lh-body:1.6;
  /* tracking · Latin tight, Hangeul never tracked */
  --ls-tight:-.025em; --ls-caps:.12em; --ls-ko:0;
  /* spacing scale */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px; --sp-7:48px; --sp-8:64px; --sp-9:96px;
  /* radii · 3 only */
  --rd-s:12px; --rd-m:18px; --rd-pill:9999px;
  /* form controls · equal heights for button = input = select, four sizes (52 = phone bottom CTA) */
  --h-xl:52px; --h-l:48px; --h-m:40px; --h-s:36px;
  /* contrast-safe greys (on white): ink 18:1 · ink2 10:1 · mute 4.6:1 · mute2 4.5:1 · lines are decorative */
  --mute2:#767d8b;
  /* one shadow, one focus ring */
  --sh-desk:0 10px 30px -18px rgba(11,11,12,.25);
  --ring:0 0 0 3px #fff,0 0 0 5px var(--ink,#0b0b0c);
}
/* ---------- type classes (use these, not ad-hoc sizes) ---------- */
.t-12{font-size:var(--fs-12);line-height:var(--lh-snug)}.t-14{font-size:var(--fs-14);line-height:var(--lh-body)}.t-16{font-size:var(--fs-16);line-height:var(--lh-body)}
.t-18{font-size:var(--fs-18);line-height:var(--lh-snug)}.t-20{font-size:var(--fs-20);line-height:var(--lh-snug)}.t-24{font-size:var(--fs-24);line-height:var(--lh-tight)}
.t-32{font-size:var(--fs-32);line-height:var(--lh-tight)}.t-40{font-size:var(--fs-40);line-height:var(--lh-tight)}.t-48{font-size:var(--fs-48);line-height:var(--lh-tight)}
[lang=ko],.ko{letter-spacing:var(--ls-ko);word-break:keep-all;overflow-wrap:anywhere}
.cap,.eyebrow,.serial,.m3-bl,.mm-bl,.mm-lvl,.mm-lvl2,.m3-zone,.m3-free,.m3-here text,.mm-free,.mm-here{font-size:var(--fs-12) !important}
.mm-name,.m3-name,.mm-csub,.m3-csub,.m3-rl,.mm-rl,.m3-legend .lg-s,.m3-legend .lg-t,.m3-sign-ls span{font-size:var(--fs-12) !important}
.m3-legend .lg-h{font-size:var(--fs-16) !important}
/* ---------- focus · every interactive thing the same ring ---------- */
:focus-visible{outline:none !important;box-shadow:var(--ring)}
/* ---------- form controls · button = input = select, same height, same radius, six states ---------- */
.fc{display:inline-flex;align-items:center;gap:var(--sp-2);min-height:var(--h-l);padding:0 var(--sp-4);border:1.5px solid var(--line2,#d9d6cc);border-radius:var(--rd-pill);background:#fff;color:var(--ink,#0b0b0c);font:500 var(--fs-16)/var(--lh-tight) var(--ui,Inter,sans-serif);transition:border-color .15s,background .15s,box-shadow .15s}
.fc.xl{min-height:var(--h-xl)}.fc.m{min-height:var(--h-m);font-size:var(--fs-14);padding:0 var(--sp-3)}.fc.s{min-height:var(--h-s);font-size:var(--fs-14);padding:0 var(--sp-3)}
.fc.block{display:flex;width:100%}
input.fc,select.fc,textarea.fc{appearance:none;-webkit-appearance:none}
input.fc::placeholder,textarea.fc::placeholder{color:var(--mute2)}
select.fc{padding-right:40px;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230b0b0c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");background-repeat:no-repeat;background-position:right 14px center;background-size:16px}
textarea.fc{min-height:120px;padding:var(--sp-3) var(--sp-4);line-height:var(--lh-body);border-radius:var(--rd-m);resize:vertical}
.fc:hover{border-color:var(--ink,#0b0b0c)}
.fc:focus,.fc:focus-within{border-color:var(--ink,#0b0b0c);box-shadow:var(--ring)}
.fc[aria-invalid=true],.fc.err{border-color:var(--red,#e05252);background:var(--red-l,#fdeeee)}
.fc:disabled,.fc[aria-disabled=true]{background:var(--cream2,#f4efe3);color:var(--mute2);border-color:var(--line,#e8e6df);cursor:not-allowed}
/* busy: an <input>/<select> cannot draw ::after, so put .busy on a wrapper span.fc or on the button */
.fc.busy{color:transparent;position:relative;pointer-events:none}
.fc.busy:after{content:"";position:absolute;left:50%;top:50%;width:18px;height:18px;margin:-9px 0 0 -9px;border:2px solid var(--line2,#d9d6cc);border-top-color:var(--ink,#0b0b0c);border-radius:50%;animation:v2spin .8s linear infinite}
@keyframes v2spin{to{transform:rotate(360deg)}}
/* the buttons from v2.css get the same height tokens and states */
.btn{min-height:var(--h-l)}.btn.sm{min-height:var(--h-m)}.btn.xl{min-height:var(--h-xl)}
.btn.m{min-height:var(--h-m);padding:0 16px;font-size:var(--fs-14)}.btn.s{min-height:var(--h-s);padding:0 14px;font-size:var(--fs-14)} /* 10-23: m/s were missing, so button ≠ input at m/s */
.btn:active{transform:translateY(0);filter:brightness(.92)}
.btn:disabled,.btn[aria-disabled=true]{background:var(--cream2,#f4efe3);border-color:var(--line,#e8e6df);color:var(--mute2);box-shadow:none;cursor:not-allowed;transform:none}
.btn.busy{color:transparent;position:relative;pointer-events:none}
.btn.busy:after{content:"";position:absolute;left:50%;top:50%;width:18px;height:18px;margin:-9px 0 0 -9px;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:v2spin .8s linear infinite}
.btn.o.busy:after{border-color:var(--line2,#d9d6cc);border-top-color:var(--ink,#0b0b0c)}
/* field = label + control + help/error, fixed vertical rhythm */
.field{display:grid;gap:var(--sp-2);align-content:start} /* start: in a grid row next to a taller field the control must not stretch */
.field>label{font:700 var(--fs-14)/var(--lh-snug) var(--ui,Inter,sans-serif);color:var(--ink,#0b0b0c)}
.field .help{font:400 var(--fs-12)/var(--lh-snug) var(--ui,Inter,sans-serif);color:var(--mute,#6b7280)}
.field .err-msg{display:flex;gap:6px;align-items:flex-start;font:500 var(--fs-12)/var(--lh-snug) var(--ui,Inter,sans-serif);color:var(--red,#e05252)}
.field.err .fc{border-color:var(--red,#e05252);background:var(--red-l,#fdeeee)}
/* check · radio · switch (the 4 states incl. on+disabled) */
.ck{display:inline-flex;align-items:flex-start;gap:var(--sp-3);min-height:44px;cursor:pointer;font:400 var(--fs-16)/var(--lh-snug) var(--ui,Inter,sans-serif);color:var(--ink,#0b0b0c)}
.ck input{appearance:none;-webkit-appearance:none;width:22px;height:22px;margin:1px 0 0;border:2px solid var(--ink,#0b0b0c);border-radius:6px;background:#fff;flex:none;display:grid;place-items:center;cursor:pointer}
.ck input[type=radio]{border-radius:50%}
.ck input:checked{background:var(--ink,#0b0b0c)}
.ck input[type=checkbox]:checked:after{content:"";width:6px;height:11px;border:solid #fff;border-width:0 2.5px 2.5px 0;transform:translateY(-1px) rotate(45deg)}
.ck input[type=radio]:checked:after{content:"";width:8px;height:8px;border-radius:50%;background:#fff}
.ck input:disabled{border-color:var(--line2,#d9d6cc);background:var(--cream2,#f4efe3);cursor:not-allowed}
.ck input:disabled:checked{background:var(--line2,#d9d6cc)}
.ck input:disabled~span{color:var(--mute2)}
.sw{display:inline-flex;align-items:center;gap:var(--sp-3);min-height:44px;cursor:pointer;font:400 var(--fs-16)/var(--lh-snug) var(--ui,Inter,sans-serif)}
.sw input{appearance:none;-webkit-appearance:none;width:46px;height:28px;margin:0;border-radius:var(--rd-pill);background:var(--line2,#d9d6cc);position:relative;flex:none;cursor:pointer;transition:background .2s}
.sw input:after{content:"";position:absolute;left:3px;top:3px;width:22px;height:22px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.25);transition:transform .2s}
.sw input:checked{background:var(--ink,#0b0b0c)}.sw input:checked:after{transform:translateX(18px)}
.sw input:disabled{background:var(--cream2,#f4efe3);cursor:not-allowed}.sw input:disabled:after{box-shadow:none;background:var(--line,#e8e6df)}
.sw input:disabled:checked{background:var(--line2,#d9d6cc)}
/* ---------- underline tabs (Session 1 · 2, level filters where chips are too loud) ---------- */
.utabs{display:flex;gap:var(--sp-5);border-bottom:1px solid var(--line,#e8e6df);overflow-x:auto;scrollbar-width:none}
.utabs::-webkit-scrollbar{display:none}
.utabs button,.utabs a{appearance:none;border:0;background:none;padding:0 2px var(--sp-3);min-height:44px;font:600 var(--fs-16)/var(--lh-tight) var(--ui,Inter,sans-serif);color:var(--mute,#6b7280);white-space:nowrap;text-overflow:ellipsis;overflow:hidden;max-width:60vw;flex:none;position:relative;cursor:pointer;text-decoration:none}
.utabs [aria-selected=true],.utabs .on{color:var(--ink,#0b0b0c)}
.utabs [aria-selected=true]:after,.utabs .on:after{content:"";position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--ink,#0b0b0c);border-radius:3px 3px 0 0} /* bottom:0 — the button clips overflow (for the ellipsis), so -1px lost a pixel of the bar */
/* ---------- responsive table · first column fixed, text columns flexible, long cells clip ---------- */
.tbl{width:100%;border-collapse:collapse;font:400 var(--fs-14)/var(--lh-body) var(--ui,Inter,sans-serif)}
.tbl th,.tbl td{text-align:left;vertical-align:top;padding:var(--sp-3) var(--sp-2);border-top:1px solid var(--line,#e8e6df)}
.tbl thead th{border-top:0;border-bottom:1.5px solid var(--ink,#0b0b0c);font:700 var(--fs-12)/var(--lh-snug) var(--ui,Inter,sans-serif);letter-spacing:var(--ls-caps);text-transform:uppercase;color:var(--mute,#6b7280)}
.tbl .fix{white-space:nowrap;width:1%}
.tbl .clip{max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tbl-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
@media (max-width:640px){.tbl.stack,.tbl.stack tbody{display:block}.tbl.stack thead{display:none}.tbl.stack tr{display:grid;grid-template-columns:minmax(0,1fr);padding:var(--sp-3) 0;border-top:1px solid var(--line,#e8e6df)}.tbl.stack td{border:0;padding:2px 0}.tbl.stack .clip{max-width:none}.tbl.stack .fix{width:auto}.tbl.stack td[data-h]:before{content:attr(data-h);display:block;font:700 var(--fs-12)/var(--lh-snug) var(--ui,Inter,sans-serif);letter-spacing:var(--ls-caps);text-transform:uppercase;color:var(--mute,#6b7280)}}
/* ---------- empty · error states ---------- */
.empty{display:grid;justify-items:center;text-align:center;gap:var(--sp-3);padding:var(--sp-7) var(--sp-4);border:1px dashed var(--line2,#d9d6cc);border-radius:var(--rd-m);background:var(--cream,#fbf8f1)}
.empty .glyph{font-size:clamp(56px,16vw,96px);line-height:1;color:var(--mute2)}
.empty b{font:800 var(--fs-20)/var(--lh-tight) var(--ui,Inter,sans-serif);color:var(--ink,#0b0b0c)}
.empty p{font:400 var(--fs-14)/var(--lh-body) var(--ui,Inter,sans-serif);color:var(--mute,#6b7280);max-width:32em}
.empty.err{border-color:var(--red,#e05252);background:var(--red-l,#fdeeee)}
.empty .pen{font-size:var(--fs-24)}
/* ---------- overlays · one toast, one alert, one bottom sheet ---------- */
.toast{position:fixed;left:50%;bottom:calc(84px + env(safe-area-inset-bottom));transform:translateX(-50%);z-index:90;display:inline-flex;align-items:center;gap:var(--sp-3);max-width:calc(100vw - 32px);min-height:var(--h-l);padding:0 var(--sp-4);border-radius:var(--rd-pill);background:var(--ink,#0b0b0c);color:#fff;font:600 var(--fs-14)/var(--lh-tight) var(--ui,Inter,sans-serif);box-shadow:var(--sh-desk);animation:v2toast .25s ease-out}
.toast a{color:var(--sky,#7cc8ff);text-decoration:none;font-weight:700}
@keyframes v2toast{from{opacity:0;transform:translate(-50%,8px)}to{opacity:1;transform:translate(-50%,0)}}
@media (min-width:1024px){.toast{bottom:32px}}
.v2-dim{position:fixed;inset:0;z-index:80;background:rgba(11,11,12,.45);display:grid;place-items:center;padding:var(--sp-4)}
.v2-dim.sheet{align-items:end;padding:0}
.alert{width:100%;max-width:400px;background:#fff;border-radius:var(--rd-m);padding:var(--sp-5);display:grid;gap:var(--sp-3);box-shadow:var(--sh-desk)}
.alert b{font:800 var(--fs-20)/var(--lh-tight) var(--ui,Inter,sans-serif);color:var(--ink,#0b0b0c)}
.alert p{font:400 var(--fs-16)/var(--lh-body) var(--ui,Inter,sans-serif);color:var(--ink2,#2e3440)}
.alert .row{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2);margin-top:var(--sp-2)}
.alert .row.one{grid-template-columns:1fr}
.bsheet{width:100%;max-height:85vh;overflow:auto;background:#fff;border-radius:var(--rd-m) var(--rd-m) 0 0;padding:var(--sp-2) var(--sp-4) calc(var(--sp-5) + env(safe-area-inset-bottom));box-shadow:0 -10px 30px -18px rgba(0,0,0,.35)}
.bsheet:before{content:"";display:block;width:40px;height:4px;border-radius:2px;background:var(--line2,#d9d6cc);margin:0 auto var(--sp-4)}
.bsheet h3{font-size:var(--fs-20);line-height:var(--lh-tight);margin-bottom:var(--sp-3)}
@media (min-width:1024px){.v2-dim.sheet{align-items:center;padding:var(--sp-4)}.bsheet{max-width:520px;border-radius:var(--rd-m)}.bsheet:before{display:none}}
/* ---------- bottom CTA (phone) uses the xl height ---------- */
.v2-bar .btn{min-height:var(--h-xl)}
/* ---------- utilities ---------- */
.clip1{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.clip2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
