/* ==========================================================================
   Mobbia — "The Ledger"
   A living ledger. Deep ink ground, ruled cells, one committed gold.
   Mobile-first: the base layer is the 320px case, width is added upward.

   No min-width, no fixed columns, no absolute layout, no mixed grays.
   ========================================================================== */

/* --- Type --------------------------------------------------------------- */

@font-face {
	font-family: 'Barlow';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/barlow-400.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
		U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
		U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Barlow';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/barlow-400-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
		U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
		U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'Barlow';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('../fonts/barlow-500.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
		U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
		U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Barlow';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('../fonts/barlow-500-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
		U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
		U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
	font-family: 'Barlow';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url('../fonts/barlow-600.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
		U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
		U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Barlow';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url('../fonts/barlow-600-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
		U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
		U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'Barlow';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('../fonts/barlow-700.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
		U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
		U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Barlow';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('../fonts/barlow-700-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
		U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
		U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* One family, four weights. It used to be two: Barlow for the body (which only
   shipped 400/500) and Barlow Semi Condensed for every 600/700, so body text
   could never be genuinely bold and the two families had to share every heavy
   element. The Semi Condensed faces were removed rather than shipped dead. */

/* --- Tokens -------------------------------------------------------------
   Zero mixed grays: every value below is a pure step between the ink and the
   text. Contrast is carried by weight and proximity, never by tinting.        */

:root {
	/* Ink ground — three steps, no tint */
	--ink-900: #0a0e14;
	--ink-800: #0d1219;
	--ink-700: #131a24;
	--ink-600: #1c2431;
	--ink-500: #28323f;
	--ink-400: #3a4655;

	/* Text — four steps */
	--text-primary: #f2f5f8;
	--text-secondary: #b4bfcc;
	--text-muted: #8592a3;
	--text-faint: #6b7787;

	/* The one committed color: TibiaCoins gold. Ledger and coin register. */
	--gold-400: #f0c674;
	--gold-500: #d9a441;
	--gold-600: #a87a25;

	/* Verde de marca, medido sobre el boton "Play" de la landing
	   (images/landing/btn-green-640.png): #47704c es el color dominante y
	   #56845b el tono de borde/hover. Se usa en el boton de descarga, que es la
	   accion que el visitante quiere hacer y no la unica de la pagina: en oro
	   competia con el resto de acentos dorados y no destacaba. */
	--green-400: #56845b;
	--green-500: #47704c;

	--gold-wash: rgba(217, 164, 65, 0.12);
	--gold-edge: rgba(217, 164, 65, 0.38);

	/* Live signal. Deliberately rare: when it appears it means something. */
	--live: #4ec98a;
	--live-wash: rgba(78, 201, 138, 0.12);
	--down: #d95f5f;
	/* Rojo para TEXTO de error, mas claro que --down. --down esta calibrado para
	   bordes y rellenos, y ahi el contraste importa menos; usado como color de
	   texto sobre ink-600 da 4.27 y sobre ink-500 da 3.55, los dos por debajo de AA
	   (4.5). Este da 7.49 / 6.68 / 5.56 sobre ink-700 / ink-600 / ink-500, con
	   margen en todos. No es un rojo distinto: es el mismo, aclarado hasta que se
	   lee. */
	--down-ink: #ef8f8f;

	--rule: #1f2833;
	--rule-strong: #2b3746;

	--font-body: 'Barlow', ui-sans-serif, system-ui, sans-serif;
	/* Chrome was 'Barlow Semi Condensed', a second family. There is now one, so
	   --font-chrome is the same stack: heavy elements pick their weight from the
	   600/700 faces instead of from a condensed sibling with a different rhythm. */
	--font-chrome: 'Barlow', ui-sans-serif, system-ui, sans-serif;

	--step-0: 0.9375rem;
	--step-1: 1.0625rem;
	--step-2: 1.375rem;
	--step-3: 1.875rem;
	--step-4: 2.5rem;
	--step-5: 3.5rem;

	--gap: 1rem;
	--gap-lg: 1.75rem;
	--pad: 1rem;
	--measure: 70ch;

	--radius: 3px;

	/* One tempo, shared by the pulse rule and the save countdown */
	--tempo: 3s;

	--ease-out: cubic-bezier(0.16, 1, 0.3, 1);

	color-scheme: dark;
}

/* --- Reset -------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

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

body.ledger {
	margin: 0;
	background: var(--ink-900);
	color: var(--text-primary);
	font-family: var(--font-body);
	font-size: var(--step-1);
	line-height: 1.6;
	-webkit-font-smoothing: antialiased;
	overflow-wrap: break-word;
}

h1, h2, h3, h4 {
	font-family: var(--font-chrome);
	font-weight: 700;
	line-height: 1.15;
	text-wrap: balance;
	margin: 0 0 0.5em;
	letter-spacing: -0.01em;
}

h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); }

p { margin: 0 0 1em; max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

img, svg { max-width: 100%; height: auto; display: block; }

/* Browser surfaces carry the design, not the default */
::selection { background: var(--gold-600); color: var(--ink-900); }

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

.visually-hidden {
	position: absolute;
	width: 1px; height: 1px;
	margin: -1px; padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.skip-link {
	position: absolute;
	left: 0.5rem;
	top: -3rem;
	z-index: 100;
	padding: 0.6rem 1rem;
	background: var(--gold-500);
	color: var(--ink-900);
	font-family: var(--font-chrome);
	font-weight: 700;
	text-decoration: none;
	transition: top 0.15s var(--ease-out);
}
.skip-link:focus { top: 0.5rem; }

/* --- Links -------------------------------------------------------------- */

a {
	color: var(--gold-400);
	text-underline-offset: 0.18em;
	text-decoration-thickness: 1px;
	transition: color 0.12s var(--ease-out);
}
a:hover { color: var(--text-primary); }

/* --- The spine: one rule, width of the page, every section hangs off it --- */

.ledger-rule {
	height: 1px;
	background: var(--rule-strong);
	border: 0;
	margin: 0;
}

.ledger-page {
	display: flex;
	flex-direction: column;
	min-height: 100dvh;
}

/* --- Header ------------------------------------------------------------- */

.ledger-header {
	position: sticky;
	top: 0;
	z-index: 50;
	background: rgba(10, 14, 20, 0.94);
	backdrop-filter: blur(8px);
	border-bottom: 1px solid var(--rule);
}

.ledger-header__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75rem var(--gap);
	padding: 0.7rem var(--pad);
	max-width: 1400px;
	margin: 0 auto;
}

.ledger-brand {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	text-decoration: none;
}
.ledger-brand img { height: 28px; width: auto; }

/* Disclosure: nav is collapsed by default on narrow screens */
.ledger-nav__toggle {
	margin-left: auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 40px;
	background: transparent;
	border: 1px solid var(--rule-strong);
	border-radius: var(--radius);
	color: var(--text-primary);
	cursor: pointer;
}
.ledger-nav__toggle-bars,
.ledger-nav__toggle-bars::before,
.ledger-nav__toggle-bars::after {
	display: block;
	width: 18px;
	height: 2px;
	background: currentColor;
	content: '';
	transition: transform 0.2s var(--ease-out), opacity 0.15s var(--ease-out);
}
.ledger-nav__toggle-bars { position: relative; }
.ledger-nav__toggle-bars::before { position: absolute; top: -6px; }
.ledger-nav__toggle-bars::after { position: absolute; top: 6px; }

.ledger-nav__toggle[aria-expanded='true'] .ledger-nav__toggle-bars { background: transparent; }
.ledger-nav__toggle[aria-expanded='true'] .ledger-nav__toggle-bars::before { transform: translateY(6px) rotate(45deg); }
.ledger-nav__toggle[aria-expanded='true'] .ledger-nav__toggle-bars::after { transform: translateY(-6px) rotate(-45deg); }

.ledger-nav {
	display: none;
	flex-basis: 100%;
	order: 4;
	padding-bottom: 0.75rem;
}
.ledger-nav[data-open='true'] { display: block; }

.ledger-nav__categories {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.25rem;
}
.ledger-nav__category { border-top: 1px solid var(--rule); }
.ledger-nav__category:last-child { border-bottom: 1px solid var(--rule); }

.ledger-nav__heading {
	display: block;
	padding: 0.7rem 0.25rem 0.35rem;
	font-family: var(--font-chrome);
	font-weight: 700;
	font-size: var(--step-0);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-primary);
	text-decoration: none;
}
.ledger-nav__heading[aria-current='page'] { color: var(--gold-400); }

.ledger-nav__items {
	list-style: none;
	margin: 0 0 0.5rem;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 0.15rem 0.9rem;
}
.ledger-nav__items a {
	display: inline-block;
	padding: 0.2rem 0;
	font-size: var(--step-0);
	color: var(--text-muted);
	text-decoration: none;
}
.ledger-nav__items a:hover { color: var(--text-primary); }

.ledger-header__account {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	margin-left: auto;
}

/* --- Buttons ------------------------------------------------------------ */

.ledger-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.45rem;
	min-height: 40px;
	padding: 0.5rem 0.95rem;
	background: var(--ink-600);
	color: var(--text-primary);
	border: 1px solid var(--rule-strong);
	border-radius: var(--radius);
	font-family: var(--font-chrome);
	font-weight: 600;
	font-size: var(--step-0);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 0.15s var(--ease-out), border-color 0.15s var(--ease-out);
}
.ledger-btn:hover {
	background: var(--ink-500);
	color: var(--text-primary);
	border-color: var(--ink-400);
}
.ledger-btn--quiet { background: transparent; color: var(--text-secondary); }

.ledger-btn--waypoint {
	background: var(--gold-500);
	border-color: var(--gold-400);
	color: var(--ink-900);
	font-weight: 700;
}
.ledger-btn--waypoint:hover {
	background: var(--gold-400);
	border-color: var(--gold-400);
	color: var(--ink-900);
}
.ledger-btn--waypoint .waypoint { flex: 0 0 auto; }

/* --- Live status band: the site's reason for existing --------------------- */

.ledger-band {
	background: var(--ink-800);
	border-bottom: 1px solid var(--rule);
}

.ledger-figures {
	list-style: none;
	margin: 0 auto 3rem;
	padding: 0;
	max-width: 1400px;
	display: grid;
	grid-template-columns: 1fr;
}

.ledger-figure {
	position: relative;
	display: grid;
	grid-template-columns: 1fr auto;
	grid-template-areas:
		'label value'
		'sub    value'
		'prov   prov';
	column-gap: var(--gap);
	padding: 0.7rem var(--pad) 0.8rem;
	border-bottom: 1px solid var(--rule);
}
.ledger-figure:last-child { border-bottom: 0; }

.ledger-figure__label {
	grid-area: label;
	font-family: var(--font-chrome);
	font-weight: 600;
	font-size: var(--step-0);
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--text-muted);
}
/* step-2, not step-3. At step-3 (1.875rem, bold) these three read as the loudest
   thing on any page they appear on, and two of the three are not news: "83642
   monsters loaded" is a figure the server reports about itself, not something a
   visitor came to read. The band is a status strip, so the label leads and the
   figure is a value beside it.

   The figures are also demoted a step in colour rather than only in size, so the
   hierarchy survives when a value runs to three digits and the row grows. --text-primary
   on the band is 15.9:1 and --text-secondary is 8.6:1, both well clear of AA. */
.ledger-figure__value {
	grid-area: value;
	align-self: center;
	font-family: var(--font-chrome);
	font-weight: 700;
	font-size: var(--step-2);
	font-variant-numeric: tabular-nums;
	line-height: 1;
	color: var(--text-secondary);
}
.ledger-figure__sub {
	grid-area: sub;
	font-size: var(--step-0);
	color: var(--text-muted);
}
/* Provenance is always in the DOM. A stale reading is visible, not implied. */
.ledger-figure__provenance {
	grid-area: prov;
	margin-top: 0.3rem;
	font-size: 0.8125rem;
	color: var(--text-muted);
}

.ledger-figure[data-state='live'] .ledger-figure__value { color: var(--live); }
.ledger-figure[data-state='down'] .ledger-figure__value { color: var(--down); }

/* The one authored moment: a rule filling while the value refreshes.
   Exponential ease-out from an already-visible default, so nothing that is
   present in the DOM ever renders invisible because of animation timing. */
.ledger-figure[data-state='live']::after {
	content: '';
	position: absolute;
	left: 0;
	bottom: 0;
	height: 2px;
	width: 100%;
	background: linear-gradient(90deg, var(--live) 0%, var(--live) 100%);
	transform-origin: 0 50%;
	animation: ledger-pulse var(--tempo) var(--ease-out) infinite;
	opacity: 0.5;
}

@keyframes ledger-pulse {
	0%   { transform: scaleX(0); opacity: 0.9; }
	55%  { transform: scaleX(1); opacity: 0.35; }
	100% { transform: scaleX(1); opacity: 0.15; }
}

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	.ledger-figure[data-state='live']::after {
		animation: none;
		transform: scaleX(1);
		opacity: 0.2;
	}
	*, *::before, *::after {
		transition-duration: 0.01ms !important;
	}
}

