/* ============================================================
   PODO trial-lesson additions — loaded AFTER ../lesson-card.css
   Adds: lime brand pages (cover / act dividers / closing),
   greeting chat with katakana reading (yomi), needs-analysis
   option rows, and the consultation/roadmap worksheet bits
   (ported from the retired onboarding-screens prototype, restyled
   to the shared lesson-card system).
   ============================================================ */

/* ---------- brand pages (cover · divider · closing) ---------- */
.brand-page {
  min-height: 640px;
  margin: 24px 20px 0;
  padding: 40px 30px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  background: var(--lime);
  border-radius: 16px;
  box-shadow: 0 6px 0 var(--ink);
}

.phone > .brand-page:first-child {
  margin-top: 20px;
}

.brand-page.divider {
  min-height: 580px;
}

/* mascot on act dividers — white sticker so the lime body reads on the lime page */
.brand-mascot {
  width: 164px;
  height: 164px;
  object-fit: contain;
  padding: 16px;
  background: #fff;
  border: 1px solid var(--gray-200);
  border-radius: 26px;
  box-sizing: border-box;
}

/* every trial page card stays taller than it is wide (no square pages on mobile) */
.section {
  min-height: 580px;
}

.podo-badge {
  display: inline-flex;
  align-items: center;
  background: #1c1c1c;
  border-radius: 999px;
  padding: 6px 6px 6px 20px;
}

.podo-badge .logo {
  color: #fff;
  font-size: 18px;
  font-weight: 900;
  letter-spacing: .02em;
  padding-right: 14px;
}

.podo-badge .tag {
  background: #fff;
  border-radius: 999px;
  padding: 7px 15px;
  color: #1c1c1c;
  font-size: 13.5px;
  font-weight: 800;
  white-space: nowrap;
}

.brand-kicker {
  margin: 26px 0 0;
  color: rgba(28,28,28,.55);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.brand-title {
  margin: 8px 0 0;
  color: #1c1c1c;
  font-size: 44px;
  font-weight: 900;
  line-height: 1.12;
  letter-spacing: -.02em;
  word-break: keep-all;
}

.brand-page.divider .brand-title {
  font-size: 33px;
}

.brand-title .small {
  display: block;
  margin-top: 8px;
  font-size: 15px;
  font-weight: 700;
  color: rgba(28,28,28,.55);
  letter-spacing: 0;
}

/* japanese step name under a big korean divider title */
.brand-title .ja {
  display: block;
  margin-top: 10px;
  font-size: 17px;
  font-weight: 800;
  color: rgba(28,28,28,.6);
  letter-spacing: 0;
}

.brand-sub {
  max-width: 320px;
  margin: 16px 0 0;
  color: rgba(28,28,28,.66);
  font-size: 15px;
  line-height: 1.55;
  font-weight: 700;
  word-break: keep-all;
}

/* closing page */
.end-head {
  margin: 0;
  color: #1c1c1c;
  font-size: 21px;
  font-weight: 900;
}

.end-card {
  width: 100%;
  margin-top: 20px;
  padding: 16px 20px 36px;
  background: #fff;
  border: 1px solid var(--gray-200);
  border-radius: 18px;
  text-align: left;
}

.end-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 13px;
  border-bottom: 1px solid #ececea;
  color: #1c1c1c;
  font-size: 15px;
  font-weight: 800;
}

.end-check {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--lime);
  color: #1c1c1c;
  font-size: 14px;
  font-weight: 900;
}

.end-title {
  margin: 36px 0 0;
  text-align: center;
  color: #1c1c1c;
  font-size: 29px;
  font-weight: 900;
  line-height: 1.28;
  letter-spacing: -.01em;
  word-break: keep-all;
}

/* No accent on the closing title. Green type is neither the brand lime nor
   readable ink, and a lime highlight is the colour of the page showing round
   the card, so it punches a hole in it. The line is large and bold already —
   emphasising half of it adds nothing. */

.end-copy {
  margin: 16px 0 0;
  text-align: center;
  color: #575753;
  font-size: 14.5px;
  line-height: 1.6;
  font-weight: 600;
  word-break: keep-all;
}

/* ---------- chat with reading (yomi) ---------- */
/* same bubble language as the roleplay cards: the learner-language
   translation sits in a header strip on top, Korean below — plus the
   katakana reading tucked under the Korean line.
   Every bubble takes it, not just the greeting: the reading is a deck-wide
   component now (see .yomi in lesson-card.css), so the rule that positions
   it inside a bubble cannot be scoped to .intro. */
/* This kept a bottom padding of 0 from the days when a greeting bubble ALWAYS
   carried a reading. Now the switch can take it away, and a floorless bubble
   is what is left — so the floor lives here and the rule below lifts it only
   while a reading is actually there to stand on it. */
.bubble.intro > .korean {
  padding: 13px 16px;
  font-size: 20px;
  font-weight: 800;
}

/* When a reading is present it takes over the card's bottom padding — but
   `:has()` and `+` are structural, so they keep matching after the switch
   hides the reading, and the card loses its floor. Every rule that HANDS
   space to a reading is therefore conditional on the reading being shown. */
body:not(.no-yomi) .bubble:has(> .yomi) > .korean { padding-bottom: 0; }

.bubble > .yomi {
  margin-top: 0;
  padding: 5px 16px 13px;
  letter-spacing: .18em;
}

/* ---------- 발음 표기, per component ----------
   The reading itself is one component (.yomi in lesson-card.css); what
   changes here is only where it sits and how big, because a line under a
   29px hero sentence and a line inside a 13px tile cannot be the same
   size. Everything below is placement, never a second look.

   Two shapes recur. Inside a card that already pads its Korean, the
   reading takes over the bottom padding (.model-line, .bubble). Inside a
   tile the learner taps, the tile becomes a column so the reading sits
   under the word rather than beside it (.opt, .choice, .bt-out). */

/* cards whose Korean line owns the padding: hand the bottom to the reading */
body:not(.no-yomi) .model-line:has(> .yomi) > .korean { padding-bottom: 0; }
.model-line > .yomi { margin-top: 0; padding: 4px 16px 14px; }

/* A sentence and its reading are ONE thing; the translation is the second
   thing. Given equal gaps the card read as three sibling lines and the
   Korean stopped leading, so the reading tucks up under it and the break
   goes below the pair. */
.sent-hero > .yomi { margin-top: 7px; font-size: 13px; letter-spacing: .12em; }
body:not(.no-yomi) .sent-hero > .yomi + .translation { margin-top: 18px; }

.sent-more .yomi { margin-top: 3px; font-size: 11.5px; }
body:not(.no-yomi) .sent-more .yomi + .translation { margin-top: 7px; }

.pi-card > .yomi { margin-top: 7px; margin-bottom: 2px; }

/* 오늘의 목표: the reading belongs to the Korean line above it, not to the
   Japanese below — same order as everywhere else in the deck */
.known.lines .known-row > .yomi { margin-top: 0; }

.answer-fill .yomi { margin-top: 6px; }
.example-card .yomi { margin-top: 5px; font-size: 11.5px; }

/* Each line of a swap owns its own reading — both are sentences the learner
   is asked to say, so the quiet one gets one too. Neither line hands its
   padding to the reading, so the card keeps its floor when the switch is
   off and nothing here has to be conditional. */
.sw-from > .yomi,
.sw-to > .yomi { margin-top: 3px; font-size: 11.5px; }

/* a reading between two paragraphs has to carry both gaps itself — the
   Japanese line under it sets its own margins to zero */
.card > .yomi { margin: 7px 0 12px; }

/* tap targets: the word and its reading stack, centred. Only the
   inline-flex ones need turning — the tiles in a grid or a flex row are
   blockified already, so a block reading simply falls underneath.

   `.opt` is NOT in this list, and that is a content rule, not a layout one:
   the two-way pills only ever hold the pattern the page just taught
   (이에요/예요, 은/는), so by the time a learner is choosing between them
   the reading is not help — it is a second line of type inside a 2-em
   target, and four rows of it turn a glance into a paragraph. The word
   beside the pills keeps its reading; the thing being chosen doesn't need
   one. Reorder chips (.choice) are wide enough to hold both. */
.choice:has(> .yomi),
.bt-out:has(> .yomi) {
  display: inline-flex;   /* both sit in a running line or a flex row and must
                             not blockify into a full-width column */
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.choice > .yomi {
  margin-top: 3px;
  font-size: 10.5px;
  letter-spacing: .06em;
}

.choose-word > .yomi { margin-top: 4px; font-size: 11.5px; text-align: center; }
.choose-sentence > .yomi { margin-top: 8px; }

/* the 받침 diagram: the pill keeps its own ink, one step quieter, so the
   reading never reads as a second word inside the equation */
.bt-out > .yomi {
  margin-top: 2px;
  color: inherit;
  opacity: .62;
  font-size: 12px;
  letter-spacing: .06em;
}

.bt-ex > span > .yomi { margin-top: 3px; font-size: 11px; font-weight: 700; }

/* the 8 × 2 table: the tiles are already small, so the reading is the
   smallest type in the deck — it is there to be decodable, not read across */
.combi-nouns > span > .yomi,
.combi-ends > span > .yomi {
  margin-top: 2px;
  font-size: 9.5px;
  letter-spacing: .02em;
}

.combi-ends > span > .yomi { color: inherit; opacity: .6; }

/* The 목표 / 다음 화 pages are white cards standing on a dark ground, so the
   dark-page reading colour above would put white text on a white card. The
   reading inside a .known-row takes the ordinary quiet ink instead. */
.transition-page .known-row .yomi { color: var(--gray-400); }

/* ---------- 등장인물 (제N화 타이틀 카드) ----------
   A contextual lesson is sold as a scene, and a scene has a cast. The title
   card names who is in it and, more importantly, which one the learner is —
   without that line the dialogue that follows reads as two example sentences
   with faces on them.

   No new page type: the dark transition page was already shaped like a title
   card. This is the only thing added to it, and it borrows .avatar from the
   dialogue so a character looks the same here as they do three pages later. */
.scene-cast {
  display: grid;
  gap: 10px;
  margin-top: 26px;
}

.cast-row {
  display: flex;
  align-items: center;
  gap: 12px;
}

.cast-row .avatar { width: 34px; height: 34px; }
.cast-row .avatar.icon { background: #b3e187; }
.cast-row .avatar.icon svg { width: 21px; height: 21px; }

.cast-who {
  color: #fff;
  font-size: 15px;
  font-weight: 800;
  line-height: 1.25;
}

.cast-who small {
  display: block;
  margin-top: 1px;
  color: rgba(255,255,255,.62);
  font-size: 11.5px;
  font-weight: 700;
}

/* ---------- よみがな switch (runtime/js/yomi.js) ----------
   Top-right of every page that has readings on it. It used to be an ア button
   in the pager, wedged between ← T →, where it read as deck machinery — the
   learner never guessed it was theirs. On the card, named in their own
   language, it is obviously a thing they may turn off.

   No meaning-bearing colour: the track is ink, not green and not lime. This
   is a view preference sitting on twenty-five pages, and green (state) or
   lime (brand) on all of them would drain the one thing each colour says.
   A switch shape carries "on/off" by itself. */
.yomi-sw {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 7px;
  padding: 4px 7px 4px 10px;
  border: 1px solid var(--gray-200);
  border-radius: 999px;
  background: #fff;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* On a learning page the switch rides the title's own line. Putting it in the
   flow rather than over it is what makes that safe at any title length: the
   title is the flexible half, so a long one wraps inside its own box instead
   of sliding under the switch — which is the failure the earlier floating
   version was always one title away from. */
.page-head {
  display: flex;
  /* flex-start, not center: at the deck's 480px column every title is one line
     and the two are identical, but on a real phone the Japanese gloss drops to
     a second line — and the switch has to stay on the Korean title's line
     rather than float to the middle of a two-line block. */
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.page-head > .section-title { flex: 1 1 auto; min-width: 0; }

/* Cover and transition pages centre their content, so there is no title line
   to ride — those keep the corner. */
.phone > .brand-page:has(> .yomi-sw.corner),
.phone > .transition-page:has(> .yomi-sw.corner) { position: relative; }

.yomi-sw.corner {
  position: absolute;
  top: 11px;
  right: 13px;
  z-index: 2;
}

.yomi-sw-t {
  color: var(--gray-500);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .02em;
  line-height: 1;
  white-space: nowrap;
}

/* the track: ink when readings are on, grey when off, with the knob sliding */
.yomi-sw-k {
  position: relative;
  width: 26px;
  height: 15px;
  border-radius: 999px;
  background: var(--ink);
  transition: background .14s ease;
}

.yomi-sw-k::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 13px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #fff;
  transition: left .14s ease;
}

.yomi-sw.off .yomi-sw-k { background: var(--gray-200); }
.yomi-sw.off .yomi-sw-k::after { left: 2px; }
.yomi-sw.off .yomi-sw-t { color: var(--gray-400); }

.yomi-sw:focus-visible { outline: 2px solid var(--green-500); outline-offset: 2px; }

/* dark transition pages: the chip is the light card, same as every other
   component that lands on them */
.transition-page > .yomi-sw {
  border-color: rgba(255,255,255,.22);
  background: rgba(255,255,255,.1);
}
.transition-page > .yomi-sw .yomi-sw-t { color: rgba(255,255,255,.72); }
.transition-page > .yomi-sw .yomi-sw-k { background: #fff; }
.transition-page > .yomi-sw .yomi-sw-k::after { background: #1c1c1c; }
.transition-page > .yomi-sw.off .yomi-sw-k { background: rgba(255,255,255,.28); }

/* lime brand pages: white chip on lime, ink track — no border needed, the
   fill already separates it from the ground */
.brand-page > .yomi-sw { border-color: rgba(28,28,28,.12); }

@media print { .yomi-sw { display: none; } }

/* a hint chip is one line by design, so its reading runs inline after the
   Korean rather than under it — a two-line chip stops being a chip */
.hint-chip > .yomi {
  display: inline;
  margin: 0 0 0 5px;
  font-size: 11px;
  letter-spacing: .02em;
}

/* The reading under a page's own big title takes that page's ink — and ONLY
   the title's. Scoping this to `.transition-page .yomi` painted every reading
   on the page white, including the ones inside the white 오늘의 목표 cards,
   where they vanished: the components on a dark page were never dark, they
   are light cards on a dark ground (ux-philosophy → "Dark pages need no
   separate system"). The child combinator is what keeps that true. */
.brand-page > .brand-title > .yomi {
  margin-top: 9px;
  color: rgba(28,28,28,.55);
  font-size: 15px;
  letter-spacing: .08em;
}

.transition-page > .transition-title > .yomi {
  margin-top: 9px;
  color: rgba(255,255,255,.62);
  font-size: 14px;
  letter-spacing: .08em;
}

.bubble.me.intro {
  background: #fff;
}

/* speaker column: avatar with the name underneath */
.who {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  width: 48px;
}

.who-name {
  color: #575753;
  font-size: 10.5px;
  font-weight: 800;
  line-height: 1.2;
  text-align: center;
  word-break: keep-all;
}

/* blue nudge folded into the foot of the learner's bubble:
   "reply to the tutor!" — the instruction sits with the line to say */
.bubble.intro > .cue {
  display: block;
  padding: 8px 16px;
  border-top: 1px solid var(--gray-200);
  background: var(--gray-50);
  color: var(--gray-500);
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.35;
  word-break: keep-all;
}

/* ---------- needs-analysis option rows ---------- */
.opt-list {
  display: grid;
  gap: 11px;
}

.opt-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border: 1px solid var(--gray-200);
  border-radius: 13px;
  background: #fff;
}

.opt-row .emo {
  flex: none;
  font-size: 22px;
  line-height: 1;
}

.opt-row .opt-body {
  flex: 1 1 auto;
  min-width: 0;
}

.opt-row .opt-main {
  display: block;
  color: #1c1c1c;
  font-size: 16px;
  font-weight: 800;
  line-height: 1.3;
}

.opt-row .opt-sub {
  display: block;
  margin-top: 2px;
  color: var(--gray-500);
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.35;
}

.opt-row .lv-badge {
  flex: none;
  min-width: 48px;
  padding: 10px 0;
  text-align: center;
  background: var(--gray-100);
  color: var(--ink);
  border-radius: 11px;
  font-size: 13px;
  font-weight: 800;
}

/* numbered variant: a bare numeral, sized up so it reads at a glance */
.opt-row .lv-badge.num {
  min-width: 38px;
  padding: 4px 0;
  font-size: 24px;
  line-height: 1.3;
  font-weight: 900;
}

/* ---------- consultation worksheet ---------- */
.ws-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 0;
  border-bottom: 1px solid var(--gray-200);
}

.ws-row:first-child {
  padding-top: 0;
}

.ws-row:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

.ws-row .lab {
  flex: none;
  width: 88px;
  color: #1c1c1c;
  font-size: 13.5px;
  font-weight: 800;
}

.chips {
  display: flex;
  gap: 7px;
}

.nchip {
  position: relative;
  line-height: 0;
  cursor: pointer;
}

.nchip input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}

.nchip span {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  background: #fff;
  font-size: 14px;
  font-weight: 800;
}

.nchip input:checked + span {
  background: var(--green-100);
  border-color: var(--green-500);
}

/* course checkboxes */
.cgroup-label {
  display: block;
  margin: 20px 0 0;
  color: var(--gray-500);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.cgroup-label:first-child,
.section-subtitle + .cgroup-label {
  margin-top: 0;
}

.cgroup {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}

.ccheck {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 13px;
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  background: #fff;
  cursor: pointer;
}

.ccheck .t {
  color: #1c1c1c;
  font-size: 13.5px;
  font-weight: 800;
}

.ccheck .t small {
  margin-left: 3px;
  color: var(--gray-500);
  font-size: 10.5px;
  font-weight: 600;
}

.cbox {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  flex: none;
  width: 17px;
  height: 17px;
  margin: 0;
  border: 1px solid var(--gray-200);
  border-radius: 4px;
  background: #fff;
  cursor: pointer;
}

.cbox:checked {
  background: var(--green-100);
  border-color: var(--green-500);
}

.cbox:checked::after {
  content: "✓";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #1c1c1c;
  font-size: 11px;
  font-weight: 900;
}

/* the one big write-in: months / per-week / total sessions */
.plan-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px 18px;
  margin-top: 22px;
  padding: 16px 18px;
  background: #1c1c1c;
  border-radius: 14px;
  color: #fff;
}

.plan-banner .k {
  color: var(--lime);
  font-size: 13px;
  font-weight: 800;
  text-align: center;
}

.plan-banner .k small {
  display: block;
  margin-top: 2px;
  color: rgba(255,255,255,.5);
  font-size: 10px;
  font-weight: 700;
}

.plan-banner .line small {
  display: inline;
  margin: 0;
  color: rgba(255,255,255,.72);
  font-size: 12.5px;
  font-weight: 800;
}

.plan-banner .line {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 16px;
  font-weight: 800;
}

.write {
  width: 56px;
  padding: 4px 2px;
  border: 1.5px dashed var(--gray-200);
  border-radius: 8px;
  background: var(--gray-100);
  color: #1c1c1c;
  text-align: center;
  font-family: inherit;
  font-size: 20px;
  font-weight: 800;
}

.write::placeholder {
  color: rgba(28,28,28,.35);
  font-size: 14px;
}

.write:focus {
  outline: 2px solid #fff;
}

/* ---------- freetalk question ladder ---------- */
.ladder {
  display: grid;
  gap: 12px;
}

.ladder-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--gray-200);
  border-radius: 13px;
  background: #fff;
}

.ladder-item .lv {
  flex: none;
  margin-top: 2px;
  padding: 4px 10px;
  border: 1.5px solid var(--green-500);
  border-radius: 999px;
  background: var(--green-100);
  color: #3f7a1c;
  font-size: 11.5px;
  font-weight: 800;
  white-space: nowrap;
}

.ladder-item .lv.hot {
  border-color: var(--green-500);
  background: var(--green-100);
  color: var(--green-500);
}

.ladder-item .korean {
  font-size: 17px;
}

/* the question and its Japanese are one column next to the badge — without
   this they become two flex items and sit side by side */
.ladder-item .qbody {
  flex: 1 1 auto;
  min-width: 0;
}

/* ============================================================
   HANGUL TEACHING KIT (trial-1)
   ------------------------------------------------------------
   One idea runs through every page: a syllable is not a picture,
   it is a BOX with two seats. 子音 = amber seat, 母音 = rose seat.
   The same two colours mark the letter cards, the read drills,
   the words and the write-in guides, so the learner stops seeing
   a squiggle and starts seeing structure.

   TRAINING WHEELS: tints are teaching aids, so they are switched
   OFF (.plain) on the find / dictation drills — the learner has
   to see the parts without help there.
   ============================================================ */
:root {
  --c-bg: #ffeeb8;   /* 子音 seat */
  --c-ink: #96690d;
  --v-bg: #ffd7e5;   /* 母音 seat */
  --v-ink: #bf1b5c;
  --b-bg: #cfe3ff;   /* 받침 seat — never taught in the trial, only previewed
                        on the curriculum page as "this is what comes later" */
}

/* ---------- anatomy block: the glyph sitting in its two seats ---------- */
.anat {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-top: 24px;
}

.blk {
  display: block;   /* spans are inline: without this the box collapses */
  position: relative;
  flex: none;
  margin: 0 auto;
  width: 162px;
  height: 162px;
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  background: #fff;
  overflow: hidden;
}

.blk.sm { width: 150px; height: 150px; }

.blk .zone {
  position: absolute;
  display: flex;
  justify-content: center;
  padding: 5px 2px;
  font-size: 10px;
  font-weight: 800;
  line-height: 1;
}

.blk.lr .zone.c { inset: 0 54% 0 0; align-items: flex-end; background: var(--c-bg); color: var(--c-ink); }
.blk.lr .zone.v { inset: 0 0 0 46%; align-items: flex-end; background: var(--v-bg); color: var(--v-ink); }
.blk.tb .zone.c { inset: 0 0 50% 0; align-items: flex-start; background: var(--c-bg); color: var(--c-ink); }
.blk.tb .zone.v { inset: 50% 0 0 0; align-items: flex-end; background: var(--v-bg); color: var(--v-ink); }

.blk .glyph {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #1c1c1c;
  font-size: 92px;
  font-weight: 800;
  line-height: 1;
}

.blk.sm .glyph { font-size: 86px; }

.anat .eq {
  color: #1c1c1c;
  font-size: 28px;
  font-weight: 900;
}

.anat .kana {
  color: #1c1c1c;
  font-size: 62px;
  font-weight: 900;
  line-height: 1;
  text-align: center;
}

.anat .kana small {
  display: block;
  margin-top: 8px;
  color: var(--gray-500);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .06em;
}

/* the parts named underneath the block */
.parts {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 16px;
}

.part {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  border: 1px solid var(--gray-200);
  border-radius: 11px;
  font-size: 13px;
  font-weight: 800;
}

.part b { font-size: 21px; line-height: 1; }
.part em { color: #575753; font-size: 12px; font-style: normal; font-weight: 700; }

/* ---------- build strip: ㅇ + ㅏ → 아 ---------- */
.build {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: 10px;
  margin-top: 24px;
}

.build .b { text-align: center; }

.build .tile {
  display: grid;
  place-items: center;
  width: 96px;
  height: 96px;
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  background: #fff;
  font-size: 50px;
  font-weight: 800;
  line-height: 1;
}

.build .tile.res { box-shadow: none; border-color: var(--green-500); }

.build .b small {
  display: block;
  margin-top: 7px;
  color: var(--gray-500);
  font-size: 11.5px;
  font-weight: 700;
}

.build .op {
  align-self: center;
  padding-bottom: 20px;
  font-size: 24px;
  font-weight: 900;
}

/* ---------- placement blocks side by side ---------- */
.blk-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 16px;
  margin-top: 24px;
}

.blk-item { text-align: center; }

.blk-item .cap {
  display: block;
  margin-top: 11px;
  color: #1c1c1c;
  font-size: 13.5px;
  font-weight: 800;
}

.blk-item .cap small {
  display: block;
  margin-top: 3px;
  color: var(--gray-500);
  font-size: 11.5px;
  font-weight: 700;
}

/* ---------- combination table (payoff: 2 × 6 = 12 blocks) ---------- */
.combo {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 5px;
  margin-top: 24px;
}

.combo span {
  display: grid;
  place-items: center;
  height: 64px;
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  background: #fff;
  font-size: 27px;
  font-weight: 800;
  line-height: 1;
}

.combo .corner { border: none; background: transparent; }

/* ---------- read drills ----------
   the letters ARE the activity, so they fill the page: a 3-wide grid of
   big tiles rather than a thin row of chips floating in white space */
.read-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin-top: 24px;
}

.read-chip {
  display: grid;
  place-items: center;
  height: 148px;
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  background: #fff;
  font-size: 76px;
  font-weight: 800;
  line-height: 1;
}

/* whole words need width, not height */
.read-grid.words .read-chip {
  height: 112px;
  font-size: 34px;
}

/* ---------- words broken into syllables ---------- */
.wordset {
  display: grid;
  gap: 11px;
  margin-top: 24px;
}

.word-card {
  display: flex;
  align-items: center;
  gap: 15px;
  padding: 13px 16px;
  border: 1px solid var(--gray-200);
  border-radius: 13px;
  background: #fff;
}

.word-card .syls {
  display: flex;
  flex: none;
  gap: 5px;
}

.word-card .syl {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 9px;
  font-size: 28px;
  font-weight: 800;
  line-height: 1;
}

.word-card .body { min-width: 0; }

.word-card .yomi-line {
  display: block;
  color: #57a021;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
}

.word-card .mean {
  display: block;
  margin-top: 3px;
  color: #575753;
  font-size: 14.5px;
  font-weight: 700;
}

/* ---------- the unreadable-sentence hook ---------- */
.hook-quote {
  margin-top: 24px;
  padding: 26px 20px;
  border-radius: 14px;
  background: #1c1c1c;
  text-align: center;
}

.hook-quote .q {
  display: block;
  color: #fff;
  font-size: 25px;
  font-weight: 800;
  line-height: 1.35;
  word-break: keep-all;
}

.hook-quote .m {
  display: block;
  margin-top: 12px;
  color: rgba(255,255,255,.6);
  font-size: 13px;
  font-weight: 600;
}

/* ---------- "you already know some Korean" rows ---------- */
.known {
  display: grid;
  gap: 10px;
  margin-top: 24px;
}

.known-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 20px 18px;
  border: 1px solid var(--gray-200);
  border-radius: 13px;
  background: #fff;
}

.known-row .k {
  flex: none;
  width: 108px;
  color: #1c1c1c;
  font-size: 25px;
  font-weight: 800;
  line-height: 1.25;
}

.known-row .j {
  color: #575753;
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.35;
  word-break: keep-all;
}

.known-row .j small {
  display: block;
  margin-top: 2px;
  font-size: 11.5px;
  font-weight: 700;
}

/* sentences, not words: a whole sentence cannot live in the 108px word
   column, so the row stacks instead of running two columns */
.known.lines .known-row {
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
}

.known.lines .known-row .k {
  width: auto;
  font-size: 22px;
}

/* ---------- payoff counter ---------- */
.payoff {
  margin-top: 24px;
  padding: 34px 20px;
  border: 1px solid var(--gray-200);
  border-radius: 16px;
  background: var(--lime);
  box-shadow: none;
  text-align: center;
}

.payoff .eqline {
  color: #1c1c1c;
  font-size: 15.5px;
  font-weight: 800;
}

.payoff .big {
  display: block;
  margin: 6px 0 2px;
  color: #1c1c1c;
  font-size: 84px;
  font-weight: 900;
  line-height: 1.05;
  letter-spacing: -.03em;
}

.payoff .cap {
  display: block;
  color: rgba(28,28,28,.7);
  font-size: 14px;
  font-weight: 800;
}

/* letter cards: the glyph sits in its coloured seat(s) */
.letter-card > .korean.seat-lr,
.letter-card > .korean.seat-tb,
.letter-card > .korean.seat-v,
.letter-card > .korean.seat-c {
  flex: 0 0 74px;
  height: 74px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  font-size: 44px;
}

/* The kana anchor, big enough to read as an equal partner, in a fixed
   column so every card lines up. A mouth hint used to sit to its right,
   but only some letters need one, so that column was empty on half the
   cards — that contrast now has its own comparison page. */
.letter-card > .kana-eq {
  flex: none;
  min-width: 56px;
  display: flex;
  align-items: center;
  gap: 9px;
  color: #1c1c1c;
  font-size: 27px;
  font-weight: 900;
  line-height: 1;
}

