/* 젠시팝 편집기 - 우리 화면을 우리가 고치는 자리
 *
 * ## 왜 우리가 만들었나 (2026-09-13, 대표님 지시)
 *
 * 그 전까지 쓰던 `@studiolab-dev/editor-kit` 은 범용 디자인 편집기라 우리 것에 안 맞았다.
 *
 * | 남의 부품 | 우리에게 필요한 것 |
 * |---|---|
 * | 문구가 영어로 하드코딩되어 소비 앱에서 못 고친다 | 전부 한국어 |
 * | 쪽이 여러 장 | 기기 한 대는 한 쪽만 띄운다 |
 * | 색이 무제한 | 그 기기가 낼 수 있는 색만 |
 * | 글자 크기가 연속값 | 조판이 쓰는 아홉 단만 |
 * | 기기 · 디더 · 판독 거리 개념이 없다 | 그것이 이 제품의 전부다 |
 *
 * ## 2026-09-14: 젠시라이트 **고객 편집기**와 같은 UI 언어로 맞췄다 (대표님 지시, 계약 §80)
 *
 * > 「기존 젠시라이트 보면 좌측에 수정탭있고 우측에 캔버스영역있고 좌측탭에 다양한
 * >  요소도 있고한데 나 그런거 다 그대로 쓰고싶은데」
 *
 * 🔴 **젠시라이트에는 편집기가 둘이고, 그 전까지 엉뚱한 쪽을 베끼고 있었다.**
 *
 * | | 경로 | 누가 쓰나 | 생김새 |
 * |---|---|---|---|
 * | 베끼던 것 | `admin/design-editor` | 내부 어드민 | 어두운 바탕 · 왼쪽 목록 · 오른쪽 속성 |
 * | 정본 | `features/aplus-ai` | **고객** | 흰 바탕 · 왼쪽 레일+패널 · 오른쪽 캔버스 |
 *
 * 둘을 가르는 것은 폴더 이름이 아니라 **누가 쓰는가**다. 우리 편집기를 쓰는 사람은
 * 점주이니 고객 쪽이 정본이다. 옮긴 값은 이렇다.
 *
 * | 무엇 | 젠시라이트 고객 편집기 | 여기 |
 * |---|---|---|
 * | 상단바 | `h-12` = 48px · 흰 바탕 · 3열 그리드 | 같다 |
 * | 왼쪽 레일 | `w-16` = 64px · 아이콘 20px + 라벨 10px 세로 | 같다 |
 * | 활성 탭 | `bg-blue-50 text-blue-600` | 같다 |
 * | 수정 패널 | 400px · 같은 탭을 다시 누르면 220ms 로 접힘 | 같다 |
 * | 캔버스 | `bg-gray-50` · 나머지 폭 전부 | 같다 |
 * | 절 | `px-4 py-3` · 10px 흐린 대문자 라벨 | 같다 |
 * | 모서리 | `rounded-lg` (8px) | 같다 |
 *
 * ⚠ 탭은 일곱이 아니라 **여섯**이다. 젠시라이트 일곱(AI · 템플릿 · 테마 · 이미지 ·
 *   텍스트 · 브랜드 · 섹션)은 **섹션이 여럿인 긴 상세페이지**를 다루는 축이고,
 *   젠시팝은 800×480 한 장이라 섹션도 템플릿 갈아끼우기도 없다. 줄이되 **갈리는
 *   축은 그대로 「무엇을 할지」로 둔다.**
 *
 * ⚠ **토큰을 `:root` 에 두지 않고 `.gfe` 안에 둔다.** 편집기는 관리 화면 덮개 안에서
 *   열리므로, `:root` 를 건드리면 뒤에 깔린 관리 화면까지 같이 물든다.
 */

.gfe {
  /* 젠시라이트 고객 편집기에서 옮긴 값. 이름은 우리 것으로 붙였다 */
  --gfe-ink: var(--color-gray-900);          /* 본문 글자 (gency.ai 실측, 2026-09-23) */
  --gfe-ink-sub: var(--color-gray-700);      /* 보조 글자 - gency 레일 글자색 */
  --gfe-ink-faint: var(--color-gray-500);    /* 라벨 · 단위 */
  --gfe-line: var(--color-gray-200);         /* 경계 */
  --gfe-line-soft: var(--color-gray-150);    /* 옅은 경계 · 눌린 바탕 */
  --gfe-field: var(--color-gray-100);        /* 입력 칸 바탕 */
  --gfe-accent: var(--color-blue-600);       /* gency 파랑 - 저장 · 고른 것 */
  --gfe-accent-soft: var(--color-blue-500);  /* blue-400 - 누른 칸의 테두리 */

  /* 🔴 짜임은 **상단바 한 줄 + 그 아래 가로줄 하나**다. 가로줄 안에서 레일 64px,
     수정 패널(접히면 0), 캔버스가 나머지를 flex 로 나눈다. 젠시라이트 고객 편집기가
     같은 짜임이다 (`Shell.tsx` 의 `relative flex min-h-0 flex-1`).

     ⚠ **세 칸을 그리드 트랙으로 나누지 않는다.** 두 번 실측으로 막혔다.
       ① 트랙을 `auto` 로 두고 패널에 `width: 400px` 을 주면, `overflow: hidden` 인
          아이템이라 트랙이 0 으로 줄어 패널 폭이 1px 이 된다.
       ② 트랙에 직접 `64px 400px 1fr` 을 주고 `transition: grid-template-columns` 를
          걸면, `1fr` 이 섞인 트랙 목록은 크롬이 보간을 포기해 **끝값으로도 안 간다.**
          클래스는 붙어 있는데 계산값이 `0px` 에 멈춰 있었다.
       flex 자식의 `width` 전이는 이 둘을 다 피한다. */
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-rows: 48px 1fr;
  grid-template-areas:
    'bar'
    'body';
  background: var(--color-gray-100);
  color: var(--gfe-ink);
  font-size: 12px; line-height: 20px;
  overflow: hidden;
}

