/* ==========================================================================
   KO PANEL - DESIGN SYSTEM
   Original dark MMORPG design system built for this panel in 2026.
   Mobile first. No framework. CSS Grid + Flexbox + custom properties.

   CONTENTS
     01  Tokens
     02  Reset & base
     03  Layout primitives
     04  Typography & section headings
     05  Buttons
     06  Panels / cards
     07  Forms
     08  Tables (with mobile card fallback)
     09  Badges, nations, classes, clan grades
     10  Navigation (topbar, header, mega menu, mobile drawer)
     11  Hero & homepage blocks
     12  News
     13  Rankings
     14  UserCP dashboard
     15  Tabs, pagination, empty states, loader
     16  Toasts (flash messages)
     17  Item tooltips
     18  Footer
     19  Utilities
     20  Reduced motion / print
     21  Character sheet (UserProfile)
   ========================================================================== */

/* ---------- 01  TOKENS ---------------------------------------------------- */
:root {
  /* surfaces */
  --ko-bg:          #0a0b0e;
  --ko-bg-2:        #0d0f14;
  --ko-surface:     #14171f;
  --ko-surface-2:   #191d27;
  --ko-surface-3:   #1f2430;

  /* lines */
  --ko-line:        #242a36;
  --ko-line-2:      #313849;

  /* text */
  --ko-text:        #e4e7ee;
  --ko-text-2:      #a4abbb;
  --ko-text-3:      #6d7585;

  /* brand: aged gold */
  --ko-gold:        #c8a44a;
  --ko-gold-hi:     #e8cd80;
  --ko-gold-lo:     #8f7429;
  --ko-gold-soft:   rgba(200,164,74,.12);
  --ko-gold-line:   rgba(200,164,74,.32);

  /* nations */
  --ko-karus:       #c2453a;
  --ko-elmorad:     #3f80c4;

  /* status */
  --ko-ok:          #55a86b;
  --ko-warn:        #d59a3c;
  --ko-err:         #cc4d42;
  --ko-info:        #4a8fc0;

  /* type */
  --ko-font:        'Barlow', 'Segoe UI', Roboto, system-ui, -apple-system, sans-serif;
  --ko-font-display:'Cinzel', 'Times New Roman', Georgia, serif;

  /* spacing scale */
  --ko-1: 4px;  --ko-2: 8px;  --ko-3: 12px; --ko-4: 16px;
  --ko-5: 20px; --ko-6: 24px; --ko-8: 32px; --ko-10: 40px;
  --ko-12: 48px; --ko-16: 64px; --ko-20: 80px;

  /* geometry */
  --ko-radius:   3px;
  --ko-radius-lg:4px;
  --ko-container: 1280px;
  --ko-header-h: 64px;

  /* elevation */
  --ko-shadow-1: 0 1px 2px rgba(0,0,0,.5);
  --ko-shadow-2: 0 4px 16px rgba(0,0,0,.45);
  --ko-shadow-3: 0 12px 40px rgba(0,0,0,.55);

  --ko-ease: cubic-bezier(.4,0,.2,1);
}

/* ---------- 02  RESET & BASE --------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body.ko-body {
  margin: 0;
  min-height: 100vh;
  background-color: var(--ko-bg);
  background-image:
    radial-gradient(900px 420px at 50% -180px, rgba(200,164,74,.055), transparent 70%),
    linear-gradient(180deg, #0c0e13 0%, var(--ko-bg) 420px);
  background-repeat: no-repeat;
  color: var(--ko-text);
  font-family: var(--ko-font);
  font-size: 15px;
  line-height: 1.6;
  font-weight: 400;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

img, svg, video { max-width: 100%; height: auto; display: block; }
a { color: var(--ko-gold); text-decoration: none; transition: color .15s var(--ko-ease); }
a:hover { color: var(--ko-gold-hi); }
button { font: inherit; color: inherit; }
input, select, textarea { font: inherit; }
hr { border: 0; border-top: 1px solid var(--ko-line); margin: var(--ko-6) 0; }

:focus-visible {
  outline: 2px solid var(--ko-gold);
  outline-offset: 2px;
}

::selection { background: rgba(200,164,74,.28); color: #fff; }

/* scrollbars */
* { scrollbar-width: thin; scrollbar-color: var(--ko-line-2) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: var(--ko-bg-2); }
*::-webkit-scrollbar-thumb { background: var(--ko-line-2); border: 2px solid var(--ko-bg-2); }
*::-webkit-scrollbar-thumb:hover { background: #3d4658; }

.ko-skip {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--ko-gold); color: #14171f; padding: 10px 18px; font-weight: 700;
}
.ko-skip:focus { left: 8px; top: 8px; }

/* ---------- 03  LAYOUT ---------------------------------------------------- */
.ko-container {
  width: 100%;
  max-width: var(--ko-container);
  margin-inline: auto;
  padding-inline: var(--ko-4);
}
@media (min-width: 768px)  { .ko-container { padding-inline: var(--ko-6); } }
@media (min-width: 1280px) { .ko-container { padding-inline: var(--ko-8); } }

.ko-main { display: block; padding-bottom: var(--ko-16); min-height: 50vh; }

.ko-stack   { display: flex; flex-direction: column; gap: var(--ko-6); min-width: 0; }
.ko-stack-4 { display: flex; flex-direction: column; gap: var(--ko-4); min-width: 0; }
.ko-row     { display: flex; flex-wrap: wrap; gap: var(--ko-3); align-items: center; }

/* Homepage / page grids: single column on mobile, split on large screens */
.ko-grid { display: grid; gap: var(--ko-6); grid-template-columns: minmax(0, 1fr); }
/* Grid children default to min-width:auto, which refuses to shrink below their
   content. Without this a table with a min-width pushes the whole page wider
   than the viewport on a phone. */
.ko-grid > * { min-width: 0; }

@media (min-width: 1024px) {
  .ko-grid--sidebar      { grid-template-columns: minmax(0,1fr) 320px; }
  .ko-grid--sidebar-left { grid-template-columns: 300px minmax(0,1fr); }
  .ko-grid--home         { grid-template-columns: minmax(0,1fr) 340px; }
}
@media (min-width: 640px) {
  .ko-grid--2 { grid-template-columns: repeat(2, minmax(0,1fr)); }
}
@media (min-width: 900px) {
  .ko-grid--3 { grid-template-columns: repeat(3, minmax(0,1fr)); }
  .ko-grid--4 { grid-template-columns: repeat(2, minmax(0,1fr)); }
}
@media (min-width: 1200px) {
  .ko-grid--4 { grid-template-columns: repeat(4, minmax(0,1fr)); }
}

/* ---------- 04  TYPOGRAPHY ------------------------------------------------ */
h1,h2,h3,h4,h5 {
  font-family: var(--ko-font-display);
  font-weight: 700;
  line-height: 1.2;
  margin: 0 0 var(--ko-3);
  letter-spacing: .01em;
  color: #f0f2f6;
}
h1 { font-size: clamp(1.6rem, 4vw, 2.4rem); }
h2 { font-size: clamp(1.3rem, 3vw, 1.75rem); }
h3 { font-size: clamp(1.1rem, 2.2vw, 1.3rem); }
h4 { font-size: 1.05rem; }
p  { margin: 0 0 var(--ko-4); color: var(--ko-text-2); }

.ko-lead { font-size: 1.05rem; color: var(--ko-text-2); }
.ko-muted { color: var(--ko-text-3); }
.ko-small { font-size: .8125rem; }

/* Section heading: gold rule + uppercase label */
.ko-section-head {
  display: flex; align-items: center; gap: var(--ko-3);
  margin-bottom: var(--ko-4);
  padding-bottom: var(--ko-3);
  border-bottom: 1px solid var(--ko-line);
}
.ko-section-head__icon {
  width: 28px; height: 28px; flex: none;
  display: grid; place-items: center;
  color: var(--ko-gold);
  background: var(--ko-gold-soft);
  border: 1px solid var(--ko-gold-line);
}
.ko-section-head h2,
.ko-section-head h3 {
  margin: 0;
  font-size: 1rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ko-text);
  flex: 1 1 auto;
  min-width: 0;
}
.ko-section-head__link {
  font-family: var(--ko-font);
  font-size: .8125rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ko-text-3);
  white-space: nowrap;
}
.ko-section-head__link:hover { color: var(--ko-gold); }

/* Page banner used at the top of internal pages */
.ko-pagehead {
  position: relative;
  padding: var(--ko-10) 0 var(--ko-8);
  margin-bottom: var(--ko-8);
  border-bottom: 1px solid var(--ko-line);
  background:
    linear-gradient(180deg, rgba(10,11,14,.72) 0%, rgba(10,11,14,.94) 100%),
    var(--ko-pagehead-img, none) var(--ko-pagehead-pos, center)/cover no-repeat,
    var(--ko-bg-2);
}
.ko-pagehead::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--ko-gold-line) 30%, var(--ko-gold-line) 70%, transparent);
}
.ko-pagehead h1 { margin: 0; text-transform: uppercase; letter-spacing: .04em; }
.ko-pagehead p  { margin: var(--ko-2) 0 0; max-width: 62ch; }

.ko-breadcrumb {
  display: flex; flex-wrap: wrap; gap: var(--ko-2);
  font-size: .8125rem; color: var(--ko-text-3);
  margin-bottom: var(--ko-3); padding: 0; list-style: none;
}
.ko-breadcrumb li + li::before { content: "/"; margin-right: var(--ko-2); color: var(--ko-line-2); }
.ko-breadcrumb a { color: var(--ko-text-3); }
.ko-breadcrumb a:hover { color: var(--ko-gold); }