/* --- Main --------------------------------------------------------------- */

.ledger-main {
	flex: 1 0 auto;
	width: 100%;
	max-width: 1400px;
	margin: 0 auto;
	padding: 0 var(--pad) var(--gap-lg);
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--gap-lg);
	align-items: start;
}

.ledger-aside { display: grid; gap: var(--gap); }
.ledger-content { min-width: 0; }

/* --- Cards: lit surfaces ruled with hairlines, never rounded blobs ------- */

.card {
	background: var(--ink-800);
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	padding: var(--pad);
}
.card + .card { margin-top: var(--gap); }
.card__body > *:last-child { margin-bottom: 0; }

.card__title {
	font-family: var(--font-chrome);
	font-weight: 700;
	font-size: var(--step-2);
	margin: 0 0 0.6rem;
	padding-bottom: 0.5rem;
	border-bottom: 1px solid var(--rule);
}

.card__headline {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.25rem 1rem;
	margin-bottom: 0.75rem;
	padding-bottom: 0.5rem;
	border-bottom: 1px solid var(--rule);
}
.card__headline h1, .card__headline h2 { margin: 0; font-size: var(--step-2); }
.card__headline time { font-size: var(--step-0); color: var(--text-faint); }

/* --- Tables: bilateral columns flanking a centre, marginal counts --------- */

.ledger-table-wrap {
	overflow-x: auto;
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	-webkit-overflow-scrolling: touch;
}

/* A wide table has to scroll itself, never the document. Any table that can be
   wider than the viewport (the Experience Table's level/experience columns are
   the case) goes inside one of these; the box scrolls, the page does not. No
   border here: the wrapped table already carries its own frame. */
.ledger-scroll-x {
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	max-width: 100%;
}

.ledger-table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--step-0);
	font-variant-numeric: tabular-nums;
}
.ledger-table th,
.ledger-table td {
	padding: 0.55rem 0.7rem;
	text-align: left;
	white-space: nowrap;
	border-bottom: 1px solid var(--rule);
}
.ledger-table thead th {
	background: var(--ink-700);
	color: var(--text-secondary);
	font-family: var(--font-chrome);
	font-weight: 600;
	font-size: 0.8125rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	position: sticky;
	top: 0;
}
.ledger-table tbody tr:nth-child(even) { background: var(--ink-700); }
.ledger-table tbody tr:hover { background: var(--ink-600); }
.ledger-table tbody tr:last-child td { border-bottom: 0; }
.ledger-table td.num,
.ledger-table th.num { text-align: right; }

/* Forum board list (theme override of forum.boards.html.twig). Core sizes each
   row from its two short lines, which made "Trade" read thinner than the rest;
   every row now has the same minimum height and the description is allowed to
   wrap instead of widening the table. */
.ledger-forum-boards tbody tr { height: 4rem; }
.ledger-forum-boards td { vertical-align: middle; }
.ledger-forum-boards td:first-child { white-space: normal; }
.ledger-forum-boards td:first-child small { color: var(--text-muted); }
.ledger-forum-boards thead th span { font-size: inherit; }

/* --- Experience Table (pages/exp-table.php) ------------------------------
   Ten <details> sections of 100 levels. The disclosure is native, so the page
   works with scripting off; the search card is a plain GET form for the same
   reason, and mobbia.js only turns it into an instant, no-reload lookup.
   ------------------------------------------------------------------------ */

.exp-search__row {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	gap: 0.6rem;
}
.exp-search__row input { flex: 1 1 10rem; width: auto; margin: 0; }

.exp-search__result { margin: 0.9rem 0 0; color: var(--text-secondary); }
.exp-search__result .ledger-num { color: var(--text-primary); }
.exp-search__result--error { color: var(--down-ink); }

.exp-section {
	background: var(--ink-800);
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	margin-top: var(--gap);
}
.exp-section__title {
	display: flex;
	align-items: baseline;
	gap: 0.6rem;
	padding: 0.85rem var(--pad);
	font-family: var(--font-chrome);
	font-weight: 700;
	font-size: var(--step-1);
	cursor: pointer;
	list-style: none;
}
.exp-section__title::-webkit-details-marker { display: none; }
/* The +/- marker is drawn from the gold rule, so the open state is not carried by
   colour alone. Same gesture as the FAQ disclosure. */
.exp-section__title::before {
	content: '+';
	flex: 0 0 1rem;
	color: var(--gold-400);
	font-variant-numeric: tabular-nums;
}
.exp-section[open] > .exp-section__title::before { content: '\2212'; }

.exp-section .ledger-scroll-x { padding: 0 var(--pad) var(--pad); }

/* The looked-up row. Gold wash plus the colour change, and aria-current carries
   the same fact to assistive tech, so the mark is never colour alone. */
.exp-table__grid .is-match td {
	background: var(--gold-wash);
	color: var(--gold-400);
}

/* --- The waypoint: the site's one recurring gesture ------------------------ */

.waypoint-pin {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	font-family: var(--font-chrome);
	font-weight: 700;
	color: var(--gold-400);
}

/* --- Empty and error states --------------------------------------------- */

.ledger-empty {
	padding: var(--gap) 0;
	color: var(--text-muted);
	font-style: italic;
}

.ledger-notice {
	padding: 0.7rem 0.85rem;
	border: 1px solid var(--rule-strong);
	border-radius: var(--radius);
	background: var(--ink-700);
	font-size: var(--step-0);
}
.ledger-notice--error {
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	color: var(--down-ink);
	font-size: var(--step-1);
	/* padding is gone, so the breathing room the panel used to provide is now
	   margin: clear of the headline above, clear of the first field below. */
	margin: 0.2rem 0 1.1rem;
}
/* No fill, no rule, no padding: an error here is a line of red text in the flow of
   the form, not a panel. A tinted box read as a console readout and pulled the eye
   away from the two fields the reader actually has to act on. Only --down-ink
   reaches AA as text; --down is a 3.55:1 fill colour and fails on ink-500. */
.ledger-notice--error a {
	color: var(--down-ink);
	text-decoration-color: var(--down-ink);
	text-underline-offset: 0.18em;
}
.ledger-notice--error a:hover,
.ledger-notice--error a:focus-visible {
	text-decoration-thickness: 2px;
}
.ledger-notice--gold {
	border-color: var(--gold-edge);
	background: var(--gold-wash);
}

/* --- Forms -------------------------------------------------------------- */

.ledger-field { display: grid; gap: 0.3rem; margin-bottom: 0.9rem; }
.ledger-field label {
	font-family: var(--font-chrome);
	font-weight: 600;
	font-size: var(--step-0);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--text-secondary);
}
.ledger-field input,
.ledger-field select,
.ledger-field textarea {
	width: 100%;
	min-height: 42px;
	padding: 0.5rem 0.65rem;
	background: var(--ink-900);
	color: var(--text-primary);
	border: 1px solid var(--rule-strong);
	border-radius: var(--radius);
	font-family: var(--font-body);
	font-size: var(--step-1);
}
.ledger-field input:focus-visible,
.ledger-field select:focus-visible,
.ledger-field textarea:focus-visible {
	border-color: var(--gold-500);
	outline: 2px solid var(--gold-500);
	outline-offset: 0;
}
.ledger-field input::placeholder { color: var(--text-faint); }
.ledger-field input:disabled { opacity: 0.5; cursor: not-allowed; }

/* The one checkbox-shaped field (remember me on the login form). The base rule sizes
   every control in a .ledger-field as a full-width 42px input, which would stretch a
   checkbox across the card; here the checkbox keeps its natural size and the row
   becomes an inline pair, so the label sits next to it instead of under it. */
.ledger-field--inline {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
}
.ledger-field--inline input[type='checkbox'] {
	width: auto;
	min-height: 0;
	margin: 0;
	accent-color: var(--gold-500);
}
.ledger-field--inline label {
	text-transform: none;
	letter-spacing: 0.01em;
	font-weight: 500;
	color: var(--text-muted);
	cursor: pointer;
}

/* --- Formularios del core: tablas, no .ledger-field ---------------------- */

/* Mobbia no carga basic.css ni bootstrap-myaac.css (los estilos de Canary), asi que
   las clases de tabla que usan los formularios del core — account/create,
   account/manage, el login — no tienen ninguna regla aqui. Los <td class="LabelV">
   que llevan el texto de cada campo no heredaban color: caian al negro del UA sobre
   el fondo oscuro de la pagina, que es como los labels se veian invisibles. No era
   que faltara el texto en el HTML (esta ahi, como <span> dentro del td).

   Se dejan como tablas en vez de rehacer los formularios en .ledger-field porque los
   envian el core y los nombres de campo no se tocan; lo unico que se agrega es color
   y layout. La sombra Table* y TableShadow* se deja como esta: son divs vacios, no
   aportan nada en este tema y no estorban. */

.TableContent,
.Table5 {
	color: var(--text-primary);
	background: transparent;
	border-collapse: collapse;
	width: 100%;
}
.TableContent td,
.Table5 td {
	color: var(--text-primary);
	padding: 0.35rem 0.5rem 0.35rem 0;
	vertical-align: top;
}

/* Cajas de mensaje (note/warning/success/error).
   El core las emite por note()/warning()/error() y las estiliza con
   tools/css/messages.css, que es la hoja legacy: fondo pastel claro, 11px y
   bold. Ese archivo se carga en todas las paginas, asi que en Mobbia —fondo
   oscuro— el texto claro de adentro queda casi invisible sobre el pastel. No se
   borra la hoja porque el core la referencia desde varias plantillas; se pisa
   aca con los tokens del tema, que ya es lo que se hace con las tablas de arriba. */
