@import url(style_cs.1789269432.css);

* {
  box-sizing: border-box;
}

/* every font-size below this point is in rem, relative to this one root
   value — bump --font-size-base in colors.css to rescale the whole forum */
html {
  font-size: var(--font-size-base);
}

/* screen-reader-only utility — used throughout the forum markup (post author
   labels, action link suffixes) to keep text accessible without showing it */
.acchide,
/* "(Íåò àâàòàðà)" fallback text — the placeholder box below replaces it visually */
#viewprofile-next.no-avatar #pa-avatar strong,
/* lore-article tab radios: same clip technique, kept clickable via their
   <label for>, see LORE ARTICLE TEMPLATE below. chronicle-era-input reuses
   the identical radio+label mechanism for the timeline's era cards (see
   WORLD TIMELINE below); chronicle-filter-input is the scope filter's
   checkboxes, same technique, kept clickable via their own <label for>. */
.lore-article .lore-tab-input,
.chronicle-page .chronicle-era-input,
.chronicle-page .chronicle-filter-input {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* form-element resets .acchide doesn't need (it's never applied to an <input>) */
.lore-article .lore-tab-input,
.chronicle-page .chronicle-era-input,
.chronicle-page .chronicle-filter-input {
  margin: calc(-0.125 * var(--base-spacing));
  padding: 0;
  border: 0;
}

body {
  margin: 0;
  background: var(--color-bg);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-kerning: normal;
}

/* base link style, wherever a more specific component rule doesn't already
   set one (nav, cards, dark-surface menus etc. all style their own anchors) */
a {
  color: var(--color-link);
  text-decoration: none;
}

a:hover {
  color: var(--color-heading-hover);
}

#html-header {
  width: 100%;
  max-width: 1082px;
  margin: 0 auto;
  position: relative;
}

/* ---- HERO ---- */
.hero {
  position: relative;
  width: 100%;
  height: 390px;
  overflow: hidden;
  border-bottom: 2px solid var(--color-border);
  background: url(https://upforme.ru/uploads/001c/c7/56/2/860653.jpg) no-repeat;
  background-size: cover;
  background-position: center top;
}

.hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: saturate(1.05);
}

.hero::after {
  /* gentle vignette so overlaid text stays legible on either half */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(var(--color-bg-rgb), 0.55) 0%, rgba(var(--color-bg-rgb), 0.05) 30%, rgba(var(--color-bg-rgb), 0.05) 70%, rgba(var(--color-bg-rgb), 0.6) 100%);
}

.title-overlay {
  position: absolute;
  top: calc(2.5 * var(--base-spacing));
  left: 0;
  right: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.title-overlay h1 {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 2.71429rem;
  letter-spacing: 5px;
  color: var(--color-text-on-dark);
  line-height: 1;
  text-shadow: 0 2px 8px rgba(var(--color-shadow-rgb), 0.85), 0 0 18px rgba(var(--color-shadow-rgb), 0.6);
}

.title-overlay .subtitle {
  margin-top: calc(1 * var(--base-spacing));
  font-style: italic;
  font-size: 1.14286rem;
  letter-spacing: 2px;
  color: var(--color-accent-light);
  line-height: 1;
  text-shadow: 0 1px 6px rgba(var(--color-shadow-rgb), 0.85);
}

/* ---- HIGHLIGHTS STRIP (overlaid on hero) ---- */
.highlights {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  display: flex;
  background: rgba(var(--color-bg-rgb), 0.6);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  border-top: 1px solid rgba(var(--color-accent-rgb), 0.4);
}

/* wraps the first 3 cards so mobile can turn them into a carousel with nav
   arrows and dots (see MOBILE below) without touching the desktop layout —
   display:contents on the wrapper and its inner viewport/track unwraps them
   invisibly into the flex algorithm above 640px; the nav/dots controls are
   mobile-only UI so they're simply hidden here rather than unwrapped */
.highlights-carousel,
.highlights-carousel-viewport,
.highlights-carousel-track {
  display: contents;
}

.carousel-nav,
.carousel-dots {
  display: none;
}

.highlight-card {
  flex: 1;
  padding: calc(1.25 * var(--base-spacing)) calc(2 * var(--base-spacing)) calc(1.5 * var(--base-spacing));
  border-right: 1px solid rgba(var(--color-accent-rgb), 0.2);
}

.highlight-card:last-child {
  border-right: none;
}

.highlight-card--wide {
  flex: 1.3;
}

.highlight-card--queue {
  flex: 1.15;
}

.highlight-label {
  font-family: var(--font-heading);
  font-size: 0.78571rem;
  letter-spacing: 2px;
  color: var(--color-accent);
  margin-bottom: calc(1.25 * var(--base-spacing));
  display: block;
  text-transform: uppercase;
}

/* players */
.players-row {
  display: flex;
  gap: calc(1.25 * var(--base-spacing));
}

.player {
  text-align: center;
  flex: 1;
}

.player .av {
  width: 34px;
  height: 34px;
  border-radius: calc(0.5 * var(--base-spacing));
  margin: 0 auto calc(0.5 * var(--base-spacing));
  background: linear-gradient(145deg, var(--color-text-muted), var(--color-text));
  border: 2px solid var(--color-accent);
}

.player .name {
  font-size: 0.71429rem;
  color: var(--color-text-cream);
  line-height: 1.15;
}

/* best post / episode */
.post-title,
.episode-title {
  font-family: var(--font-heading);
  font-size: 0.92857rem;
  color: var(--color-text-on-dark);
  margin: 0 0 calc(0.375 * var(--base-spacing));
}

.post-excerpt,
.episode-desc {
  font-size: 0.85714rem;
  color: var(--color-text-on-dark-subtle);
  font-style: italic;
  line-height: 1.3;
  margin: 0 0 calc(0.5 * var(--base-spacing));
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.highlight-link {
  font-size: 0.85714rem;
  color: var(--color-accent-hover);
  text-decoration: none;
  border-bottom: 1px solid var(--color-border);
}

.highlight-link:hover {
  color: var(--color-text-on-dark);
}

/* ---- QUEST QUEUE (compact, inside overlay) ---- */
.quest-mini {
  list-style: none;
  margin: 0;
  padding: 0;
}

.quest-mini li {
  display: flex;
  flex-direction: column;
  padding: calc(0.375 * var(--base-spacing)) 0;
  border-bottom: 1px solid rgba(var(--color-accent-rgb), 0.15);
}

.quest-mini li:last-child {
  border-bottom: none;
}

.q-name {
  font-size: 0.82143rem;
  color: var(--color-text-on-dark);
  font-style: italic;
  line-height: 1.2;
}

.q-meta {
  font-size: 0.71429rem;
  color: var(--color-text-on-dark-subtle);
  letter-spacing: 0.2px;
}

/* keep our header block from inheriting forum body font defaults */
#html-header,
#html-header * {
  font-family: var(--font-body);
  box-sizing: border-box;
}

#html-header .title-overlay h1,
#html-header .highlight-label {
  font-family: var(--font-heading);
}

/* ============ PAGE-WIDE UNIFICATION ============ */
html,
body {
  margin: 0;
  padding: 0;
  background: var(--color-bg);
}

/* .punbb already wraps everything below the header in the real markup —
   turning it into one continuous parchment panel instead of per-section defaults */
.punbb {
  position: relative;
  display: flex;
  flex-direction: column;
  max-width: 1082px;
  margin: 0 auto;
  background-position: 0 -169px;
  background-color: var(--color-punbb-bg-fallback);
  border-left: 1px solid var(--color-border);
  border-right: 1px solid var(--color-border);
  border-bottom: 2px solid var(--color-border);
  box-shadow: 0 10px 34px rgba(var(--color-shadow-rgb), 0.5);
  overflow: hidden;
}

/* pull navlinks/ulinks above html-header visually — DOM order unchanged, only
   flex `order` reshuffles paint order; all other children stay at default
   order 0 so they keep their normal relative sequence */

/* strip the platform's default panel chrome so everything reads as one paper surface */
.punbb .section {
  border: none !important;
  box-shadow: none !important;
  margin: 0 !important;
  font-family: var(--font-body);
  color: var(--color-text);
  background: rgba(var(--color-bg-rgb), 0.93);
  backdrop-filter: blur(2px);
}

.punbb .crumbs {
  font-family: var(--font-heading);
  font-size: 0.78571rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-text-on-dark-muted);
  background: transparent;
  border: none;
  border-bottom: 1px dashed rgba(var(--color-border-rgb), 0.3);
  box-shadow: none;
  box-sizing: border-box;
  margin: 0;
  padding: calc(1 * var(--base-spacing)) calc(3 * var(--base-spacing));
}

/* "you are here" label reads as the anchor point, brighter than the trail around it */
.punbb .crumbs strong {
  font-family: var(--font-heading);
  font-size: 0.78571rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-text-on-dark);
}

/* chevron separators sit quiet so the eye lands on labels and links, not dividers */
.punbb .crumbs em {
  color: rgba(var(--color-accent-rgb), 0.5);
  font-style: normal;
}

.punbb .crumbs a,
.punbb .crumbs span {
  color: var(--color-accent);
  text-decoration: none;
}

.punbb .crumbs a:hover {
  color: var(--color-accent-bright);
  text-decoration: underline;
}

.punbb #pun-main {
  background: var(--color-panel-bg-alt);
  padding: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.punbb #pun-main>h1 {
  grid-column: 1;
  grid-row: 1;
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(180deg, var(--color-banner-bg-light) 0%, var(--color-banner-bg) 100%);
  border-top: 2px solid var(--color-accent);
  border-bottom: 2px solid var(--color-accent);
  padding: calc(1.5 * var(--base-spacing)) calc(2.5 * var(--base-spacing));
  margin: 0;
  text-align: center;
  box-shadow: 0 2px 6px rgba(var(--color-shadow-rgb), 0.3);
}

.punbb #pun-main>h1 span,
.punbb #pun-stats h2 span,
.forum h2 .item1 {
  font-family: var(--font-heading);
  font-size: 1.07143rem;
  letter-spacing: 3px;
  color: var(--color-text-on-dark);
  text-transform: uppercase;
}

/* "Ôîðóì" label — redundant under our header on index */
.punbb #pun-index #pun-main>h1 {
  display: none;
}

/* pagination + new-topic/new-poll toolbar merged into the h1 banner row */
.punbb #pun-main>h1+.linkst {
  grid-column: 1;
  grid-row: 1;
  position: relative;
  z-index: 2;
  margin: 0;
  color: var(--color-text-on-dark-muted);
}

.punbb #pun-main>h1+.linkst .pagelink strong {
  color: var(--color-accent-bright);
}

/* drop the parchment-page button chrome — on the banner these read as native
   header controls, pinned flush to the far right edge */
.punbb #pun-main>h1+.linkst .postlink {
  margin-left: auto;
  gap: 0;
}

.punbb #pun-main>h1+.linkst .postlink a {
  background: none;
  border: none;
  border-radius: 0;
  padding: calc(0.25 * var(--base-spacing)) calc(1.25 * var(--base-spacing));
  font-size: 0.75rem;
  letter-spacing: 1px;
  color: var(--color-text-on-dark-muted);
}

.punbb #pun-main>h1+.linkst .postlink span+span {
  border-left: 1px solid rgba(var(--color-accent-rgb), 0.4);
}

.punbb #pun-main>h1+.linkst .postlink a:hover {
  color: var(--color-accent-bright);
}

/* #pun-stats also matches .punbb .section above, which already forces
   border/box-shadow to none (!important) and sets the same font-family,
   color and backdrop-filter — only the background actually differs here */
.punbb #pun-stats {
  background: var(--color-panel-bg-alt);
  width: 100%;
  box-sizing: border-box;
}

.punbb #pun-stats h2 {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(1.25 * var(--base-spacing));
  font-family: var(--font-heading);
  font-size: 0.92857rem;
  letter-spacing: 2px;
  color: var(--color-heading);
  text-transform: uppercase;
  background: linear-gradient(180deg, var(--color-banner-bg-light) 0%, var(--color-banner-bg) 100%);
  border-top: 2px solid var(--color-accent);
  border-bottom: 2px solid var(--color-accent);
  padding: calc(1.5 * var(--base-spacing)) calc(2.5 * var(--base-spacing));
  margin: 0 calc(-2 * var(--base-spacing));
  box-shadow: 0 2px 6px rgba(var(--color-shadow-rgb), 0.3);
}

