/* N3 UI (.uif) DOM rendering — see apps/web/client/ui/uif-dom.ts */
/* Fonts: var(--ko-font-sans) comes from /fonts/fonts.css (bundled web fonts, apps/web/client/ui/font-map.ts); pages load it first. */
/* The 1024x768 native canvas is fitted as one unit; portrait space is letterboxed, never stretched.
   These selectors override the old fixed-footer inline rules without changing source UIF coordinates. */
html body:has(> #viewport) { display: flex; flex-direction: column; height: 100vh; height: 100dvh; min-width: 0; }
body > #viewport { flex: 1 1 0; width: 100%; height: auto; min-height: 0; }
body > #footer { flex: 0 0 auto; box-sizing: border-box; width: 100%; height: auto; min-height: 24px; flex-wrap: wrap; gap: 4px 12px; padding: 0 8px; }
body > #footer > * { min-width: 0; max-width: 100%; }
html body > #log { bottom: var(--ko-footer-height, 24px); }
.native-stage-layout-notice { position: absolute; left: 12px; right: 12px; top: 12px; z-index: 1; max-width: 34em; margin: 0 auto; color: #bfb8a8; font: 13px/1.45 var(--ko-font-sans); text-align: center; pointer-events: none; }
.native-stage-layout-notice[hidden] { display: none; }
.browser-audio-controls { flex-wrap: wrap; }
.uif-root { position: absolute; overflow: visible; }
.n3 { position: absolute; box-sizing: border-box; pointer-events: none; }
.n3-clickable { pointer-events: auto; cursor: pointer; }
.n3-clickable:focus { outline: 1px dotted #d9b76a; }
.n3-disabled { cursor: default; filter: grayscale(.4) brightness(.8); }
/* An IMAGE without a usable texture draws nothing, like the native CN3UIImage (empty edit/NPC-choice button images).
   uif-dom.ts keeps data-missing-texture="<path>" and UifView.missingTextures for diagnostics; no visible outline. */
.n3-missing-texture { outline: none; }
.n3-input { position: absolute; left: 4px; top: 0; width: calc(100% - 8px); height: 100%; margin: 0; padding: 0; border: 0; background: transparent; outline: none; pointer-events: auto; color: #fff; caret-color: #ffe600; }
.n3-list-items { position: absolute; inset: 0; overflow: hidden; pointer-events: auto; }
.n3-list-item { padding: 0 6px; line-height: 1.3; cursor: pointer; white-space: nowrap; overflow: hidden; }
.n3-list-item:hover { background: #ffffff14; }
.n3-list-item.selected { background: #d9b76a33; }
.screen-character { position: absolute; inset: 0; background: #000; }
.character-scene-canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; touch-action: none; }
.screen-character > .uif-root { z-index: 1; }
.character-scene-status { position: absolute; top: 8px; left: 260px; right: 260px; z-index: 3; padding: 6px 10px; background: #000b; color: #f3d7a3; font: 13px/1.35 var(--ko-font-sans); text-align: center; pointer-events: none; }
.screen-character [hidden] { display: none !important; }
.n3-button-hit { position: absolute; pointer-events: auto; background: transparent; }
.screen-world { background: #000; }
.world-canvas { width: 100%; height: 100%; position: absolute; inset: 0; touch-action: none; }
/* Game gestures own selection/drag; real text fields retain browser editing. */
#viewport { user-select: none; -webkit-user-select: none; }
#viewport input, #viewport textarea, #viewport [contenteditable="true"], #viewport [contenteditable=""] { user-select: text; -webkit-user-select: text; }
#viewport img { -webkit-user-drag: none; }
.world-hud { position: absolute; inset: 0; pointer-events: none; }
/* World stacking, one place together with world-names.ts: 3D canvas -> name labels -> HUD UIF windows -> item tooltip
   (body-level, below) -> .world-exit-menu / disconnect view. Every panel mounted into .world-hud is a UifView root
   (hp, target, hotkey, inventory, dropped, taskbar, NPC shop, skills, revival); panels with their own inline z-index
   (shop 50/55, skills 20, revival 100, hotbar drag ghost) stay above this baseline. Names remain visible behind windows. */
.world-hud > .world-names { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.world-hud > .uif-root { position: absolute; z-index: 1; }
/* Native item-info window: Client/UI_US/Co_ItemInfo_us.uif (SHA256 57c4fbe2d12b…) is a 256px-wide root with a 굴림체 13px bold
   title and 11px lines; its background tile in ui\ui_message.dxt is plain black at alpha 187/255; row colours come from the
   EXE palette at 0051421E..005142B4. Border colour, 15px line pitch and 6/8px padding are sampled/estimated from the native
   screenshot, not proven pixel-equal. z-index 1000 clears the transformed #stage and the letterbox notice (z 1). */
.ko-item-tooltip { position: fixed; left: 0; top: 0; z-index: 1000; box-sizing: border-box; max-width: 256px; padding: 6px 8px;
  background: rgba(0, 0, 0, .733); border: 1px solid #867545; color: #fff; pointer-events: none; user-select: none;
  font: 11px/15px var(--ko-font-sans); text-align: left; white-space: nowrap; }
.ko-item-tooltip[hidden] { display: none; }
.ko-item-tooltip__title { font-size: 13px; font-weight: bold; line-height: 17px; text-align: center; white-space: normal; }
.ko-item-tooltip__kind { text-align: center; margin-bottom: 6px; }
.ko-item-tooltip__line { white-space: normal; min-height: 15px; }
/* UISTYLE_STRING_ALIGNCENTER rows of the item-info builder (tradeability 0051A5B1, description "*...*" 0051A6FE/0051A8D0). */
.ko-item-tooltip__line--center { text-align: center; }
/* Inventory PointerEvent drag (inventory-view.ts bindInventoryDrag): picked-up source is dimmed, the slot under the pointer
   is outlined (gold = the swap passes the local placement rule, red = the controller would refuse it), and the item icon
   follows the pointer as a body-level fixed layer above the tooltip. !important wins over the inline click-select outline. */
.ko-inventory-slot[data-drag-source="true"] { opacity: .35; }
.ko-inventory-slot[data-drop-target="valid"] { outline: 1px solid #d8c081 !important; }
.ko-inventory-slot[data-drop-target="invalid"] { outline: 1px solid #ff3c3c !important; }
.ko-item-drag-icon { position: fixed; z-index: 1001; pointer-events: none; object-fit: fill; user-select: none; }
.world-load-status { position: absolute; z-index: 5; top: 100px; left: 220px; right: 220px; color: #ffe8b8; background: #000a; font: 13px/1.4 var(--ko-font-sans); text-align: center; }
.world-load-status:empty { display: none; }
.world-exit-menu { z-index: 10; }
.screen-world [hidden] { display: none !important; }
.browser-audio-controls { display: inline-flex; align-items: center; gap: 4px; }
.browser-audio-controls input[type="range"] { width: 58px; }
.character-entry-fade { position: absolute; inset: 0; z-index: 50; background: #000; pointer-events: none; }
/* Native chat (co_chatting_box_us.uif, text0) and information (co_information_box_us.uif, text_message) text regions.
   Rows use the 10pt Gulim UIF font as 13px at 96 DPI; newest line at the bottom, 255-line pools (EXE 005968DC/0057744F).
   Wrapping by the browser at the region width is an adaptation of the native per-pixel line split. */
.ko-text-lines { position: absolute; left: 0; right: 0; bottom: 0; white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-all; }
.ko-text-line { margin: 0; padding: 0; }
.ko-chat-window .ko-chat-input { caret-color: #fff; }
/* Text rows sit in base_area, clipped to the text region (Render viewport) and bottom-anchored with whole rows only
   (EXE 00596742..00596774); the region lets clicks through to the world like the native base_area (0059442C). */
.ko-text-clip { position: absolute; overflow: hidden; pointer-events: none; }
.ko-text-band { position: absolute; left: 0; right: 0; bottom: 0; overflow: hidden; }
/* Window region of the chat/information frame minus base_area (clip-path hole): blocks the world under the frame and
   starts a move inside the root's movable rectangle (info-view.ts NativeWindowFrame). */
.ko-window-hit { position: absolute; pointer-events: auto; touch-action: none; }
.ko-chat-window [data-id="img_sizechange"], .ko-info-window [data-id="img_sizechange"] { touch-action: none; }
/* Display states 2/3 hide base_chat / base_msgwnd (vtable +54); the chat edit and its img_edit1 icon are still drawn
   while editing (Render 0059B339..0059B397), so they keep their own inline display. */
.ko-frame-hidden > :not([data-id="edit0"]):not([data-id="img_edit1"]) { display: none !important; }
.ko-chat-window.ko-frame-off > [data-id="base_filter"] { display: none !important; }
/* Visible filter popup belongs to the window region (00598BB4..00598C10). */
.ko-chat-window > [data-id="base_filter"] { pointer-events: auto; }