.note,
.warning,
.success,
.error {
	/* El shorthand y no solo background-color a proposito: messages.css ademas
	   pone background-image (note.gif), background-repeat y background-position.
	   Si solo se pisa el color, el gif legacy sigue puesto sobre el fondo nuevo.
	   Y sin este background, el pastel claro de messages.css gana por ser la
	   unica regla que lo declara: por eso el texto claro quedaba invisible. */
	background: var(--ink-600) no-repeat;
	padding: 0.7rem 1rem;
	border: 1px solid var(--rule-strong);
	border-left-width: 3px;
	border-radius: var(--radius);
	font-family: var(--font-body);
	font-size: var(--step-0);
	font-weight: 400;
	line-height: 1.55;
	color: var(--text-primary);
	letter-spacing: normal;
	text-transform: none;
}
/* El borde de acento es lo que distingue cada tipo; el fondo se mantiene oscuro
   para que el texto no invierta el contraste. warning y error comparten el rojo a
   proposito: los dos dicen "algo va mal", y distinguirlos por tono sin que el texto
   lo diga seria adivinar. success sí lleva su propio verde porque es el unico
   caso de la lista que se puede leer de un vistazo sin leer la frase. */
.note {
	border-left-color: var(--gold-500);
}
.warning {
	border-left-color: var(--down);
}
.success {
	border-left-color: var(--live);
}
.error {
	border-left-color: var(--down);
}
/* Las tablas que van dentro de una caja de mensaje no necesitan el layout de
   formulario: las celdas se alinean arriba y la primera columna no se estrecha. */
.note .Table5 td,
.warning .Table5 td,
.success .Table5 td,
.error .Table5 td {
	padding: 0.2rem 0.75rem 0.2rem 0;
}
.note .Table5 .LabelV,
.warning .Table5 .LabelV,
.success .Table5 .LabelV,
.error .Table5 .LabelV {
	width: auto;
	white-space: nowrap;
}
/* Los parrafos de adentro no deben traer el margen del navegador: se van
   juntos contra el borde de la caja. */
.note > p:first-child,
.warning > p:first-child,
.success > p:first-child,
.error > p:first-child {
	margin-top: 0;
}
.note > p:last-child,
.warning > p:last-child,
.success > p:last-child,
.error > p:last-child {
	margin-bottom: 0;
}
/* El label del campo: misma jerarquia que .ledger-field label. El <td> trae un width
   inline de 150px desde el Twig, asi que en movil hay que dejarlo fluir. */
.LabelV {
	color: var(--text-secondary);
	font-family: var(--font-chrome);
	font-weight: 600;
	font-size: var(--step-0);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	white-space: normal;
}
/* Los <span> dentro de .LabelV heredan, pero el .red de los errores tiene que
   ganarle al uppercase del td. */
.LabelV .red,
.LabelV span.red {
	color: var(--down-ink);
	text-transform: none;
	letter-spacing: 0.01em;
	font-weight: 600;
}
/* El .red puede caer sobre la propia celda (<td class="red">), y ahi la regla de
   celda de arriba —.TableContent td, .Table5 td— le gana por especificidad
   (0,1,1 contra 0,1,0) y lo deja en text-primary: el texto de error se ve igual
   que el normal y la senal se pierde. Por eso el .red de celda se declara aparte,
   con selectores que empatan o ganan contra esa regla. */
.TableContent td.red,
.Table5 td.red,
td.red {
	color: var(--down-ink);
	text-transform: none;
	letter-spacing: 0.01em;
	font-weight: 600;
}
/* Controles de estos formularios: el core los emite con size="30" y sin clase, asi
   que sin esto quedan con el aspecto por defecto del navegador. */
.TableContent input[type='text'],
.TableContent input[type='password'],
.TableContent input[type='email'],
.TableContent select,
.TableContent textarea,
.Table5 input[type='text'],
.Table5 input[type='password'],
.Table5 input[type='email'],
.Table5 select,
.Table5 textarea {
	min-height: 40px;
	padding: 0.45rem 0.6rem;
	background: var(--ink-900);
	color: var(--text-primary);
	border: 1px solid var(--rule-strong);
	border-radius: var(--radius);
	font-family: var(--font-body);
	font-size: var(--step-1);
}
.TableContent input:focus-visible,
.TableContent select:focus-visible,
.TableContent textarea:focus-visible,
.Table5 input:focus-visible,
.Table5 select:focus-visible,
.Table5 textarea:focus-visible {
	border-color: var(--gold-500);
	outline: 2px solid var(--gold-500);
	outline-offset: 0;
}
.TableContent input[type='checkbox'],
.TableContent input[type='radio'],
.Table5 input[type='checkbox'],
.Table5 input[type='radio'] {
	accent-color: var(--gold-500);
	min-height: 0;
	width: auto;
}
/* Inputs sin atributo type. El core emite el campo de nombre de personaje asi
   (`<input id="character_name" name="name" size="..."/>`), y sin type el
   selector [type='text'] no lo matchea: se quedaba con el aspecto nativo del
   navegador (gris claro) al lado de los otros, que siTOMABAN estilo. Se apunta
   por id, que es estable, en vez de usar un selector de atributo que excluye a
   los que no declaran type. */
.TableContent input#character_name,
.TableContent input#account_input {
	width: 100%;
	max-width: 22rem;
	min-height: 40px;
	padding: 0.45rem 0.6rem;
	background: var(--ink-900);
	color: var(--text-primary);
	border: 1px solid var(--rule-strong);
	border-radius: var(--radius);
	font-family: var(--font-body);
	font-size: var(--step-1);
}
.TableContent input#character_name:focus-visible,
.TableContent input#account_input:focus-visible {
	border-color: var(--gold-500);
	outline: 2px solid var(--gold-500);
	outline-offset: 0;
}
/* El <img id="account_country_img"> lo emite el Twig con src="" y lo puebla el JS
   del core (account.create.js.html.twig, updateFlag) segun el <select>. Ese JS si
   corre, asi que la bandera aparece de verdad y hay que maquetarla: sin nada cae
   en la fila de abajo del select (el <img> es un inline que no participa de la
   linea del select) y se ve descolgada. Se la pone al lado con flex en la celda,
   y se oculta solo mientras no tenga src (antes de que corra el JS), que es cuando
   el navegador la dibujaria como una imagen rota. */
.TableContent img#account_country_img:not([src]),
.TableContent img#account_country_img[src=''] {
	display: none;
}
.TableContent img#account_country_img[src]:not([src='']) {
	display: inline-block;
	vertical-align: middle;
	margin-left: 0.5rem;
	height: 1.1rem;
	width: auto;
}
/* La celda del select y la bandera van en linea; el select toma el ancho y la
   bandera se queda al costado en vez de romper a la fila siguiente. */
.TableContent td:has(> select#account_country) {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}
.TableContent td:has(> select#account_country) > select#account_country {
	flex: 1 1 auto;
	min-width: 0;
}
/* La fila de genero / vocation / town mete una tabla dentro de la celda para
   alinear los radios en linea. Sin esto cada opcion cae a su propia linea. */
.TableContent td table td {
	padding: 0.15rem 0.9rem 0.15rem 0;
	border: 0;
}
.FormFieldError {
	color: var(--down-ink);
	font-size: var(--step-0);
	display: block;
}

@media (max-width: 40rem) {
	/* El width:150px inline del Twig sobre .LabelV aprieta los campos en movil:
	   el label y el input se turnan en columna. */
	.TableContent td.LabelV {
		width: auto !important;
		padding-bottom: 0.15rem;
	}
	.TableContent input[type='text'],
	.TableContent input[type='password'],
	.TableContent select {
		width: 100%;
	}
}

/* --- Helper ------------------------------------------------------------- */

.ledger-helper {
	position: absolute;
	z-index: 90;
	max-width: 280px;
	padding: 0.7rem 0.85rem;
	background: var(--ink-600);
	border: 1px solid var(--gold-edge);
	border-radius: var(--radius);
	font-size: var(--step-0);
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}
.ledger-helper[hidden] { display: none; }
.ledger-helper__headline { display: block; margin-bottom: 0.3rem; font-family: var(--font-chrome); }
.ledger-helper__arrow { display: none; }

/* --- Footer ------------------------------------------------------------- */

.ledger-footer {
	flex: 0 0 auto;
	margin-top: var(--gap-lg);
	background: var(--ink-800);
	border-top: 1px solid var(--rule);
}
.ledger-footer__inner {
	max-width: 1400px;
	margin: 0 auto;
	padding: var(--gap) var(--pad);
	display: grid;
	gap: 0.6rem;
}
.ledger-footer__server { margin: 0; color: var(--text-secondary); font-size: var(--step-0); }
/* flex-wrap: nowrap, and the size comes off the padding rather than the box.

   With wrap, eight 36px links plus the gaps measured 344px against 343px of
   column at 375px and wrapped outright at 360 and 320 - the envelope was the one
   that dropped, so a visitor looking for the contact address found it on a line of
   its own. Shrinking the hit area to 30px and the gap to 0.25rem puts the row at
   8x30 + 7x4 = 268px, which fits a 320px viewport with room to spare.

   30px is still above the 24px minimum target size, so the tap area does not get
   traded away to fix the wrap. */
.ledger-footer__social {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	gap: 0.15rem 0.25rem;
}
.ledger-footer__social a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.875rem;
	height: 1.875rem;
	color: var(--text-secondary);
	border-radius: 50%;
	text-decoration: none;
	transition: color 0.12s var(--ease-out), background-color 0.12s var(--ease-out);
}
.ledger-footer__social a:hover,
.ledger-footer__social a:focus-visible {
	color: var(--gold-400);
	background: var(--gold-wash);
}
.ledger-social-icon {
	fill: currentColor;
	flex: 0 0 auto;
}
/* Los enlaces legales (FAQ · Server rules · Log in) se separan con flex y gap en
   vez de dejar que los &middot; queden pegados al texto: el navegador solo les da
   el espacio de un caracter, que en escritorio los leia como un bloque. Los
   &middot; siguen en el HTML y pasan a ser items anonimos del flex, asi que el
   gap los centra entre cada par de enlaces. */
.ledger-footer__legal {
	margin: 0;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem 1rem;
	font-size: var(--step-0);
	color: var(--text-muted);
}

/* ==========================================================================
   Content components.

   These are the page-level pieces the Twig overrides and the boxes are built from.
   Same rules as the shell: ruled rather than boxed, gold only where something is
   being asserted, and no fixed widths anywhere - a guild list, a calendar and a
   meter lay out identically at 320px.
   ========================================================================== */

/* --- Section headings ----------------------------------------------------- */

.card__body > *:first-child,
.ledger-article__body > *:first-child { margin-top: 0; }

.ledger-subhead {
	margin: 0 0 0.75rem;
	font-family: var(--font-chrome);
	font-size: var(--step-1);
	font-weight: 600;
	letter-spacing: 0.01em;
	text-transform: uppercase;
	color: var(--text-secondary);
}

.ledger-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 1rem 0;
	padding: 0;
	list-style: none;
}
.ledger-actions .ledger-btn { flex: 0 0 auto; }

/* --- Articles (news, changelog entries) ----------------------------------- */

