/* Ashveil UI kit — base BEM components for the in-game interface.
   Consumes design tokens from tokens.css (--ui-*). Load BOTH after the legacy css.
   Convention: .ui-block, .ui-block__element, .ui-block--modifier. No inline styles, no tables for layout.
   Grow this file per migrated block; keep components generic + token-driven. */

/* ── Button ────────────────────────────────────────────────────────────────
   The one button. The game had four looks for the same control -- raw OS chrome
   (the 360-odd unclassed inputs), a dark .btn, a parchment .btnnew/.btnnew2, and
   a grey bold .btnnew3 -- so the same action looked different depending on which
   screen you were standing on. Rather than touch ~390 markup sites, the base is
   bound to the elements themselves and the legacy class names are kept as bare
   aliases. ui-kit.css loads after main.css in the shell, so this wins there;
   standalone legacy pages that never load the kit keep their old look.
   Use a modifier only when the action genuinely differs in weight. */
.ui-btn,
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
.btn,
.btnnew,
.btnnew2,
.btnnew3,
.knopka {
	display: inline-block;
	padding: var(--ui-space-2) var(--ui-space-4);
	border: 1px solid var(--ui-border-soft);
	border-radius: var(--ui-radius);
	background: var(--ui-btn-bg);
	color: var(--ui-btn-text);
	font: bold var(--ui-fs) var(--font-ui);
	line-height: 1.35;
	text-decoration: none;
	text-align: center;
	cursor: pointer;
	transition: background .12s ease, border-color .12s ease;
}
.ui-btn:hover,
button:hover,
input[type="button"]:hover,
input[type="submit"]:hover,
input[type="reset"]:hover,
.btn:hover,
.btnnew:hover,
.btnnew2:hover,
.btnnew3:hover,
.knopka:hover {
	background: var(--ui-btn-bg-hover);
	border-color: var(--ui-border);
	color: var(--ui-text-strong);
}
/* Pressed state: the legacy OS button had real depth and players read it as
   feedback. One pixel of travel is enough to keep that without a skeuomorph. */
.ui-btn:active,
button:active,
input[type="button"]:active,
input[type="submit"]:active,
input[type="reset"]:active,
.btn:active,
.btnnew:active,
.btnnew2:active,
.btnnew3:active,
.knopka:active { transform: translateY(1px); }

.ui-btn:focus-visible,
button:focus-visible,
input[type="button"]:focus-visible,
input[type="submit"]:focus-visible,
input[type="reset"]:focus-visible {
	outline: 2px solid var(--ui-link);
	outline-offset: 1px;
}

.ui-btn[disabled],
button[disabled],
input[type="button"][disabled],
input[type="submit"][disabled],
input[type="reset"][disabled],
.ui-btn--disabled {
	opacity: .45;
	cursor: default;
	transform: none;
	background: var(--ui-btn-bg);
	border-color: var(--ui-border-soft);
	color: var(--ui-btn-text);
}

/* Modifiers. --primary is the one action a screen wants you to take; --danger is
   destructive and unrecoverable (a stat reset, a deletion). Never both. */
.ui-btn--primary {
	background: var(--ui-surface-accent);
	border-color: #bfa96b;
	color: var(--ui-text-strong);
}
.ui-btn--primary:hover { background: #fffbef; border-color: #a8904f; }

.ui-btn--danger { color: var(--ui-danger); border-color: #c9a3a3; }
.ui-btn--danger:hover { background: #f6e7e7; border-color: var(--ui-danger); color: var(--ui-danger); }

.ui-btn--sm { padding: var(--ui-space-1) var(--ui-space-3); font-size: var(--ui-fs-sm); }
.ui-btn--block { display: block; width: 100%; }

/* ── Form field ────────────────────────────────────────────────────────────
   The same treatment the button got: bind the base to the elements, so the ~230
   unclassed text fields, selects and textareas across the game stop wearing raw OS
   chrome, and keep .ui-field__control as an explicit alias for markup that names it.
   Buttons are excluded — they have their own base above. */
.ui-field { display: flex; flex-direction: column; gap: var(--ui-space-1); margin-bottom: var(--ui-space-3); }

.ui-field__control,
input[type="text"],
input[type="password"],
input[type="number"],
input[type="email"],
input[type="search"],
input[type="url"],
input[type="tel"],
input:not([type]),
select,
textarea {
	padding: var(--ui-space-2) var(--ui-space-3);
	border: 1px solid var(--ui-border);
	border-radius: var(--ui-radius-sm);
	background: var(--ui-input-bg);
	color: var(--ui-input-text);
	font: var(--ui-fs) var(--font-ui);
	/* The padding this base adds must eat into the field, not grow it. Legacy popups
	   size their input to the box (width:100% or a fixed px), so without this the field
	   grew by the padding and spilled out of the window that framed it. */
	box-sizing: border-box;
	max-width: 100%;
}

.ui-field__control:focus,
input[type="text"]:focus,
input[type="password"]:focus,
input[type="number"]:focus,
input[type="email"]:focus,
input[type="search"]:focus,
input[type="url"]:focus,
input[type="tel"]:focus,
input:not([type]):focus,
select:focus,
textarea:focus { outline: 2px solid var(--ui-link); outline-offset: -1px; }

.ui-field__control[disabled],
input[disabled],
select[disabled],
textarea[disabled] { opacity: .55; cursor: default; }

textarea { resize: vertical; }

/* ── Inline helpers ────────────────────────────────────── */
.ui-faint { color: var(--ui-text-faint); }

/* Authenticated game frame page shell. */
.game-main-page {
	padding-top: 0;
	margin-top: 7px;
	height: 100%;
	background-color: #dedede;
	background-image: url("/assets/img/bgmain.jpg");
}

/* Authenticated game shell overlay primitives. */
.ui-shell-hidden { display: none; }
.ui-shell-layer { position: absolute; }
.ui-shell-layer--tooltip { z-index: 1111; }
.ui-shell-layer--person-menu { z-index: 1110; }
.ui-shell-layer--windows { z-index: 1101; }
.ui-noscript-warning { text-align: center; }

/* Authenticated frame shell: chat/topbar fragments migrated from buttons.php. */
#qsst {
	position: absolute;
	z-index: 10000000;
	cursor: default;
	display: none;
}

#onbon {
	position: absolute;
	z-index: 100;
	cursor: default;
	display: none;
	bottom: 30px;
	left: 18px;
}

#mini_qsst {
	position: absolute;
	z-index: 100;
	cursor: default;
	display: none;
	bottom: 10px;
	right: 18px;
}

