:root {
  --paper: whitesmoke;
  --ink: #111111;
  --muted: #6b6b6b;
  --rule: #d8d8d8;
  --blue: #0000ee;
  --type-size: 4rem;
  --type-leading: 1;
  --type-font: '3ChannelKR-RGB', sans-serif;
}

html,
body {
  height: 100%;
  height: 100dvh;
  margin: 0;
}

body#3channelkr {
  background: var(--paper);
  color: var(--ink);
  overflow: hidden;
  overscroll-behavior: none;
}

#main {
  position: relative;
  width: 100%;
  height: 100%;
  height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* ── Demo (masthead + stage) ── */

body.is-demo {
  background: var(--paper);
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

body.is-demo #main {
  display: flex;
  flex-direction: column;
  height: 100%;
  height: 100dvh;
}

/*
 * Outer black frame = one 전각상자 (matches inner --cell), with a floor.
 * contentWidth = 100vw - 2*frame, cell = contentWidth / cols
 * → ideal frame = 100vw / (cols + 2); never below --frame-min
 */
body.is-framed {
  --frame-cols: var(--frame-cols-sm, var(--phrase-cols-sm, 12));
  --frame-min: 2.5rem;
  --frame: max(var(--frame-min), calc(100vw / (var(--frame-cols) + 2)));
  position: relative;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  background: #000;
  padding: var(--frame);
}

@media screen and (min-width: 600px) {
  body.is-framed {
    --frame-cols: var(--frame-cols-md, var(--phrase-cols-md, 36));
    --frame-min: 3rem;
  }
}
@media screen and (min-width: 900px) {
  body.is-framed {
    --frame-cols: var(--frame-cols-lg, var(--phrase-cols-lg, 36));
  }
}
@media screen and (min-width: 1200px) {
  body.is-framed {
    --frame-cols: var(--frame-cols-xl, var(--phrase-cols-xl, 36));
  }
}

body.is-framed #main {
  flex: 1 1 auto;
  min-height: 0;
  height: auto;
  background: var(--paper);
}

/* Content subpages (about / rgb / cmy): scroll inside the paper */
body.is-framed:not(.is-demo) {
  color: var(--ink);
}

body.is-framed:not(.is-demo) #main {
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: none;
  overscroll-behavior-y: none;
  box-sizing: border-box;
  padding: 2.5rem 1.5rem;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

body.is-framed:not(.is-demo) #main::-webkit-scrollbar {
  display: none;
}

body.is-framed.is-rgb h1,
body.is-framed.is-cmy h1 {
  margin: 0;
  font-family: '3ChannelKRBody70', sans-serif;
  font-size: 1rem;
  font-weight: normal;
  line-height: 1.4;
}

/*
 * Static mosaic pages (DEMO_STATIC + PAGE_TEXT): same stripe as home,
 * full copy scrolls inside the paper (no viewport trim).
 */
body.is-demo.is-static #stage {
  flex: 1 1 auto;
  min-height: 0;
  height: auto;
  display: flex;
  flex-direction: column;
}

body.is-demo.is-static #demo,
body.is-demo.is-static.is-stripe #demo .demo-pane.is-rgb-pane {
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: none;
  overscroll-behavior-y: none;
  height: 100%;
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* legacy Edge */
}

body.is-demo.is-static #demo::-webkit-scrollbar,
body.is-demo.is-static.is-stripe #demo .demo-pane.is-rgb-pane::-webkit-scrollbar {
  display: none; /* Chrome, Safari */
}

body.is-demo.is-static .demo-text {
  height: auto;
  min-height: 100%;
}

body.is-demo.is-static .demo-caret {
  display: none;
}

body.is-demo.is-static.is-live.is-placeholder .demo-text {
  opacity: 0.35;
}

body.is-demo.is-static.is-live.is-align-center.is-stripe .demo-text {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: center;
  width: 100%;
  min-height: 100%;
}