.punbb #pun-stats ul {
  list-style: none;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: calc(0.5 * var(--base-spacing)) calc(3 * var(--base-spacing));
  font-size: 0.89286rem;
  color: var(--color-text-muted);
  padding: 0;
}

#pun-stats .statscon {
  background: transparent;
  border-top: none;
  box-shadow: inset 0 1px 0 rgba(var(--color-highlight-rgb), 0.3);
  padding: calc(3 * var(--base-spacing)) calc(2.5 * var(--base-spacing));
}

#pun-stats ul.container li {
  padding: calc(0.25 * var(--base-spacing)) calc(0.75 * var(--base-spacing));
  border-radius: 2px;
  transition: background 0.15s;
}

#pun-stats ul.container li:hover {
  background: rgba(var(--color-border-rgb), 0.08);
}

#pun-stats li,
#pun-stats span {
  font-family: var(--font-body);
  color: var(--color-text);
  font-size: 0.92857rem;
}

.punbb #pun-stats strong {
  font-family: var(--font-body);
  color: var(--color-heading);
  font-size: 0.92857rem;
  font-weight: 600;
}

.punbb #pun-stats a {
  color: var(--color-link);
  text-decoration: none;
}

.punbb #pun-stats a:hover {
  color: var(--color-heading);
}

/* #pun-about also matches .punbb .section above (same background too here,
   nothing to override) — only padding/text-align add anything new */
.punbb #pun-about {
  padding: calc(1.5 * var(--base-spacing)) calc(3 * var(--base-spacing)) calc(2.5 * var(--base-spacing));
  text-align: center;
}

.punbb #pun-about a {
  font-family: var(--font-body);
  color: var(--color-link);
  text-decoration: none;
  font-size: 0.85714rem;
  letter-spacing: 0.5px;
}

.punbb #pun-about a:hover {
  color: var(--color-heading);
}

#pun-about .item1 {
  padding-left: 0;
}

/* ============ FORUM BODY (category + listing) ============ */
/* .forum (topic listing inside a forum, on viewforum pages) reuses this same
   row/table layout — its content differs (topics not forums, no h3 wrapper, plain
   byuser instead of lastpost), so only the shared structural rules below are
   extended to it; markup-specific rules follow in their own TOPIC LISTING block */
.category,
.forum {
  font-family: var(--font-body);
  margin: 0 0 calc(0.5 * var(--base-spacing));
}

.category h2 {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(1.25 * var(--base-spacing));
  background: linear-gradient(180deg, var(--color-banner-bg-light) 0%, var(--color-banner-bg) 100%);
  border-top: 2px solid var(--color-accent);
  border-bottom: 2px solid var(--color-accent);
  padding: calc(1.5 * var(--base-spacing)) calc(2.5 * var(--base-spacing));
  margin: 0;
  text-align: center;
  box-shadow: 0 2px 6px rgba(var(--color-shadow-rgb), 0.3);
}

.category h2::before {
  content: "";
  position: absolute;
  top: 50%;
  left: calc(3 * var(--base-spacing));
  right: calc(3 * var(--base-spacing));
  height: 1px;
  background: rgba(var(--color-accent-light-rgb), 0.5);
}

.category h2::after {
  right: calc(3 * var(--base-spacing));
}

.category h2 span {
  font-family: var(--font-heading);
  font-size: 1.07143rem;
  letter-spacing: 3px;
  background: linear-gradient(180deg, var(--color-banner-bg-light) 0%, var(--color-banner-bg) 100%);
  color: var(--color-text-on-dark);
  text-transform: uppercase;
  position: relative;
  z-index: 2;
  padding: 0 calc(3 * var(--base-spacing));
}

.category .catleft,
.category .catright {
  display: none;
}

.category .container,
.forum .container {
  border-top: none;
  padding: 0;
  box-shadow: inset 0 1px 0 rgba(var(--color-highlight-rgb), 0.3);
}

.category table,
.forum table {
  width: 100%;
  border-collapse: collapse;
}

.category thead,
.forum thead {
  display: none;
}

.category tbody tr {
  position: relative;
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-start;
  padding: calc(1.625 * var(--base-spacing)) calc(2.5 * var(--base-spacing));
  border-bottom: 1px solid rgba(var(--color-border-rgb), 0.3);
  border-left: 5px solid transparent;
  /* default = read state */
  transition: background 0.15s;
}

/* no description/tags line here (unlike .category), so a plain wrapping flex
   row lays tcl/tc2/tc3/tcr out directly — no need for .category's
   force-wrap-then-absolutely-position-the-second-line trick */
.forum tbody tr {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  padding: calc(1.625 * var(--base-spacing)) calc(2.5 * var(--base-spacing));
  border-bottom: 1px solid rgba(var(--color-border-rgb), 0.3);
  border-left: 5px solid transparent;
  transition: background 0.15s;
}

.category tbody tr:last-child,
.forum tbody tr:last-child {
  border-bottom: none;
}

.category tbody tr:hover,
.forum tbody tr:hover {
  background: rgba(var(--color-border-rgb), 0.08);
}

/* unread state — sole indicator is this border + tint, no dedicated dot/icon.
   .inew is the real forum class (confirmed on #messages markup) */
.category tbody tr.inew,
.forum tbody tr.inew,
#messages tbody tr.inew {
  border-left: 5px solid var(--color-accent);
  background: rgba(var(--color-accent-rgb), 0.1);
  box-shadow: inset calc(0.5 * var(--base-spacing)) 0 calc(1 * var(--base-spacing)) calc(-0.5 * var(--base-spacing)) rgba(var(--color-accent-rgb), 0.5);
}

/* ---- LINE 1: icon + title + description + tags — full width, forces the wrap ---- */
.category td.tcl {
  display: flex;
  align-items: flex-start;
  gap: calc(1.25 * var(--base-spacing));
  flex: 0 1 auto;
  width: 100%;
  padding: 0;
}

.forum td.tcl {
  display: flex;
  align-items: center;
  gap: calc(1.25 * var(--base-spacing));
  flex: 1 1 auto;
  min-width: 0;
  padding: 0;
}

.category .intd,
.forum .intd,
#messages .intd {
  display: flex;
  align-items: flex-start;
  gap: calc(1.25 * var(--base-spacing));
  width: 100%;
}

/* no dedicated new/read icon — the row's left border (see tr.inew above) is the only indicator */
.category .icon,
.forum .icon,
#messages .icon {
  display: none;
}

.category .tclcon,
.forum .tclcon,
#messages .tclcon {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.96429rem;
  color: var(--color-text-muted);
  line-height: 1.4;
  text-align: justify;
}

.category .tclcon h3 {
  margin: 0 0 calc(0.375 * var(--base-spacing));
  font-size: 1.14286rem;
  min-width: 0;
}

/* ellipsis has to live on the link, not the h3 — the h3 is a flex item now
   (see .forum-meta-row h3), and flex containers don't truncate their own text */
.category .tclcon h3 a {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-heading);
  color: var(--color-heading);
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.category .tclcon h3 a:hover {
  color: var(--color-heading-hover);
}

/* description links rendered as compact pill tags — the last-post avatar link
   also lives inside .tclcon (forum-meta-row is nested there), so it's excluded
   here rather than picking up pill margin/border/background too */
.category .forum-links {
  margin-top: calc(2 * var(--base-spacing));
}

.category .forum-links a {
  display: inline-block;
  font-style: normal;
  text-transform: uppercase;
  font-size: 0.71429rem;
  letter-spacing: 0.5px;
  color: var(--color-text-muted);
  text-decoration: none;
  background: rgba(var(--color-border-rgb), 0.12);
  border: 1px solid rgba(var(--color-border-rgb), 0.3);
  border-radius: 10px;
  padding: calc(0.25 * var(--base-spacing)) calc(1.125 * var(--base-spacing));
  margin: calc(0.75 * var(--base-spacing)) calc(0.5 * var(--base-spacing)) 0 0;
}

.category .forum-links a:hover {
  background: rgba(var(--color-accent-rgb), 0.25);
  color: var(--color-heading);
}

/* ---- LINE 2: counts + last-post — footer JS wraps tc2/tc3/tcr together with
   h3 into .forum-meta-row, so they flex-position off the title itself instead
   of relying on fixed pixel offsets ---- */
.category .forum-meta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(0.5 * var(--base-spacing)) calc(1.75 * var(--base-spacing));
  margin: calc(0.375 * var(--base-spacing)) 0 calc(0.75 * var(--base-spacing));
}

/* title now lives inside the same flex row as the counts (JS moved h3 in here) —
   let it fill whatever width tc2/tc3/tcr don't take, truncating instead of wrapping */
.category .forum-meta-row h3 {
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  margin: 0 0 calc(0.375 * var(--base-spacing));
}

.category .forum-meta-row td.tc2,
.category .forum-meta-row td.tc3 {
  display: flex;
  align-items: center;
  gap: calc(0.5 * var(--base-spacing));
  width: auto;
  padding-right: calc(1.75 * var(--base-spacing));
  border-right: 1px solid rgba(var(--color-border-rgb), 0.3);
  font-size: 0.82143rem;
  color: var(--color-text);
  white-space: nowrap;
}

.category .forum-meta-row td.tc2::after {
  content: " òåì";
  color: var(--color-link);
  font-size: 0.75rem;
}

.category .forum-meta-row td.tc3::after {
  content: " ñîîáù.";
  color: var(--color-link);
  font-size: 0.75rem;
}

/* avatar | link+timestamp layout — br between lastpost-link and .lastpost is
   forum-generated markup we can't touch, so it's hidden and grid auto-placement
   (row-major, sparse) drops the link into col2/row1 and .lastpost into col2/row2
   on its own once the avatar claims col1 across both rows */
.category .forum-meta-row td.tcr,
.forum td.tcr {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: calc(1 * var(--base-spacing));
  font-size: 0.82143rem;
  color: var(--color-text-muted);
  text-align: left;
}

.category .forum-meta-row td.tcr {
  width: 220px;
  min-width: 220px;
}

.category .forum-meta-row td.tcr br,
.forum td.tcr br {
  display: none;
}

.category .forum-meta-row td.tcr .user-avatar,
.forum td.tcr .user-avatar {
  grid-row: 1 / 3;
  grid-column: 1;
  align-self: stretch;
}

/* .forum (topic listing) — plain in-flow flex columns, no position:absolute
   trick: the single-line title + byuser here doesn't need the two-line
   force-wrap that .category's description/tags block requires */
.forum td.tc2,
.forum td.tc3 {
  flex: 0 0 auto;
  width: 72px;
  padding: 0 calc(1 * var(--base-spacing));
  border-right: 1px solid rgba(var(--color-border-rgb), 0.3);
  text-align: center;
  font-size: 0.82143rem;
  color: var(--color-text);
  white-space: nowrap;
}

.forum td.tcr {
  flex: 0 0 auto;
  width: 220px;
}

.category .user-avatar,
.forum .user-avatar,
#messages .user-avatar {
  position: relative;
  flex: 0 0 auto;
}

.punbb .user-avatar {
  width: auto !important;
  height: auto !important;
  margin: 0 !important;
  float: none !important;
}

.punbb .user-avatar .isonline {
  top: calc(-0.125 * var(--base-spacing)) !important;
  right: calc(-0.125 * var(--base-spacing)) !important;
}

/* extra.css (uncontrolled, loaded on the live forum) targets this exact
   selector — .punbb .user-avatar .avatar-image — at 3-class specificity, so
   !important is needed throughout to keep our plain square instead of its
   36px/opacity/float version */
.category .avatar-image,
.forum .avatar-image,
.usertable .avatar-image,
#messages .avatar-image {
  display: block !important;
  width: 26px !important;
  height: 26px !important;
  border-radius: 4px !important;
  background-size: cover !important;
  background-position: center center !important;
  background-repeat: no-repeat !important;
  border: none !important;
  overflow: hidden !important;
  opacity: 1 !important;
  float: none !important;
}

/* last-post avatar sized to match the two stacked text rows beside it —
   height:100%/aspect-ratio on an auto-sized grid track is circular (column
   width depends on avatar width, which depends on a row height not known
   until column widths are settled) and collapses the avatar to 0&#215;0, so this
   uses a fixed square instead */