.chat-settings__title {
	text-align: center;
}

.game-resize-cap {
	display: block;
	height: 4px;
	background-repeat: repeat;
}

.game-resize-cap--left {
	position: absolute;
	float: left;
	width: 9px;
	background-image: url("/assets/img/lite/_top_24.gif");
}

.game-resize-cap--right {
	float: right;
	width: 10px;
	background-image: url("/assets/img/lite/_top_28.gif");
}

/* Topbar — flexbox with restored light Combats-style textures (three-strip: 14+17+6=37px). */
.game-topbar {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 31px;
	/* Two rows like the legacy bar: 14px dark cap strip on top, 17px stone
	   texture at the bottom. One style everywhere — no per-city variants. */
	background:
		url("/assets/img/topbar/bg-main.webp") repeat-x left bottom,
		url("/assets/img/topbar/bg-top.webp") repeat-x left top #333;
	box-shadow: 0 1px 3px rgba(0, 0, 0, .35);
	z-index: 10;
}

/* Full-width thin strip under the bar, like the legacy bottom-strip row. */
.game-topbar::after {
	content: "";
	position: absolute;
	top: 31px;
	left: 0;
	right: 0;
	height: 6px;
	background: url("/assets/img/topbar/bg-strip.webp") repeat-x;
}

.game-topbar__logo {
	position: absolute;
	top: 5px; /* drop the wordmark onto the stone strip (lower 17px row) */
	left: 12px;
	z-index: 3;
}

.game-topbar__logo img {
	display: block;
	height: 36px;
	width: auto;
	filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .55));
}

.game-topbar__mail {
	position: absolute;
	left: 260px;
	top: 13px;
	width: 24px;
	height: 15px;
	background: url("/assets/img/topbar/icon-mail.webp") no-repeat center;
}

.game-topbar__panel {
	position: absolute;
	top: 0;
	right: 0;
	width: 446px;          /* fixed width — prevents menu items jumping when switching tabs */
}

.game-topbar__tabs {
	position: relative;
	height: 14px;
	background: url("/assets/img/topbar/bg-tabs.webp") repeat-x;
	padding: 0 37px 0 31px; /* room for the carved stone end caps */
	display: flex;
	flex-wrap: nowrap;
	justify-content: flex-end;
}

.game-topbar__menus {
	position: relative;
	height: 17px;
	background: url("/assets/img/topbar/bg-menu.webp") repeat-x;
	padding: 0 22px 0 20px; /* room for the carved stone end caps */
	display: flex;
	align-items: center;
	justify-content: flex-end;
	white-space: nowrap;
	font-size: 10px;
	line-height: 1;
}

/* Inter's deep descenders push the baseline toward the strip below; nudge the
   visible menu row up so the links read centered on the stone face. */
.game-topbar__menus > span {
	position: relative;
	top: -2px;
}

/* Carved stone end caps, absolute at the row edges like the legacy GIF cells. */
.game-topbar__deco {
	position: absolute;
	top: 0;
	display: block;
}

.game-topbar__deco--tabs-left,
.game-topbar__deco--menu-left {
	left: 0;
}

.game-topbar__deco--tabs-right,
.game-topbar__deco--menu-right {
	right: 0;
}

.game-topbar__deco--tabs-left,
.game-topbar__deco--tabs-right {
	height: 14px;
}

.game-topbar__deco--menu-left,
.game-topbar__deco--menu-right {
	height: 17px;
}

.game-topbar-tab {
	padding: 0 12px;
	height: 14px;
	line-height: 14px;
	font-size: 10px;
	font-weight: bold;
	color: #f0f0f0;
	cursor: pointer;
	border-left: 1px solid #777;   /* CSS separator, replaces the legacy GIF mennu112_09 */
}

.game-topbar-tab:first-child {
	border-left: 0;
}

.game-topbar-tab:hover {
	color: #ffffff;
	background-color: #404040;
}

.game-topbar__menus .menutop {
	color: #3B3936;
	font-weight: bold;
	text-decoration: none;
}

.game-topbar__menus .menutop:hover {
	color: var(--ui-text-muted);
}

.game-frame-shell {
	width: 100%;
	height: 100%;
	border-collapse: collapse;
	border-spacing: 0;
}

.game-frame-shell td {
	padding: 0;
}

.game-frame-top-spacer {
	height: 31px;
	background-color: #D6D6D6;
}

.game-frame-top-spacer--left {
	width: 9px;
}

.game-frame-top-spacer--right {
	width: 12px;
}

.game-frame-side {
	background-color: #D6D6D6;
}

.game-frame-side--left {
	background-image: url("/assets/img/lite/_top_24.gif");
}

.game-frame-side--right {
	background-image: url("/assets/img/lite/_top_28.gif");
}

.game-main-cell {
	vertical-align: top;
	background-color: var(--ui-shop-section);
}

.game-main-frame-wrap {
	/* The topbar's 6px stone strip is drawn by ::after, outside the bar's 31px box,
	   so the flow never reserved room for it and the screen started 3px UNDERNEATH
	   the strip. Give back the strip, then a little air. */
	margin-top: 14px;
	/* Keep #main-region's absolute partial overlay inside the main viewport. */
	position: relative;
	overflow: hidden;
}

.game-main-frame {
	display: block;
	padding: 0;
	margin: 0;
	width: 100%;
	border: 0;
}