body.is-demo.is-static.is-live.is-align-center.is-stripe .demo-text .demo-ch {
  flex: 0 0 var(--cell);
  width: var(--cell);
  height: var(--cell);
}

body.is-demo.is-static.is-live.is-align-center.is-stripe .demo-text .demo-nl,
body.is-demo.is-static.is-live.is-align-center.is-stripe .demo-text .demo-row-spacer {
  flex: 0 0 100%;
  width: 100%;
  grid-column: unset;
}

#tester-bar {
  position: absolute;
  bottom: 0;
  right: 0;
  z-index: 2;
  width: auto;
  max-width: 100%;
  flex: 0 0 auto;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
  box-sizing: border-box;
  padding: 0.75rem;
  border: 0;
  background: none;
  font-family: '3ChannelKRBody70', sans-serif;
  font-size: 0.75rem;
  line-height: 1;
  color: var(--ink);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s ease;
}

#tester-bar.is-visible {
  opacity: 1;
  pointer-events: auto;
}

#tester-bar .control {
  flex: 0 1 8rem;
  width: 8rem;
  max-width: 8rem;
  font-family: inherit;
  color: var(--ink);
}

#tester-bar .control #tester-size {
  display: block;
  width: 100%;
}

@media screen and (max-width: 599px) {
  #tester-bar {
    left: 0;
    width: 100%;
    justify-content: space-between;
  }

  #tester-bar .control {
    flex: 1 1 auto;
    width: auto;
    max-width: none;
  }
}

#tester-bar .control-label {
  width: auto;
  text-transform: none;
  letter-spacing: 0;
}

#tester-bar .control-origin {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.5rem;
  flex: 0 0 auto;
  width: auto;
  max-width: none;
  margin: 0;
  padding: 0;
  border: 0;
  min-inline-size: 0;
}

#tester-bar .origin-opt {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  margin: 0;
  color: var(--muted);
  cursor: pointer;
}

#tester-bar .origin-opt input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

#tester-bar .origin-icon {
  display: block;
  width: 1.25rem;
  height: 1.25rem;
  pointer-events: none;
}

#tester-bar .origin-opt:has(input:checked) {
  color: var(--ink);
}

#tester-bar .origin-opt:hover {
  color: var(--ink);
}

#tester-bar .visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

body.is-demo.is-static.is-live #stage {
  position: relative;
}

#live-type {
  position: absolute;
  inset: 0;
  z-index: 1;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  resize: none;
  outline: none;
  overflow: hidden;
  opacity: 0;
  color: transparent;
  caret-color: transparent;
  background: transparent;
  font-size: 1rem;
}

#masthead {
  flex: 0 0 auto;
  box-sizing: border-box;
  max-height: 25vh;
  padding: 1rem 0.75rem;
  overflow: auto;
  margin-bottom: 6rem;
}

#stage {
  flex: 1 1 auto;
  position: relative;
  min-height: 0;
  width: 100%;
}

/* ── Glyph run: RGB + Body70 side by side ── */

body.is-glyph-run #stage {
  container-type: size;
}

body.is-glyph-run #glyph-stage {
  --pair: min(50cqw, 100cqh);
  --body-scale: 1;
  --body-nudge-y: -0.24em;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-end;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

body.is-glyph-run .glyph-row {
  display: flex;
  flex-direction: row;
  align-items: flex-end;
  justify-content: flex-start;
  width: calc(var(--pair) * 2);
  height: var(--pair);
  margin: 0;
  padding: 0;
}

body.is-glyph-run .glyph {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--pair);
  height: var(--pair);
  margin: 0;
  padding: 0;
  font-size: var(--pair);
  line-height: 1;
  text-align: center;
  color: var(--ink);
  -webkit-user-select: none;
  user-select: none;
}

body.is-glyph-run .glyph.is-rgb {
  font-family: '3ChannelKR-RGB', sans-serif;
}