.letter-card > .kana-eq i {
  color: var(--gray-400);
  font-size: 19px;
  font-style: normal;
  font-weight: 800;
}

/* The sound column: the letters that spell the block, in their seat
   colours. Present on every card, so the row never goes ragged — and it
   does what kana cannot: ナ does not come apart, n ＋ a does. */
.letter-card > .sound {
  flex: none;
  display: flex;
  align-items: center;
  gap: 7px;
}

.letter-card > .sound i {
  display: grid;
  place-items: center;
  min-width: 30px;
  padding: 5px 7px;
  border-radius: 9px;
  color: #1c1c1c;
  font-size: 15px;
  font-style: normal;
  font-weight: 800;
  line-height: 1;
}

.letter-card > .sound b {
  color: var(--gray-400);
  font-size: 13px;
  font-weight: 800;
}

/* ---------- mouth photos (Sejong 한국어 입문, 학습1/학습5) ----------
   The lesson is audio-only, so the learner can never watch the tutor's
   mouth. These photos put that information back into the page: front
   view for the lip shape, side view for rounding and protrusion. */
.letter-card > .mouth {
  flex: none;
  width: 60px;
  height: 60px;
  border-radius: 11px;
  border: 1px solid var(--gray-200);
  object-fit: cover;
  background: #fff;
}

/* the letter cards run four uniform slots once a mouth photo joins:
   glyph · kana · sound · mouth — so the columns are retuned to fit */
.letter-card {
  gap: 14px;
  padding: 15px 20px;
}

/* The same photo, smaller, wherever the learner reads or taps a block.
   Every block has a vowel in it, so the slot is never ragged — and on a
   ㄴ/ㅁ block the photo is the vowel's, which is the part the mouth is
   doing the work of.
   It gives nothing away: the letter is already printed on the block, so
   the picture cannot answer a 고르기 row for you — both options carry
   one, and on a read drill it only says what to do with your lips while
   you say the letter out loud. One component throughout: same white card,
   same grey outline, only the size changes. */
/* The photo takes no outline of its own. It lives inside a block that is
   already a box, and a second rounded rectangle around it turned it into a
   sticker pasted onto the block rather than part of it.

   The strip shows ~54% of the source's height, set as a ratio so it holds
   at whatever width the block ends up: the illustrations are 260x260 and
   cover scales them to the block's width, so a fixed px height would crop
   a different amount of face on a narrow screen.

   Why 54% and not less: the six illustrations are NOT registered to a
   common baseline. Measured, the lips run 0.265-0.692 of the frame in 아
   and 0.308-0.738 in 어 — a 5% offset between the extremes. A tighter
   strip pinched 아 against the top and 어 against the bottom; this one
   clears the worst case on both sides with one number instead of a table
   of six per-file crops that a seventh vowel would silently fall out of.
   The real fix is re-registering the source art. */
.read-item > .mouth,
.tap-tile > .mouth {
  border-radius: 9px;
  object-fit: cover;
  aspect-ratio: 1.85;
  /* height:auto is load-bearing — the markup's height="" attribute is a
     presentational hint on the height property, so without this it wins
     over aspect-ratio and the strip keeps whatever the tag happens to say. */
  height: auto;
}

/* ---- read drill: one block, glyph over mouth ----
   The photo cannot sit ON the seat fill — the fill is the code for 자음/모음
   and a picture parked in one half hides the split (a 오 chip is cream over
   pink; a photo in the pink pushes the glyph up into the cream, so the
   letter reads as if it belonged to the consonant seat alone). But left to
   hang under a bordered chip it read as a second, unrelated thing.
   So the OUTLINE moves out one level: the card is the block, and inside it
   the seat tile is a fill with no border of its own and the photo sits
   directly beneath it. Same two-levels-of-boxes rule as .letter-card, which
   holds a seat-filled glyph and a mouth photo in exactly this way. */
.read-item {
  display: grid;
  justify-items: center;
  gap: 7px;
  padding: 9px;
  border: 1px solid var(--gray-200);
  border-radius: 16px;
  background: #fff;
}

.read-item > .read-chip {
  width: 100%;
  height: 110px;
  border: none;
  border-radius: 11px;
  font-size: 66px;
}

/* Full width, so the photo is the block's second band rather than a small
   picture floating under a wide tile — two bands of one card. Cropping to a
   strip also throws away the chin and the neck and leaves the lips, which
   are the only part the learner is being asked to copy.

   No object-position: the lips sit near the middle of every frame (measured
   mid-points 0.46-0.52 of the height), so cover's own centre crop is right
   and nudging the window down only ate into the chin. */
.read-item > .mouth { width: 100%; }

/* A tap tile is plain white, so the photo goes straight inside the block —
   cropped to the same lip strip the read block uses, sitting right under
   the glyph rather than parked at the foot of the tile. */
/* align-content, not just place-items. The glyph is a bare text node, so it
   is an ANONYMOUS grid item — its row is auto-sized and the tile's leftover
   height gets stretched into both rows by default. The gap between the two
   then reads as ~22px while the photo ends up 6px off the floor: a letter
   floating over a strip stuck to the bottom edge, which is the opposite of
   the one-block reading. Centring the pair as a group and letting the rows
   hug their content puts the air back on the outside where it belongs. */
.tap-grid.rows .tap-tile:has(> .mouth) {
  height: 116px;
  align-content: center;
  gap: 7px;
  padding-bottom: 8px;
}

.tap-tile > .mouth { width: 88px; }

/* a wrong tile recedes as one thing — the glyph fades, so the photo does too */
.tap-tile.wrong > .mouth { opacity: .4; }

/* ---------- same-kana pairs, compared side by side ---------- */
.pair-list {
  display: grid;
  gap: 14px;
  margin-top: 24px;
}

.pair-row {
  display: flex;
  align-items: stretch;
  gap: 12px;
  padding: 16px;
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  background: #fff;
}

/* the shared katakana, stated once for the pair */
.pair-kana {
  flex: none;
  display: grid;
  place-items: center;
  width: 52px;
  border-radius: 11px;
  background: #1c1c1c;
  color: #fff;
  font-size: 30px;
  font-weight: 900;
  line-height: 1;
}

.pair-side {
  flex: 1 1 0;
  min-width: 0;
  text-align: center;
}

.pair-side .g {
  display: grid;
  place-items: center;
  height: 74px;
  border-radius: 12px;
  font-size: 44px;
  font-weight: 800;
  line-height: 1;
}

/* front then side: the side view is what shows rounding and protrusion */
.pair-side .shots {
  display: flex;
  justify-content: center;
  gap: 5px;
  margin-top: 8px;
}

.pair-side .shots img {
  width: 56px;
  height: 56px;
  border: 1px solid var(--gray-200);
  border-radius: 9px;
  object-fit: cover;
}

.pair-side small {
  display: block;
  margin-top: 8px;
  color: #575753;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.3;
  word-break: keep-all;
}

/* Concept pages carry one small diagram, so the leftover space is split
   above and below it rather than dumped at the foot of the card — the
   activity sits in the optical centre where the eye lands. */
.section:has(> .anat),
.section:has(> .build),
.section:has(> .blk-row),
.section:has(> .combo),
.section:has(> .payoff),
.section:has(> .usp),
.section:has(> .offer),
.section:has(> .ptable),
.section:has(> .sent-hero),
.section:has(> .pitch),
.section:has(> .batchim) {
  display: flex;
  flex-direction: column;
}

/* One rhythm under the script box. These four carry their own 24px, which on
   a block page collapses into the script's 26px but on these flex pages adds
   to it — so half the deck sat 26px under the script and half sat 50px. The
   script owns the gap; the component brings none. (Kept conditional on there
   being a script above: a page without one still needs the margin.) */
.section:has(> .section-subtitle) > .sent-hero,
.section:has(> .section-subtitle) > .pitch,
.section:has(> .section-subtitle) > .batchim,
.section:has(> .section-subtitle) > .combi,
.section:has(> .section-subtitle) > .anat,
.section:has(> .section-subtitle) > .build,
.section:has(> .section-subtitle) > .blk-row,
.section:has(> .section-subtitle) > .combo,
.section:has(> .section-subtitle) > .payoff,
.section:has(> .section-subtitle) > .usp,
.section:has(> .section-subtitle) > .offer,
.section:has(> .section-subtitle) > .ptable { margin-top: 0; }

/* Free space used to open ABOVE the diagram (margin-top:auto here) so the
   activity landed in the optical centre. It reads as a hole: what the tutor
   says and what the learner looks at while they say it are one thought, and
   on a light page half a screen of white between them looks like something
   failed to load — the emptier the page, the worse it got.
   Every page now hangs its content a fixed distance under the script and
   lets the leftover space fall to the foot of the card. Kept as flex
   columns above: the layout is the same, only the spacers are gone. */


/* a hint chip sitting under a component needs air (hard shadows below) */
.section > .hint { margin-top: 16px; }

/* The two seat fills, reused by every component above. Declared last
   and doubled (.seat-lr.seat-lr) so they always win over a component's
   own white background — the colour code must never be overridden. */
.seat-lr.seat-lr { background: linear-gradient(90deg, var(--c-bg) 0 46%, var(--v-bg) 46%); }
.seat-tb.seat-tb { background: linear-gradient(180deg, var(--c-bg) 0 50%, var(--v-bg) 50%); }
.seat-v.seat-v   { background: var(--v-bg); }
.seat-c.seat-c   { background: var(--c-bg); }

/* ---------- responsive ---------- */
@media (max-width: 480px) {
  .brand-page {
    margin: 20px 12px 0;
    padding: 36px 22px;
  }

  .brand-title {
    font-size: 38px;
  }

  .brand-page.divider .brand-title {
    font-size: 29px;
  }

  .combo span { height: 58px; font-size: 24px; }
  .read-chip { height: 128px; font-size: 66px; }
  .read-item > .read-chip { height: 96px; font-size: 58px; }
  .anat { gap: 12px; }
  .blk { width: 146px; height: 146px; }
  .blk .glyph { font-size: 84px; }
  .anat .kana { font-size: 54px; }
  .letter-card > .kana-eq { font-size: 24px; }
}

/* ============================================================
   PATTERN DECK · 문장도 상자다 (trial-2)
   ------------------------------------------------------------
   The hangul deck draws a syllable as a box with two seats. This
   deck does the same thing one level up: a sentence is a FRAME
   with a swappable word in it, and the frame has exactly two
   pieces — the topic marker and the polite ending.

     은/는      violet   the piece that marks what you're talking about
     입니다/까  orange   the piece that ends the sentence politely
     the noun   white    the only thing that changes

   These are seat colours, not state colours: they are pedagogy
   and they mean one thing each, exactly like 子音/母音 above.
   Three rules keep them honest:

     - TRAINING WHEELS, same as the .plain drills in the hangul
       deck: the tint is on where a sentence is SHOWN (teach
       pages, model lines, the story read-through) and off where
       one is PRODUCED (대화 채우기, 한국 여행, every blank and
       every choose row). A learner who still needs the colour to
       find the ending has not learnt the ending.
     - so it never lands where green already means something —
       green owns state, and no cell carries both
     - it tints the glyph, never a padded pill: a chip with side
       padding fakes a space into 학생입니다
   ============================================================ */
:root {
  --topic-bg:  #e7e0fb;   /* 은/는 — the topic marker */
  --topic-mid: #c6b4f5;   /* the same colour as a highlighter swipe, which
                             needs more body than a fill behind dark text */
  --topic-ink: #5a3ec8;
  --ending-bg:  #ffe2cc;   /* 이에요 / 예요 — the sentence ending */
  --ending-mid: #ffbe92;
  --ending-ink: #b2591c;
}

/* ---------- the two pieces, inline inside a sentence ---------- */
.topic, .ending {
  padding: 1px 2px;
  margin: 0 -1px;      /* give back what the padding took, so the word stays tight */
  border-radius: 4px;
  font-weight: 900;
  -webkit-box-decoration-break: clone;
          box-decoration-break: clone;
}

.topic { background: var(--topic-bg); color: var(--topic-ink); }
.ending { background: var(--ending-bg); color: var(--ending-ink); }

/* ---------- the same mark on both lines ----------
   The reference phrasebook (references/curricula/k-village-esther-bunny, p.30) puts
   the swappable word in an identical box in BOTH the Japanese and the
   Korean line, so the two lines point at each other and the learner never
   has to work out which piece corresponds to which. That is the half we
   were missing: 입니다 was orange and です was not.

   The Japanese stays secondary support — same hue, one step quieter —
   so it anchors the Korean instead of competing with it. */
.translation .topic,
.translation .ending {
  font-weight: 800;
  opacity: .92;
}

/* On a fill page the Japanese header already carries a highlighter swipe
   meaning "this is the bit you say in Korean". Keep the swipe — it is a
   different claim from the tint — but give it the colour of the piece it
   is pointing at, so です does not read as lime here and orange two pages
   earlier. The chip styling is dropped; only the hue carries over. */
.answer-label .target.topic,
.answer-label .target.ending {
  padding: 0;
  margin: 0;
  border-radius: 0;
  font-weight: 800;
  color: var(--ink);
}

.answer-label .target.topic  { background: linear-gradient(transparent 52%, var(--topic-mid) 52%); }
.answer-label .target.ending { background: linear-gradient(transparent 52%, var(--ending-mid) 52%); }

/* ---------- the pattern, as one finished sentence ----------
   The page shows the sentence whole, in a card tinted with the colour
   of the piece it is teaching, and lets that piece carry the accent.
   It carries a reading line like everything else in this deck. That used
   to be a deliberate omission — "the learner has already done hangul, and
   kana over every word is the crutch the hangul track exists to remove."
   The trial audience turned out not to be that learner: a 초급 trial is
   often someone's first hour of Korean, so a page they cannot decode is
   a page they cannot practise from. The ア switch is what puts the old
   rule back for the learner it was written for. */
.sent-hero {
  margin-top: 24px;
  padding: 26px 20px 22px;
  border: 1px solid #f3cfb2;
  border-radius: 16px;
  background: #fff8f3;
  text-align: center;
}

.sent-hero .korean {
  display: block;
  font-size: 29px;
  font-weight: 800;
  line-height: 1.25;
  word-break: keep-all;
}

/* the taught piece takes the accent as ink, not as a chip — inside a
   tinted card a second fill reads as a separate object sitting on top.
   Both lines are marked, so the Japanese still points at the Korean. */
.sent-hero .ending,
.sent-hero .topic {
  padding: 0;
  margin: 0;
  border-radius: 0;
  background: none;
  opacity: 1;
}

.sent-hero .ending { color: var(--ending-ink); }
.sent-hero .topic  { color: var(--topic-ink); }

.sent-hero .translation {
  display: block;
  margin-top: 14px;
  color: var(--gray-500);
  font-size: 14px;
  font-weight: 700;
}

/* part 2 teaches the marker, so its card is tinted the marker's colour.
   The card says which pattern the page is about before a word is read. */
.sent-hero.topic { border-color: #d9cdf7; background: #faf8ff; }

/* ---------- the same frame, filled a second and third way ----------
   A pattern is a frame with a slot, and the page used to say so in chips
   nobody reads out ("名前・仕事・国、どれにもつく"). Showing the frame filled
   three ways says it without words, and gives the tutor three things to
   read instead of one.

   They sit in a grey tray FUSED to the underside of the card — the same
   move the script box makes with its tutor note. Loose centred lines under
   a card read as leftovers; a tray says "same thing, quieter", and each
   sentence gets its own white seat so two examples read as two, not as a
   four-line paragraph. Fills, not outlines: a bordered row inside a
   bordered tray inside the page card would be three frames deep. */
.sent-hero:has(+ .sent-more) {
  border-radius: 16px 16px 0 0;
}

.sent-more {
  display: grid;
  gap: 8px;
  padding: 14px;
  border: 1px solid var(--gray-200);
  border-top: none;
  border-radius: 0 0 16px 16px;
  background: var(--gray-50);
  text-align: center;
}

.sent-more > div {
  padding: 12px 14px;
  border-radius: 10px;
  background: #fff;
}

.sent-more .korean {
  display: block;
  font-size: 21px;
  font-weight: 800;
  line-height: 1.25;
  word-break: keep-all;
}

.sent-more .translation {
  display: block;
  margin-top: 4px;
  color: var(--gray-500);
  font-size: 13px;
  font-weight: 700;
}

/* ---------- intonation: the ending drawn, not written ----------
   ↘ and ↗ were characters inside the Korean string, which is the one
   place they cannot be read — they sat at the same size as the text
   they were describing. */
.pitch {
  display: grid;
  gap: var(--item-gap);
  margin-top: 24px;
}

.pi-card {
  padding: 22px 20px 18px;
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  background: #fff;
}

.pi-card .korean {
  display: block;
  font-size: 30px;
  font-weight: 800;
  line-height: 1.2;
}

.pi-curve {
  display: block;
  width: 100%;
  height: 56px;
  margin: 12px 0 10px;
  overflow: visible;
  color: var(--ending-ink);
}

.pi-curve path {
  fill: none;
  stroke: currentColor;
  stroke-width: 3.5;
  stroke-linecap: round;
}

.pi-curve circle { fill: currentColor; }

.pi-card .translation {
  display: block;
  color: #575753;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.45;
}

/* ---------- 받침: the thing that decides 은 or 는 ----------
   The rule is about the FLOOR of the last syllable, so the page shows
   the floor: filled under 생, empty under 저. */
.batchim {
  display: grid;
  gap: var(--item-gap);
  margin-top: 24px;
}

/* The box is an equation read left to right — syllable → the form it takes —
   with the label and the examples as captions under it. The earlier version
   put the rule in a column of four small texts beside the glyph, so the one
   thing the page exists to say (floor ⇒ 이에요) was the same size as its own
   footnotes. */
.bt-box {
  display: grid;
  justify-items: center;
  gap: 15px;
  padding: 22px 16px 20px;
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  background: #fff;
  text-align: center;
}

.bt-eq {
  display: flex;
  align-items: center;
  gap: 18px;
}

/* ---------- two shapes, one ending ----------
   A rule that covers more than one vowel has to show more than one, or the
   half that never appears reads as a footnote — 「ㅏ · ㅗ」 above a single 앉
   taught ㅏ and merely mentioned ㅗ. So the stems stack on the left of one
   arrow and the ending answers both at once, which is also the honest
   picture: two different-looking syllables, same ending.

   The pair sits side by side and the tiles step down to pay for it. Stacked
   they cost the box ~100px of height, and with two boxes on the page the
   second one falls under the fold — on a page whose whole job is comparing
   them, which is the one thing it cannot afford. Side by side the page is
   exactly as tall as it was with one stem in each box.

   Two tiles a hair apart read as one word — 앉 놀 was being read 앉놀 — so
   the pair takes the `/` the 고르기 rows already use for "one or the other".
   It carries the separation, which lets the gaps close to almost nothing
   and buys back most of the width the slash costs. */
.bt-syls {
  display: flex;
  align-items: center;
  gap: 4px;
}

/* between two 78px tiles the choose-row's 19px slash vanishes — it has to
   hold a gap this wide open, so it scales with what it is separating */
.bt-syls > .sep {
  font-size: 27px;
  line-height: 1;
}

.bt-syls > .bt-syl {
  width: 78px;
  height: 78px;
  font-size: 45px;
}

.bt-syl {
  position: relative;
  isolation: isolate;   /* keeps the floor's z-index:-1 inside this box */
  display: grid;
  place-items: center;
  width: 108px;
  height: 108px;
  border-radius: 14px;
  background: var(--gray-50);
  font-size: 62px;
  font-weight: 800;
  line-height: 1;
}

/* the floor sits UNDER the glyph, so the glyph is never tinted itself —
   what is coloured is the seat, exactly as in the hangul deck */
.bt-syl::after {
  content: "";
  position: absolute;
  z-index: -1;          /* behind the glyph — the seat is tinted, never the letter */
  inset: 62% 10px 10px;
  border-radius: 7px;
}

.bt-syl.on::after { background: var(--topic-bg); }
.bt-syl.off::after { border: 1.5px dashed var(--gray-400); }

/* ---------- the seat can also sit on the RIGHT ----------
   Not every rule is decided at the floor. 아도/어도 is decided by the stem's
   VOWEL, and the page that teaches it drew the same equation with an
   untouched glyph — so 앉 and 먹 looked identical and the only thing telling
   them apart was a line of caption text. The learner had to already know
   where the vowel is to read a page whose job is to point at it.

   So the seat moves to where the deciding part actually is. In every stem
   that page uses (앉 · 받 · 먹 · 찍) the vowel is the stroke down the right
   side, above the 받침 — which makes the two rule pages a matched pair:
   look DOWN for a 받침, look RIGHT for the vowel.

   The floor is deliberately left alone here. It already means 받침 nine
   pages earlier, and ㅗ-type vowels — which sit under the consonant, right
   in that band — would land on it and say the wrong thing. */
.bt-syl.vowel::after {
  inset: 18% 18% 34% 55%;
  background: var(--topic-bg);
}

/* ...and a vowel does not always live on the right. ㅗ ㅜ ㅡ ㅛ ㅠ are drawn
   flat and sit UNDER the consonant, so 놀 stacks ㄴ / ㅗ / ㄹ in three bands
   and the seat becomes the middle one. Which is the whole reason ㅗ could
   not simply be named in the caption and left undrawn: the learner would
   have gone looking down the right side of a syllable that keeps nothing
   there. The takeaway the two positions teach together is "find the vowel",
   not "look right".

   Still not the floor — that band is the 받침 (놀's own ㄹ is sitting in
   it), and it means exactly that nine pages earlier. */
.bt-syl.vowel.under::after {
  inset: 41% 16% 34% 16%;
}

.bt-arrow {
  color: var(--gray-400);
  font-size: 30px;
  font-weight: 900;
  line-height: 1;
}

/* the right-hand side of the equation: the form the learner will actually
   say. It is the biggest coloured thing on the page, which is correct —
   it is the answer the rule produces. */
.bt-out {
  padding: 8px 18px;
  border-radius: 12px;
  background: var(--topic-bg);
  color: var(--topic-ink);
  font-size: 34px;
  font-weight: 900;
  line-height: 1.1;
  white-space: nowrap;   /* 이에요 breaking across two lines is not a pill */
}

.bt-head {
  display: block;
  font-size: 18px;
  font-weight: 800;
}

.bt-head small {
  display: block;
  margin-top: 4px;
  color: var(--gray-500);
  font-size: 13px;
  font-weight: 700;
}

/* the examples are the rule already applied, so each one gets its own seat
   instead of running together into a line of small text with dots in it */
.bt-ex {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}

.bt-ex > span {
  padding: 9px 14px;
  border-radius: 10px;
  background: var(--gray-50);
  color: #575753;
  font-size: 18px;
  font-weight: 800;
  line-height: 1.2;
  word-break: keep-all;
}

.bt-ex b { color: var(--topic-ink); font-weight: 900; }

/* The same 받침 rule decides 이에요/예요 one part earlier, so the page reuses
   this component in the ending's colour. The floor is what picks the form —
   whichever form the part is about — so the seat takes that part's hue and
   the learner sees one rule taught twice, not two rules.

   The modifier is NOT called .ending: that class is the inline mark for the
   ending itself (an orange fill), and on a container it paints the whole
   component orange and adds a box inside the box. */
.batchim.ending-rule .bt-syl.on::after,
.batchim.ending-rule .bt-syl.vowel::after { background: var(--ending-bg); }
.batchim.ending-rule .bt-out { background: var(--ending-bg); color: var(--ending-ink); }
.batchim.ending-rule .bt-ex b { color: var(--ending-ink); }

/* ---------- 원어민 팁: the same sentence, the way a native says it ----------
   Every tip page in the decks teaches a SWAP — 돼요? becomes 될까요?, 저는
   drops out — and the card they used never drew it. It showed two example
   boxes each holding only the finished form, so the learner read a result
   and had to reconstruct the move that produced it. Around them sat a
   bordered .card inside the page card inside a filled .example-card: three
   levels where this folder allows two, under a black-and-lime badge that
   said ネイティブのコツ directly beneath a title already reading
   ネイティブのひとこと — the loudest object on the page spent on a word the
   page had just used.

   So the swap becomes the component. One row per sentence, said twice: the
   ordinary version quiet and the native version in full ink under it, with
   the piece that changed carrying its own mark (.ending where an ending
   changed, .topic where a topic dropped — the deck's existing two, so the
   colour keeps meaning what it already meant). The learner sees the move,
   not just its result.

   The Japanese rides the same header band as .model-line and the dialogue
   cards. That band means "the Japanese of the Korean below" everywhere else
   in the deck, and the old page had put （はじめて会う人に） and a whole
   second Korean sentence in it. */
.swap {
  display: grid;
  gap: var(--item-gap);
  margin-top: 24px;
}

.swap-row {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--gray-200);
  border-radius: 12px;
  overflow: hidden;
}

.swap-row > .translation {
  order: -1;
  margin: 0;
  padding: 9px 14px;
  background: var(--gray-100);
  border-bottom: 1px solid var(--gray-200);
  color: #575753;
  font-size: 12.5px;
  line-height: 1.35;
  font-weight: 700;
}

/* the ordinary version — present, and plainly the one being left behind */
.sw-from {
  display: block;
  padding: 13px 16px 9px;
  color: var(--gray-400);
  font-size: 16px;
  font-weight: 700;
  line-height: 1.35;
}

/* ...and the one the learner should walk out saying */
.sw-to {
  display: block;
  padding: 0 16px 14px;
  font-size: 19px;
  font-weight: 800;
  line-height: 1.35;
}

/* the turn from one into the other. It is drawn, not written, and it comes
   from CSS so no deck has to remember to type it. */
.sw-to::before {
  content: "↓";
  display: block;
  margin-bottom: 5px;
  color: var(--gray-400);
  font-size: 13px;
  font-weight: 900;
  line-height: 1;
}

/* ---------- 漢字 bridge: the equivalence IS the point ---------- */
.bridge {
  display: grid;
  gap: var(--item-gap);
  margin-top: 24px;
}

.br-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 26px minmax(0, 1fr);
  align-items: center;
  gap: 6px;
  padding: 16px 14px;
  border: 1px solid var(--gray-200);
  border-radius: 13px;
  background: #fff;
  text-align: center;
}

.br-cn {
  color: var(--gray-500);
  font-size: 33px;
  font-weight: 800;
  line-height: 1.1;
}

/* the arrow is the claim the page is making, so it is not a faint tick */
.br-eq { color: var(--ink); font-size: 22px; font-weight: 900; line-height: 1; }

.br-ko {
  font-size: 33px;
  font-weight: 800;
  line-height: 1.1;
}

/* the reading under the Korean here is a .yomi like every other one in the
   deck, so it takes its colour — it only sits closer and a step larger,
   because the Korean above it is 33px */
.br-ko small {
  display: block;
  margin-top: 5px;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .08em;
}

/* ---------- the 16, shown as the multiplication it is ----------
   Writing out all sixteen sentences put the noun on the page sixteen
   times and still never showed the multiplication being claimed. The
   reference (p.124) does it with two banks and one ＋: pick from the
   left, pick from the right. Eight nouns, two endings, and the number
   underneath is something you can check by eye. */
.combi { margin-top: 24px; }

.combi-head,
.combi-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 34px minmax(0, 1fr);
  align-items: center;
  gap: 6px;
}

.combi-head { margin-bottom: 10px; }

.combi-tag {
  padding: 7px 0;
  border-radius: 9px;
  font-size: 12.5px;
  font-weight: 900;
  text-align: center;
}