.game-chat-shell {
	width: 100%;
	height: 100%;
	border-collapse: collapse;
	border-spacing: 0;
	border-top: 1px solid #CCCCCC;
}

.game-chat-shell td {
	padding: 0;
}

.game-chat-cell {
	height: 40%;
	vertical-align: top;
	background-color: #eeeeee;
}

.game-chat-block {
	position: relative;
	display: block;
	border-top: 1px solid #808080;
	vertical-align: top;
}

.game-chat-mini-settings {
	cursor: pointer;
}

.game-chat-menus {
	position: absolute;
	right: 0;
	top: 3px;
	padding-right: 20px;
	height: 18px;
	text-align: right;
	white-space: nowrap;
}

.game-chat-menu-table {
	margin-top: -3px;
	float: right;
}

.game-chat-menu {
	text-align: right;
	white-space: nowrap;
}

.game-chat-scroll-spacer {
	width: 3px;
}

.game-smiles-popup {
	z-index: 1100;
}

.game-chat-list,
.game-online-list {
	cursor: default;
}

.game-online-cell {
	width: 240px;
	vertical-align: top;
	background-color: #faf2f2;
	border-left: 2px solid #CCCCCC;
	border-top: 1px solid #808080;
}

.game-online-actions {
	margin-top: 5px;
	text-align: center;
}

.game-online-room {
	padding: 0 0 8px 0;
	font-size: 10pt;
	color: var(--ui-heading);
}

.game-online-options {
	border-top: #cac2c2 solid 1px;
	padding: 5px;
	margin-top: 5px;
}

.game-chat-input-edge {
	height: 30px;
	background-color: #D6D6D6;
}

.game-chat-input-edge--left {
	vertical-align: bottom;
}

.game-chat-input-edge--right {
	text-align: right;
}

.game-chat-input-edge__img {
	width: 9px;
	height: 30px;
}

.game-chat-input-bar {
	height: 30px;
	background-color: #E9E9E9;
	background-image: url("/assets/img/buttons/chat_bg.gif");
}

.game-chat-toolbar {
	width: 100%;
	height: 26px;
	border-collapse: collapse;
	border-spacing: 0;
}

.game-chat-toolbar td {
	padding: 0;
}

.game-chat-toolbar-button {
	width: 30px;
}

.game-chat-toolbar-icon {
	width: 30px;
	height: 30px;
}

.game-chat-toolbar-spacer--small {
	width: 6px;
}

.game-chat-toolbar-spacer--tiny {
	width: 5px;
}

.game-chat-toolbar-spacer--medium {
	width: 10px;
}

.game-chat-toolbar-explode {
	width: 16px;
	background-color: #BAB7B3;
}

.game-chat-toolbar-explode__img {
	width: 16px;
	height: 30px;
}

.game-chat-trader-cell {
	width: 100px;
	text-align: center;
}

.game-chat-trader {
	width: 90%;
	margin-left: -2px;
	padding: 2px;
	border: 1px solid #CCCCCC;
}

.game-chat-input {
	width: 100%;
	margin-bottom: 2px;
	font-size: 9pt;
}

/* The frame's bottom edge. Its texture was still being asked for at the site root -- a path from
   before the assets moved under /assets -- so every game page fetched a 404 for it. */
.game-frame-bottom {
	height: 5px;
	background-color: #D6D6D6;
	background-image: url("/assets/img/sand_mid_31.png");
}

/* Location item cards injected into the parent chat frame by main.php. */
.game-location-items-error {
	padding: 10px;
}

.game-location-item {
	display: inline-block;
	width: 80px;
	height: 80px;
	text-align: center;
}

.game-location-item--state-0 {
	background-color: #e5e5e5;
}

.game-location-item--state-0:hover,
.game-location-item--state-1:hover {
	background-color: #d5d5d5;
	text-align: center;
}

.game-location-item--state-1 {
	background-color: #d5d5e5;
}

.game-location-item--state-2 {
	background-color: #FFD700;
}

.game-location-item--state-2:hover {
	background-color: #DAA520;
	text-align: center;
}

.game-location-item__outer {
	display: table;
	position: absolute;
	width: 80px;
	height: 80px;
}

.game-location-item__middle {
	display: table-cell;
	vertical-align: middle;
}

.game-location-item__inner {
	margin-left: auto;
	margin-right: auto;
	width: 80px;
}

/* ── Section title (centered heading) ──────────────────── */
.ui-title {
	margin: var(--ui-space-3) 0;
	text-align: center;
	color: var(--ui-heading);
	font-size: var(--ui-fs-lg);
	font-weight: bold;
}

/* ── Divider ───────────────────────────────────────────── */
.ui-divider { margin: var(--ui-space-3) 0; border: 0; border-top: 1px solid var(--ui-line); }
/* The short rules the profile draws inside a column. They were bare 1px divs with a hardcoded grey
   and a hardcoded width -- the same line, said three different ways. */
.ui-divider--narrow { max-width: 240px; }

/* ── Profile data (anketa): label: value rows ──────────── */
.ui-anketa { line-height: 11pt; }
.ui-anketa__label { font-weight: bold; color: var(--ui-text-label); }
.ui-anketa__icon { display: inline-block; vertical-align: bottom; }

/* ── Character stats: padded box + dynamic-colour stat value ── */
.ui-statbox { padding: var(--ui-space-3); }
.ui-stat__value { color: var(--stat-c, inherit); } /* --stat-c set inline per stat (buff/debuff gradient) */
.ui-clanhead { color: var(--ui-clanhead); }

/* ── Tabs ──────────────────────────────────────────────────
   A row of sections, one of them current. Screens built this out of table cells with
   hardcoded percentage widths and a two-letter class (.m / .s) for "current". */
.ui-tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 1px;
	margin: 0 0 var(--ui-space-4);
	border-bottom: 2px solid var(--ui-border-soft);
}