body.is-glyph-run .glyph.is-body {
  font-family: '3ChannelKRBody70', sans-serif;
  font-size: calc(var(--pair) * var(--body-scale));
  transform: translateY(var(--body-nudge-y));
}

/* ── Demo columns (한 줄 글자 수) ──
 * phrases.js DEMO_COLS → --phrase-cols-* (없으면 아래 기본값)
 */
body.is-demo #demo {
  --demo-cols: var(--phrase-cols-sm, 12);
}
@media screen and (min-width: 600px) {
  body.is-demo #demo {
    --demo-cols: var(--phrase-cols-md, 36);
  }
}
@media screen and (min-width: 900px) {
  body.is-demo #demo {
    --demo-cols: var(--phrase-cols-lg, 36);
  }
}
@media screen and (min-width: 1200px) {
  body.is-demo #demo {
    --demo-cols: var(--phrase-cols-xl, 36);
  }
}

body.is-demo #demo {
  /* 3ChannelKRBody70 hangul ink mid ≈ 0.26em */
  --noto-scale: 0.85;
  --noto-nudge-y: -0.24em;
  /*
   * --cell must be set on a DESCENDANT of the query container.
   * cqw on the container itself falls back to the viewport (≈2× pane width in split).
   */
  container-type: inline-size;
  position: relative;
  box-sizing: border-box;
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  text-align: left;
  font-family: var(--type-font);
  line-height: 1;
  letter-spacing: 0;
  direction: ltr;
}

/* Split: left RGB / right Body, same text in sync */
body.is-demo.is-split #demo {
  display: flex;
  flex-direction: row;
  container-type: normal;
}

body.is-demo.is-split #demo .demo-pane {
  box-sizing: border-box;
  position: relative;
  flex: 1 1 50%;
  width: 50%;
  min-width: 0;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  container-type: inline-size;
  line-height: 1;
  letter-spacing: 0;
  text-align: left;
  direction: ltr;
}

body.is-demo.is-split #demo .demo-pane.is-rgb-pane {
  font-family: '3ChannelKR-RGB', sans-serif;
}

body.is-demo.is-split #demo .demo-pane.is-body-pane {
  font-family: '3ChannelKRBody70', sans-serif;
}

/* Stripe: one pane, rows alternate RGB / Body */
body.is-demo.is-stripe #demo {
  --noto-scale: 0.75;
  display: block;
  container-type: inline-size;
}

body.is-demo.is-stripe #demo .demo-pane.is-body-pane {
  display: none;
}

body.is-demo.is-stripe #demo .demo-pane.is-rgb-pane {
  box-sizing: border-box;
  position: relative;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  /* --cell lives on .demo-text; pane is not the query container */
  container-type: normal;
  line-height: 1;
  letter-spacing: 0;
  text-align: left;
  direction: ltr;
}

/*
 * Exact col grid so wrap matches JS stripe rows (inline-block % widths
 * can wrap a char early from subpixel rounding → RGB/Body out of sync).
 */
body.is-demo.is-stripe .demo-text {
  --mosaic-scale: 1.02;
  display: grid;
  grid-template-columns: repeat(var(--demo-cols), minmax(0, 1fr));
  gap: 0;
  justify-content: start;
  justify-items: stretch;
  align-content: start;
  text-align: left;
}

body.is-demo.is-stripe .demo-text .demo-ch {
  width: auto;
  height: auto;
  aspect-ratio: 1;
  /* Cover subpixel paper hairlines between mosaic tiles */
  transform: scale(var(--mosaic-scale, 1.02));
  transform-origin: center;
}

body.is-demo.is-stripe .demo-text .demo-nl {
  grid-column: 1 / -1;
}

/* Visible blank mosaic row — prefer --cell so it doesn’t collapse */
body.is-demo.is-stripe .demo-text .demo-row-spacer {
  grid-column: 1 / -1;
  display: block;
  width: 100%;
  height: var(--cell, 1em);
  min-height: var(--cell, 1em);
  overflow: hidden;
  pointer-events: none;
}