.ledger-article {
	padding: 0 0 var(--gap-lg);
	margin: 0 0 var(--gap-lg);
	border-bottom: 1px solid var(--rule);
}
.ledger-article:last-of-type { border-bottom: 0; margin-bottom: 0; }

.ledger-article__head { margin-bottom: 0.6rem; }

.ledger-article__title {
	margin: 0;
	font-family: var(--font-chrome);
	font-size: var(--step-2);
	font-weight: 600;
	line-height: 1.2;
}
.ledger-article__title a { color: inherit; }
.ledger-article__title a:hover { color: var(--gold-400); }

.ledger-article__byline {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem 1rem;
	margin: 0.35rem 0 0;
	font-size: var(--step-0);
	color: var(--text-muted);
}
.ledger-article__date { font-variant-numeric: tabular-nums; }

.ledger-article__body {
	max-width: var(--measure);
	color: var(--text-secondary);
	line-height: 1.6;
}
.ledger-article__body p { margin: 0 0 1rem; }
.ledger-article__body img { max-width: 100%; height: auto; border-radius: var(--radius); }
.ledger-article__body h2,
.ledger-article__body h3 { color: var(--text-primary); line-height: 1.25; }

.news-body { max-width: var(--measure); line-height: 1.6; }
.news-body img { max-width: 100%; height: auto; }

/* A rule under each paragraph of body copy: the ledger's defining gesture. */
.news-body > p + p,
.ledger-article__body > p + p {
	padding-top: 1rem;
	border-top: 1px solid var(--rule);
}

.ledger-article__foot {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 1rem;
	margin-top: 0.75rem;
	font-size: var(--step-0);
	color: var(--text-muted);
}

/* --- Definition rows (server info, rules) --------------------------------- */

.ledger-defs { margin: 0; }
.ledger-defs__row {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 0.25rem 1rem;
	padding: 0.6rem 0;
	border-bottom: 1px solid var(--rule);
}
.ledger-defs__row:last-child { border-bottom: 0; }
.ledger-defs__row dt { color: var(--text-muted); }
.ledger-defs__row dd {
	margin: 0;
	color: var(--text-primary);
	font-variant-numeric: tabular-nums;
}
.ledger-defs__country {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
}
.ledger-defs__country img { vertical-align: middle; }

/* --- Ruled lists (last kills, guilds, ranks) ------------------------------ */

.ledger-list,
.ledger-rank,
.ledger-guilds,
.ledger-history,
.ledger-ticks,
.ledger-slots,
.ledger-characters { list-style: none; margin: 0; padding: 0; }

.ledger-list__row,
.ledger-rank__row,
.ledger-guilds__row,
.ledger-history > li,
.ledger-ticks__item,
.ledger-characters__row {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	padding: 0.55rem 0;
	border-bottom: 1px solid var(--rule);
}
.ledger-list__row:last-child,
.ledger-rank__row:last-child,
.ledger-guilds__row:last-child,
.ledger-history > li:last-child,
.ledger-ticks__item:last-child,
.ledger-characters__row:last-child { border-bottom: 0; }

/* Rank: position, outfit, name, value. The value is pushed right and made tabular
   so digits stay in column even as the numbers change length between polls. */
.ledger-rank__pos {
	flex: 0 0 1.75rem;
	color: var(--text-faint);
	font-family: var(--font-chrome);
}
.ledger-rank__row:first-child .ledger-rank__pos { color: var(--gold-500); }
.ledger-rank__outfit {
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
	image-rendering: pixelated;
}
.ledger-rank__name { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.ledger-rank__value { margin-left: auto; color: var(--gold-400); }

.ledger-list__title { flex: 1 1 auto; min-width: 0; }
.ledger-list__meta { flex: 0 0 auto; color: var(--text-muted); font-size: var(--step-0); }
.ledger-list__marker {
	flex: 0 0 auto;
	width: 0.4rem;
	height: 0.9rem;
	background: var(--gold-500);
}

/* --- FAQ (native disclosure) -----------------------------------------------
   Each entry is a <details>; the summary is the question and is the control, so
   the answer only enters the accessibility tree when it is open. The +/- marker
   is drawn from the gold rule so the open state is not carried by colour alone.
   ------------------------------------------------------------------------ */

.ledger-faq { list-style: none; margin: 0; padding: 0; }
.ledger-faq__item { border-bottom: 1px solid var(--rule); }
.ledger-faq__item:last-child { border-bottom: 0; }

.ledger-faq__q {
	display: flex;
	align-items: baseline;
	gap: 0.6rem;
	padding: 0.8rem 0;
	font-family: var(--font-chrome);
	font-weight: 600;
	color: var(--text-primary);
	cursor: pointer;
	list-style: none;
}
.ledger-faq__q::-webkit-details-marker { display: none; }
.ledger-faq__q::before {
	content: '+';
	flex: 0 0 1rem;
	color: var(--gold-400);
	font-variant-numeric: tabular-nums;
}
.ledger-faq__entry[open] > .ledger-faq__q::before { content: '\2212'; }

.ledger-faq__a {
	max-width: var(--measure);
	padding: 0 0 0.9rem 1.6rem;
	color: var(--text-secondary);
	line-height: 1.6;
}
.ledger-faq__a p:first-child { margin-top: 0; }

.ledger-faq__admin {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	padding: 0 0 0.9rem 1.6rem;
}

/* --- Presence ------------------------------------------------------------
   The one dot that means "online", reusing --live so it cannot drift out of step
   with the status band.
   ------------------------------------------------------------------------ */

.ledger-presence {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	font-size: var(--step-0);
	color: var(--text-muted);
}
.ledger-presence__dot {
	flex: 0 0 auto;
	width: 0.5rem;
	height: 0.5rem;
	border-radius: 50%;
	background: var(--text-faint);
}
.ledger-presence[data-online='1'] { color: var(--live); }
.ledger-presence[data-online='1'] .ledger-presence__dot {
	background: var(--live);
	box-shadow: 0 0 0 3px var(--live-wash);
}

/* --- Meters (character vitals) -------------------------------------------- */

.meter { display: grid; gap: 0.3rem; margin-bottom: 0.85rem; }
.meter__head {
	display: flex;
	justify-content: space-between;
	gap: 1rem;
	font-size: var(--step-0);
}
.meter__label { color: var(--text-muted); }
.meter__value { color: var(--text-secondary); }
.meter__track {
	height: 0.4rem;
	background: var(--ink-600);
	border-radius: 999px;
	overflow: hidden;
}
.meter__fill {
	height: 100%;
	background: var(--gold-500);
	border-radius: inherit;
}
.meter__pct { font-size: var(--step-0); color: var(--text-muted); } /* --text-faint is the disabled token (4.12:1); this is live text */
.meter[data-state='warn'] .meter__fill { background: var(--gold-400); }
.meter[data-state='bad'] .meter__fill { background: var(--down); }

/* --- Character profile ---------------------------------------------------- */

.ledger-character { display: grid; gap: var(--gap); }

.ledger-character__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75rem;
}
.ledger-character__outfit {
	flex: 0 0 auto;
	width: 64px;
	height: 64px;
	padding: 0.25rem;
	background: var(--ink-700);
	border: 1px solid var(--rule-strong);
	border-radius: var(--radius);
}
.ledger-character__outfit img {
	display: block;
	width: 100%;
	height: 100%;
	image-rendering: pixelated;
}

.ledger-character__ident { flex: 1 1 12rem; min-width: 0; }
.ledger-character__name {
	margin: 0;
	font-family: var(--font-chrome);
	font-size: var(--step-3);
	font-weight: 600;
	line-height: 1.1;
	overflow-wrap: anywhere;
}
.ledger-character__line {
	margin: 0.15rem 0 0;
	color: var(--text-muted);
	font-size: var(--step-0);
}
.ledger-character__admin { margin: 0.2rem 0 0; }
.ledger-character__comment {
	margin: 0.15rem 0 0;
	color: var(--text-muted);
	font-size: var(--step-0);
	font-style: italic;
}
/* No .ledger-character__signature rule: the signature PNG is not rendered any more
   (see characters.html.twig). Kept as a note so it does not get added back. */

/* The former name, which only exists for a character that has been renamed. It sits
   inside the <h1> with the character name, so it has to read as a quiet aside and
   not compete with the name: own line on a narrow screen, same line when it fits. */
.ledger-character__former {
	display: block;
	color: var(--text-faint);
	font-family: var(--font-body);
	font-size: var(--step-0);
	font-weight: 400;
	letter-spacing: 0;
}
@media (min-width: 480px) {
	.ledger-character__former { display: inline; margin-left: 0.5rem; }
}

/* Achievement badges. Name on the left, grade on the right, on a ruled cell like the
   rest of the profile's lists. The grade is the rarer half, so it gets the gold; the
   name stays in ordinary text because there can be a dozen of them. */
.ledger-achievements {
	list-style: none;
	margin: 0;
	padding: 0;
}
.ledger-achievements__item {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.75rem;
	padding: 0.55rem 0;
	border-bottom: 1px solid var(--rule);
}
.ledger-achievements__item:last-child { border-bottom: 0; }
.ledger-achievements__name { color: var(--text-secondary); }
.ledger-achievements__grade {
	flex: none;
	color: var(--gold-400);
	font-family: var(--font-chrome);
	font-weight: 600;
	font-size: var(--step-0);
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

/* Back to the search form, above the identity rather than buried under it. */
.ledger-character__back {
	justify-self: start;
	font-size: var(--step-0);
	color: var(--text-muted);
}
.ledger-character__back:hover { color: var(--gold-400); }

.ledger-characters__head {
	display: flex;
	justify-content: space-between;
	gap: 1rem;
	padding-bottom: 0.5rem;
	border-bottom: 1px solid var(--rule-strong);
	font-family: var(--font-chrome);
	font-size: var(--step-0);
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--text-muted);
}
.ledger-characters__row { flex-wrap: wrap; }
.ledger-characters__name {
	flex: 1 1 10rem;
	min-width: 0;
	overflow-wrap: anywhere;
}
.ledger-characters__facts {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
	gap: 0.55rem 1rem;
	flex: 1 1 100%;
	width: 100%;
	color: var(--text-muted);
	font-size: var(--step-0);
}
.ledger-characters__facts > div { min-width: 0; }
.ledger-characters__facts dt {
	font-family: var(--font-chrome);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--text-faint);
}
/* The browser's default dd margin-inline-start: 40px was what pushed 7 and
   Sorcerer to the right of their labels. */
.ledger-characters__facts dd {
	margin: 0;
	color: var(--text-primary);
	font-variant-numeric: tabular-nums;
	overflow-wrap: anywhere;
}

.ledger-vitals { margin: 0; }
.ledger-outfit { image-rendering: pixelated; }
.ledger-cell--name { color: var(--text-primary); font-weight: 500; }

/* --- Guilds --------------------------------------------------------------- */

.ledger-guilds__row { flex-wrap: wrap; }
.ledger-guilds__logo {
	flex: 0 0 auto;
	width: 2.25rem;
	height: 2.25rem;
	object-fit: cover;
	background: var(--ink-700);
	border: 1px solid var(--rule-strong);
	border-radius: var(--radius);
}
.ledger-guilds__body { flex: 1 1 12rem; min-width: 0; }
.ledger-guilds__description {
	margin: 0.15rem 0 0;
	color: var(--text-muted);
	font-size: var(--step-0);
}
.ledger-guilds__admin { flex: 0 0 auto; }
.ledger-guilds__action { flex: 0 0 auto; margin-left: auto; }

