/* 운영 화면. 기준은 2026-10-03 전체 화면 정렬 시안(htmldocs/endocab-ui-ref/screens-gen.py)이고, 영업팀 PDF(2025.11.04) 14쪽을 같은 규칙으로 다시 그린 것이다.
   파이는 1280 x 720을 돌려서 내보내므로 화면은 세로 720 x 1280이다. 모든 좌표는 이 720 x 1280 화소 기준이고, 창 크기가 다르면 common.js가 통째로 줄이거나 늘린다.
   공통 규칙: 바깥 여백 48, 제목 0~152, 본문 152~1056, 아래 단추 1088~1220(132 정사각형 네 자리 x=48, 212, 376, 540),
   모서리 28(칸, 패널, 단추, 탭)과 14(설정 줄, 숫자판, 표), 그림자는 아래 4px 진한 남색 한 가지 */
html, body { margin: 0; height: 100%; background: #3b65b5; overflow: hidden; }
.screen { position: absolute; left: 0; top: 0; width: 720px; height: 1280px; transform-origin: 0 0; background: #3b65b5; overflow: hidden;
  font-family: Carlito, Calibri, Arial, "Noto Sans CJK KR", "Noto Sans KR", Pretendard, sans-serif; user-select: none; -webkit-user-select: none; }
.screen div, .screen b, .screen button, .screen section { box-sizing: border-box; }
.view { position: absolute; inset: 0; }
.view[hidden] { display: none; }
.view > * { position: absolute; }

/* 제목(0~152). 나머지 화면은 60px */
.t { left: 48px; right: 48px; top: 0; height: 152px; display: flex; align-items: center; justify-content: center; color: #fff; font-weight: 700; font-size: 60px; letter-spacing: 1px; white-space: nowrap; text-transform: uppercase; }
/* 기본화면 제목은 작게 왼쪽에, 오른쪽에는 현재 온도를 크게 둔다(2026-10-05 사용자 지시). 위 8~40은 버전 표지 자리라 40부터 쓴다 */
.t.big { top: 40px; right: auto; height: 112px; justify-content: flex-start; font-size: 34px; text-transform: none; }
.temp { right: 48px; top: 40px; height: 112px; display: flex; align-items: center; color: #fff; font-size: 72px; font-weight: 700; white-space: nowrap; }

/* 기본화면 채널 칸(296 x 202). 색은 요구사항과 매뉴얼의 네 가지를 따른다(2026-10-05 사용자 지시 "칸 색을 회색, 주황, 녹색, 노랑에 맞춰. 최대한 강렬한 색으로"):
   대기(Ready) 회색, 건조 중(Drying) 주황, 보관 중(Storage) 녹색, 재처리(Reprocess) 노랑. 근거는 SRS-01 428~431행, SRS-03 120~123행,
   요구사항 시트 Rev.0 353~356행, 사용자 매뉴얼 Rev1.1.1 59~62행. 그전의 하늘색, 연두, 초록, 빨강은 영업팀 PDF(2025.11.04) 그림을 따른 것이었다.
   번호 글자는 요구사항 시트대로 회색에 검정, 주황과 녹색에 흰색. 노랑은 시트가 흰색이라 적었으나 읽히지 않아 검정으로 둔다.
   오른쪽 위 점은 바람이 흐르면 초록 */
.ch { width: 296px; height: 202px; border-radius: 28px; background: #8e8e8e; box-shadow: 0 4px 0 #24467f; display: flex; align-items: center; justify-content: center; color: #000; font-size: 132px; font-weight: 700; line-height: 1; cursor: pointer; }
.ch i { position: absolute; top: 22px; right: 22px; width: 34px; height: 34px; border-radius: 50%; background: #fff; box-shadow: 0 0 0 4px #24467f33; }
.ch i.on { background: #00c853; box-shadow: 0 0 0 5px #fff; }
.ch.dr { background: #ff6a00; color: #fff; }
.ch.st { background: #00b140; color: #fff; }
.ch.ex { background: #ffe500; color: #000; }
/* 재처리 칸의 상태 글자(번호 아래). 글자가 있으면 번호를 조금 올린다. 긴 말(러시아어, 폴란드어)은 작게 */
.ch em { position: absolute; left: 8px; right: 8px; bottom: 16px; text-align: center; font-style: normal; font-size: 34px; font-weight: 700; line-height: 1; white-space: nowrap; overflow: hidden; }
.ch em:empty { display: none; }
.ch.ex { padding-bottom: 40px; }
:root:lang(ru) .ch em { font-size: 24px; }
:root:lang(pl) .ch em { font-size: 30px; }

/* 아래 그림 단추(132 x 132). 색은 자리마다 다르다 */
.k { top: 1088px; width: 132px; height: 132px; border: 0; padding: 0; border-radius: 28px; box-shadow: 0 4px 0 #24467f; display: flex; align-items: center; justify-content: center; cursor: pointer; }
.k[hidden] { display: none; }
.k svg { width: 88px; height: 88px; }
.k.s0 { left: 48px; } .k.s1 { left: 212px; } .k.s2 { left: 376px; } .k.s3 { left: 540px; }
.k.or { background: #e8650f; } .k.ye { background: #f2b600; } .k.gy { background: #8f8f8f; } .k.gr { background: #4f9a2c; }
.k:active, .ch:active, .pk:active, .kk:active, .tab:active { filter: brightness(0.88); }

/* 설정과 날짜 화면의 줄(이름 384 x 64, 값 224 x 64, 줄 간격 76). 고른 줄은 이름이 남색, 값은 흰 바탕에 빨간 글씨와 빨간 테두리 */
.rn, .rv { height: 64px; border-radius: 14px; background: #d6e6f6; box-shadow: 0 3px 0 #24467f; display: flex; align-items: center; color: #000; font-size: 36px; white-space: nowrap; overflow: hidden; cursor: pointer; }
.rn { left: 48px; width: 384px; padding-left: 24px; }
.rv { left: 448px; width: 224px; justify-content: center; font-weight: 700; }
.rn.act { background: #1f3864; color: #fff; }
.rv.act { background: #fff; color: #c62828; box-shadow: 0 0 0 5px #c62828; }
.rv.fixed, .rn.fixed { cursor: default; }
/* 숫자를 넣는 중이면 숫자 뒤에 깜빡이는 막대 */
.caret { display: inline-block; width: 4px; height: 1.2em; margin-left: 3px; background: currentColor; vertical-align: -0.2em; animation: caret-blink 1s steps(1) infinite; }
@keyframes caret-blink { 50% { opacity: 0; } }
/* 이탈리아어는 항목 이름이 길어 작게 둔다 */
:root:lang(it) .rn { font-size: 28px; }

/* 숫자판, 기록 필터, 문자판을 담는 패널 */
.panel { left: 48px; width: 624px; border-radius: 28px; background: #9dc3e6; box-shadow: 0 4px 0 #24467f; }
.panel > * { position: absolute; }
.pk { border-radius: 14px; background: #e4e4e4; box-shadow: 0 3px 0 #6b7f99; display: flex; align-items: center; justify-content: center; color: #000; font-size: 44px; font-weight: 700; cursor: pointer; }
.pk.sel { background: #404040; color: #fff; }
.pk.off { font-size: 36px; }
/* 러시아어 ОТКЛ은 36px에서 단추(89px)보다 넓다(97px). 30px면 81px로 들어간다. */
html[lang="ru"] .pk.off { font-size: 30px; }
/* 폴란드어 WYŁ.은 36px에서 90px로 단추보다 1px 넓다. 32px면 80px. */
html[lang="pl"] .pk.off { font-size: 32px; }
.kk { border-radius: 10px; background: #e4e4e4; box-shadow: 0 3px 0 #6b7f99; display: flex; align-items: center; justify-content: center; color: #000; font-size: 34px; font-weight: 700; cursor: pointer; }
.keypad, .dtpad { top: 856px; height: 200px; }
.qwerty { top: 600px; height: 456px; }
.qwerty[hidden] { display: none; }

/* 등록과 목록의 두 칸(304 x 88). 고르지 않은 쪽은 진한 파랑 */
.tab { top: 152px; width: 304px; height: 88px; border-radius: 28px; background: #d6e6f6; box-shadow: 0 4px 0 #24467f; display: flex; align-items: center; justify-content: center; color: #000; font-size: 40px; font-weight: 700; white-space: nowrap; text-transform: uppercase; cursor: pointer; }
.tab.off { background: #2b5aa8; color: #c9dcf2; box-shadow: inset 0 0 0 3px #c9dcf255; }
.tab[data-kind=endoscope] { left: 48px; } .tab[data-kind=operator] { left: 368px; }
/* 등록 칸(이름 232, 값 376). 값 칸을 누르면 문자판이 뜬다 */
.reg-form { display: contents; }
.reg-form[hidden] { display: none; }
.reg-form > * { position: absolute; }
.reg-form .rn { width: 232px; cursor: default; }
.reg-form .rv { left: 296px; width: 376px; font-weight: 400; white-space: pre; }
.reg-form .rv.long { font-size: 26px; }
:root:lang(it) .reg-form .rn { font-size: 30px; }

/* 목록과 기록 표. 흰 바탕 안에 머리줄(진회색)과 56px 간격의 줄. 고른 줄은 남색 */
.tb { left: 48px; width: 624px; border-radius: 14px; background: #fff; }
.tb .lhead { position: absolute; left: 4px; top: 4px; }
.tb .lbody { position: absolute; left: 4px; top: 60px; width: 616px; overflow-y: auto; overflow-x: hidden; scrollbar-width: none; }
.tb .lbody::-webkit-scrollbar { display: none; }
.lrow { display: grid; column-gap: 4px; height: 52px; }
.lbody .lrow { margin-bottom: 4px; }
.lrow span { display: flex; align-items: center; justify-content: center; min-width: 0; overflow: hidden; white-space: nowrap; font-size: 27px; letter-spacing: -0.5px; background: #efefef; color: #000; }
.lhead span { background: #595959; color: #fff; font-weight: 700; }
.lbody .lrow.on span { background: #1f3864; color: #fff; }
.lbody .lrow[data-id], .lbody .lrow[data-key] { cursor: pointer; }
.tb[data-kind=endoscope] .lrow { grid-template-columns: 45px 181px 175px 199px; }
.tb[data-kind=operator] .lrow { grid-template-columns: 70px 205px 162px 162px; }
.tb.rtable .lrow { grid-template-columns: 45px 168px 193px 193px; }
/* 바코드 겹창 아래의 고르기 목록(이름, 등록번호) */
.tb.ptable .lrow { grid-template-columns: 300px 312px; }
.tb.ptable { box-shadow: 0 8px 24px #000a; }
/* 줄이 표보다 많으면 아래 끝에 남은 줄 수를 알린다 */
.tb .more { position: absolute; right: 12px; bottom: 6px; padding: 0 12px; border-radius: 10px; background: #1f3864; color: #fff; font-size: 22px; line-height: 34px; }
.tb .more[hidden] { display: none; }

/* 화면을 어둡게 덮는 겹창(바코드 입력, 확인). 레이아웃은 밀지 않는다 */
.dim { position: absolute; left: 0; top: 0; width: 720px; height: 1280px; background: #0b1a3aa6; z-index: 6; }
.dim[hidden] { display: none; }
/* 키 잠금 중 화면 전체를 덮어 눌림을 받는 투명한 막(keylock.js). 겹창과 배너보다 위, 누른 자리 표시보다 아래. */
#keylock-shield { position: absolute; left: 0; top: 0; width: 720px; height: 1280px; z-index: 40; }
#keylock-shield[hidden] { display: none; }
#keylock-shield > .k { position: absolute; left: 210px; top: 490px; width: 300px; height: 300px; border-radius: 60px; box-shadow: 0 8px 0 #24467f, 0 0 0 10px #ffffff66; cursor: default; }
#keylock-shield > .k svg { width: 200px; height: 200px; }
.dim > * { position: absolute; }
.pop { left: 80px; width: 560px; border-radius: 28px; background: #eef3fa; box-shadow: 0 8px 24px #000a; }
.pl { left: 112px; width: 496px; height: 48px; display: flex; align-items: center; justify-content: center; color: #000; font-size: 38px; font-weight: 700; }
.pi { box-sizing: border-box; left: 112px; width: 496px; height: 72px; border: 0; outline: 0; border-radius: 14px; background: #fff; box-shadow: inset 0 0 0 3px #7f8fa6; text-align: center; font: inherit; font-size: 36px; color: #000; caret-color: #000; padding: 0 16px; }
.pi.focus { box-shadow: inset 0 0 0 5px #1f3864; }
.cq { left: 112px; top: 500px; width: 496px; height: 120px; display: flex; align-items: center; justify-content: center; text-align: center; color: #000; font-size: 40px; font-weight: 700; line-height: 1.25; overflow-wrap: anywhere; }
.confirm .pk { top: 652px; width: 236px; height: 80px; text-transform: uppercase; }

/* 위쪽에 겹쳐 뜨는 안내 배너. 화면을 밀지 않는다 */
/* 배너는 누르기를 가로채지 않는다(밑의 단추와 기록 제목 5초 누르기가 그대로 된다) */
.banner { pointer-events: auto; position: absolute; left: 48px; right: 48px; top: 16px; z-index: 8; padding: 18px 24px; border-radius: 14px; background: #1f3864f2; color: #fff; font-family: "Noto Sans CJK KR", "Noto Sans KR", Pretendard, sans-serif; font-size: 32px; line-height: 1.35; text-align: center; box-shadow: 0 4px 0 #0b1a3a; }
.banner[hidden] { display: none; }
.banner.error { background: #a11a1af2; }
/* 비상 정지 배너(emergency.js). 걸려 있는 동안 늘 보인다. 버전 표지(z 30)는 가리지 않고 눌림은 받지 않는다 */
.banner.emergency { z-index: 29; pointer-events: none; border: 4px solid #fff; background: #a11a1a; }
.banner.emergency b { display: block; font-size: 40px; }
.banner.emergency span { display: block; font-size: 28px; }

/* 소프트웨어 버전. 오른쪽 위에 떠 있는 표지로 늘 보인다(2026-10-04 사용자 지시: 아래 띠에 두지 말고 오른쪽 위에 눈에 띄게). 겹창이 떠도 가리지 않고, 화면 배치에는 자리를 차지하지 않으며 터치도 받지 않는다 */
.version-bar { position: absolute; left: 10px; right: 10px; top: 8px; height: 32px; z-index: 30; display: flex; justify-content: flex-end; align-items: center; column-gap: 8px; pointer-events: none; }
.version { flex: 0 0 auto; height: 32px; padding: 0 12px; display: flex; align-items: center; border-radius: 16px; background: #ffd21f; color: #10203f; box-shadow: 0 2px 6px #0b1a3a80; font-family: "Roboto Mono", ui-monospace, monospace; font-size: 20px; font-weight: 700; letter-spacing: 0; white-space: nowrap; pointer-events: none; }
/* 마지막 커밋 제목(2026-10-04 사용자 지시 "커밋메시지도 보여줘"). 시각 표지 왼쪽에 한 줄로 두고 넘치면 말줄임표로 자른다 */
.version.subject { flex: 0 1 auto; min-width: 0; display: block; line-height: 32px; overflow: hidden; text-overflow: ellipsis; background: #fff1a8; font-family: "Noto Sans CJK KR", "Noto Sans KR", Pretendard, sans-serif; }
.version.subject:empty { display: none; }
.version:empty { display: none; }

/* 끌기나 확대로 터치를 가로채지 않게 한다. 밀어서 보는 곳은 표뿐이다 */
html, body, .screen { touch-action: none; }
.lbody { touch-action: pan-y; }
/* 마우스 커서 숨김(touch.js의 setCursorVisible). 단추마다 준 손 모양 커서보다 앞선다 */
.hide-cursor, .hide-cursor * { cursor: none !important; }
/* 누른 자리 표시(touch.js). 원이 퍼지며 사라진다 */
.touch-ripple { position: fixed; z-index: 50; width: 20vmin; height: 20vmin; margin: -10vmin 0 0 -10vmin; box-sizing: border-box; border-radius: 50%; border: 0.9vmin solid #fff; background: #ffffff55; box-shadow: 0 0 0 0.4vmin #1f386488; pointer-events: none; animation: touch-ripple 450ms ease-out forwards; }
@keyframes touch-ripple { from { transform: scale(0.15); opacity: 1; } to { transform: scale(1); opacity: 0; } }
[role=button]:focus-visible, button:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }

/* 패널 고유 해상도(세로 600 x 1024). 장비의 LCD는 1024 x 600이다. 창이 정확히 600 x 1024이면 native.js가 이 파일과 screen.html의
   720 x 1280 좌표를 600 x 1024 화소로 옮겨 적는다(가로 600/720배, 세로와 글자 0.8배, 정수 반올림). 이 블록은 그 규칙으로
   안 되는 자리만 정한다. native.js는 @media 안을 건드리지 않으므로 여기 값은 600 x 1024 화소 그대로다.
   아래 단추는 106 정사각형 네 자리(x=40, 178, 316, 454, 간격 32), 잠금 그림은 240 정사각형을 가운데(x=180)에 둔다. */
@media (width: 600px) and (height: 1024px) {
  .k.s0 { left: 40px; } .k.s1 { left: 178px; } .k.s2 { left: 316px; } .k.s3 { left: 454px; }
  #keylock-shield > .k { left: 180px; }
  /* 배너 줄 높이는 글자 크기의 1.35배(26 x 1.35 = 35.1)라 줄 수에 따라 높이가 소수가 된다. 정수로 둔다 */
  .banner { line-height: 35px; }
  /* 폴란드어 사용자 등록의 INSTYTUCJA가 29px에서 이름 칸(193)보다 6px 넓다. 27px면 들어간다(720 x 1280에서도 14px 넘치지만 그쪽 규칙은 그대로 둔다) */
  :root:lang(pl) .reg-form .rn { font-size: 27px; }
}