.demo-text {
  /* Child of #demo (single) or .demo-pane (split) → cqw = that container’s width */
  --cell: calc(100cqw / var(--demo-cols));
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  font-size: var(--cell);
  line-height: 1;
  color: inherit;
  /* <pre> defaults to white-space:pre, which blocks soft-wrap of .demo-ch cells */
  white-space: normal;
  text-align: left;
  position: relative;
  left: 0;
  top: 0;
}

/*
 * Each cell stacks RGB + Body faces. Wipe only toggles opacity — never swaps
 * font-family on a live run (iPad WebKit COLR often bleeds R/G when that happens).
 */
.demo-text .demo-ch {
  position: relative;
  display: inline-block;
  box-sizing: border-box;
  width: calc(100% / var(--demo-cols));
  height: var(--cell);
  /* Kill inline strut so row height == --cell (not ~2×) */
  font-size: 0;
  line-height: 0;
  text-align: center;
  vertical-align: top;
  isolation: isolate;
  overflow: hidden;
}

.demo-text .demo-face {
  display: block;
  width: 100%;
  height: 100%;
  line-height: 1;
  text-align: center;
}

.demo-text .demo-face.is-rgb {
  font-family: '3ChannelKR-RGB', sans-serif;
  font-size: var(--cell);
  color: var(--ink);
}

/* CMY tester: colour row is a process square, not the COLR glyph. */
body.is-ink-cmy .demo-text .demo-face.is-cmy {
  font-size: 0;
}

body.is-ink-cmy #face-switch-slot .face-part.is-cmy-swatch {
  width: 1em;
  height: 1em;
  transform: none;
}

.demo-text .demo-face.is-noto {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: '3ChannelKRBody70', sans-serif;
  font-size: calc(var(--cell) * var(--noto-scale));
  line-height: 1;
  color: var(--ink);
  -webkit-text-fill-color: var(--ink);
  transform: translateY(var(--noto-nudge-y));
  opacity: 0;
}

.demo-text .demo-ch.is-wiped .demo-face.is-rgb {
  opacity: 0;
}

.demo-text .demo-ch.is-wiped .demo-face.is-noto {
  opacity: 1;
}

/* Split / stripe: single-face cells fill the fixed cell */
body.is-demo.is-split .demo-text .demo-ch.is-single .demo-face,
body.is-demo.is-stripe .demo-text .demo-ch.is-single .demo-face {
  position: absolute;
  inset: 0;
  opacity: 1;
}

body.is-demo.is-split .demo-text .demo-ch.is-single .demo-face.is-noto,
body.is-demo.is-stripe .demo-text .demo-ch.is-single .demo-face.is-noto {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(var(--cell) * var(--noto-scale));
  transform: translateY(var(--noto-nudge-y));
}

.demo-text .demo-nl {
  display: block;
  width: 100%;
  height: 0;
  overflow: hidden;
  font-size: 0;
  line-height: 0;
}

/* Caret is positioned in JS to the end of .demo-text */
.demo-caret {
  position: absolute;
  left: 0;
  top: 0;
  display: none;
  width: 1px;
  height: 1em;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--ink);
  animation: caret-blink 1s steps(1) infinite;
  pointer-events: none;
}

.demo-caret.is-paused {
  animation: none;
  opacity: 0.35;
}

@keyframes caret-blink {
  0%,
  49% {
    opacity: 1;
  }
  50%,
  100% {
    opacity: 0;
  }
}

/* ── Chrome (mousemove reveal; bottom of framed home) ── */

#chrome {
  position: absolute;
  right: 1rem;
  bottom: 0.5rem;
  z-index: 3;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s ease;
}

#chrome.is-visible {
  opacity: 1;
  pointer-events: auto;
}

/*
 * Framed: L-rail along the white paper — bottom strip, then right strip.
 * Wrapper spans paper+bottom+right but stays pointer-events:none so the
 * mosaic stays clickable; only the action lists receive pointers when visible.
 */