/* --- Account -------------------------------------------------------------- */

.ledger-account { display: grid; gap: var(--gap); }
.ledger-account__welcome { margin: 0 0 var(--gap); color: var(--text-secondary); }
.ledger-account__nav {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem 1.25rem;
	margin: 0 0 var(--gap);
	padding: 0 0 0.6rem;
	border-bottom: 1px solid var(--rule);
}
.ledger-account__nav a[aria-current='page'] { color: var(--gold-400); }

.ledger-auth { max-width: 26rem; }

.ledger-auth__social {
	max-width: 26rem;
	margin-top: 1rem;
	padding-top: 1rem;
	border-top: 1px solid var(--rule);
}
.ledger-auth__social--create {
	margin: 0 0 1rem;
	padding: 1rem;
	background: var(--ink-800);
	border: 1px solid var(--rule);
	border-radius: var(--radius);
}
.ledger-auth__alt-label {
	margin: 0 0 0.6rem;
	color: var(--text-muted);
	font-size: var(--step-0);
}
.ledger-social { display: grid; gap: 0.5rem; }
.ledger-social .ledger-btn {
	width: 100%;
	text-transform: none;
	letter-spacing: 0;
}
.ledger-hint {
	margin: 0.75rem 0 0;
	color: var(--text-muted);
	font-size: 0.8125rem;
	line-height: 1.5;
}
.ledger-linked__row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.6rem 1rem;
	padding: 0.75rem 0;
	border-top: 1px solid var(--rule);
}
.ledger-linked__row:first-of-type { border-top: 0; }
.ledger-linked__row form { margin: 0; }
.ledger-linked__status {
	display: block;
	margin-top: 0.15rem;
	color: var(--text-muted);
	font-size: 0.8125rem;
}
.ledger-linked__state {
	color: var(--text-secondary);
	font-size: 0.8125rem;
}

.ledger-confirm {
	padding: 0.75rem;
	background: var(--ink-700);
	border: 1px solid var(--rule-strong);
	border-radius: var(--radius);
	color: var(--text-secondary);
}

/* --- Filters and pager ---------------------------------------------------- */

.ledger-filters {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	margin-bottom: var(--gap);
}
.ledger-filters label { color: var(--text-muted); font-size: var(--step-0); }

/* Un campo que se estira a todo el ancho libre de la fila.
   El buscador de la wiki usaba .ledger-search, que es un grid de una sola
   columna: el input se encogia al ancho de su contenido y quedaba mas pequeno
   que el de las demas secciones. Con flex-basis en.rem se lleva el hueco que
   sobra en vez de medir el texto que lleva dentro.
   El margin-bottom de .ledger-field se anula porque dentro de un flex con
   align-items:center el padding vertical descentraria la fila. */
.ledger-field--wide {
	flex: 1 1 22rem;
	margin-bottom: 0;
}

/* Buscador centrado.
   .ledger-field--wide se estira a todo el hueco libre, asi que en una tarjeta que no
   tiene mas contenido al lado el campo queda pegado a la izquierda y el boton al
   final de la linea, separado del campo. Aqui el campo toma un ancho fijo de lectura
   comoda y el grupo entero (campo + boton) se centra en la tarjeta.
   El margen inferior se recupera en el contenedor, porque .ledger-field lo anula para
   que el campo no descentre la fila de flex. */
.ledger-filters--center {
	justify-content: center;
}

.ledger-filters--center .ledger-field--wide {
	flex: 0 1 28rem;
}

/* El margen queia en 0.9rem y alineaba el boton con el input en vertical, porque el
   campo lleva etiqueta encima y el boton no. Medido en escritorio, el boton quedaba
   por debajo de la linea del input: -2rem lo sube a la altura justa. Es un margen
   negativo a proposito y no un padding, que no puede ser negativo en CSS.
   En el breakpoint de movil se anula, porque alli el grupo va apilado y un margen
   negativo descuadraria el boton respecto al campo. */
.ledger-filters--center .ledger-btn {
	margin-bottom: -2rem;
	align-self: center;
}

@media (max-width: 560px) {
	/* En movil el grupo se apila y el campo ocupa el ancho entero; centrado en
	   horizontal se translate en "pegado a la izquierda", que es lo unico sensato. */
	.ledger-filters--center {
		flex-direction: column;
		align-items: stretch;
	}

	.ledger-filters--center .ledger-field--wide {
		flex: 1 1 auto;
	}

	.ledger-filters--center .ledger-btn {
		margin-bottom: 0;
		align-self: center;
	}
}

.ledger-pager {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	margin-top: var(--gap);
	padding-top: 0.75rem;
	border-top: 1px solid var(--rule);
}
.ledger-pager a,
.ledger-pager span {
	padding: 0.25rem 0.55rem;
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	color: var(--text-secondary);
}
.ledger-pager [aria-current='page'] {
	background: var(--gold-wash);
	border-color: var(--gold-edge);
	color: var(--gold-400);
}
.ledger-pager__pages {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	list-style: none;
	margin: 0;
	padding: 0;
}
.ledger-pager__gap {
	color: var(--text-faint);
	line-height: 1;
}

/* --- Boxes: server save and character search ------------------------------ */

.ledger-save__label {
	margin: 0 0 0.35rem;
	color: var(--text-muted);
	font-size: var(--step-0);
}
.ledger-save__count {
	margin: 0;
	font-size: var(--step-4);
	font-weight: 500;
	color: var(--gold-400);
}
.ledger-save__count[data-passed='true'] { color: var(--text-muted); }

.ledger-search { display: grid; gap: 0.6rem; }
.ledger-search input[type='submit'] { justify-self: start; }

/* --- Wiki (pages/wiki/*) ------------------------------------------------
   La ficha imprime claves literales del datapack (imbuementslot > increase
   speed), y dentro de un <dt> que ya esta en --text-muted un monoespaciado
   sin configurar seria indistinguible del resto. Se define aqui y no antes
   porque no hay otro <code> en el tema: hacerlo global seria preventive sin
   un segundo consumidor. */

.ledger-defs__row code,
.ledger-character__comment code {
	font-family: ui-monospace, 'SF Mono', 'Cascadia Mono', Menlo, Consolas, monospace;
	font-size: 0.9em;
	color: var(--text-secondary);
}

/* La descripcion de un item va bajo su nombre en la tabla del indice: dos lineas
   como mucho, porque items.xml las trae largas y 3722 de 37527 las tienen. */
.ledger-wiki-desc {
	margin: 0.2rem 0 0;
	font-size: var(--step-0);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* --- Monsters (pages/monsters.php) ----------------------------------------
   One responsive grid of sprite cards. Each card is the creature's link, so the
   whole target is the sprite plus its name; [hidden] is restored because the
   generic display rule would otherwise beat the UA's [hidden] rule. */

.ledger-monsters {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
	gap: var(--gap);
}
.ledger-monsters__item[hidden] { display: none; }
.ledger-monsters__link {
	display: grid;
	gap: 0.3rem;
	padding: 0.7rem;
	height: 100%;
	background: var(--ink-700);
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	color: var(--text-primary);
	text-decoration: none;
	transition: border-color 0.12s var(--ease-out), background-color 0.12s var(--ease-out);
}
.ledger-monsters__link:hover,
.ledger-monsters__link:focus-visible {
	border-color: var(--gold-edge);
	background: var(--ink-600);
}
.ledger-monsters__art {
	display: grid;
	place-items: center;
	height: 80px;
	background: var(--ink-800);
	border-radius: var(--radius);
}
.ledger-monsters__art img {
	width: 64px;
	height: 64px;
	object-fit: contain;
	image-rendering: pixelated;
}
.ledger-monsters__name {
	font-family: var(--font-chrome);
	font-weight: 600;
	font-size: var(--step-0);
	line-height: 1.2;
}
.ledger-monsters__meta {
	color: var(--text-muted);
	font-size: 0.8125rem;
	font-variant-numeric: tabular-nums;
}

/* --- Monster page (monster.html.twig) -------------------------------------
   The creature's sprite and its stat block share the hero. The sprite sits in the
   same lit surface the index uses, so a creature reads the same in both places.
   Loot rows are the index card in miniature: sprite, then the item as its own
   link text. */

.monster-hero { display: grid; gap: var(--gap); }
.monster-hero__art {
	display: grid;
	place-items: center;
	padding: 1.25rem;
	background: var(--ink-800);
	border: 1px solid var(--rule);
	border-radius: var(--radius);
}
.monster-hero__art img {
	width: 96px;
	height: 96px;
	object-fit: contain;
	image-rendering: pixelated;
}
.monster-hero__defs { min-width: 0; }

.monster-voices {
	list-style: none;
	margin: 0 0 var(--gap);
	padding: 0;
}
.monster-voices > li {
	padding: 0.5rem 0;
	border-bottom: 1px solid var(--rule);
	color: var(--text-secondary);
}
.monster-voices > li:last-child { border-bottom: 0; margin-bottom: 0; }

.ledger-loot {
	display: flex;
	align-items: center;
	gap: 0.6rem;
}
.ledger-loot img {
	flex: 0 0 auto;
	width: 48px;
	height: 48px;
	object-fit: contain;
	image-rendering: pixelated;
}

/* El sprite del drop enlaza a su ficha de la wiki. El enlace lleva tabindex="-1" y
   aria-hidden en la plantilla porque el nombre del objeto, a su lado, ya es el enlace
   y da el mismo destino: dos enlaces identicos seguidos en la tabla son ruido para
   quien navega con teclado o lector de pantalla. El clic en el sprite sigue siendo
   util con el raton. */
.ledger-loot__sprite {
	display: inline-flex;
	flex: 0 0 auto;
	line-height: 0;
}

/* --- Tickers (news strip) ------------------------------------------------- */

.ledger-ticker { display: grid; gap: 0.35rem; }
.ledger-ticker__label {
	font-family: var(--font-chrome);
	font-size: var(--step-0);
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--text-muted);
}
.ledger-ticker__track {
	display: flex;
	gap: 0.4rem;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	padding-bottom: 0.25rem;
}
.ledger-ticker__track > * { flex: 0 0 auto; scroll-snap-align: start; }
.ledger-ticker__track a {
	display: block;
	padding: 0.3rem 0.6rem;
	background: var(--ink-700);
	border: 1px solid var(--rule);
	border-radius: 999px;
	color: var(--text-secondary);
	font-size: var(--step-0);
	white-space: nowrap;
}
.ledger-ticker__track a:hover { border-color: var(--gold-edge); color: var(--gold-400); }

/* --- Slots (online page capacity) ----------------------------------------- */