.combi-tag.n { background: var(--gray-100); color: #575753; }
.combi-tag.e { background: var(--ending-bg); color: var(--ending-ink); }

.combi-plus {
  color: var(--gray-400);
  font-size: 20px;
  font-weight: 900;
  text-align: center;
}

.combi-nouns {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 5px;
}

.combi-nouns > span {
  padding: 8px 3px;
  border: 1px solid var(--gray-200);
  border-radius: 9px;
  background: #fff;
  font-size: 13px;
  font-weight: 800;
  text-align: center;
  word-break: keep-all;
}

.combi-ends { display: grid; gap: 5px; }

.combi-ends > span {
  padding: 15px 3px;
  border-radius: 10px;
  background: var(--ending-bg);
  color: var(--ending-ink);
  font-size: 16px;
  font-weight: 900;
  text-align: center;
}

/* The number and the table that produces it are one group, welded — the number
   on top, the table under it as the receipt. Written at the same weight as the
   rhythm rule above (which zeroes both) and after it, or the gap collapses and
   the green box sits on the head row. An 8 × 2 line used to close the table;
   it said the multiplication twice, since the banks are countable by eye and
   the box now leads with the answer. */
.section > .payoff + .combi { margin-top: 24px; }

@media (max-width: 480px) {
  /* the box is one centred column at every width — only the type steps down */
  .bt-syl { width: 94px; height: 94px; font-size: 54px; }
  /* A pair of stems is the widest thing the equation ever carries — nearly
     twice a single one — so it is the case that decides this breakpoint.
     Measured on a 360px column: any bigger and the page scrolls sideways,
     which on a rule page means the ending walks off the screen. The gaps
     close with it rather than the tiles paying the whole cost alone. */
  .bt-syls > .bt-syl { width: 62px; height: 62px; font-size: 36px; }
  .bt-syls { gap: 5px; }
  .bt-syls > .sep { font-size: 22px; }
  .bt-eq:has(.bt-syls) { gap: 11px; }
  .bt-out { padding: 7px 15px; font-size: 30px; }
  .bt-ex { font-size: 16px; }
  .combi-nouns > span { font-size: 12px; }
}

/* ============================================================
   TAP ACTIVITIES (no whiteboard)
   ------------------------------------------------------------
   Every task is answered by tapping. Two components carry all of
   them, so the learner learns one interaction and reuses it:
     .tap-grid  — choose the tile(s) (find / listen-and-pick)
     .builder   — assemble a syllable from a jamo keypad, which is
                  what "write the character" becomes without a pen
   ============================================================ */

/* ---------- tap to choose ---------- */
.tap-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin-top: 24px;
}

.tap-grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* Listen-and-pick is not one six-way choice, it is three two-way ones. Laid
   out as a plain grid the learner reads all six as a single question and the
   drill looks far harder than it is, so each question gets its own numbered
   band. The band is filled, never bordered — the tiles inside already carry
   a border, and a bordered wrapper would box them twice. */
.tap-grid.rows {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 24px;
}

.tap-row {
  display: grid;
  grid-template-columns: 30px 1fr 1fr;
  align-items: center;
  gap: 12px;
  padding: 10px 12px 10px 2px;
  border-radius: 18px;
  /* the grouping surface has to be lighter than any tile that can sit on it,
     or an answered-wrong tile sinks into its own row and stops reading as a
     tile at all */
  background: var(--gray-50);
}

.tap-n {
  font-size: 17px;
  font-weight: 800;
  color: var(--gray-400);
  text-align: center;
}

.tap-grid.rows .tap-tile { height: 100px; font-size: 48px; }

.tap-tile {
  position: relative;
  display: grid;
  place-items: center;
  height: 118px;
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  background: #fff;
  color: #1c1c1c;
  font-family: inherit;
  font-size: 54px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform .09s, background .12s, box-shadow .12s;
}

.tap-grid.words .tap-tile { height: 136px; font-size: 34px; }

.tap-tile:active { transform: scale(.96); }

/* ANSWERED. Right and wrong have to be told apart in about a second by
   someone who has known the alphabet for ten minutes, and once both states
   are pale tints, "lighter green vs lighter grey" is not enough on its own.
   So they differ on two independent channels rather than on brightness:

     right → has colour   (green-100 fill, green-500 outline, solid badge)
             and keeps the glyph at full ink strength
     wrong → has none     (grey fill, grey outline) and the glyph recedes

   The badge is the one saturated thing on the page, and it sits in the
   corner so the letter itself is never covered.

   Wrong is deliberately NOT dashed any more: dashed grey now means
   "write here" everywhere else in the system (.slot, .slot-input,
   .build-slot), and a wrong answer is not an empty field. */
.tap-tile.right {
  background: var(--green-100);
  border: 1.5px solid var(--green-500);
  box-shadow: none;
}

.tap-tile.wrong {
  background: var(--gray-100);
  border: 1px solid var(--gray-200);
  color: var(--gray-400);
}

.tap-tile::after {
  position: absolute;
  top: 6px;
  right: 8px;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  font-size: 12px;
  font-weight: 900;
  line-height: 1;
}

.tap-tile.right::after { content: "✓"; background: var(--green-500); color: #fff; }
.tap-tile.wrong::after { content: "✕"; background: var(--gray-200); color: var(--gray-500); }

/* ---------- build a syllable from the keypad ---------- */
.builder { margin-top: 24px; }

.build-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-bottom: 14px;
}

.build-task {
  flex: 1 1 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.build-task .ask {
  color: #575753;
  font-size: 15px;
  font-weight: 800;
  white-space: nowrap;
}

/* the slot the keypad is currently filling */
.build-slot {
  position: relative;
  width: 74px;
  height: 74px;
  border: 1.5px dashed var(--gray-200);
  border-radius: 12px;
  background: #fff;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.build-slot.active {
  border-style: solid;
  box-shadow: 0 0 0 4px rgba(181,253,76,.55);
}

.build-slot.done { border-style: solid; }

.build-slot .zone {
  position: absolute;
  border-radius: 9px;
}

.build-slot.lr .zone.c { inset: 4px 54% 4px 4px; }
.build-slot.lr .zone.v { inset: 4px 4px 4px 46%; }
.build-slot.tb .zone.c { inset: 4px 4px 50% 4px; }
.build-slot.tb .zone.v { inset: 50% 4px 4px 4px; }

.build-slot .glyph {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 42px;
  font-weight: 800;
  line-height: 1;
}

.build-slot .ok {
  position: absolute;
  top: -8px;
  right: -8px;
  display: none;
  width: 24px;
  height: 24px;
  place-items: center;
  border: 1px solid var(--gray-200);
  border-radius: 50%;
  background: var(--green-100);
  border-color: var(--green-500);
  font-size: 13px;
  font-weight: 900;
}

.build-slot.done .ok { display: grid; }

/* the tasks stack prompt over slot so three fit across a phone */
.build-task {
  flex-direction: column;
  gap: 8px;
}

/* the keypad: only the 8 parts this lesson has taught, in seat colours,
   so the learner can never build a letter they have not met */
.keys-label {
  margin: 16px 0 8px;
  color: var(--gray-500);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .04em;
}

.keys {
  display: grid;
  gap: 7px;
}

.keys.c3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.keys.v6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }

/* one taught consonant so far. The key keeps the width it has in .c3 and sits
   centred, so a single option doesn't read as two keys that failed to load. */
.keys.c1 {
  grid-template-columns: minmax(0, calc((100% - 14px) / 3));
  justify-content: center;
}

.key {
  display: grid;
  place-items: center;
  height: 48px;
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  background: #fff;
  color: #1c1c1c;
  font-family: inherit;
  font-size: 23px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform .09s, box-shadow .12s;
}

.key:active { transform: scale(.92); }
.key.on { box-shadow: 0 0 0 3px rgba(28,28,28,.3); }