.ui-tabs__tab {
	flex: 1 1 auto;
	padding: var(--ui-space-2) var(--ui-space-4);
	border: 1px solid var(--ui-border-soft);
	border-bottom: none;
	border-radius: var(--ui-radius-sm) var(--ui-radius-sm) 0 0;
	background: var(--ui-surface);
	color: var(--ui-link);
	font: bold var(--ui-fs) var(--font-ui);
	text-align: center;
	text-decoration: none;
	white-space: nowrap;
}
.ui-tabs__tab:hover { background: var(--ui-btn-bg-hover); }

.ui-tabs__tab--active {
	position: relative;
	bottom: -2px;
	background: var(--ui-surface-accent);
	border-color: #bfa96b;
	border-bottom: 2px solid var(--ui-surface-accent);
	color: var(--ui-text-strong);
}

/* ── Pager ─────────────────────────────────────────────── */
.ui-pager {
	display: flex;
	justify-content: space-between;
	gap: var(--ui-space-4);
	margin: var(--ui-space-4) 0;
}

.ui-empty {
	margin: var(--ui-space-6) 0;
	text-align: center;
	color: var(--ui-text-muted);
}

/* ── Battle lobby (поединки) ───────────────────────────── */
.zv-lobby { padding: var(--ui-space-3) var(--ui-space-4) 0; }

.zv-list { line-height: 1.6; }

/* Day stepper on the finished-battles log: previous | date | next. */
.zv-daynav {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--ui-space-4);
	margin-bottom: var(--ui-space-3);
}
.zv-daynav__title { margin: 0; text-align: center; }

.zv-filter {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: var(--ui-space-3);
	margin-bottom: var(--ui-space-4);
}
.zv-filter label { display: inline-flex; align-items: center; gap: var(--ui-space-2); }

.zv-lobby__head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--ui-space-4);
	margin-bottom: var(--ui-space-3);
}
.zv-lobby__me { min-width: 0; }

/* ── Page head ─────────────────────────────────────────────
   Title on the left, its one action on the right. Screens used to do this with a
   two-cell table whose only job was to push a button to the far side. */
.ui-page-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--ui-space-4);
	margin: 0 0 var(--ui-space-4);
}
.ui-page-head__title { margin: 0; }

/* ── Form field grid (2-col label/control, replaces field tables) ── */
.ui-form { display: grid; grid-template-columns: max-content 1fr; gap: var(--ui-space-2) var(--ui-space-3); align-items: center; margin: var(--ui-space-3) 0; }
.ui-form--top { align-items: flex-start; } /* tall fields (textarea, datepicker) align labels to row top */
.ui-field__control--wide { width: 95%; }
.ui-float-right { float: right; }
.ui-form__label { text-align: right; color: var(--ui-text); }
.ui-form__actions { grid-column: 1 / -1; margin-top: var(--ui-space-2); }
.ui-fieldset { max-width: 480px; } /* constrain the settings form block width */

/* ── Twink-avatar highlight ────────────────────────────── */
.ui-twink { color: var(--ui-twink); }

/* ── Zodiac / alignment side panel ─────────────────────── */
.ui-zodiac { float: right; }
.ui-zodiac__inner { text-align: center; }
.ui-zodiac__sign { padding: var(--ui-space-3); }
.ui-zodiac__flag { padding: var(--ui-space-3); }

/* ── Centered block (search etc.) ──────────────────────── */
.ui-center { text-align: center; }

/* ── Bank (location) — scoped element styles ───────────── */
/* Migrated from inline <style> in bank.php: the fieldset/hr pair was duplicated
   verbatim across two blocks → collapsed here. A third .pay block was dead
   (no class="pay" element existed) → dropped, not migrated. Scoped to .ui-bank
   so global <fieldset>/<hr> on other pages (changepass, anketa, …) stay intact.
   Literal greys kept from the legacy markup (no token role for this border). */