.ledger-slots { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.ledger-slots__slot {
	width: 0.6rem;
	height: 0.6rem;
	border-radius: 2px;
	background: var(--ink-500);
}
.ledger-slots__slot[data-used='1'] { background: var(--gold-500); }

/* --- Calendar and events (pages/event-schedule.php) -----------------------
   The month reads as a wall calendar: every day is its own ruled box, and the
   events live inside the box as coloured strips rather than as dots. A three
   column header puts the pager at the edges and the month in the centre.
   ------------------------------------------------------------------------ */

.ledger-calendar__head {
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	gap: 0.75rem;
	margin-bottom: 0.9rem;
}
.ledger-calendar__month {
	margin: 0;
	text-align: center;
	font-family: var(--font-chrome);
	font-size: var(--step-2);
	font-weight: 600;
	color: var(--text-primary);
}
/* Gold pager. 2.5rem keeps the target above the 24px minimum on touch. */
.ledger-calendar__navbtn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.5rem;
	height: 2.5rem;
	border: 1px solid var(--gold-edge);
	border-radius: var(--radius);
	background: var(--gold-wash);
	color: var(--gold-400);
	font-size: 1.5rem;
	line-height: 1;
	text-decoration: none;
	transition: color 0.12s var(--ease-out), background-color 0.12s var(--ease-out);
}
.ledger-calendar__navbtn:hover,
.ledger-calendar__navbtn:focus-visible {
	border-color: var(--gold-500);
	background: var(--gold-500);
	color: var(--ink-900);
}
/* The month swap is a same-page fetch; dim and block the card until the new
   grid arrives so a second click cannot race the first request. */
#event-calendar.is-loading {
	opacity: 0.55;
	pointer-events: none;
	transition: opacity 0.12s var(--ease-out);
}

/* border-collapse: separate plus border-spacing is what turns the grid into
   boxes with a gutter between them; with collapse the shared edges read as a
   spreadsheet, not a calendar. */
.ledger-calendar {
	width: 100%;
	border-collapse: separate;
	border-spacing: 4px;
	table-layout: fixed;
}
.ledger-calendar th {
	padding: 0.3rem 0.1rem;
	font-family: var(--font-chrome);
	font-size: var(--step-0);
	font-weight: 500;
	text-transform: uppercase;
	color: var(--text-faint);
}
.ledger-calendar td {
	padding: 0.3rem;
	height: 4.4rem;
	vertical-align: top;
	text-align: left;
	white-space: normal;
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	background: var(--ink-800);
}
/* Padding cells: the gap, not a box, so the month reads as starting on the
   right weekday instead of as a grid with holes. */
.ledger-calendar__cell--pad {
	border-color: transparent;
	background: transparent;
}
.ledger-calendar__cell--today {
	border-color: var(--gold-edge);
	box-shadow: inset 0 0 0 1px var(--gold-edge);
}
.ledger-calendar__day {
	display: block;
	padding: 0 0.1rem 0.25rem;
	line-height: 1.1;
	font-variant-numeric: tabular-nums;
	font-weight: 600;
	color: var(--text-secondary);
}
.ledger-calendar__cell--event .ledger-calendar__day { color: var(--text-primary); }
.ledger-calendar__cell--today .ledger-calendar__day { color: var(--gold-400); }

/* One coloured strip per event, in the event's own colour. The name truncates
   rather than widening the column; the full name is in title and in the list
   below the grid. */
.ledger-calendar__event {
	display: block;
	margin-top: 0.15rem;
	padding: 0.15rem 0.35rem;
	border-radius: 2px;
	background: var(--event-color, var(--gold-500));
	color: #fff;
	font-size: 0.72rem;
	font-weight: 600;
	line-height: 1.25;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
/* Below ~600px seven columns leave too little room for a label to be read, so
   the strips keep their colour and lose their text. The full names and
   descriptions are in the list directly underneath. */
@media (max-width: 600px) {
	.ledger-calendar { border-spacing: 2px; }
	.ledger-calendar th { font-size: 0.7rem; }
	.ledger-calendar td { height: 3.2rem; padding: 0.18rem; }
	.ledger-calendar__event {
		height: 0.28rem;
		margin-top: 0.15rem;
		padding: 0;
		border-radius: 1px;
		font-size: 0;
	}
}

/* Character Bazaar section tabs. Seeded CMS body, so this lives with the theme
   rather than inline: one row per section, alternating ink to separate them,
   and a gold edge for the current one (aria-current is set in the body). */
.ledger-bazaar-nav {
	margin: 0 0 1.1rem;
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	overflow: hidden;
}
.ledger-bazaar-nav ul { list-style: none; margin: 0; padding: 0; }
.ledger-bazaar-nav li:nth-child(odd) { background: var(--ink-800); }
.ledger-bazaar-nav li:nth-child(even) { background: var(--ink-700); }
.ledger-bazaar-nav li + li { border-top: 1px solid var(--rule); }
.ledger-bazaar-nav a {
	display: block;
	padding: 0.6rem 0.85rem;
	color: var(--text-secondary);
	text-decoration: none;
}
.ledger-bazaar-nav a:hover { background: var(--ink-600); color: var(--text-primary); }
.ledger-bazaar-nav a[aria-current='page'] {
	box-shadow: inset 3px 0 0 var(--gold-500);
	color: var(--gold-400);
	font-weight: 600;
}

/* Event footer: the coloured band carries the title and range, the description
   sits underneath it. */
.ledger-events {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.65rem;
}
.ledger-events__item {
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	overflow: hidden;
	background: var(--ink-800);
}
.ledger-events__band {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.25rem 0.75rem;
	padding: 0.55rem 0.8rem;
	background: var(--event-color, var(--gold-500));
	color: #fff;
}
.ledger-events__band h3 {
	margin: 0;
	font-size: var(--step-1);
	font-weight: 600;
	color: #fff;
}
.ledger-events__when {
	margin: 0;
	color: rgba(255, 255, 255, 0.82);
	font-size: var(--step-0);
	font-variant-numeric: tabular-nums;
}
.ledger-events__desc {
	margin: 0;
	padding: 0.7rem 0.8rem;
	color: var(--text-secondary);
}

.ledger-helper__text { color: var(--text-secondary); }

/* Classes that arrive with core or plugin markup this theme does not own. One
   declaration each, so they read as a decision rather than as leftovers. */
.LabelH {
	font-family: var(--font-chrome);
	font-weight: 600;
	color: var(--text-primary);
}
.white { color: var(--text-primary); }

/* --- Helpers ------------------------------------------------------------ */

.ledger-u-hide { display: none !important; }
.ledger-muted { color: var(--text-muted); }
.ledger-num { font-variant-numeric: tabular-nums; }

/* ==========================================================================
   Width is added upward. Nothing below 768px inherits a fixed column.
   ========================================================================== */

@media (min-width: 480px) {
	:root { --pad: 1.25rem; }

	.ledger-figures { grid-template-columns: repeat(3, 1fr); }
	.ledger-figure {
		border-bottom: 0;
		border-right: 1px solid var(--rule);
	}

	.monster-hero { grid-template-columns: auto 1fr; align-items: start; }
	.ledger-figure:last-child { border-right: 0; }

	.ledger-footer__inner {
		grid-template-columns: 1fr auto;
		align-items: center;
	}
	.ledger-footer__social { grid-column: 2; grid-row: 1; }
	.ledger-footer__legal { grid-column: 1 / -1; }
}

@media (min-width: 768px) {
	:root {
		--pad: 1.5rem;
		--gap: 1.25rem;
		--gap-lg: 2.5rem;
	}

	/* Nav leaves the disclosure and becomes a horizontal category bar */
	.ledger-nav {
		display: block;
		flex-basis: auto;
		order: 0;
		padding-bottom: 0;
		margin-left: var(--gap);
	}
	.ledger-nav__toggle { display: none; }
	.ledger-nav__categories { display: flex; gap: 0.25rem; }
	.ledger-nav__category {
		border: 0;
		position: relative;
	}
	.ledger-nav__heading { padding: 0.3rem 0.5rem; }
	.ledger-nav__heading[aria-current='page']::after {
		content: '';
		position: absolute;
		left: 0.5rem;
		right: 0.5rem;
		bottom: -0.1rem;
		height: 2px;
		background: var(--gold-500);
	}
	/* Sub-items become the hover/second-row layer */
	.ledger-nav__items {
		position: absolute;
		left: 0;
		top: 100%;
		z-index: 40;
		min-width: 190px;
		margin: 0;
		padding: 0.4rem;
		flex-direction: column;
		gap: 0;
		background: var(--ink-600);
		border: 1px solid var(--rule-strong);
		border-radius: var(--radius);
		box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
		opacity: 0;
		visibility: hidden;
		transform: translateY(-4px);
		/* visibility is NOT transitioned: a transitioned visibility stays hidden at
		   the instant focus lands, so a fast Tab skips the whole submenu. It flips
		   instantly (opacity still fades), which keeps the dropdown keyboard-reachable. */
		transition: opacity 0.14s var(--ease-out), transform 0.14s var(--ease-out);
	}
	.ledger-nav__category:hover .ledger-nav__items,
	.ledger-nav__category:focus-within .ledger-nav__items {
		opacity: 1;
		visibility: visible;
		transform: translateY(0);
	}
	.ledger-nav__items a { padding: 0.35rem 0.5rem; width: 100%; }
	.ledger-nav__category:last-child .ledger-nav__items { left: auto; right: 0; }

	.ledger-figure { padding: 0.85rem var(--pad); }

	.card { padding: 1.25rem; }
	.ledger-main { padding-bottom: var(--gap-lg); }
}

@media (min-width: 1024px) {
	:root { --step-4: 3rem; --step-5: 4.25rem; }

	/* Content beside the boxes, rather than boxes under the content */
	.ledger-main {
		grid-template-columns: minmax(0, 1fr) 300px;
		gap: 2.5rem 3rem;
	}
	.ledger-aside {
		grid-column: 2;
		grid-row: 1;
		position: sticky;
		top: 76px;
	}
	.ledger-content { grid-column: 1; grid-row: 1; }
	/* No box rendered on this page: give the content the whole width instead of
	   leaving the reserved sidebar column empty. */
	.ledger-main--solo { grid-template-columns: minmax(0, 1fr); }
}

@media (min-width: 1280px) {
	.ledger-main { padding-left: 2rem; padding-right: 2rem; }
	.ledger-header__inner { padding-left: 2rem; padding-right: 2rem; }
	.ledger-figures { padding: 0; }
}

/* --- Print -------------------------------------------------------------- */

@media print {
	body.ledger { background: #fff; color: #000; }
	.ledger-header, .ledger-aside, .ledger-footer, .skip-link, .ledger-nav__toggle { display: none; }
	.ledger-main { display: block; }
	.card { border-color: #999; background: #fff; }
}

/* ==========================================================================
   Brand layer: the game's palette on the site's chrome
   --------------------------------------------------------------------------
   The landing (css/landing.css) is built from the colours in the client's own
   artwork: teal-black and warm gold. Those two were never applied to the rest of
   the site, which kept the neutral ink steps above, and the result was a home page
   that looked like a different product from the pages behind it.

   This is the narrow fix: only the header and the footer take the game's palette.
   Content surfaces (cards, tables, fields) keep the ink steps, so no page body is
   restyled and no template had to change. Widening this later is a matter of
   moving the same two families into the token block and deleting what is here.

   Measured, not guessed: the values below were checked as composited pairs against
   WCAG 2.1 AA at the size each is used at — header text-secondary 9.77:1, brand-gold
   8.10:1, footer text-muted 5.71:1, button label on --brand-ink-600 14.59:1. Nothing
   here is a colour that only looks right.

   One thing deliberately NOT restyled: --text-faint is the disabled token and only
   appears on content surfaces (rank position, pager gap, calendar headings, the
   meter's unfilled track), none of which sit on the header or the footer. Its ratio
   against the new footer ground would be 3.97:1, below AA, so if a future change puts
   faint text in the chrome it has to move to --text-muted (5.71:1) first.          */

:root {
	/* Teal-black, from the client's panel ground over the illustration. */
	--brand-ink-800: #081820;
	--brand-ink-700: #0a1a24;
	--brand-ink-600: #10242f;
	--brand-edge:    #2c4a5c;

	/* Warm gold, from the mark. --gold-500 is #d9a441 and stays the action colour
	   throughout the site; this is the landing's #e0b64d, one step warmer, used only
	   where the game's own art is the reference (landing + footer). */
	--brand-gold:    #e0b64d;
	--brand-gold-2:  #f2d184;
	--brand-wash:    rgba(224, 182, 77, 0.12);
}

/* --- Header ------------------------------------------------------------- */

.ledger-header {
	background: rgba(8, 24, 32, 0.94);
	border-bottom-color: var(--brand-edge);
}

/* Nav links stay text-secondary. Measured against the composited header ground
   (#08171f, that is rgba(8,24,32,.94) over --ink-900) it is 9.77:1, and the active
   gold heading is 8.10:1, so both clear AA without lightening either. */
.ledger-nav__heading,
.ledger-nav__items a { color: var(--text-secondary); }
.ledger-nav__heading:hover,
.ledger-nav__items a:hover { color: var(--text-primary); }

/* The active category carries the game's gold rather than the ledger's, so the
   top of every page says which product you are in before you read anything. */
.ledger-nav__heading[aria-current='page'] { color: var(--brand-gold); }
.ledger-nav__items a:hover { text-decoration-color: var(--brand-gold); }

/* The brand mark is gold on the header; on ink it was the only warm thing here,
   and the teal ground makes it read as the game's rather than the site's. */
.ledger-brand:hover .ledger-brand__text,
.ledger-brand:hover img { opacity: 0.85; }

.ledger-nav__toggle { border-color: var(--brand-edge); }

/* Cascade trap, and the reason this restates two variants that already exist
   further up the file.

   .ledger-btn and .ledger-btn--waypoint are both single-class selectors, so this
   later block wins on source order and silently repaints the download button: the
   gold fill is gone and its label (--ink-900) ends up near-black on the teal, at
   1.1:1. Restating the two variants here is not duplication, it is the cascade
   being made explicit instead of accidental. If a third button variant is added to
   the button section above, it needs a line here too, or the same thing happens. */
.ledger-btn {
	background: var(--brand-ink-600);
	border-color: var(--brand-edge);
}
.ledger-btn:hover { background: #16303d; border-color: var(--brand-gold); }
.ledger-btn--quiet { background: transparent; }

.ledger-btn--waypoint {
	background: var(--gold-500);
	border-color: var(--gold-400);
	color: var(--ink-900);
}
.ledger-btn--waypoint:hover {
	background: var(--gold-400);
	border-color: var(--gold-400);
	color: var(--ink-900);
}

/* --- Footer ------------------------------------------------------------- */

.ledger-footer {
	background: var(--brand-ink-800);
	border-top-color: var(--brand-edge);
}
.ledger-footer__social a:hover,
.ledger-footer__social a:focus-visible {
	color: var(--brand-gold);
	background: var(--brand-wash);
}

/* --- Contact block (support list) -----------------------------------------
   The support list is where a player goes looking for staff, and staff presence
   is not a way to reach them, so the page ends with an address. The envelope is
   inline SVG from mobbia_icon() in index.php, not a second copy of the glyph. */

.ledger-contact__lead { margin-bottom: 0.75rem; }

.ledger-contact__mail { margin-bottom: 0.5rem; }

.ledger-contact__mail a {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-family: var(--font-chrome);
	font-weight: 700;
	font-size: var(--step-1);
	color: var(--gold-400);
	text-decoration: none;
	border-bottom: 1px solid var(--gold-edge);
	padding-bottom: 2px;
}
.ledger-contact__mail a:hover,
.ledger-contact__mail a:focus-visible {
	color: var(--gold-500);
	border-bottom-color: var(--gold-500);
}
.ledger-contact__mail .ledger-social-icon { fill: currentColor; }

.ledger-contact .ledger-muted { font-size: var(--step-0); }

/* --- Downloads (the CMS page seeded by bootstrap.php) --------------------
   The body is seeded into myaac_pages, not a template, so these classes are its
   only styling surface and they have to live here.

   The seed shipped one inline-styled <a> per file, each sized by its own text and
   wrapped in a <p>: three platforms, five files, five different button widths, and a
   brown (#5f4d41) that belongs to neither this theme nor the client's art. Everything
   below replaces that with one card per platform, a ruled row per file, and a single
   fixed-width button, so the row is a table you can scan instead of a list of
   differently sized slabs.

   The size always goes in its own cell rather than after the name. Inline, "Download
   Mobbia-installer-1.0.5.exe (41.5 MB)" is one long unbreakable label that pushes the
   button wider on every row that has a longer filename. */

.downloads__head {
	margin-bottom: var(--gap-lg);
	padding-bottom: var(--gap);
	border-bottom: 1px solid var(--rule-strong);
}

.downloads__version {
	margin: 0;
	color: var(--text-secondary);
	font-size: var(--step-0);
}
.downloads__version strong { color: var(--text-primary); font-variant-numeric: tabular-nums; }

/* Desktop y Mobile: dos bloques con su propio titulo, cada uno con una rejilla de
   plataformas dentro (Windows/Linux; Android/iPhone). */
.downloads__group + .downloads__group { margin-top: var(--gap-lg); }

.downloads__group-name {
	margin: 0 0 0.85rem;
	padding-bottom: 0.35rem;
	border-bottom: 1px solid var(--rule);
	font-family: var(--font-chrome);
	font-size: var(--step-2);
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-primary);
}

.downloads__grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--gap-lg);
}

.downloads__platform {
	background: var(--ink-700);
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	overflow: hidden;
}

.downloads__platform-name {
	margin: 0;
	padding: 0.7rem 1rem;
	background: var(--ink-600);
	border-bottom: 1px solid var(--rule-strong);
	font-size: var(--step-0);
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--gold-400);
}