/* a wrong pair shakes rather than scolding */
@keyframes miss { 0%,100%{transform:translateX(0)} 25%{transform:translateX(-5px)} 75%{transform:translateX(5px)} }
.build-slot.miss { animation: miss .3s; border-color: #d9534f; }

/* ============================================================
   TEACHING MODE  (선생님 모드)
   ------------------------------------------------------------
   The blue-100 band is what the tutor SAYS to the learner. The
   blue-200 band fused under it is what the tutor DOES — read
   order, answers, pacing — and the learner must never see it, so
   none of it exists in the page until the switch on the cover is
   turned on. Student view is the default, and reloading returns to it.

   Notes are written in Korean: the tutor reads Korean, and a
   Japanese beginner cannot, which is a second lock on the answers.
   ============================================================ */
.tutor-note { display: none; }

/* Sits directly under the blue script it belongs to — the tutor reads
   the line, then sees what to do next. In student view it is display:none,
   so it collapses completely and leaves no gap behind. */
/* A blue-200 chip. The tutor reads the blue line, THEN glances here, so it has
   to sit below the script in the hierarchy — hence a chip, hugging its own
   text, rather than a slab. What says "do not read this one aloud" is the
   튜터만 badge below, not the fill; see the note on it. */
body.teaching .tutor-note {
  display: flex;
  align-items: baseline;
  gap: 9px;
  /* Both margins are real — several components that follow bring no top
     margin, and a .dialogue would otherwise collide with it. */
  margin: 14px 0 18px;
  padding: 8px 13px;
  border-radius: 10px;
  background: var(--blue-200);
  width: fit-content;
  max-width: 100%;
}

/* The badge is what makes softening safe. Ink used to carry the whole "do not
   read this one aloud" load by brute contrast; against blue-100 that was an
   ~86-point lightness slam, and the merged card looked torn in half. Say it in
   words instead, and the fill only has to be a *step* rather than a shock —
   blue-200 is the same family as the script it hangs off, one shade down, so
   the two bands read as one card with a private second half.
   Korean, like every tutor-facing string: the tutor reads it, a beginner
   learner cannot, which is the second lock. Set from CSS so all 48 notes in
   the decks get it without touching any markup. */
/* A memo written against this instruction belongs WITH it — the merged
   block's 26px would otherwise leave the memo stranded between the script and
   the activity. Lives here rather than in the shared sheet because the merged
   rule above ties it on specificity and this sheet loads last.

   Zero, not 8: the memo brings its own 8px top margin. Whatever sits above it
   contributes nothing, so the memo hangs at the same distance whether it
   follows a script box, a tutor note, or a script box on a flex page — where
   margins do not collapse and two 8s become 16. */
body.teaching .tutor-note:has(+ .note-input),
body.teaching .section-subtitle + .tutor-note:has(+ .note-input) { margin-bottom: 0; }

.tutor-note::before {
  content: "튜터만";
  flex: none;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(28, 28, 28, .09);
  color: var(--blue-ink);
  font-size: 10.5px;
  font-weight: 800;
  white-space: nowrap;
}

/* ---- MERGED WITH THE SCRIPT IT BELONGS TO ----
   One card, two bands: the tutor reads the blue line, then their eye drops
   straight into the footer without crossing a gap. Two separate floating
   boxes for what is really one instruction made the page read as clutter.

   Merging is only safe BECAUSE the two bands stay told apart — blue-200 a step
   down from blue-100, a dashed fold between them, and the 튜터만 badge saying
   it in words. One undifferentiated blue box would have put a do-not-say-this
   line inside the surface that means "say this out loud".

   Student view is untouched: the whole rule is behind body.teaching, so the
   script box keeps its own radius and bottom margin, and the note is
   display:none with nothing left behind. Where a tutor note does NOT follow a
   script box (17 of the 48 in the decks) neither rule matches and it keeps the
   standalone chip above. */
body.teaching .section-subtitle:has(+ .tutor-note) {
  margin-bottom: 0;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

body.teaching .section-subtitle + .tutor-note {
  width: auto;
  max-width: none;
  margin: 0 0 26px;
  padding: 9px 16px 10px;
  /* the fold between "say this out loud" and "this one is yours" */
  border-top: 1px dashed #ccd3e4;
  border-radius: 0 0 12px 12px;
}

.tutor-note {
  color: var(--blue-ink);
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.45;
  word-break: keep-all;
}

/* answers surface the way .slot does in the pattern lessons: present
   for the tutor, never loud — a ghost of the answer inside the blank.

   Only while the blank is still blank. The ghost is drawn over the whole
   slot, so the moment the learner puts a part in it, the answer and their
   attempt were stacked on the same 74px square and neither could be read —
   and that square is precisely what the tutor is watching to see what the
   learner reached for. An occupied slot no longer needs the prompt: they
   have committed, and the ✓ or the shake answers them next. */
body.teaching .build-slot:not(.done):has(> .glyph:empty)::after {
  content: attr(data-a);
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #e6e6e4;
  font-size: 42px;
  font-weight: 800;
  pointer-events: none;
}

body.teaching .tap-tile[data-ok]:not(.right):not(.wrong)::before {
  content: "";
  position: absolute;
  inset: 7px;
  border: 2px dashed #e2e2e0;
  border-radius: 10px;
}

/* A tile carrying a mouth photo has something near its floor, and the marker
   at 7px landed 2px off the band — close enough to read as touching it. It
   hugs the tile edge instead; the ring still says "this one" either way. */
body.teaching .tap-tile[data-ok]:has(> .mouth):not(.right):not(.wrong)::before {
  inset: 5px;
  border-radius: 11px;
}

/* ---------- the switch, tucked into the cover's corner ----------
   Deliberately quiet: a learner should not notice it, and should have
   no reason to try it. It only asserts itself once it is on, so the
   tutor can see at a glance that answers are showing. */
.phone > .brand-page:first-child { position: relative; }

.mode-toggle {
  position: absolute;
  top: 14px;
  right: 14px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 9px 5px 6px;
  border: 1.2px solid rgba(28,28,28,.22);
  border-radius: 999px;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .15s, border-color .15s;
}

.mode-toggle input {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
}

.mode-toggle .sw {
  position: relative;
  flex: none;
  width: 26px;
  height: 15px;
  border: 1.2px solid rgba(28,28,28,.3);
  border-radius: 999px;
  background: transparent;
  transition: background .15s, border-color .15s;
}

.mode-toggle .sw i {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: rgba(28,28,28,.35);
  transition: transform .15s, background .15s;
}

.mode-toggle .lbl {
  color: rgba(28,28,28,.42);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .01em;
}

/* on: no longer shy, so the tutor cannot leave it on by accident */
.mode-toggle input:checked ~ .lbl { color: #1c1c1c; }
.mode-toggle:has(input:checked) {
  background: #1c1c1c;
  border-color: #1c1c1c;
}
.mode-toggle:has(input:checked) .lbl { color: var(--lime); }
.mode-toggle input:checked + .sw { background: var(--green-500); border-color: var(--green-500); }
.mode-toggle input:checked + .sw i { transform: translateX(11px); background: #1c1c1c; }


/* ============================================================
   CONSULTATION · the deck remembers the answers
   ------------------------------------------------------------
   The needs-analysis rows are real answers now, and the report
   page reads them back: goal + pace + the tutor's level call
   become an expected duration, a curve and a course list.
   ============================================================ */
.opt-list {
  display: grid;
  gap: 11px;
}

button.opt-row {
  width: 100%;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform .09s, background .12s, box-shadow .12s;
}

button.opt-row:active { transform: scale(.99); }

.opt-row.on {
  background: var(--green-100);
  border: 1.5px solid var(--green-500);
  box-shadow: none;
}

.opt-row.on .opt-sub { color: var(--gray-500); }
.opt-row.on .lv-badge { background: var(--green-500); color: #fff; }

/* 학습 동기 줄의 그림 — 이모지 자리를 그대로 대신한다. 이모지는 기기마다
   다른 그림이 나오고, 옆 장의 PODO 아트와 나란히 놓으면 혼자만 튄다. */
.opt-row .r-ico { flex: none; width: 32px; height: 32px; object-fit: contain; }

/* ============================================================
   두 개짜리 선택 · 카드가 곧 화면이다
   ------------------------------------------------------------
   고를 것이 둘뿐인 장에서 한 줄짜리 카드는 화면을 못 채운다. 위쪽에
   작게 얹혀 있으면 "설명 두 줄" 로 읽히고, 눌러야 하는 물건이라는 게
   전달되지 않는다. 그래서 두 장이 남는 높이를 반씩 나눠 갖고, 카드마다
   자기를 설명한다 — 무슨 성격인지(칩), 고르면 무슨 일이 일어나는지(세 줄),
   그리고 지금 골라져 있는지(오른쪽 위 동그라미).

   동그라미가 하는 일이 크다. 카드 전체가 초록으로 물드는 것만으로는
   "고를 수 있다" 를 미리 말해 주지 못한다 — 비어 있는 동그라미는 누르기
   전에도 보이기 때문에, 그 자리가 선택지라는 걸 먼저 알린다.
   ============================================================ */
/* 클래스 하나짜리 이름인 게 중요하다: :has() 는 인자 중 가장 특정한 것의
   특정도를 그대로 가져오므로, .opt-list.fill 로 쓰면 페이지를 숨기는 규칙
   (.phone.paged > *)을 이겨서 고르기 장이 다음 장에도 계속 보인다. */
.section:has(> .picks) {
  display: flex;
  flex-direction: column;
}

.section > .picks {
  flex: 1 1 auto;
  grid-auto-rows: 1fr;                  /* 두 장이 남은 높이를 반씩 */
  gap: 13px;
}

.opt-row.pick {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  padding: 16px 18px 18px;
  border-radius: 16px;
}

.opt-row.pick .opt-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  margin-bottom: 14px;
}

/* ---------- 두 스타일의 색 ----------
   이 두 색은 "어느 쪽인가" 만 뜻한다 — 말하기 쪽인가, 교정 쪽인가. 상태가
   아니다. 고른 것은 여전히 초록(테두리 + 동그라미)이 말하고, 이 색은 고르기
   전에도 후에도 그대로 있어 두 장을 갈라 보이게만 한다. 그래서 초록·파랑·
   라임·붉은색과 겹치지 않는 두 색을 쓴다: 청록과 보라.

   카드 바탕은 흰색으로 둔다. 바탕까지 물들이면 고른 쪽의 초록이 두 색과
   경쟁해서, 무엇이 골라졌는지가 흐려진다. 색은 칩과 그림에만 얹는다. */
.opt-tag {
  padding: 5px 11px 6px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 800;
  line-height: 1;
  white-space: nowrap;
}

.opt-row.talk .opt-tag { background: #e4f4f0; color: #17705f; }
.opt-row.edit .opt-tag { background: #efeafa; color: #5541a6; }

/* 그림은 자기 색 판 위에 앉는다 — 카드 위쪽이 색을 갖는 것만으로 두 장이
   멀리서도 갈린다 */
.opt-row.pick .r-ico {
  padding: 7px;
  border-radius: 13px;
}

.opt-row.talk .r-ico { background: #e4f4f0; }
.opt-row.edit .r-ico { background: #efeafa; }

.opt-row.talk .opt-note { border-top-color: #d5ebe5; }
.opt-row.edit .opt-note { border-top-color: #e2daf5; }

.opt-radio {
  flex: none;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border: 2px solid var(--gray-200);
  border-radius: 50%;
  background: #fff;
  color: transparent;
  font-size: 14px;
  font-weight: 900;
  line-height: 1;
  transition: background .12s, border-color .12s;
}

.opt-row.on .opt-radio {
  border-color: var(--green-500);
  background: var(--green-500);
  color: #fff;
}

.opt-row.pick .r-ico {
  width: 56px;
  height: 56px;
  margin-bottom: 12px;
}

.opt-row.pick .opt-main {
  font-size: 20px;
  font-weight: 900;
  line-height: 1.3;
  word-break: keep-all;
}

.opt-row.pick .opt-sub {
  margin-top: 4px;
  font-size: 13.5px;
}

.opt-row.pick .opt-note {
  width: 100%;
  margin-top: auto;                     /* 목록은 카드 바닥에 붙는다 */
  padding-top: 14px;
}

.opt-row.pick .opt-note li { font-size: 13.5px; }

.opt-note {
  display: grid;
  gap: 6px;
  margin: 12px 0 0;
  padding: 11px 0 0;
  border-top: 1px solid var(--gray-200);
  list-style: none;
}

.opt-row.on .opt-note { border-top-color: var(--green-500); }

.opt-note li {
  display: grid;
  grid-template-columns: 11px 1fr;
  color: #8a8a85;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.45;
  word-break: keep-all;
}

.opt-note li::before { content: "·"; font-weight: 800; }
.opt-row.on .opt-note li { color: var(--gray-500); }

/* ============================================================
   예습 지문 · 한 문장이 한 줄
   ------------------------------------------------------------
   지문은 예습에서 이미 읽고 온 것이라, 수업에서는 참고 자료다.
   그래서 문단이 아니라 문장 단위로 끊어 둔다 — 궁금한 문장을 짚어
   말하려면 "세 번째 문단의 뒷부분" 이 아니라 그 줄 하나를 누를 수
   있어야 한다. 번역은 눌러야 나온다: 옆에 늘 붙어 있으면 눈이
   한국어를 건너뛰고 일본어만 읽는다.

   테두리는 주지 않는다. 줄마다 상자를 치면 글이 아니라 목록으로
   읽히고, 읽어 오는 물건이라는 성격이 사라진다.

   「訳」 같은 표시도 붙이지 않는다. 한 줄만 눌러 보면 바로 아는 일이고,
   일곱 줄마다 붙은 표시는 지문을 읽는 동안 내내 눈에 걸린다.
   ============================================================ */
/* 지문은 한 덩어리의 종이다. 흰 바탕에 흰 줄을 얹으면 어디까지가 지문인지
   보이지 않아서, 회색 판 위에 줄을 놓는다 — 이 시트가 타일을 얹을 때 쓰는
   바로 그 바탕이다. 열린 줄만 흰색으로 떠오른다. */
.sents {
  display: grid;
  grid-template-columns: minmax(0, 1fr);   /* 자동 최소폭이 판을 넓히지 못하게 */
  gap: 0;
  margin-top: 24px;
  padding: 6px;
  border-radius: 14px;
  background: var(--gray-50);
}

/* flex 인 이유: <button> 은 자식들을 익명 상자에 담아 가운데로 몰아넣는다.
   닫혀 있을 때는 자식이 하나뿐이라 티가 안 나다가, 번역이 열려 두 줄이 되는
   순간 좁은 쪽이 가운데로 밀린다 — 누를 때마다 글이 옆으로 움직이던 이유다. */
.sent {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 100%;
  padding: 9px 12px 10px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .12s;
}

.sent .s-ko {
  display: block;
  color: #1c1c1c;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.62;
  word-break: keep-all;
}

/* 일본어는 띄어쓰기가 없다. keep-all 을 그대로 두면 한 문장이 통째로 한 낱말이
   되어 줄을 못 바꾸고, 그 최소폭이 줄 카드를 판 밖으로 밀어낸다 — 번역을 여는
   순간 그 줄만 오른쪽으로 삐져나오던 이유다. 일본어는 어디서든 끊는다. */
.sent .s-ja {
  display: none;
  word-break: normal;
  overflow-wrap: anywhere;
  margin-top: 7px;
  color: var(--gray-500);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.6;
  word-break: keep-all;
}

.sent:focus { outline: none; }

.sent:focus-visible {
  outline: 2px solid var(--green-500);
  outline-offset: -2px;
}

.sent.open {
  background: #fff;
  box-shadow: 0 1px 2px rgba(28, 28, 28, .06);
}
.sent.open .s-ja { display: block; }

/* ============================================================
   질문 카드 · 그 장의 주인공
   ------------------------------------------------------------
   질문 장에는 질문 하나와 교정 칸뿐이라, 질문이 작으면 화면이 통째로
   비어 보인다. 상자는 그대로 스크립트 상자다 — 파랑은 여기서도 "튜터가
   소리 내어 읽는다" 는 뜻이고, 크기와 알약 하나가 무게를 만든다.
   ============================================================ */
.section-subtitle.ask {
  margin-bottom: 0;
  padding: 24px 22px 26px;
  border-radius: 18px;
}

.section-subtitle.ask .q-n {
  display: inline-block;
  margin-bottom: 12px;
  padding: 6px 13px 7px;
  border-radius: 999px;
  background: #fff;
  color: var(--blue-ink);
  font-size: 12px;
  font-weight: 800;
  line-height: 1;
}

/* 질문은 카드가 크면 되지, 글자가 클 필요는 없다 — 두 줄 넘어가면 오히려
   한눈에 안 들어온다. 대신 일본어를 돌려놓는다: 알아듣지 못한 질문에는
   대답이 나오지 않고, 그 한 줄이 없으면 튜터가 통역부터 하게 된다. */
.section-subtitle.ask .ko {
  font-size: 19px;
  line-height: 1.5;
}

.section-subtitle.ask .ja {
  margin-top: 7px;
  font-size: 13px;
}

/* 한 문장씩 짝지어질 때(script-lines.js)의 간격도 카드 크기에 맞춘다 */
.section-subtitle.ask.lined .sline + .sline { margin-top: 14px; }

/* ============================================================
   피드백 블록 · 프리토킹이 파는 한 장면
   ------------------------------------------------------------
   말한 문장 → 고친 문장 → 달라진 곳. 한 질문에 여러 번 고칠 수 있으니
   블록이 여러 개 쌓인다. 다음 블록은 앞 블록을 쓰기 시작하면 저절로
   나타난다 — 버튼을 누르게 하면 그 "눌렀다" 는 사실까지 두 화면이
   맞춰야 하는데, 칸이 찼는지 여부는 이미 양쪽이 아는 값이다.

   회색 라벨 띠를 걷어냈다. 빈 칸 세 개가 회색 덩어리로 쌓여 있으면
   카드가 폼처럼 보이고, 정작 중요한 세 번째 줄(달라진 곳)이 묻힌다.
   지금은 흰 카드에 작은 캡션과 실선 하나뿐이고, 색은 고친 쪽과
   달라진 곳에만 들어간다.
   ============================================================ */
/* 질문과 교정은 한 동작이다 — 듣고, 받아 적는다. 그래서 붙여 놓는다.
   남는 높이를 위아래로 갈라 가운데에 세워 봤더니 둘 사이가 벌어져서,
   질문을 읽고 눈이 한참 내려가야 칸이 나왔다. 지금은 위에서부터 쌓고,
   대신 두 덩어리를 키운다. 교정이 여러 개면 아래로 넘치는 게 낫다. */
.fb {
  display: grid;
  gap: var(--item-gap);
  margin-top: 26px;      /* the deck's one script→activity distance */
}

/* 블록을 더 여는 버튼 둘. 회색 판을 깔면 카드만큼 무거워져서, 정작 읽어야 할
   교정보다 버튼이 먼저 보인다 — 그래서 테두리만 남기고 비운다. 점선은 쓰지
   않는다: 점선 회색은 "여기 쓰세요" 한 가지 뜻으로만 쓰고, 이건 누르는 것이다.

   종류가 둘인 이유는 튜터가 하는 일이 둘이기 때문이다. 고칠 문장이 있으면
   교정, 고칠 건 없는데 짚고 싶은 게 있으면 노트. */
.fb-adds {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: 10px;
}

.fb-adds.hide { display: none; }

.fb-add {
  display: block;
  width: 100%;
  padding: 11px;
  border: 1px solid var(--gray-200);
  border-radius: 11px;
  background: transparent;
  color: var(--gray-400);
  font-family: inherit;
  font-size: 13px;
  font-weight: 800;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform .09s, background .12s, color .12s;
}

.fb-add:active { transform: scale(.995); background: var(--gray-50); }
.fb-add.hide { display: none; }

/* 한 칸은 교정이거나 노트다. 두 벌을 따로 두면 노트가 늘 교정 아래로
   밀리므로(＋ 교정을 누르면 적어 둔 노트 위로 끼어든다), 칸은 한 줄로 세우고
   무엇으로 쓸지만 갈라 놓는다. 노트로 쓰이면 학생 문장·교정 줄이 없고,
   차이를 그릴 일도 없어서 카드가 한 줄로 끝난다. */
.fb-block.as-fix .fb-row.nrow { display: none; }
.fb-block.as-note .fb-row.orig,
.fb-block.as-note .fb-row.fix { display: none; }
.fb-block.as-note .fb-row { background: #fff; }

.fb-block {
  position: relative;
  border: 1px solid var(--gray-200);
  border-radius: 12px;
  background: #fff;
  overflow: hidden;
}

/* 지우기는 열려 있는 칸이면 늘 있다 — 잘못 연 빈 칸도 닫을 수 있어야 한다.
   예외는 하나, 마지막 남은 빈 칸이다: 지워도 그 자리는 다시 열려 있어야 해서
   눌러도 아무 일이 없다. 캡션 알약과 같은 높이, 반대쪽 끝. */
.fb-del {
  position: absolute;
  top: 12px;
  right: 12px;
  display: none;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--gray-400);
  font-family: inherit;
  font-size: 12px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .12s, color .12s;
}

.fb-block .fb-del { display: grid; }
.fb-block.nodel .fb-del { display: none; }
.fb-del:hover { background: var(--gray-100); color: var(--gray-500); }
.fb-del:active { transform: scale(.94); }

.fb-block.hide { display: none; }

/* 아직 안 쓴 블록은 점선이다 — 이 시스템에서 점선 회색은 "여기 쓰세요" 하나만
   뜻하고, 비어 있는 교정 칸이 정확히 그것이다. 채워지는 순간 실선이 된다. */
.fb-block.empty { border-style: dashed; }
.fb-block.empty .fb-row.fix { background: transparent; }
.fb-block.empty .fb-row.fix .fb-cap { color: #a8c98e; }

.fb-row { padding: 14px 16px 16px; background: var(--gray-50); }
.fb-row + .fb-row { border-top: 1px solid var(--gray-200); }

/* 캡션은 알약이다. 작은 회색 글씨로 얹어 두면 카드가 흰 판에 흰 글씨처럼
   보이고, 세 줄이 각각 무엇인지 한눈에 갈리지 않는다. */
.fb-cap {
  display: inline-block;
  margin-bottom: 8px;
  padding: 5px 11px 6px;
  border: 1px solid var(--gray-200);
  border-radius: 999px;
  background: #fff;
  color: var(--gray-500);
  font-size: 11.5px;
  font-weight: 800;
  line-height: 1;
}

/* 블록 번호는 캡션 앞에 붙는 작은 숫자다 — 한 질문에서 몇 번째 교정인지 */
.fb-in {
  display: block;
  width: 100%;
  min-height: 48px;                     /* 비어 있어도 카드가 납작해 보이지 않게 */
  padding: 0;
  border: 0;
  background: transparent;
  color: #1c1c1c;
  font-family: inherit;
  font-size: 17.5px;
  font-weight: 700;
  line-height: 1.55;
  resize: none;
  overflow: hidden;                     /* 높이는 내용에 맞춰 스크립트가 늘린다 */
  word-break: keep-all;
}

.fb-in:focus { outline: none; }
.fb-in::placeholder { color: #c9c9c4; font-weight: 600; }

/* 고친 쪽이 나은 쪽이다 — 초록은 이 시스템에서 맞는 말이라는 뜻 */
.fb-row.fix { background: #f6fdf0; }
.fb-row.fix .fb-cap { color: #3f7a1c; }
.fb-row.fix .fb-in::placeholder { color: #b6d99b; }

/* 교정이 들어오면, 학생 문장 칸은 원문 대신 "무엇이 바뀌었는지" 를 보여 준다.
   칸을 하나 더 만들지 않는 이유: 원문과 교정과 그 차이를 나란히 세 번 읽게
   하면, 정작 봐야 할 한 가지(어디가 달라졌나)가 셋 중 하나로 묻힌다.
   튜터가 받아 적은 문장을 다시 손봐야 할 수도 있으니, 누르면 칸으로 돌아온다. */
/* 줄 이름은 .orig 다 — 칸에 붙은 .said 와 같은 이름을 쓰면 스크립트가
   querySelector(".said") 로 칸 대신 줄을 집는다(줄이 먼저 나온다). */
.fb-row.orig .fb-diff { display: none; }
.fb-block.has-diff .fb-row.orig .fb-diff { display: block; cursor: text; }
.fb-block.has-diff .fb-row.orig .fb-in { display: none; }
.fb-block.has-diff.editing .fb-row.orig .fb-diff { display: none; }
.fb-block.has-diff.editing .fb-row.orig .fb-in { display: block; }

/* 칸과 같은 크기·같은 줄높이·같은 최소높이여야 한다. 교정이 들어오는 순간
   이 자리는 입력칸에서 차이 보기로 바뀌는데, 둘의 치수가 다르면 그 순간
   블록이 위아래로 튄다 — 줄 수가 같아도 그렇다. */
.fb-diff {
  margin: 0;
  min-height: 48px;
  font-size: 17.5px;
  font-weight: 700;
  line-height: 1.55;
  word-break: keep-all;
}

/* 표시는 글자에 딱 붙어야 한다. 좌우 여백을 주면 낱말 안에서 고친 한 글자가
   낱말 밖으로 떨어져 나와, 「선택해요」 가 「선택 해 요」 세 덩어리로 읽힌다. */
/* 취소선은 얇게, 그리고 글자와 다른 색으로 긋는다.
   굵게 그으면(2px) 두 글자짜리 어미가 덮여 무엇을 고쳤는지 읽을 수 없고 —
   한글은 가로획이 가운데를 지나가서 특히 그렇다 — 글자와 같은 붉은색으로
   그으면 획에 섞여 아예 보이지 않는다. 그래서 1px 먹색 55%: 대비는 색이
   내고 굵기는 최소로 남긴다. 그어진 건 보이고, 글자는 그대로 읽힌다. */
.fb-diff del {
  text-decoration-line: line-through;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(28, 28, 28, .35);
  color: #c9857e;
  background: #fdf7f6;
  border-radius: 3px;
  padding: 1px 0;
  box-shadow: 0 0 0 1px #fdf7f6;
}

/* 빠진 말은 흐리게, 들어온 말은 또렷하게. 둘 다 진하면 문장이 두 번 읽히고,
   정작 읽어야 할 것은 고쳐진 쪽이다. */
.fb-diff ins {
  text-decoration: none;
  color: #3f7a1c;
  background: var(--green-100);
  border-radius: 3px;
  padding: 1px 0;
  box-shadow: 0 0 0 1px var(--green-100);
}

/* ---------- level check ---------- */
.lvpick {
  display: grid;
  gap: 10px;
  margin-top: 24px;
}

.lvrow {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 13px 16px;
  border: 1px solid var(--gray-200);
  border-radius: 13px;
  background: #fff;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .12s, box-shadow .12s;
}

.lvrow.on { background: var(--green-100); border: 1.5px solid var(--green-500); box-shadow: none; }

.lvrow .lvn {
  flex: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: var(--gray-100);
  color: var(--ink);
  font-size: 17px;
  font-weight: 900;
}

.lvrow.on .lvn { background: var(--green-500); color: #fff; }
.lvrow .lvt { display: block; font-size: 15px; font-weight: 800; }
.lvrow .lvs { display: block; margin-top: 2px; color: var(--gray-500); font-size: 12px; font-weight: 600; }
.lvrow.on .lvs { color: var(--gray-500); }

/* ---------- the report ---------- */
/* Skeleton preview: the report's own shape in grey, so the page reads as
   "your plan lands here" rather than as an empty card. */
.rep-empty {
  display: grid;
  gap: 12px;
  margin-top: 24px;
}

.sk {
  border: 1.5px solid #ececea;
  border-radius: 14px;
  background: var(--gray-50);
}

/* 그래프 자리는 테두리 없이 — 실제 그래프도 테두리가 없다 */
.sk-plot { height: 152px; padding: 12px 8px; border: 0; background: none; }
.sk-plot svg { display: block; width: 100%; height: 100%; }

.sk-facts { display: grid; gap: 0; padding: 4px 16px; }

.sk-facts i {
  height: 13px;
  margin: 13px 0;
  border-radius: 999px;
  background: #ededeb;
}

.sk-facts i:nth-child(1) { width: 62%; }
.sk-facts i:nth-child(2) { width: 48%; }
.sk-facts i:nth-child(3) { width: 55%; }
.sk-facts i:nth-child(4) { width: 44%; }

.sk-course { height: 50px; }

/* the skeleton's companion: names the missing answer AND goes there */
.rep-jump {
  display: block;
  margin-top: 14px;
  padding: 13px 14px;
  border: 1px solid var(--gray-200);
  border-radius: 12px;
  background: var(--lime);
  box-shadow: 0 4px 0 var(--ink);
  color: #1c1c1c;
  text-align: center;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

.rep-jump:active { transform: translateY(2px); box-shadow: 0 2px 0 var(--ink); }
.rep-jump .rj-t { display: block; font-size: 14px; font-weight: 900; word-break: keep-all; }
.rep-jump .rj-s { display: block; margin-top: 3px; font-size: 11.5px; font-weight: 700; opacity: .62; }
.rep-jump .rj-s::after { content: " ↑"; }

.rep.ready ~ .rep-jump, .rep-jump.hide { display: none; }

.rep { display: none; }
.rep.ready { display: block; }
.rep.ready + .rep-empty, .rep-empty.hide { display: none; }

/* 레이더(.rad)와 같은 취급 — 테두리 없이 폭을 다 쓴다. 카드에 넣으면
   박스 안의 박스가 되고, 안쪽 여백만큼 선이 쪼그라든다. */
.rep-plot {
  display: block;
  width: 100%;
  height: auto;
  margin: -2px auto 2px;
}

.rep-facts {
  display: grid;
  gap: 0;
  margin-top: 16px;
  padding: 4px 16px;
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  background: #fff;
}

.rf {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--gray-200);
}

.rf:last-child { border-bottom: 0; }
.rf .k { flex: 1 1 auto; color: var(--gray-500); font-size: 13px; font-weight: 700; }
.rf .v { flex: none; color: #1c1c1c; font-size: 14.5px; font-weight: 800; }

.rep .cgroup-label { margin-top: 20px; }


.rep-courses {
  display: grid;
  gap: 9px;
  margin-top: 10px;
}

.rc {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 12px 14px;
  border: 1px solid var(--gray-200);
  border-radius: 12px;
  background: #fff;
  color: #1c1c1c;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

.rc .rcn {
  flex: none;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: var(--lime);
  font-size: 12px;
  font-weight: 900;
}

.rc .rcb { flex: 1 1 auto; min-width: 0; }
.rc .rct { display: block; font-size: 14px; font-weight: 800; }
.rc .rcs { display: block; margin-top: 2px; color: var(--gray-500); font-size: 11.5px; font-weight: 700; }
.rc::after { content: "→"; flex: none; color: var(--gray-400); font-size: 14px; font-weight: 900; }
.rc:active { transform: translateY(2px); }

.rep-why {
  margin: 14px 0 0;
  color: #575753;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.5;
  word-break: keep-all;
}

/* ============================================================
   INFO & SALES pages (from the PODO KOREAN deck)
   ============================================================ */
.jump {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 9px;
  width: 100%;
  margin-top: 26px;
}

.jbtn {
  display: grid;
  place-items: center;
  padding: 13px 8px;
  border: 1px solid var(--gray-200);
  border-radius: 12px;
  background: #fff;
  color: #1c1c1c;
  font-size: 13.5px;
  font-weight: 800;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

.jbtn:active { transform: translateY(2px); }

.usp {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 11px;
  margin-top: 24px;
}

.uspc {
  padding: 16px 14px;
  border: 1px solid var(--gray-200);
  border-radius: 13px;
  background: #fff;
}

.uspc .n { display: block; color: #1c1c1c; font-size: 21px; font-weight: 900; line-height: 1.1; }
.uspc .t { display: block; margin-top: 5px; font-size: 13.5px; font-weight: 800; }
.uspc .s { display: block; margin-top: 4px; color: var(--gray-500); font-size: 11.5px; font-weight: 600; line-height: 1.4; word-break: keep-all; }

/* ------------------------------------------------------------
   THE OFFER — one plan, then the discounts walked down to it.
   Built as a receipt on purpose: the learner watches the number
   fall instead of comparing three cards and guessing.
   ------------------------------------------------------------ */
.offer {
  margin-top: 22px;
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  background: #fff;
  box-shadow: 0 5px 0 var(--ink);
  overflow: hidden;
}

.offer-h {
  position: relative;
  padding: 15px 16px 14px;
  border-bottom: 1px solid var(--gray-200);
  background: var(--lime);
}

.obadge {
  display: inline-block;
  margin-bottom: 7px;
  padding: 3px 10px;
  border-radius: 999px;
  background: #1c1c1c;
  color: var(--lime);
  font-size: 10.5px;
  font-weight: 900;
}

.offer-h .ot { display: block; font-size: 19px; font-weight: 900; letter-spacing: -.01em; }
.offer-h .os { display: block; margin-top: 3px; color: rgba(28,28,28,.62); font-size: 12px; font-weight: 700; }

.calc { padding: 6px 16px 4px; }

.cl {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid #ececea;
  font-size: 13.5px;
  font-weight: 700;
}

.cl span { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 6px; }
.cl b { flex: none; font-size: 15px; font-weight: 800; }

.cl em {
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--green-100);
  color: var(--green-500);
  font-size: 11px;
  font-style: normal;
  font-weight: 900;
}

.cl .d3 {
  padding: 2px 7px;
  border-radius: 999px;
  background: #1c1c1c;
  color: var(--lime);
  font-size: 10px;
  font-style: normal;
  font-weight: 900;
}

.cl.cut b { color: var(--green-500); }

.cl.total {
  align-items: center;
  padding: 13px 0 14px;
  border-bottom: 0;
  font-size: 15px;
  font-weight: 900;
}

.cl.total b { font-size: 30px; font-weight: 900; letter-spacing: -.02em; }

.offer-f {
  padding: 11px 16px;
  border-top: 1px solid var(--gray-200);
  background: var(--gray-100);
  color: #575753;
  font-size: 12px;
  font-weight: 700;
}

.offer-f b { color: #1c1c1c; font-weight: 900; }

/* the next decision, not a competing one — shown after they're in */
.upsell {
  margin-top: 14px;
  padding: 14px 16px 15px;
  border-radius: 13px;
  background: var(--gray-100);
}

.upsell .ut { display: block; font-size: 13.5px; font-weight: 900; }

.urow {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 8px;
  padding: 9px 12px;
  border-radius: 10px;
  background: #fff;
}

.urow.best { background: var(--green-100); box-shadow: inset 0 0 0 1.5px var(--green-500); }
.urow .ul { flex: none; width: 48px; font-size: 12.5px; font-weight: 800; }
.urow .uv { font-size: 16px; font-weight: 900; }
.urow .uv small { margin-left: 2px; color: var(--gray-500); font-size: 11px; font-weight: 700; }
.urow .usave { margin-left: auto; color: var(--green-500); font-size: 11.5px; font-weight: 900; }

.unote { margin: 9px 0 0; color: var(--gray-500); font-size: 11.5px; font-weight: 700; }

.morelink {
  display: block;
  margin-top: 14px;
  padding: 12px;
  border: 1.5px dashed #b0b0ac;
  border-radius: 11px;
  color: var(--gray-500);
  font-size: 12.5px;
  font-weight: 800;
  text-align: center;
  text-decoration: none;
}

.morelink::after { content: " →"; }

/* ---------- the full table, only if they ask ---------- */
.ptable {
  width: 100%;
  margin-top: 22px;
  border: 1px solid var(--gray-200);
  border-radius: 13px;
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;
  font-size: 12.5px;
}

.ptable th, .ptable td { padding: 10px 8px; text-align: center; }

.ptable thead th {
  border-bottom: 1px solid var(--gray-200);
  background: #1c1c1c;
  color: #fff;
  font-size: 11.5px;
  font-weight: 800;
}

.ptable tbody td { border-bottom: 1px solid #ececea; font-weight: 800; }
.ptable tbody tr:last-child td { border-bottom: 0; }
.ptable tbody tr.grp td { border-top: 1px solid var(--gray-200); }
.ptable tbody tr.grp:first-child td { border-top: 0; }

.ptable td[rowspan] {
  background: var(--gray-100);
  font-size: 13px;
  font-weight: 900;
}

.ptable td[rowspan] small { display: block; margin-top: 3px; color: var(--gray-500); font-size: 10.5px; font-weight: 700; }
.ptable td.hi { background: var(--green-100); color: #1c1c1c; }

.pt-note { margin: 12px 0 0; color: var(--gray-500); font-size: 11.5px; font-weight: 700; line-height: 1.5; }

/* FAQ */
.faq { display: grid; gap: 11px; margin-top: 24px; }

.qa {
  padding: 14px 16px;
  border: 1px solid var(--gray-200);
  border-radius: 13px;
  background: #fff;
}

.qa .q { display: block; font-size: 14px; font-weight: 800; line-height: 1.4; word-break: keep-all; }
.qa .q::before { content: "Q. "; color: var(--green-500); font-weight: 900; }
.qa .a { display: block; margin-top: 7px; color: #575753; font-size: 13px; font-weight: 600; line-height: 1.5; word-break: keep-all; }

/* ============================================================
   LINE BREAKING
   ------------------------------------------------------------
   word-break:keep-all keeps Korean words whole, and several
   components inherit it. Japanese has no spaces, so under
   keep-all a JP sentence can only break at 。 — it then runs
   the full width and rams the card edge. Every Japanese-bearing
   element opts back out to normal breaking.
   (The plan and sales pages are Korean, so they keep keep-all.)
   ============================================================ */
.title-ja,
.section-subtitle .ja,
.brand-title .ja,
.bubble.intro > .cue,
.who-name,
.transition-copy,
.known-row .j,
.pair-side small,
.blk-item .cap small,
.letter-card > .english,
.model-line > .translation,
.word-card .mean,
.sign .english,
.uspc .s,
.card .row,
.mission li,
.end-title,
.end-copy,
.hint-chip,
.brand-page:not(#p-info) .brand-sub {
  word-break: normal;
  line-break: normal;
}

/* ============================================================
   CURRICULUM PAGE
   ------------------------------------------------------------
   One long page instead of four thin ones. The learner reads it
   bottom-up in the order they will actually study: 한글 first,
   then patterns, then the worlds, then freetalking. Every stage
   answers the same three questions in the same order —
   what it is, what it looks like, what you can do after it.
   ============================================================ */
.cur-hero {
  display: block;
  width: 100%;
  height: auto;
  margin: 20px auto 0;
}

/* the four stages as a jump rail, so the tutor can open one directly */
.rail {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin-top: 18px;
}

.rl {
  display: grid;
  justify-items: center;
  gap: 6px;
  padding: 11px 4px;
  border: 1px solid var(--gray-200);
  border-radius: 12px;
  background: #fff;
  color: #1c1c1c;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

.rl:active { transform: translateY(2px); }

.rl-n {
  display: grid;
  place-items: center;
  width: 21px;
  height: 21px;
  border-radius: 999px;
  background: #1c1c1c;
  color: #fff;
  font-size: 11.5px;
  font-weight: 900;
}

.rl-t { font-size: 12px; font-weight: 800; }

/* ---------- one stage ---------- */
.stg {
  margin-top: 14px;
  padding: 17px 15px 19px;
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  background: #fff;
  scroll-margin-top: 14px;
}

.stg-h { display: flex; align-items: center; gap: 10px; }

.stg-n {
  flex: none;
  display: grid;
  place-items: center;
  width: 27px;
  height: 27px;
  border-radius: 999px;
  background: #1c1c1c;
  color: #fff;
  font-size: 13.5px;
  font-weight: 900;
}

.stg-t { font-size: 18px; font-weight: 900; letter-spacing: -.01em; }

.stg-c {
  margin-left: auto;
  flex: none;
  color: var(--gray-500);
  font-size: 11.5px;
  font-weight: 800;
  white-space: nowrap;
}

.stg-p {
  margin: 10px 0 0;
  color: #575753;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.55;
}

/* the demo area — background only, so a stage stays ONE box deep */
.stg-viz {
  margin-top: 13px;
  padding: 15px 12px;
  border-radius: 12px;
  background: var(--gray-100);
}

.viz-cap {
  margin: 11px 0 0;
  color: var(--gray-500);
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.45;
  text-align: center;
}

/* what you can do at the end of the stage */
.stg-goal {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 13px;
  padding: 11px 13px;
  border-radius: 11px;
  background: var(--green-100);
  font-size: 13px;
  font-weight: 800;
  line-height: 1.45;
}

.stg-goal::before { content: "→"; flex: none; color: var(--green-500); font-weight: 900; }

/* the lime thread that shows the stages are one road, not four products */
.stg-link {
  display: block;
  width: 4px;
  height: 18px;
  margin: 0 auto;
  border-radius: 999px;
  background: var(--lime);
}

/* ---------- stage 1 · letters snapping into blocks ---------- */
.crow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
}

.crow + .crow { margin-top: 11px; }
.crow i { color: var(--gray-400); font-size: 15px; font-style: normal; font-weight: 900; }

.lt {
  display: grid;
  place-items: center;
  flex: none;
  width: 42px;
  height: 42px;
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  background: #fff;
  font-size: 23px;
  font-weight: 800;
  line-height: 1;
}

.lt.c { background: var(--c-bg); }
.lt.v { background: var(--v-bg); }
.lt.b { background: var(--b-bg); }

/* the assembled syllable, seats showing through */
.sq {
  position: relative;
  flex: none;
  width: 52px;
  height: 52px;
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  background: #fff;
  overflow: hidden;
}

.sq em { position: absolute; }
.sq.lr em.zc { inset: 0 54% 0 0; background: var(--c-bg); }
.sq.lr em.zv { inset: 0 0 0 46%; background: var(--v-bg); }
.sq.b3 em.zc { inset: 0 54% 32% 0; background: var(--c-bg); }
.sq.b3 em.zv { inset: 0 0 32% 46%; background: var(--v-bg); }
.sq.b3 em.zb { inset: 68% 0 0 0; background: var(--b-bg); }

.sq b {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 32px;
  font-weight: 800;
  line-height: 1;
}

.ck {
  flex: none;
  min-width: 34px;
  color: var(--gray-500);
  font-size: 13px;
  font-weight: 800;
  text-align: center;
}

/* ---------- stage 2 · one pattern, many sentences ---------- */
.sent { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; }

.wrd {
  padding: 7px 11px;
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  background: #fff;
  font-size: 14.5px;
  font-weight: 800;
}

.wrd.hole { border-style: dashed; background: var(--green-100); border-color: var(--green-500); letter-spacing: -.06em; }
.wrd.pat { background: #1c1c1c; color: var(--lime); }

/* the whole point of the stage: ONE frame, and the sentences fall out of it */
.pf-tag {
  display: block;
  width: fit-content;
  margin: 0 auto 9px;
  padding: 3px 11px;
  border-radius: 999px;
  background: #1c1c1c;
  color: var(--lime);
  font-size: 11px;
  font-weight: 900;
}

.pf-tag.out { margin-top: 9px; background: var(--green-500); color: #fff; }

.pf-arrow {
  display: block;
  margin-top: 10px;
  color: var(--gray-500);
  font-size: 11.5px;
  font-weight: 800;
  text-align: center;
}

.pf-arrow::before { content: "↓"; display: block; color: var(--green-500); font-size: 15px; font-weight: 900; }

.pat-out { display: grid; gap: 6px; }

.po {
  padding: 8px 12px;
  border-radius: 10px;
  background: #fff;
  font-size: 14px;
  font-weight: 800;
  text-align: center;
}

/* highlighter, not a chip — a padded chip fakes a space into 학생입니다 */
.po b { background: linear-gradient(transparent 48%, var(--lime) 48%); font-weight: 900; }
.po.more { background: none; color: var(--gray-500); font-size: 12px; font-weight: 700; }

/* a real line from the course, with the pattern it hands over */
.ex {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 9px;
  padding: 10px 13px;
  border-radius: 11px;
  background: var(--gray-100);
}

.ex-lv {
  flex: none;
  width: 34px;
  color: var(--gray-500);
  font-size: 11px;
  font-weight: 800;
}

.ex-k { flex: 1 1 auto; min-width: 0; font-size: 13.5px; font-weight: 800; }

.ex-p {
  flex: none;
  padding: 3px 9px;
  border-radius: 999px;
  background: #1c1c1c;
  color: var(--lime);
  font-size: 11px;
  font-weight: 800;
  white-space: nowrap;
}

/* ---------- stage 3 · the four worlds ---------- */
.worlds { display: grid; gap: 10px; margin-top: 13px; }

.wd {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  align-items: center;
  gap: 4px 12px;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--gray-100);
}

.wd img { width: 44px; height: 44px; }
.wd-h { display: flex; align-items: baseline; gap: 8px; font-size: 15px; font-weight: 900; }
.wd-h small { margin-left: auto; color: var(--gray-500); font-size: 11px; font-weight: 700; }

.wd-l {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 11px;
  border-radius: 9px;
  background: #fff;
  font-size: 13px;
  font-weight: 800;
}

.wd-l small { margin-left: auto; flex: none; color: var(--gray-500); font-size: 10.5px; font-weight: 700; }

/* ---------- stage 4 · freetalking ---------- */
.free-hero { display: flex; align-items: center; gap: 14px; }
.free-hero img { flex: none; width: 96px; height: 96px; }

.free-hero p {
  margin: 0;
  font-size: 14.5px;
  font-weight: 900;
  line-height: 1.45;
}

.free-hero p small {
  display: block;
  margin-top: 6px;
  color: var(--gray-500);
  font-size: 11.5px;
  font-weight: 700;
}

/* themes read as icons first — the names are abstract, the shapes aren't */
.tgrid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin-top: 10px;
}

.tg {
  display: grid;
  justify-items: center;
  align-content: start;
  gap: 7px;
  padding: 11px 5px 10px;
  border-radius: 11px;
  background: var(--gray-100);
  font-size: 11.5px;
  font-weight: 800;
  line-height: 1.35;
  text-align: center;
  word-break: keep-all;
}

.tg svg {
  width: 28px;
  height: 28px;
  fill: none;
  stroke: #1c1c1c;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.tg svg .fill { fill: var(--lime); }

.tg.more {
  align-content: center;
  background: var(--lime);
  color: #1c1c1c;
}

/* one real question, so "주제" stops being an abstraction */
.qcard {
  margin-top: 10px;
  padding: 13px 15px;
  border-radius: 12px;
  background: var(--green-100);
  font-size: 15px;
  font-weight: 900;
  line-height: 1.4;
  text-align: center;
}

.qcard small {
  display: block;
  margin-bottom: 6px;
  color: var(--green-500);
  font-size: 11px;
  font-weight: 800;
}

/* ============================================================
   PAGED MODE  (the default)
   ------------------------------------------------------------
   The deck is a flat list of pages under .phone, so "one at a
   time" costs nothing structurally: hide the siblings, show one.
   Scrolling is one tap away and remains the fallback — printing,
   Cmd+F and scanning ahead all depend on it, so this never
   becomes the only way to read the deck. @media print always
   expands the whole deck regardless of mode.
   ============================================================ */
.mode-toggle.view { top: 46px; }

.phone.paged > * { display: none; }
.phone.paged > .pg-on { display: flex; }
.phone.paged > .section.pg-on { display: block; }

/* the section rules that centre a lone component use :has(), which
   still applies — but display:block above would drop the flex they
   set up, so re-assert it for those pages only */
.phone.paged > .section.pg-on:has(> .anat),
.phone.paged > .section.pg-on:has(> .build),
.phone.paged > .section.pg-on:has(> .blk-row),
.phone.paged > .section.pg-on:has(> .combo),
.phone.paged > .section.pg-on:has(> .payoff),
.phone.paged > .section.pg-on:has(> .usp),
.phone.paged > .section.pg-on:has(> .offer),
.phone.paged > .section.pg-on:has(> .ptable),
.phone.paged > .section.pg-on:has(> .sent-hero),
.phone.paged > .section.pg-on:has(> .pitch),
.phone.paged > .section.pg-on:has(> .batchim),
.phone.paged > .section.pg-on:has(> .picks) { display: flex; }

body { padding-bottom: 84px; }         /* the bar must not cover the last line */

/* a page on its own should fill the screen rather than leave a dead band
   above the bar — the :has() centring rules then have room to work */
.phone.paged > .pg-on { min-height: calc(100vh - 118px); }
@supports (height: 100dvh) { .phone.paged > .pg-on { min-height: calc(100dvh - 118px); } }

/* Paged mode fills the screen with the single active page, which already
   reserves room for the bar (the -118px above). The scroll-mode chrome that
   lives OUTSIDE that page — the .phone 100vh floor and the body's bottom
   padding — would otherwise stack on top of a full-height page and force a
   scroll even on a short one. Drop both while paged. */
.phone.paged { min-height: 0; }
body.paged { padding-bottom: 0; }

/* The bar floats over the bottom of the screen. On a short page that is just
   empty card, so nothing to clear; on a page tall enough to scroll, the last
   line has to stop above it. Put that clearance INSIDE the scrollable page
   (only .section pages ever grow tall — brand/transition pages stay short),
   so it travels with the scroll instead of stacking onto every page the way
   the body padding did. */
.phone.paged > .section.pg-on { padding-bottom: 88px; }

.pager {
  position: fixed;
  left: 50%;
  bottom: 14px;
  z-index: 60;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 8px;
  width: min(calc(100% - 32px), 448px);
  padding: 8px;
  border: 1px solid var(--gray-200);
  border-radius: 999px;
  background: #fff;
  /* The one blurred shadow in the system, and the only element that earns it:
     the bar genuinely floats above the page, and a hard offset that reads as
     construction on a card reads as a smear on something detached. Everything
     that sits IN the page keeps flat edges. */
  box-shadow: 0 6px 18px rgba(28, 28, 28, .10);
}

.pg-btn {
  flex: none;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--gray-200);
  border-radius: 50%;
  background: #fff;
  color: var(--ink);
  font-family: inherit;
  font-size: 16px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.pg-btn:active { transform: translateY(2px); }
.pg-next { background: var(--lime); border-color: var(--lime); }   /* the only primary action */
.pg-btn:disabled { background: var(--gray-100); border-color: var(--gray-200); color: var(--gray-400); cursor: default; }
.pg-next:disabled { background: var(--gray-100); border-color: var(--gray-200); }

/* the browser's own focus ring landed as a stray blue circle on a page with no
   other blue except the tutor's script — give it the system's own ring */
.pg-btn:focus-visible { outline: 2px solid var(--green-500); outline-offset: 2px; }
.pg-btn:disabled:active { transform: none; }

.pg-mid { flex: 1 1 auto; min-width: 0; }

.pg-label {
  display: flex;
  align-items: baseline;
  gap: 6px;
  justify-content: center;
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1.2;
}

.pg-label .pg-act { font-size: 14.5px; font-weight: 800; }
.pg-label .pg-n { color: var(--gray-500); }

/* a page opened from the 포도 안내 index is off the Next chain, so say so */
.pg-label .pg-n.ref { color: var(--green-500); font-weight: 800; }

@media print {
  .pager { display: none; }
  .phone.paged > * { display: block; }   /* printing always gets the whole deck */
}

/* ---------- the scrubber, on its own row above the buttons ----------
   A 25-page deck makes "back to the page before last" four taps of an arrow.
   Lime on the thumb because lime is the pager's colour — the same fill as
   다음, so it reads as the same object.

   The row break is made by wrap and nothing else: stamp.js inserts the stamp
   button before .pg-teach, so wrapping the buttons in a div of their own
   would delete that slot. The bar takes a squarer radius while it is two
   rows tall — a stadium shape on a two-row bar bows the corners inward.
   Without this rule the scrubber's flex-basis:100% has nowhere to go and it
   squeezes the label into a vertical column of syllables. */
.pager:has(.pg-scrub) {
  flex-wrap: wrap;
  row-gap: 2px;
  padding: 10px 12px 8px;
  border-radius: 26px;
}

.pg-scrub {
  flex: 1 0 100%; width: 100%; height: 20px; margin: 0;
  -webkit-appearance: none; appearance: none; background: none;
  cursor: grab; -webkit-tap-highlight-color: transparent;
}
.pg-scrub:active { cursor: grabbing; }
.pg-scrub::-webkit-slider-runnable-track { height: 6px; border-radius: 999px; background: var(--gray-200); }
.pg-scrub::-moz-range-track { height: 6px; border-radius: 999px; background: var(--gray-200); }
.pg-scrub::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; margin-top: -7px;
  width: 20px; height: 20px; border: 1.5px solid var(--ink); border-radius: 50%; background: var(--lime);
}
.pg-scrub::-moz-range-thumb {
  width: 20px; height: 20px; border: 1.5px solid var(--ink); border-radius: 50%; background: var(--lime);
}
.pg-scrub:focus-visible { outline: none; }
.pg-scrub:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 3px rgba(28,28,28,.22); }

.pg-teach, .pg-exit { width: 32px; height: 32px; background: #fff; font-size: 13px; font-weight: 900; }
.phone.paged ~ .pager .pg-exit { background: var(--ink); border-color: var(--ink); color: #fff; }
.pg-teach.on { background: var(--green-500); border-color: var(--green-500); color: #fff; }

/* ============================================================
   Frameless page cards — no black outline/offset-shadow around
   the page itself. Inner components keep their borders; only the
   OUTER page frame is dropped, so pages float on the background.
   ============================================================ */
.section        { border-color: transparent; box-shadow: none; }
.brand-page     { box-shadow: none; }
.transition-page { box-shadow: none; }


/* ============================================================
   PATTERN ACTIVITIES  (문장 활동)
   ------------------------------------------------------------
   The hangul deck answers everything with .tap-grid / .builder.
   A pattern deck needs three more, and they are the three the
   interactive core lesson already ships — so the markup, the
   class names and the states are taken from
   interactive/sample-lesson-interactive.html rather than invented:

     .slot / .answer-space  → typed blanks     (kind "value")
     .choose-row .opt       → tap one of two   (kind "selection")
     .choice → .build-zone  → order the words  (kind "order")

   Feedback stays quiet and immediate, the way a tap-tile's does:
   right fills lime, wrong greys back out, and the tutor still leads.
   ============================================================ */

/* ---------- typed blanks ---------- */
.slot-input.correct {
  border-style: solid;
  background: var(--green-100);
  border-color: var(--green-500);
}

.slot-input.wrong {
  border-color: #d9534f;
  background: #fdf1f1;
  color: #d9534f;
  animation: miss .3s;               /* the builder's shake, reused */
}

/* a write-in area becomes a real field and keeps the tinted
   "fill the whole thing here" box it already had */
.answer-space.as-input {
  padding: 0;
  color: #1c1c1c;
}

.answer-space.as-input .space-input,
.answer-space.as-input .free-input {
  display: block;
  width: 100%;
  min-height: inherit;
  padding: 13px 16px;
  border: 0;
  background: transparent;
  color: #1c1c1c;
  font: inherit;
  font-family: inherit;
  font-weight: 700;
  resize: none;
  -webkit-appearance: none;
}

/* 자유 작문 칸의 높이는 스크립트가 내용에 맞춰 잡는다. 스크롤바가 뜨면
   방금 쓴 줄이 화면 밖으로 밀려나므로, 넘칠 일 자체를 없앤다. */
.answer-space.as-input .free-input {
  overflow: hidden;
}

.answer-space.as-input .space-input:focus,
.answer-space.as-input .free-input:focus { outline: none; }
.answer-space.as-input:focus-within { background: #fff; }

.answer-space.as-input .space-input::placeholder,
.answer-space.as-input .free-input::placeholder { color: #d8d8d4; font-weight: 700; }

.answer-space.as-input.correct,
.bubble.me .answer-space.as-input.correct { background: #e9fbcf; }

/* ---------- order the words ---------- */
/* the answer area turns into the tray the chips land in; the pool
   underneath holds the ones not placed yet */
.build-zone {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  color: #1c1c1c;
}

.build-zone .choice,
.chip-pool .choice { margin: 0; }

.build-zone.correct,
.bubble.me .build-zone.correct { background: #e9fbcf; }

.build-zone.wrong {
  background: #fdf1f1;
  box-shadow: inset 0 0 0 1.5px #d9534f;
}

.chip-pool {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  min-height: 20px;
  margin-top: 10px;
}

/* ---------- the pieces, inside the box they build in ----------
   The tray is fused to the answer box's underside on the same quiet grey the
   hint band uses: the words you are given and the sentence you are given them
   for are one object. Outside the box they read as loose chips that happened
   to land under it — and the box's rounded bottom clipped the wrong-answer
   fill, because the build zone was the last band in a rounded, clipping box. */
.answer-box > .chip-tray {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 14px;
  border-top: 1px solid var(--gray-200);
  background: var(--gray-50);
}

.chip-tray > .chip-pool {
  flex: 1 1 auto;
  min-height: 34px;      /* holds its height once every chip has been placed */
  margin: 0;
  align-content: center;
}

/* Quiet on purpose: it is the way back, not the thing to do. Grey text on the
   tray's own fill, and it only exists once there is something to undo. */
.build-reset {
  flex: none;
  align-self: center;
  padding: 7px 12px;
  border: 1px solid var(--gray-200);
  border-radius: 999px;
  background: #fff;
  color: var(--gray-500);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.build-reset::before {
  content: "↺";
  margin-right: 5px;
  font-size: 13px;
  font-weight: 700;
}

.build-reset:hover { background: var(--gray-50); color: #1c1c1c; }
.build-reset:active { transform: translateY(1px); }
.build-reset[hidden] { display: none; }

.choice {
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.choice:active { transform: translateY(1px); }

/* ---------- tap one of two ---------- */
.opt {
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.opt.correct { border-style: solid; background: var(--green-100); border-color: var(--green-500); }

/* a wrong pick greys back out and STAYS greyed — `chosen` is the class
   that travels, so the look has to survive as long as the choice does
   (a 700ms flash is invisible to the other screen) */
.opt.chosen:not(.correct) { background: var(--gray-100); color: var(--gray-400); }
.opt.wrong { border-color: #d9534f; background: #fdf1f1; color: #d9534f; animation: miss .3s; }
.opt.dim { opacity: .35; }

/* ---------- which part of the Japanese line the blank asks for ----------
   The header strip carries the whole sentence, but the blank is usually only
   a piece of it — a particle, an ending, one clause. A highlighter swipe
   under that piece (the same one the 안내 page uses on patterns) says "this
   is the part you say in Korean", without adding a second line of text.
   No mark means the whole line is the answer. */
.answer-label .target {
  background: linear-gradient(transparent 52%, var(--lime) 52%);
  color: #1c1c1c;
  font-weight: 800;
}

/* ---------- self-check list ---------- */
.mission li {
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}

.mission li.checked::before {
  content: "✓";
  background: var(--green-100);
  border-color: var(--green-500);
  color: #1c1c1c;
  font-size: 11px;
  font-weight: 800;
  line-height: 13px;
  text-align: center;
}

/* ---------- teaching mode ----------
   Same rule as the letter deck: the answer is present for the tutor and
   never loud. Typed blanks take the answer as their placeholder (set in
   the deck's script — CSS cannot reach inside an input); these two have
   nowhere to put one, so they get a ghost of their own. */
body.teaching .opt[data-correct]:not(.chosen) { box-shadow: 0 0 0 2.5px #e6e6e4; }

body.teaching .build-zone:not(:has(> *))::after {
  content: attr(data-a);
  color: #ddddd9;
  font-size: 17px;
  font-weight: 700;
}


/* ============================================================
   FULL TRIAL · 니즈 파악 · 리포트 · 안내(판매) 페이지
   ------------------------------------------------------------
   레슨을 감싸는 열다섯 장이 쓰는 것들. 체험 레슨 덱 넷이 모두
   같은 앞뒤를 두르므로 한 덱의 <style> 안이 아니라 여기 있다 —
   trial-1 에만 있던 동안, 스크러버도 스크롤바 자리도 그 덱에서만
   고쳐졌다.

   레슨 페이지에는 닿지 않는다: 공용 컴포넌트를 건드리는 다섯 줄은
   전부 이 페이지들의 클래스나 id 로 좁혀져 있다.
   ============================================================ */

/* ================================================================
   NEEDS + REPORT · trial-1 에서 잘라낸 상담 파트
   앞쪽(니즈 3장 + 레벨 체크)은 trial-1-hangul.html 그대로. 뒤쪽 리포트
   3장은 _experiments/trial-report-rebuild.html v5 의 설계를 적용했다.

   리포트는 학습자가 직접 읽는 화면이라 단일 언어다 — 초록 튜터 스크립트
   박스도, 일본어 병기도 없다(지금은 한국어, 실제 출시는 일본어).
   흐름: ① 지금 레벨 → ② 항목별 진단 → ③ 도착 예측.

   클래스 이름에 lvc- 접두사를 쓴 이유: trial.css 가 .opt-row .lv-badge 를
   이미 쓰고 있어서, 목표 선택지의 번호 배지와 충돌하지 않게 갈라 둔다.
   ================================================================ */

/* ---------- 목표 선택지 ----------
   이유 하나가 묶음 하나, 그 안의 세 줄이 그 이유로 갈 수 있는 거리다.
   묶음 제목은 앞 장의 학습 동기를 글자 그대로 되받고, 오른쪽 배지는 그
   줄이 도착하는 레벨 — 처음 보는 사람에게 "Lv.7" 은 아무 크기도 아니라서
   /10 을 붙여 둔다. */
/* 카드 하나 = 도착 레벨 하나. 제목이 거리를 말하고, 속의 줄들이 그 거리가
   이 사람에게 무슨 뜻인지를 이유별로 말한다 — 고를 것은 넷, 읽을 것은
   자기가 고른 이유의 수만큼. */
/* 학습 동기 줄의 그림 — 이모지 자리를 그대로 대신한다 */
.opt-row .r-ico { flex: none; width: 30px; height: 30px; object-fit: contain; }

.goal-list { display: grid; gap: 12px; }
/* 껍데기는 .opt-row 와 같은 값을 쓴다 — 앞뒤 장(학습 동기·학습 페이스)이
   그 컴포넌트라, 여기만 다른 꼴이면 같은 질문이 세 번 다른 화면으로 온다.
   안쪽(막대 배지, 이유별 줄)만 이 페이지의 것이다. */
.glc {
  display: block; width: 100%; padding: 15px 16px 14px; text-align: left;
  border: 1px solid var(--gray-200); border-radius: 13px; background: #fff;
  font-family: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform .09s, background .12s, box-shadow .12s;
}
.glc:active { transform: scale(.99); }
.glc.on { background: var(--green-100); border: 1.5px solid var(--green-500); box-shadow: none; }
.glc-h { display: flex; align-items: center; gap: 13px; }
/* 도착 지점은 숫자가 아니라 막대로 — 「Lv.7」 은 처음 보는 사람에게 크기가
   없는 말이고, 넉 칸 중 몇 칸인지는 세지 않아도 보인다. */
.glc-b { flex: none; display: flex; align-items: flex-end; gap: 3.5px; height: 26px; padding: 0 2px; }
.glc-b i { width: 5px; border-radius: 3px; background: #dcdcd6; }
.glc-b i:nth-child(1) { height: 9px; }
.glc-b i:nth-child(2) { height: 15px; }
.glc-b i:nth-child(3) { height: 21px; }
.glc-b i:nth-child(4) { height: 26px; }
.glc-b i.on { background: #1c1c1c; }
/* 고르면 채운 칸이 초록으로 — .opt-row 의 배지가 하는 것과 같다 */
.glc.on .glc-b i.on { background: var(--green-500); }
.glc-n { font-size: 15.5px; font-weight: 900; color: #1c1c1c; line-height: 1.3; }
.glc-n small { display: block; margin-top: 2px; font-size: 11.5px; font-weight: 700; color: #a5a5a0; }
.glc.on .glc-n small { color: var(--gray-500); }
/* 이유별 「할 수 있게 되는 일」 — 고른 이유의 줄만 남는다.
   구분선은 실선이다: 점선 회색은 이 시스템에서 "여기 쓰세요" 하나만 뜻한다. */
.glc-l { display: grid; gap: 7px; margin-top: 13px; padding-top: 12px; border-top: 1px solid var(--gray-200); }
.glc.on .glc-l { border-top-color: var(--green-500); }
.glc-i { display: grid; grid-template-columns: 22px 1fr; column-gap: 9px; align-items: center; }
.glc-i.hide, .glc-e.hide { display: none; }
/* 이유 그림은 PODO 앱 온보딩과 같은 것을 쓴다 — 앱에서 고른 이유와
   상담에서 고른 이유가 같은 그림이면, 설명 없이 같은 질문으로 읽힌다. */
.glc-ico { width: 22px; height: 22px; object-fit: contain; }
.glc-i b { font-size: 13.5px; font-weight: 800; color: #1c1c1c; line-height: 1.4; word-break: keep-all; }
.glc-i em {
  grid-column: 2; margin-top: 1px; font-style: normal; font-size: 11.5px;
  font-weight: 600; color: #8a8a85; line-height: 1.4; word-break: keep-all;
}
.glc.on .glc-i em { color: var(--gray-500); }
.glc-e { font-size: 12px; font-weight: 600; color: #a5a5a0; line-height: 1.45; }

/* 리포트 페이지는 튜터 스크립트 대신 담담한 부제를 쓴다 */
.rv-sub { margin: 8px 0 24px; font-size: 14px; font-weight: 500; color: #8a8a85; line-height: 1.55; word-break: keep-all; }
/* trial.css 가 700 으로 세워 둔 본문을 낮춘다 — 굵기는 제목·수치에만 */

/* ---------- ② 레이더 (지금 채움 vs 평균 외곽) ---------- */
.rad-legend { display: flex; justify-content: center; gap: 24px; margin: 4px 0 0; }
.rad-legend span { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 700; color: #1c1c1c; }
.rad-legend i { width: 14px; height: 14px; border-radius: 5px; }
.rad-legend i.avg { border: 2px dashed #b4b4b0; background: none; border-radius: 4px; }
.rad { display: block; width: 100%; height: auto; margin: -2px auto 6px; }

/* ================================================================
   ⓪ 튜터 콘솔 · 레벨 체크
   리포트 전체가 이 선택에서 파생되므로 페이지 맨 위에 둔다. 학습자에게는
   아예 없는 블록이고(teaching 모드에서만 뜬다), 고르고 나면 한 줄로
   접힌다 — 튜터도 폼을 채우러 온 게 아니라 리포트를 보러 온 사람이다.
   선택 자체는 공유된다: 컨트롤만 튜터의 것이고, 결과인 리포트는 둘 다
   같은 걸 봐야 한다.
   ================================================================ */
.tcon { display: none; }
body.teaching .tcon { display: block; margin: 0 0 28px; }
.tcon-body { padding: 18px 18px 16px; border: 1.5px dashed #1c1c1c; border-radius: 14px; background: #fbfbf8; }
.tcon.folded .tcon-body { display: none; }
.tcon:not(.folded) .tcon-sum { display: none; }

.tcon-sum { display: flex; align-items: center; gap: 10px; width: 100%; padding: 11px 14px; border: 1.5px dashed #1c1c1c; border-radius: 12px; background: #fbfbf8; font-family: inherit; text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.tcon-sum .ts-lv { flex: none; padding: 3px 10px; border-radius: 999px; background: #1c1c1c; color: #b5fd4c; font-size: 12px; font-weight: 900; }
.tcon-sum .ts-ax { flex: 1 1 auto; min-width: 0; font-size: 12px; font-weight: 700; color: #6f6f6a; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tcon-sum .ts-go { flex: none; font-size: 11.5px; font-weight: 800; color: #4a7a2a; }

.tcon-h { display: flex; align-items: baseline; gap: 8px; font-size: 15px; font-weight: 900; color: #1c1c1c; }
.tcon-h small { font-size: 11px; font-weight: 800; color: #8a8a85; }
.tcon-q { margin: 17px 0 0; font-size: 12.5px; font-weight: 800; color: #55554f; }
.tcon-q small { font-weight: 600; color: #8a8a85; }
.tcon .lvpick { gap: 7px; margin-top: 10px; }
.tcon .lvrow { gap: 11px; padding: 9px 12px; border-radius: 11px; }
.tcon .lvrow .lvn { width: 28px; height: 28px; border-radius: 8px; font-size: 14px; }
.tcon .lvrow .lvt { font-size: 13.5px; }
.tcon .lvrow .lvs { margin-top: 1px; font-size: 11px; }

.tcon-fold { width: 100%; margin-top: 18px; padding: 10px; border: 1.5px solid #1c1c1c; border-radius: 11px; background: #fff; font-family: inherit; font-size: 13px; font-weight: 800; color: #1c1c1c; cursor: pointer; }

/* ---------- 한 장으로 합친 리포트 ----------
   ①②③ 이 한 페이지 안에서 이어지므로 블록 사이는 가는 선으로만 나눈다.
   초록 카드는 이제 페이지가 아니라 페이지 안의 첫 블록이다. */



/* ================================================================
   리포트 · Figma「❤️ PODO JP」> 상담 및 리포트 v2 > 리포트
   초록 테두리 카드 넉 장이 리포트 전체다. 카드는 흰 바탕이 기본이고,
   레벨·커리큘럼처럼 "나에 대한 이야기" 인 두 장만 연한 라임 물을 먹는다 —
   같은 굵기의 테두리 안에서 바탕만 갈라 두면 넉 장이 읽는 순서를 갖는다.
   ================================================================ */
/* 리포트 페이지는 페이지 카드의 테두리를 벗는다 — 초록 카드 넉 장이
   이미 상자라, 그 밖을 한 번 더 두르면 상자가 세 겹이 된다. */
.rep-page.rep-page {
  margin: 0; padding: 24px 20px 36px;
  border: 0; border-radius: 0; box-shadow: none;
}
.rep-page .rhead { margin-bottom: 4px; }
.rhead-k { display: block; color: var(--green-500); font-size: 12px; font-weight: 800; letter-spacing: -.02em; }
.rhead-t { margin: 6px 0 0; font-size: 22px; font-weight: 800; line-height: 1.45; letter-spacing: -.02em; word-break: keep-all; }
.rhead-m { margin: 2px 0 0; color: var(--gray-400); font-size: 14px; font-weight: 500; }

.rsec {
  margin-top: 16px; padding: 20px;
  border: 1px solid var(--green-500); border-radius: 24px; background: #fff;
}
/* 네 장 모두 흰 바탕에 초록 테두리다. 카드 자체를 연두로 칠하면 그 안의
   상자들이 흰색으로 뒤집혀야 하고, 그러면 「연두 = 포도가 짚어 주는 것」
   이라는 읽는 법이 카드마다 반대가 된다. 칠하는 쪽은 늘 안쪽 상자다. */
.rsec-h { margin: 0 0 16px; font-size: 18px; font-weight: 700; line-height: 26px; letter-spacing: -.02em; word-break: keep-all; }
.rsec-h small { display: block; margin-top: 4px; color: var(--gray-400); font-size: 14px; font-weight: 500; }

/* ---------- ① 내 레벨 ---------- */
.lvbig { display: flex; align-items: center; gap: 4px; }
.lvbig-b { flex: 1 1 auto; min-width: 0; }
.lvbig-n { margin: 0; display: flex; align-items: baseline; }
.lvbig-n b { font-size: 40px; font-weight: 900; letter-spacing: -.02em; }
.lvbig-n span { margin-left: 4px; color: var(--gray-400); font-size: 22px; font-weight: 800; }
.lvbig-l { margin: 4px 0 0; font-size: 18px; font-weight: 800; letter-spacing: -.02em; word-break: keep-all; }
.lvbig-l b { font-weight: 800; color: var(--green-500); }
/* 레벨 마스코트 — 열 단계가 한 장씩 있고, 고른 레벨의 그림으로 갈린다 */
.lvbig-img { flex: none; width: 80px; height: 80px; object-fit: contain; }

.rline { height: 1px; margin: 16px 0; border: 0; background: var(--gray-200); }

/* 근거 줄 — ✓ 원이 붙은 짧은 문장. 카드 안의 유일한 상자다 */
.chk.hide { display: none; }
.chk { margin: 0; padding: 12px; border-radius: 12px; background: #f2fce0; list-style: none; }
.chk li { display: flex; gap: 8px; align-items: flex-start; font-size: 14px; font-weight: 500; line-height: 1.45; word-break: keep-all; }
.chk li + li { margin-top: 12px; }
.chk li b { font-weight: 800; }
.chk i {
  flex: none; width: 20px; height: 20px; margin-top: 1px; border-radius: 50%;
  display: grid; place-items: center; background: var(--green-500);
  color: #fff; font-size: 11px; font-style: normal; font-weight: 900;
}
.chk li.miss i { background: #dcdbd6; color: #6f6f6a; }

.topikrow { display: flex; align-items: center; gap: 4px; margin: 16px 0 0; }
.topikrow i {
  flex: none; padding: 4px 10px; border-radius: 999px; background: var(--ink);
  color: #fff; font-size: 12px; font-style: normal; font-weight: 800;
}
.topikrow span { font-size: 12px; font-weight: 800; word-break: keep-all; }

/* ---------- ② 항목별 진단 ---------- */
.radbox { padding: 12px; border-radius: 12px; background: #fff; box-shadow: 0 0 6px rgba(0,0,0,.15); }
.rsec .rad { margin: 0; }
.rsec .rad-legend { justify-content: flex-start; gap: 16px; margin: 0 0 4px; }
.rsec .rad-legend span { font-size: 11px; font-weight: 500; }
.rsec .rad-legend i { width: 4px; height: 4px; border-radius: 50%; background: var(--green-500); }
/* 평균은 레이더에서도 막대에서도 회색 점선이다 — 범례도 같은 재질로 말한다 */
.rsec .rad-legend i.avg { width: 14px; height: 0; border: 0; border-top: 2px dashed #b4b4b0; border-radius: 0; background: none; }
.rsec .rad-legend .avg + * , .rsec .rad-legend span:last-child { color: var(--gray-400); }

/* 항목 다섯 줄. 트랙 하나에 채움 하나 — 잘하는 두 항목만 파랑이라,
   아래 「좋아요」 상자와 색으로 이어진다. */
.axbars { display: grid; gap: 8px; margin-top: 16px; padding: 0 4px; }
.axb { display: flex; align-items: center; gap: 8px; }
.axb-n { flex: none; width: 52px; font-size: 14px; font-weight: 800; letter-spacing: -.02em; }
.axb-t { position: relative; flex: 1 1 auto; height: 12px; border-radius: 999px; background: var(--gray-200); }
.axb-f { position: relative; z-index: 1; display: block; height: 100%; border-radius: 999px; background: var(--green-500); }
/* 평균 = 트랙의 0→평균 구간을 그대로 따라 그린 점선 캡슐.
   세로 눈금 하나를 세우던 자리다. 눈금은 막대와 재질이 달라서 「막대 + 눈금자」
   로 읽혔고, 초록이 그 선을 지나가면 막대에 난 금처럼 보였다. 점선 캡슐은
   막대와 같은 12px·같은 자리에 겹치고(box-sizing: border-box 라 2px 테두리가
   12px 안쪽에 그려져 막대가 두꺼워지지 않는다), 평균도 「길이」 로 말한다. */
.axb-avg {
  position: absolute; inset: 0 auto 0 0; z-index: 0; box-sizing: border-box;
  border: 2px dashed #b4b4b0; border-radius: 999px; background: none;
}
/* 캡슐은 초록 아래에 깔린다 — 덮인 구간은 초록이 매끈하게 이기고, 대신 평균이
   서 있던 자리에 그 캡슐의 「오른쪽 끝」 만 남긴다. 새 기호가 아니라 가려진
   마감 그대로라(반지름 5 = 막대 높이의 절반), 평균 아래 줄의 둥근 점선 끝과
   같은 곡률이다. 호의 꼭짓점이 평균값 자리에 선다. */
.axb-cap { position: absolute; top: 0; z-index: 2; }
.axb-cap svg { display: block; overflow: visible; }
.axb-cap path { fill: none; stroke: #3f7d1a; stroke-width: 2; stroke-dasharray: 3 3; }

.axsum.hide, .axtip.hide { display: none; }
.axsum { display: flex; gap: 4px; margin-top: 16px; }
/* 잘하는 쪽/아쉬운 쪽은 초록·회색이 아니라 파랑·분홍이다: 초록은 이 페이지에서
   이미 「내 값」 이라, 칭찬에까지 쓰면 어느 초록인지 매번 되짚어야 한다. */
.axs { flex: 1 1 0; min-width: 0; padding: 12px; border-radius: 12px; background: #dee9f7; }
.axs.weak { background: #fae4e5; }
.axs h4 { display: flex; align-items: center; gap: 4px; margin: 0; color: #1087ff; font-size: 16px; font-weight: 800; letter-spacing: -.02em; }
.axs.weak h4 { color: #fa2a49; }
.axs h4 img { width: 20px; height: 20px; }
.axs ul { margin: 4px 0 0; padding-left: 21px; }
.axs li { font-size: 14px; font-weight: 500; line-height: 1.45; }

.axtip { margin-top: 6px; padding: 12px; border-radius: 12px; background: var(--green-100); }
.axtip h4 { display: flex; align-items: center; gap: 4px; margin: 0; color: var(--green-500); font-size: 16px; font-weight: 800; letter-spacing: -.02em; }
.axtip h4 img { width: 24px; height: 24px; }
.axtip p b { font-weight: 800; }
.axtip p { margin: 4px 0 0; font-size: 14px; font-weight: 500; line-height: 1.45; word-break: keep-all; }

/* ---------- ③ 원하는 레벨까지 · 주당 횟수 슬라이더 ---------- */
.freq.hide, .tiles.hide { display: none; }
.freq { padding: 12px 14px; border-radius: 12px; background: var(--gray-100); }
.freq-h { margin: 0; font-size: 16px; font-weight: 700; line-height: 24px; letter-spacing: -.02em; }
.freq-h b { color: var(--green-500); }
.freq-h span { color: var(--ink); }
.freq-slot { position: relative; margin-top: 4px; padding-top: 24px; }
/* 말풍선이 손잡이 위에 붙어 지금 값을 말한다 — 트랙 위에는 숫자를 얹을
   자리가 없고, 끌면서 눈이 손잡이를 따라가기 때문이다. */
.freq-bub {
  position: absolute; top: 0; transform: translateX(-50%);
  color: var(--green-500); font-size: 14px; font-weight: 800; white-space: nowrap;
}
.freq-range {
  display: block; width: 100%; height: 16px; margin: 0;
  -webkit-appearance: none; appearance: none; background: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.freq-range::-webkit-slider-runnable-track { height: 12px; border-radius: 999px; background: var(--gray-200); }
.freq-range::-moz-range-track { height: 12px; border-radius: 999px; background: var(--gray-200); }
.freq-range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; margin-top: -2px;
  width: 16px; height: 16px; border: 3px solid var(--green-500); border-radius: 50%; background: #fff;
}
.freq-range::-moz-range-thumb {
  width: 16px; height: 16px; border: 3px solid var(--green-500); border-radius: 50%; background: #fff;
}
.freq-ends { display: flex; justify-content: space-between; margin-top: 6px; }
.freq-ends i { font-style: normal; font-size: 12px; font-weight: 500; color: var(--ink); }

.tiles { display: flex; gap: 8px; margin-top: 8px; }
.tile { flex: 1 1 0; min-width: 0; padding: 12px 14px; border-radius: 12px; background: var(--green-100); }
.tile-k { display: block; color: var(--green-500); font-size: 16px; font-weight: 700; line-height: 24px; letter-spacing: -.02em; }
.tile-v { display: flex; align-items: center; gap: 11px; margin-top: 4px; }
.tile-v img { width: 37px; height: 37px; }
.tile-v b { font-size: 22px; font-weight: 700; line-height: 32px; letter-spacing: -.02em; }

/* 추천 코스 길 */
.road { margin-top: 12px; padding: 12px 14px; border-radius: 12px; background: var(--green-100); }
.road-k { display: block; color: var(--green-500); font-size: 16px; font-weight: 700; line-height: 24px; letter-spacing: -.02em; }
.road-svg { display: block; width: 100%; height: auto; margin-top: 4px; }
/* 길과 점 · 상태는 전부 여기서 입는다(report.js 는 클래스만 갈아 끼운다).
   한 걸음이 색과 크기를 함께 바꾸므로 전환을 걸어 두면 「다음」 을 누를 때
   초록이 차오르는 것과 점이 자라는 것이 같은 박자로 움직인다. */
.rd-track { stroke: #e8eae1; }
.rd-fill { stroke: var(--green-500); }
.rd-dot {
  r: 6; fill: #fff; stroke: #e8eae1; stroke-width: 3.5;
  transition: r .3s ease, fill .3s ease, stroke .3s ease, stroke-width .3s ease;
}
/* 코스가 서지 않은 자리는 이름 없는 눈금으로 내린다 — 그림의 점 수는 고정이고
   코스는 그중 몇 자리에만 서므로, 나머지가 정거장과 같은 무게면 안 된다 */
.rd-dot.minor { r: 4; stroke-width: 3; }
.rd-dot.minor.done { r: 2; }
/* 도착점은 늘 서 있다 — 크기로 목적지라고 말한다 */
.rd-dot.goal { r: 8.5; stroke: var(--green-500); stroke-width: 4; }
/* 지나온 마디는 길 안으로 들어가 흰 점 하나만 남긴다. 길 밖으로 나오지 않는 것이
   핵심이다 — 반지름(선 굵기 12 → 6)을 넘기는 순간 곧은 길에는 물집이 잡히고
   굽이에서는 곡선이 우그러진다. 자국까지 지우면 지나온 자리가 아예 없던 자리가
   되므로, 길 안에 들어갈 만큼만 남긴다. */
.rd-dot.done { r: 3; fill: #fff; stroke-width: 0; }
/* 지금 선 자리 · 눈금이든 정거장이든 밟고 있으면 제 크기로 선다 */
.rd-dot.now { r: 8; fill: #fff; stroke: var(--green-500); stroke-width: 4.5; }
.rd-dot.goal.now { r: 10; stroke-width: 5; }
.rd-halo { fill: var(--green-500); opacity: 0; transition: opacity .3s ease; }
.rd-halo.on { opacity: .15; }
/* 라벨 · 지금과 ⅓·⅔ 는 같은 기준선의 한 단, 도착만 한 단 위 */
.rd-cap { font-weight: 800; letter-spacing: -.02em; }
.rd-cap.start { font-size: 11px; fill: var(--ink); }
.rd-cap.wp { font-size: 10px; font-weight: 700; fill: var(--gray-500); }
/* 도착 눈금은 초록과 굵기만으로도 끝이라고 말한다 — 크기까지 얹으면 바로 위
   도착점을 밀어내고, 둘이 서로 붙어 한 덩어리로 뭉친다 */
.rd-cap.dest { font-size: 12px; fill: var(--green-500); }
/* 「아직 안 골랐어요」 는 비어 있다는 알림이지 이 페이지의 주된 행동이 아니다.
   trial.css 의 .rep-jump 는 라임 채움 + 먹색 오프셋 그림자라 카드 안에서 가장
   큰 소리를 내는데, 둘 다 은퇴한 Podo Bold 의 것이고 라임은 브랜드 크롬이지
   상태가 아니다. 여기서는 자리를 비워 둔 회색 칸으로 되돌린다 — 다른 덱의
   .rep-jump 는 건드리지 않도록 이 카드 안으로만 한정한다. */
.rsec .rep-jump {
  display: flex; align-items: center; gap: 12px; margin-top: 0;
  padding: 13px 14px; border: 1px solid var(--gray-200); border-radius: 12px;
  background: var(--gray-50); box-shadow: none; text-align: left;
}
.rsec .rep-jump:active { transform: none; box-shadow: none; background: var(--gray-100); }
/* 이 규칙이 trial.css 의 .rep-jump.hide 와 특정도가 같고 뒤에 오므로,
   감추는 쪽도 여기서 다시 말해 주어야 한다 */
.rsec .rep-jump.hide { display: none; }
.rsec .rep-jump .rj-b { flex: 1 1 auto; min-width: 0; }
.rsec .rep-jump .rj-t { font-size: 13.5px; font-weight: 800; color: var(--ink); }
.rsec .rep-jump .rj-s { margin-top: 2px; color: var(--gray-500); font-size: 11.5px; font-weight: 600; opacity: 1; }
/* 스크롤이 아니라 페이지 넘김이라 화살표도 위가 아니라 앞을 가리킨다 */
.rsec .rep-jump .rj-s::after { content: none; }
.rsec .rep-jump::after {
  content: "→"; flex: none; color: var(--gray-400); font-size: 15px; font-weight: 900;
}
.rcourse { padding: 10px 14px; border-radius: 12px; background: var(--green-100); }
.rcourse .k { display: block; color: var(--green-500); font-size: 16px; font-weight: 800; letter-spacing: -.02em; }
.rcourse .big { display: block; margin-top: 4px; font-size: 30px; font-weight: 800; letter-spacing: -.05em; }
.rcourse .s { display: block; margin-top: 4px; color: var(--gray-400); font-size: 14px; font-weight: 500; line-height: 1.43; }

/* ---------- ③ 이대로만 따라오면 돼요 · 기간과 길이 한 덩어리 ----------
   개월 · 레슨 · 슬라이더 · 길 네 칸이 가로·세로 모두 3 이음매로 붙는다. 한 축만
   넓거나 길만 떨어져 있으면 「세 칸 + 한 칸」 으로 갈려서, 카드가 한 덩어리가
   아니라 블록 두 개로 읽힌다. 바깥 네 귀만 12 로 두고 붙는 쪽은 전부 4 로 죽여,
   네 칸이 한 판에서 잘려 나온 조각이 되게 한다.
   원안: trial/_experiments/trial-report-plan-merge-variations.html ① */
.pm-fuse .tiles { margin-top: 0; gap: 3px; }
.pm-fuse .tiles .tile:first-child { flex: 1 1 0; border-radius: 12px 4px 4px 4px; }
.pm-fuse .tiles .tile:last-child { flex: 0 0 auto; border-radius: 4px 12px 4px 4px; }
/* 가운데 칸이라 네 귀가 다 죽는다 */
.pm-fuse .pm-freq { margin-top: 3px; padding: 12px 14px; border-radius: 4px; background: var(--green-100); }
.pm-fuse.hide { display: none; }
/* 길이 덩어리의 마지막 칸 — 아래 두 귀만 12 */
.pm-road { margin-top: 3px; }
.pm-road .road { margin-top: 0; border-radius: 4px 4px 12px 12px; }
/* 코스 카드는 이 덩어리에 속하지 않는다 — 길이 어디까지인지를 말하는 칸이
   아니라, 지금 선 마디가 무슨 코스인지를 따로 펴는 카드다. */
.pm-card .curli { margin-top: 8px; }

/* 레일 · 말풍선을 떼고 눈금 일곱을 깔았다 */
.pm-inline { display: flex; align-items: center; gap: 14px; }
.pm-rail .freq-h { flex: none; margin: 0; }
/* .freq-slot 은 말풍선 자리로 위를 24px 비워 둔다 — 말풍선을 뗐으니 그 자리도
   함께 거둔다. 안 그러면 레일만 위에 남고 손잡이가 밑으로 내려간다. */
.pm-rail .freq-slot { position: relative; flex: 1 1 auto; min-width: 0; margin-top: 0; padding-top: 0; }
/* 레일은 트랙이 아니라 슬롯이 그린다 — 눈금을 레일 뒤에 깔아야 해서다 */
.pm-rail .freq-slot::before {
  content: ""; position: absolute; left: 0; right: 0; top: 12px; height: 4px;
  border-radius: 999px; background: #d6e9c9; z-index: 0;
}
/* 눈금 일곱 · 손잡이 반지름(7px)만큼 안으로 들여야 손잡이 한가운데와 만난다.
   높이 0 인 줄 위에 세로 가운데로 걸어 두면 눈금 길이를 바꿔도 레일 한가운데를
   그대로 지난다. 손잡이가 선 눈금은 손잡이 테가 덮는다 — 삐져나오면 먹색 점
   위아래로 꼬리가 남아 십자로 읽힌다. */
.pm-ticks {
  position: absolute; left: 7px; right: 7px; top: 14px; height: 0; z-index: 0;
  display: flex; align-items: center; justify-content: space-between;
}
.pm-ticks i { width: 2px; height: 8px; border-radius: 1px; background: #cfe3c1; }
/* 레일과 눈금이 자리 잡은 레이어(absolute)는 손잡이보다 위에 그려진다 —
   띄워 주지 않으면 레일이 먹색 손잡이를 가로질러 십자로 보인다. */
.pm-rail .freq-range {
  display: block; width: 100%; height: 28px; margin: 0; position: relative; z-index: 1;
  -webkit-appearance: none; appearance: none; background: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.pm-rail .freq-range::-webkit-slider-runnable-track { height: 28px; background: none; }
.pm-rail .freq-range::-moz-range-track { height: 28px; background: none; }
.pm-rail .freq-range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; margin-top: 7px;
  width: 14px; height: 14px; border: 0; border-radius: 50%;
  background: var(--ink); box-shadow: 0 0 0 4px var(--green-100);
}
.pm-rail .freq-range::-moz-range-thumb {
  width: 14px; height: 14px; border: 0; border-radius: 50%;
  background: var(--ink); box-shadow: 0 0 0 4px var(--green-100);
}

/* ---------- ④ 커리큘럼 로드맵 ---------- */
.road-card .road { margin-top: 6px; }
.road-card .curli { margin-top: 6px; }

/* 앞뒤 버튼 + 몇 칸인지 */
.rc-nav { display: flex; align-items: center; gap: 10px; margin-top: 14px; }
.rc-btn {
  flex: none; padding: 9px 13px; border: 1px solid var(--gray-200); border-radius: 999px;
  background: #fff; font-family: inherit; font-size: 12.5px; font-weight: 800; color: var(--ink);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.rc-btn:disabled { color: #c4c4be; cursor: default; }
.rc-btn:not(:disabled):active { transform: translateY(1px); }
.rc-dots { flex: 1 1 auto; display: flex; justify-content: center; gap: 5px; }
.rc-dots i { width: 6px; height: 6px; border-radius: 50%; background: #d5ddc9; }
.rc-dots i.on { width: 18px; border-radius: 3px; background: var(--green-500); }


/* ================================================================
   코스 칸 · 그 코스에서 실제로 하는 일을 한 장으로

   코스마다 「무엇을 배우나」 를 문장으로 늘어놓던 자리다. 문장이 셋(이름 ·
   한 줄 설명 · 예문) 쌓이면 어느 것이 결론인지 알 수 없어서, 두 가지를
   바꿨다.

   ① 할 수 있게 되는 일이 이름 바로 밑으로 올라왔다. 전에는 맨 아래 칩이라
      읽는 순서상 마지막 = 「덤」 으로 보였는데, 코스를 사게 만드는 문장은
      사실 이것이다 — 이름이 「무엇을 배우나」 라면 이 줄은 「그래서 내가 뭘
      하게 되나」 이고, 궁금한 쪽은 언제나 뒤쪽이다. 이름과 한 머리(.hy-head)
      로 묶어, 그림 하나가 둘을 함께 가리키게 했다.
   ② 예문 자리에는 글 대신 그림이 선다. 코스가 배우는 일의 모양이 서로
      달라서 한 틀로 못 담는다 — 한글은 글자를 조립하는 일, 핵심은 틀을
      갈아 끼우는 일, 나머지는 말을 주고받는 일이다(report.js artHTML()).

   커버 그림은 카드 뒤에 크게 눕는다. 모서리에 또렷하게 두면 「잘린 그림」
   한 조각으로 읽혀 가운데 물건과 싸우므로, 키우고 지워서 결로 만든다.
   ================================================================ */
/* 칸마다 높이가 달라지면 「다음」 을 누를 때마다 아래 리포트가 통째로 밀린다.
   읽는 사람이 보는 건 카드 한 장인데 움직이는 건 페이지 전체라, 넘길 때마다
   눈이 자리를 다시 찾는다. 그래서 높이를 한 값으로 못 박고, 남는 세로는
   그림 자리(.hy-stage)가 혼자 먹는다 — 머리와 설명은 제자리에 그대로 있고
   그림만 가운데에서 숨을 쉰다.

   높이 값은 폭마다 다르다. 좁아지면 대사가 한 줄씩 더 접혀서 그림 자체가
   길어지기 때문이다(프리토킹의 두 줄짜리 대사가 360px 에서 세 줄이 된다).
   그래서 한 값으로 못 박는 대신, 폭 구간마다 그 구간에서 가장 큰 칸에 맞춘
   값을 준다 — 어느 폭에서 보든 넘길 때 높이는 그대로다.
     카드 폭 310 이상 : 340   (설계 폭 480 이 여기 든다. 310 에서 재면 340)
     카드 폭 290~309  : 346
     카드 폭 270~289  : 348
     카드 폭 250~269  : 389
     카드 폭 249 이하 : 410   (230 에서 재면 410)
   각 값은 그 구간의 **가장 좁은 쪽**에서 잰 것이다 — 구간이 좁아질수록 글이
   한 줄씩 더 접혀 카드가 커지므로, 구간 안에서 가장 높이 필요한 곳은 언제나
   그 구간의 왼쪽 끝이다. 거기에 맞춰야 구간 전체가 한 높이로 선다.
   그래서 각 구간의 값은 **자기 경계가 아니라 한 칸 아래 경계**에서 잰 값이다 —
   자기 경계에서 재면 그 구간의 넓은 쪽만 맞고 좁은 쪽이 넘친다.
   재는 것은 화면이 아니라 카드 자신의 폭이라야 한다(@container) — 이 덱은
   가운데 480px 짜리 판으로도 열리고 폰에서 전체 폭으로도 열려서, 화면 폭과
   카드 폭이 같지 않다. 값이 모자라 글이 한 줄 더 접히면 카드가 늘어나는 편이
   잘리는 것보다 낫다(그래서 height 가 아니라 min-height 다). */
.curli { container-type: inline-size; }
.hy {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; min-height: 340px;
  border: 1px solid var(--gray-200); border-radius: 16px; background: #fff;
}
@container (max-width: 309px) { .hy { min-height: 346px; } }
@container (max-width: 289px) { .hy { min-height: 348px; } }
@container (max-width: 269px) { .hy { min-height: 389px; } }
@container (max-width: 249px) { .hy { min-height: 410px; } }
/* 커버 워터마크(.hy-wm)가 있던 자리다. 그림이 작아서 카드가 허전할 때는
   구석의 결이라도 있는 편이 나았지만, 가운데 물건을 카드에 꽉 차게 키우고
   나니 결이 도울 일이 없어졌다 — 말풍선 옆을 지나가며 어지럽히기만 했다.
   되살리려면 이 자리에 규칙을 되돌리고 카드 마크업의 <img class="hy-wm"> 와
   .cov-src 여섯 장을 함께 되살린다(report.js renderCurriculum). */
/* ---------- 카드의 머리 ----------
   그림 하나에 두 줄이 매달리고, 아래 실선이 거기까지가 머리라고 닫는다.

     [그림]  코스 이름 · 레슨 수            n / N
             할 수 있게 되는 일
     ─────────────────────────────────────────────

   전에는 이름줄 아래에 연두 띠가 따로 앉았다. 면이 있으니 「여기가 결론」 인
   건 읽히는데, 그 결론이 바로 위 코스의 것이라는 말은 어디에도 없어서 띠가
   혼자 떠 있었다 — 면은 묶는 대신 오히려 갈랐다. 그림을 두 줄 왼쪽에 하나만
   세우면 그 그림이 둘을 함께 가리키므로, 면 없이도(면이 없어야) 둘이 한
   덩어리가 된다. 니즈 페이지의 「학습 동기」 줄과 같은 꼴이다: 그림 + 큰 줄 +
   작은 줄. 덱에 이미 있는 말투를 리포트가 그대로 쓴다. */
.hy-head {
  position: relative; display: flex; align-items: center; gap: 12px;
  padding: 13px 16px; border-bottom: 1px solid var(--gray-200);
}
.hy-hb { flex: 1 1 auto; min-width: 0; }
/* 머리줄의 셋은 모두 낱말 하나로 다룬다. 한국어는 기본적으로 아무 데서나
   줄이 꺾이므로, 자리가 좁아지면 「목표 도 / 착」 처럼 글자 사이가 갈린다.
   이름만 keep-all 로 두어 정 안 되면 띄어쓰기에서 접히게 하고, 짧은 둘은
   아예 안 접히게 묶는다. */
/* 코스 이름이 제목이다. 전에는 이름 14.5px 에 아랫줄 16px 이라 아랫줄이 더
   컸고, 그래서 카드 맨 위가 제목으로 읽히지 않았다 — 무엇의 카드인지가
   두 번째로 큰 글자에 적혀 있으면 그건 제목이 아니다. 이름을 키워 올리고
   아랫줄은 한 급 내린다: 제목 → 그래서 무엇을 하게 되나, 읽는 순서 그대로. */
.hy-h { display: flex; align-items: center; gap: 7px; }
.hy-h b { font-size: 17.5px; font-weight: 900; letter-spacing: -.03em; word-break: keep-all; }
/* 레슨 수는 알약으로 — 제목 옆에 붙는 수치라 글자로 두면 제목의 일부처럼 읽힌다 */
.hy-n {
  flex: none; white-space: nowrap; padding: 3px 8px; border-radius: 999px;
  background: var(--green-100); color: #4e9422; font-size: 11.5px; font-weight: 800;
}
.hy-no {
  flex: none; margin-left: auto; padding-left: 6px; white-space: nowrap;
  font-size: 11.5px; font-weight: 700; color: var(--gray-400);
}
/* 그래서 무엇을 하게 되나 · 제목을 받는 줄 */
.hy-do {
  margin: 4px 0 0;
  font-size: 15px; font-weight: 700; line-height: 1.35; letter-spacing: -.02em;
  color: var(--ink); word-break: keep-all;
}
/* 코스의 그림 · 니즈 페이지에서 고른 이유의 그림 그대로다.
   그림과 ✓ 는 폭이 같은 자리에 선다(30px) — 그림이 아직 없는 코스와 있는
   코스를 번갈아 넘겨도 옆 글자가 좌우로 튀지 않아야 한다. */
/* 그림은 두 줄을 합친 높이만큼 선다 — 한 줄에만 걸치면 그 줄의 장식으로
   보이고, 둘을 다 덮어야 「이 그림이 이 카드의 것」 으로 읽힌다. */
.hy-do-i { flex: none; width: 48px; height: 48px; object-fit: contain; }
.hy-head > i {
  flex: none; display: grid; place-items: center; width: 32px; height: 32px; margin: 0 8px;
  border-radius: 50%; background: var(--green-500);
  color: #fff; font-size: 16px; font-style: normal; font-weight: 900;
}
/* 그림이 서는 자리 · 여백이 이 안의 전부다. 카드에 남는 세로를 이 칸이
   혼자 먹으므로(flex: 1), 카드가 어느 칸이든 그림은 늘 가운데에 선다.
   여백은 좁게 잡는다 — 이 칸이 카드에서 가장 큰 자리이므로, 여기서 아낀
   px 가 그대로 그림의 크기가 된다. */
.hy-stage { position: relative; flex: 1 1 auto; display: grid; place-items: center; min-height: 132px; padding: 20px 16px; }
.hy-cap {
  position: relative; padding: 0 16px 16px; text-align: center;
  font-size: 12.5px; font-weight: 600; color: var(--gray-500); word-break: keep-all;
}

/* 그림 ① 한글 · 자음 + 모음 = 한 글자.
   자리색은 한글 덱의 것을 그대로 쓴다(.seat-c/.seat-v/.seat-lr) — 리포트가
   레슨과 다른 색으로 말하면 첫 수업에서 그 색을 다시 배워야 한다. */
.hy .sp-han { display: flex; align-items: flex-end; gap: 18px; }
.hy .hbk { display: grid; justify-items: center; }
.hy .hbk-j { display: flex; gap: 6px; }
.hy .hbk-j span {
  display: grid; place-items: center; width: 47px; height: 47px; border-radius: 12px;
  font-size: 26px; font-weight: 800; letter-spacing: -.02em;
}
.hy .hbk-j .seat-c { color: var(--c-ink); }
.hy .hbk-j .seat-v { color: var(--v-ink); }
/* 두 자리가 한 글자로 모이는 팔 — 화살표보다 조용하고, 「합쳐진다」 를 한 번에 말한다.
   폭은 위 타일 둘의 폭 그대로다(42+6+42=90). 좌표는 report.js 가 그 폭에 맞춰
   그리므로, 타일 크기를 바꾸면 그쪽 path 도 함께 바꿔야 한다. */
.hy .hbk-arm { display: block; width: 100px; height: 19px; margin: 5px 0 4px; }
.hy .hbk-arm path { stroke: #cfcfc9; stroke-width: 1.7; stroke-linecap: round; fill: none; }
.hy .hbk-s {
  display: grid; place-items: center; width: 78px; height: 78px; border-radius: 18px;
  font-size: 43px; font-weight: 800; letter-spacing: -.02em; color: var(--ink);
}

/* 그림 ② 핵심 패턴 · 틀은 그대로, 한 자리만 갈아 낀다.
   바뀌는 자리에만 초록이 간다 — 초록은 이 덱에서 「고른 것」 이라 뜻이 같다.

   그림이 말해야 하는 건 「틀 하나 × 단어 여럿」 이다. 전에는 자리에서 점선이
   한 뼘 내려오다 허공에서 끊기고, 아래 단어는 회색 알약이라 서로 다른 물건으로
   읽혔다 — 자리는 칸인데 단어는 태그였다. 그래서 둘을 같은 물건으로 맞췄다:
   같은 모서리(10px)의 같은 칸이고, 초록으로 채워진 하나가 지금 끼워진 것,
   흰 칸 셋이 갈아 낄 수 있는 것이다(초록 = 고른 것, 이 덱의 뜻 그대로).
   그리고 점선을 끝까지 잇는다 — 자리에서 내려와 가름대에서 셋으로 갈라져
   단어마다 내려앉으니, 「이 한 자리에 이 셋 중 하나」 가 선 하나로 읽힌다.
   참고: references/curricula/k-village-esther-bunny (틀 + 단어 은행). */
.hy .sp-pat { display: grid; justify-items: center; width: 100%; }
/* 줄을 「앞 · 자리 · 뒤」 세 칸으로 세우고 양 끝을 1fr 로 둔다. 그러면 앞뒤
   글자의 길이가 서로 달라도 갈아 끼우는 자리는 언제나 줄의 한가운데에 선다 —
   그 가운데가 아래 단어 칸의 가운데이기도 하므로, 자리에서 내려온 줄기가
   가운데 단어의 한복판에 정확히 떨어진다. 앞은 오른쪽, 뒤는 왼쪽으로 붙여
   자리를 감싸게 두어, 문장은 여전히 한 덩어리로 읽힌다.
   line-height 를 1.15 로 눌러 두면 줄에서 가장 높은 것이 언제나 그 자리라 —
   줄의 아래 끝 = 자리의 아래 끝이고, 줄기의 출발점이 흔들리지 않는다. */
.hy .pat-line {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 5px;
  width: 100%;
  font-size: 24px; font-weight: 800; line-height: 1.15; letter-spacing: -.03em;
  color: var(--ink); white-space: nowrap;
}
.hy .pat-line > span:first-child { justify-self: end; }
.hy .pat-line > span:last-child { justify-self: start; }
/* 점선 테두리 — 아래로 뻗는 선과 같은 재질이라, 「여기가 갈아 끼우는 칸」 이
   테두리 하나로 읽힌다. 참고서(k-village)가 슬롯을 점선 상자로 두는 것과 같다. */
.hy .pat-slot {
  position: relative; padding: 5px 14px;
  border: 1.5px dashed var(--green-500); border-radius: 10px; background: var(--green-100);
  color: #4e9422; font-weight: 800;
}
/* 자리에서 내려오는 줄기. 12px 아래 가름대를 만나고(.pat-fan 의 margin),
   거기서 멈추지 않고 12px 더 내려가 가운데 단어 위에 닿는다(.pat-fan 의 높이). */
.hy .pat-slot::after {
  content: ""; position: absolute; left: 50%; top: calc(100% + 1.5px); width: 0; height: 38px;
  border-left: 1.5px dashed var(--green-500); opacity: .55;
}
/* 가름대와 눈금 · 자리는 report.js 가 단어 수에서 계산해 인라인으로 얹는다 */
.hy .pat-fan {
  position: relative; width: 100%; max-width: 300px; height: 18px; margin-top: 20px;
  opacity: .55;
}
.hy .pf-bar { position: absolute; top: 0; border-top: 1.5px dashed var(--green-500); }
.hy .pf-t {
  position: absolute; top: 0; bottom: 0; width: 0;
  border-left: 1.5px dashed var(--green-500);
}
/* 눈금 바로 밑에 서야 해서 균등 분할이다 — 칸 너비가 아니라 자리로 줄을 맞춘다 */
.hy .pat-words {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 8px;
  width: 100%; max-width: 300px;
}
/* 칸에 아주 얕은 그림자를 깔아 「집어서 저 자리에 끼우는 물건」 으로 보이게
   하고, 위 가장자리 한가운데에 점 하나를 박는다. 그 점은 위에서 내려온 선이
   닿는 자리다 — 선이 칸의 테두리에서 그냥 끝나면 선과 칸이 남남이지만,
   닿는 자리에 구멍이 하나 있으면 꽂힌 것으로 읽힌다. 글자만 있던 칸에
   물성을 주는 데 이 둘이면 충분하다. */
.hy .pat-words span {
  position: relative;
  display: grid; place-items: center; padding: 10px 5px;
  border: 1.5px solid var(--gray-200); border-radius: 12px; background: #fff;
  box-shadow: 0 1.5px 0 rgba(28,28,28,.05);
  font-size: 17px; font-weight: 800; color: var(--ink); letter-spacing: -.02em;
}
.hy .pat-words span::before {
  content: ""; position: absolute; left: 50%; top: 0;
  width: 6px; height: 6px; margin: -3px 0 0 -3px;
  border-radius: 50%; background: var(--green-500); opacity: .55;
}

/* 그림 ④ 도착 · 다다른 레벨 한 장.
   그림 → 레벨 → 한 줄 → 급수, 가운데로 모아 곧게 내린다. 간격은 하나(8px)로
   같고, 급수만 한 칸(10px) 떨어져 앞의 셋과 묶이지 않는다 — 앞 셋은 「어디에
   닿는가」 한 덩어리고 급수는 그것을 밖에서 환산한 값이라, 사이를 벌려 두면
   읽는 사람이 묶음을 세지 않아도 된다.
   위 「내 레벨」 카드(.lvbig)와 같은 짜임이다 — 큰 레벨, 그 아래 한 줄, 그
   아래 TOPIK. 리포트가 「지금」 을 그렇게 보여 줬으니 「나중」 도 같은 꼴이라야
   두 장이 같은 자의 양 끝으로 읽힌다. */
.hy .sp-goal { display: grid; justify-items: center; gap: 7px; text-align: center; }
.hy .gl-face { width: 74px; height: 74px; object-fit: contain; }
.hy .gl-lv {
  font-size: 26px; font-weight: 900; letter-spacing: -.03em; color: var(--green-500);
  line-height: 1;
}
.hy .gl-line {
  margin: 0; font-size: 17px; font-weight: 800; line-height: 1.35; letter-spacing: -.02em;
  color: var(--ink); word-break: keep-all;
}
.hy .gl-line b { font-weight: 800; color: var(--green-500); }
/* 급수는 앞의 셋에서 한 칸 떨어져, 옅은 알약으로 — 머리의 레슨 수 알약과 같은 결 */
.hy .gl-cert {
  padding: 3px 10px; border-radius: 999px;
  background: var(--green-100); color: #4e9422; font-size: 11.5px; font-weight: 800;
}
/* 아직 목표를 안 고른 칸 — 초록은 「고른 것」 이라 여기에 쓰면 거짓말이 된다 */
.hy .hy-do-e { color: var(--gray-500); }
.hy-goal .hy-head > i { background: var(--gray-400); }

/* 그림 ③ 대사 두 턴 · 덱의 말풍선 규칙 그대로 — 상대는 왼쪽 흰 칸,
   학습자는 오른쪽 연두 채움에 테두리 없음(말하는 사람은 고른 것이 아니다). */
/* 대사 · 레슨의 .turn 부품을 그대로 쓰고 크기만 줄인다(report.js artHTML).
   여기서 새로 정하는 것은 없다 — 말풍선의 꼴도, 꼬리가 어느 모서리에 붙는지도,
   내 말이 연두인 것도 lesson-card.css 의 규칙 그대로다. 리포트에 나온 그림이
   첫 수업 화면과 같아야, 이 카드가 파는 것이 무엇인지 한 번에 붙는다. */
.hy .sp-talk { width: 100%; }
.hy .turn + .turn { margin-top: 12px; }
.hy .turn .who { width: 40px; gap: 3px; }
.hy .turn .avatar { width: 36px; height: 36px; }
.hy .turn .avatar.icon svg { width: 22px; height: 22px; }
.hy .turn .who-name { font-size: 10px; }
/* 말풍선은 내용만큼만 — 레슨에서는 답 쓰는 칸이 들어가서 폭을 다 쓰지만,
   여기 있는 것은 완성된 대사 한 줄이라 꽉 채우면 대화가 아니라 표로 보인다. */
.hy .turn .bubble { flex: 0 1 auto; border-radius: 14px; }
.hy .turn.other .bubble { border-top-left-radius: 4px; }
.hy .turn.me .bubble { border-top-right-radius: 4px; }
/* 레슨에서 내 말풍선이 흰 것은 밑에 붙는 번역 띠가 연두를 맡기 때문이다.
   리포트에는 번역이 없으므로(한국어 한 언어) 연두를 말풍선이 도로 가져온다. */
.hy .turn.me .bubble.me { background: var(--green-100); }
.hy .turn .bubble > .korean { padding: 11px 13px; font-size: 15.5px; line-height: 1.4; }


/* ---------- 항목별 체크 · 레이더 아래, 한 번에 한 항목 ----------
   튜터만 보이는 블록이라 페이지의 다른 카드와 같은 꼴을 쓰지 않는다:
   콘솔과 같은 먹색 점선 테두리가 "이건 학습자 화면에 없다" 는 표시다. */
.axsteps { display: none; }
body.teaching .axsteps {
  display: block; margin-top: 16px; padding: 14px;
  border: 1.5px dashed var(--ink); border-radius: 14px; background: #fbfbf8;
}
/* 다섯 칩이 진행 상황이자 되돌아가는 길이다 */
.axst-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.axst-chips button {
  display: flex; align-items: center; gap: 5px; padding: 5px 11px;
  border: 1.5px solid #ddddd8; border-radius: 999px; background: #fff;
  font-family: inherit; font-size: 11.5px; font-weight: 800; color: #9a9a95;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.axst-chips button.done { border-color: var(--green-500); background: var(--green-100); color: var(--ink); }
.axst-chips button.done::before { content: "✓"; color: var(--green-500); }
/* 지금 보고 있는 칸은 먹선으로만 — 초록은 이미 「끝난 것」 을 뜻한다 */
.axst-chips button.now { border-color: var(--ink); color: var(--ink); }

.axq { display: none; margin-top: 14px; }
.axq.now { display: block; }
.axq-h { margin: 0 0 9px; font-size: 14px; font-weight: 900; color: var(--ink); }
.axq-h small { margin-left: 7px; font-size: 11.5px; font-weight: 700; color: #8a8a85; }

/* ---------- 보기 한 줄 ----------
   종합 레벨과 다섯 항목이 같은 컨트롤을 쓴다: 네 칸 막대 + 문장 하나.
   막대가 있어서 문장을 다 읽기 전에 어느 쪽 끝인지가 먼저 보이고, 맨 아래
   칸은 하나도 차지 않는다 — 다섯 칸을 네 개의 막대로 세는 방법이다. */
.lvpick, .axq-opts { display: grid; gap: 7px; }
.rung-row {
  display: flex; align-items: center; gap: 12px; width: 100%; padding: 11px 13px;
  border: 1px solid var(--gray-200); border-radius: 11px; background: #fff;
  font-family: inherit; font-size: 13px; font-weight: 600; color: #55554f;
  line-height: 1.45; text-align: left; word-break: keep-all;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background .12s, border-color .12s;
}
.rung-row.on { border: 1.5px solid var(--green-500); background: var(--green-100); color: var(--ink); font-weight: 700; }
.rung-row:active { transform: scale(.995); }
.rung { flex: none; display: flex; align-items: flex-end; gap: 3px; height: 20px; }
.rung i { width: 4px; border-radius: 2px; background: #e2e2dc; }
.rung i:nth-child(1) { height: 7px; }
.rung i:nth-child(2) { height: 11px; }
.rung i:nth-child(3) { height: 15px; }
.rung i:nth-child(4) { height: 20px; }
.rung i.on { background: #1c1c1c; }
.rung-row.on .rung i.on { background: var(--green-500); }
.rung-row.on .rung i { background: rgba(28,28,28,.14); }
.rung-row.on .rung i.on { background: var(--green-500); }
.rung-t { flex: 1 1 auto; min-width: 0; }
/* 「추천」 은 상태가 아니라 제안이라 초록을 쓰지 않는다 — 회색 칩 하나로,
   고르면 사라진다. */
.rung-row.sug { border-color: #d5d5cf; }
.rung-row.sug::after {
  content: "추천"; flex: none; padding: 2px 7px; border-radius: 999px;
  background: var(--gray-100); color: var(--gray-500); font-size: 10.5px; font-weight: 800;
}
.rung-row.on::after { content: none; }

.axq-done { display: none; margin: 14px 0 0; font-size: 12px; font-weight: 700; color: #8a8a85; }
.axsteps.all .axq-done { display: block; }

/* ---------- 레벨 체크 · 초록 카드 안, 튜터만 ----------
   항목별 체크와 같은 꼴이다: 먹색 점선이 "학습자 화면에는 없다" 는 표시고,
   고르는 자리가 그 값을 보여 주는 카드 안에 있다. */
.lvcheck { display: none; }
body.teaching .lvcheck {
  display: block; margin-top: 16px; padding: 14px;
  border: 1.5px dashed var(--ink); border-radius: 14px; background: #fbfbf8;
}
.lvcheck-h { display: block; font-size: 14px; font-weight: 900; color: var(--ink); }
.lvcheck-h small { margin-left: 7px; font-size: 11px; font-weight: 800; color: #8a8a85; }
.lvcheck-q { margin: 4px 0 0; font-size: 12.5px; font-weight: 700; color: #55554f; }
.lvcheck .lvpick { margin-top: 11px; }
/* 고른 뒤에는 고른 줄만 남는다. 나머지는 지우지 않고 감추기만 한다 —
   보드가 원격 선택을 합성 클릭으로 적용하므로 옵션은 DOM 에 있어야 한다. */
.lvcheck.folded .rung-row:not(.on) { display: none; }
.lvcheck.folded .lvcheck-q { display: none; }
.lvcheck-redo {
  display: none; width: 100%; margin-top: 8px; padding: 8px;
  border: 1px solid var(--gray-200); border-radius: 10px; background: #fff;
  font-family: inherit; font-size: 12px; font-weight: 800; color: #6f6f6a;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.lvcheck.folded .lvcheck-redo { display: block; }

/* ================================================================
   상담 · Figma「❤️ PODO JP」> 상담 및 리포트 v2
   리포트 뒤에 오는 판매 파트. 새로 생긴 조각만 여기 있고, 이미 있는
   것(.usp · .ptable · .stg · .rail)은 그대로 쓴다.
   ================================================================ */
/* 판매 파트의 첫 줄 — 여기서는 파란 튜터 스크립트 대신 라임 띠를 쓴다.
   이 열 장은 학습 화면이 아니라 안내 화면이고, 파란 상자는 "튜터가 지금
   소리 내어 읽는 줄" 하나에만 걸어 둔 색이라 여기까지 끌고 오지 않는다. */
.section-subtitle.sell {
  padding: 13px 16px; border: 1.5px solid var(--ink); border-radius: 14px;
  background: var(--lime); font-size: 15px; font-weight: 900; letter-spacing: -.028em;
}

/* 회사 소개 · 앱 리포트 예고처럼 "한 줄 배지 + 큰 제목 + 설명" 꼴의 상자 */
.fact { margin-top: 14px; padding: 15px; border: 1.5px solid #cdea97; border-radius: 18px; }
.badges { display: flex; flex-wrap: wrap; gap: 5px; }
.fact.fill { border-color: #cdea97; background: #f5fde9; }
.badge-dark {
  display: inline-block; padding: 3px 10px; border-radius: 999px;
  background: var(--ink); color: var(--lime); font-size: 9.5px; font-weight: 900;
}
.fact-t { margin: 6px 0 0; font-size: 20px; font-weight: 900; letter-spacing: -.04em; }
.fact.fill .fact-t { font-size: 17px; letter-spacing: -.035em; }
.fact-s { margin: 6px 0 0; color: #4a5142; font-size: 11.5px; font-weight: 500; line-height: 1.65; word-break: keep-all; }

.sub-h { margin: 14px 0 0; font-size: 16px; font-weight: 900; letter-spacing: -.03em; }
/* 상자 안에서 소제목으로 쓸 때는 상자의 안쪽 여백이 이미 자리를 냈다 */
.fact > .sub-h:first-child { margin-top: 0; }
.fact > .sub-h + * { margin-top: 10px; }
.fact-s.lg { font-size: 13px; line-height: 1.62; }

/* 숫자 넉 장 — 하나가 한 가지 사실이라, 상자마다 큰 수 하나만 든다 */
.statgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 14px; }
.stat { padding: 13px 8px 14px 12px; border-radius: 14px; background: #f5fde9; }
.stat .n { display: block; color: #4a8b24; font-size: 21px; font-weight: 900; letter-spacing: -.045em; line-height: 1.3; }
.stat .t { display: block; margin-top: 1px; color: #4a5142; font-size: 11.5px; font-weight: 700; }
/* 숫자가 어디서 나온 값인지 — 큰 수 밑에 아주 작게. 안 읽어도 되는 줄이다 */
.stat .c { display: block; margin-top: 5px; color: #8a9180; font-size: 9.5px; font-weight: 500; line-height: 1.4; word-break: keep-all; }

/* 후기 — 사진이 먼저 오고 제목은 그 아래. 두 칸 격자.
   일본어 · 영어 두 묶음이라 묶음마다 제목이 하나씩 붙는다. */
.rev-h { margin: 16px 0 0; font-size: 13.5px; font-weight: 900; letter-spacing: -.03em; }
.revgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 9px; margin-top: 9px; align-items: start; }
.rev img { display: block; width: 100%; height: 113px; border: 1px solid #e7eae0; border-radius: 10px; object-fit: cover; }
.rev .t { display: block; margin-top: 7px; font-size: 12.5px; font-weight: 900; letter-spacing: -.028em; line-height: 1.44; word-break: keep-all; }
/* 후기에서 눈이 먼저 닿아야 하는 조각 하나 — 빨강은 이 덱에서 기한과 여기뿐이다 */
.rev .t b { color: #d51f3c; font-weight: 900; }
.rev .w { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; margin-top: 7px; color: #8a9180; font-size: 10.5px; font-weight: 700; }
.rev .w i {
  padding: 2px 8px; border-radius: 999px; background: #eafdc9; color: #4a8b24;
  font-size: 10px; font-style: normal; font-weight: 900; white-space: nowrap;
}

.fineprint { margin: 14px 0 0; color: #8a9180; font-size: 10.5px; font-weight: 500; line-height: 1.62; word-break: keep-all; }

/* 다음 장으로 넘기는 한 줄 — 페이지의 마지막에만 온다 */
.arrowline {
  display: flex; gap: 8px; margin-top: 14px; padding: 10px 13px; border-radius: 12px;
  background: #f5fde9; color: var(--green-500); font-size: 12.5px; font-weight: 900;
  letter-spacing: -.02em; line-height: 1.52; word-break: keep-all;
}
.arrowline::before { content: "→"; flex: none; }

/* 본문 아래 붙는 회색 참고 상자. 티칭 노트(.tutor-note)와는 다르다 —
   이건 학습자도 읽는다. */
.smallnote { margin-top: 14px; padding: 13px 15px; border-radius: 14px; background: #f5f6f2; }
.smallnote p { margin: 0; color: #4a5142; font-size: 11.5px; font-weight: 500; line-height: 1.57; word-break: keep-all; }
.smallnote p + p { margin-top: 6px; }
.smallnote b { color: var(--ink); font-weight: 900; }

/* 수업의 네 가지 — 큰 말 · 이름 · 한 줄 */
.featgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 14px; }
.feat { padding: 14px 12px 16px 14px; border: 1.5px solid #cdea97; border-radius: 16px; }
.feat .n { display: block; font-size: 20px; font-weight: 900; letter-spacing: -.04em; }
.feat .t { display: block; font-size: 12.5px; font-weight: 900; letter-spacing: -.02em; }
.feat .s { display: block; margin-top: 5px; color: #8a9180; font-size: 11px; font-weight: 500; line-height: 1.55; word-break: keep-all; }
/* v2 의 제목은 「25분」 이 아니라 「비대면 25분」 이라 두 칸 폭에 들어가지 않는다 */
.feat .n { font-size: 17px; letter-spacing: -.045em; line-height: 1.25; }
.feat .t { margin-top: 3px; line-height: 1.35; word-break: keep-all; }

/* 예약·취소 · 이 덱의 유일한 먹색 상자다. 밝은 카드가 이어지는 흐름에서
   한 번 끊어 주는 자리라, 여기 말고는 쓰지 않는다. */
.sched { margin-top: 14px; padding: 20px 18px; border-radius: 20px; background: var(--ink); }
.sched .k { display: block; color: var(--lime); font-size: 12px; font-weight: 900; }
.sched .big { margin: 0; color: #edf3e2; font-size: 26px; font-weight: 900; letter-spacing: -.042em; line-height: 1.31; }
.sched .big em { font-style: normal; color: var(--lime); }
.sched .s { margin: 0; color: #a3ad94; font-size: 12px; font-weight: 500; line-height: 1.58; word-break: keep-all; }
.sched-mini { display: flex; gap: 7px; margin-top: 16px; }
.sched-mini div { flex: 1 1 0; min-width: 0; padding: 10px 4px; border-radius: 12px; background: rgba(255,255,255,.08); text-align: center; }
.sched-mini .k2 { display: block; color: #98a28a; font-size: 10px; font-weight: 700; }
.sched-mini .v2 { display: block; color: #edf3e2; font-size: 12.5px; font-weight: 900; letter-spacing: -.028em; }

/* ---------- 튜터 ---------- */
.tstat { display: flex; gap: 8px; margin-top: 14px; text-align: center; }
.tstat div { flex: 1 1 0; min-width: 0; padding: 12px 6px; border: 1.5px solid #cdea97; border-radius: 14px; }
.tstat .n { display: block; color: var(--green-500); font-size: 20px; font-weight: 900; letter-spacing: -.04em; }
.tstat .t { display: block; color: #4a5142; font-size: 11px; font-weight: 700; }

.week { display: flex; gap: 5px; }
.week div { flex: 1 1 0; min-width: 0; text-align: center; }
.week span { display: block; margin-bottom: 5px; color: #8a9180; font-size: 10.5px; font-weight: 900; }
.week .sun { color: #d51f3c; }
.week img { display: block; width: 100%; aspect-ratio: 1; border: 1.5px solid #cdea97; border-radius: 999px; object-fit: cover; }

.tgroup + .tgroup { margin-top: 16px; }
.tg-head { display: flex; align-items: center; gap: 9px; margin-bottom: 10px; }
.tg-tag { flex: none; padding: 5px 13px; border-radius: 999px; font-size: 12.5px; font-weight: 900; letter-spacing: -.02em; }
.tg-head p { margin: 0; color: #8a9180; font-size: 11.5px; font-weight: 500; line-height: 1.48; word-break: keep-all; }
.tutgrid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 9px; }
.tcard img { display: block; width: 100%; aspect-ratio: 1; border: 1.5px solid; border-radius: 14px; object-fit: cover; }
.tcard .nm { display: block; margin-top: 6px; font-size: 14px; font-weight: 900; letter-spacing: -.03em; }
.tcard .nm small { color: #8a9180; font-size: 10.5px; font-weight: 700; }
.tcard .tags { display: flex; flex-wrap: wrap; gap: 3px; margin-top: 6px; }
.tcard .tags span { padding: 2px 7px; border-radius: 999px; color: #2a2e22; font-size: 9.5px; font-weight: 900; }
/* 관심사마다 색이 하나 — 태그·사진 테두리·칩 바탕이 같은 계열로 묶인다.
   이 색은 상태가 아니라 분류다(초록/라임은 여기 쓰지 않는다). */
.tgroup.g1 .tg-tag { background: #7ea3ff; }
.tgroup.g1 .tcard img { border-color: #7ea3ff; }
.tgroup.g1 .tcard .tags span { background: #edf2ff; }
.tgroup.g2 .tg-tag { background: #fb97ff; }
.tgroup.g2 .tcard img { border-color: #fb97ff; }
.tgroup.g2 .tcard .tags span { background: #fdeffe; }
.tgroup.g3 .tg-tag { background: #c0ff6d; }
.tgroup.g3 .tcard img { border-color: #c0ff6d; }
.tgroup.g3 .tcard .tags span { background: #f2fee0; }
.tgroup.g4 .tg-tag { background: #8ec743; }
.tgroup.g4 .tcard img { border-color: #8ec743; }
.tgroup.g4 .tcard .tags span { background: #f0f8e4; }

/* ---------- 수강료 ----------
   빨강은 이 덱에서 여기에만 쓴다: 기한이 있는 것 하나. */
.deadline { margin-top: 14px; border: 2px solid #d51f3c; border-radius: 18px; overflow: hidden; }
.dl-bar { display: flex; align-items: center; justify-content: space-between; padding: 9px 15px; background: #d51f3c; }
.dl-bar .t { color: #fff; font-size: 13px; font-weight: 900; letter-spacing: -.02em; }
.dl-bar .d { padding: 2px 8px; border-radius: 999px; background: rgba(255,255,255,.24); color: #fff; font-size: 10.5px; font-weight: 900; }
.dl-body { padding: 14px 15px 15px; background: #ffeff1; }
.dl-big { margin: 0; color: #d51f3c; font-size: 22px; font-weight: 900; letter-spacing: -.041em; line-height: 1.27; }
.dl-s { margin: 5px 0 0; color: #4a5142; font-size: 12px; font-weight: 500; line-height: 1.58; word-break: keep-all; }
.dl-days { display: flex; gap: 5px; margin-top: 12px; text-align: center; }
.dl-days div { flex: 1 1 0; min-width: 0; padding: 7px 2px; border: 1px solid #f6c3cb; border-radius: 10px; background: #fff; }
.dl-days .d { display: block; font-size: 12.5px; font-weight: 900; }
.dl-days .w { display: block; color: #4a5142; font-size: 11px; font-weight: 700; }
.dl-days .now { border-color: var(--ink); background: var(--ink); }
.dl-days .end { border-color: #d51f3c; background: #d51f3c; }
.dl-days .now .d, .dl-days .end .d { color: #fff; }
.dl-days .now .w, .dl-days .end .w { color: #d9dfce; }

.plan2 { margin-top: 14px; border: 2px solid var(--ink); border-radius: 20px; overflow: hidden; }
.plan2-h { padding: 15px 16px 14px; border-bottom: 1.5px solid var(--ink); background: var(--lime); }
.plan2-h .badge-dark { font-size: 10.5px; }
.plan2-h .t { display: block; margin-top: 6px; font-size: 21px; font-weight: 900; letter-spacing: -.045em; }
.plan2-h .s { display: block; margin-top: 6px; color: #3a4230; font-size: 12px; font-weight: 700; }
.plan2-rows { padding: 4px 16px 0; }
.pr { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 11px 0; border-bottom: 1px solid #e7eae0; }
.pr .k { display: flex; align-items: center; gap: 7px; font-size: 14px; font-weight: 700; letter-spacing: -.018em; }
.pr .v { font-size: 14px; font-weight: 900; letter-spacing: -.021em; }
.pr .cut { color: var(--green-500); }
.pr .tagr { padding: 2px 7px; border-radius: 999px; background: #d51f3c; color: #fff; font-size: 10px; font-weight: 900; }
.pr.total { padding: 14px 0 4px; border-bottom: 0; border-top: 1.5px solid var(--ink); }
.pr.total .k { font-size: 15px; font-weight: 900; }
.pr.total .v { font-size: 32px; letter-spacing: -.05em; }
.perlesson {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin: 12px 16px 14px; padding: 12px 14px; border-radius: 14px; background: #eafdc9;
}
.perlesson .l { display: flex; align-items: baseline; gap: 5px; font-size: 15px; font-weight: 900; letter-spacing: -.03em; }
.perlesson .l b { color: #4a8b24; font-size: 24px; font-weight: 900; letter-spacing: -.05em; }
.perlesson .r { color: #8a9180; font-size: 11.5px; font-weight: 700; }
.plan2-f { padding: 11px 16px 13px; border-top: 1px solid #e7eae0; background: #f5f6f2; color: #4a5142; font-size: 11.5px; font-weight: 700; line-height: 1.57; word-break: keep-all; }
.plan2-f b { color: var(--ink); font-weight: 900; }
.plan2-f p { margin: 0; }
.plan2-f p + p { margin-top: 5px; color: #8a9180; font-size: 10.5px; font-weight: 500; }
.plan2-f .auto { padding-bottom: 8px; border-bottom: 1px solid #e2e4dd; }

/* 정가 → 반값. 값이 한 번에 두 개 나오면 어느 쪽을 내는지 헷갈려서,
   떨어지는 순서를 화살표 · 빨간 띠 · 라임 상자로 눈에 보이게 세워 둔다. */
.pdrop { margin: 2px 0 0; color: #8a9180; font-size: 15px; font-weight: 900; text-align: center; }
.pcta {
  display: block; width: fit-content; margin: 4px auto 0; padding: 6px 15px; border-radius: 999px;
  background: #d51f3c; color: #fff; font-size: 12.5px; font-weight: 900; letter-spacing: -.025em;
}
.pbox { margin: 11px 16px 0; padding: 14px 15px 15px; border-radius: 16px; background: var(--lime); }
.pbox-h { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.pbox-h .k { font-size: 15px; font-weight: 900; letter-spacing: -.033em; }
.pbox-h .off { padding: 3px 9px; border-radius: 999px; background: #d51f3c; color: #fff; font-size: 10.5px; font-weight: 900; }
.pbox-n { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px; margin: 12px 0 0; }
.pbox-n s { color: #56613f; font-size: 14px; font-weight: 700; }
.pbox-n i { color: #56613f; font-size: 13px; font-style: normal; font-weight: 900; }
.pbox-n b { font-size: 34px; font-weight: 900; letter-spacing: -.052em; }
.pbox-n small { color: #3a4230; font-size: 11px; font-weight: 700; }
.pbox-s { margin: 6px 0 0; color: #3a4230; font-size: 11.5px; font-weight: 700; }

.incl { margin-top: 14px; padding: 15px; border: 1.5px solid #cdea97; border-radius: 18px; }
.incl h4 { margin: 0 0 11px; font-size: 15px; font-weight: 900; letter-spacing: -.033em; }
.incl .il { display: flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 700; letter-spacing: -.023em; line-height: 1.46; word-break: keep-all; }
.incl .il + .il { margin-top: 11px; }
.incl .il::before { content: "✓"; flex: none; color: var(--green-500); font-weight: 900; }
.incl .il b { font-weight: 900; }
.incl .tagl { flex: none; padding: 2px 8px; border-radius: 999px; background: #eafdc9; color: #4a8b24; font-size: 9.5px; font-weight: 900; }
.incl .tagr { flex: none; padding: 2px 8px; border-radius: 999px; background: #d51f3c; color: #fff; font-size: 9.5px; font-weight: 900; }
.incl .tail { margin-left: auto; padding: 2px 8px; border-radius: 999px; background: #eafdc9; color: #4a8b24; font-size: 10px; font-weight: 900; white-space: nowrap; }

.versus { display: flex; gap: 8px; margin-top: 14px; }
.versus div { flex: 1 1 0; min-width: 0; padding: 12px 13px; border: 1.5px solid #e7eae0; border-radius: 14px; }
.versus div.on { border-color: var(--ink); background: #f5fde9; }
.versus .k { display: block; color: #4a5142; font-size: 11.5px; font-weight: 700; letter-spacing: -.021em; }
.versus .v { display: block; margin-top: 2px; font-size: 22px; font-weight: 900; letter-spacing: -.05em; }
.versus div.on .v { color: #4a8b24; }
.versus .s { display: block; margin-top: 2px; color: #8a9180; font-size: 10.5px; font-weight: 500; }

.switchcard { margin-top: 14px; border: 1.5px solid #cdea97; border-radius: 18px; overflow: hidden; }
.switchcard > .top { padding: 13px 15px; background: #f5fde9; }
.switchcard > .top .t { display: block; font-size: 15px; font-weight: 900; letter-spacing: -.033em; }
.switchcard > .top .s { display: block; margin-top: 3px; color: #4a5142; font-size: 11.5px; font-weight: 500; }
.switchcard > .body { padding: 13px 15px 14px; }
.swsteps { display: flex; align-items: center; gap: 5px; text-align: center; }
.swsteps div { flex: 1 1 0; min-width: 0; padding: 9px 6px; border: 1px solid #e7eae0; border-radius: 12px; }
.swsteps div.a { background: #f5fde9; }
.swsteps div.b { border: 1.5px solid var(--ink); background: #eafdc9; }
.swsteps .k { display: block; color: #8a9180; font-size: 10px; font-weight: 700; }
.swsteps .v { display: block; font-size: 12px; font-weight: 900; letter-spacing: -.025em; }
.swsteps i { flex: none; color: #cdea97; font-size: 14px; font-style: normal; font-weight: 900; }
.swrow { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 9px 0; border-bottom: 1px solid #e7eae0; }
.swrow.best { margin-top: 0; padding: 9px 12px; border-bottom: 0; border-radius: 10px; background: #eafdc9; }
.swrow .k { display: flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 900; letter-spacing: -.018em; }
.swrow .save { padding: 2px 8px; border-radius: 999px; background: #fff; color: #4a8b24; font-size: 10.5px; font-weight: 900; }
.swrow .v { font-size: 13.5px; font-weight: 900; letter-spacing: -.022em; }
.swrow .v small { margin-left: 1px; color: #8a9180; font-size: 11px; font-weight: 700; }
.swnotes { margin-top: 11px; }
.swnotes .sn { display: flex; gap: 7px; color: #4a5142; font-size: 12px; font-weight: 500; line-height: 1.58; word-break: keep-all; }
.swnotes .sn + .sn { margin-top: 7px; }
.swnotes .sn::before { content: "✓"; flex: none; color: var(--green-500); font-weight: 900; }
.swnotes b { color: var(--ink); font-weight: 900; }
.swcall { display: flex; gap: 8px; margin-top: 11px; padding: 11px 13px; border-radius: 12px; background: #f5f6f2; color: #4a5142; font-size: 12px; font-weight: 700; line-height: 1.58; word-break: keep-all; }
.swcall::before { content: "☎"; flex: none; }
.swcall b { color: var(--ink); font-weight: 900; }

/* ---------- FAQ · 주제로 한 번 나눈다 ---------- */
.faq-div { display: flex; align-items: center; gap: 8px; margin-top: 14px; }
.faq-div span { color: var(--green-500); font-size: 11.5px; font-weight: 900; letter-spacing: -.022em; }
.faq-div i { flex: none; width: 100px; height: 1px; background: #cdea97; }
.qa2 { margin-top: 9px; padding: 12px 14px; border: 1.5px solid #cdea97; border-radius: 14px; }
.qa2.hi { border-color: var(--ink); background: #f5fde9; }
.qa2 .q { display: block; font-size: 13.5px; font-weight: 900; letter-spacing: -.03em; line-height: 1.48; word-break: keep-all; }
.qa2 .q::before { content: "Q. "; color: var(--green-500); }
.qa2 .a { display: block; margin-top: 4px; color: #4a5142; font-size: 12.5px; font-weight: 500; line-height: 1.6; word-break: keep-all; }
.qa2 .a + .a { margin-top: 6px; }
/* 목록의 끝 — 여기 없는 것은 사람에게 물어보면 된다는 한 줄 */
.faq-end {
  margin-top: 14px; padding: 14px 15px; border: 1.5px solid var(--ink); border-radius: 14px;
  background: var(--lime); font-size: 13px; font-weight: 900; letter-spacing: -.028em;
  line-height: 1.55; word-break: keep-all;
}

/* 전환 안내가 둘(기간 · 언어)이라, 「고객센터에 말씀만」 은 두 상자 중
   하나에 붙지 않고 페이지 바닥에 한 번만 온다 */
.swcall.out { margin-top: 14px; }
.switchcard + .switchcard { margin-top: 14px; }

/* 전체 요금표 — 밀고 있는 한 칸만 라임이고, 나머지 한국어 열은 옅게 */
.ptable td.hi.rec { background: var(--lime); }
.ptable td.hi.rec::after { content: "추천"; margin-left: 5px; font-size: 10.5px; font-weight: 900; }

/* .section:has(> .ptable) 규칙은 「표 한 장이 페이지의 전부」 인 화면을 위해
   표 위로 빈 칸을 몰아 준다(.ptable 에 margin-top:auto). 이 장은 표 뒤에
   설명이 세 덩이 더 붙는 안내 화면이라, 그 규칙이 배너와 표 사이에 빈 칸만
   남긴다. Figma 도 위에서부터 쌓아 두었으니 여기서만 되돌린다.

   .pg-on 을 함께 걸어 두는 것이 중요하다. id 만으로 쓰면 특정도(1,0,0)가
   페이지를 감추는 규칙(.phone.paged > *)을 이겨서, 이 장만 페이저가 끌 수
   없게 된다 — 어느 장을 보든 그 밑에 요금표가 따라붙는다. */
.phone.paged > #p-price-all.pg-on { display: block; }
#p-price-all > .ptable { margin-top: 22px; }

/* ---------- 커리큘럼 · v2 에서 늘어난 조각 ----------
   2단계가 2-1(패턴) · 2-2(말투)로 갈라져서, 동그란 번호로는 담기지 않는다 */
.stg-n.wide { width: auto; height: 22px; padding: 0 9px; border-radius: 999px; font-size: 12px; }

/* 같은 문장을 상대에 따라 갈아 끼우는 세 줄. 고르는 자리가 아니라 보여
   주는 자리라, 초록은 「반말」 한 줄에만 — 이 장에서 새로 배우는 것이다. */
.tone { display: flex; align-items: center; gap: 9px; margin-top: 7px; padding: 9px 11px; border-radius: 10px; background: #fff; }
.tone .tn {
  flex: none; padding: 3px 9px; border-radius: 999px; background: var(--gray-100);
  color: #575753; font-size: 10.5px; font-weight: 900;
}
.tone.on .tn { background: var(--lime); color: #1c1c1c; }
.tone .tk { flex: 1 1 auto; min-width: 0; font-size: 13.5px; font-weight: 900; letter-spacing: -.025em; }
.tone .tw { flex: none; color: #8a9180; font-size: 10.5px; font-weight: 700; white-space: nowrap; }

/* 물음표로 시작하는 줄 — 패턴 예문(.ex)과 같은 껍데기를 쓰되, 왼쪽 배지가
   과 번호가 아니라 「이런 것도 다룬다」 는 표시다 */
.ex-p.lime { background: var(--lime); color: #1c1c1c; }

/* 프리토킹 · 말풍선 고리 그림 한 장 + 오른쪽에 한 문단 */
.free-hero img { width: 104px; height: auto; }
.free-hero p { font-size: 13.5px; letter-spacing: -.03em; }
.tg.more { font-size: 11px; line-height: 1.4; }
.qcard { font-size: 13px; line-height: 1.5; }

/* 엔딩 · 앱에서 리포트를 여는 안내가 마지막 상자다 */
.end-report { margin-top: 20px; padding: 14px 15px; border: 1.5px solid #cdea97; border-radius: 14px; background: #f5fde9; text-align: center; }
.end-report .badge-dark { font-size: 9.5px; }
.end-report .t { display: block; margin-top: 7px; font-size: 16px; font-weight: 900; letter-spacing: -.037em; }
.end-report .s { display: block; margin-top: 7px; color: #4a5142; font-size: 11.5px; font-weight: 500; line-height: 1.65; }


/* ============================================================
   상담 리포트 v5 (`trial/reports/`)
   ------------------------------------------------------------
   풀덱의 리포트(위 FULL TRIAL 절)보다 나중에 그린 설계다 —
   ⓪ 튜터 콘솔 · ① 지금 레벨 카드 · ② 항목별 카드 · ③ 도착 예측.
   두 세대가 공존하는 중이라 클래스 이름을 갈라 두었다(lvc- / axc- /
   rep-all vs lvcheck / axsteps). 어느 쪽으로 합칠지는 아직 정하지 않았다.
   ============================================================ */
/* ================================================================
   NEEDS + REPORT · trial-1 에서 잘라낸 상담 파트
   앞쪽(니즈 3장 + 레벨 체크)은 trial-1-hangul.html 그대로. 뒤쪽 리포트
   3장은 _experiments/trial-report-rebuild.html v5 의 설계를 적용했다.

   리포트는 학습자가 직접 읽는 화면이라 단일 언어다 — 초록 튜터 스크립트
   박스도, 일본어 병기도 없다(지금은 한국어, 실제 출시는 일본어).
   흐름: ① 지금 레벨 → ② 항목별 진단 → ③ 도착 예측.

   클래스 이름에 lvc- 접두사를 쓴 이유: trial.css 가 .opt-row .lv-badge 를
   이미 쓰고 있어서, 목표 선택지의 번호 배지와 충돌하지 않게 갈라 둔다.
   ================================================================ */

/* ---------- 목표 선택지 ----------
   이유 하나가 묶음 하나, 그 안의 세 줄이 그 이유로 갈 수 있는 거리다.
   묶음 제목은 앞 장의 학습 동기를 글자 그대로 되받고, 오른쪽 배지는 그
   줄이 도착하는 레벨 — 처음 보는 사람에게 "Lv.7" 은 아무 크기도 아니라서
   /10 을 붙여 둔다. */
/* 카드 하나 = 도착 레벨 하나. 제목이 거리를 말하고, 속의 줄들이 그 거리가
   이 사람에게 무슨 뜻인지를 이유별로 말한다 — 고를 것은 넷, 읽을 것은
   자기가 고른 이유의 수만큼. */
/* 학습 동기 줄의 그림 — 이모지 자리를 그대로 대신한다 */
.opt-row .r-ico { flex: none; width: 30px; height: 30px; object-fit: contain; }

.goal-list { display: grid; gap: 12px; }
/* 껍데기는 .opt-row 와 같은 값을 쓴다 — 앞뒤 장(학습 동기·학습 페이스)이
   그 컴포넌트라, 여기만 다른 꼴이면 같은 질문이 세 번 다른 화면으로 온다.
   안쪽(막대 배지, 이유별 줄)만 이 페이지의 것이다. */
.glc {
  display: block; width: 100%; padding: 15px 16px 14px; text-align: left;
  border: 1px solid var(--gray-200); border-radius: 13px; background: #fff;
  font-family: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform .09s, background .12s, box-shadow .12s;
}
.glc:active { transform: scale(.99); }
.glc.on { background: var(--green-100); border: 1.5px solid var(--green-500); box-shadow: none; }
.glc-h { display: flex; align-items: center; gap: 13px; }
/* 도착 지점은 숫자가 아니라 막대로 — 「Lv.7」 은 처음 보는 사람에게 크기가
   없는 말이고, 넉 칸 중 몇 칸인지는 세지 않아도 보인다. */
.glc-b { flex: none; display: flex; align-items: flex-end; gap: 3.5px; height: 26px; padding: 0 2px; }
.glc-b i { width: 5px; border-radius: 3px; background: #dcdcd6; }
.glc-b i:nth-child(1) { height: 9px; }
.glc-b i:nth-child(2) { height: 15px; }
.glc-b i:nth-child(3) { height: 21px; }
.glc-b i:nth-child(4) { height: 26px; }
.glc-b i.on { background: #1c1c1c; }
/* 고르면 채운 칸이 초록으로 — .opt-row 의 배지가 하는 것과 같다 */
.glc.on .glc-b i.on { background: var(--green-500); }
.glc-n { font-size: 15.5px; font-weight: 900; color: #1c1c1c; line-height: 1.3; }
.glc-n small { display: block; margin-top: 2px; font-size: 11.5px; font-weight: 700; color: #a5a5a0; }
.glc.on .glc-n small { color: var(--gray-500); }
/* 이유별 「할 수 있게 되는 일」 — 고른 이유의 줄만 남는다.
   구분선은 실선이다: 점선 회색은 이 시스템에서 "여기 쓰세요" 하나만 뜻한다. */
.glc-l { display: grid; gap: 7px; margin-top: 13px; padding-top: 12px; border-top: 1px solid var(--gray-200); }
.glc.on .glc-l { border-top-color: var(--green-500); }
.glc-i { display: grid; grid-template-columns: 22px 1fr; column-gap: 9px; align-items: center; }
.glc-i.hide, .glc-e.hide { display: none; }
/* 이유 그림은 PODO 앱 온보딩과 같은 것을 쓴다 — 앱에서 고른 이유와
   상담에서 고른 이유가 같은 그림이면, 설명 없이 같은 질문으로 읽힌다. */
.glc-ico { width: 22px; height: 22px; object-fit: contain; }
.glc-i b { font-size: 13.5px; font-weight: 800; color: #1c1c1c; line-height: 1.4; word-break: keep-all; }
.glc-i em {
  grid-column: 2; margin-top: 1px; font-style: normal; font-size: 11.5px;
  font-weight: 600; color: #8a8a85; line-height: 1.4; word-break: keep-all;
}
.glc.on .glc-i em { color: var(--gray-500); }
.glc-e { font-size: 12px; font-weight: 600; color: #a5a5a0; line-height: 1.45; }

/* 리포트 페이지는 튜터 스크립트 대신 담담한 부제를 쓴다 */
.rv-sub { margin: 8px 0 24px; font-size: 14px; font-weight: 500; color: #8a8a85; line-height: 1.55; word-break: keep-all; }
/* trial.css 가 700 으로 세워 둔 본문을 낮춘다 — 굵기는 제목·수치에만 */
.rep-page .rep-why { font-weight: 500; color: #6f6f6a; }
.rep-page .rf .k { font-weight: 500; }

/* ---------- ① 지금 레벨 — 리포트를 여는 초록 카드 ----------
   헤더(키커·제목·부제) 없이 카드로 리포트를 연다.
   읽는 순서: 마스코트+레벨 → 눈금(어디쯤) → 문단(무엇을) →
   근거 3줄(항목별로 어디가 되고 어디가 아직인지) → TOPIK(공인 기준). */
.lvc { background: #f2fce0; border-radius: 15px; padding: 32px 26px; }
.lvc-top { display: flex; align-items: center; gap: 18px; }
.lvc-top img { flex: none; width: 100px; height: auto; }
.lvc-badge { display: inline-block; padding: 5px 13px; border-radius: 999px; background: #1c1c1c; color: #b5fd4c; font-size: 13px; font-weight: 900; letter-spacing: .01em; }
.lvc-line { margin: 9px 0 0; font-size: 19px; font-weight: 900; color: #1c1c1c; line-height: 1.35; word-break: keep-all; }
.lvc-line b { color: #4f9a1e; font-weight: 900; }

/* 레벨 눈금 — 총 10단계 중 지금 자리.
   한 칸 = 한 레벨이라 단계 수가 세어지고, 칸·숫자 모두 flex:1 이라
   간격이 저절로 균등해진다. */
.lad { margin: 22px 0 0; }
.lad-segs { display: flex; gap: 3px; }
.lad-segs span { flex: 1 1 0; height: 8px; border-radius: 3px; background: #ddeec2; }
.lad-segs span.on { background: #6abe36; }
.lad-nums { display: flex; gap: 3px; margin-top: 9px; }
.lad-nums span { flex: 1 1 0; text-align: center; font-size: 10.5px; font-weight: 700; color: #a8bd8c; }
.lad-nums span.on { font-size: 11.5px; font-weight: 900; color: #1c1c1c; }

.lvc-panel { margin: 16px 0 0; padding: 17px 18px 15px; border-radius: 14px; background: #fff; }
.lvc-diag { margin: 0; font-size: 14px; font-weight: 500; line-height: 1.72; color: #55554f; word-break: keep-all; }
.lvc-diag b { font-weight: 800; color: #1c1c1c; }

/* 오늘 수업 근거 3줄 (✓ 된 것 · · 아직인 것) */
.lvc-ev { margin: 15px 0 0; padding: 0; list-style: none; }
.lvc-ev li { display: flex; gap: 9px; align-items: flex-start; padding: 4px 0; font-size: 13px; font-weight: 600; line-height: 1.5; color: #55554f; word-break: keep-all; }
.lvc-ev i { flex: none; width: 17px; height: 17px; margin-top: 1px; border-radius: 50%; display: grid; place-items: center; font-size: 10px; font-style: normal; font-weight: 900; color: #fff; background: #6abe36; }
.lvc-ev li.miss i { background: #dcdbd6; color: #6f6f6a; }

/* 공인 시험 기준 — 급수를 숫자로 못박는다 */
.lvc-cert { display: flex; align-items: baseline; gap: 9px; margin-top: 15px; padding-top: 14px; border-top: 1px solid #f0efeb; }
.lvc-cert i { flex: none; align-self: center; padding: 4px 10px; border-radius: 999px; background: #1c1c1c; color: #fff; font-size: 11px; font-weight: 900; font-style: normal; letter-spacing: .02em; }
.lvc-cert b { font-size: 15px; font-weight: 900; color: #1c1c1c; }
.lvc-cert span { font-size: 12.5px; font-weight: 600; color: #8a8a85; word-break: keep-all; }

/* ---------- ② 레이더 (지금 채움 vs 평균 외곽) ---------- */
.rad-legend { display: flex; justify-content: center; gap: 24px; margin: 4px 0 0; }
.rad-legend span { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 700; color: #1c1c1c; }
.rad-legend i { width: 14px; height: 14px; border-radius: 5px; }
.rad-legend i.avg { border: 2px dashed #b4b4b0; background: none; border-radius: 4px; }
.rad { display: block; width: 100%; height: auto; margin: -2px auto 6px; }

/* ---------- 항목별 카드 ----------
   한 항목 = 한 장. 눈금은 ① 지금 레벨 카드의 10칸 사다리를 다시 쓴다 —
   같은 척도를 두 가지 그림으로 보여 주면 읽는 사람이 매번 환산해야 한다.
   테두리는 없다: 리포트는 읽는 문서라 다섯 장이 먹선으로 둘러싸이면 화면이
   칸으로 쪼개져 읽히고, 정작 눈이 가야 할 초록 눈금과 라임 배지가 묻힌다.
   경계는 옅은 배경색만으로 낸다.
   아이콘은 Figma「❤️ PODO JP」> 일본어 리포트 의 항목 아이콘(ㅈ/A 라인
   아트)을 먹색으로 바꿔 가져왔다. */
.axcard { margin-top: 14px; border-radius: 18px; background: #fafaf7; overflow: hidden; }

.axc-top { display: flex; align-items: center; gap: 13px; padding: 17px 18px 0; }
.axc-ico { flex: none; display: grid; place-items: center; width: 52px; height: 52px; border-radius: 15px; background: #eaffc9; }
.axc-ico img { width: 33px; height: 33px; }
.axc-name { font-size: 16px; font-weight: 900; color: #1c1c1c; }
/* 레벨 숫자는 이 배지에만 있다 — 눈금·문장에서 다시 반복하지 않는다 */
.axc-lv { margin-left: auto; padding: 4px 11px; border-radius: 999px; background: #b5fd4c; font-size: 12.5px; font-weight: 900; color: #1c1c1c; }

/* 10칸 사다리 + 평균이 서 있는 칸 */
.axc-lad { padding: 16px 18px 0; }
.axc-segs { display: flex; gap: 3px; }
.axc-segs span { flex: 1 1 0; height: 8px; border-radius: 3px; background: #ebebe6; }
.axc-segs span.on { background: #6abe36; }
.axc-mark { position: relative; height: 15px; margin-top: 5px; }
.axc-mark b { position: absolute; transform: translateX(-50%); white-space: nowrap; font-size: 10px; font-weight: 800; color: #a6a6a1; }

.axc-tx { margin: 13px 0 0; padding: 0 18px 17px; font-size: 13.5px; font-weight: 500; line-height: 1.6; color: #5a5a56; word-break: keep-all; }

/* 추천은 카드 안의 아래층 — 살짝 짙은 바탕으로만 나눈다 */
.axc-tip { display: flex; gap: 10px; padding: 13px 18px; background: #f1f3ea; }
.axc-tip .ic { flex: none; font-size: 14px; line-height: 1.5; }
.axc-tip .t { font-size: 12.5px; font-weight: 500; color: #4d5a3a; line-height: 1.6; word-break: keep-all; }
.axc-tip .t b { margin-right: 5px; font-weight: 900; color: #3d6b1e; }

/* ---------- ③ 도착 예측 ----------
   레이더와 같은 꼴로 둔다: 범례 한 줄 + 테두리 없는 전폭 그래프. 그래프를
   카드에 넣으면 박스 안의 박스가 되고, 안쪽 여백만큼 선이 쪼그라든다.
   레이더는 면(네모 칩)을 두 개 비교하지만 여기는 선 두 개라, 같은 범례
   골격에 칩만 선으로 바꿔 끼운다. */
.rep-legend i { width: 18px; height: 3px; border-radius: 2px; background: #6abe36; }
.rep-legend i.slow { height: 0; border-top: 2px dashed #b4b4b0; border-radius: 0; background: none; }
.rep-legend b { font-weight: 700; }

/* ================================================================
   ⓪ 튜터 콘솔 · 레벨 체크
   리포트 전체가 이 선택에서 파생되므로 페이지 맨 위에 둔다. 학습자에게는
   아예 없는 블록이고(teaching 모드에서만 뜬다), 고르고 나면 한 줄로
   접힌다 — 튜터도 폼을 채우러 온 게 아니라 리포트를 보러 온 사람이다.
   선택 자체는 공유된다: 컨트롤만 튜터의 것이고, 결과인 리포트는 둘 다
   같은 걸 봐야 한다.
   ================================================================ */
.tcon { display: none; }
body.teaching .tcon { display: block; margin: 0 0 28px; }
.tcon-body { padding: 18px 18px 16px; border: 1.5px dashed #1c1c1c; border-radius: 14px; background: #fbfbf8; }
.tcon.folded .tcon-body { display: none; }
.tcon:not(.folded) .tcon-sum { display: none; }

.tcon-sum { display: flex; align-items: center; gap: 10px; width: 100%; padding: 11px 14px; border: 1.5px dashed #1c1c1c; border-radius: 12px; background: #fbfbf8; font-family: inherit; text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.tcon-sum .ts-lv { flex: none; padding: 3px 10px; border-radius: 999px; background: #1c1c1c; color: #b5fd4c; font-size: 12px; font-weight: 900; }
.tcon-sum .ts-ax { flex: 1 1 auto; min-width: 0; font-size: 12px; font-weight: 700; color: #6f6f6a; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tcon-sum .ts-go { flex: none; font-size: 11.5px; font-weight: 800; color: #4a7a2a; }

.tcon-h { display: flex; align-items: baseline; gap: 8px; font-size: 15px; font-weight: 900; color: #1c1c1c; }
.tcon-h small { font-size: 11px; font-weight: 800; color: #8a8a85; }
.tcon-q { margin: 17px 0 0; font-size: 12.5px; font-weight: 800; color: #55554f; }
.tcon-q small { font-weight: 600; color: #8a8a85; }
.tcon .lvpick { gap: 7px; margin-top: 10px; }
.tcon .lvrow { gap: 11px; padding: 9px 12px; border-radius: 11px; }
.tcon .lvrow .lvn { width: 28px; height: 28px; border-radius: 8px; font-size: 14px; }
.tcon .lvrow .lvt { font-size: 13.5px; }
.tcon .lvrow .lvs { margin-top: 1px; font-size: 11px; }

/* 항목별 — 10칸 칩 한 줄. 종합 레벨과 다를 때만 튜터가 손을 댄다. */
.axpick { display: grid; gap: 8px; margin-top: 10px; }
.axrow { display: flex; align-items: center; gap: 10px; }
.axrow .axn { flex: none; width: 44px; font-size: 12.5px; font-weight: 800; color: #1c1c1c; }
.axchips { flex: 1 1 auto; display: grid; grid-template-columns: repeat(10, 1fr); gap: 4px; }
.axchips button { padding: 6px 0; border: 1.5px solid #ddddd8; border-radius: 7px; background: #fff; font-family: inherit; font-size: 11.5px; font-weight: 800; color: #9a9a95; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.axchips button.on { border-color: #1c1c1c; background: #b5fd4c; color: #1c1c1c; }
/* 손대지 않은 항목이 종합 레벨을 따라가고 있다는 표시 — 고른 것과는 다르게 옅다 */
.axchips button.echo { border-color: #cfcfc9; background: #f4f4f1; color: #55554f; }
.tcon-fold { width: 100%; margin-top: 18px; padding: 10px; border: 1.5px solid #1c1c1c; border-radius: 11px; background: #fff; font-family: inherit; font-size: 13px; font-weight: 800; color: #1c1c1c; cursor: pointer; }

/* ---------- 한 장으로 합친 리포트 ----------
   ①②③ 이 한 페이지 안에서 이어지므로 블록 사이는 가는 선으로만 나눈다.
   초록 카드는 이제 페이지가 아니라 페이지 안의 첫 블록이다. */
.rep-all .rep-sec { margin-top: 34px; padding-top: 30px; border-top: 1.5px solid #ececea; }
.rep-all .rv-sub { margin-bottom: 20px; }
.rep-all .lvc { margin: 0; }
.rep-all .trks { margin-top: 6px; }

/* ---------- 학습 순서 ----------
   한 카드 = 한 코스. 아이콘이 먼저 보이고, 그 코스에서 실제로 하게 되는
   말 한 줄이 증거로 붙는다. 기간·레슨 수는 일부러 넣지 않는다 — 그 숫자는
   위 그래프가 이미 말했고, 여기서 다시 세면 카탈로그처럼 읽힌다. */
.cmap { margin-top: 12px; }
.cst { position: relative; padding: 15px 16px 16px; border-radius: 16px; background: #f6f6f3; }
.cst + .cst { margin-top: 28px; }
/* 카드 사이를 잇는 세로선 — 순서가 있다는 표시 */
.cst + .cst::before {
  content: ""; position: absolute; left: 56px; top: -28px;
  width: 2px; height: 28px; background: #cfe8b4;
}
.cst-top { display: flex; align-items: center; gap: 15px; }
.cst-b { flex: 1 1 auto; min-width: 0; }

/* 강의 커버 — 색 바탕 + 그림 + 짧은 이름. 원본 아이콘에 구워져 있던
   흰 타일을 벗겨 낸 그림을 쓰기 때문에 바탕색이 그대로 보인다.
   테두리는 없다: 카드 안의 카드가 되면 상자가 세 겹이 된다. */
.cst-cov {
  position: relative; flex: none; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 1px;
  width: 82px; height: 100px; border-radius: 16px; overflow: hidden;
}
.cst-cov img { width: 52px; height: 52px; object-fit: contain; }
.cst-cov em { font-style: normal; font-size: 11px; font-weight: 900; color: #1c1c1c; letter-spacing: -.01em; }
/* 그래프의 마디와 같은 동그라미 — 번호도 모양도 같아야 이어진다 */
.cst-n {
  position: absolute; top: 6px; left: 6px; display: grid; place-items: center;
  width: 21px; height: 21px; border: 1.5px solid #1c1c1c; border-radius: 50%;
  background: #b5fd4c; font-size: 11.5px; font-weight: 900; color: #1c1c1c;
}
.cst-t { font-size: 17px; font-weight: 900; color: #1c1c1c; }
.cst-flag {
  display: inline-block; margin-left: 8px; padding: 3px 9px; border-radius: 999px;
  background: #1c1c1c; color: #b5fd4c; font-size: 10.5px; font-weight: 900; vertical-align: 3px;
}
.cst-s { display: block; margin-top: 5px; font-size: 12.5px; font-weight: 600; color: #8a8a85; line-height: 1.45; word-break: keep-all; }
/* 그 코스를 마치면 할 수 있게 되는 말 — 위 그래프의 마디에 붙어 있던 그
   한 줄을 그대로 받아서(굵은 줄), 예문 하나로 한 번 더 푼다. */
.cst-l {
  display: flex; align-items: flex-start; gap: 10px; margin-top: 14px; padding: 12px 13px;
  border-radius: 11px; background: #fff;
}
.cst-l i {
  flex: none; display: grid; place-items: center; width: 18px; height: 18px; margin-top: 1px;
  border-radius: 50%; background: #6abe36; color: #fff; font-size: 10px; font-style: normal; font-weight: 900;
}
.cst-l .ct { font-size: 13.5px; font-weight: 800; color: #1c1c1c; line-height: 1.4; word-break: keep-all; }
.cst-l .ct em {
  display: block; margin-top: 4px; font-style: normal;
  font-size: 12px; font-weight: 600; color: #7d7d78; line-height: 1.5; word-break: keep-all;
}
.cst.goal { background: #f2fce0; }
.cst.goal .cst-l { background: #fff; }

/* ---------- 리포트 저장 · 리포트가 끝나는 자리, 튜터만 ----------
   레벨 체크(.lvcheck)와 같은 꼴이다: 먹색 점선이 「학습자 화면에는 없다」는
   표시고, 누르는 자리가 그 값이 다 모인 자리 바로 뒤에 있다.
   버튼만 라임을 쓴다 — 이 화면에서 튜터가 실제로 「누르는」 것이 이것 하나라,
   상태색(초록)이 아니라 브랜드 크롬 쪽이 맞다(.rep-jump 와 같은 자리). */
.rep-send { display: none; }
body.teaching .rep-send {
  display: block; margin-top: 18px; padding: 14px;
  border: 1.5px dashed var(--ink); border-radius: 14px; background: #fbfbf8;
}
.rep-send-h { display: block; font-size: 14px; font-weight: 900; color: var(--ink); }
.rep-send-h small { margin-left: 7px; font-size: 11px; font-weight: 800; color: #8a8a85; }
.rs-btn {
  display: block; width: 100%; margin-top: 11px; padding: 13px;
  border: 1.5px solid var(--ink); border-radius: 12px; background: var(--lime);
  font-family: inherit; font-size: 14.5px; font-weight: 900; color: var(--ink);
  letter-spacing: -.02em; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
/* 아직 못 보내는 상태는 「눌러도 안 되는 라임」이 아니라 아예 다른 것으로
   보여야 한다 — 색만 흐리면 탭이 먹었는지 아닌지를 튜터가 매번 시험한다. */
.rs-btn:disabled {
  border-color: var(--gray-200); background: var(--gray-100);
  color: #b0b0aa; cursor: default;
}
.rs-btn:not(:disabled):active { transform: translateY(1px); }
.rs-msg {
  margin: 9px 0 0; font-size: 12px; font-weight: 700; color: #6f6f6a;
  line-height: 1.5; word-break: keep-all;
}
.rep-send[data-state="done"] .rs-msg { color: var(--green-500); }
.rep-send[data-state="error"] .rs-msg { color: #c0392b; }