body.is-framed #chrome {
  left: var(--frame);
  right: 0;
  top: var(--frame);
  bottom: 0;
  height: auto;
  width: auto;
  display: block;
  box-sizing: border-box;
  padding: 0;
  pointer-events: none;
}

body.is-framed #chrome.is-visible {
  pointer-events: none;
}

body.is-framed #chrome.is-visible #chrome-actions,
body.is-framed #chrome.is-visible #chrome-actions-side {
  pointer-events: auto;
}

body.is-framed #chrome-actions {
  --chrome-type: calc(var(--frame) * 0.4);
  position: absolute;
  left: 0;
  right: var(--frame);
  bottom: 0;
  width: auto;
  height: var(--frame);
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: flex-start;
  justify-content: flex-start;
  gap: calc(var(--chrome-type) * 2);
  padding-left: 0;
  box-sizing: border-box;
  margin: 0;
  list-style: none;
  overflow: visible;
}

body.is-framed #chrome-actions > li {
  flex: 0 0 auto;
  min-width: max-content;
}

body.is-framed #chrome-actions .chrome-btn {
  flex-shrink: 0;
  width: max-content;
  max-width: none;
  white-space: nowrap;
}

/* Overflow items: up the right edge, labels rotated −90° */
body.is-framed #chrome-actions-side {
  --chrome-type: calc(var(--frame) * 0.4);
  position: absolute;
  top: 0;
  right: 0;
  bottom: var(--frame);
  width: var(--frame);
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column-reverse;
  align-items: flex-start;
  justify-content: flex-start;
  gap: calc(var(--chrome-type) * 2);
  box-sizing: border-box;
  overflow: visible;
}

body.is-framed #chrome-actions-side > li {
  position: relative;
  flex: 0 0 auto;
  width: 1em;
  font-size: var(--chrome-type, calc(var(--frame) * 0.4));
}

body.is-framed #chrome-actions-side .chrome-btn {
  position: absolute;
  /* origin at outer edge of the 1em rail → thickness goes into the black strip, not the paper */
  left: 100%;
  bottom: 0;
  white-space: nowrap;
  transform: rotate(-90deg);
  transform-origin: left bottom;
}

body.is-framed #chrome-actions-side .chrome-btn > span {
  /* keep Body70 nudge; rotation is on the button */
  display: block;
  transform: translateY(calc(-1 * var(--chrome-body-nudge)));
}

body.is-framed #chrome-actions-side .chrome-btn:hover {
  transform: rotate(-90deg);
  transform-origin: left bottom;
}

body.is-framed #chrome-actions-side .chrome-btn:hover > span {
  transform: none;
}

/* Top-right face toggles: flush to the paper corner */
body.is-framed #face-switch-slot {
  --chrome-type: calc(var(--frame) * 0.4);
  position: absolute;
  top: 0;
  right: var(--frame);
  z-index: 3;
  box-sizing: border-box;
  height: var(--frame);
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: flex-end;
  justify-content: flex-end;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s ease;
}

body.is-framed #face-switch-slot.is-visible {
  opacity: 1;
  pointer-events: auto;
}

body.is-framed #face-switch-slot .face-toggle {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  width: auto;
  margin: 0;
  cursor: pointer;
  font-family: inherit;
  --chrome-body-nudge: 0.24em;
  opacity: 0.25;
}

body.is-framed #face-switch-slot .face-toggle.is-on {
  opacity: 1;
}

body.is-framed #face-switch-slot .face-toggle:hover {
  --chrome-body-nudge: 0.24em;
  background: var(--paper);
  color: #111111;
  font-family: inherit;
  text-decoration: none;
  opacity: 0.7;
}

body.is-framed #face-switch-slot .face-toggle.is-on:hover {
  opacity: 1;
}

body.is-framed #face-switch-slot .face-toggle:hover > span {
  transform: none;
}