.category .forum-meta-row td.tcr .avatar-image,
.forum td.tcr .avatar-image {
  width: 35px !important;
  height: 35px !important;
}

.category .isonline,
.forum .isonline,
.usertable .isonline,
#messages .isonline {
  position: absolute;
  bottom: calc(-0.125 * var(--base-spacing));
  right: calc(-0.125 * var(--base-spacing));
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-status-online);
  border: 1px solid var(--color-panel-bg);
}

.category .lastpost-link {
  color: var(--color-heading);
  text-decoration: none;
  font-style: italic;
  margin: 0 !important;
}

.category .lastpost {
  display: block;
  font-size: 0.71429rem;
  color: var(--color-link);
  margin-top: calc(0.125 * var(--base-spacing));
}

/* ============ TOPIC LISTING (.forum markup-specific) ============ */
/* .forum h2 (topic-count/pagination banner) is unconditionally hidden by the
   `display: none !important` combinator at the bottom of this file, so it's
   left unstyled here rather than styling an element that never renders */

.forum .tclcon a,
#messages .tclcon a {
  font-family: var(--font-heading);
  font-size: 1.07143rem;
  color: var(--color-heading);
  text-decoration: none;
  letter-spacing: 0.5px;
}

.forum .tclcon a:hover,
#messages .tclcon a:hover {
  color: var(--color-heading-hover);
}

.forum .tclcon .byuser {
  font-size: 0.78571rem;
  font-style: italic;
  color: var(--color-link);
}

.forum td.tcr a {
  color: var(--color-heading);
  text-decoration: none;
  font-style: italic;
}

.forum td.tcr .byuser {
  display: block;
  margin-top: calc(0.125 * var(--base-spacing));
  font-size: 0.71429rem;
  color: var(--color-link);
}

/* search/active-topics reuses the exact .forum row markup, but tc2 there
   holds the source forum's name (a link, arbitrary length) instead of a
   short reply count — the 72px/nowrap sizing meant for numbers lets it
   overflow past its border straight into tc3's count */
#pun-searchtopics .forum td.tc2 {
  width: calc(15 * var(--base-spacing));
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: left;
}

/* ============ PLAIN DATA TABLES (online.php list + userlist.php + respect.php) ============ */
/* .online-list, .usertable and #pun-respect's table are real tabular grids
   with a visible header — unlike .category/.forum's card-style rows above,
   so they share one flat table skin instead of duplicating it per page.
   .online-list and #pun-respect's wrapper both carry the generic .section
   class, which forces a near-opaque dark background (see .punbb .section)
   meant for chrome like crumbs/status bars; overridden here to the same
   light parchment sub-surface .usertable already sits on (it isn't
   .section at all, so it never picked up the dark override), so all three
   read as one content panel like the rest of the page. #pun-respect's
   wrapper has no distinguishing class of its own (just "section"), so it's
   scoped by id instead — specifically #pun-main's child, since #pun-respect
   also wraps page chrome (logo/navlinks/crumbs/ad slots) that all carry
   the same bare .section class and must stay on the dark chrome background */
.punbb .section.online-list,
#pun-respect #pun-main .section {
  background: var(--color-panel-bg-alt);
}

.online-list .container,
.usertable .container,
#pun-respect .container {
  padding: calc(1.5 * var(--base-spacing)) calc(2.5 * var(--base-spacing));
}

.online-list table,
.usertable table,
#pun-respect table,
#filetable {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-body);
}

.online-list thead th,
.usertable thead th,
#pun-respect thead th,
#filetable thead th {
  text-align: left;
  font-family: var(--font-heading);
  font-size: 0.78571rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-link);
  border-bottom: 2px solid var(--color-accent);
  padding: calc(0.75 * var(--base-spacing)) calc(1 * var(--base-spacing)) calc(0.75 * var(--base-spacing)) 0;
}

.online-list thead th.time,
.usertable thead th.tc3,
#filetable thead th.tc3 {
  text-align: right;
}

/* #pun-respect's own tc3 is "Êòî" (a name), not a time column like
   .usertable's — only its rightmost column (tcr, "Â òåìå") gets the
   right-align treatment, on both header and cells */
#pun-respect thead th.tcr,
#pun-respect td.tcr {
  text-align: right;
}

/* the live forum's own uncontrolled global stylesheet pins bare
   `.tcl`/`.tc2`/`.tc3`/`.tcr` to fixed width percentages (20/10/20/50%) and
   `td.tc2` to a larger font-size, `!important` — leftover badge styling for
   its classic topic-list replies/views columns. #pun-respect reuses those
   same class names for unrelated columns, so the squeeze bleeds in: "Çà
   ÷òî" (tc3.tc4) gets crushed into a 20%-wide column and wraps into a tall,
   mostly-blank ribbon instead of using the row's/card's full width, on both
   the desktop table and the stacked mobile card. `#pun-respect`'s id lifts
   specificity above the bare classes, so matching their `!important` here
   is enough to win outright — `width: auto` then means "size the desktop
   column by content" and "fill the mobile card's full width", each in its
   own display context. */
#pun-respect th.tcl,
#pun-respect th.tc2,
#pun-respect th.tc3,
#pun-respect th.tcr,
#pun-respect td.tcl,
#pun-respect td.tc2,
#pun-respect td.tc3,
#pun-respect td.tcr {
  width: auto !important;
}

#pun-respect td.tc2 {
  font-size: 0.85714rem !important;
}

.online-list tbody tr,
.usertable tbody tr,
#pun-respect tbody tr,
#filetable tbody tr {
  border-bottom: 1px solid rgba(var(--color-border-rgb), 0.3);
  transition: background 0.15s;
}

.online-list tbody tr:last-child,
.usertable tbody tr:last-child,
#pun-respect tbody tr:last-child,
#filetable tbody tr:last-child {
  border-bottom: none;
}

.online-list tbody tr:hover,
.usertable tbody tr:hover,
#pun-respect tbody tr:hover,
#filetable tbody tr:hover {
  background: rgba(var(--color-border-rgb), 0.08);
}

.online-list td,
.usertable td,
#pun-respect td,
#filetable td {
  padding: calc(1 * var(--base-spacing)) calc(1 * var(--base-spacing)) calc(1 * var(--base-spacing)) 0;
  font-size: 0.85714rem;
  color: var(--color-text-muted);
  vertical-align: top;
}

.online-list td.tc3,
.usertable td.tc3,
#filetable td.tc3 {
  text-align: right;
  white-space: nowrap;
}

.online-list td:last-child,
.usertable td:last-child,
.online-list th:last-child,
.usertable th:last-child,
#pun-respect td:last-child,
#pun-respect th:last-child,
#filetable td:last-child,
#filetable th:last-child {
  padding-right: 0;
}

.online-list td a,
.usertable td a,
#pun-respect td a,
#filetable td a {
  color: var(--color-link);
  text-decoration: none;
}

.online-list td a:hover,
.usertable td a:hover,
#pun-respect td a:hover,
#filetable td a:hover {
  color: var(--color-heading-hover);
  text-decoration: underline;
}

/* the whole cell gets the heading treatment (not just an `a.registered-user`
   selector) so a guest row's bare "Ãîñòü" text — no link at all — reads with
   the same weight as a member's name; an admin viewing this table also gets
   a second link per row (the visitor's IP, for moderate.php) inside the same
   cell, reset back to a plain link separately below so it doesn't inherit it */
.online-list td.username,
.usertable td.username .usersname a {
  font-family: var(--font-heading);
  font-weight: 600;
  letter-spacing: 0.5px;
  color: var(--color-heading);
}

.online-list td.username a:first-child:hover,
.usertable td.username .usersname a:hover {
  color: var(--color-heading-hover);
}

/* filename is #filetable's identity column, same weight as usertable's username */
#filetable td.tcl a {
  font-family: var(--font-heading);
  font-weight: 600;
  letter-spacing: 0.3px;
  color: var(--color-heading);
}

#filetable td.tcl a:hover {
  color: var(--color-heading-hover);
}

#filetable input[type="checkbox"] {
  accent-color: var(--color-accent);
  cursor: pointer;
}

.online-list td.username a:not(:first-child) {
  font-family: var(--font-body);
  font-weight: normal;
  letter-spacing: normal;
  color: var(--color-link);
}

/* ============ PAGE TOOLBAR (pagelink / postlink / modmenu) ============ */
/* shared by the topic listing (.linkst/.linksb around .forum) and the topic
   view (.linkst/.linksb around #topic_t1) — same markup on both pages */
.punbb .linkst {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: calc(1 * var(--base-spacing)) calc(2 * var(--base-spacing));
  padding: calc(1.5 * var(--base-spacing)) calc(2.5 * var(--base-spacing));
  font-size: 0.85714rem;
  color: var(--color-text-muted);
}

.punbb .linksb {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: calc(1 * var(--base-spacing)) calc(2 * var(--base-spacing));
  padding: calc(1.5 * var(--base-spacing)) calc(2.5 * var(--base-spacing));
  font-size: 0.85714rem;
  color: var(--color-text-muted);
  border-top: 1px dashed rgba(var(--color-border-rgb), 0.3);
}

.punbb .pagelink strong {
  color: var(--color-heading);
}

/* .linksb markup order differs from .linkst (postlink, pagelink, subscribelink) —
   reorder visually to match .linkst's pagelink-then-postlink order. On the forum
   listing page .postlink is wrapped in a <noindex> tag, which is the actual flex
   item there — order has to target that wrapper too or it's ignored */
.punbb .linksb .pagelink {
  order: 1;
  flex-grow: 1;
}

.punbb .linksb .postlink,
.punbb .linksb noindex {
  order: 2;
}

.punbb .linksb .subscribelink {
  order: 3;
}

.punbb .postlink {
  display: flex;
  gap: calc(1 * var(--base-spacing));
}

.punbb .postlink a,
.punbb .subscribelink a {
  display: inline-block;
  font-family: var(--font-heading);
  font-size: 0.78571rem;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--color-text-on-dark);
  text-decoration: none;
  background: linear-gradient(180deg, var(--color-banner-bg-light) 0%, var(--color-banner-bg) 100%);
  border: 1px solid var(--color-accent);
  border-radius: calc(0.5 * var(--base-spacing));
  padding: calc(0.5 * var(--base-spacing)) calc(1.25 * var(--base-spacing));
}

.punbb .postlink a:hover,
.punbb .subscribelink a:hover {
  border-color: var(--color-accent-hover);
  color: var(--color-accent-bright);
}

.punbb .modmenu {
  padding: calc(1.25 * var(--base-spacing)) calc(2.5 * var(--base-spacing));
  font-size: 0.78571rem;
  color: var(--color-text-muted);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: calc(0.5 * var(--base-spacing)) calc(2 * var(--base-spacing));
  border-top: 1px dashed rgba(var(--color-border-rgb), 0.3);
}

.punbb .modmenu a {
  color: var(--color-link);
}

.punbb .modmenu a:hover {
  color: var(--color-heading);
}

.punbb .modmenu select {
  color: var(--color-link);
  font-family: var(--font-body);
  font-size: 0.78571rem;
  background: var(--color-panel-bg);
  border: 1px solid var(--color-border);
  border-radius: calc(0.375 * var(--base-spacing));
  padding: calc(0.25 * var(--base-spacing)) calc(0.5 * var(--base-spacing));
}

/* top fade removed — the dark #pun-navlinks bar right after the header
   handles the dark-to-cream transition directly, no overlay needed */
#html-header+#pun-break1 {
  padding: 0 !important;
}

/* dark tone continues from the header's greeting bar, through the divider and
   breadcrumb, down to the category header — cream only starts below it */
.punbb #pun-break1,
.punbb #pun-break2 {
  background: var(--color-banner-bg) !important;
}

.punbb #pun-break1 hr,
.punbb #pun-break2 hr {
  border: none;
  border-top: 1px solid rgba(var(--color-accent-light-rgb), 0.3);
  margin: 0 calc(2.5 * var(--base-spacing));
}

/* ============ REUSABLE BUTTON ============ */
.button {
  display: inline-block;
  font-family: var(--font-heading);
  font-size: 0.85714rem;
  letter-spacing: 1px;
  font-weight: 500;
  text-transform: uppercase;
  color: var(--color-text-on-dark);
  background: linear-gradient(180deg, var(--color-banner-bg-light) 0%, var(--color-banner-bg) 100%);
  border: 1px solid var(--color-accent);
  border-radius: calc(0.5 * var(--base-spacing));
  padding: calc(0.75 * var(--base-spacing)) calc(2 * var(--base-spacing));
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(var(--color-shadow-rgb), 0.3);
  transition: background 0.25s ease, color 0.25s ease, box-shadow 0.25s ease, transform 0.15s ease;
}