/* 🔴 **관리 화면의 전역 단추 규칙을 여기서 끊는다.** `web/style.css` 가
   `button, .btn { padding: 8px 16px; min-height: 44px; font-size: 14px; line-height: 22px; border: 1px solid }`
   를 태그 이름으로 걸어 두는데, 편집기는 그 화면 위에 오버레이로 뜨므로 그 규칙이
   편집기 단추에도 그대로 걸린다. 우리가 적은 `height: 28px` 는 `min-height: 44px` 에
   지고, 좌우 padding 16px 이 28px 짜리 아이콘 단추 안의 그림을 **폭 0 으로 짜부라뜨린다.**

   ⚠ 그래서 정본과 똑같은 값을 적어 두고도 화면이 안 닮았다. 실측한 것이 이렇다 -
     절 머리 · 칩 · 맞춤 · 위치 초기화 · 비율 잠금이 전부 44px 이었고, 젠시라이트는
     28px 이다. 패널 하나에 단추가 열댓이라 그 16px 씩이 쌓여 **밀도가 통째로 갈린다.**

   ⚠ `editor.html` 을 주소로 직접 열면 `style.css` 가 없어 28px 로 정상으로 보인다.
     편집기만 따로 띄워 보는 검수로는 이 어긋남을 영영 못 찾는다.

   🔑 `:where()` 로 감싸 특이도를 `.gfe` 하나(0,1,0)로 낮춘다. 그러면 아래에 오는
      부품 규칙들이 전부 이겨서, **이 줄은 전역 규칙만 지우고 우리 값은 안 건드린다.**

   ⚠ 둘을 `:where(button, select)` 한 덩이로 묶지 않는다. 「편집기 규칙이 자기 밖으로
     안 샌다」를 재는 검사가 선택자를 쉼표로 쪼개는데, 괄호 안의 쉼표까지 같이 쪼개져
     뒷조각이 `.gfe` 로 시작하지 않게 된다. */
.gfe :where(button),
.gfe :where(select) {
  min-height: 0;
  padding: 0;
  font-size: inherit;
  border: none;
}

/* ---- 위 막대 ---- */

/* 젠시라이트는 3열 그리드다. `justify-between` 으로 두면 가운데 칸이 양쪽 폭에 따라
   좌우로 흔들리는데, 저장 상태 글자는 길이가 자주 바뀌는 자리라 그것이 눈에 띈다. */
.gfe__bar {
  grid-area: bar;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  padding: 0 16px;
  background: var(--color-white);
  border-bottom: 1px solid var(--gfe-line);
}

.gfe__barLeft {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.gfe__barMid {
  display: flex;
  align-items: center;
  justify-content: center;
}

.gfe__barRight {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

.gfe__barSplit {
  width: 1px;
  height: 20px;
  background: var(--gfe-line);
  flex: none;
}

.gfe__nameInput {
  font: inherit;
  font-size: 14px; line-height: 22px;
  font-weight: 600;
  color: var(--gfe-ink);
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 4px 8px;
  min-width: 0;
  max-width: 260px;
}

.gfe__nameInput:hover { border-color: var(--gfe-line); }

.gfe__nameInput:focus {
  border-color: var(--gfe-accent-soft);
  background: var(--color-white);
  outline: none;
}

.gfe__nameInput::placeholder { color: var(--gfe-ink-faint); font-weight: 400; }

/* 아이콘만 있는 단추 (뒤로 · 되돌리기 · 다시 하기). */
.gfe__iconBtn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 6px;
  background: none;
  color: var(--gfe-ink-faint);
  cursor: pointer;
  flex: none;
}

.gfe__iconBtn:hover:not(:disabled) { background: var(--gfe-line-soft); color: var(--gfe-ink); }
.gfe__iconBtn:disabled { opacity: .35; cursor: default; }

.gfe__icon { display: block; width: 16px; height: 16px; }

/* 글자만 있는 단추 (처음으로 · 기기에서 보기). */
.gfe__ghost {
  font: inherit;
  font-size: 12px; line-height: 20px;
  height: 30px;
  padding: 0 10px;
  border-radius: 6px;
  background: none;
  color: var(--gfe-ink-sub);
  cursor: pointer;
  white-space: nowrap;
}

.gfe__ghost:hover:not(:disabled) { background: var(--gfe-line-soft); color: var(--gfe-ink); }
.gfe__ghost:disabled { opacity: .35; cursor: default; }

.gfe__primary {
  font: inherit;
  font-size: 12px; line-height: 20px;
  font-weight: 600;
  height: 30px;
  padding: 0 16px;
  border-radius: 6px;
  background: var(--gfe-accent);
  color: var(--color-white);
  cursor: pointer;
  white-space: nowrap;
}

.gfe__primary:hover:not(:disabled) { background: var(--color-blue-900); }

.gfe__status {
  font-size: 12px; line-height: 20px;
  color: var(--gfe-ink-faint);
  white-space: nowrap;
}

.gfe__status--bad { color: var(--color-red-800); }

/* ---- 왼쪽 레일 ---- */

/* 🔴 젠시라이트 `ToolTabBar` 그대로 64px 이다. 아이콘 20px 과 라벨 10px 이 세로로
   쌓여 한 단추가 되고, 그 단추가 레일 폭을 다 쓴다. 라벨을 뺄 수 없다 - 점주는
   아이콘만 보고 「모양」과 「자리」를 못 가른다. */
/* 🔴 64px 은 젠시라이트 `ToolTabBar` 의 `w-16` 이다. 폭을 여기서 못 박는다 -
   그리드 트랙이 정하던 것을 flex 로 옮기면서 한 번 빠뜨려 37px 로 오그라들었다. */
.gfe__rail {
  flex: 0 0 64px;
  width: 64px;
  display: flex;
  flex-direction: column;
  background: var(--color-white);
  border-right: 1px solid var(--gfe-line);
  overflow-y: auto;
}

.gfe__railBtn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 100%;
  padding: 12px 4px;
  background: none;
  color: var(--gfe-ink-sub);
  cursor: pointer;
  flex: none;
}