body.is-framed #face-switch-slot .face-part {
  display: block;
  flex: 0 0 auto;
  line-height: 1;
}

body.is-framed #face-switch-slot .face-part.is-rgb {
  font-family: '3ChannelKR-RGB', sans-serif;
  transform: none;
}

body.is-framed #face-switch-slot .face-part.is-body {
  font-family: '3ChannelKRBody70', sans-serif;
  transform: translateY(calc(-1 * var(--chrome-body-nudge)));
}

body.is-framed #face-switch-slot .face-toggle:hover .face-part.is-body {
  transform: translateY(calc(-1 * var(--chrome-body-nudge)));
}

body.is-framed #face-switch-slot .face-toggle:hover .face-part.is-rgb {
  transform: none;
}

#masthead #chrome {
  position: static;
  opacity: 1;
  pointer-events: auto;
  transition: none;
}

#chrome-actions {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

#masthead #chrome-actions {
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
}

.chrome-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.chrome-btn {
  display: block;
  font-family: '3ChannelKRBody70', sans-serif;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1;
  color: var(--ink);
  text-decoration: none;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

body.is-framed .chrome-btn {
  /* Body70: empty top of em ≈ 0.24em — nudge ink up, clip the rest */
  --chrome-body-nudge: 0.24em;
  font-size: var(--chrome-type, calc(var(--frame) * 0.4));
  height: 1em;
  overflow: hidden;
  color: #111111;
  background: var(--paper);
}

body.is-framed .chrome-btn > span {
  display: block;
  transform: translateY(calc(-1 * var(--chrome-body-nudge)));
}

/* Face-switch parts set their own transform — don't inherit menu nudge twice */
body.is-framed #face-switch > span {
  transform: none;
}

.chrome-btn-sm {
  font-size: 1rem;
}

body.is-framed .chrome-btn-sm {
  font-size: inherit;
}

.chrome-btn-sm:first-child {
  margin-left: 0;
}

.chrome-btn:hover {
  text-decoration: underline;
  text-underline-offset: 0.25rem;
}

body.is-framed .chrome-btn:hover {
  font-family: '3ChannelKR-RGB', sans-serif;
  --chrome-body-nudge: 0;
  background: transparent;
  color: #ffffff;
  text-decoration: none;
}

body.is-framed .chrome-btn:hover > span {
  transform: none;
}

/* Current tab: colour face; hover inverts to body only */
body.is-framed .chrome-btn.is-current {
  font-family: '3ChannelKR-RGB', sans-serif;
  --chrome-body-nudge: 0;
}

/* RGB treats "/" as an empty 전각 — paper shows through. Fill that cell. */
body.is-framed .chrome-btn.is-current .chrome-punct {
  background: #111111;
}

body.is-framed .chrome-btn.is-current:hover {
  font-family: '3ChannelKRBody70', sans-serif;
  --chrome-body-nudge: 0.24em;
  background: var(--paper);
  color: #111111;
}

body.is-framed .chrome-btn.is-current:hover .chrome-punct {
  background: transparent;
}

body.is-framed .chrome-btn.is-current:hover > span {
  transform: translateY(calc(-1 * var(--chrome-body-nudge)));
}

.chrome-btn-sm:hover {
  text-decoration: underline;
  text-underline-offset: 0.125rem;
}

body.is-framed .chrome-btn-sm:hover {
  text-decoration: none;
}

/* ── Tester ── */

#typewriter {
  flex: 1 1 auto;
  width: 100%;
  min-height: 0;
  padding: 1.5rem;
  padding-right: 8.5rem;
  border: none;
  outline: none;
  resize: none;
  background: transparent;
  color: var(--ink);
  font-family: var(--type-font);
  font-size: var(--type-size);
  line-height: var(--type-leading);
  letter-spacing: -0.02em;
  caret-color: var(--ink);
}

#typewriter::placeholder {
  color: var(--muted);
  opacity: 1;
}