.button:hover {
  border-color: var(--color-accent-hover);
  box-shadow: 0 4px 10px rgba(var(--color-shadow-rgb), 0.35), 0 0 0 1px rgba(var(--color-accent-rgb), 0.2);
  transform: translateY(-1px);
}

.button:active {
  transform: translateY(0);
  box-shadow: 0 1px 3px rgba(var(--color-shadow-rgb), 0.3);
}

/* ============ REPUTATION MODAL ("Ïîäíÿòü ðåïóòàöèþ") ============ */
/* #pun-reputation is injected unstyled by the forumscripts.ru post_voters
   plugin (third-party, not in forms/) — theme it to match the rest of the site */
#pun-reputation .bg.post_reputation {
  background: rgba(var(--color-bg-rgb), 0.75);
}

#pun-reputation .inner.post_reputation {
  background: var(--color-panel-bg);
  border: 1px solid var(--color-border);
  border-top: 2px solid var(--color-accent);
  border-radius: calc(0.5 * var(--base-spacing));
  box-shadow: 0 10px 24px rgba(var(--color-shadow-rgb), 0.5);
  /* the plugin centers this by writing an inline top/left in px, sized for its
     own (unstyled) natural height — that math doesn't know about max-height
     below, so on a short viewport the box still starts too low and runs off
     the bottom. Re-center with a fixed anchor point instead (!important to
     beat the inline style) so it always fits, and scroll instead of clipping
     when content is still taller than that */
  position: fixed !important;
  top: 50% !important;
  left: 50% !important;
  margin: 0 !important;
  transform: translate(-50%, -50%);
  max-height: 90vh;
  overflow-y: auto;
}

#pun-reputation h1 {
  margin: 0;
  padding: calc(1.25 * var(--base-spacing)) calc(2 * var(--base-spacing));
  background: linear-gradient(180deg, var(--color-banner-bg-light) 0%, var(--color-banner-bg) 100%);
  border-bottom: 1px solid var(--color-accent);
  /* .inner's overflow is now auto (scrollable), not hidden, so this needs its
     own top radius to keep the rounded corners instead of relying on clipping */
  border-radius: calc(0.5 * var(--base-spacing) - 1px) calc(0.5 * var(--base-spacing) - 1px) 0 0;
}

#pun-reputation h1 span {
  font-family: var(--font-heading);
  font-size: 1.14286rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-text-on-dark);
}

#pun-reputation .container {
  padding: calc(2 * var(--base-spacing)) !important;
  font-family: var(--font-body);
  color: var(--color-text);
}

#pun-reputation table {
  width: 100%;
  border-collapse: collapse;
}

#pun-reputation td {
  padding: calc(0.75 * var(--base-spacing)) 0;
  vertical-align: top;
}

#pun-reputation td.tcl {
  padding-right: calc(1.5 * var(--base-spacing));
  font-family: var(--font-heading);
  font-weight: 600;
  letter-spacing: 0.5px;
  color: var(--color-heading);
  white-space: nowrap;
}

#pun-reputation #reputationText {
  width: 100% !important;
  box-sizing: border-box;
}

#pun-reputation .button {
  margin-right: calc(0.5 * var(--base-spacing));
}

.postlink.long {
  width: auto !important;
}

/* ============ REUSABLE FORM FIELDS (generic inputs/selects) ============ */
/* excludes .modmenu's own select, which already carries a complete compact style of
   its own — kept as the sole rule touching that element rather than layering a second */
input[type="text"],
input[type="password"],
input[type="email"],
input[type="search"],
input[type="number"],
input[type="url"] {
  font-family: var(--font-body);
  font-size: 0.92857rem;
  color: var(--color-text);
  background: var(--color-panel-bg);
  border: 1px solid var(--color-border);
  border-radius: calc(0.5 * var(--base-spacing));
  padding: calc(0.75 * var(--base-spacing)) calc(1.25 * var(--base-spacing));
  box-sizing: border-box;
}

select:not(.modmenu *) {
  font-family: var(--font-body);
  font-size: 0.92857rem;
  color: var(--color-text);
  background: var(--color-panel-bg);
  border: 1px solid var(--color-border);
  border-radius: calc(0.5 * var(--base-spacing));
  padding: calc(0.625 * var(--base-spacing)) calc(1.25 * var(--base-spacing));
  box-sizing: border-box;
  cursor: pointer;
}

input[type="text"]:focus,
input[type="password"]:focus,
input[type="email"]:focus,
input[type="search"]:focus,
input[type="number"]:focus,
input[type="url"]:focus,
select:not(.modmenu *):focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 2px rgba(var(--color-accent-rgb), 0.25);
}

/* ============ POST SYMBOL COUNT (topic post form only, see footer.html) ============ */
.symbol-count {
  margin-top: calc(0.5 * var(--base-spacing));
  font-size: 0.78571rem;
  color: var(--color-text-muted);
  text-align: right;
}

/* ============ FLOAT BUTTONS ([float=left]/[float=right], see footer.html) ============ */
/* was an inline <style> in footer.html — moved here per this file's own rule
   that all styling lives in style.css, not scattered inline tags */
#form-buttons .vibor {
  width: calc(2.75 * var(--base-spacing));
  height: calc(2.75 * var(--base-spacing));
}

/* ============ INSTANT PREVIEW TOGGLE (#togglePreview, see footer.html) ============ */
/* was an inline <style> in footer.html — moved here per this file's own rule
   that all styling lives in style.css, not scattered inline tags. Floats the
   toggle button up next to the fieldset's own legend instead of it falling
   into normal flow above the toolbar. */
#togglePreview {
  float: right;
  /* right margin matches #post-form legend's own right padding (see below)
     so the button lines up with the legend's right inset instead of sitting
     flush against the fieldset's raw edge */
  margin: calc(-2 * var(--base-spacing)) calc(3 * var(--base-spacing)) 0 0;
}

/* ============ SCROLL NAV (jump to top / bottom) ============ */
.scroll-nav {
  position: fixed;
  right: calc(3 * var(--base-spacing));
  bottom: calc(3 * var(--base-spacing));
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: calc(1 * var(--base-spacing));
}

.scroll-nav-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(5 * var(--base-spacing));
  height: calc(5 * var(--base-spacing));
  background: linear-gradient(180deg, var(--color-banner-bg-light) 0%, var(--color-banner-bg) 100%);
  border: 1px solid var(--color-accent);
  border-radius: 4px;
  box-shadow: 0 2px 6px rgba(var(--color-shadow-rgb), 0.3);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s, border-color 0.2s;
}

.scroll-nav-btn.is-visible {
  opacity: 1;
  pointer-events: auto;
}

.scroll-nav-btn::before {
  font: normal 900 16px "Font Awesome 6 Free";
  color: var(--color-accent);
  transition: color 0.2s;
}

.scroll-nav-btn:hover,
.settings-drawer-toggle.is-open {
  border-color: var(--color-accent-hover);
}

.scroll-nav-btn:hover::before,
.settings-drawer-toggle.is-open::before {
  color: var(--color-accent-bright);
}

.scroll-nav-btn:focus-visible,
.font-size-slider:focus-visible,
.settings-drawer-toggle:focus-visible,
.settings-drawer-close:focus-visible {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 2px;
}

.scroll-nav-btn--up::before {
  content: "\f102";
  /* fa-angles-up */
}

.scroll-nav-btn--down::before {
  content: "\f103";
  /* fa-angles-down */
}

/* ============ SETTINGS DRAWER (topic reading settings, see footer.html) ============ */
/* Icon toggle sits fixed in its own top-right corner — right above where
   .settings-drawer itself pops out from, rather than down in the bottom-right
   .scroll-nav stack with the up/down arrows, so the trigger stays visually
   attached to the panel it opens. It borrows the .scroll-nav-btn box/icon
   look below (footer.html adds that class) and is always visible (no
   .is-visible scroll gating) — only its own position, ::before content and
   .is-open highlight are specific to it. .settings-drawer's own top offset
   is pushed down to clear this button (see below). */
.settings-drawer-toggle {
  position: fixed;
  top: calc(3 * var(--base-spacing));
  right: calc(3 * var(--base-spacing));
  z-index: 50;
}

.settings-drawer-toggle::before {
  content: "\f031";
  /* fa-font */
}

.settings-drawer {
  position: fixed;
  /* toggle sits at top: 3 * base-spacing, is 5 * base-spacing tall — this
     clears it with a 1 * base-spacing gap instead of sitting underneath it */
  top: calc(9 * var(--base-spacing));
  right: 0;
  z-index: 45;
  width: min(300px, 88vw);
  background: var(--color-panel-bg);
  border: 1px solid var(--color-accent);
  border-right: none;
  border-radius: calc(0.75 * var(--base-spacing)) 0 0 calc(0.75 * var(--base-spacing));
  box-shadow: -4px 4px 16px rgba(var(--color-shadow-rgb), 0.35);
  transform: translateX(100%);
  transition: transform 0.3s ease;
  overflow: hidden;
}

.settings-drawer.is-open {
  transform: translateX(0);
}

.settings-drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(1 * var(--base-spacing));
  padding: calc(1.25 * var(--base-spacing)) calc(2 * var(--base-spacing));
  background: linear-gradient(180deg, var(--color-banner-bg-light) 0%, var(--color-banner-bg) 100%);
  border-bottom: 1px solid var(--color-accent);
}

.settings-drawer-header span {
  font-family: var(--font-heading);
  font-size: 0.85714rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--color-text-on-dark);
}

.settings-drawer-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(2.5 * var(--base-spacing));
  height: calc(2.5 * var(--base-spacing));
  background: none;
  border: none;
  color: var(--color-text-on-dark-muted);
  cursor: pointer;
  transition: color 0.2s;
}

.settings-drawer-close::before {
  font: normal 900 0.85714rem "Font Awesome 6 Free";
  content: "\f00d";
  /* fa-xmark */
}

.settings-drawer-close:hover {
  color: var(--color-accent-bright);
}

.settings-drawer-body {
  padding: calc(2 * var(--base-spacing));
}

.font-size-control {
  display: flex;
  align-items: center;
  gap: calc(1 * var(--base-spacing));
}

.font-size-control-icon {
  font-family: var(--font-heading);
  font-weight: 600;
  line-height: 1;
  color: var(--color-accent);
  user-select: none;
}

.font-size-control-icon--dec {
  font-size: 0.71429rem;
}

.font-size-control-icon--inc {
  font-size: 1.14286rem;
}

.font-size-control-value {
  min-width: calc(4 * var(--base-spacing));
  font-family: var(--font-heading);
  font-size: 0.71429rem;
  letter-spacing: 0.5px;
  color: var(--color-text-on-dark-subtle);
  text-align: center;
  user-select: none;
}

/* Native range input, restyled per-browser (WebKit/Blink + Firefox need
   separate pseudo-elements — there's no shared shorthand) to match the site's
   gold-on-dark theme instead of the OS default slider. */
.font-size-slider {
  -webkit-appearance: none;
  appearance: none;
  width: calc(11 * var(--base-spacing));
  height: calc(0.5 * var(--base-spacing));
  background: rgba(var(--color-accent-rgb), 0.3);
  border-radius: calc(0.25 * var(--base-spacing));
  outline: none;
  cursor: pointer;
}

.font-size-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: calc(2.25 * var(--base-spacing));
  height: calc(2.25 * var(--base-spacing));
  border-radius: 50%;
  background: linear-gradient(180deg, var(--color-accent-light), var(--color-accent));
  box-shadow: 0 1px 3px rgba(var(--color-shadow-rgb), 0.3);
  cursor: pointer;
  transition: transform 0.15s;
}

.font-size-slider::-moz-range-track {
  background: rgba(var(--color-accent-rgb), 0.3);
  height: calc(0.5 * var(--base-spacing));
  border-radius: calc(0.25 * var(--base-spacing));
}