/* iPhone aun no existe: la tarjeta se muestra apagada y solo anuncia que llega. */
.downloads__platform--soon {
	border-style: dashed;
	background: transparent;
}
.downloads__platform--soon .downloads__platform-name { color: var(--text-muted); }
.downloads__soon {
	margin: 0;
	padding: 0.85rem 1rem;
	color: var(--text-muted);
	font-style: italic;
}

.downloads__files {
	margin: 0;
	padding: 0;
	list-style: none;
}

.downloads__file {
	display: grid;
	grid-template-columns: 1fr auto;
	align-items: center;
	gap: 0.75rem 1rem;
	padding: 0.85rem 1rem;
}

/* The rule between rows stops at the card's edges, so it reads as a table inside the
   panel instead of a list that spills past it. */
.downloads__file + .downloads__file { border-top: 1px solid var(--rule); }

.downloads__file-text {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
	min-width: 0;
}

/* break-word, not anywhere. `anywhere` is willing to cut mid-segment, which turned
   "Mobbiaclient-linux-1.0.5-x86_64.AppImage" into "AppIma/ge". These filenames are
   all hyphen- and underscore-separated, and a browser will break after one of those
   on its own if a word cannot fit - so `break-word` gives the readable break points
   and only resorts to a hard cut for a single segment longer than the cell. */
.downloads__file-name {
	color: var(--text-primary);
	overflow-wrap: break-word;
}

.downloads__file-size {
	color: var(--text-muted);
	font-size: var(--step-0);
	font-variant-numeric: tabular-nums;
}

/* One button width for every row. Fixed, not content-sized, so the column lines up
   down the card whatever the filenames are. */
.downloads__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 8.5rem;
	min-height: 40px;
	padding: 0.5rem 1.25rem;
	background: var(--gold-500);
	border: 1px solid var(--gold-400);
	border-radius: var(--radius);
	color: var(--ink-900);
	font-family: var(--font-chrome);
	font-weight: 700;
	font-size: var(--step-0);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-decoration: none;
	white-space: nowrap;
	transition: background-color 0.15s var(--ease-out), border-color 0.15s var(--ease-out);
}
.downloads__btn:hover {
	background: var(--gold-400);
	border-color: var(--gold-400);
	color: var(--ink-900);
}

/* El boton de descarga va en verde, no en oro.
   El verde no es un verde inventado: es el dominante de btn-green-640.png, la
   pieza que dibuja el boton "Play" de la landing (images/landing/). Medido sobre
   esa imagen: #47704c, con acentos lima #a3fd08 que son adorno del artwork y no
   se intentan reproducir aqui.
   Sobre #47704c el blanco mide 5,69:1, que pasa AA para texto normal; con la tinta
   oscura del tema solo daba 3,29:1, asi que el texto va en blanco. */
.downloads__btn--primary {
	background: var(--green-500);
	border-color: var(--green-400);
	color: #fff;
}
.downloads__btn--primary:hover {
	background: var(--green-400);
	border-color: var(--green-400);
	color: #fff;
}

/* Bloque de verificacion de la firma, bajo el boton de Android.
   Es un <details> a proposito y no texto abierto: la huella es larga y solo
   interesa al que ya seCuatro que el aviso de Play Protect le aparecio. Abierto
   por defecto taparia la tabla de descargas en movil, que es justo donde ese
   aviso se ve. */
.downloads__cert {
	/* En la fila del archivo (grid text + boton), el desplegable ocupa la linea
	   entera debajo de los dos. */
	grid-column: 1 / -1;
	margin-top: 0.6rem;
	font-size: var(--step-0);
	color: var(--text-secondary);
}

.downloads__cert summary {
	cursor: pointer;
	color: var(--text-muted);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.downloads__cert summary:hover { color: var(--text-secondary); }

.downloads__cert p { margin: 0.5rem 0 0; }

/* La huella se parte por los dos puntos para que quepa en movil sin salirse. */
.downloads__cert-fingerprint code {
	display: block;
	padding: 0.45rem 0.6rem;
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	background: var(--ink-900);
	color: var(--text-secondary);
	font-family: ui-monospace, 'SF Mono', 'Cascadia Mono', Menlo, Consolas, monospace;
	font-size: 0.8em;
	word-break: break-all;
	line-height: 1.5;
}

.downloads__mirror {
	margin: 0;
	padding: 0.7rem 1rem;
	border-top: 1px solid var(--rule);
	background: var(--ink-800);
	font-size: var(--step-0);
}

/* --- Verify your download (checksum table) -------------------------------
   Una fila por archivo y tres columnas: File | SHA-256 | MD5. Los hashes son
   largos, asi que los <code> van display:block: word-break solo actua sobre
   contenedores de bloque y el <code> inline anterior lo ignoraba, de modo que
   el SHA-256 de 64 caracteres estiraba su celda, la tabla, y con ellas toda la
   pagina (el scroll lateral que se veia). Con block + break-all el hash se
   parte dentro de la columna. El contenedor scrollea solo como respaldo en
   pantallas mas angostas que las tres columnas; en una moderada no hace falta. */
.downloads__verify { text-align: left; }
.downloads__checksums { margin-top: 0.5rem; }
.downloads__checksum-table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--step-0);
}
.downloads__checksum-table th,
.downloads__checksum-table td {
	padding: 0.6rem 0.7rem;
	text-align: left;
	vertical-align: top;
	border-bottom: 1px solid var(--rule);
}
.downloads__checksum-table thead th {
	background: var(--ink-700);
	color: var(--text-secondary);
	font-family: var(--font-chrome);
	font-weight: 600;
	font-size: 0.8125rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	white-space: nowrap;
}
.downloads__checksum-table tbody tr:nth-child(even) { background: var(--ink-700); }
.downloads__checksum-table tbody tr:last-child td,
.downloads__checksum-table tbody tr:last-child th { border-bottom: 0; }
.downloads__checksum-name {
	font-weight: 600;
	color: var(--gold-400);
	overflow-wrap: break-word;
}
.downloads__checksum-hash code {
	display: block;
	font-family: ui-monospace, 'SF Mono', 'Cascadia Mono', Menlo, Consolas, monospace;
	font-size: 0.8em;
	line-height: 1.5;
	color: var(--text-secondary);
	word-break: break-all;
	overflow-wrap: anywhere;
}