#font-switcher {
  position: absolute;
  top: 1.5rem;
  right: 1.5rem;
  z-index: 2;
  display: flex;
  gap: 0.75rem;
  align-items: baseline;
  font-family: "SFMono-Regular", "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.75rem;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.font-btn {
  padding: 0;
  border: none;
  background: none;
  color: var(--muted);
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
}

.font-btn:hover {
  color: var(--ink);
}

.font-btn.is-active {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 0.125rem;
}

#controls {
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 2.5rem;
  align-items: center;
  padding: 1rem 1.5rem;
  border-top: 1px solid var(--rule);
  background: var(--paper);
}

.control {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
  flex: 1 1 12rem;
  max-width: 24rem;
  font-family: "SFMono-Regular", "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.75rem;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
}

.control-label {
  flex-shrink: 0;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  width: 4.5rem;
}

.control-value {
  flex-shrink: 0;
  color: var(--ink);
  min-width: 2.5rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.control input[type="range"] {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  height: 1rem;
  margin: 0;
  appearance: none;
  background: transparent;
  cursor: pointer;
}

.control input[type="range"]::-webkit-slider-runnable-track {
  height: 1px;
  background: var(--ink);
}

.control input[type="range"]::-webkit-slider-thumb {
  appearance: none;
  width: 0.75rem;
  height: 0.75rem;
  margin-top: -0.375rem;
  border: 1px solid var(--ink);
  border-radius: 0;
  background: var(--paper);
}

.control input[type="range"]::-moz-range-track {
  height: 1px;
  background: var(--ink);
  border: none;
}

.control input[type="range"]::-moz-range-thumb {
  width: 0.75rem;
  height: 0.75rem;
  border: 1px solid var(--ink);
  border-radius: 0;
  background: var(--paper);
}

/* ── Glyph cube (RGB) ── */

body.is-framed.is-cube #main {
  overflow: hidden;
  padding: 0;
}

body.is-cube #cube-stage {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  width: 100%;
  height: 100%;
  background: var(--paper);
}

body.is-framed.is-cube #cube-canvas {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
}

.page-loading {
  position: absolute;
  inset: 0;
  z-index: 1;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: var(--paper);
}

body.is-demo.is-stripe .page-loading .demo-text {
  --cell: 1rem;
  --mosaic-scale: 1;
  --noto-scale: 0.85;
  --noto-nudge-y: -0.24em;
  width: calc(var(--cell) * var(--demo-cols, 13));
  max-width: 100%;
  height: auto;
  min-height: calc(var(--cell) * 2);
  flex: none;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(var(--demo-cols, 13), minmax(0, 1fr));
}

body.is-cube #cube-loading[hidden],
body.is-cube #cube-mobile[hidden],
body.is-dict #page-loading[hidden] {
  display: none;
}

body.is-cube #cube-loading.is-hidden {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s ease;
}

body.is-cube #face-switch-slot {
  gap: var(--chrome-type);
}

body.is-cube #face-switch-slot .cube-key {
  opacity: 0.25;
}

body.is-cube #face-switch-slot .cube-key.is-current {
  opacity: 1;
}

body.is-dict #face-switch-slot,
body.is-glyphs #face-switch-slot {
  gap: var(--chrome-type);
}

body.is-dict #face-switch-slot .dict-size:disabled,
body.is-glyphs #face-switch-slot .dict-size:disabled {
  opacity: 0.25;
  cursor: default;
}

/* ── Dictionary wall (RGB) ── */

body.is-framed.is-dict #main {
  overflow: hidden;
  padding: 0;
}

body.is-dict #stage,
body.is-dict #demo {
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: none;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

body.is-dict #demo::-webkit-scrollbar,
body.is-dict #stage::-webkit-scrollbar {
  display: none;
}

body.is-dict #demo .demo-pane.is-rgb-pane {
  position: relative;
  overflow-x: hidden;
  overflow-y: auto;
  height: 100%;
}