.font-size-slider::-moz-range-thumb {
  width: calc(2.25 * var(--base-spacing));
  height: calc(2.25 * var(--base-spacing));
  border: none;
  border-radius: 50%;
  background: linear-gradient(180deg, var(--color-accent-light), var(--color-accent));
  box-shadow: 0 1px 3px rgba(var(--color-shadow-rgb), 0.3);
  cursor: pointer;
  transition: transform 0.15s;
}

.font-size-slider:hover::-webkit-slider-thumb,
.font-size-slider:hover::-moz-range-thumb {
  transform: scale(1.12);
}

/* ============ MOBILE (&#8804;640px) ============ */
@media (max-width: 640px) {
  .hero {
    height: auto;
    overflow: visible;
  }

  /* the vignette exists so overlaid title text stays legible on the image —
     on mobile the title sits in normal flow below the image, not overlaid,
     and .hero grows to auto height around the stacked content below it, so
     this inset:0 gradient would otherwise stretch down and shadow the
     highlights section too */
  .hero::after {
    display: none;
  }

  .hero img {
    height: 200px;
    width: 100%;
    object-fit: cover;
    display: block;
  }

  .title-overlay {
    position: relative;
    padding: calc(3 * var(--base-spacing)) 0 calc(10 * var(--base-spacing));
    top: 0;
  }

  .title-overlay h1 {
    font-size: 1.71429rem;
    letter-spacing: 2px;
  }

  .title-overlay .subtitle {
    font-size: 0.85714rem;
    margin-top: calc(0.5 * var(--base-spacing));
  }

  /* the 4-card overlay is too cramped on a short mobile hero — pull it out of the
     image entirely and let it run as a solid strip below: the first 3 cards
     (players/post/episode) become a carousel with nav arrows and dots, and
     the queue card stretches full-width underneath it */
  .highlights {
    position: static;
    flex-direction: column;
    background: var(--color-surface-raised);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-top: 2px solid var(--color-border);
  }

  .highlights-carousel {
    display: block;
    width: 100%;
  }

  .highlights-carousel-viewport {
    position: relative;
  }

  .highlights-carousel-track {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }

  .highlights-carousel-track::-webkit-scrollbar {
    display: none;
  }

  /* the extra side padding (beyond .highlight-card's own) keeps text clear of
     the overlaid nav arrows — each is 3*base wide, offset 0.5*base from the edge */
  .highlights-carousel-track .highlight-card {
    flex: 0 0 100%;
    scroll-snap-align: start;
    padding-left: calc(4 * var(--base-spacing));
    padding-right: calc(4 * var(--base-spacing));
  }

  /* z-index pins these above the track's own content — .highlight-card
     descendants may establish their own positioned/stacking context, which
     would otherwise let card content paint over these sibling buttons */
  .carousel-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    z-index: 2;
    top: 50%;
    transform: translateY(-50%);
    width: calc(3 * var(--base-spacing));
    height: calc(3 * var(--base-spacing));
    border: 1px solid rgba(var(--color-accent-rgb), 0.4);
    border-radius: 50%;
    background: rgba(var(--color-bg-rgb), 0.7);
    color: var(--color-accent);
    font-size: 1.14286rem;
    line-height: 1;
    cursor: pointer;
  }

  .carousel-nav--prev {
    left: calc(0.5 * var(--base-spacing));
  }

  .carousel-nav--next {
    right: calc(0.5 * var(--base-spacing));
  }

  .carousel-nav:disabled {
    opacity: 0.35;
    cursor: default;
  }

  .carousel-dots {
    display: flex;
    justify-content: center;
    gap: calc(0.5 * var(--base-spacing));
    padding: calc(0.75 * var(--base-spacing)) 0;
  }

  .carousel-dot {
    width: calc(0.75 * var(--base-spacing));
    height: calc(0.75 * var(--base-spacing));
    border: none;
    border-radius: 50%;
    padding: 0;
    background: rgba(var(--color-accent-rgb), 0.3);
    cursor: pointer;
  }

  .carousel-dot--active {
    background: var(--color-accent);
  }

  .highlight-card {
    border-right: none;
    border-bottom: none;
    padding: calc(1.25 * var(--base-spacing)) calc(2 * var(--base-spacing));
  }

  .highlight-card--queue {
    width: 100%;
    border-top: 1px solid rgba(var(--color-accent-rgb), 0.2);
  }

  .players-row {
    flex-wrap: wrap;
    justify-content: center;
    gap: calc(1 * var(--base-spacing)) calc(1.5 * var(--base-spacing));
  }

  .post-excerpt,
  .episode-desc {
    -webkit-line-clamp: 2;
  }

  #pun-navlinks {
    padding: calc(1 * var(--base-spacing)) calc(1.75 * var(--base-spacing));
  }

  #pun-navlinks a {
    font-size: 0.71429rem;
  }

  .status-avatar {
    width: calc(3.5 * var(--base-spacing));
    height: calc(3.5 * var(--base-spacing));
  }

  .punbb {
    border-left: none;
    border-right: none;
    box-shadow: none;
  }

  /* !important here: #pun-crumbs2's own padding shorthand is set at desktop
     width, so a normal-weight override can never win regardless of specificity */
  .punbb .crumbs,
  #pun-crumbs2 {
    padding-left: calc(1.75 * var(--base-spacing)) !important;
    padding-right: calc(1.75 * var(--base-spacing)) !important;
  }

  /* the desktop "counts next to title" trick relies on fixed pixel offsets that
     only work at desktop widths — abandon it here and fall back to simple stacked flow */
  .category tbody tr {
    flex-wrap: wrap;
    padding: calc(1.5 * var(--base-spacing)) calc(1.75 * var(--base-spacing));
  }

  .category .tclcon {
    max-width: 100%;
  }

  .category .tclcon h3 {
    max-width: 100%;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }

  .category .forum-meta-row {
    margin-top: calc(0.75 * var(--base-spacing));
  }

  .category .forum-meta-row td.tc2 {
    padding-right: calc(1.25 * var(--base-spacing));
  }

  .category .forum-meta-row td.tc3 {
    padding: 0 calc(1.25 * var(--base-spacing));
  }

  .category .forum-meta-row td.tcr {
    flex: 1 1 100%;
    padding-top: calc(1 * var(--base-spacing));
    border-top: 1px dashed rgba(var(--color-border-rgb), 0.3);
  }

  /* .forum mobile: the same boxed-card treatment as the usertable/online-list
     cards above (background/border/radius per row) instead of the bare
     divider list this table used until now, so every card list on the site
     reads as one system. Title/username are unbounded length, but the
     counts and pagination next to them are short and effectively
     fixed-width — forcing the unbounded fields (tcl, tcr) onto their own
     full line means the fixed pair (tc2/tc3) always lands together on the
     line between them, regardless of how long the title is. */
  .forum tbody tr {
    padding: calc(1.25 * var(--base-spacing)) calc(1 * var(--base-spacing));
    margin-bottom: calc(1 * var(--base-spacing));
    background: rgba(var(--color-border-rgb), 0.06);
    border: 1px solid rgba(var(--color-border-rgb), 0.25);
    border-radius: calc(0.5 * var(--base-spacing));
  }

  .forum tbody tr:last-child {
    margin-bottom: 0;
  }

  /* title+started-by is this card's identity line — same divider treatment
     as .usertable's username row */
  .forum td.tcl {
    flex: 1 1 100%;
    padding-bottom: calc(0.75 * var(--base-spacing));
    margin-bottom: calc(0.5 * var(--base-spacing));
    border-bottom: 1px solid rgba(var(--color-border-rgb), 0.25);
  }

  /* fixed-length stat pair, side by side as label:value — the border-right
     divider from the desktop skin only made sense flush inside a full row;
     floating alone here it read as a stray mark, so it's dropped in favor
     of the same ::before label convention used throughout the other cards */
  .forum td.tc2,
  .forum td.tc3 {
    flex: 1 1 50%;
    width: auto;
    box-sizing: border-box;
    border-right: none;
    text-align: left;
  }

  .forum td.tc2::before {
    content: "Îòâåòîâ: ";
    color: var(--color-link);
  }

  .forum td.tc3::before {
    content: "Ïðîñìîòðîâ: ";
    color: var(--color-link);
  }

  /* search/active-topics remaps the columns: tc2 is the source forum's name
     (its own desktop rule pins it to 120px for the inline ellipsis look,
     which isn't needed once it has the full card width to itself), tc3 is
     a reply count rather than a view count */
  #pun-searchtopics .forum td.tc2 {
    width: auto;
  }

  #pun-searchtopics .forum td.tc2::before {
    content: "Ôîðóì: ";
  }

  #pun-searchtopics .forum td.tc3::before {
    content: "Îòâåòîâ: ";
  }

  .forum td.tcr {
    flex: 1 1 100%;
    width: auto;
    padding-top: calc(0.75 * var(--base-spacing));
    margin-top: calc(0.5 * var(--base-spacing));
    border-top: 1px solid rgba(var(--color-border-rgb), 0.25);
  }

  /* the overlaid title/toolbar row has no room to share a line at mobile widths —
     drop the overlay and stack the toolbar back under the title */
  .punbb #pun-main>h1 {
    padding: calc(1.25 * var(--base-spacing)) calc(1.5 * var(--base-spacing));
  }

  .punbb #pun-main>h1 span {
    font-size: 0.92857rem;
    letter-spacing: 2px;
  }

  .punbb #pun-main>h1+.linkst {
    grid-row: 2;
    position: static;
    z-index: auto;
    justify-content: center;
    text-align: center;
    border-bottom: 1px dashed rgba(var(--color-border-rgb), 0.3);
    color: var(--color-text-muted);
  }

  .punbb #pun-main>h1+.linkst .pagelink strong {
    color: var(--color-heading);
  }

  /* buttons are off the banner and back on the panel background here — restore
     the normal button chrome instead of the flush-embedded header treatment */
  .punbb #pun-main>h1+.linkst .postlink {
    margin-left: 0;
    justify-content: center;
    gap: calc(1 * var(--base-spacing));
  }

  .punbb #pun-main>h1+.linkst .postlink a {
    background: linear-gradient(180deg, var(--color-banner-bg-light) 0%, var(--color-banner-bg) 100%);
    border: 1px solid var(--color-accent);
    border-radius: calc(0.5 * var(--base-spacing));
    padding: calc(0.5 * var(--base-spacing)) calc(1.25 * var(--base-spacing));
    font-size: 0.78571rem;
    color: var(--color-text-on-dark);
  }

  .punbb #pun-main>h1+.linkst .postlink span+span {
    border-left: none;
  }

  /* stack pagelink/buttons/subscribe instead of the lopsided line-break wrap
     that flex-wrap alone produces once the row no longer fits. align-items
     has to be overridden too — the base rule's "center" carries into column
     mode as the cross axis (width), which would keep every row shrunk to
     content instead of letting them stretch full-width below */
  .punbb .linksb,
  .punbb .linkst {
    flex-direction: column;
    align-items: stretch;
    text-align: center;
    padding: calc(1 * var(--base-spacing)) calc(1.5 * var(--base-spacing));
  }

  /* the forum platform's own stylesheet fixes .postlink.long at width: 30em
     for the desktop two-button row — that overrides our percentage widths
     below and eats the right-side padding once buttons stack, so pin it
     back to the container's width here */
  .punbb .linksb .postlink,
  .punbb .linkst .postlink {
    flex-wrap: wrap;
    width: 100%;
  }

  /* postlink's buttons are each wrapped in their own <span> — that span, not
     the <a>, is the flex item postlink lays out, so it has to stretch too.
     the forum platform's own stylesheet puts a right-padding spacer on the
     first span (for the desktop side-by-side layout) — zero it out here since
     stacked buttons space themselves via the postlink gap instead */
  .punbb .linkst .postlink>span,
  .punbb .linksb .postlink>span {
    width: 100%;
    padding: 0;
  }

  .punbb .linksb .postlink a,
  .punbb .linkst .postlink a,
  .punbb .linksb .subscribelink a {
    box-sizing: border-box;
    width: 100%;
  }

  /* .font-size-control (see footer.html) isn't wrapped in its own <span> like
     the "Îòâåòèòü" link above — it's the plain div the widget script
     appends — so it needs the same full-width stacking spelled out directly
     instead of inheriting it from the >span/a rules above. */
  .punbb .linksb .font-size-control {
    box-sizing: border-box;
    width: 100%;
    justify-content: center;
  }

  /* profile sidebar stacks above the post body instead of sitting beside it */
  .messages-container .post {
    margin: calc(2 * var(--base-spacing)) 0 0;
  }

  .topic .post .container,
  .messages-container .post .container {
    flex-direction: column;
  }

  .post-author {
    flex: 0 0 auto;
    width: 100%;
    box-sizing: border-box;
    border-right: none;
    border-bottom: 2px solid var(--color-accent);
    padding: calc(0.75 * var(--base-spacing)) calc(1.25 * var(--base-spacing));
    text-align: left;
    top: 0;
  }

  /* the scrim/border lives on the list box itself (colors.css), so on mobile the
     grid goes on .post-author ul directly instead of dissolving it away —
     letting the li's be placed explicitly instead of stacking in DOM order */
  .post-author ul {
    display: grid;
    grid-template-columns: 64px 1fr;
    justify-content: start;
    gap: var(--base-spacing);
    align-items: center;
    position: relative;
    z-index: 2;
  }

  .post-author li {
    padding: calc(0.125 * var(--base-spacing)) 0;
  }

  /* row 1-2: username, title stacked plainly beside the avatar (no badge/pill) */
  .post-author .pa-author {
    grid-column: 2;
    grid-row: 1;
  }

  .post-author .pa-title {
    grid-column: 2;
    grid-row: 2;
    width: auto;
    margin: 0;
    border-top: none;
    padding-top: 0;
  }

  /* avatar (real or placeholder) sits beside username + title */
  .post-author .pa-avatar,
  .post-author.no-avatar::before {
    grid-column: 1;
    grid-row: 1 / 3;
    align-self: start;
  }

  .post-author .pa-avatar img,
  .post-author.no-avatar::before {
    width: 64px;
    height: 64px;
    margin: 0;
  }

  .topic .post h3,
  .messages-container .post h3 {
    padding-left: calc(3 * var(--base-spacing));
  }

  /* fld3 doesn't fit this compact layout */
  .post-author .pa-fld3 {
    display: none;
  }

  /* plashka banner dropped on mobile, both here and on the profile view
     page's card — the shared class covers both */
  .profile-card-plashka {
    display: none;
  }

  /* .pa-stats (wrapper added by JS) spans the full row below avatar/title as
     one bar, splitting evenly across whichever of these fields this user has set */
  .post-author .pa-stats {
    order: 1;
    grid-column: 1 / -1;
    margin: 0;
  }

  .post-author .pa-stats>li {
    padding: calc(0.5 * var(--base-spacing)) calc(0.5 * var(--base-spacing)) calc(0.375 * var(--base-spacing));
    text-align: center;
  }

  .post-author .pa-positive {
    order: 1;
    grid-column: 1 / -1;
    justify-self: start;
    box-sizing: border-box;
    width: auto;
    margin: 0;
    padding: calc(0.5 * var(--base-spacing)) calc(0.5 * var(--base-spacing)) calc(0.375 * var(--base-spacing));
    background: var(--pa-panel-bg);
    border: var(--pa-panel-border);
    border-radius: var(--pa-panel-radius);
  }

  .post-author .pa-positive .fld-name {
    display: block;
    font-size: 0;
  }

  .post-author .pa-positive .fld-name a::before {
    font: normal 900 10px "Font Awesome 6 Free";
    color: color-mix(in srgb, var(--pa-neutral) 85%, transparent);
    content: "\f164";
    /* fa-thumbs-up */
  }

  /* everything else keeps stacking below, one full-width row each, after the icon stats */
  .post-author .pa-reg,
  .post-author .pa-invites,
  .post-author .pa-time-visit,
  .post-author .pa-ip {
    order: 2;
    grid-column: 1 / -1;
    width: auto;
    margin: 0;
  }


  .post-links {
    flex-basis: 100%;
    margin-left: 0;
  }

  .post-content,
  .post-rating,
  .post-links {
    padding-left: calc(2 * var(--base-spacing));
    padding-right: calc(2 * var(--base-spacing));
  }

  #post-form legend,
  #post-form .fs-box,
  #post-form .formsubmit,
  #post-form>p {
    padding-left: calc(1.75 * var(--base-spacing));
    padding-right: calc(1.75 * var(--base-spacing));
  }

  /* desktop pulls this up over the legend's own line with a negative
     margin, assuming the legend's instruction text fits on one line — at
     mobile widths that text is much more likely to wrap to two lines, and
     the overlap hack would collide with the wrapped second line. Drop it
     into normal flow below the legend instead. */
  #togglePreview {
    float: none;
    display: block;
    margin: calc(0.5 * var(--base-spacing)) 0 0;
  }

  #post-form .formsubmit,
  #post-form>p {
    flex-direction: column;
    align-items: stretch;
  }

  /* auto-margin push only makes sense inline, next to the buttons row — stacked
     column layout already puts it on its own line */
  #post-form>p>.checkfield {
    margin-left: 0;
  }

  /* submit + preview stack full-width instead of sitting side by side */
  #post-form>p>span:first-child {
    flex-direction: column;
    align-items: stretch;
  }

  #post-form>p>span:first-child .button {
    width: 100%;
    text-align: center;
  }

  /* the fixed 32px-per-button offsets used to line panels up with their desktop
     toolbar column don't hold once the toolbar wraps onto multiple lines — drop
     back into normal flow, directly under the toolbar, instead */
  #post-form .container[id$="-area"] {
    position: static !important;
    margin-top: calc(1 * var(--base-spacing));
    max-width: 100%;
    box-sizing: border-box;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* bigger tap targets than the 32px desktop row */
  #form-buttons td,
  #tags>table td {
    flex-basis: 40px;
    height: 40px;
  }

  #form-buttons td::before,
  #tags>table td::before {
    font-size: 1.14286rem;
  }

  /* ---- userlist ---- */
  .formal .fs-box.inline {
    flex-direction: column;
  }

  .formal .inputfield input[type="text"],
  .formal .selectfield select {
    width: 100%;
  }

  #messages td.pmtc22 {
    white-space: normal;
  }

  /* ---- plain data tables (online users list + member list + respect
     list): real multi-column grids don't fit narrow screens, so all three
     stack each row's cells identically, with a hardcoded label per column
     standing in for the now-hidden header ---- */
  .online-list thead,
  .usertable thead,
  #pun-respect thead {
    display: none;
  }

  .online-list table,
  .online-list tbody,
  .online-list tr,
  .online-list td,
  .usertable table,
  .usertable tbody,
  .usertable tr,
  .usertable td,
  #pun-respect table,
  #pun-respect tbody,
  #pun-respect tr,
  #pun-respect td {
    display: block;
  }

  .online-list tr,
  .usertable tr,
  #pun-respect tr {
    padding: calc(1 * var(--base-spacing)) 0;
  }

  .online-list td,
  .usertable td,
  #pun-respect td {
    padding: calc(0.25 * var(--base-spacing)) 0;
    text-align: left;
    white-space: normal;
  }

  /* .tc3 carries `white-space: nowrap` + `text-align: right` in the desktop
     table skin (style.css ~1024) at higher specificity than the reset above,
     so it survives into the stacked mobile layout and forces a horizontal
     scrollbar on the whole table — reset it explicitly here. #pun-respect's
     equivalent right-aligned column is .tcr, not .tc3 (see desktop skin). */
  .online-list td.tc3,
  .usertable td.tc3,
  #pun-respect td.tcr {
    text-align: left;
    white-space: normal;
  }

  /* the forum platform's own extra.css pins this column to 25% width via
     `#pun-online .tcl.action` (an ID selector we don't control, at higher
     specificity than a plain class rule) — that 25% is fine as a table
     column, but on the stacked mobile card it squeezes "Ñìîòðèò ñïèñîê
     àêòèâíûõ ïîëüçîâàòåëåé" down to ~84px, wrapping one word per line.
     `#pun-online` here matches it back to reclaim full width; the extra
     .action class pushes the class-count tiebreak in our favor too. */
  #pun-online .online-list td.action {
    width: 100%;
  }

  /* ---- boxed-card shell shared by all three tables: a bare stacked list
     reads as one continuous run with no boundary between rows, so every row
     becomes its own card. .online-list/.usertable additionally divide off a
     username heading; #pun-respect has no single identity column to lead
     with (see labels below), so it skips that divider and labels every
     field instead. usertable's extra stat fields need the 2-col grid added
     further below. ---- */
  .online-list tbody tr,
  .usertable tbody tr,
  #pun-respect tbody tr {
    padding: calc(1.25 * var(--base-spacing)) calc(1 * var(--base-spacing));
    margin-bottom: calc(1 * var(--base-spacing));
    background: rgba(var(--color-border-rgb), 0.06);
    border: 1px solid rgba(var(--color-border-rgb), 0.25);
    border-radius: calc(0.5 * var(--base-spacing));
  }

  .online-list tbody tr:last-child,
  .usertable tbody tr:last-child,
  #pun-respect tbody tr:last-child {
    margin-bottom: 0;
  }

  .online-list td.username,
  .usertable tbody td.username {
    padding-bottom: calc(0.75 * var(--base-spacing));
    margin-bottom: calc(0.25 * var(--base-spacing));
    border-bottom: 1px solid rgba(var(--color-border-rgb), 0.25);
  }

  .online-list td.action::before {
    content: "Äåéñòâèå: ";
    color: var(--color-link);
  }

  .online-list td.tc3::before {
    content: "Âðåìÿ: ";
    color: var(--color-link);
  }

  /* #pun-respect column labels — table has no single self-explanatory
     identity column (unlike a username), so every field gets one, including
     the first. The empty-state row ("Ê Õ ïîêà íå âûðàæàëè...") is a single
     td.tcl with colspan, not a real data row — :not([colspan]) keeps the
     label off it. */
  #pun-respect td.tcl:not([colspan])::before {
    content: "Êîãäà: ";
    color: var(--color-link);
  }

  #pun-respect td.tc2::before {
    content: "×òî: ";
    color: var(--color-link);
  }

  #pun-respect td.tc3:not(.tc4)::before {
    content: "Êòî: ";
    color: var(--color-link);
  }

  #pun-respect td.tc4::before {
    content: "Çà ÷òî: ";
    color: var(--color-link);
  }

  #pun-respect td.tcr::before {
    content: "Â òåìå: ";
    color: var(--color-link);
  }

  .usertable td.user_title::before {
    content: "Ñòàòóñ: ";
    color: var(--color-link);
  }

  .usertable td.relation::before {
    content: "Óâàæåíèå: ";
    color: var(--color-link);
  }

  .usertable td.num_posts::before {
    content: "Ñîîáùåíèé: ";
    color: var(--color-link);
  }

  .usertable td.registered::before {
    content: "Çàðåãèñòðèðîâàí: ";
    color: var(--color-link);
  }

  .usertable td.last_visit::before {
    content: "Áûë: ";
    color: var(--color-link);
  }

  /* ---- usertable member cards: on top of the shared card shell above,
     the five stat fields (status/relation/posts/registered/last_visit)
     read better as a compact label:value grid than as five full-width
     lines each mostly empty space — .online-list has no equivalent since
     its 3 columns are already a single line of running text (no avatar,
     no stat block), so it stays with plain block stacking.
     `tbody` in every selector here matches the desktop
     `.usertable tbody tr`/`tbody tr:hover` rules' specificity (0,2,0) so
     these mobile overrides actually win by source order instead of losing
     to the desktop rule despite the media query. ---- */
  .usertable tbody tr {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: calc(1 * var(--base-spacing));
    row-gap: calc(0.5 * var(--base-spacing));
  }

  .usertable tbody td {
    display: flex;
    justify-content: flex-start;
    align-items: baseline;
    gap: calc(0.5 * var(--base-spacing));
    padding: 0;
  }

  .usertable tbody td::before {
    flex: 0 0 auto;
  }

  /* a long status/group name would otherwise wrap the "Ñòàòóñ: " label onto
     its own line inside the narrow grid column — truncate it instead. Not a
     flex row like the other stat cells: text-overflow:ellipsis needs one
     plain text flow (label + value) to clip as a unit, which a flex layout
     (label and value as separate boxes) can't do */
  .usertable tbody td.user_title {
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* the date value itself is short but "2026-08-30" carries soft-wrap
     opportunities at each hyphen, so normal wrapping still breaks it
     mid-date once label + value don't both fit on one line */
  .usertable tbody td.registered {
    white-space: nowrap;
  }

  .usertable tbody td.username {
    grid-column: 1 / -1;
    justify-content: flex-start;
    align-items: center;
    gap: calc(1 * var(--base-spacing));
  }

  .usertable .avatar-image {
    width: 40px !important;
    height: 40px !important;
  }

  .scroll-nav {
    right: calc(1.5 * var(--base-spacing));
    bottom: calc(1.5 * var(--base-spacing));
  }

  /* top: 1.5 * base-spacing (matching .scroll-nav's own mobile inset) would
     sit under the header bar's right-side controls (user menu, mail) at this
     width — push it below the header instead */
  .settings-drawer-toggle {
    top: calc(8 * var(--base-spacing));
    right: calc(1.5 * var(--base-spacing));
  }

  /* toggle shrinks to 4.5 * base-spacing tall at this width (.scroll-nav-btn
     override below) and sits at top: 8 instead of 3 — keep the same 1 *
     base-spacing gap under it */
  .settings-drawer {
    top: calc(13.5 * var(--base-spacing));
  }

  /* below ~1082px the parchment panel runs edge-to-edge, so there's no dark
     margin for the buttons to float in — they sit over live content instead.
     Ease that with the same translucent-blur treatment already used for
     overlays on the hero (.highlights), instead of a solid opaque block. */
  .scroll-nav-btn {
    width: calc(4.5 * var(--base-spacing));
    height: calc(4.5 * var(--base-spacing));
    background: rgba(var(--color-bg-rgb), 0.55);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
  }
}