.gfe__railBtn:hover:not([aria-selected='true']) {
  background: var(--gfe-line-soft);
  color: var(--color-gray-700);
}

.gfe__railBtn[aria-selected='true'] {
  background: var(--color-blue-100);
  color: var(--gfe-accent);
}

.gfe__railBtn[hidden] { display: none; }

.gfe__railIcon { display: block; width: 20px; height: 20px; }

.gfe__railLabel { font-size: 11px; line-height: 1; }

/* ---- 수정 패널 ---- */

/* 상단바 아래 가로줄. 레일 · 패널 · 캔버스가 여기서 나뉜다.
   `min-height: 0` 이 없으면 캔버스가 넘칠 때 가로줄이 같이 늘어나 상단바가 밀린다. */
.gfe__body {
  grid-area: body;
  display: flex;
  min-height: 0;
  overflow: hidden;
}

/* 🔴 폭은 400px 이고 **같은 탭을 다시 누르면 0 이 된다** (젠시라이트 `toggleTab`).
   800×480 한 장을 크게 보고 싶은 자리가 실제로 있고, 접는 길이 없으면 400px 이 늘
   화면을 먹는다.

   ⚠ 폭만 0 으로 줄이고 안쪽은 400px 그대로 둔다(`.gfe__panelInner`). 안쪽까지 같이
     줄이면 접히는 220ms 동안 글자가 줄바꿈되며 요동친다. */
.gfe__panel {
  width: 0;
  flex: 0 0 auto;
  overflow: hidden;
  background: var(--color-white);
  border-right: 1px solid var(--gfe-line);
  color: var(--gfe-ink);
  transition: width .22s cubic-bezier(.32, .72, 0, 1);
}

.gfe--panelOpen .gfe__panel { width: 400px; }

.gfe__panelInner {
  display: flex;
  flex-direction: column;
  width: 400px;
  height: 100%;
}

.gfe__panelHead {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--gfe-line);
  flex: none;
}

.gfe__panelTitle {
  font-size: 14px; line-height: 22px;
  font-weight: 600;
  color: var(--color-gray-800);
}

/* 🔴 스크롤은 **여기 하나뿐**이다. 절마다 스크롤을 가지면, 값 하나를 고치고 자리를
   보려는 손이 패널 안에서 어느 칸을 굴릴지부터 골라야 한다. */