/* ---------- 05  BUTTONS --------------------------------------------------- */
.ko-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--ko-2);
  min-height: 44px;                     /* touch target */
  padding: 10px 20px;
  border: 1px solid var(--ko-line-2);
  border-radius: var(--ko-radius);
  background: linear-gradient(180deg, var(--ko-surface-3), var(--ko-surface));
  color: var(--ko-text);
  font-family: var(--ko-font);
  font-size: .875rem; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  cursor: pointer;
  transition: background-color .15s var(--ko-ease), border-color .15s var(--ko-ease),
              color .15s var(--ko-ease), transform .1s var(--ko-ease);
  text-align: center;
  -webkit-appearance: none; appearance: none;
}
.ko-btn:hover { border-color: var(--ko-gold-line); color: #fff; }
.ko-btn:active { transform: translateY(1px); }
.ko-btn[disabled], .ko-btn.is-disabled { opacity: .5; pointer-events: none; }

.ko-btn--primary {
  border-color: var(--ko-gold-lo);
  background: linear-gradient(180deg, var(--ko-gold-hi), var(--ko-gold));
  color: #1a1608;
  text-shadow: 0 1px 0 rgba(255,255,255,.25);
}
.ko-btn--primary:hover {
  background: linear-gradient(180deg, #f2dc9b, var(--ko-gold-hi));
  border-color: var(--ko-gold);
  color: #1a1608;
}

.ko-btn--ghost { background: transparent; border-color: var(--ko-line-2); color: var(--ko-text-2); }
.ko-btn--ghost:hover { background: var(--ko-surface); color: var(--ko-text); }

.ko-btn--outline { background: transparent; border-color: var(--ko-gold-line); color: var(--ko-gold); }
.ko-btn--outline:hover { background: var(--ko-gold-soft); color: var(--ko-gold-hi); }

.ko-btn--danger { border-color: rgba(204,77,66,.5); color: #e8837a; background: rgba(204,77,66,.08); }
.ko-btn--danger:hover { background: rgba(204,77,66,.16); color: #f0a49d; }

.ko-btn--sm { min-height: 36px; padding: 6px 14px; font-size: .78125rem; }
.ko-btn--lg { min-height: 52px; padding: 14px 32px; font-size: .9375rem; }
.ko-btn--block { display: flex; width: 100%; }

.ko-btn-group { display: flex; flex-wrap: wrap; gap: var(--ko-3); }
@media (max-width: 479px) { .ko-btn-group--stack .ko-btn { flex: 1 1 100%; } }

/* ---------- 06  PANELS / CARDS -------------------------------------------- */
.ko-panel {
  background: var(--ko-surface);
  border: 1px solid var(--ko-line);
  border-radius: var(--ko-radius);
  box-shadow: var(--ko-shadow-1);
  overflow: hidden;
}
.ko-panel__head {
  display: flex; align-items: center; gap: var(--ko-3);
  padding: var(--ko-4) var(--ko-5);
  border-bottom: 1px solid var(--ko-line);
  background: linear-gradient(180deg, var(--ko-surface-2), var(--ko-surface));
}
.ko-panel__head h2, .ko-panel__head h3 {
  margin: 0; font-size: .9375rem; letter-spacing: .08em; text-transform: uppercase;
  flex: 1 1 auto; min-width: 0;
}
.ko-panel__head .ko-panel__icon { color: var(--ko-gold); flex: none; }
.ko-panel__body { padding: var(--ko-5); }
.ko-panel__body--flush { padding: 0; }
.ko-panel__foot {
  padding: var(--ko-3) var(--ko-5);
  border-top: 1px solid var(--ko-line);
  background: var(--ko-bg-2);
  font-size: .8125rem;
}

/* Card with a top gold hairline that lights up on hover */
.ko-card {
  position: relative;
  display: flex; flex-direction: column;
  background: var(--ko-surface);
  border: 1px solid var(--ko-line);
  border-radius: var(--ko-radius);
  overflow: hidden;
  transition: border-color .2s var(--ko-ease), transform .2s var(--ko-ease);
}
.ko-card::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 2px;
  background: linear-gradient(90deg, transparent, var(--ko-gold), transparent);
  opacity: 0; transition: opacity .25s var(--ko-ease);
}
.ko-card:hover { border-color: var(--ko-line-2); }
.ko-card:hover::before { opacity: .7; }
.ko-card__media { position: relative; overflow: hidden; background: var(--ko-bg-2); }
/* News artwork keeps its own proportions (2026-09-06). The old rule forced a
   16/9 box with object-fit:cover, which centre-cropped a 672x55 banner into an
   unreadable strip. height:auto lets the intrinsic ratio decide; max-height is
   only a guard so an unusually tall portrait image cannot stretch the card.
   520px is not arbitrary: the widest news card inside the 1280px container is
   ~860px, and 924 x 9/16 = 520, so a normal 16/9 or wider picture is never
   cropped at any breakpoint - only genuinely tall art meets the guard.
   Measured in Chromium at 375/414/720/1024/1366/1920. */
.ko-card__media img {
  display: block; width: 100%; height: auto;
  max-height: 520px; object-fit: cover; object-position: center top;
  transition: transform .4s var(--ko-ease);
}
.ko-card:hover .ko-card__media img { transform: scale(1.04); }
.ko-card__body { padding: var(--ko-4); flex: 1 1 auto; display: flex; flex-direction: column; gap: var(--ko-2); }
.ko-card__title { font-size: 1rem; margin: 0; }
.ko-card__title a { color: var(--ko-text); }
.ko-card__title a:hover { color: var(--ko-gold); }
.ko-card__meta { display: flex; flex-wrap: wrap; gap: var(--ko-3); font-size: .75rem; color: var(--ko-text-3); margin-top: auto; }

/* ---------- 07  FORMS ----------------------------------------------------- */
.ko-form { display: flex; flex-direction: column; gap: var(--ko-4); }
.ko-field { display: flex; flex-direction: column; gap: var(--ko-2); min-width: 0; }
.ko-field__label {
  font-size: .75rem; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ko-text-2);
}
.ko-field__label .ko-req { color: var(--ko-gold); margin-left: 2px; }

.ko-input, .ko-select, .ko-textarea {
  width: 100%;
  min-height: 46px;
  padding: 11px 14px;
  background: var(--ko-bg-2);
  border: 1px solid var(--ko-line-2);
  border-radius: var(--ko-radius);
  color: var(--ko-text);
  font-size: .9375rem;
  transition: border-color .15s var(--ko-ease), background-color .15s var(--ko-ease);
  -webkit-appearance: none; appearance: none;
}
.ko-textarea { min-height: 120px; resize: vertical; padding-top: 12px; }
.ko-input::placeholder, .ko-textarea::placeholder { color: var(--ko-text-3); }
.ko-input:hover, .ko-select:hover, .ko-textarea:hover { border-color: #3c4557; }
.ko-input:focus, .ko-select:focus, .ko-textarea:focus {
  outline: none;
  border-color: var(--ko-gold);
  background: var(--ko-surface);
  box-shadow: 0 0 0 3px var(--ko-gold-soft);
}
.ko-input:disabled, .ko-select:disabled { opacity: .55; cursor: not-allowed; }

.ko-select {
  padding-right: 40px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23a4abbb' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
}

.ko-field__hint { font-size: .75rem; color: var(--ko-text-3); }
.ko-field--error .ko-input,
.ko-field--error .ko-select { border-color: var(--ko-err); }
.ko-field__error { font-size: .75rem; color: #e8837a; }

.ko-inputgroup { display: flex; gap: var(--ko-2); }
.ko-inputgroup .ko-input { flex: 1 1 auto; min-width: 0; }

.ko-check { display: flex; align-items: flex-start; gap: var(--ko-2); font-size: .875rem; color: var(--ko-text-2); cursor: pointer; }
.ko-check input { width: 18px; height: 18px; margin-top: 2px; flex: none; accent-color: var(--ko-gold); }

.ko-form__actions { display: flex; flex-wrap: wrap; gap: var(--ko-3); margin-top: var(--ko-2); }
@media (max-width: 479px) { .ko-form__actions .ko-btn { flex: 1 1 100%; } }

@media (min-width: 640px) {
  .ko-form__row { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: var(--ko-4); }
}

/* Auth pages: centred card on an atmospheric background */
.ko-auth {
  display: grid; gap: var(--ko-8);
  align-items: start;
  padding-block: var(--ko-10) var(--ko-16);
}
@media (min-width: 1024px) { .ko-auth { grid-template-columns: minmax(0,1fr) 420px; } }
.ko-auth__card { max-width: 460px; width: 100%; margin-inline: auto; }
.ko-auth__aside { display: none; }
@media (min-width: 1024px) { .ko-auth__aside { display: block; } }

/* ---------- 08  TABLES ---------------------------------------------------- */
/* Wrapper gives horizontal scroll on narrow screens without breaking the page */
.ko-tablewrap {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--ko-line);
  border-radius: var(--ko-radius);
  background: var(--ko-surface);
}
.ko-table {
  width: 100%;
  border-collapse: collapse;
  font-size: .875rem;
  min-width: 560px;              /* forces the scroll instead of squashing */
}
.ko-table th, .ko-table td {
  padding: 11px var(--ko-4);
  text-align: left;
  border-bottom: 1px solid var(--ko-line);
  vertical-align: middle;
}
.ko-table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--ko-surface-2);
  color: var(--ko-text-2);
  font-size: .6875rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  white-space: nowrap;
  border-bottom-color: var(--ko-line-2);
}
.ko-table tbody tr { transition: background-color .12s var(--ko-ease); }
.ko-table tbody tr:hover { background: rgba(255,255,255,.022); }
.ko-table tbody tr:last-child td { border-bottom: 0; }
.ko-table .ko-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ko-table .ko-center { text-align: center; }
.ko-table__rank { width: 56px; text-align: center; color: var(--ko-text-3); font-weight: 700; font-variant-numeric: tabular-nums; }
.ko-table__rank--1 { color: var(--ko-gold); }
.ko-table__rank--2 { color: #c6cbd6; }
.ko-table__rank--3 { color: #b07a4a; }
/* Ranking boards that also carry the character's class and clan
   (.ko-table--rankmeta, set only by the Monthly Rankings page) sit two-up in a
   half-width panel, so the points header is the widest rigid item in the row.
   Only that header may wrap here; the numbers under it keep nowrap. */
.ko-table--rankmeta thead th.ko-num { white-space: normal; }

/* Monthly Rankings character cell: [Clan] CharacterName on one line.

   The board carries a fixed layout on purpose. With the default auto layout a
   table column is at least as wide as its widest cell's min-content, so a long
   clan or a long character name still widened the column and pushed the board
   into a sideways scroll no matter how shrinkable the cell contents were. Fixed
   layout makes the three column widths a property of the board, not of the
   names inside it: rank and points are pinned, the character column takes what
   is left, and the Monthly NP column can never be pushed around by a name. */
.ko-table--rankmeta { table-layout: fixed; }
/* [Clan] CharacterName needs roughly 230px of character cell before it starts
   cutting text, and a two-up board only offers ~115px of it below 1366px -
   measured, at 720/1024 the two boards are just 332/334px wide because the
   control-panel sidebar takes the rest. Rather than cut names, the two boards
   take a row each below 1366 and go back to sitting side by side above it.
   .ko-grid.ko-grid--rankmeta, not the bare class, so this always outranks
   .ko-grid--2's own 2-column rule rather than relying on source order. */
@media (max-width: 1365px) {
  .ko-grid.ko-grid--rankmeta { grid-template-columns: minmax(0, 1fr); }
}
.ko-table--rankmeta .ko-table__rank { width: 52px; }
.ko-table--rankmeta .ko-num { width: 8rem; }

/* Priority order inside the character cell when it is tight: the class chip
   never shrinks, the clan collapses first (its flex-shrink is 100x the name's),
   and the character name - the row's identity - gives way only after the clan
   is gone. Both texts ellipsis rather than wrap, so every row is exactly one
   line high whatever the clan and name lengths are. */
.ko-rankchar { display: flex; align-items: center; gap: 7px; min-width: 0; }
.ko-rankchar > .ko-class { flex: none; }
.ko-rankchar__name { flex: 0 1 auto; min-width: 0; }
/* [Clan]: the brackets are pseudo-elements, not text, so they never end up
   inside the truncated string, are never copied with the clan name, and can sit
   a step dimmer than the clan, which is itself a step dimmer than the gold
   character name. Nothing at all is emitted for a character with no clan. */
.ko-clanpre {
  display: inline-flex; align-items: center; gap: 1px;
  flex: 0 100 auto; min-width: 0; max-width: 104px;
  font-size: .8125rem; color: var(--ko-text-3);
}
.ko-clanpre::before { content: "["; flex: none; }
.ko-clanpre::after  { content: "]"; flex: none; }
/* The floor lives on the name, not on the tag: a floor on the tag would pad
   [ABC] out to the same box as [Knights] and leave dead space before the
   character name, while a floor here only bites when the tag is being squeezed,
   so a squeezed clan degrades to [Bl...] and never to an empty [ ]. */
.ko-clanpre__name { min-width: 1.5rem; color: var(--ko-text-2); }
.ko-clanpre__name:hover { color: var(--ko-text); }
/* In the stacked card layout the row has a whole line to itself, so nothing has
   to be cut: the clan is allowed to drop under the name instead of truncating. */
@media (max-width: 719px) {
  /* The card layout stacks every cell, so the fixed column widths above must be
     released or the Monthly NP value would be clipped inside a 8rem block. */
  .ko-table--cards.ko-table--rankmeta .ko-table__rank,
  .ko-table--cards.ko-table--rankmeta .ko-num { width: 100%; }
  .ko-table--cards .ko-rankchar { flex-wrap: wrap; justify-content: flex-end; }
  .ko-table--cards .ko-clanpre { max-width: 100%; }
}

/*
   Card mode: below 720px each row becomes a stacked card using the
   data-label attribute on every cell. Add class ko-table--cards to opt in.
*/
@media (max-width: 719px) {
  .ko-table--cards { min-width: 0 !important; width: 100%; }
  .ko-tablewrap--cards { max-width: 100%; }
  .ko-table--cards thead { display: none; }
  .ko-table--cards, .ko-table--cards tbody, .ko-table--cards tr, .ko-table--cards td { display: block; width: 100%; }
  .ko-table--cards tr {
    border: 1px solid var(--ko-line);
    border-radius: var(--ko-radius);
    background: var(--ko-surface-2);
    margin-bottom: var(--ko-3);
    padding: var(--ko-2) var(--ko-3);
  }
  .ko-table--cards td {
    display: flex; align-items: center; justify-content: space-between; gap: var(--ko-3);
    border-bottom: 1px dashed var(--ko-line);
    padding: 9px 0; text-align: right;
  }
  .ko-table--cards td:last-child { border-bottom: 0; }
  .ko-table--cards td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-size: .6875rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
    color: var(--ko-text-3); text-align: left;
  }
  .ko-table--cards td[data-label=""]::before { content: none; }
  .ko-tablewrap--cards { border: 0; background: transparent; overflow: visible; }
}

/* key/value list used on profile pages */
.ko-kv { display: grid; gap: 1px; background: var(--ko-line); border: 1px solid var(--ko-line); border-radius: var(--ko-radius); overflow: hidden; }
.ko-kv__row { display: grid; grid-template-columns: 1fr; gap: 2px; background: var(--ko-surface); padding: var(--ko-3) var(--ko-4); }
@media (min-width: 480px) { .ko-kv__row { grid-template-columns: 160px minmax(0,1fr); gap: var(--ko-4); align-items: center; } }
.ko-kv__k { font-size: .75rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--ko-text-3); }
.ko-kv__v { color: var(--ko-text); word-break: break-word; }

/* ---------- 09  BADGES / NATIONS / CLASSES -------------------------------- */
.ko-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px;
  border: 1px solid var(--ko-line-2);
  border-radius: 2px;
  background: var(--ko-surface-2);
  font-size: .6875rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ko-text-2);
  white-space: nowrap;
}
.ko-badge--gold   { border-color: var(--ko-gold-line); background: var(--ko-gold-soft); color: var(--ko-gold-hi); }
.ko-badge--karus  { border-color: rgba(194,69,58,.45);  background: rgba(194,69,58,.12);  color: #e08b81; }
.ko-badge--elmorad{ border-color: rgba(63,128,196,.45); background: rgba(63,128,196,.12); color: #8ab8e4; }
.ko-badge--ok     { border-color: rgba(85,168,107,.45); background: rgba(85,168,107,.12); color: #83c795; }
.ko-badge--warn   { border-color: rgba(213,154,60,.45); background: rgba(213,154,60,.12); color: #e0b46e; }
.ko-badge--err    { border-color: rgba(204,77,66,.45);  background: rgba(204,77,66,.12);  color: #e8837a; }

/* News category colours */
.ko-badge--event  { border-color: rgba(154,92,196,.45); background: rgba(154,92,196,.14); color: #c194e0; }
.ko-badge--notice { border-color: rgba(63,128,196,.45); background: rgba(63,128,196,.14); color: #8ab8e4; }
.ko-badge--update { border-color: rgba(85,168,107,.45); background: rgba(85,168,107,.14); color: #83c795; }
.ko-badge--guide  { border-color: rgba(213,154,60,.45); background: rgba(213,154,60,.14); color: #e0b46e; }
.ko-badge--maint  { border-color: rgba(196,74,74,.45);  background: rgba(196,74,74,.14);  color: #e08a8a; }
.ko-badge--faq    { border-color: var(--ko-line-2); background: var(--ko-surface-3); color: var(--ko-text-2); }

/* Authority labels rendered by dbo::GetAuthority() */
.auth { font-weight: 600; font-size: .8125rem; }
.auth--gm      { color: #c194e0; }
.auth--player  { color: var(--ko-text); }
.auth--sheriff { color: #83c795; }
.auth--muted   { color: #8ab8e4; }
.auth--banned  { color: #e8837a; }

/* Nation + class chips. Icon images are the panel's existing assets. */
.ko-nation {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: .8125rem; font-weight: 600; white-space: nowrap;
}
.ko-nation::before {
  content: ""; width: 16px; height: 16px; flex: none;
  background-size: contain; background-repeat: no-repeat; background-position: center;
}
.ko-nation--1 { color: #e08b81; }
.ko-nation--1::before { background-image: url("../rank-icon/1.png"); }
.ko-nation--2 { color: #8ab8e4; }
.ko-nation--2::before { background-image: url("../rank-icon/2.png"); }
.ko-nation--0 { color: var(--ko-text-3); }
.ko-nation--0::before { display: none; }

.ko-class {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 7px; border-radius: 2px;
  font-size: .6875rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  border: 1px solid var(--ko-line-2); background: var(--ko-surface-2); color: var(--ko-text-2);
  white-space: nowrap;
}
.ko-class--1 { color: #e0a06e; border-color: rgba(224,160,110,.4); background: rgba(224,160,110,.1); } /* Warrior */
.ko-class--2 { color: #83c795; border-color: rgba(131,199,149,.4); background: rgba(131,199,149,.1); } /* Rogue   */
.ko-class--3 { color: #8ab8e4; border-color: rgba(138,184,228,.4); background: rgba(138,184,228,.1); } /* Mage    */
.ko-class--4 { color: #e6d18a; border-color: rgba(230,209,138,.4); background: rgba(230,209,138,.1); } /* Priest  */
.ko-class--5 { color: #c194e0; border-color: rgba(193,148,224,.4); background: rgba(193,148,224,.1); } /* Kurian  */

/* Class icon. Inline SVG drawn with currentColor, so it always matches the
   chip's text colour. One drawing per class category - never a nation or
   subclass variant. See ko_class_icon_svg() in system/helpers.php. */
.ko-class__icon {
  width: 13px; height: 13px; flex: none;
  display: block;
  opacity: .95;
}
.ko-class__label { min-width: 0; }

/* Larger variant for the character sheet identity band. */
.ko-class--lg { font-size: .75rem; padding: 3px 9px; gap: 6px; }
.ko-class--lg .ko-class__icon { width: 15px; height: 15px; }

.ko-clantag {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--ko-text-2); font-size: .8125rem;
}
.ko-clantag::before {
  content: ""; width: 14px; height: 14px; flex: none;
  background: url("../rank-icon/default_clan.png") center/contain no-repeat;
  opacity: .8;
}
.ko-grade { display: inline-block; font-size: .75rem; color: var(--ko-text-3); }

/* progress / capacity bar */
.ko-meter { height: 8px; background: var(--ko-bg-2); border: 1px solid var(--ko-line); border-radius: 2px; overflow: hidden; }
.ko-meter__fill {
  height: 100%;
  background: linear-gradient(90deg, var(--ko-gold-lo), var(--ko-gold));
  transition: width .5s var(--ko-ease);
}
.ko-meter--ok .ko-meter__fill { background: linear-gradient(90deg, #3f7a51, var(--ko-ok)); }

/* ---------- 10  NAVIGATION ------------------------------------------------ */

/* Thin utility bar above the header */
.ko-topbar {
  border-bottom: 1px solid var(--ko-line);
  background: var(--ko-bg-2);
  font-size: .75rem;
}
.ko-topbar__inner {
  display: flex; align-items: center; justify-content: space-between; gap: var(--ko-4);
  min-height: 36px; padding-block: 4px;
}
.ko-topbar__status { display: flex; align-items: center; gap: var(--ko-2); color: var(--ko-text-3); }
.ko-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ko-text-3); flex: none; }
.ko-dot--on { background: var(--ko-ok); box-shadow: 0 0 0 3px rgba(85,168,107,.16); }
.ko-dot--off{ background: var(--ko-err); box-shadow: 0 0 0 3px rgba(204,77,66,.16); }
.ko-topbar__social { display: flex; align-items: center; gap: var(--ko-1); }
.ko-topbar__social a {
  width: 30px; height: 30px; display: grid; place-items: center;
  color: var(--ko-text-3); border: 1px solid transparent; border-radius: 2px;
}
.ko-topbar__social a:hover { color: var(--ko-gold); border-color: var(--ko-line); background: var(--ko-surface); }
@media (max-width: 639px) { .ko-topbar__status span.ko-hide-xs { display: none; } }

/* --- Language switcher (top bar + drawer) --------------------------------
   Two plain links styled as a segmented control. No JavaScript, so it keeps
   working with scripts blocked, and each option is a real, crawlable URL. */
.ko-topbar__right { display: flex; align-items: center; gap: var(--ko-3); }

.ko-lang {
  display: inline-flex; align-items: center; gap: 2px;
  border: 1px solid var(--ko-line); border-radius: 3px;
  background: var(--ko-bg-1); padding: 1px;
}
.ko-lang__icon {
  display: grid; place-items: center;
  width: 20px; color: var(--ko-text-3);
}
.ko-lang__opt {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 32px; min-height: 26px; padding: 0 7px;
  font-size: .7rem; font-weight: 600; letter-spacing: .06em;
  color: var(--ko-text-3); border-radius: 2px; text-decoration: none;
  transition: color .15s ease, background .15s ease;
}
.ko-lang__opt:hover { color: var(--ko-gold); background: var(--ko-surface); }
.ko-lang__opt.is-active {
  color: var(--ko-bg-1); background: var(--ko-gold);
  cursor: default;
}
.ko-lang__opt:focus-visible { outline: 2px solid var(--ko-gold); outline-offset: 1px; }

/* Drawer variant: full width, larger touch targets */
.ko-lang--block {
  display: flex; width: 100%; margin-bottom: var(--ko-3);
  padding: 3px; justify-content: stretch;
}
.ko-lang--block .ko-lang__icon { width: 28px; }
.ko-lang--block .ko-lang__opt {
  flex: 1 1 0; min-width: 0; min-height: 40px; font-size: .8rem;
}

/* Four languages instead of two (2026-09-06): NO CSS CHANGE WAS NEEDED.
   Measured in a real browser at 320, 360, 375 and 414px - four options render
   on one row, 160px wide, with no overflow and no collision with the status
   text on the left, using exactly the rules above. An earlier version of this
   pass hid the globe icon and shrank the options below 480px; that was removed
   on audit because it changed the existing two-language mobile appearance
   without being necessary. Do not re-add it without measuring first. */

@media (max-width: 479px) {
  .ko-topbar__social { display: none; }
  .ko-topbar__right  { gap: var(--ko-2); }
}

/* Main header */
.ko-header {
  position: sticky; top: 0; z-index: 60;
  background: rgba(13,15,20,.92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--ko-line);
}
.ko-header__inner {
  display: flex; align-items: center; gap: var(--ko-4);
  min-height: var(--ko-header-h);
}
.ko-brand { display: flex; align-items: center; gap: var(--ko-3); flex: none; min-width: 0; }
.ko-brand img { max-height: 40px; width: auto; }
.ko-brand__text {
  font-family: var(--ko-font-display); font-weight: 700; font-size: 1.05rem;
  letter-spacing: .08em; text-transform: uppercase; color: var(--ko-gold);
  white-space: nowrap;
}
@media (max-width: 419px) { .ko-brand__text { font-size: .9rem; } }

/* desktop nav */
.ko-nav { display: none; flex: 1 1 auto; min-width: 0; }
@media (min-width: 1024px) { .ko-nav { display: block; } }
.ko-nav__list { display: flex; align-items: center; gap: 2px; list-style: none; margin: 0; padding: 0; }
.ko-nav__item { position: relative; }
.ko-nav__link {
  display: flex; align-items: center; gap: 6px;
  padding: 0 14px; height: var(--ko-header-h);
  font-size: .8125rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ko-text-2);
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  background: none; border-left: 0; border-right: 0; border-top: 0; cursor: pointer;
}
.ko-nav__link:hover { color: var(--ko-text); background: rgba(255,255,255,.03); }
.ko-nav__item.is-active > .ko-nav__link { color: var(--ko-gold); border-bottom-color: var(--ko-gold); }
.ko-nav__caret { width: 10px; height: 10px; transition: transform .2s var(--ko-ease); }

/* dropdown */
.ko-nav__panel {
  position: absolute; top: 100%; left: 0; z-index: 70;
  min-width: 230px;
  padding: var(--ko-2);
  background: var(--ko-surface);
  border: 1px solid var(--ko-line-2);
  border-top: 2px solid var(--ko-gold);
  box-shadow: var(--ko-shadow-3);
  list-style: none; margin: 0;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .15s var(--ko-ease), transform .15s var(--ko-ease), visibility .15s;
}
.ko-nav__item:hover > .ko-nav__panel,
.ko-nav__item:focus-within > .ko-nav__panel {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.ko-nav__panel a {
  display: flex; align-items: center; gap: var(--ko-2);
  padding: 9px 12px;
  font-size: .8125rem; color: var(--ko-text-2);
  border-left: 2px solid transparent;
}
.ko-nav__panel a:hover { background: var(--ko-surface-2); color: var(--ko-gold); border-left-color: var(--ko-gold); }
.ko-nav__panel .ko-nav__group {
  padding: 10px 12px 4px; font-size: .625rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ko-text-3);
}

/* header account area */
.ko-header__actions { display: flex; align-items: center; gap: var(--ko-2); margin-left: auto; flex: none; }
@media (max-width: 639px) { .ko-header__actions .ko-hide-xs { display: none; } }

.ko-user { position: relative; }
.ko-user__btn {
  display: flex; align-items: center; gap: var(--ko-2);
  padding: 5px 10px 5px 5px;
  background: var(--ko-surface); border: 1px solid var(--ko-line-2); border-radius: var(--ko-radius);
  cursor: pointer; min-height: 40px;
}
.ko-user__btn:hover { border-color: var(--ko-gold-line); }
.ko-user__avatar {
  width: 28px; height: 28px; flex: none; border-radius: 2px;
  background: var(--ko-gold-soft); border: 1px solid var(--ko-gold-line);
  display: grid; place-items: center; color: var(--ko-gold);
  font-weight: 700; font-size: .8125rem; text-transform: uppercase;
}
.ko-user__name { font-size: .8125rem; font-weight: 600; max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 479px) { .ko-user__name { display: none; } }
.ko-user__menu {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 70;
  min-width: 220px; padding: var(--ko-2);
  background: var(--ko-surface); border: 1px solid var(--ko-line-2);
  border-top: 2px solid var(--ko-gold); box-shadow: var(--ko-shadow-3);
  list-style: none; margin: 0;
  display: none;
}
.ko-user.is-open .ko-user__menu { display: block; }
.ko-user__menu a { display: flex; align-items: center; gap: var(--ko-2); padding: 9px 12px; font-size: .8125rem; color: var(--ko-text-2); }
.ko-user__menu a:hover { background: var(--ko-surface-2); color: var(--ko-gold); }
.ko-user__cash {
  display: flex; justify-content: space-between; gap: var(--ko-3);
  padding: 10px 12px; margin-bottom: var(--ko-1);
  background: var(--ko-bg-2); border: 1px solid var(--ko-line);
  font-size: .75rem;
}
.ko-user__cash b { color: var(--ko-gold); font-variant-numeric: tabular-nums; }

/* burger */
.ko-burger {
  display: grid; place-items: center;
  width: 44px; height: 44px; flex: none;
  background: transparent; border: 1px solid var(--ko-line-2); border-radius: var(--ko-radius);
  cursor: pointer; color: var(--ko-text-2);
}
.ko-burger:hover { color: var(--ko-gold); border-color: var(--ko-gold-line); }
@media (min-width: 1024px) { .ko-burger { display: none; } }
.ko-burger__bars { position: relative; width: 20px; height: 2px; background: currentColor; transition: background-color .2s; }
.ko-burger__bars::before, .ko-burger__bars::after {
  content: ""; position: absolute; left: 0; width: 20px; height: 2px; background: currentColor;
  transition: transform .25s var(--ko-ease), top .25s var(--ko-ease);
}
.ko-burger__bars::before { top: -6px; }
.ko-burger__bars::after  { top: 6px; }
body.ko-drawer-open .ko-burger__bars { background: transparent; }
body.ko-drawer-open .ko-burger__bars::before { top: 0; transform: rotate(45deg); }
body.ko-drawer-open .ko-burger__bars::after  { top: 0; transform: rotate(-45deg); }

/* mobile drawer - a purpose built menu, not a squashed desktop one */
.ko-drawer-backdrop {
  position: fixed; inset: 0; z-index: 80;
  background: rgba(0,0,0,.65);
  opacity: 0; visibility: hidden; transition: opacity .25s var(--ko-ease), visibility .25s;
}
body.ko-drawer-open .ko-drawer-backdrop { opacity: 1; visibility: visible; }

.ko-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 90;
  width: min(370px, 88vw);
  display: flex; flex-direction: column;
  background: var(--ko-bg-2);
  border-left: 1px solid var(--ko-line-2);
  box-shadow: var(--ko-shadow-3);
  transform: translateX(100%);
  transition: transform .28s var(--ko-ease);
  overscroll-behavior: contain;
}
body.ko-drawer-open .ko-drawer { transform: translateX(0); }
body.ko-drawer-open { overflow: hidden; }
@media (min-width: 1024px) { .ko-drawer, .ko-drawer-backdrop { display: none; } }

.ko-drawer__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--ko-3);
  padding: var(--ko-4);
  border-bottom: 1px solid var(--ko-line);
  min-height: var(--ko-header-h);
}
.ko-drawer__close {
  width: 40px; height: 40px; display: grid; place-items: center;
  background: transparent; border: 1px solid var(--ko-line-2); color: var(--ko-text-2); cursor: pointer;
}
.ko-drawer__close:hover { color: var(--ko-gold); border-color: var(--ko-gold-line); }
.ko-drawer__body { flex: 1 1 auto; overflow-y: auto; padding: var(--ko-4) 0 var(--ko-8); }
.ko-drawer__foot { padding: var(--ko-4); border-top: 1px solid var(--ko-line); display: grid; gap: var(--ko-2); }

.ko-drawer__account {
  display: flex; align-items: center; gap: var(--ko-3);
  margin: 0 var(--ko-4) var(--ko-4);
  padding: var(--ko-3);
  background: var(--ko-surface); border: 1px solid var(--ko-line);
}
.ko-drawer__account .ko-user__avatar { width: 40px; height: 40px; font-size: 1rem; }

.ko-mnav { list-style: none; margin: 0; padding: 0; }
.ko-mnav > li { border-bottom: 1px solid var(--ko-line); }
.ko-mnav__link, .ko-mnav__toggle {
  display: flex; align-items: center; gap: var(--ko-3);
  width: 100%; min-height: 52px;
  padding: 12px var(--ko-4);
  background: none; border: 0; text-align: left; cursor: pointer;
  font-size: .9375rem; font-weight: 600; letter-spacing: .04em;
  color: var(--ko-text);
}
.ko-mnav__link:hover, .ko-mnav__toggle:hover { background: var(--ko-surface); color: var(--ko-gold); }
.ko-mnav > li.is-active > .ko-mnav__link { color: var(--ko-gold); box-shadow: inset 3px 0 0 var(--ko-gold); }
.ko-mnav__toggle .ko-nav__caret { margin-left: auto; }
.ko-mnav__toggle[aria-expanded="true"] .ko-nav__caret { transform: rotate(180deg); }
.ko-mnav__sub { list-style: none; margin: 0; padding: 0 0 var(--ko-2); display: none; background: rgba(0,0,0,.24); }
.ko-mnav__sub.is-open { display: block; }
.ko-mnav__sub a {
  display: flex; align-items: center; gap: var(--ko-2);
  min-height: 46px; padding: 10px var(--ko-4) 10px var(--ko-10);
  font-size: .875rem; color: var(--ko-text-2);
}
.ko-mnav__sub a:hover { color: var(--ko-gold); background: rgba(255,255,255,.03); }
.ko-mnav__groupname {
  padding: var(--ko-4) var(--ko-4) var(--ko-1) var(--ko-10);
  font-size: .625rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--ko-text-3);
}

/* announcement ticker */
.ko-ticker {
  border-bottom: 1px solid var(--ko-line);
  background: linear-gradient(90deg, rgba(200,164,74,.07), transparent 60%);
  overflow: hidden;
}
.ko-ticker__inner { display: flex; align-items: center; gap: var(--ko-4); min-height: 42px; }
.ko-ticker__label {
  display: flex; align-items: center; gap: 6px; flex: none;
  font-size: .6875rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ko-gold);
}
.ko-ticker__items { flex: 1 1 auto; min-width: 0; display: flex; gap: var(--ko-6); overflow-x: auto; scrollbar-width: none; }
.ko-ticker__items::-webkit-scrollbar { display: none; }
.ko-ticker__items a, .ko-ticker__items span {
  font-size: .8125rem; color: var(--ko-text-2); white-space: nowrap; padding-block: 10px;
}
.ko-ticker__items a:hover { color: var(--ko-gold); }

/* ---------- 11  HERO & HOMEPAGE BLOCKS ------------------------------------ */
.ko-hero {
  position: relative;
  isolation: isolate;
  padding: var(--ko-16) 0 var(--ko-12);
  min-height: 460px;
  display: flex; align-items: center;
  border-bottom: 1px solid var(--ko-line);
  overflow: hidden;
}
@media (min-width: 1024px) { .ko-hero { min-height: 560px; } }
.ko-hero__bg {
  position: absolute; inset: 0; z-index: -2;
  background-position: center 28%;
  background-size: cover;
  background-repeat: no-repeat;
}
.ko-hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(90deg, rgba(8,9,12,.94) 0%, rgba(8,9,12,.80) 38%, rgba(8,9,12,.35) 70%, rgba(8,9,12,.55) 100%),
    linear-gradient(180deg, rgba(10,11,14,.45) 0%, rgba(10,11,14,.20) 45%, var(--ko-bg) 100%);
}
@media (max-width: 767px) {
  .ko-hero::after {
    background:
      linear-gradient(180deg, rgba(8,9,12,.72) 0%, rgba(8,9,12,.86) 55%, var(--ko-bg) 100%);
  }
}
.ko-hero__inner { max-width: 640px; position: relative; width: 100%; }
.ko-hero__eyebrow {
  display: inline-flex; align-items: center; gap: var(--ko-2);
  margin-bottom: var(--ko-4);
  padding: 5px 12px;
  border: 1px solid var(--ko-gold-line); background: var(--ko-gold-soft);
  font-size: .6875rem; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ko-gold-hi);
}
.ko-hero h1 {
  font-size: clamp(2rem, 7vw, 3.75rem);
  line-height: 1.05;
  margin: 0 0 var(--ko-4);
  text-transform: uppercase;
  letter-spacing: .02em;
  text-shadow: 0 3px 24px rgba(0,0,0,.65);
}
.ko-hero h1 em { font-style: normal; color: var(--ko-gold); }
.ko-hero__sub { font-size: clamp(.95rem, 2vw, 1.125rem); color: var(--ko-text-2); max-width: 52ch; margin-bottom: var(--ko-6); }
.ko-hero__cta { display: flex; flex-wrap: wrap; gap: var(--ko-3); }
@media (max-width: 479px) { .ko-hero__cta .ko-btn { flex: 1 1 100%; } }
.ko-hero__facts {
  display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 1px;
  margin-top: var(--ko-8);
  background: var(--ko-line);
  border: 1px solid var(--ko-line);
  max-width: 560px;
}
@media (min-width: 640px) { .ko-hero__facts { grid-template-columns: repeat(4, minmax(0,1fr)); } }

.ko-stat { background: rgba(20,23,31,.82); padding: var(--ko-4); text-align: center; }
.ko-stat__value {
  display: block;
  font-family: var(--ko-font-display); font-weight: 700;
  font-size: clamp(1.1rem, 3vw, 1.5rem);
  color: var(--ko-gold); line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.ko-stat__label {
  display: block; margin-top: 2px;
  font-size: .625rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ko-text-3);
}

/* Feature strip: download / register / discord calls to action */
.ko-cta-strip {
  display: grid; gap: var(--ko-4); grid-template-columns: 1fr;
  padding-block: var(--ko-8);
}
@media (min-width: 768px) { .ko-cta-strip { grid-template-columns: repeat(3, minmax(0,1fr)); } }
.ko-cta {
  display: flex; align-items: center; gap: var(--ko-4);
  padding: var(--ko-5);
  background: linear-gradient(135deg, var(--ko-surface), var(--ko-bg-2));
  border: 1px solid var(--ko-line);
  transition: border-color .2s var(--ko-ease);
}
.ko-cta:hover { border-color: var(--ko-gold-line); }
.ko-cta__icon {
  width: 46px; height: 46px; flex: none; display: grid; place-items: center;
  border: 1px solid var(--ko-gold-line); background: var(--ko-gold-soft); color: var(--ko-gold);
}
.ko-cta > span:last-child { min-width: 0; }
.ko-cta__title {
  display: block;
  font-family: var(--ko-font-display); font-weight: 700; font-size: 1rem;
  color: var(--ko-text); margin: 0 0 2px;
}
.ko-cta__desc { display: block; font-size: .8125rem; color: var(--ko-text-3); margin: 0; }

/* server status panel */
.ko-server { display: grid; gap: var(--ko-4); }
.ko-server__row { display: flex; align-items: center; justify-content: space-between; gap: var(--ko-3); font-size: .875rem; }
.ko-server__nations { display: grid; grid-template-columns: 1fr 1fr; gap: var(--ko-3); }
.ko-server__nation {
  padding: var(--ko-3); text-align: center;
  border: 1px solid var(--ko-line); background: var(--ko-bg-2);
}
.ko-server__nation b { display: block; font-size: 1.25rem; font-variant-numeric: tabular-nums; line-height: 1.2; }
.ko-server__nation--1 b { color: #e08b81; }
.ko-server__nation--2 b { color: #8ab8e4; }
.ko-server__nation span { font-size: .625rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ko-text-3); }

/* ---------- 12  NEWS ------------------------------------------------------ */
.ko-newslist { display: grid; gap: var(--ko-3); }
.ko-newsitem {
  display: grid; gap: var(--ko-3);
  grid-template-columns: 1fr;
  padding: var(--ko-3);
  border: 1px solid var(--ko-line);
  background: var(--ko-surface);
  transition: border-color .2s var(--ko-ease), background-color .2s var(--ko-ease);
}
@media (min-width: 560px) { .ko-newsitem { grid-template-columns: 132px minmax(0,1fr); align-items: center; } }
.ko-newsitem:hover { border-color: var(--ko-line-2); background: var(--ko-surface-2); }
.ko-newsitem__thumb { overflow: hidden; background: var(--ko-bg-2); border: 1px solid var(--ko-line); align-self: center; }
/* Below 560px the row stacks and the thumb spans the full width, so the 132px
   guard tuned for the 132px-wide desktop column would crop a normal 16/9
   picture by about a fifth. Two guards, one per layout. */
.ko-newsitem__thumb img { display: block; width: 100%; height: auto; max-height: 200px; object-fit: cover; }
@media (min-width: 560px) { .ko-newsitem__thumb img { max-height: 132px; } }
.ko-newsitem__title { margin: 0 0 4px; font-size: .9375rem; font-family: var(--ko-font); font-weight: 600; }
.ko-newsitem__title a { color: var(--ko-text); }
.ko-newsitem__title a:hover { color: var(--ko-gold); }
.ko-newsitem__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ko-2); font-size: .75rem; color: var(--ko-text-3); }

.ko-article__body {
  font-size: .9375rem; line-height: 1.75; color: var(--ko-text-2);
  overflow-wrap: break-word;
}
.ko-article__body img { margin: var(--ko-4) 0; border: 1px solid var(--ko-line); }
.ko-article__body h1, .ko-article__body h2, .ko-article__body h3 { color: var(--ko-text); margin-top: var(--ko-6); }
.ko-article__body a { text-decoration: underline; text-underline-offset: 2px; }
.ko-article__body table { width: 100%; border-collapse: collapse; display: block; overflow-x: auto; }
.ko-article__body td, .ko-article__body th { border: 1px solid var(--ko-line); padding: 8px; }
.ko-article__body ul, .ko-article__body ol { padding-left: var(--ko-5); }
.ko-article__body iframe { max-width: 100%; }

/* ---------- 13  RANKINGS -------------------------------------------------- */
.ko-rankmini { list-style: none; margin: 0; padding: 0; }
.ko-rankmini li {
  display: grid;
  grid-template-columns: 34px minmax(0,1fr) auto;
  align-items: center; gap: var(--ko-3);
  padding: 9px var(--ko-4);
  border-bottom: 1px solid var(--ko-line);
}
.ko-rankmini li:last-child { border-bottom: 0; }
.ko-rankmini li:hover { background: rgba(255,255,255,.022); }
.ko-rankmini__pos { font-weight: 700; font-size: .8125rem; color: var(--ko-text-3); text-align: center; font-variant-numeric: tabular-nums; }
.ko-rankmini li:nth-child(1) .ko-rankmini__pos { color: var(--ko-gold); }
.ko-rankmini li:nth-child(2) .ko-rankmini__pos { color: #c6cbd6; }
.ko-rankmini li:nth-child(3) .ko-rankmini__pos { color: #b07a4a; }
.ko-rankmini__who { min-width: 0; }
.ko-rankmini__name { display: block; font-size: .875rem; font-weight: 600; color: var(--ko-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ko-rankmini__sub  { display: flex; align-items: center; gap: var(--ko-2); font-size: .6875rem; color: var(--ko-text-3); }
.ko-rankmini__np   { font-size: .8125rem; font-weight: 700; color: var(--ko-gold); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ---------- 14  USERCP ---------------------------------------------------- */
.ko-cp { display: grid; gap: var(--ko-6); grid-template-columns: minmax(0, 1fr); align-items: start; }
.ko-cp > * { min-width: 0; }
@media (min-width: 1024px) { .ko-cp { grid-template-columns: 260px minmax(0,1fr); } }

.ko-cp__side { position: static; }
@media (min-width: 1024px) { .ko-cp__side { position: sticky; top: calc(var(--ko-header-h) + var(--ko-4)); } }

.ko-cp__id {
  display: flex; align-items: center; gap: var(--ko-3);
  padding: var(--ko-4);
  border-bottom: 1px solid var(--ko-line);
  background: linear-gradient(180deg, var(--ko-surface-2), var(--ko-surface));
}
.ko-cp__id .ko-user__avatar { width: 44px; height: 44px; font-size: 1.125rem; }
.ko-cp__id strong { display: block; font-size: .9375rem; overflow: hidden; text-overflow: ellipsis; }
.ko-cp__id span { font-size: .75rem; color: var(--ko-text-3); }

.ko-cp__nav { list-style: none; margin: 0; padding: var(--ko-2); display: grid; gap: 2px; }
.ko-cp__nav a {
  display: flex; align-items: center; gap: var(--ko-3);
  min-height: 44px; padding: 10px var(--ko-3);
  font-size: .875rem; font-weight: 500; color: var(--ko-text-2);
  border-left: 2px solid transparent;
}
.ko-cp__nav a:hover { background: var(--ko-surface-2); color: var(--ko-text); }
.ko-cp__nav a.is-active {
  background: var(--ko-gold-soft); color: var(--ko-gold-hi);
  border-left-color: var(--ko-gold);
}
.ko-cp__nav svg { flex: none; opacity: .8; }

/* horizontal nav for the CP on small screens */
@media (max-width: 1023px) {
  .ko-cp__nav { display: flex; overflow-x: auto; gap: var(--ko-1); padding: var(--ko-2); scrollbar-width: none; }
  .ko-cp__nav::-webkit-scrollbar { display: none; }
  .ko-cp__nav a {
    white-space: nowrap; border-left: 0; border-bottom: 2px solid transparent;
    padding-inline: var(--ko-3);
  }
  .ko-cp__nav a.is-active { border-left: 0; border-bottom-color: var(--ko-gold); }
}

.ko-cp__stats { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 1px; background: var(--ko-line); }
@media (min-width: 700px) { .ko-cp__stats { grid-template-columns: repeat(4, minmax(0,1fr)); } }
.ko-cp__stat { background: var(--ko-surface); padding: var(--ko-4); }
.ko-cp__stat span { display: block; font-size: .625rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ko-text-3); margin-bottom: 4px; }
.ko-cp__stat b { font-size: 1.05rem; color: var(--ko-text); font-variant-numeric: tabular-nums; word-break: break-word; }
.ko-cp__stat b.ko-gold { color: var(--ko-gold); }

/* ---------- 15  TABS / PAGINATION / EMPTY / LOADER ------------------------ */
.ko-tabs {
  display: flex; gap: 2px; overflow-x: auto;
  border-bottom: 1px solid var(--ko-line);
  scrollbar-width: none;
}
.ko-tabs::-webkit-scrollbar { display: none; }
.ko-tab {
  flex: none;
  padding: 11px var(--ko-4);
  background: none; border: 0; border-bottom: 2px solid transparent;
  font-size: .8125rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ko-text-3); cursor: pointer; white-space: nowrap; min-height: 44px;
}
.ko-tab:hover { color: var(--ko-text-2); }
.ko-tab.is-active { color: var(--ko-gold); border-bottom-color: var(--ko-gold); }
/* A magic bag that is not equipped keeps its tab, so the panel still says the
   bag exists - it is just not selectable. A disabled button fires no click,
   so the shared tab script ignores it without needing to know about bags. */
.ko-tab[disabled] { opacity: .4; cursor: not-allowed; }
.ko-tab[disabled]:hover { color: var(--ko-text-3); }
.ko-tabpanel { display: none; }
.ko-tabpanel.is-active { display: block; }

/* Magic Bag only - the shared tab component is untouched everywhere else.
 *
 * Two measured problems, both in the same place:
 *
 *  1. .ko-tabpanel carries no padding, so the first row of slots sat 0.0px
 *     below the .ko-tabs border. Measured, not estimated: the gap between the
 *     underline and the grid was exactly zero.
 *  2. .ko-panel__body's 20px top padding put dead space ABOVE the tab strip.
 *     A tab bar reads as part of the header, not as floating content, and
 *     that 20px was also making the panel taller than the Inventory beside it
 *     for no reason.
 *
 * So the spacing moves from above the tabs to below them: the strip sits
 * flush under the panel head, and the slots get real breathing room. The
 * panel also ends up 8px shorter. Tab size, colours, the active underline and
 * the disabled state are all unchanged.
 */
.ko-sheet__mbag > .ko-panel__body { padding-top: 0; }
.ko-sheet__mbag .ko-tabpanel.is-active { padding-top: var(--ko-3); }
/* The per-bag X / 12 counts live in the panel head and reuse .ko-tabpanel so
   the existing tab script shows only the active one. The rule above would
   otherwise push them 12px down inside the flex head, out of line with the
   heading. Head only - the slot panels below keep their spacing exactly. */
.ko-sheet__mbag .ko-panel__head .ko-tabpanel.is-active { padding-top: 0; }

.ko-pagination { display: flex; flex-wrap: wrap; gap: var(--ko-1); justify-content: center; margin-top: var(--ko-6); }
.ko-pagination a, .ko-pagination span {
  min-width: 40px; min-height: 40px;
  display: grid; place-items: center; padding: 0 12px;
  border: 1px solid var(--ko-line); background: var(--ko-surface);
  font-size: .8125rem; font-weight: 600; color: var(--ko-text-2);
}
.ko-pagination a:hover { border-color: var(--ko-gold-line); color: var(--ko-gold); }
.ko-pagination .is-active { border-color: var(--ko-gold); background: var(--ko-gold-soft); color: var(--ko-gold-hi); }
.ko-pagination .is-disabled { opacity: .4; pointer-events: none; }

.ko-empty {
  display: grid; place-items: center; gap: var(--ko-3);
  padding: var(--ko-12) var(--ko-5);
  text-align: center; color: var(--ko-text-3);
}
.ko-empty__icon { color: var(--ko-line-2); }
.ko-empty p { margin: 0; }

.ko-loader { display: none; padding: var(--ko-8); text-align: center; }
.ko-loader.is-on { display: block; }
.ko-spinner {
  width: 30px; height: 30px; margin: 0 auto;
  border: 2px solid var(--ko-line-2); border-top-color: var(--ko-gold);
  border-radius: 50%;
  animation: ko-spin .7s linear infinite;
}
@keyframes ko-spin { to { transform: rotate(360deg); } }

.ko-skeleton {
  background: linear-gradient(90deg, var(--ko-surface) 25%, var(--ko-surface-3) 37%, var(--ko-surface) 63%);
  background-size: 400% 100%;
  animation: ko-shimmer 1.3s ease-in-out infinite;
  border-radius: 2px;
}
@keyframes ko-shimmer { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }

/* ---------- 16  TOASTS (flash messages) ----------------------------------- */
.ko-toasts {
  position: fixed; z-index: 200;
  left: var(--ko-4); right: var(--ko-4); bottom: var(--ko-4);
  display: grid; gap: var(--ko-2);
  pointer-events: none;
}
@media (min-width: 640px) {
  .ko-toasts { left: auto; right: var(--ko-6); bottom: var(--ko-6); width: 380px; }
}
.ko-toast {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: var(--ko-3);
  padding: var(--ko-3) var(--ko-4);
  background: var(--ko-surface);
  border: 1px solid var(--ko-line-2);
  border-left: 3px solid var(--ko-text-3);
  box-shadow: var(--ko-shadow-3);
  font-size: .875rem; color: var(--ko-text);
  animation: ko-toast-in .28s var(--ko-ease);
}
@keyframes ko-toast-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.ko-toast--success { border-left-color: var(--ko-ok); }
.ko-toast--error   { border-left-color: var(--ko-err); }
.ko-toast--info    { border-left-color: var(--ko-info); }
.ko-toast__icon { flex: none; margin-top: 2px; }
.ko-toast--success .ko-toast__icon { color: var(--ko-ok); }
.ko-toast--error   .ko-toast__icon { color: var(--ko-err); }
.ko-toast--info    .ko-toast__icon { color: var(--ko-info); }
.ko-toast__msg { flex: 1 1 auto; min-width: 0; overflow-wrap: break-word; }
.ko-toast__close {
  flex: none; background: none; border: 0; cursor: pointer;
  color: var(--ko-text-3); font-size: 1.1rem; line-height: 1; padding: 2px 4px;
}
.ko-toast__close:hover { color: var(--ko-text); }
.ko-toast.is-out { opacity: 0; transform: translateY(8px); transition: opacity .25s, transform .25s; }

/* Inline alert (non transient) */
.ko-alert {
  display: flex; gap: var(--ko-3);
  padding: var(--ko-4);
  border: 1px solid var(--ko-line-2);
  border-left: 3px solid var(--ko-text-3);
  background: var(--ko-surface-2);
  font-size: .875rem;
}
.ko-alert--error   { border-left-color: var(--ko-err);  background: rgba(204,77,66,.07); }
.ko-alert--success { border-left-color: var(--ko-ok);   background: rgba(85,168,107,.07); }
.ko-alert--warn    { border-left-color: var(--ko-warn); background: rgba(213,154,60,.07); }
.ko-alert--info    { border-left-color: var(--ko-info); background: rgba(74,143,192,.07); }
.ko-alert p:last-child { margin-bottom: 0; }

/* ---------- 17  ITEM TOOLTIPS --------------------------------------------- */
.ko-tip {
  position: fixed; z-index: 300;
  max-width: 320px;
  padding: var(--ko-3);
  background: rgba(10,11,14,.97);
  border: 1px solid var(--ko-gold-line);
  box-shadow: var(--ko-shadow-3);
  font-size: .75rem; line-height: 1.55;
  color: var(--ko-text-2);
  pointer-events: none;
  display: none;
}
.ko-tip.is-on { display: block; }
.ko-tip .item_title { display: block; font-weight: 700; font-size: .875rem; margin-bottom: 2px; }
.ko-tip .item_type  { display: block; font-size: .6875rem; margin-bottom: 2px; }
.ko-tip .item_kind  { display: block; color: var(--ko-text-3); font-size: .6875rem; margin-bottom: 6px; }
.ko-tip .item_property { display: block; margin-bottom: 4px; }
.ko-tip .item_property:empty { display: none; }
.ko-tip .tt-warn { display: block; color: #e8837a; text-align: center; margin-top: 4px; }

/* item rarity colours, shared by tooltips and lists */
.white  { color: #dfe3ea; }
.blue   { color: #7fb2e8; }
.yellow { color: #e8d07f; }
.lime   { color: #96d68a; }
.purple { color: #b98ee0; }
.reverse{ color: #e88f7f; }
.unique_item { color: #e0a94a; }
.event_item  { color: #7fe0c8; }
.cospre      { color: #e07fb2; }

.ko-itemicon {
  width: 40px; height: 40px; flex: none;
  border: 1px solid var(--ko-line-2); background: var(--ko-bg-2);
  object-fit: contain;
}
.ko-itemrow { display: flex; align-items: center; gap: var(--ko-3); min-width: 0; }
.ko-itemrow__name { min-width: 0; overflow-wrap: break-word; }

.ko-itemgrid { display: flex; flex-wrap: wrap; gap: var(--ko-2); list-style: none; margin: 0; padding: 0; }
.ko-itemgrid li { flex: none; }
.ko-itemgrid button, .ko-itemgrid a {
  display: grid; place-items: center;
  /* fixed box so the control keeps a usable touch target even if the icon
     image is missing - otherwise the button collapses to a few pixels */
  width: 48px; height: 48px; padding: 3px;
  background: var(--ko-bg-2);
  border: 1px solid var(--ko-line-2); cursor: pointer; line-height: 0;
}
.ko-itemgrid button:hover, .ko-itemgrid a:hover { border-color: var(--ko-gold); }
.ko-itemgrid img { width: 40px; height: 40px; object-fit: contain; display: block; }


/* ---------- 21  CHARACTER SHEET (UserProfile) -----------------------------
   Mirrors the in-game character window: attributes, an equipment paper-doll
   and the 28-slot bag. Mobile-first - the doll keeps its body shape at every
   width, it just gets smaller cells, because a 3-wide doll still fits a
   320 px screen. Nothing here relies on a fixed pixel canvas.
   ------------------------------------------------------------------------- */

/* --- identity header --- */
.ko-charhead {
  display: grid; gap: var(--ko-5);
  padding: var(--ko-5);
  margin-bottom: var(--ko-5);
  background:
    linear-gradient(180deg, rgba(20,23,31,.92) 0%, rgba(13,15,20,.96) 100%);
  border: 1px solid var(--ko-line);
  border-top: 2px solid var(--ko-line-2);
  position: relative; overflow: hidden;
}
.ko-charhead::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 3px;
  background: var(--ko-text-3);
}
.ko-charhead--n1::before { background: var(--ko-karus); }
.ko-charhead--n2::before { background: var(--ko-elmorad); }

.ko-charhead__id { display: flex; align-items: center; gap: var(--ko-4); min-width: 0; }
.ko-charhead__avatar {
  width: 60px; height: 60px; flex: none;
  display: grid; place-items: center;
  font-family: var(--ko-font-display); font-size: 1.6rem; font-weight: 700;
  background: var(--ko-surface); border: 1px solid currentColor;
  border-radius: 2px;
}
.ko-charhead__names { min-width: 0; }
.ko-charhead__name {
  font-family: var(--ko-font-display);
  font-size: 1.35rem; line-height: 1.2; margin: 0 0 var(--ko-2);
  overflow-wrap: anywhere;
}
.ko-charhead__tags { display: flex; flex-wrap: wrap; gap: var(--ko-2); align-items: center; }

.ko-charhead__facts {
  display: grid; gap: var(--ko-2);
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  margin: 0; padding-top: var(--ko-4);
  border-top: 1px solid var(--ko-line);
}
.ko-charhead__facts > div { min-width: 0; }
.ko-charhead__facts dt {
  font-size: .6875rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ko-text-3); margin-bottom: 2px;
}
.ko-charhead__facts dd {
  margin: 0; font-weight: 600; font-size: 1.05rem;
  overflow-wrap: anywhere;
}

/* --- attribute tiles --- */
.ko-attrs {
  display: grid; gap: var(--ko-2);
  /* 112px keeps the longest label - "Intelligence (INT)" - on one line, so
     the tiles in a row all come out the same height */
  grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
}
.ko-attr {
  min-width: 0; padding: var(--ko-3);
  background: var(--ko-bg-2); border: 1px solid var(--ko-line);
  border-radius: 2px;
}
.ko-attr__k {
  display: block; font-size: .625rem; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ko-text-3);
  margin-bottom: 2px; overflow-wrap: anywhere;
}
.ko-attr__v {
  display: block; font-size: 1.25rem; line-height: 1.1; font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* --- the three-part body --- */
.ko-sheet { display: grid; gap: var(--ko-5); grid-template-columns: minmax(0, 1fr); }
.ko-sheet > *, .ko-sheet__gear > *, .ko-sheet__bags > * { min-width: 0; }
.ko-sheet__gear,
.ko-sheet__bags { display: grid; gap: var(--ko-5); grid-template-columns: minmax(0, 1fr); align-content: start; }
.ko-sheet__note {
  margin: 0; font-size: .75rem; color: var(--ko-text-3);
}

.ko-panel__meta {
  margin-left: auto; font-size: .75rem; color: var(--ko-text-3);
  font-variant-numeric: tabular-nums;
}

/* --- one slot --------------------------------------------------------------
   The size is a custom property so the doll, the bag and the cospre row can
   each pick their own scale without duplicating the rest of the rules. */
.ko-slot {
  --slot: 52px;
  position: relative;
  width: 100%; aspect-ratio: 1 / 1;
  min-width: 0;
  display: grid; place-items: center;
  padding: 3px;
  background:
    linear-gradient(180deg, rgba(31,36,48,.85) 0%, rgba(20,23,31,.85) 100%);
  border: 1px solid var(--ko-line-2);
  border-radius: 2px;
  overflow: hidden;
  cursor: default;
  line-height: 0;
  -webkit-tap-highlight-color: transparent;
}
/* aspect-ratio is not in every PHP 7-era browser; this keeps the square. */
@supports not (aspect-ratio: 1 / 1) {
  .ko-slot { height: var(--slot); }
}
/* Item icons are NOT all square - weapons are tall, some scrolls are wide.
   Constraining with max-* instead of width/height:100% lets the icon keep its
   own aspect ratio and be letterboxed inside the square slot, instead of
   stretching the grid row to the icon's height. */
.ko-slot img {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  object-fit: contain;
  display: block;
}
.ko-slot--spacer { background: none; border-color: transparent; pointer-events: none; }
.ko-slot.is-empty {
  background:
    repeating-linear-gradient(135deg,
      rgba(255,255,255,.014) 0 6px, rgba(255,255,255,0) 6px 12px),
    linear-gradient(180deg, rgba(18,21,28,.9) 0%, rgba(12,14,19,.9) 100%);
  border-style: dashed; border-color: var(--ko-line);
}
.ko-slot__unknown {
  font: 700 .8rem/1 var(--ko-font); color: var(--ko-text-3);
}
.ko-slot__count, .ko-slot__dur {
  position: absolute; bottom: 1px;
  font: 700 .625rem/1 var(--ko-font);
  text-shadow: 0 0 3px #000, 0 1px 2px #000;
  pointer-events: none;
}
.ko-slot__count { right: 3px; color: #fff; }
/* a low durability reading, kept distinct from a stack count so a nearly
   broken item is not mistaken for a quantity */
.ko-slot__dur   { left: 3px;  color: #e8837a; }

/* occupied slots are interactive */
button.ko-slot { cursor: pointer; }
button.ko-slot:hover,
button.ko-slot:focus-visible { border-color: var(--ko-gold); outline: none; }
button.ko-slot:focus-visible { box-shadow: 0 0 0 2px var(--ko-gold-soft); }
button.ko-slot.is-active { border-color: var(--ko-gold); box-shadow: 0 0 0 2px var(--ko-gold-soft); }

/* rarity edge, matching the tooltip colours */
.ko-slot--blue        { border-color: rgba(127,178,232,.55); }
.ko-slot--yellow      { border-color: rgba(232,208,127,.55); }
.ko-slot--lime        { border-color: rgba(150,214,138,.55); }
.ko-slot--purple      { border-color: rgba(185,142,224,.55); }
.ko-slot--unique_item { border-color: rgba(224,169,74,.7); }
.ko-slot--event_item  { border-color: rgba(127,224,200,.6); }
.ko-slot--cospre      { border-color: rgba(224,127,178,.6); }
.ko-slot--reverse     { border-color: rgba(232,143,127,.6); }

/* --- the equipment panel and the cospre doll ---------------------------
   Both are the original's three-column grids: the equipment panel is the 3x5
   block from inventory.tpl (slots 0-13 in reading order), the cospre doll is
   the body-shaped block (slots 42-49). Three columns of 56 px plus gaps fit a
   320 px screen, so the shape survives all the way down instead of collapsing
   into a list. */
.ko-equip,
.ko-mbag,
.ko-doll {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--ko-2);
  max-width: 260px;
  margin: 0 auto;
}

/* The cospre doll needs a centred PAIR in its last row (the two magic bags),
   which three columns cannot express. Six half-columns can: every ordinary
   cell spans two of them, so rows 1-3 are the same width and the same gap as
   before - 2col+gap is identical to (W-2g)/3 - and the two bags take columns
   2-3 and 4-5, leaving one half-column of margin on each side. Same slot size
   as every other cell, symmetric about the centre, no offsets. */
.ko-doll { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.ko-doll > * { grid-column: span 2; }
.ko-doll > :nth-last-child(2) { grid-column: 2 / span 2; }
.ko-doll > :last-child        { grid-column: 4 / span 2; }

/* --- bag: as many columns as fit, never below a 44 px touch target --- */
.ko-bag {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(46px, 1fr));
  gap: var(--ko-2);
}

/* --- tablet and up --- */
@media (min-width: 560px) {
  .ko-equip, .ko-mbag, .ko-doll { max-width: 300px; gap: var(--ko-3); }
  .ko-bag  { grid-template-columns: repeat(auto-fill, minmax(52px, 1fr)); }
  .ko-charhead { grid-template-columns: minmax(0, auto) minmax(0, 1fr); align-items: center; }
  .ko-charhead__facts {
    border-top: 0; border-left: 1px solid var(--ko-line);
    padding-top: 0; padding-left: var(--ko-5);
    /* one row of figures, so the header stays a band rather than a tall
       block with the name floating in the middle of it */
    display: flex; flex-wrap: wrap; gap: var(--ko-5) var(--ko-6);
    justify-content: flex-end;
  }
  .ko-charhead__facts > div { flex: 0 0 auto; }
}

/* --- desktop: the in-game 7-wide bag, side by side with the doll --- */
@media (min-width: 900px) {
  .ko-sheet {
    grid-template-columns: minmax(0, 19rem) minmax(0, 17rem) minmax(0, 1fr);
    align-items: start;
  }
  /* Desktop arrangement:
   *
   *   +-------------+---------+---------------------+
   *   | Character   | Cospre  |      Equipped       |
   *   | Statistics  |         +---------------------+
   *   |             |         |      Inventory      |
   *   +-------------+---------+---------------------+
   *
   * The column template above is DELIBERATELY UNCHANGED. Every panel simply
   * takes over the cell its predecessor used, so it inherits that cell's
   * width exactly:
   *   Cospre    -> column 2, the cell Equipment used to hold
   *   Equipment -> column 3 row 1, the cell the Inventory used to hold
   *   Inventory -> column 3 row 2, still column 3, so its width, its column
   *                count and its slot size are bit-for-bit what they were.
   *
   * Equipment and Cospre live inside .ko-sheet__gear, which exists so the
   * narrow layouts can stack them; display:contents dissolves that wrapper
   * (and .ko-sheet__bags) at this width only, promoting their children to
   * real grid items so they can take separate cells. Below 900px both are
   * ordinary grid boxes again and the stacked order is untouched. */
  .ko-sheet__gear,
  .ko-sheet__bags { display: contents; }

  .ko-sheet__stats  { grid-column: 1; grid-row: 1 / span 3; }
  .ko-sheet__cospre { grid-column: 2; grid-row: 1; }
  .ko-sheet__equip  { grid-column: 3; grid-row: 1; }
  /* Column 2 row 2 - the cell under Cospre, which was empty. Same column
     means the same width as the doll above it, with no template change.
     align-self:start keeps the panel at its own height: row 2 is as tall
     as the Inventory beside it, and stretching would just add a hole
     under the last row of bag slots. */
  .ko-sheet__mbag   { grid-column: 2; grid-row: 2; align-self: start; }
  .ko-sheet__bag    { grid-column: 3; grid-row: 2; }
  .ko-sheet__note   { grid-column: 3; grid-row: 3; }

  /* Spanning rows 1-3 keeps the statistics panel from setting row 1's height.
     Sharing a single row with the dolls would push the Inventory down by the
     difference between them. align-items:start still gives it its natural
     height, so nothing about the panel itself changes. */

  /* Cospre is conditional on the build. When it does not render, fall back to
     the arrangement that was here before, rather than leaving column 2 empty.
     A browser without :has() ignores these three rules and shows the gap -
     still usable, never broken. */
  .ko-sheet:has(.ko-sheet__gear > .ko-sheet__equip:last-child) .ko-sheet__equip { grid-column: 2; grid-row: 1; }
  .ko-sheet:has(.ko-sheet__gear > .ko-sheet__equip:last-child) .ko-sheet__bag   { grid-column: 3; grid-row: 1; }
  .ko-sheet:has(.ko-sheet__gear > .ko-sheet__equip:last-child) .ko-sheet__note  { grid-column: 3; grid-row: 2; }
  /* In that fallback the Inventory shares row 1, so the row can be far taller
     than the panels. Statistics must not stretch to meet it - at 1920 that
     dragged it to 748px. It keeps its natural height here. */
  .ko-sheet:has(.ko-sheet__gear > .ko-sheet__equip:last-child) .ko-sheet__stats { align-self: start; }

  /* Both dolls are pinned to the width the equipment doll had in column 2
     before the move. Column 3 is much wider, so without this the equipment
     doll would grow to fill it - the panel must move, not resize. */
  .ko-equip, .ko-mbag, .ko-doll { max-width: 230px; }

  /* First-row balance.
   *
   * Cospre's doll is four rows where Equipment's is five, so at the same slot
   * size its panel always comes out about 90px shorter - which is what made
   * the top of the sheet read as three unrelated boxes.
   *
   * Only COSPRE is stretched, never Equipment. Equipment is the taller of the
   * pair, so it alone sets row 1's height and Cospre grows to meet it. Doing
   * it the other way round - stretching both - makes each panel's height
   * depend on the row and the row's height depend on the panels, and the
   * browser resolves that circle by collapsing the dolls.
   *
   * The doll is pinned with flex: none so it keeps its own size inside the
   * now-taller body; centring it turns the leftover into symmetric padding
   * above and below the slots instead of a hole under the last row. Slot
   * sizes, slot positions and panel widths are all untouched.
   *
   * Character Statistics is deliberately NOT stretched. It keeps
   * grid-row: 1 / span 3 and its natural height, which is what stops it from
   * setting row 1's height - if it grew the row, the Inventory would be
   * pushed down and a gap would open under Cospre and Equipment. From 1200px
   * up its height already lands within a few pixels of Equipment's. */
  .ko-sheet__cospre {
    align-self: stretch;
    display: flex;
    flex-direction: column;
  }
  .ko-sheet__cospre > .ko-panel__body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
  /* width:100% restores what the doll had as a normal block child. As a flex
     item its own "margin: 0 auto" cancels the cross-axis stretch, so without
     this it shrinks to its content and the slots collapse. max-width still
     caps it and the auto margins still centre it. */
  .ko-sheet__cospre .ko-doll { flex: none; width: 100%; }

  /* Still auto-filled here. Between 900 and 1200 the bag column is only about
     370 px wide, and forcing the in-game 7 columns into it squeezes each slot
     down to ~36 px - below a usable target. */
  .ko-bag  { grid-template-columns: repeat(auto-fill, minmax(56px, 1fr)); }
  .ko-bag--cospre { grid-template-columns: repeat(auto-fill, minmax(56px, 1fr)); }
}

/* Wide enough for the real thing: the 7-wide bag and the 8-wide cospre row
   exactly as the game lays them out. */
@media (min-width: 1200px) {
  .ko-sheet { grid-template-columns: minmax(0, 20rem) minmax(0, 19rem) minmax(0, 1fr); }
  /* The width the dolls had in the 19rem column before the move. */
  .ko-equip, .ko-mbag, .ko-doll { max-width: 262px; }

  /* Character Statistics joins the first row properly.
   *
   * From 1200px up it is measurably SHORTER than Equipment - by 5px for a
   * character with an Experience row, by ~54px for one without - so it can
   * safely be placed in row 1 and stretched to meet the other two. Below
   * 1200px the opposite is true (Statistics runs 47-180px TALLER, because the
   * narrower 19rem column wraps its values onto two lines), which is why this
   * lives here and not in the 900px block: putting it in row 1 there would
   * make it set the row height and push the Inventory down.
   *
   * The extra height is handed to the attribute tiles rather than left as
   * blank background - the tiles' own grid rows stretch, so the panel fills
   * out with content. The key/value list underneath keeps its natural size. */
  .ko-sheet__stats {
    grid-row: 1;
    align-self: stretch;
    display: flex;
    flex-direction: column;
  }
  .ko-sheet__stats > .ko-panel__body:not(.ko-panel__body--flush) {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
  }
  .ko-sheet__stats .ko-attrs {
    flex: 1 1 auto;
    align-content: stretch;
  }
  .ko-bag  { grid-template-columns: repeat(7, minmax(0, 1fr)); }
  .ko-bag--cospre { grid-template-columns: repeat(8, minmax(0, 1fr)); }
}

/* Between 560 and 900 the doll and the bags sit two-up, stats full width. */
@media (min-width: 560px) and (max-width: 899px) {
  .ko-sheet { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .ko-sheet__stats { grid-column: 1 / -1; }
  .ko-bag--cospre { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---------- 22  MY CHARACTERS (account character selector) ----------------
   Scoped entirely to .ko-chars / .ko-charcard. Nothing here can reach the
   character sheet, the bags or any other page: no existing class is
   redefined, and every selector below starts with one of those two names.
   The nation stripe, the class colours, .ko-nation and ko_class_badge() are
   reused as-is so a character looks the same here as on its profile. */
.ko-chars {
  display: grid;
  gap: var(--ko-4);
  grid-template-columns: minmax(0, 1fr);
  align-items: stretch;
}
/* Tablet: the 2x2 block. Desktop keeps 2 up to 1200 because four cards in a
   ~900px column squeeze the name and the three figures under it. */
@media (min-width: 560px)  { .ko-chars { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Wide desktop: the four slots read as one row, which is what the account
   actually is. At 1200 each card is ~270px - comfortable, not cramped. */
@media (min-width: 1200px) { .ko-chars { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--ko-5); } }

.ko-chars__note {
  margin: var(--ko-5) 0 0;
  font-size: .75rem;
  color: var(--ko-text-3);
}

.ko-charcard {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  gap: var(--ko-3);
  min-width: 0;
  padding: var(--ko-6) var(--ko-4) var(--ko-4);
  text-align: center;
  color: var(--ko-text);
  background: var(--ko-surface);
  border: 1px solid var(--ko-line);
  border-radius: var(--ko-radius);
  overflow: hidden;
  transition: border-color .2s var(--ko-ease), transform .2s var(--ko-ease),
              background-color .2s var(--ko-ease);
}
/* Nation stripe, the same two colours the profile header uses. */
.ko-charcard::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 2px;
  background: var(--ko-line-2);
}
.ko-charcard--n1::before { background: var(--ko-karus); }
.ko-charcard--n2::before { background: var(--ko-elmorad); }

a.ko-charcard { text-decoration: none; }
a.ko-charcard:hover,
a.ko-charcard:focus-visible {
  border-color: var(--ko-gold-line);
  background: var(--ko-surface-2);
  transform: translateY(-2px);
  outline: none;
}
a.ko-charcard:focus-visible { box-shadow: 0 0 0 2px var(--ko-gold-soft); }
a.ko-charcard:hover .ko-charcard__name,
a.ko-charcard:focus-visible .ko-charcard__name { color: var(--ko-gold); }

.ko-charcard__slot {
  font-size: .625rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ko-text-3);
}

/* The class colour classes (.ko-class--1..5) already carry colour, border and
   background, so the avatar picks up the character's class for free. */
.ko-charcard__avatar {
  width: 56px; height: 56px; border-radius: 50%;
  display: grid; place-items: center;
  font: 700 1.25rem/1 var(--ko-font);
  border: 1px solid var(--ko-line-2);
  background: var(--ko-surface-2);
}
.ko-charcard__avatar--empty {
  color: var(--ko-line-2);
  border-style: dashed;
  background: transparent;
}

.ko-charcard__name {
  font-size: 1rem; font-weight: 700; letter-spacing: .02em;
  min-width: 0; overflow-wrap: anywhere;
  transition: color .2s var(--ko-ease);
}

.ko-charcard__tags {
  display: flex; flex-wrap: wrap; gap: var(--ko-2);
  justify-content: center;
}

/* margin-top:auto pins the figures to the bottom, so cards of different
   heights in one row still line their numbers up. */
.ko-charcard__facts {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--ko-2);
  width: 100%; margin: auto 0 0;
  padding-top: var(--ko-3);
  border-top: 1px solid var(--ko-line);
}
.ko-charcard__facts > div { min-width: 0; }
.ko-charcard__facts dt {
  font-size: .625rem; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ko-text-3); margin-bottom: 2px; overflow-wrap: anywhere;
}
.ko-charcard__facts dd {
  margin: 0; font-size: .8125rem; font-weight: 600;
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
}

/* An empty slot is drawn as an empty slot - the account has four of them and
   hiding the gaps would misrepresent which slot a character sits in. */
.ko-charcard--empty {
  border-style: dashed;
  background: transparent;
  justify-content: center;
}
.ko-charcard--empty .ko-charcard__name { color: var(--ko-text-3); font-weight: 600; }
.ko-charcard--missing { justify-content: center; }
.ko-charcard--missing .ko-charcard__name { color: var(--ko-text-2); }

/* Banned character (USERDATA.Authority = 255 - the same value
   dbo::GetAuthority() calls "Banned Player" and the Banned Players ranking
   selects on).

   Deliberately NOT the "unavailable" treatment: that card is dashed, centred,
   has no figures and is not a link. A banned character is a real character -
   it keeps every figure, keeps full-contrast text and stays clickable. What
   changes is the frame: the nation stripe becomes the error red, the border
   picks up the same red, a faint diagonal hatch marks the card, and the
   decorative chips (avatar, nation, class) desaturate so the red badge is the
   loudest thing on the card. Name, level, NP and clan are untouched. */
.ko-charcard--banned { border-color: rgba(204,77,66,.42); }
.ko-charcard--banned::before { background: var(--ko-err); }
/* The hatch is decoration only: pointer-events:none keeps the whole card
   clickable, and 5% alpha leaves every figure at full legibility. */
.ko-charcard--banned::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(135deg,
    rgba(204,77,66,.05) 0 10px, rgba(204,77,66,0) 10px 20px);
}
/* Only the decorative chips are muted - never the text that carries data. */
.ko-charcard--banned .ko-charcard__avatar,
.ko-charcard--banned .ko-nation,
.ko-charcard--banned .ko-class { filter: grayscale(.8); opacity: .8; }
a.ko-charcard--banned:hover,
a.ko-charcard--banned:focus-visible { border-color: rgba(204,77,66,.75); }

/* --- attribute value colours: a quiet nod to the in-game stat colours --- */
.ko-stat-str { color: #e0a06e; }
.ko-stat-sta { color: #83c795; }
.ko-stat-dex { color: #e6d18a; }
.ko-stat-int { color: #8ab8e4; }
.ko-stat-cha { color: #b98ee0; }

.ko-empty--sm { padding: var(--ko-6) var(--ko-4); }
.ko-empty--sm p { margin: 0; }

/* --- tooltip: pinned mode for touch and keyboard -------------------------
   A hover tooltip is unreachable on a phone. Tapping a slot pins the panel;
   below 720 px it becomes a bottom sheet so a long item description is fully
   readable and never runs off the screen. */
.ko-tip.is-pinned { pointer-events: auto; }
.ko-tip__close {
  display: none;
  position: absolute; top: 4px; right: 4px;
  width: 32px; height: 32px;
  background: none; border: 0; color: var(--ko-text-3);
  font: 400 1.25rem/1 var(--ko-font); cursor: pointer;
}
.ko-tip.is-pinned .ko-tip__close { display: block; }
.ko-tip__close:hover { color: var(--ko-text); }

@media (max-width: 719px) {
  .ko-tip.is-sheet {
    left: 0 !important; right: 0; top: auto !important; bottom: 0;
    max-width: none; width: 100%;
    max-height: 62vh; overflow-y: auto;
    padding: var(--ko-5) var(--ko-5) calc(var(--ko-5) + env(safe-area-inset-bottom, 0px));
    border: 0; border-top: 2px solid var(--ko-gold-line);
    font-size: .8125rem;
  }
  .ko-tip.is-sheet .item_title { font-size: 1rem; }
}

/* ---------- 18  FOOTER ---------------------------------------------------- */
.ko-footer {
  margin-top: auto;
  border-top: 1px solid var(--ko-line);
  background: var(--ko-bg-2);
  padding-top: var(--ko-10);
}
.ko-footer__grid { display: grid; gap: var(--ko-8); grid-template-columns: 1fr; }
@media (min-width: 640px)  { .ko-footer__grid { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (min-width: 1024px) { .ko-footer__grid { grid-template-columns: 1.6fr 1fr 1fr 1fr; } }
.ko-footer h4 {
  font-size: .75rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ko-gold); margin-bottom: var(--ko-4);
  font-family: var(--ko-font); font-weight: 700;
}
.ko-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--ko-2); }
.ko-footer a { color: var(--ko-text-3); font-size: .875rem; }
.ko-footer a:hover { color: var(--ko-gold); }
.ko-footer__about p { font-size: .875rem; color: var(--ko-text-3); max-width: 46ch; }
.ko-footer__social { display: flex; gap: var(--ko-2); margin-top: var(--ko-4); }
.ko-footer__social a {
  width: 38px; height: 38px; display: grid; place-items: center;
  border: 1px solid var(--ko-line); color: var(--ko-text-3); background: var(--ko-surface);
}
.ko-footer__social a:hover { color: var(--ko-gold); border-color: var(--ko-gold-line); }
.ko-footer__bottom {
  margin-top: var(--ko-10);
  padding-block: var(--ko-5);
  border-top: 1px solid var(--ko-line);
  display: flex; flex-wrap: wrap; gap: var(--ko-3);
  align-items: center; justify-content: space-between;
  font-size: .75rem; color: var(--ko-text-3);
}
.ko-footer__bottom p { margin: 0; }

/* ---------- 19  UTILITIES ------------------------------------------------- */
.ko-hidden { display: none !important; }
.ko-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.ko-gold { color: var(--ko-gold); }
.ko-nowrap { white-space: nowrap; }
.ko-ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ko-tabnum { font-variant-numeric: tabular-nums; }
.ko-mt-0 { margin-top: 0; }
.ko-mb-0 { margin-bottom: 0; }
.ko-mt-4 { margin-top: var(--ko-4); }
.ko-mt-6 { margin-top: var(--ko-6); }
.ko-mt-8 { margin-top: var(--ko-8); }
.ko-mb-4 { margin-bottom: var(--ko-4); }
.ko-mb-6 { margin-bottom: var(--ko-6); }
.ko-py-8 { padding-block: var(--ko-8); }
.ko-text-center { text-align: center; }
.ko-flex-1 { flex: 1 1 auto; min-width: 0; }
@media (max-width: 767px)  { .ko-hide-sm { display: none !important; } }
@media (min-width: 1024px) { .ko-only-mobile { display: none !important; } }

/* Nothing may make the document wider than the viewport. */
html, body.ko-body { max-width: 100%; overflow-x: hidden; }
.ko-container, .ko-main, .ko-panel, .ko-card { min-width: 0; max-width: 100%; }
.ko-panel__body, .ko-panel__head, .ko-panel__foot { min-width: 0; }

/* Legacy safety net: any leftover old markup stays inside the viewport
   instead of forcing the page to scroll sideways. */
.ko-main table:not(.ko-table) { max-width: 100%; display: block; overflow-x: auto; }
.ko-main img { max-width: 100%; height: auto; }
.ko-main iframe { max-width: 100%; }
.ko-main [style*="width:"] { max-width: 100%; }

/* ---------- 20  REDUCED MOTION / PRINT ------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

@media print {
  .ko-topbar, .ko-header, .ko-ticker, .ko-footer, .ko-drawer, .ko-toasts, .ko-btn { display: none !important; }
  body.ko-body { background: #fff; color: #000; }
  .ko-panel, .ko-card { border-color: #ccc; }
}

/* ---------- 23  NEWS CMS + ARTICLE  (added 2026-09-06) -------------------- */

/* --- admin: article list ------------------------------------------------- */
.ko-admnews__thumbcol { width: 88px; }
.ko-admnews__thumb {
  width: 72px; height: 41px; object-fit: cover;
  border-radius: 2px; border: 1px solid var(--ko-line); display: block;
}
.ko-admnews__id { display: block; font-size: .6875rem; color: var(--ko-text-3); }
.ko-admnews__t  { display: block; overflow: hidden; text-overflow: ellipsis; }
/* Language tag in front of each non-English title on the admin news list. */
.ko-admnews__lg {
  display: inline-block; min-width: 1.6em; margin-right: 4px;
  font-size: .625rem; font-weight: 700; letter-spacing: .06em;
  color: var(--ko-text-3);
}
.ko-admnews__actcol { width: 1%; }
.ko-admnews__acts { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.ko-admnews__del { display: inline; margin: 0; }
.ko-btn--danger {
  border-color: rgba(204,77,66,.45); background: rgba(204,77,66,.12); color: #e8837a;
}
.ko-btn--danger:hover { background: rgba(204,77,66,.2); color: #f0a09a; }
.ko-panel__action { margin-left: auto; }

/* --- admin: form --------------------------------------------------------- */
.ko-field { margin-bottom: var(--ko-5); }
.ko-field > label {
  display: block; margin-bottom: 6px;
  font-size: .75rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ko-text-2);
}
.ko-field__hint { margin: 6px 0 0; font-size: .8125rem; color: var(--ko-text-3); }
.ko-field__hint.is-over { color: #e8837a; font-weight: 700; }
.ko-newsform__img { display: flex; gap: var(--ko-4); align-items: flex-start; flex-wrap: wrap; }
.ko-newsform__preview {
  width: 240px; height: 135px; object-fit: cover; flex: none;
  border: 1px solid var(--ko-line); border-radius: var(--ko-radius); background: var(--ko-bg-2);
}
.ko-newsform__foot {
  display: flex; gap: var(--ko-3); align-items: center; flex-wrap: wrap;
  padding-top: var(--ko-4); border-top: 1px solid var(--ko-line);
}
.ko-langpane { display: none; }
.ko-langpane.is-active { display: block; }

/* --- admin: editor ------------------------------------------------------- */
.ko-editor {
  border: 1px solid var(--ko-line-2); border-radius: var(--ko-radius);
  background: var(--ko-surface); overflow: hidden;
}
.ko-editor__bar {
  display: flex; flex-wrap: wrap; gap: 2px; align-items: center;
  padding: 6px; background: var(--ko-surface-2);
  border-bottom: 1px solid var(--ko-line-2);
}
.ko-editor__b {
  min-width: 32px; height: 30px; padding: 0 8px;
  border: 1px solid transparent; border-radius: 2px;
  background: transparent; color: var(--ko-text-2);
  font-size: .8125rem; line-height: 1; cursor: pointer;
  transition: background-color .12s var(--ko-ease), color .12s var(--ko-ease);
}
.ko-editor__b:hover { background: var(--ko-surface-3); color: var(--ko-text); }
.ko-editor__b.is-on {
  background: var(--ko-gold-soft); border-color: var(--ko-gold-line); color: var(--ko-gold-hi);
}
.ko-editor__sep { width: 1px; height: 18px; margin: 0 4px; background: var(--ko-line-2); }
.ko-editor__area {
  min-height: 260px; max-height: 60vh; overflow-y: auto;
  padding: var(--ko-4); color: var(--ko-text); font-size: .9375rem; line-height: 1.7;
}
.ko-editor__area:focus { outline: 2px solid var(--ko-gold-line); outline-offset: -2px; }
.ko-editor__area.is-empty::before {
  content: attr(data-placeholder); color: var(--ko-text-3); pointer-events: none;
}
.ko-editor__area > :first-child { margin-top: 0; }
.ko-editor__area p { margin: 0 0 .8em; color: inherit; }
.ko-editor__area h3 { font-size: 1.15rem; margin: 1.2em 0 .5em; }
.ko-editor__area h4 { font-size: 1rem; margin: 1.1em 0 .45em; }
.ko-editor__area ul, .ko-editor__area ol { margin: 0 0 .8em; padding-left: 1.4em; }
.ko-editor__area blockquote {
  margin: 0 0 .8em; padding: .5em .9em;
  border-left: 3px solid var(--ko-gold-line); background: var(--ko-surface-2);
}
.ko-editor__area a { color: var(--ko-gold); text-decoration: underline; }

/* --- public: article ----------------------------------------------------- */
.ko-article__hero {
  /* margin:0 is load-bearing: <figure> carries a 1em/40px UA margin that
     otherwise pushes the hero 20px past the panel on both sides. */
  position: relative; width: 100%; margin: 0 0 var(--ko-6);
  border: 1px solid var(--ko-line); border-radius: var(--ko-radius);
  overflow: hidden; background: var(--ko-bg-2);
}
.ko-article__hero img {
  display: block; width: 100%; height: auto;
  max-height: 460px; object-fit: cover; object-position: center;
}
.ko-article__meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--ko-3);
  margin-bottom: var(--ko-5); padding-bottom: var(--ko-4);
  border-bottom: 1px solid var(--ko-line);
  font-size: .8125rem; color: var(--ko-text-3);
}
.ko-article__meta > span { display: inline-flex; align-items: center; gap: 6px; }
.ko-article__body { font-size: 1rem; line-height: 1.75; color: var(--ko-text-2); }
.ko-article__body > :first-child { margin-top: 0; }
.ko-article__body > :last-child { margin-bottom: 0; }
.ko-article__body p { margin: 0 0 1.1em; color: inherit; }
.ko-article__body h3 {
  font-size: 1.25rem; margin: 1.8em 0 .6em; color: var(--ko-text);
  padding-left: .6em; border-left: 3px solid var(--ko-gold-line);
}
.ko-article__body h4 { font-size: 1.05rem; margin: 1.5em 0 .5em; color: var(--ko-text); }
.ko-article__body ul, .ko-article__body ol { margin: 0 0 1.1em; padding-left: 1.5em; }
.ko-article__body li { margin-bottom: .4em; }
.ko-article__body a { color: var(--ko-gold); text-decoration: underline; text-underline-offset: 2px; }
.ko-article__body a:hover { color: var(--ko-gold-hi); }
.ko-article__body strong, .ko-article__body b { color: var(--ko-text); font-weight: 700; }
.ko-article__body blockquote {
  margin: 0 0 1.2em; padding: .9em 1.1em;
  border-left: 3px solid var(--ko-gold-line);
  background: var(--ko-surface-2); border-radius: 0 var(--ko-radius) var(--ko-radius) 0;
  color: var(--ko-text-2);
}
.ko-article__body blockquote > :last-child { margin-bottom: 0; }

@media (max-width: 719px) {
  .ko-article__hero img { max-height: 220px; }
  .ko-newsform__preview { width: 100%; height: auto; aspect-ratio: 16 / 9; }
  .ko-admnews__acts { justify-content: flex-start; }
  .ko-editor__area { min-height: 200px; }
}

/* ---------- 24  ADMINCP + NEWS IMAGE CONTROLS  (added 2026-09-06) --------- */
.ko-pagehead--admin { border-bottom-color: var(--ko-gold-line); }
.ko-admtag {
  display: inline-block; vertical-align: middle; margin-right: 8px;
  padding: 3px 9px; border: 1px solid var(--ko-gold-line); border-radius: 2px;
  background: var(--ko-gold-soft); color: var(--ko-gold-hi);
  font-size: .625rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
}
.ko-user__avatar--adm {
  display: inline-flex; align-items: center; justify-content: center;
  border-color: var(--ko-gold-line); background: var(--ko-gold-soft); color: var(--ko-gold-hi);
}
/* Entry point from UserCP, rendered for authority 0 only. */
.ko-cp__admin {
  display: flex; align-items: center; gap: var(--ko-3);
  margin: 0 var(--ko-3) var(--ko-3); padding: var(--ko-3);
  border: 1px solid var(--ko-gold-line); border-radius: var(--ko-radius);
  background: var(--ko-gold-soft); color: var(--ko-text);
}
.ko-cp__admin:hover { background: rgba(200,164,74,.16); color: var(--ko-text); }
.ko-cp__admin strong { display: block; font-size: .875rem; color: var(--ko-gold-hi); }
.ko-cp__admin__ico { flex: none; color: var(--ko-gold-hi); display: inline-flex; }

/* Image picker: preview keeps the real aspect ratio, with a floating remove
   control. Nothing is uploaded or deleted here - the X only sets a form flag. */
.ko-newsform__prevbox {
  position: relative; margin: 0; flex: none;
  width: 240px; max-width: 100%;
  border: 1px solid var(--ko-line); border-radius: var(--ko-radius);
  background: var(--ko-bg-2); overflow: hidden; line-height: 0;
}
.ko-newsform__preview { display: block; width: 100%; height: auto; max-height: 200px; object-fit: contain; }
.ko-imgx {
  position: absolute; top: 6px; right: 6px;
  width: 26px; height: 26px; padding: 0; line-height: 1;
  border: 1px solid rgba(204,77,66,.5); border-radius: 2px;
  background: rgba(18,19,24,.86); color: #e8837a;
  font-size: 1rem; cursor: pointer;
}
.ko-imgx:hover { background: rgba(204,77,66,.28); color: #f3aaa4; }
@media (max-width: 719px) { .ko-newsform__prevbox { width: 100%; } }

/* =========================================================================
   DOWNLOADS (added 2026-09-07)

   Every selector here is prefixed .ko-dl and is used only by
   content/KO/pages/Downloads.php and content/KO/admincp/Downloads.php. No
   existing rule above was edited, reordered or removed, so no other page can
   be affected by this block. Only tokens already defined by the design system
   are used, so both themes and every breakpoint stay consistent.
   ========================================================================= */

/* --- public: the Full Client hero row ------------------------------------ */
.ko-dlhero {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: var(--ko-5);
}
.ko-dlhero__text { min-width: 0; flex: 1 1 260px; }
.ko-dlhero__btn { flex: none; }
@media (max-width: 559px) {
  .ko-dlhero { flex-direction: column; align-items: stretch; }
  .ko-dlhero__btn { width: 100%; justify-content: center; }
}

/* --- public: the mirror list --------------------------------------------- */
.ko-dlmirrors { border-top: 1px solid var(--ko-line); }
.ko-dlsub {
  margin: 0 0 var(--ko-4); font-size: .8125rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ko-text-3);
}
.ko-dlmirrors__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--ko-3); }
.ko-dlmirror {
  display: flex; align-items: center; gap: var(--ko-4);
  padding: var(--ko-3) var(--ko-4);
  border: 1px solid var(--ko-line); background: var(--ko-surface-2);
  transition: border-color .2s var(--ko-ease);
}
.ko-dlmirror:hover { border-color: var(--ko-gold-line); }
.ko-dlmirror__n {
  width: 26px; height: 26px; flex: none; display: grid; place-items: center;
  border: 1px solid var(--ko-gold-line); background: var(--ko-gold-soft);
  color: var(--ko-gold); font-size: .75rem; font-weight: 700;
}
.ko-dlmirror__t { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.ko-dlmirror__b { flex: none; }
@media (max-width: 479px) {
  .ko-dlmirror { flex-wrap: wrap; }
  .ko-dlmirror__t { flex-basis: calc(100% - 26px - var(--ko-4)); }
  .ko-dlmirror__b { width: 100%; justify-content: center; }
}

/* --- AdminCP: the three sections ----------------------------------------- */
.ko-dlsec + .ko-dlsec { margin-top: var(--ko-8); padding-top: var(--ko-6); border-top: 1px solid var(--ko-line); }
.ko-dlsec__h {
  display: flex; align-items: center; gap: var(--ko-2);
  margin: 0 0 var(--ko-2); font-size: .8125rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ko-text-2);
}
.ko-dlsec__h .ko-badge { margin-left: var(--ko-2); }
.ko-dlurl { display: inline-block; max-width: 42ch; overflow-wrap: anywhere; word-break: break-all; }
/* Keep Edit and Delete on one line in the admin tables: the URL column is
   greedy, and the shared .ko-admnews__acts allows wrapping. Scoped to
   .ko-dlsec so the News and FAQ lists are untouched. */
.ko-dlsec .ko-admnews__acts { flex-wrap: nowrap; }
@media (max-width: 719px) {
  .ko-dlsec .ko-admnews__acts { flex-wrap: wrap; }
  .ko-dlurl { max-width: 100%; }
}
.ko-dl-acts { margin-left: auto; display: flex; flex-wrap: wrap; gap: var(--ko-2); }
@media (max-width: 559px) {
  .ko-panel__head .ko-dl-acts { margin-left: 0; width: 100%; }
}

/* ===========================================================================
   PAYMENTS - shop grid, pager, and the Buy NPoints call-to-action.
   Added 2026-09-07 with the payment system. Appended only; no existing rule
   above was altered. Every value uses the tokens already defined at the top of
   this file, so the block inherits the site's palette and spacing.
   ======================================================================== */

.ko-shop {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--ko-4);
}
.ko-shop__item {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--ko-3);
  padding: var(--ko-6) var(--ko-5) var(--ko-5);
  background: var(--ko-surface);
  border: 1px solid var(--ko-line);
  border-radius: var(--ko-radius-lg);
  box-shadow: var(--ko-shadow-1);
  transition: transform .18s var(--ko-ease), border-color .18s var(--ko-ease), box-shadow .18s var(--ko-ease);
}
.ko-shop__item:hover { transform: translateY(-2px); border-color: var(--ko-gold-line); box-shadow: var(--ko-shadow-2); }
.ko-shop__item.is-featured { border-color: var(--ko-gold); box-shadow: var(--ko-shadow-2); }

.ko-shop__flag {
  position: absolute; top: -11px; left: 50%; transform: translateX(-50%);
  padding: 2px 10px; white-space: nowrap;
  font: 600 11px/1.8 var(--ko-font); letter-spacing: .08em; text-transform: uppercase;
  color: #14161c; background: var(--ko-gold); border-radius: 999px;
}
.ko-shop__name { margin: 0; font-family: var(--ko-font-display); font-size: 15px; letter-spacing: .04em; text-transform: uppercase; }
.ko-shop__np { display: flex; align-items: baseline; gap: var(--ko-2); }
.ko-shop__npval { font-family: var(--ko-font-display); font-size: 30px; line-height: 1.1; color: var(--ko-gold); }
.ko-shop__nplab { font-size: 12px; letter-spacing: .06em; text-transform: uppercase; opacity: .75; }
.ko-shop__desc { margin: 0; font-size: 13px; opacity: .8; }
.ko-shop__price { margin-top: auto; padding-top: var(--ko-2); font-size: 18px; font-weight: 600; }
.ko-shop__form { margin: 0; }
.ko-shop__bal { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--ko-2); }
.ko-shop__bal strong { font-family: var(--ko-font-display); font-size: 20px; color: var(--ko-gold); }
.ko-shop__note p { margin: 0 0 var(--ko-2); }
.ko-shop__note p:last-child { margin-bottom: 0; }

/* Pagination used by the UserCP payment history and the AdminCP transaction
   list. There was no pager component before; this is the only new component. */
.ko-pager { display: flex; align-items: center; justify-content: center; gap: var(--ko-4); }

/* Buy NPoints call-to-action in the header. Keyed off the 'cta' flag in
   system/nav.php, which only that one entry sets - the pre-existing 'accent'
   flag on Download is untouched and still renders exactly as before. */
.ko-nav__link--cta {
  color: var(--ko-gold);
  border: 1px solid var(--ko-gold-line);
  border-radius: var(--ko-radius);
  background: var(--ko-gold-soft);
}
.ko-nav__link--cta:hover { color: var(--ko-gold-hi); border-color: var(--ko-gold); }
.ko-mnav__link--cta { color: var(--ko-gold); }

/* Buy NPoints entry in the UserCP sidebar (added 2026-09-07).

   Deliberately the same shape as .ko-cp__admin directly above it - same box,
   same padding, same rhythm - so the two read as one stacked pair when an
   administrator sees both. Only the accent differs: AdminCP keeps gold,
   this uses the existing --ko-ok token so a purchase action is instantly
   distinguishable from an administration link without introducing a new
   colour to the design system.

   No existing rule was edited, reordered or removed. Both selectors here are
   new and are used only by content/KO/pages/UserCP.php. */
.ko-cp__buy {
  display: flex; align-items: center; gap: var(--ko-3);
  margin: 0 var(--ko-3) var(--ko-3); padding: var(--ko-3);
  border: 1px solid rgba(85,168,107,.34); border-radius: var(--ko-radius);
  background: rgba(85,168,107,.12); color: var(--ko-text);
}
.ko-cp__buy:hover { background: rgba(85,168,107,.18); color: var(--ko-text); }
.ko-cp__buy strong { display: block; font-size: .875rem; color: var(--ko-ok); }
.ko-cp__buy__ico { flex: none; color: var(--ko-ok); display: inline-flex; }

/* =========================================================================
   CHECKOUT / EMBEDDED PAYMENT / TEST PROVIDER (added 2026-09-08)

   Every selector below is new and is used only by the checkout, embedded
   Stripe and Test Provider pages plus the AdminCP provider panels. No
   existing rule above was edited, reordered or removed, and only tokens
   already defined by the design system are used.
   ========================================================================= */

/* Checkout: summary beside the method list, stacking on narrow screens. */
.ko-co { display: grid; gap: var(--ko-4); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px) { .ko-co { grid-template-columns: 360px 1fr; } }
.ko-co__np    { font-family: var(--ko-font-display); font-size: 22px; color: var(--ko-gold); }
.ko-co__price { font-family: var(--ko-font-display); font-size: 22px; }
.ko-co__list  { display: grid; gap: var(--ko-3); }

/* One selectable payment method. The whole card is the label, so the hit
   area is the card rather than the radio dot. */
.ko-co__opt {
  display: flex; align-items: flex-start; gap: var(--ko-3);
  padding: var(--ko-3); cursor: pointer;
  border: 1px solid var(--ko-line); border-radius: var(--ko-radius);
  background: var(--ko-bg-2); transition: border-color .15s var(--ko-ease), background .15s var(--ko-ease);
}
.ko-co__opt:hover { border-color: var(--ko-gold-line); }
.ko-co__opt input[type="radio"] { margin-top: 3px; flex: none; }
.ko-co__opt__body { display: flex; flex-direction: column; gap: 2px; }
.ko-co__opt__name { font-weight: 600; display: flex; align-items: center; gap: var(--ko-2); }
.ko-co__opt__desc { font-size: 13px; opacity: .8; }
.ko-co__opt.is-dev { border-style: dashed; }
/* :has() is progressive - browsers without it simply show no highlight. */
.ko-co__opt:has(input:checked) { border-color: var(--ko-gold); background: var(--ko-gold-soft); }
.ko-co__foot { margin-top: var(--ko-4); }
.ko-co__note { margin-top: var(--ko-2); }

/* Embedded Stripe: the mount point Stripe replaces with its own iframe. */
.ko-emb__head   { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--ko-2); }
.ko-emb__amount { font-family: var(--ko-font-display); font-size: 20px; color: var(--ko-gold); }
.ko-emb__mount  { min-height: 320px; }

/* Test Provider checkout. */
.ko-tp { display: grid; gap: var(--ko-4); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px) { .ko-tp { grid-template-columns: 1fr 340px; } }
.ko-tp__banner { display: flex; flex-direction: column; gap: 2px; }
.ko-tp__row    { display: grid; gap: var(--ko-3); grid-template-columns: 1fr 1fr; }
.ko-tp__ref    { margin-top: var(--ko-4); }
.ko-tp__ref h3 { font-size: 14px; margin: 0 0 var(--ko-2); }
.ko-tp__scen   { margin: 0 0 var(--ko-2); }

/* AdminCP: Test/Live credential groups, and the webhook event list. */
.ko-credset {
  margin: var(--ko-4) 0 0; padding: var(--ko-3);
  border: 1px solid var(--ko-line); border-radius: var(--ko-radius);
  background: var(--ko-bg-2);
}
.ko-credset > legend { padding: 0 var(--ko-2); font-weight: 600; color: var(--ko-gold); }
.ko-wh__events { margin: 0 0 var(--ko-3); padding-left: 1.1rem; }
.ko-wh__events li { margin: 0 0 2px; }

/* Overview provider availability cards (added 2026-09-08). New selectors only;
   nothing above was edited. */
.ko-provgrid { display: grid; gap: var(--ko-3); grid-template-columns: 1fr; }
@media (min-width: 720px) { .ko-provgrid { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); } }
.ko-provcard {
  padding: var(--ko-3); border: 1px solid var(--ko-line);
  border-radius: var(--ko-radius); background: var(--ko-bg-2);
}
.ko-provcard.is-dev { border-style: dashed; }
.ko-provcard__head { display: flex; align-items: center; gap: var(--ko-2); margin-bottom: var(--ko-2); }
.ko-derived { margin: 0 0 var(--ko-3); }