@media (min-width: 900px) {
	/* Two abreast, not three. Three left the name column at about 120px once the
	   fixed-width button took its share, and every filename broke across four lines.
	   Two gives the name roughly 300px, which fits these names on one or two. */
	.downloads__grid { grid-template-columns: repeat(2, 1fr); align-items: start; }
}

@media (max-width: 480px) {
	/* Below this the button and the name cannot share a line without the name
	   breaking into three words, so the button takes its own row. */
	.downloads__file { grid-template-columns: 1fr; }
	.downloads__btn { width: 100%; }
}

@media print {
	.downloads__btn { border: 1px solid #000; color: #000; background: none; }
}

/* --- Server info (pages/ots-info.php) ------------------------------------
   A column of cards, each one a subject. The page used to be a definition list per
   subject rendered full width, which on a wide screen left the value in the next
   province; this keeps the label and its value within reading distance. */

.ledger-doc {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--gap-lg);
	align-items: start;
}

.ledger-doc .card { padding: 0; }
.ledger-doc .card__headline { padding: 0.75rem 1.1rem; }
.ledger-doc .ledger-defs { padding: 0.35rem 1.1rem 0.9rem; }
.ledger-doc .ledger-muted { padding: 0 1.1rem; }
.ledger-doc .ledger-list { padding: 0.35rem 1.1rem 0.9rem; }

@media (min-width: 1024px) {
	/* Two abreast: world + rates on the first row, the links card beside them. */
	.ledger-doc { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 560px) {
	.ledger-doc .card__headline,
	.ledger-doc .ledger-defs,
	.ledger-doc .ledger-muted,
	.ledger-doc .ledger-list { padding-left: 0.9rem; padding-right: 0.9rem; }
}

/* --- Version chooser (pages/selected-version.php) ------------------------
   Two branches, side by side. Each card is a flex column with the CTA pushed to
   the bottom, so the two buttons line up even when the descriptions differ in
   length. The version number is the thing the eye should land on. */

.version-lead {
	max-width: 62ch;
	margin: 0 0 var(--gap);
	color: var(--text-secondary);
}

.version-choice {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--gap-lg);
	align-items: stretch;
}
@media (min-width: 768px) {
	.version-choice { grid-template-columns: repeat(2, 1fr); }
}

.version-card {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}
.version-card__eyebrow {
	margin: 0;
	font-family: var(--font-chrome);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--gold-400);
}
.version-card__name {
	margin: 0;
	font-family: var(--font-chrome);
	font-size: var(--step-2);
	font-weight: 600;
	line-height: 1;
	color: var(--text-primary);
}
.version-card__number {
	font-size: var(--step-4);
	color: var(--gold-400);
}
.version-card__desc {
	margin: 0;
	color: var(--text-secondary);
}
.version-card__list li {
	padding: 0.3rem 0;
	border-bottom: 1px solid var(--rule);
}
.version-card__list li:last-child { border-bottom: 0; }
.version-card__cta {
	margin-top: auto;
	align-self: flex-start;
}
/* .card + .card adds a vertical gap for stacked cards. In a grid the gap already
   does that job, and the margin instead pushed the second card down inside its
   equally tall cell. */
.version-choice > .card + .card,
.ledger-doc > .card + .card { margin-top: 0; }

/* --- Tibia 7.4 (pages/tibia-7-4.php) ------------------------------------- */

.version-hero__title {
	margin: 0.25rem 0 0.6rem;
	font-size: var(--step-2);
	color: var(--text-primary);
}
.version-hero__lead {
	max-width: 62ch;
	margin: 0 0 1.1rem;
	color: var(--text-secondary);
}
.version-hero__cta { margin: 0 0 0.6rem; }
.version-hero__note { font-size: var(--step-0); }
.version-list li {
	padding: 0.45rem 0;
	border-bottom: 1px solid var(--rule);
}
.version-list li:last-child { border-bottom: 0; }

@media (max-width: 480px) {
	.version-card__cta { align-self: stretch; }
}

/* --- Achievement picker (account character settings) --------------------- */

.ledger-check {
	display: inline-flex;
	align-items: flex-start;
	gap: 0.55rem;
	padding: 0.2rem 0;
	cursor: pointer;
	line-height: 1.4;
}

.ledger-check input[type='checkbox'] {
	margin: 0.25rem 0 0;
	flex: 0 0 auto;
	accent-color: var(--gold-500);
	cursor: pointer;
}

.ledger-check:hover span { color: var(--gold-400); }

/* --- Character vitals, numbers only ----------------------------------------
   The three meters became three numbers. The bars spanned the whole page width to
   report "1000 / 1000" and "0 / 0", which is a full screen of decoration around two
   digits. What is left is a ruled row per value, same as the rest of the page. */

.ledger-vitals--plain {
	display: grid;
	grid-template-columns: 1fr;
	gap: 0;
	background: var(--ink-700);
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	overflow: hidden;
}

/* Grupos de opciones excluyentes (Houses).
   fieldset y legend, no celdas de tabla: el elemento significa exactamente eso, un
   conjunto de opciones del que solo se puede elegir una con su titulo. Antes cada
   opcion era un input suelto con un <br> detras, sin agrupacion semantica y sin
   nombre accesible. */
.ledger-radio-groups {
	display: grid;
	gap: 1.1rem;
	grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
	margin: 0;
	padding: 0;
	border: 0;
}

.ledger-radio-group {
	margin: 0;
	padding: 0.75rem 0.9rem;
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	background: var(--ink-800);
}

.ledger-radio-group legend {
	padding: 0 0.35rem;
	font-family: var(--font-chrome);
	font-size: var(--step-0);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--text-muted);
}

.ledger-radio {
	display: flex;
	align-items: center;
	gap: 0.45rem;
	padding: 0.15rem 0;
	cursor: pointer;
}

.ledger-radio input { flex: 0 0 auto; margin: 0; }
.ledger-radio label { color: var(--text-secondary); cursor: pointer; }

/* El pueblo es el unico grupo con lista larga: con todos los pueblos en una columna
   empuja a los otros tres grupos fuera de pantalla. */
.ledger-radio-group--tall { grid-row: span 3; }

@media (min-width: 900px) {
	.ledger-radio-groups { align-items: start; }
}

/* --- Sprites de la wiki de objetos -----------------------------------------
   El endpoint devuelve el recorte con el tamano real de la celda (32x32, 32x64,
   64x32 o 64x64 conviven), asi que la caja es cuadrada y fija y lo que se escala es
   la imagen con image-rendering: pixelated, que es lo que quiere un sprite: sin
   suavizado, o los bordes de 1 px salen grises. */
.wiki-items__sprite,
.wiki-item__sprite {
	margin: 0;
	text-align: center;
}

.wiki-items__sprite img,
.wiki-item__sprite img {
	display: block;
	margin: 0 auto;
	max-width: 100%;
	height: auto;
	image-rendering: pixelated;
}

/* Un item sin sprite devuelve un PNG vacio. El hueco se reserva para que las filas
   no den un salto al cargar, pero el marco no se dibuja: es mas honesto un hueco
   que un marco alrededor de la nada. */
/* Un item sin sprite devuelve un PNG de 1x1 transparente (item-sprite.php lo dice
   con su cabecera), y el hueco que dejaba al ocultarlo se leia como celda rota:
   4590 de los 37527 objetos del catalogo no tienen sprite en el cliente, asi que no
   es un caso raro sino una de cada ocho filas.

   En vez de dejar la celda vacia se dibuja una marca discreta. Va en CSS y no como
   imagen aparte para no anadir una peticion por fila: el catalogo ya pide 60 sprites
   por pagina, y sumar 60 peticiones mas por los huecos seria justo lo contrario de
   lo que se busca.

   El marco se dibuja en el contenedor, no en la imagen, porque la imagen es el
   elemento que se oculta. El simbolo es el gesto del sitio (una mira de oro),
   aqui en trazo y a bajo contraste: informa sin meterse con los objetos de al lado. */
.wiki-items__sprite--none,
.wiki-item__sprite--none {
	position: relative;
	min-width: 48px;
	min-height: 48px;
	display: flex;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	background: var(--ink-800);
}

.wiki-items__sprite--none::after,
.wiki-item__sprite--none::after {
	content: '';
	width: 10px;
	height: 10px;
	border: 1px solid var(--ink-500);
	transform: rotate(45deg);
}

.wiki-items__sprite--none img,
.wiki-item__sprite--none img {
	visibility: hidden;
}

/* El texto solo lo lee un lector de pantalla: para quien ve la pantalla la marca
   ya dice "no hay imagen", y el nombre del objeto no aporta nada ahi. */
.wiki-sprite-missing {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
}

.wiki-item__sprite .wiki-sprite-label {
	display: block;
	margin-top: 0.35rem;
	font-size: var(--step-0);
	color: var(--text-faint);
}

.wiki-items__sprite-col {
	width: 1%;
	white-space: nowrap;
}

/* En la ficha el sprite va sobre el bloque de definiciones, que en movil es una
   columna. El margen se separa del titular de arriba. */
.wiki-item__sprite {
	margin: 0.5rem 0 1rem;
}

/* Solo para lectores de pantalla: el encabezado de la columna del sprite no lleva
   texto visible, pero un th sin nombre rompe la navegacion por tabla. */
.ledger-visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}


.ledger-vitals__cell {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--gap);
	padding: 0.6rem 1rem;
}

.ledger-vitals__cell + .ledger-vitals__cell { border-top: 1px solid var(--rule); }

.ledger-vitals__label {
	font-family: var(--font-chrome);
	font-weight: 600;
	font-size: var(--step-0);
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--text-muted);
}

.ledger-vitals__value {
	font-family: var(--font-chrome);
	font-weight: 700;
	font-size: var(--step-1);
	color: var(--text-primary);
	text-align: right;
}

@media (min-width: 640px) {
	/* Three abreast once there is room for a row each, which is also how the band at
	   the top of the page reads them. */
	.ledger-vitals--plain { grid-template-columns: repeat(3, 1fr); }
	.ledger-vitals__cell + .ledger-vitals__cell {
		border-top: 0;
		border-left: 1px solid var(--rule);
	}
	.ledger-vitals__cell { flex-direction: column; align-items: flex-start; gap: 0.15rem; }
	.ledger-vitals__value { text-align: left; }
}