#pun-index #pun-main h1,
.usertable h2,
.forum h2,
#pun-viewtopic .topic h2,
.translatelink,
#pun-live-rusff {
  display: none !important;
}

/* ============ WORLD TIMELINE (articles/timeline.html) ============
   Standalone page, not a per-country lore article — reuses .lore-article
   for the shared paper/type/spacing shell plus .lore-badge/.lore-tagline/
   .lore-tab-input/.lore-tabs/.lore-tab/.lore-panels/.lore-panel verbatim
   (era switching is the exact same checked-radio + nth-of-type mechanism as
   the country template, capped at 6 the same way — see colors.css). It
   deliberately skips .lore-intro's two-column/aside layout — this page has
   no single country crest to show — and everything below is new: the era
   cards double as the nth-of-type-wired tab labels, and the scope filter
   chips + timeline entries are rendered from JSON by the inline script in
   articles/timeline.html (post it wrapped in [html]...[/html] — without
   that BBCode tag the forum won't run the inserted <script>). Colors:
   --tl-* vars in colors.css. */

.chronicle-filter {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: calc(1 * var(--base-spacing));
  margin: calc(2.5 * var(--base-spacing)) 0 calc(3 * var(--base-spacing));
  padding-bottom: calc(1.5 * var(--base-spacing));
  border-bottom: 1px solid var(--lc-paper-deep);
}