.ui-bank fieldset { border: 1px solid #AEAEAE; }
.ui-bank hr { border: 0; border-bottom: 1px solid #aeaeae; }

/* ── Bank account rows ─────────────────────────────────── */
.ui-bankrow { padding: var(--ui-space-3); border-bottom: 1px solid var(--ui-border); }
.ui-bankrow--inline { display: inline-block; }
.ui-bankrow--active { background: var(--ui-surface); }
.ui-bankrow__num { display: inline-block; width: 75px; }
.ui-bankrow__amount { display: inline-block; width: 100px; }
.ui-bankrow__col { display: inline-block; }

/* ── Alerts / warnings ─────────────────────────────────── */
.ui-warn { color: var(--ui-warn); }
.ui-alert { color: var(--ui-warn); background: var(--ui-alert-bg); }

/* ── Effects panel (centered block) ────────────────────── */
.ui-effects { display: block; text-align: center; }

/* ── Chat-colour picker: per-value option swatches ──────── */
/* User-facing colour palette (not theme roles) → literal named colours,
   one rule per option value, matching the saved ChatColor string. */
.ui-chatcolor option { background: #f2f0f0; }
.ui-chatcolor option[value="Black"] { color: black; }
.ui-chatcolor option[value="Blue"] { color: blue; }
.ui-chatcolor option[value="Fuchsia"] { color: fuchsia; }
.ui-chatcolor option[value="Gray"] { color: gray; }
.ui-chatcolor option[value="Green"] { color: green; }
.ui-chatcolor option[value="Maroon"] { color: maroon; }
.ui-chatcolor option[value="Navy"] { color: navy; }
.ui-chatcolor option[value="Olive"] { color: olive; }
.ui-chatcolor option[value="Purple"] { color: purple; }
.ui-chatcolor option[value="Teal"] { color: teal; }
.ui-chatcolor option[value="Orange"] { color: orange; }
.ui-chatcolor option[value="Chocolate"] { color: chocolate; }
.ui-chatcolor option[value="DarkKhaki"] { color: darkkhaki; }
.ui-chatcolor option[value="SandyBrown"] { color: sandybrown; }
.ui-chatcolor option[value="Red"] { color: red; }

/* ── Location panel (stats_loc) ── */
.ui-locstats { font-size: 12px; }
.ui-help { cursor: help; }
.ui-locbtn { width: 164px; margin-top: 5px; }
.ui-muted-note { color: grey; }

/* ── Shop (taverna + bookshop/zooshop/komorka/nakova2 family) ── */
/* Heading above the counter (was local .pH3). */
.ui-shop__title {
	color: var(--ui-heading);
	font-family: var(--font-ui);
	font-size: 12pt;
	font-weight: bold;
}
/* Counter / section-header strip (was bgcolor="var(--ui-shop-counter)"). */
.ui-shop__counter { background: var(--ui-shop-counter); }
.ui-shop__counter-head {
	height: 21px;
	text-align: center;
}
/* Hidden JS-popup anchors (hint3/textgo) — keep the node, hide via class not inline. */
.ui-shop__hidden { visibility: hidden; }
/* The profile-info badge that follows a character's name (battle log, chat, dungeon
   reports). It is a bare inline <img>, so it sat on the text baseline and hung below
   it — next to "exmac [8]" the badge dropped a couple of pixels. There is no class to
   hook: the badge is emitted as raw markup from ~20 places, so key off the image. */
img[src*="inf_capitalcity"] {
	vertical-align: middle;
	position: relative;
	top: -1px;
}

/* The badges that sit in front of a name -- alignment, clan, the relationship marker -- are
   15-16px tall next to 12px text, and the sheet aligns every bare <img> to the bottom of the
   line box. So they hung below the name instead of standing beside it: in the post office,
   picking a recipient drew their face a couple of pixels into the floor. Same problem as the
   city badge above, same lack of a class to hook, so key off the images the same way. */
img[src*="/align/align"],
img[src*="/clan/"],
img[src*="/ico/rel_"] {
	vertical-align: middle;
	position: relative;
	top: -1px;
}

/* The right-hand column of every location screen (departments, exits, balance) is a
   280px cell sitting next to the item list in a cellpadding=0 table, so the two
   columns touched along their whole edge. 31 screens share this exact cell, so one
   rule keyed on it gives them all the gutter instead of 31 edits. */
td[width="280"] { padding-left: 18px; }

/* Department list (right column). The heading used to butt straight up against the
   buttons above it, so the sections read as part of the toolbar. */
.ui-shop__sections-head {
	margin-top: var(--ui-space-5);
	padding: 3px;
	text-align: center;
	font-weight: bold;
	background: var(--ui-shop-counter);
}
.ui-shop__sections { padding-top: var(--ui-space-2); line-height: 17px; }
.ui-shop__section { background: var(--ui-shop-section); }
.ui-shop__section--active { background: var(--ui-shop-section-on); }
/* Player balance (bright counter green, brighter than --ui-accent). */
.ui-shop__money { color: var(--ui-shop-money); font-weight: bold; }
.ui-shop__sale-bonus { color: grey; }
/* Unique-prize item display (shop_priz $itmg2 block): cell separator + image spacing. */

/* Legacy shared shop subheader (defined inline in ~10 shop files; hoisted here once -- those inline copies become redundant as each shop migrates). */
.shop_menu_txt { background-color: #d5d5d5; }
.ui-shop__city-ico { display: inline-block; vertical-align: bottom; } /* dungeon department city icons */

/* Responsive shell — first breakpoints for the legacy table-based game frame.
   The shell uses <table id="globalMain" class="game-frame-shell"> with fixed
   columns for the main iframe and chat/online panels. On narrow screens these
   collapse: the side caps hide, the main/chat split becomes vertical, and
   fonts/touch targets grow to readable sizes. Tablet (900px) and phone (640px). */
@media (max-width: 900px) {
	.game-frame-top-spacer,
	.game-frame-side--left,
	.game-frame-side--right {
		display: none;
	}
	.game-chat-cell {
		height: 240px;
	}
	/* Topbar: let the nav panel take the full width instead of the fixed 446px
	   right-aligned column, and drop the logo to make room on narrow screens. */
	.game-topbar__panel {
		width: 100%;
	}
	.game-topbar__logo,
	.game-topbar__mail {
		display: none;
	}
}

@media (max-width: 640px) {
	/* Stack main content above chat instead of the fixed 60/40 horizontal split. */
	.game-frame-shell tr,
	.game-frame-shell td,
	.game-chat-shell tr,
	.game-chat-shell td {
		display: block;
		width: 100% !important;
	}
	.game-chat-cell {
		height: 200px;
	}
	.game-main-frame {
		min-height: 60vh;
	}
	/* Raise base font from the legacy 10px to a readable mobile size. */
	.game-frame-shell {
		font-size: 14px;
	}
}

/* Inline-style utility classes — extracted from the most repeated inline style=
   patterns across PHP modules (see audit 2026-07-11-frontend-visual-modernization.md
   Phase 3). Each replaces a literal inline style that appeared 20+ times. */

/* Display */
.u-block { display: block; }
.u-inline-block { display: inline-block; }

/* Text */
.u-text-brown { color: brown; }
.u-text-xs { font-size: 10px; }
.u-cursor-default { cursor: default; }

/* Layout alignment */
.u-valign-bottom { vertical-align: bottom; }
.u-w-full { width: 100%; }

/* Dividers (replaces border-bottom:1px solid #CCCCCC / #cac9c7) */
.u-row-divider { border-bottom: 1px solid #CCCCCC; }
.u-row-divider-soft { border-bottom: 1px solid #cac9c7; margin-bottom: 5px; padding-bottom: 5px; }

/* Status indicator (replaces background-color: green in dragopsh) */
.u-state-ok { background-color: green; }

/* Card panel (replaces the _mod.php info-card pattern) */
.u-panel-card { padding: 0 10px 5px 10px; margin: 5px; border-bottom: 1px solid #cac9c7; }

/* Main content region — the single rendering target for all game screens.
   Previously an overlay on top of a hidden iframe; now the only content
   container in #touchmain. Loaded via getUrl2 (fetch + executePartialScript). */
#main-region {
	width: 100%;
	height: 100%;
	overflow-x: hidden;
	overflow-y: auto;
	position: relative;
}

/* <font> tag replacement utility classes — replacing deprecated HTML4 <font>
   tags with semantic spans. Each maps to the design token system. */
.u-text-danger { color: var(--ui-danger); }
.u-text-danger,
.u-text-success,
.u-text-muted,
.u-text-strong,
.u-text-brown,
.u-text-heading { font-weight: inherit; }
.u-text-success { color: var(--ui-accent); }
.u-text-muted { color: var(--ui-text-muted); }
.u-text-heading { color: var(--ui-heading); }

/* Inline-style utility classes batch 2 — next most repeated patterns. */
.u-nowrap-pad { white-space: nowrap; padding-left: 3px; padding-right: 3px; height: 10px; }
.u-cursor-pointer { cursor: pointer; }
.u-float-right { float: right; }
.u-float-left { float: left; }
.u-pad-top-19 { padding-top: 19px; }
.u-pos-relative { position: relative; }
.u-border-cell { border-bottom: 1px solid #232323; border-right: 1px solid #232323; }
.u-color-red { color: var(--ui-danger); }
.u-pad-3 { padding: 3px; }
.u-pad-2 { padding: 2px; }
.u-pad-10 { padding: 10px; }

/* Inline-style utility classes batch 3. */
.u-pad-left-0 { padding-left: 0px; }
.u-color-red { color: var(--ui-danger); }
.u-border-bottom-ccc { border-bottom: 1px solid #CCCCCC; }
.u-border-cell-dark { border-bottom: 1px solid #232323; border-right: 1px solid #232323; }

/* Inline-style utility classes batch 4 — safe patterns (NO display toggles). */
.u-pad-3 { padding: 3px; }
.u-pad-5 { padding: 5px; }
.u-text-link { color: var(--ui-link); }
.u-color-lightgray { color: #D8D8D8; }
.u-border-rt-black { border-right: 1px solid #000; border-top: 1px solid #000; }

/* Inline-style utility classes batch 7. */
.u-btn-style { cursor: pointer; font-weight: bold; color: #D8D8D8; font-size: 10px; }
.u-w-35 { width: 35px; }
.u-w-210 { width: 210px; }
.u-w-144 { width: 144px; }
.u-w-100 { width: 100px; }
.u-ml-10 { margin-left: 10px; }
.u-fs-11 { font-size: 11px; }
.u-border-top-black { border-top: 1px solid #000; }
.u-border-r-dark { border-right: 1px solid #232323; }
.u-w-44 { width: 44px; }
a.menutop { cursor: pointer; }
.u-pos-rel-cursor { position: relative; cursor: pointer; }
.u-pad-l-10 { padding-left: 10px; }
.u-w-224-mt-5 { width: 224px; margin-top: 5px; }
.u-w-500 { width: 500px; }
.u-pad-7 { padding: 7px; }
.u-ml-11 { margin-left: 11px; }
.u-mr-11-fs-9 { margin-right: 11px; font-size: 9px; }
.u-w-211 { width: 211px; }
.u-border-pad10 { border: 1px solid #CECECE; padding: 10px; }
.u-mb-pb-border { margin-bottom: 3px; padding-bottom: 3px; border-bottom: 1px solid #b7ae96; }
.u-pl-pb-border-grey { padding-left: 15px; padding-bottom: 5px; border-bottom: 1px solid grey; }

/* Inline icons sitting in a line of text.
   The shell sets `img { vertical-align: bottom }` — a legacy fix that kills the
   descender gap under images in the old table layouts, but it also drops every
   small inline icon to the baseline's bottom edge, so exit arrows and name-line
   badges sank below their own text. Re-align the icons that live inside a
   sentence; the table-layout images keep the bottom default. */
img[src$="/move/links.gif"],
.room-exits__arrow,
.char-name img,
#lgnthm img {
	vertical-align: middle;
}

/* Character name line (profile card header). Was a deprecated align="center"
   div with inline width/padding. */
.char-name {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: 3px;
	width: 246px;
	padding: 2px;
	box-sizing: border-box;
}

/* Room exit links ("→ Зал воинов"). Rendered by roomExitLink() as a flat list
   instead of the old one-row-per-link nested tables. */
.room-exits {
	display: flex;
	flex-direction: column;
	gap: 1px;
	background-color: #DEDEDE;
	padding: 1px;
}

.room-exits__item {
	display: flex;
	align-items: center;
	gap: 4px;
	padding: 1px 3px;
	background-color: #D3D3D3;
	white-space: nowrap;
}

/* ── Room interior banner ──────────────────────────────────
   The art of the room you just walked into, above its content. Rendered by
   roomBanner() (modules_data/_locations.php) for rooms that have art. */
.room-banner {
	position: relative;
	overflow: hidden;
	border-radius: 4px;
	border: 1px solid #b9b9b9;
	box-shadow: 0 1px 4px rgba(0, 0, 0, .25);
	margin-bottom: 8px;
	/* Crop the tall generated art down to a header band. */
	height: 132px;
}

.room-banner__art {
	display: block;
	width: 100%;
	height: 100%;
	/* Crop to the band and hold the eye level of the scene, where the props are,
	   instead of the empty ceiling. */
	object-fit: cover;
	object-position: center 62%;
}

/* Scrim so the room name stays readable over any art. */
.room-banner::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 56px;
	background: linear-gradient(180deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, .72));
	pointer-events: none;
}

.room-banner__title {
	position: absolute;
	left: 12px;
	bottom: 8px;
	z-index: 1;
	color: #f3e7c8;
	font-family: Georgia, "Times New Roman", serif;
	font-size: 17px;
	font-weight: bold;
	letter-spacing: .04em;
	text-shadow: 0 1px 3px rgba(0, 0, 0, .9);
}

/* ── The item row ──────────────────────────────────────────
   One row, one set of rules: the backpack and both counters render through
   User::itemRow(), so a shop item and a backpack item are the same thing on
   screen. The striping used to be an inline bgcolor emitted per row, which no
   stylesheet could override; it lives here. */
.item-row {
	background-color: #d8d8d8;
	transition: background-color .1s ease;
}

.item-row:nth-child(even) {
	background-color: #cfcfcf;
}

.item-row:hover {
	background-color: #e4e0d2;
}

.item-row > td {
	border-bottom: 1px solid #bcbcbc;
	vertical-align: top;
}

/* One section of an item description, kept whole. Without this the column rule cut
   the flat run wherever it landed, so "Требуется минимальное:" could sit at the foot
   of one column with its own requirements starting the next — which reads as labels
   in one column and values in another, for no reason a player could infer. */
.item-sec {
	break-inside: avoid;
	-webkit-column-break-inside: avoid;
	margin-top: var(--ui-space-3);
}
.item-sec:first-child { margin-top: 0; }

/* (The backpack used to stripe its rows through tr.item and the counters through .item-row — two
   sets of rules for the same list, because the two wrote different markup. They write the same row
   through the same template now (User::itemRow), so .item-row above is all of it. The backpack
   keeps the .item class on top of it: that is what its name filter hides rows by.) */

/* ── Inventory filter ──────────────────────────────────────
   The clear cross used to be pinned at top:3px — a number measured against the old
   bare-OS input. The field has real padding now, so it grew and the cross stayed at
   the top of it. Centre it against whatever height the field ends up being. */
.inv-filter__clear {
	position: absolute;
	right: 6px;
	top: 50%;
	transform: translateY(-50%);
	width: 12px;
	height: 12px;
	cursor: pointer;
}

.inv-sort { flex: none; }

/* ── The backpack: tabs, toolbar, list ─────────────────────
   The three of these were nested layout tables -- a row of <td> tabs picked out by a bgcolor
   attribute, a three-cell bar of mass/pager/search, and the scroll box. They are flex now. (The list
   itself is still a table of rows: those are the shared item rows, and a <tr> needs a table to sit
   in. The scaffolding around it is what changed.) */
.inv-panel {
	max-width: 1280px;
	margin: 0 auto;
}

.inv-tabs {
	display: flex;
	gap: 2px;
	background: #d4d2d2;
}

.inv-tab {
	flex: 1 1 0;
	padding: 7px 6px;
	text-align: center;
	font-weight: bold;
	color: var(--ui-link);
	border-bottom: 2px solid transparent;
}

.inv-tab:hover { background: rgba(0, 0, 0, .04); }

/* Which section you are reading. It was a bgcolor on a cell; now the active tab is lifted out of the
   strip and underlined, so the current tab reads as current instead of merely a different grey. */
.inv-tab--active {
	background: #ececec;
	color: var(--ui-text-strong);
	border-bottom-color: var(--ui-link);
	cursor: default;
}

.inv-toolbar {
	display: flex;
	align-items: center;
	gap: var(--ui-space-3);
	padding: 4px 6px;
	background: var(--ui-shop-counter);
	border-left: 1px solid var(--ui-shop-counter);
	border-right: 1px solid var(--ui-shop-counter);
	color: #2b2c2c;
	font-size: 12px;
}

.inv-toolbar__mass { flex: none; white-space: nowrap; }
.inv-toolbar__pager { flex: 1 1 auto; text-align: center; }

.inv-toolbar__search {
	display: flex;
	align-items: center;
	gap: var(--ui-space-2);
	flex: none;
}

.inv-toolbar__search form {
	display: flex;
	align-items: center;
	gap: var(--ui-space-2);
	margin: 0;
}

.inv-toolbar__search label { white-space: nowrap; }

/* The search field and its clear cross, positioned together. */
.inv-filter {
	position: relative;
	display: inline-block;
}

.inv-filter input[type="text"] {
	width: 240px;
	padding-right: 22px;
}

/* The list. The height used to be a hard 350px inline; keep the scroll, but let the box breathe with
   the frame it is in. */
.inv-list {
	/* Height is driven by the viewport, not JS. The old inventoryHeight() read #itmAll's height on
	   $(window).ready, but under the partial loader the fragment is not laid out yet, so the box
	   collapsed to one row with a scrollbar until a tab switch recomputed it. A CSS max-height sizes
	   to content (short lists stay short) and caps near the viewport bottom, with no timing to lose. */
	max-height: calc(100vh - 170px);
	overflow-y: auto;
	border-top: 1px solid var(--ui-shop-counter);
	border-bottom: 1px solid var(--ui-shop-counter);
}

.inv-list > table { width: 100%; }

@media (max-width: 760px) {
	.inv-toolbar { flex-wrap: wrap; }
	.inv-toolbar__pager { order: 3; flex-basis: 100%; }
	.inv-filter input[type="text"] { width: 150px; }
}

/* ── Skills sheet (умения) ─────────────────────────────────────────────────
   Two columns: the character's stats, and the tabbed sheet. They were table cells with
   a 1px grey <TD> between them standing in for a border. */
.um {
	display: flex;
	align-items: flex-start;
	gap: var(--ui-space-5);
	padding: 0 var(--ui-space-4);
}

.um__stats {
	flex: 0 0 300px;
	width: 300px;
	border-right: 1px solid var(--ui-border);
	padding-right: var(--ui-space-4);
}

.um__stats-head {
	padding: var(--ui-space-2);
	margin-bottom: var(--ui-space-2);
	background: var(--ui-surface);
	border-radius: var(--ui-radius-sm);
	font-weight: bold;
	text-align: center;
	color: var(--ui-text-strong);
}

.um__stats-body { padding-left: var(--ui-space-2); }

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

.um__actions { display: flex; gap: var(--ui-space-2); }

/* Each tab's panel. .dtz is hidden by default; setlevel() opens the current one. */
.um__sheet .dtz { padding-top: var(--ui-space-2); }

/* ── Notices ───────────────────────────────────────────────
   Was <font color=red>, a tag HTML4 retired. */
.ui-notice {
	display: block;
	margin: var(--ui-space-2) 0;
	color: var(--ui-text);
}
.ui-notice--bad { color: var(--ui-danger); font-weight: bold; }
.ui-notice--ok { color: var(--ui-accent); font-weight: bold; }

/* ── Transfer report ─────────────────────────────────────── */
.trf { max-width: 760px; padding: 0 var(--ui-space-4); }
.trf__row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--ui-space-3);
	margin-top: var(--ui-space-4);
}

/* The save gate on the skills sheet: a confirmation that says what it is confirming, and the
   button it unlocks. Reads top-down -- the warning, then the act. */
.um__confirm {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 8px;
	max-width: 420px;
	margin: 10px 0 4px;
	padding: 10px 12px;
	border: 1px solid #c9c4b8;
	border-radius: 4px;
	background: #f2f0ea;
}
.um__confirm-check {
	display: flex;
	align-items: flex-start;
	gap: 6px;
	font-size: 11px;
	line-height: 1.4;
	color: #4a4438;
	cursor: pointer;
}
.um__confirm-check input {
	margin: 1px 0 0;
	flex: 0 0 auto;
}

/* (The walk gauge lives in its own sheet -- /assets/css/move-bar.css -- because the auction screen
   draws the same widget and cannot load this one.) */

/* An item as it appears in the backpack list: the icon and its actions on the left, what the item
   says about itself on the right. It used to be a table nested inside the list's own table -- a
   100px cell, a 1px border, a cell that took the rest -- which is what a flex row with a border
   does, minus the scaffolding and minus the width the table imposed on everything around it.
   (.item-row above is the shop's striping and belongs to the <tr>; this is the cell inside it.) */
.inv-row {
	text-align: left;
}
.inv-row__inner {
	display: flex;
	/* Both columns run the full height of the row, which is what draws the divider all the way down
	   -- the old inner table did it with a cell border, and the row reads wrong without it. */
	align-items: stretch;
}
.inv-row__media {
	box-sizing: border-box;
	flex: 0 0 100px;
	padding: 5px;
	border-right: 1px solid var(--ui-shop-counter);
	/* The icon and its actions sit in the middle of however tall the description makes the row. */
	display: flex;
	align-items: center;
	justify-content: center;
}
.inv-row__media-inner {
	text-align: center;
}
/* The art gets a real slot rather than floating on the row's grey. Direct children only: the action
   icons under it live inside links, and a framed 16px cross is not what anybody meant. (This was the
   counter's `.item-row > td:first-child img`; it belongs to every list now, backpack included.) */
.inv-row__media-inner > img {
	background: #f4f2ec;
	border: 1px solid #b3b0a6;
	border-radius: 3px;
	padding: 2px;
}
/* A named gift carries its give button in the media column, and a button is wider than an icon. */
.gift-row .inv-row__media {
	flex: 0 0 160px;
}
.gift-row__give {
	margin-top: 5px;
}
.inv-row__body {
	/* min-width:0 lets a long name wrap instead of pushing the row wider than the list holding it. */
	flex: 1 1 auto;
	min-width: 0;
	padding: 7px 3px 3px 3px;
	/* What the item says about itself flows into columns on a wide screen instead of running down
	   the page in one thin ribbon. (This used to be selected as `tr.item td td:last-child > div`:
	   the <div align="left"> the old markup wrapped the description in. This block is that div.) */
	column-width: 340px;
	column-gap: 24px;
	column-rule: 1px solid #c4c4c4;
	line-height: 1.35;
}

/* The telegram window's content area. The window is 350px tall; a compose form is taller than that,
   and used to push straight through the bottom border of the frame. */
.tgf-body {
	height: 280px;
	overflow-y: auto;
	overflow-x: hidden;
}

/* The item menu (right-click a slot in the quick panel, a name in the chat) is drawn at z-index 1000
   by the legacy sheet, and the windows it is opened from sit at 1102 -- so the menu opened behind the
   window that asked for it, and the player saw nothing happen. It belongs on the same layer as the
   character menu, above the windows. */
.topusermenu {
	z-index: 1110;
}

/* ── Settings pages (security) ─────────────────────────────
   A column of fieldsets that used to run the full width of the window with their explanatory text
   as one unbroken wall above them. Give the page a reading measure, and let the blocks breathe. */
.settings-page {
	max-width: 560px;
	padding: 0 var(--ui-space-4);
}

.settings-intro {
	margin-bottom: var(--ui-space-5);
	line-height: 1.5;
}

.settings-intro p { margin: 0 0 var(--ui-space-3); }

.settings-page .ui-fieldset {
	max-width: none;
	margin-bottom: var(--ui-space-5);
	padding: var(--ui-space-2) var(--ui-space-4) var(--ui-space-4);
}

.settings-page .ui-fieldset > legend {
	padding: 0 var(--ui-space-2);
	color: var(--ui-heading);
}

.ui-form__hint {
	margin: 0 0 var(--ui-space-3);
	color: var(--ui-text-faint);
	font-size: var(--ui-fs-sm);
	line-height: 1.5;
}

/* ── Toasts ────────────────────────────────────────────────
   Corner notices for the short red in-game messages (level too low, credits received) that used to
   print inline across the top of the screen. Injected by top.toast() (gameEngine.js). */
#ash-toasts {
	position: fixed;
	top: 44px;
	right: 14px;
	z-index: 10000;
	display: flex;
	flex-direction: column;
	gap: 8px;
	max-width: 340px;
	pointer-events: none;
}

.ash-toast {
	padding: 10px 14px;
	border: 1px solid var(--ui-danger);
	border-left: 3px solid var(--ui-danger);
	border-radius: 6px;
	background: var(--ui-bg);
	box-shadow: 0 6px 18px rgb(0 0 0 / 0.2);
	color: var(--ui-heading);
	font-size: var(--ui-fs);
	font-weight: 700;
	cursor: pointer;
	pointer-events: auto;
	opacity: 0;
	transform: translateX(18px);
	transition: opacity 0.3s ease, transform 0.3s ease;
}

.ash-toast.is-shown {
	opacity: 1;
	transform: none;
}