.gfe__panelBody {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.gfe__pane[hidden] { display: none; }

/* 고른 것이 없을 때 그 탭에 세우는 안내. */
.gfe__idle { padding: 20px 16px; }

.gfe__idleHead {
  margin: 0 0 4px;
  font-size: 14px; line-height: 22px;
  font-weight: 600;
  color: var(--color-gray-700);
}

.gfe__idleBody {
  margin: 0;
  font-size: 12px;
  line-height: 20px;
  color: var(--gfe-ink-faint);
}

/* ---- 넣기 ---- */

.gfe__addGrid {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.gfe__add {
  display: grid;
  grid-template-columns: 32px 1fr;
  grid-template-rows: auto auto;
  align-items: center;
  gap: 0 10px;
  padding: 10px 12px;
  text-align: left;
  border: 1px solid var(--gfe-line) !important;
  border-radius: 10px;
  background: var(--color-white);
  cursor: pointer;
}

.gfe__add:hover {
  border-color: var(--gfe-accent-soft) !important;
  background: var(--color-gray-100);
}

.gfe__addMark {
  grid-row: 1 / 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: var(--gfe-line-soft);
  color: var(--color-gray-700);
  font-size: 14px;
  line-height: 1;
}

.gfe__addLabel { font-size: 14px; line-height: 22px; font-weight: 600; color: var(--color-gray-800); }
.gfe__addHint { font-size: 11px; line-height: 16px; color: var(--gfe-ink-faint); }

/* ---- 놓인 것 ---- */

/* ⚠ 목록이 이제 밝은 패널 안에 있다. §79 까지는 어두운 레일 안이라 색을 뒤집어 두었는데,
   그 색을 그대로 두면 흰 바탕에서 배지가 안 읽힌다. */
.gfe__layer {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px !important;
  border-radius: 8px;
  background: none;
  text-align: left;
  cursor: pointer;
}

.gfe__layer + .gfe__layer { margin-top: 2px; }
.gfe__layer:hover:not([aria-selected='true']) { background: var(--gfe-line-soft); }

.gfe__layer[aria-selected='true'] {
  background: var(--color-blue-100);
  box-shadow: inset 2px 0 0 var(--gfe-accent);
}

.gfe__layerKind {
  flex: none;
  font-size: 11px; line-height: 16px;
  font-weight: 700;
  padding: 2px 4px;
  border-radius: 3px;
}

.gfe__layerKind--text { background: var(--color-purple-100); color: var(--color-purple-900); }
.gfe__layerKind--image { background: var(--color-blue-300); color: var(--color-blue-900); }
.gfe__layerKind--shape { background: var(--color-green-100); color: var(--color-green-800); }

.gfe__layerText { flex: 1; min-width: 0; }

.gfe__layerName {
  display: block;
  font-size: 12px; line-height: 20px;
  color: var(--color-gray-700);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gfe__layerPeek {
  display: block;
  font-size: 11px; line-height: 16px;
  color: var(--gfe-ink-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gfe__layerWarn {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-orange-600);
}

.gfe__empty {
  font-size: 12px;
  color: var(--gfe-ink-faint);
  text-align: center;
  padding: 20px 8px;
  line-height: 20px;
  margin: 0;
}

/* ---- 캔버스 ---- */

/* 🔴 바탕이 **밝은 회색**이다. §79 까지는 `#0a0c10` 이었는데, 그것은 어드민 편집기의
   값이고 고객 편집기는 `bg-gray-50` 이다. 종이가 흰색이라 대비가 옅어 보이지만,
   그 옅음이 맞다 - 벽에 걸리는 것이 흰 종이이고, 편집기가 어두우면 점주가 화면에서
   본 밝기와 실제 밝기를 다르게 기억한다.

   🔴 세로는 **위쪽에 붙인다** (젠시라이트 `transformOrigin: top center`). 가운데 세우면
   종이가 칸보다 클 때 위아래가 같이 잘리고, 그때 굴려도 **잘린 위쪽으로는 못 올라간다**
   - 그리드가 음수 자리로 밀어낸 몫이라 스크롤 범위 밖이다. 가로만 가운데다. */
.gfe__stage {
  flex: 1 1 0;
  min-width: 0;
  position: relative;
  overflow: auto;
  display: grid;
  place-items: start center;
  padding: 32px;
  background: var(--color-gray-100);
  min-width: 0;
}

/* 종이 그림자. 밝은 바닥이라 §79 의 `rgba(0,0,0,.5)` 는 너무 무겁다 - 어두운 바닥에서
   종이를 띄우려고 쓰던 값이고, 흰 바탕에서는 종이 주위가 회색으로 번져 보인다. */
.gfe__paper {
  position: relative;
  background: var(--color-white);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .08), 0 8px 24px rgba(0, 0, 0, .08);
}

.gfe__canvas { display: block; }

/* 선택한 요소 위에 얹히는 테두리와 손잡이. 캔버스에 그리지 않고 DOM 으로 올린다 -
   캔버스에 그리면 저장할 그림에 선택 표시가 같이 구워진다. */
.gfe__sel {
  position: absolute;
  border: 1.5px solid var(--gfe-accent);
  pointer-events: none;
}

.gfe__handle {
  position: absolute;
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  background: var(--color-white);
  border: 1.5px solid var(--gfe-accent);
  border-radius: 2px;
  pointer-events: auto;
  touch-action: none;
}

.gfe__handle--nw { cursor: nwse-resize; }
.gfe__handle--ne { cursor: nesw-resize; }
.gfe__handle--sw { cursor: nesw-resize; }
.gfe__handle--se { cursor: nwse-resize; }

/* 끄는 동안에만 뜨는 자리·크기 표. 손이 캔버스에 있을 때 필요한 숫자는 캔버스에 둔다. */
.gfe__badge {
  position: absolute;
  transform: translateY(-100%);
  margin-top: -6px;
  padding: 4px 8px;
  border-radius: 8px;
  background: var(--gfe-accent);
  color: var(--color-white);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  pointer-events: none;
}

/* 격자선. 조판이 쓰는 정렬 축을 눈에 보이게 한다 - 이것이 없으면 사람이 만든 화면만
   축이 흩어져서, 생성한 것과 고친 것이 다른 제품처럼 보인다.
   ⚠ 평소에는 거의 안 보일 만큼 옅다. 끌기 시작하면 진해진다 - 축은 **붙일 자리를 찾는
     동안에만** 쓸모가 있다. */
.gfe__guide {
  position: absolute;
  background: rgba(10, 143, 245, .14);
  pointer-events: none;
  transition: background .12s ease;
}

.gfe__paper--dragging .gfe__guide { background: rgba(10, 143, 245, .5); }

.gfe__guide--v { width: 1px; top: 0; bottom: 0; }
.gfe__guide--h { height: 1px; left: 0; right: 0; }

/* ---- 패널 안의 부품 ---- */

/* 고른 요소의 머리. 타입 배지 + 이름. 왼쪽 목록의 배지와 같은 뜻이지만 밝은 바탕이라
   색을 뒤집는다 - 어두운 쪽 색을 그대로 쓰면 밝은 바탕에서 안 읽힌다. */
.gfe__pick {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--gfe-line-soft);
  flex: none;
}

.gfe__pickKind {
  font-size: 11px; line-height: 16px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 3px;
}

.gfe__pickKind--text { background: var(--color-purple-100); color: var(--color-purple-900); }
.gfe__pickKind--image { background: var(--color-blue-300); color: var(--color-blue-900); }
.gfe__pickKind--shape { background: var(--color-green-100); color: var(--color-green-800); }

.gfe__pickName {
  font-size: 12px; line-height: 20px;
  font-weight: 500;
  color: var(--color-gray-800);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 아코디언 절. 젠시라이트의 `SectionAccordion` 그대로다. */
.gfe__acc { border-top: 1px solid var(--gfe-line-soft); }

.gfe__accHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  font: inherit;
  font-size: 11px; line-height: 16px;
  font-weight: 600;
  letter-spacing: .25px;
  color: var(--gfe-ink-faint);
  background: none;
  border: none;
  padding: 12px 16px;
  cursor: pointer;
  text-align: left;
}

.gfe__accHead:hover { background: var(--color-gray-100); }

/* ⚠ 화살표는 글자(▼ ▶)가 아니라 선으로 그린 꺾쇠다. 유니코드 삼각형은 글꼴마다 크기와
   기준선이 갈려서, 절 제목의 대문자 라벨 옆에 놓으면 어떤 PC 에서는 반 칸 내려앉는다. */
.gfe__accMark {
  color: var(--gfe-ink-faint);
  display: flex;
  align-items: center;
}

.gfe__accIcon { width: 11px; height: 11px; display: block; }

.gfe__accBody { padding: 0 16px 16px; }
.gfe__accBody[hidden] { display: none; }

/* 한 줄 - 라벨이 위, 칸이 아래. 젠시라이트의 `NumberInput` 문법이다. */
.gfe__field { margin-top: 10px; }
.gfe__field:first-child { margin-top: 2px; }

.gfe__fieldLabel {
  display: block;
  font-size: 11px; line-height: 16px;
  letter-spacing: .25px;
  color: var(--gfe-ink-faint);
  margin-bottom: 4px;
}

/* 두 칸을 나란히. 크기와 굵기처럼 짧은 것끼리 묶는다.
   🔴 안쪽 칸의 위 여백을 **0 으로 눌러 줄 간격을 바깥이 맡는다.** 안 그러면 `:first-child`
      규칙 때문에 왼쪽 칸만 2px, 오른쪽 칸은 10px 이 되어 **X 와 Y 가 8px 어긋나 선다.**
      실측으로 잡았다 - 값이 같은 두 칸인데 바닥이 안 맞으면 잘못 그린 화면으로 읽힌다. */
.gfe__pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: 10px;
}

.gfe__pair > .gfe__field,
.gfe__lockRow > .gfe__field { margin-top: 0; }

.gfe__input,
.gfe__select {
  font: inherit;
  font-size: 12px; line-height: 20px;
  width: 100%;
  box-sizing: border-box;
  height: 32px;
  padding: 0 8px;
  color: var(--gfe-ink);
  background: var(--gfe-field);
  border: 1px solid var(--gfe-line);
  border-radius: 8px;
}

.gfe__input:hover,
.gfe__select:hover { border-color: var(--color-gray-400); }

.gfe__input:focus,
.gfe__select:focus {
  border-color: var(--color-blue-500);
  background: var(--color-white);
  outline: none;
}

.gfe__textarea {
  font: inherit;
  font-size: 12px;
  width: 100%;
  box-sizing: border-box;
  resize: vertical;
  min-height: 66px;
  line-height: 16px;
  padding: 8px 8px;
  color: var(--gfe-ink);
  background: var(--gfe-field);
  border: 1px solid var(--gfe-line);
  border-radius: 8px;
}

.gfe__textarea:focus { border-color: var(--color-blue-500); background: var(--color-white); outline: none; }

/* 숫자 칸. 젠시라이트의 `controls/NumberInput` 이다 - 평소에는 값과 단위만 보이고,
   누르면 그 자리가 입력 칸이 된다.

   🔴 `<input type="number">` 를 안 쓴다. 브라우저가 붙이는 스피너가 칸 오른쪽을
   차지해서, 260px 패널에 두 칸을 나란히 놓으면 숫자 세 자리가 가려진다. 게다가 단위
   글자(px)를 넣을 자리가 없어 「440」이 무엇의 440 인지 점주가 모른다. */
.gfe__num {
  display: flex;
  align-items: center;
  /* 🔴 28px 은 젠시라이트 `TextTab` 숫자 칸의 `py-1.5 text-xs` 다. 400px 패널로
     넓히면서 다른 칸을 32px 로 키웠는데, **이 칸만은 정본이 작다** - 숫자 칸 둘이
     한 줄에 나란히 서기 때문이다. */
  height: 28px;
  padding: 0 8px;
  box-sizing: border-box;
  font-size: 12px; line-height: 20px;
  background: var(--gfe-field);
  border: 1px solid var(--gfe-line);
  border-radius: 8px;
  transition: border-color .12s, background-color .12s;
}

.gfe__num:hover { border-color: var(--color-gray-400); }

.gfe__num:focus-within { border-color: var(--color-blue-500); background: var(--color-white); }

.gfe__numValue {
  flex: 1;
  min-width: 0;
  color: var(--gfe-ink);
  cursor: text;
  user-select: none;
  font-variant-numeric: tabular-nums;
}

.gfe__numUnit {
  flex: none;
  margin-left: 4px;
  font-size: 11px; line-height: 16px;
  color: var(--gfe-ink-faint);
}

.gfe__numInput {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 12px; line-height: 20px;
  font-variant-numeric: tabular-nums;
  color: var(--gfe-ink);
  background: transparent;
  border: none;
  outline: none;
  padding: 0;
}

/* 글 맞춤. 라벨 없이 한 줄을 꽉 채운다 - 아이콘 셋이 왼쪽·가운데·오른쪽을 그대로
   그리므로 「맞춤」이라고 적어 줄 필요가 없다. */
.gfe__align { display: flex; gap: 2px; }

.gfe__alignBtn {
  flex: 1;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 8px;
  background: var(--color-gray-150);
  color: var(--gfe-ink-sub);
  cursor: pointer;
}

.gfe__alignBtn:hover:not([aria-pressed='true']) { background: var(--color-gray-200); }

.gfe__alignBtn[aria-pressed='true'] { background: var(--color-gray-900); color: var(--color-white); }

.gfe__alignIcon { width: 13px; height: 13px; display: block; }

/* 너비와 높이, 그 사이에 비율 잠금. 가운데 칸을 28px 로 못 박아 사슬 단추가 양쪽
   숫자 칸과 같은 높이로 바닥에 선다 (`align-items: end`). 정본은
   `sections/LayoutSection` 의 `grid-cols-[1fr_28px_1fr]` 이다. */
.gfe__lockRow {
  display: grid;
  grid-template-columns: 1fr 28px 1fr;
  align-items: end;
  gap: 4px;
  margin-top: 10px;
}

.gfe__lock {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 8px;
  background: var(--color-gray-150);
  color: var(--gfe-ink-sub);
  cursor: pointer;
}

.gfe__lock:hover:not([aria-pressed='true']) { background: var(--color-gray-200); }

.gfe__lock[aria-pressed='true'] { background: var(--color-blue-300); color: var(--gfe-accent); }

.gfe__linkIcon { width: 12px; height: 12px; display: block; }

/* 절 맨 아래의 전체폭 단추 (「위치 초기화」). 칩과 달리 테두리가 없고 회색으로 찬다 -
   한 번 누르면 여러 값이 같이 움직이는 것이라, 한 칸짜리 칩과 같은 무게로 보이면 안 된다. */
.gfe__wide {
  width: 100%;
  height: 32px;
  margin-top: 10px;
  font: inherit;
  font-size: 11px; line-height: 16px;
  border: none;
  border-radius: 8px;
  background: var(--color-gray-150);
  color: var(--gfe-ink-sub);
  cursor: pointer;
}

.gfe__wide:hover:not(:disabled) { background: var(--color-gray-200); color: var(--gfe-ink); }
.gfe__wide:disabled { color: var(--color-gray-400); cursor: default; }

/* 세그먼트 - 선택지가 서넛뿐인 것. 젠시라이트의 `AlignButtons` 처럼 **고른 것이 검게**
   채워진다. 파랑은 저장과 고른 줄이 이미 쓰고 있어서, 여기까지 파랗게 하면 화면에
   파란 것이 넷이 되어 어느 것이 지금 중요한지 안 보인다. */
.gfe__seg { display: flex; gap: 2px; }

.gfe__seg > button {
  flex: 1;
  font: inherit;
  font-size: 11px; line-height: 16px;
  height: 32px;
  border: none;
  border-radius: 8px;
  background: var(--color-gray-150);
  color: var(--gfe-ink-sub);
  cursor: pointer;
  white-space: nowrap;
}

.gfe__seg > button:hover:not([aria-pressed='true']) { background: var(--color-gray-200); }

.gfe__seg > button[aria-pressed='true'] {
  background: var(--color-gray-900);
  color: var(--color-white);
  font-weight: 500;
}

/* 크기 스테퍼. 조판이 쓰는 아홉 단을 오르내린다 - 계단 밖으로 나갈 길이 없다. */
.gfe__stepper {
  display: flex;
  align-items: center;
  height: 32px;
  background: var(--gfe-field);
  border: 1px solid var(--gfe-line);
  border-radius: 8px;
  overflow: hidden;
}

.gfe__stepper > button {
  font: inherit;
  font-size: 14px; line-height: 22px;
  width: 32px;
  height: 100%;
  border: none;
  background: none;
  color: var(--gfe-ink-sub);
  cursor: pointer;
}

.gfe__stepper > button:hover:not(:disabled) { background: var(--color-gray-200); color: var(--gfe-ink); }
.gfe__stepper > button:disabled { color: var(--color-gray-400); cursor: default; }

.gfe__stepperValue {
  flex: 1;
  text-align: center;
  font-size: 12px; line-height: 20px;
  font-variant-numeric: tabular-nums;
  color: var(--gfe-ink);
}

/* 칩 - 한 번 눌러 끝나는 것(가운데 세우기 · 순서 바꾸기). 젠시라이트의 `PresetChips` 다. */
.gfe__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.gfe__chip {
  font: inherit;
  font-size: 11px; line-height: 16px;
  padding: 4px 9px;
  border: 1px solid var(--gfe-line);
  border-radius: 8px;
  background: var(--color-white);
  color: var(--color-gray-700);
  cursor: pointer;
  white-space: nowrap;
}

.gfe__chip:hover { border-color: var(--color-blue-500); color: var(--gfe-accent); }
.gfe__chip--danger:hover { border-color: var(--color-red-300); color: var(--color-red-800); }

.gfe__swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

/* ⚠ 테두리를 진하게 둔다. 팔레트에 흰색이 있고 패널 바탕도 흰색이라, 옅은 선으로는
   **흰 칸이 빈 자리처럼 보인다** - 점주가 고를 수 있는 색을 하나 못 본다. */
.gfe__swatch {
  width: 24px;
  height: 24px;
  border-radius: 8px;
  border: 1px solid var(--color-gray-500);
  cursor: pointer;
  padding: 0;
}

.gfe__swatch[aria-pressed='true'] {
  outline: 2px solid var(--gfe-accent);
  outline-offset: 1px;
}

/* 고를 수 없는 표시용 칩. 「이 기기가 낼 수 있는 색」 줄에 쓴다 - 누르는 것이 아니라
   보는 것이라 손 모양이 바뀌면 안 된다. */
.gfe__swatch--flat { cursor: default; width: 20px; height: 20px; border-color: var(--color-gray-400); }

.gfe__hint {
  font-size: 11px;
  line-height: 16px;
  color: var(--gfe-ink-faint);
  margin: 7px 0 0;
  white-space: pre-line;
}

.gfe__warn {
  font-size: 11px;
  line-height: 16px;
  color: var(--color-orange-1000);
  background: var(--color-orange-100);
  border-radius: 8px;
  padding: 8px 8px;
  margin: 8px 0 0;
}

/* 아무것도 안 골랐을 때 절 위에 놓는 한 줄.
   🔴 이 자리는 절이 아니다. 번호 붙인 안내 셋을 아코디언에 담았더니 260px 패널이
   통째로 설명문이 되어, 젠시라이트 편집기와 가장 안 닮아 보이는 자리가 여기였다. */
.gfe__idle {
  font-size: 11px;
  line-height: 16px;
  color: var(--gfe-ink-faint);
  margin: 0;
  padding: 10px 12px 2px;
}

/* ---- 기기에서 보기 ---- */

.gfe__peek {
  position: absolute;
  inset: 0;
  background: rgba(10, 12, 16, .72);
  display: grid;
  place-items: center;
  z-index: 5;
}

.gfe__peekBox {
  background: var(--color-white);
  color: var(--gfe-ink);
  border-radius: 8px;
  padding: 16px;
  max-width: min(92%, 900px);
  max-height: 88%;
  overflow: auto;
  box-shadow: 0 12px 48px rgba(0, 0, 0, .5);
}

.gfe__peekHead {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

.gfe__peekHead h3 { margin: 0; font-size: 14px; line-height: 22px; font-weight: 600; }

.gfe__peekGap { flex: 1; }

/* 기기가 실제로 낼 색만 남은 그림이다. 브라우저가 부드럽게 늘리면 없는 색이 생겨
   보여서, 그 순간 이 화면이 거짓말을 한다. */
.gfe__peekImg {
  display: block;
  max-width: 100%;
  image-rendering: pixelated;
  border: 1px solid var(--gfe-line);
}

/* 편집기는 넓이가 있어야 세 칸이 선다. 좁으면 캔버스가 사실상 사라지므로 아예 막고
   그 사실을 말한다 - 쓸 수 없는 화면을 띄우는 것보다 낫다.
   🔴 **1024 는 `web/app.html` 의 `EDITOR_MIN_WIDTH` 와 같은 값이어야 한다.** 첫 판은
      여기가 960 이라, 1000px 창에서 관리 화면은 「1024 이상에서 열어 주십시오」라고
      막는데 이 문구는 「960 이상이면 된다」고 말했다. 한쪽만 고치면 또 갈린다. */
.gfe__tooNarrow {
  display: none;
  padding: 32px;
  text-align: center;
  color: var(--gfe-ink-sub);
  line-height: 22px;
}

@media (max-width: 1023px) {
  .gfe { grid-template-rows: 1fr; grid-template-areas: 'narrow'; }
  .gfe__bar, .gfe__body { display: none; }
  .gfe__tooNarrow { display: block; grid-area: narrow; align-self: center; }
}

/* ============================================================ v78: 빌려 온 값 폼
 *
 * 🔴 **관리 화면의 값 폼 DOM 을 그대로 들여온다** (계약 §78, 대표님 지시 2026-09-14 -
 *    「젠시라이트의 에디터의 uiux로 적용하자고 않았나」). 앱 열둘의 폼은 검증 · 카운터 ·
 *    예시 단추 · 3벌 i18n 까지 이미 그쪽에 서 있어서, 편집기 쪽에 한 벌 더 만들면 두
 *    벌이 갈린다. 대신 **모양만 여기서 다시 입힌다** - 관리 화면은 640px 폼이고 이 칸은
 *    400px 패널이라, 그쪽 여백과 글자 크기를 그대로 쓰면 칸이 잘리고 줄이 넘친다.
 *
 * ⚠ 관리 화면 쪽 클래스(`.card` · `.field` · `.lbl` · `.hint`)를 고치지 않는다. 여기서
 *   덮어쓰기만 한다 - 그 클래스는 만들기 화면 전체가 쓰고 있어, 건드리면 편집기를 한
 *   번도 안 연 화면까지 같이 바뀐다. */
.gfe-appForm { display: block; }

.gfe__contentBody { padding: 16px; }

/* 카드 테두리를 지운다. 절 안에 카드가 또 있으면 테두리가 두 겹이 되어 패널이 더 좁아
   보이고, 젠시라이트 패널에는 카드라는 층이 없다. */
.gfe-appForm .card,
.gfe-appForm details.card {
  border: none;
  box-shadow: none;
  background: none;
  padding: 0;
  margin: 0 0 4px;
  border-radius: 0;
}

/* 앱 이름과 만들기 단추는 뺀다. 화면 이름은 상단바에 있고, 저장은 상단바 단추 하나가
   값과 자리를 같이 맡는다 - 저장 단추가 둘이면 어느 쪽이 무엇을 저장하는지 모른다. */
.gfe-appForm h2,
.gfe-appForm [data-make-btn] { display: none; }

/* 템플릿 칩도 뺀다. 양식을 바꾸는 것은 문서를 통째로 갈아 끼우는 일이라, 옮겨 둔 자리가
   전부 사라진다. 양식은 만들 때 고르는 것이고 여기서는 안 바꾼다. */
.gfe-appForm .chips { display: none; }
.gfe-appForm [id$="-tpl-field"] { display: none; }

.gfe-appForm .field,
.gfe-appForm label.field { display: block; margin: 0 0 14px; }

.gfe-appForm .lbl {
  display: block;
  font-size: 11px; line-height: 16px;
  font-weight: 400;
  letter-spacing: .25px;
  color: var(--gfe-ink-faint);
  margin: 0 0 4px;
}

.gfe-appForm input[type="text"],
.gfe-appForm input[type="number"],
.gfe-appForm input[type="time"],
.gfe-appForm input[type="date"],
.gfe-appForm input[type="datetime-local"],
.gfe-appForm select {
  font: inherit;
  font-size: 12px; line-height: 20px;
  width: 100%;
  box-sizing: border-box;
  height: 32px;
  min-height: 32px;
  padding: 0 8px;
  margin: 0;
  color: var(--gfe-ink);
  background: var(--gfe-field);
  border: 1px solid var(--gfe-line);
  border-radius: 8px;
}

.gfe-appForm textarea {
  font: inherit;
  font-size: 12px;
  width: 100%;
  box-sizing: border-box;
  resize: vertical;
  min-height: 66px;
  line-height: 16px;
  padding: 8px 8px;
  margin: 0;
  color: var(--gfe-ink);
  background: var(--gfe-field);
  border: 1px solid var(--gfe-line);
  border-radius: 8px;
}

.gfe-appForm input:focus,
.gfe-appForm select:focus,
.gfe-appForm textarea:focus {
  border-color: var(--color-blue-500);
  background: var(--color-white);
  outline: none;
}

.gfe-appForm .hint,
.gfe-appForm .tiny {
  font-size: 11px;
  line-height: 16px;
  color: var(--gfe-ink-faint);
  margin: 4px 0 0;
}

/* 접는 칸(브레이크 · 회의 등록)은 절 안의 작은 접기로 줄인다.
   🔴 화살표를 **절 머리와 같은 꺾쇠**로 맞춘다. 값 칸은 편집기 절 바로 아래에 서므로,
      여기만 유니코드 삼각형이면 한 패널에 화살표 두 종류가 보인다. 글자로 그린 삼각형은
      글꼴마다 크기와 기준선이 갈려 실제로 한 칸 내려앉아 보였다 (2026-09-14 눈 검수). */
.gfe-appForm details.fold > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11px; line-height: 16px;
  font-weight: 600;
  letter-spacing: .25px;
  color: var(--gfe-ink-sub);
  padding: 8px 0;
  cursor: pointer;
  list-style: none;
}

.gfe-appForm details.fold > summary::-webkit-details-marker { display: none; }

/* 선 두 개를 45도 돌려 만든 꺾쇠. 접히면 오른쪽, 펼치면 아래를 가리킨다. */
.gfe-appForm details.fold > summary::after {
  content: '';
  flex: none;
  width: 6px;
  height: 6px;
  margin-right: 3px;
  border-right: 1.6px solid var(--gfe-ink-faint);
  border-bottom: 1.6px solid var(--gfe-ink-faint);
  transform: rotate(-45deg);
}

.gfe-appForm details.fold[open] > summary::after {
  transform: rotate(45deg);
  margin: -3px 3px 0 0;
}
.gfe-appForm .fold-body { padding: 0; }

/* 두 칸을 나란히 놓던 줄은 260px 에서 겹쳐 놓으면 둘 다 못 읽는다 - 세로로 쌓는다. */
.gfe-appForm .row { display: block; }
.gfe-appForm .row > .field { margin-bottom: 10px; }

/* 예시 · 프리셋 단추. 편집기의 `gfe__chip` 과 같은 모양으로 맞춘다. */
.gfe-appForm .preset,
.gfe-appForm button.sm {
  font: inherit;
  font-size: 11px; line-height: 16px;
  padding: 4px 8px;
  border: 1px solid var(--gfe-line);
  background: var(--color-white);
  border-radius: 8px;
  color: var(--gfe-ink-sub);
  cursor: pointer;
}

.gfe-appForm .preset:hover,
.gfe-appForm button.sm:hover { border-color: var(--color-gray-400); background: var(--gfe-line-soft); }


/* ===================================================== gency.ai 무드 (2026-09-23)
   대표님 - 「에디터도 들어가보고 디자인 ui 모두 따라해」. gency.ai 편집기에서 잰 값이다.
   짜임(위 막대 · 64px 레일 · 패널 · 캔버스)은 이미 같아서 값만 옮긴다.
   - 레일 칸 56x56, 반경 8, 활성은 #F5FBFF 바탕 + 파랑. 라벨 11px.
   - 캔버스 바닥은 #EEF0F2 - 흰 종이가 회색 위에 뜬다.
   - 주 단추(다운로드 · 저장)는 파랑 #0A8FF5, 반경 8. */
.gfe { background: var(--color-gray-200); }
.gfe__rail { align-items: center; padding: 8px 0; gap: 4px; border-right-color: var(--color-gray-200); }
.gfe__railBtn { width: 56px; height: 56px; padding: 0; border-radius: 8px; gap: 4px; }
.gfe__railBtn:hover:not([aria-selected='true']) { background: var(--color-gray-150); color: var(--color-gray-900); }
.gfe__railBtn[aria-selected='true'] { background: var(--color-blue-50); color: var(--color-blue-600); }
.gfe__railLabel { font-size: 11px; }
.gfe__stage { background: var(--color-gray-200); }
.gfe__primary { background: var(--color-blue-600); border-radius: 8px; }
.gfe__primary:hover:not(:disabled) { background: var(--color-blue-750); }
.gfe__bar { border-bottom-color: var(--color-gray-200); }