.chronicle-filter-label {
  font-family: var(--font-heading);
  font-size: 0.85714rem;
  letter-spacing: 0.5px;
  opacity: 0.85;
}

.chronicle-filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: calc(0.75 * var(--base-spacing));
}

/* text stays full-strength even when unpicked — fading the whole chip via
   opacity (as before) faded the label along with the border, which is the
   "text too thin" complaint. Unselected/hover/selected are now three
   distinct border+background states instead of an opacity ramp. */
.chronicle-chip {
  display: inline-flex;
  align-items: center;
  padding: calc(0.375 * var(--base-spacing)) calc(1.25 * var(--base-spacing));
  border: 1px solid var(--lc-paper-deep);
  border-radius: 14px;
  font-size: 0.85714rem;
  color: var(--lc-ink);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}

.chronicle-chip:hover {
  border-color: color-mix(in srgb, var(--chip-accent, var(--tl-accent)) 50%, var(--lc-paper-deep));
}

.chronicle-filter-input:checked+.chronicle-chip {
  border-color: var(--chip-accent, var(--tl-accent));
  color: var(--chip-accent, var(--tl-accent));
  background: color-mix(in srgb, var(--chip-accent, var(--tl-accent)) 14%, transparent);
}

.chronicle-chip[data-scope="laterium"] {
  --chip-accent: var(--tl-laterium);
}

.chronicle-chip[data-scope="alsar"] {
  --chip-accent: var(--tl-alsar);
}

.chronicle-chip[data-scope="tianxia"] {
  --chip-accent: var(--tl-tianxia);
}

.chronicle-chip[data-scope="empire"] {
  --chip-accent: var(--tl-empire);
}

.chronicle-chip[data-scope="general"] {
  --chip-accent: var(--tl-general);
}

/* era cards replace .lore-tab's thin underlined-label look entirely —
   overrides win on source order (this section loads after LORE ARTICLE
   TEMPLATE in colors.css), same specificity */
.lore-article .chronicle-eras {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: calc(1.5 * var(--base-spacing));
  border-bottom: none;
  padding-bottom: 0;
  margin: 0 0 calc(3 * var(--base-spacing));
}

/* each era keeps its own color permanently, not only once picked —
   otherwise every unselected card is the same tan box and reads as one
   undifferentiated row. Five slots (--lc-accent plus the --lc-sub-1..4 set
   .lore-card cycles) rather than four, since periods.json ships exactly
   5 eras today — a 4-cycle would land era 1 and era 5 on the same hue */
.chronicle-era-card:nth-of-type(5n+1) {
  --era-accent: var(--lc-accent);
}

.chronicle-era-card:nth-of-type(5n+2) {
  --era-accent: var(--lc-sub-1);
}

.chronicle-era-card:nth-of-type(5n+3) {
  --era-accent: var(--lc-sub-2);
}

.chronicle-era-card:nth-of-type(5n+4) {
  --era-accent: var(--lc-sub-3);
}

.chronicle-era-card:nth-of-type(5n+5) {
  --era-accent: var(--lc-sub-4);
}

/* no fill — a left rule in the era's own color, echoing the
   .lore-callout/.lore-thesis left-border language elsewhere in this
   template instead of another SaaS-style tinted box. .chronicle-era-card
   also carries the base .lore-tab class, which dims unselected tabs to
   opacity 0.6 — that silently faded every card's text here. ".lore-article
   .lore-tab" is two classes, so a bare ".chronicle-era-card" rule (one
   class) can't out-specificity it; the three-class prefix below is what
   actually cancels it. */
.lore-article .chronicle-eras .chronicle-era-card {
  display: flex;
  flex-direction: column;
  gap: calc(0.5 * var(--base-spacing));
  padding: calc(0.25 * var(--base-spacing)) 0 calc(0.25 * var(--base-spacing)) calc(1.25 * var(--base-spacing));
  border-left: 3px solid color-mix(in srgb, var(--era-accent) 55%, transparent);
  opacity: 1;
}

.chronicle-era-name {
  font-family: var(--font-heading);
  font-size: 1.11429rem;
  font-weight: 700;
  color: var(--era-accent);
}

.chronicle-era-range {
  font-size: 0.8rem;
  font-style: italic;
  color: var(--lc-ink);
  opacity: 0.8;
}

.chronicle-era-oneliner {
  font-size: 0.94286rem;
  font-weight: 400;
  color: var(--lc-ink);
  opacity: 0.95;
}

/* selected era solidifies its own rule instead of switching to a shared
   gold or filling a background — same positional wiring as the
   panel/tab-label rules in colors.css. Needs the ".lore-article" prefix to
   match that rule's specificity: colors.css also sets border-bottom-color
   here (the .lore-tab selected-tab underline), and without the prefix this
   selector is one class short and silently loses that property to it. */
.lore-article .chronicle-era-input:nth-of-type(1):checked~.chronicle-eras .chronicle-era-card:nth-of-type(1),
.lore-article .chronicle-era-input:nth-of-type(2):checked~.chronicle-eras .chronicle-era-card:nth-of-type(2),
.lore-article .chronicle-era-input:nth-of-type(3):checked~.chronicle-eras .chronicle-era-card:nth-of-type(3),
.lore-article .chronicle-era-input:nth-of-type(4):checked~.chronicle-eras .chronicle-era-card:nth-of-type(4),
.lore-article .chronicle-era-input:nth-of-type(5):checked~.chronicle-eras .chronicle-era-card:nth-of-type(5),
.lore-article .chronicle-era-input:nth-of-type(6):checked~.chronicle-eras .chronicle-era-card:nth-of-type(6) {
  border-left-width: 5px;
  border-left-color: var(--era-accent);
  border-bottom-color: transparent;
}

.chronicle-era-input:nth-of-type(1):checked~.chronicle-eras .chronicle-era-card:nth-of-type(1) .chronicle-era-oneliner,
.chronicle-era-input:nth-of-type(2):checked~.chronicle-eras .chronicle-era-card:nth-of-type(2) .chronicle-era-oneliner,
.chronicle-era-input:nth-of-type(3):checked~.chronicle-eras .chronicle-era-card:nth-of-type(3) .chronicle-era-oneliner,
.chronicle-era-input:nth-of-type(4):checked~.chronicle-eras .chronicle-era-card:nth-of-type(4) .chronicle-era-oneliner,
.chronicle-era-input:nth-of-type(5):checked~.chronicle-eras .chronicle-era-card:nth-of-type(5) .chronicle-era-oneliner,
.chronicle-era-input:nth-of-type(6):checked~.chronicle-eras .chronicle-era-card:nth-of-type(6) .chronicle-era-oneliner {
  opacity: 1;
}

.chronicle-detail .chronicle-era-range {
  margin: 0 0 calc(1 * var(--base-spacing));
}

/* spine is a fading gradient rather than a flat rule — reads as an ink
   stroke that trails off at both ends instead of a hard-stopped ruler */
.chronicle-timeline {
  list-style: none;
  margin: calc(2.5 * var(--base-spacing)) 0 0;
  padding: calc(1 * var(--base-spacing)) 0 calc(1 * var(--base-spacing)) calc(3 * var(--base-spacing));
  position: relative;
}

.chronicle-timeline::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: linear-gradient(to bottom, transparent, var(--lc-paper-deep) 8%, var(--lc-paper-deep) 92%, transparent);
}

.chronicle-item {
  position: relative;
  margin-bottom: calc(2.75 * var(--base-spacing));
}

.chronicle-item:last-child {
  margin-bottom: 0;
}

/* wax-seal marker: ring + halo instead of a plain dot, echoing the
   .lore-seal ring-and-dot motif used in h2 elsewhere on this page */
.chronicle-item::before {
  content: "";
  position: absolute;
  left: calc(-3 * var(--base-spacing) - 6px);
  top: calc(0.3 * var(--base-spacing));
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--lc-paper);
  border: 2px solid var(--item-accent, var(--tl-accent));
  box-shadow: 0 0 0 3px var(--lc-paper), 0 0 0 4px color-mix(in srgb, var(--item-accent, var(--tl-accent)) 35%, transparent);
}

.chronicle-item[data-scope="laterium"] {
  --item-accent: var(--tl-laterium);
}

.chronicle-item[data-scope="alsar"] {
  --item-accent: var(--tl-alsar);
}

.chronicle-item[data-scope="tianxia"] {
  --item-accent: var(--tl-tianxia);
}

.chronicle-item[data-scope="empire"] {
  --item-accent: var(--tl-empire);
}

.chronicle-item[data-scope="general"] {
  --item-accent: var(--tl-general);
}

.chronicle-item-meta {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: calc(0.25 * var(--base-spacing)) calc(1.25 * var(--base-spacing));
  margin: 0;
}

/* year carries the accent instead of a separate pill — one color signal
   doing double duty as both date and category marker, tied to the dot */
.chronicle-year {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.14286rem;
  color: var(--item-accent, var(--tl-accent));
  white-space: nowrap;
}

.chronicle-item h4 {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 1.02857rem;
  font-weight: 700;
}

/* scope reads as a plain byline, not a boxed tag — keeps the item from
   stacking three accent-colored shapes (dot + pill + year) on one line */
.chronicle-scope-tag {
  display: block;
  font-size: 0.78571rem;
  font-style: italic;
  color: var(--item-accent, var(--tl-accent));
  opacity: 0.75;
  margin: calc(0.375 * var(--base-spacing)) 0 calc(0.75 * var(--base-spacing));
}

.chronicle-item p {
  margin: 0;
  font-size: 0.97143rem;
  max-width: none;
}