body.is-dict #dict-text.demo-text {
  display: block;
  position: static;
  width: 100%;
  margin: 0;
  word-break: break-all;
  overflow-wrap: anywhere;
  white-space: break-spaces;
  font-family: '3ChannelKR-RGB', sans-serif;
  font-size: var(--cell);
  line-height: 1;
  font-kerning: none;
  text-autospace: no-autospace;
}

body.is-demo.is-stripe .page-loading .demo-text .demo-ch {
  transform: none;
}

/*
 * Glyph atlas: one RGB text flow. Hover covers that cell with Body (about scale).
 */
body.is-glyphs #demo {
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: none;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

body.is-glyphs #demo::-webkit-scrollbar {
  display: none;
}

body.is-glyphs #glyphs-wall {
  --cell: calc(100cqw / var(--demo-cols));
  --mosaic-bleed: 1px;
  position: relative;
  width: 100%;
  margin: 0;
  font-size: var(--cell);
}

body.is-glyphs .glyphs-face {
  margin: 0;
  padding: 0;
  width: 100%;
  box-sizing: border-box;
  font-family: '3ChannelKR-RGB', sans-serif;
  /* Paint 1px over the neighbor so subpixel paper seams disappear.
   * letter-spacing pulls advance back to --cell, so wrap stays N-per-line. */
  font-size: calc(var(--cell) + var(--mosaic-bleed));
  letter-spacing: calc(var(--mosaic-bleed) * -1);
  line-height: var(--cell);
  white-space: pre-wrap;
  word-break: break-all;
  overflow-wrap: anywhere;
  font-kerning: none;
  font-variant-ligatures: none;
  text-autospace: no-autospace;
}

body.is-glyphs .glyphs-peek {
  position: absolute;
  left: 0;
  top: 0;
  display: none;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background: var(--paper);
  font-family: '3ChannelKRBody70', sans-serif;
  font-size: calc(var(--cell) * var(--noto-scale));
  line-height: 1;
  color: var(--ink);
  -webkit-text-fill-color: var(--ink);
  text-align: center;
  pointer-events: none;
  z-index: 1;
}

body.is-glyphs .glyphs-peek.is-on {
  display: flex;
  align-items: center;
  justify-content: center;
}

body.is-glyphs .glyphs-peek-ch {
  display: block;
  transform: translateY(var(--noto-nudge-y));
}

/* ── Download (stripe, like about) ── */

body.is-download #demo .demo-text .demo-ch.is-download-link {
  cursor: pointer;
}

body.is-download #demo .demo-text .demo-ch.is-download-link.is-face-body .demo-face.is-noto,
body.is-cmy.is-about #demo .demo-text .demo-ch.is-page-link.is-face-body .demo-face.is-noto {
  color: var(--blue);
  -webkit-text-fill-color: var(--blue);
}

body.is-cmy.is-about #demo .demo-text .demo-ch.is-page-link {
  cursor: pointer;
}

/* ── Book photos (CMY /cmy/images) ── */

body.is-framed.is-book #main {
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: none;
  overscroll-behavior-y: none;
  padding: 0;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

body.is-framed.is-book #main::-webkit-scrollbar {
  display: none;
}

body.is-book #book-photos {
  display: grid;
  grid-template-columns: 1fr;
  margin: 0;
  padding: 0;
}

@media screen and (min-width: 600px) {
  body.is-book #book-photos {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media screen and (min-width: 900px) {
  body.is-book #book-photos {
    grid-template-columns: repeat(4, 1fr);
  }
}

body.is-book #book-photos img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  object-position: center;
  vertical-align: top;
}

@media screen and (min-width: 600px) {
  .chrome-btn {
    font-size: 2rem;
  }

  .chrome-btn-sm {
    font-size: 1.5rem;
  }

  #typewriter {
    padding: 2.5rem;
    padding-right: 10rem;
  }

  #font-switcher {
    top: 2.5rem;
    right: 2.5rem;
  }

  #controls {
    padding: 1rem 2.5rem;
  }
}