.chronicle-empty {
  font-style: italic;
  opacity: 0.65;
  margin: calc(2 * var(--base-spacing)) 0 0;
}

@media (max-width: 640px) {
  .chronicle-eras {
    grid-template-columns: 1fr;
  }

  .chronicle-filter {
    align-items: flex-start;
  }
}

/* ============ CHARACTER ROSTER (articles/characters.html) ============
   Standalone directory page, not a per-country lore article — reuses
   .lore-article for the shared paper/type/spacing shell plus .lore-badge/
   .lore-tagline verbatim, but everything below is its own mechanism: native
   <details>/<summary> per territory instead of the radio-tab switcher (this
   list grows over time and isn't capped at 6 the way a country's tab set
   is), rendered from JSON by the inline script in articles/characters.html
   (see articles/characters-data.json — same fetch-and-render pattern as
   articles/timeline.html, different shape of data). Every territory uses
   the same --lc-accent — the LORE ARTICLE TEMPLATE's own default accent
   (colors.css), maroon, same as any country article that doesn't override
   it inline — rather than timeline.html's per-country --tl-* tinting: this
   page is a directory, not a country article, and a different color per
   entry here would read as ranking or grouping rather than just "this is
   the accent color the page uses".

   Inside a territory: one centered "masthead" card for the seat of power
   (.roster-hero, modelled on a reference roster's ruler card — office +
   title line + the court as a plain two-column list, not another boxed
   component), then a card grid of that territory's lands (.roster-lands),
   each land a bordered card listing its houses as plain rows — bold name,
   dash, role — instead of the old per-family crest-and-list block. Every
   person anywhere on the page (court, local ruler, house member) renders
   through the one .roster-row line so scanning the page means reading rows,
   not decoding three different card shapes. */

.roster-intro {
  margin: 0 0 calc(1 * var(--base-spacing));
}

/* the one place each status icon's meaning is spelled out in full — every
   .roster-status badge on the page is icon-only, so a reader learns what
   they mean once here instead of re-reading the same label on every name */
.roster-legend {
  display: flex;
  flex-wrap: wrap;
  gap: calc(0.5 * var(--base-spacing)) calc(2 * var(--base-spacing));
  margin: 0 0 calc(2 * var(--base-spacing));
}

.roster-legend-item {
  display: flex;
  align-items: center;
  gap: calc(0.5 * var(--base-spacing));
  margin: 0;
  font-size: 0.85714rem;
  opacity: 0.8;
}

.roster-territory {
  border: 1px solid var(--lc-paper-deep);
  border-left: 4px solid var(--lc-accent);
  border-radius: 0 4px 4px 0;
  margin-bottom: calc(1.25 * var(--base-spacing));
}

.roster-territory:last-child {
  margin-bottom: 0;
}

.roster-territory-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(1.5 * var(--base-spacing));
  padding: calc(1 * var(--base-spacing)) calc(1.5 * var(--base-spacing));
  background: color-mix(in srgb, var(--lc-accent) 7%, var(--lc-paper));
  cursor: pointer;
  list-style: none;
}

.roster-territory[open]>.roster-territory-summary {
  border-bottom: 2px solid var(--lc-accent);
}

.roster-territory-summary::-webkit-details-marker {
  display: none;
}

.roster-territory-summary:focus-visible {
  outline: 2px solid var(--lc-accent);
  outline-offset: -2px;
}

.roster-territory-heading {
  display: flex;
  flex-direction: column;
  gap: calc(0.25 * var(--base-spacing));
}

/* the name is a real h2, so it picks up .lore-article h2's own flex layout
   and — the point of making it a heading rather than a span — its
   .lore-seal ring-and-dot mark for free (colors.css): the same emblem every
   other section title on the site carries, instead of a plain text label */
.roster-territory .roster-territory-name {
  margin: 0;
  font-size: 1.15714rem;
  color: var(--lc-accent);
}

.roster-territory-count {
  font-size: 0.85714rem;
  opacity: 0.7;
}

/* plain triangle, rotates open — no chevron glyph needed from the icon font */
.roster-territory-toggle {
  flex: none;
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid var(--lc-accent);
  transition: transform 0.2s;
}

.roster-territory[open] .roster-territory-toggle {
  transform: rotate(180deg);
}

.roster-territory-body {
  padding: 0 calc(1.5 * var(--base-spacing)) calc(1.5 * var(--base-spacing));
}

/* shared small uppercase heading-font label — a seat's office title, a local
   ruler's title, same idiom as .lore-facts dt */
.roster-eyebrow {
  font-family: var(--font-heading);
  font-size: 0.9rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--lc-accent);
  font-weight: 600;
}

/* ---- seat of power: the Íàìåñòíèê's office and, where the territory has
   one, its hereditary ruling family (e.g. Äîì Îñíîâàòåëüíèöû in Àëüñàð) —
   the two sit side by side as equals (.roster-hero-heads--split) rather
   than one subordinate to the other, since neither outranks the other in
   how the territory is actually run. A territory with no ruling family
   (Ëàòåðèóì, Òÿíüñÿ) just gets the one head, full width. The court sits
   below, spanning both — it serves the office, not one house. ---- */
.roster-hero {
  text-align: center;
  margin: 0 calc(-1.5 * var(--base-spacing)) calc(1.5 * var(--base-spacing));
  padding: calc(1.5 * var(--base-spacing)) calc(3 * var(--base-spacing));
  background: color-mix(in srgb, var(--lc-accent) 6%, var(--lc-paper));
}

.roster-hero-heads {
  display: grid;
  grid-template-columns: 1fr;
}

.roster-hero-heads--split {
  grid-template-columns: 1fr 1fr;
}

.roster-hero-heads--split .roster-hero-head:first-child {
  padding-right: calc(1.5 * var(--base-spacing));
}

.roster-hero-heads--split .roster-hero-head:last-child {
  padding-left: calc(1.5 * var(--base-spacing));
  border-left: 1px solid var(--lc-paper-deep);
}

.roster-hero-emblem {
  width: 56px;
  height: 56px;
  margin: 0 auto calc(0.75 * var(--base-spacing));
  border: 2px solid var(--lc-accent);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.roster-hero-emblem i {
  font-size: 1.35rem;
  color: var(--lc-accent);
}

.roster-hero-title {
  margin: 0 0 calc(0.35 * var(--base-spacing));
}

.roster-hero-lede {
  margin: 0 0 calc(0.35 * var(--base-spacing));
  font-size: 1.05714rem;
  line-height: 1.5;
}

.roster-hero-lede strong {
  color: var(--lc-accent);
}

/* ---- hero card sections below the heads: currently just the court, but
   the same divider-plus-label treatment as a head's own label so the page
   keeps one visual idiom for "a labelled group of rows" ---- */
.roster-hero-section {
  margin-top: calc(1.25 * var(--base-spacing));
  padding-top: calc(1 * var(--base-spacing));
  border-top: 1px solid var(--lc-paper-deep);
  text-align: left;
}

.roster-hero-section-label {
  margin: 0 0 calc(0.5 * var(--base-spacing));
}

/* a plain two-column list of rows, not another boxed component — one card,
   one visual idiom, the rows do the rest */
.roster-hero-rows {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: calc(0.3 * var(--base-spacing)) calc(2 * var(--base-spacing));
  text-align: left;
}

/* inside a half-width head there's no room for two columns of rows */
.roster-hero-rows--stack {
  grid-template-columns: 1fr;
}

/* ---- one person, one line, everywhere on the page: bold name, dash, role
   (plus note folded in as a trailing clause) — this is the "clear character
   row" the whole page is built around ---- */
.roster-row {
  margin: 0 0 calc(0.35 * var(--base-spacing));
  font-size: 0.93429rem;
  line-height: 1.5;
}

.roster-row:last-child {
  margin-bottom: 0;
}

.roster-row strong {
  font-weight: 700;
  color: var(--lc-accent);
}

/* a linked name (not every character has a profile to link to) keeps the
   same accent color as a plain one — only the underline says it's clickable,
   so the page doesn't read as "some names are colored differently" */
.roster-row strong a,
.roster-hero-lede strong a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--lc-accent) 45%, transparent);
  text-underline-offset: 2px;
}

.roster-row strong a:hover,
.roster-hero-lede strong a:hover {
  text-decoration-color: currentColor;
}

/* ---- character status flags — icon only, right next to the name, raised
   like a footnote marker; the label for each lives once in .roster-legend
   at the top of the page instead of repeating text on every badge. Two
   independent flags (wanted/dead) share this same shape and only differ
   in color, so a second status reads as "another one of these", not a
   new kind of thing on the page ---- */
.roster-status {
  margin-left: calc(0.3 * var(--base-spacing));
  font-size: 0.7em;
  vertical-align: super;
  cursor: help;
}

.roster-status+.roster-status {
  margin-left: calc(0.15 * var(--base-spacing));
}

.roster-status--wanted {
  color: var(--lc-accent);
}

/* muted rather than the page's accent — this marks an ending, not a call
   to action the way "wanted" does, so it deliberately doesn't compete for
   the same attention */
.roster-status--dead {
  color: var(--color-neutral-muted);
}

/* ---- lands inside a territory: a card grid instead of a tab switcher —
   every land is visible at once (a directory this size is meant to be
   scanned, not clicked through one land at a time) ---- */
.roster-lands {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: calc(1.25 * var(--base-spacing));
}

.roster-land-card {
  border: 1px solid var(--lc-paper-deep);
  border-radius: 4px;
  padding: calc(1 * var(--base-spacing)) calc(1.25 * var(--base-spacing));
}

.roster-land-card-header {
  margin: 0 0 calc(0.75 * var(--base-spacing));
  padding-bottom: calc(0.5 * var(--base-spacing));
  border-bottom: 1px solid var(--lc-paper-deep);
  font-family: var(--font-heading);
  font-size: 0.85714rem;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  text-align: center;
  color: var(--lc-accent);
}

/* generic muted note line — a land's blurb, the ruling family's "why this
   isn't a regular land grant" aside, anywhere else a short aside fits */
.roster-note {
  font-size: 0.85714rem;
  font-style: italic;
  opacity: 0.8;
  margin: 0 0 calc(0.75 * var(--base-spacing));
}

.roster-land-ruler {
  margin: 0 0 calc(0.9 * var(--base-spacing));
  padding-bottom: calc(0.75 * var(--base-spacing));
  border-bottom: 1px dashed var(--lc-paper-deep);
}

.roster-house {
  margin: 0 0 calc(0.9 * var(--base-spacing));
}

.roster-house:last-child {
  margin-bottom: 0;
}

.roster-house-label {
  margin: 0 0 calc(0.3 * var(--base-spacing));
  font-family: var(--font-heading);
  font-size: 0.75rem;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  opacity: 0.65;
}

/* ---- a land divided into smaller territories (a county, a quarter) —
   one level in from the land card itself, so a district's own houses read
   as nested under it rather than as more houses of the land at large.
   Not every land needs this: one without districts just lists its houses
   straight under the card, as before. ---- */
.roster-district {
  margin: 0 0 calc(1 * var(--base-spacing));
  padding-left: calc(1 * var(--base-spacing));
  border-left: 2px solid var(--lc-accent);
}

.roster-district:last-child {
  margin-bottom: 0;
}

.roster-district-header {
  margin: 0 0 calc(0.4 * var(--base-spacing));
  font-family: var(--font-heading);
  font-size: 0.92857rem;
  font-weight: 700;
  color: var(--lc-accent);
}

@media (max-width: 640px) {
  .roster-territory-summary {
    padding: calc(0.75 * var(--base-spacing)) calc(1.25 * var(--base-spacing));
  }

  .roster-territory-body {
    padding: 0 calc(1.25 * var(--base-spacing)) calc(1.25 * var(--base-spacing));
  }

  .roster-hero-rows {
    grid-template-columns: 1fr;
  }

  .roster-hero-heads--split {
    grid-template-columns: 1fr;
    gap: calc(1.25 * var(--base-spacing));
  }

  .roster-hero-heads--split .roster-hero-head:first-child {
    padding-right: 0;
  }

  .roster-hero-heads--split .roster-hero-head:last-child {
    padding-left: 0;
    border-left: none;
    padding-top: calc(1.25 * var(--base-spacing));
    border-top: 1px solid var(--lc-paper-deep);
  }
}