@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;500;600;700&family=Lora:ital,wght@0,400;0,500;1,400&display=swap');

/* ==========================================================================
   VAELLUM -- landing page
   --------------------------------------------------------------------------
   A night-sky hero built from the game's own parallax plates (clouds,
   mountain, floor) resolving into the parchment grimoire below. One continuous
   journey: look up into the night, then open the book.

   The dark half and the parchment half share one palette. --gold and the ink
   ramp are the same hues in both, so the fold reads as a change of light
   rather than a change of site.
   ========================================================================== */

:root {
    /* Parchment ramp -- also the in-game grimoire surface */
    --parchment-0: #fbf6ec;
    --parchment-1: #f3ead9;
    --parchment-2: #e7d9c0;
    --parchment-3: #d6c3a3;
    --ink-900: #2a2118;
    --ink-700: #4a3c2c;
    --ink-500: #6b5a45;
    --ink-400: #8b7d6b;

    /* Night ramp -- the hero */
    --night-900: #0a1020;
    --night-800: #0f1830;
    --night-700: #16213f;
    --night-600: #22305a;

    --gold: #d4af37;
    --gold-bright: #f0cd63;
    --gold-deep: #9a7b1e;

    /* Rarity + status accents, tuned to stay legible on parchment */
    --rarity-common: #8b7d6b;
    --rarity-uncommon: #4f8a5b;
    --rarity-rare: #3f6fb5;
    --rarity-elite: #8b5cc7;
    --rarity-boss: #b5442f;

    --measure: 68ch;

    /* One easing curve for the whole page. Exponential out, never in. */
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

    --shell: 1180px;
}

/* --------------------------------------------------------------- reset --- */

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

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

body.landing {
    margin: 0;
    background: var(--parchment-0);
    color: var(--ink-900);
    font-family: 'Lora', Georgia, 'Times New Roman', serif;
    font-size: 17px;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

.landing img {
    max-width: 100%;
    display: block;
}

/* Browser surfaces we did not draw still carry the design. */
body.landing ::selection {
    background: rgba(212, 175, 55, 0.32);
    color: var(--ink-900);
}

body.landing {
    scrollbar-color: var(--parchment-3) var(--parchment-1);
    scrollbar-width: thin;
}

body.landing::-webkit-scrollbar { width: 11px; }
body.landing::-webkit-scrollbar-track { background: var(--parchment-1); }
body.landing::-webkit-scrollbar-thumb {
    background: var(--parchment-3);
    border: 3px solid var(--parchment-1);
    border-radius: 99px;
}
body.landing::-webkit-scrollbar-thumb:hover { background: var(--gold-deep); }

.shell {
    width: min(100% - 48px, var(--shell));
    margin-inline: auto;
}

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

/* One focus treatment everywhere, visible on both halves of the page. */
.landing a:focus-visible,
.landing button:focus-visible {
    outline: 2px solid var(--gold-bright);
    outline-offset: 3px;
    border-radius: 3px;
}

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

.display {
    font-family: 'Cinzel', 'Palatino Linotype', Georgia, serif;
    font-weight: 600;
    line-height: 1.08;
    letter-spacing: -0.015em;
    text-wrap: balance;
    margin: 0;
}

/* A section heading is the section's own voice. No eyebrow above it. */
.section-heading {
    font-size: clamp(1.85rem, 3.4vw, 2.85rem);
    color: var(--ink-900);
}

/* The quiet line under a heading. */
.section-lede {
    max-width: var(--measure);
    margin: 18px 0 0;
    font-size: 1.06rem;
    color: var(--ink-500);
    text-wrap: pretty;
}

.section-head {
    max-width: 720px;
    margin-bottom: 52px;
}
/* ------------------------------------------------------------- buttons --- */

.btn {
    --btn-bg: transparent;
    --btn-fg: var(--parchment-0);
    --btn-bd: var(--gold);
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 15px 30px;
    border: 1px solid var(--btn-bd);
    border-radius: 2px;
    background: var(--btn-bg);
    color: var(--btn-fg);
    font-family: 'Cinzel', Georgia, serif;
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    /* A gold leaf edge that lifts on press. Offset + blur, never a hard block
       shadow. */
    box-shadow: 0 2px 10px rgba(10, 16, 32, 0.28);
    transition:
        transform 180ms var(--ease-out),
        box-shadow 180ms var(--ease-out),
        background-color 180ms var(--ease-out),
        color 180ms var(--ease-out),
        border-color 180ms var(--ease-out);
}

.btn:active {
    transform: translateY(1px) scale(0.985);
    box-shadow: 0 1px 4px rgba(10, 16, 32, 0.3);
    transition-duration: 80ms;
}

@media (hover: hover) and (pointer: fine) {
    .btn:hover {
        transform: translateY(-2px);
        box-shadow: 0 10px 26px rgba(10, 16, 32, 0.34);
    }
}

.btn--primary {
    --btn-bg: var(--gold);
    --btn-fg: #241a08;
    --btn-bd: var(--gold-bright);
}

@media (hover: hover) and (pointer: fine) {
    .btn--primary:hover { --btn-bg: var(--gold-bright); }
}

.btn--primary:active { --btn-bg: var(--gold-deep); }

.btn--ghost {
    --btn-bg: rgba(255, 255, 255, 0.04);
    --btn-fg: var(--parchment-0);
    --btn-bd: rgba(244, 238, 224, 0.4);
}

@media (hover: hover) and (pointer: fine) {
    .btn--ghost:hover {
        --btn-bd: var(--gold);
        --btn-bg: rgba(212, 175, 55, 0.1);
    }
}

.btn--quiet {
    --btn-bg: transparent;
    --btn-fg: var(--ink-700);
    --btn-bd: var(--parchment-3);
    box-shadow: none;
}

@media (hover: hover) and (pointer: fine) {
    .btn--quiet:hover {
        --btn-bd: var(--gold);
        --btn-fg: var(--ink-900);
        box-shadow: 0 8px 20px rgba(74, 60, 44, 0.14);
    }
}

/* ------------------------------------------------------------------ nav --- */

.masthead {
    position: fixed;
    inset: 0 0 auto 0;
    z-index: 60;
    border-bottom: 1px solid transparent;
    transition:
        background-color 260ms var(--ease-out),
        border-color 260ms var(--ease-out),
        backdrop-filter 260ms var(--ease-out);
}

/* Blur only once the hero is behind it. At the top of the page the bar stays
   fully transparent so the sky reaches the edge of the screen. */
.masthead[data-stuck='true'] {
    background: rgba(10, 16, 32, 0.82);
    backdrop-filter: blur(14px) saturate(1.3);
    -webkit-backdrop-filter: blur(14px) saturate(1.3);
    border-bottom-color: rgba(212, 175, 55, 0.22);
}

.masthead__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 28px;
    height: 76px;
}

.masthead__brand {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
    color: var(--parchment-0);
}

.masthead__word {
    font-family: 'Cinzel', Georgia, serif;
    font-size: 1.06rem;
    font-weight: 600;
    letter-spacing: 0.3em;
    text-transform: uppercase;
}

.masthead__nav { display: flex; align-items: center; gap: 30px; }

.masthead__link {
    color: rgba(244, 238, 224, 0.76);
    font-size: 0.8rem;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    text-decoration: none;
    transition: color 160ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
    .masthead__link:hover { color: var(--gold-bright); }
}

.masthead__actions { display: flex; align-items: center; gap: 14px; }

.masthead__cta { padding: 10px 20px; font-size: 0.72rem; }

.masthead__toggle {
    display: none;
    width: 42px;
    height: 42px;
    padding: 0;
    border: 1px solid rgba(244, 238, 224, 0.28);
    border-radius: 2px;
    background: transparent;
    cursor: pointer;
}

/* The toggle only means something once landing.js can answer it. Without JS
   the links stay in the bar, so the button must not appear at all. It is only
   ever useful inside the narrow breakpoint, so that is where it is enabled. */
@media (max-width: 860px) {
    .js .masthead__toggle { display: grid; place-items: center; }
}

.masthead__toggle-bars,
.masthead__toggle-bars::before,
.masthead__toggle-bars::after {
    display: block;
    width: 18px;
    height: 1.5px;
    background: var(--parchment-0);
    transition: transform 200ms var(--ease-out), opacity 160ms var(--ease-out);
}

.masthead__toggle-bars { position: relative; }

.masthead__toggle-bars::before,
.masthead__toggle-bars::after {
    content: '';
    position: absolute;
    left: 0;
}

.masthead__toggle-bars::before { top: -6px; }
.masthead__toggle-bars::after { top: 6px; }

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

/* ----------------------------------------------------------------- hero --- */

.hero {
    position: relative;
    min-height: 100svh;
    display: flex;
    align-items: flex-end;
    padding: 130px 0 0;
    overflow: hidden;
    background: var(--night-900);
    isolation: isolate;
}

/* The sky: a deep night gradient with a cold horizon glow. The one place
   this page uses a gradient, and it is doing real work -- it is the light
   source for everything standing on it. */
.hero__sky {
    position: absolute;
    inset: 0;
    z-index: -4;
    background:
        radial-gradient(120% 80% at 50% 108%, #2c4573 0%, rgba(44, 69, 115, 0) 62%),
        linear-gradient(to bottom, #060a16 0%, #0a1020 38%, #16213f 76%, #22305a 100%);
}

/* Stars. Three layers at different sizes so the field does not read as a
   repeating tile, and a slow twinkle that is opacity-only. */
.hero__stars {
    position: absolute;
    inset: 0 0 34% 0;
    z-index: -3;
    pointer-events: none;
    background-repeat: repeat;
    background-size: 420px 420px, 260px 260px, 640px 640px;
    background-image:
        radial-gradient(1.4px 1.4px at 40px 60px, rgba(255, 255, 255, 0.9), transparent),
        radial-gradient(1px 1px at 180px 130px, rgba(214, 232, 255, 0.75), transparent),
        radial-gradient(1.8px 1.8px at 300px 40px, rgba(255, 246, 222, 0.7), transparent);
    mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%);
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%);
    animation: hero-twinkle 7s var(--ease-in-out) infinite alternate;
}

@keyframes hero-twinkle {
    from { opacity: 0.55; }
    to   { opacity: 1; }
}

/* The game's own parallax plates. Same files the combat scene uses, so the
   marketing page and the game are provably the same world. */
.hero__plate {
    position: absolute;
    left: -4%;
    width: 108%;
    background-repeat: repeat-x;
    background-position: bottom center;
    background-size: auto 100%;
    pointer-events: none;
    will-change: transform;
}

.hero__plate--clouds {
    bottom: 30%;
    z-index: -2;
    height: 46%;
    opacity: 0.5;
    background-image: url('../images/backgrounds/parallax/clouds.png');
    /* The same 60s drift the combat scene uses. */
    animation: plate-drift 60s linear infinite;
}

.hero__plate--mountain {
    bottom: 16%;
    z-index: -1;
    height: 56%;
    background-image: url('../images/backgrounds/parallax/mountain.png');
    /* Silhouetted into the night so the plate never fights the copy. */
    filter: brightness(0.34) saturate(0.6) hue-rotate(200deg);
}

.hero__plate--floor {
    bottom: 0;
    z-index: -1;
    height: 22%;
    background-image: url('../images/backgrounds/parallax/floor.png');
    background-size: auto 100%;
    filter: brightness(0.22) saturate(0.5) hue-rotate(205deg);
    mask-image: linear-gradient(to bottom, transparent 0%, #000 45%);
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 45%);
}

@keyframes plate-drift {
    from { background-position-x: 0; }
    to   { background-position-x: 200px; }
}

/* The horizon seam where the night hands off to the parchment. */
.hero__seam {
    position: absolute;
    inset: auto 0 0 0;
    z-index: 0;
    height: 40%;
    background: linear-gradient(to bottom, rgba(251, 246, 236, 0) 0%, rgba(251, 246, 236, 0.55) 78%, var(--parchment-0) 100%);
    pointer-events: none;
}

.hero__inner {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
    align-items: end;
    gap: 60px;
    width: min(100% - 48px, var(--shell));
    margin-inline: auto;
    padding-bottom: 104px;
}

.hero__copy { max-width: 640px; }

.hero__crest {
    width: clamp(88px, 11vw, 128px);
    height: auto;
    margin-bottom: 26px;
    filter: drop-shadow(0 6px 22px rgba(212, 175, 55, 0.28));
}

.hero__title {
    font-size: clamp(2.9rem, 8.2vw, 5.6rem);
    font-weight: 700;
    letter-spacing: -0.025em;
    color: var(--parchment-0);
    text-shadow: 0 2px 30px rgba(0, 0, 0, 0.55);
}

.hero__title em {
    display: block;
    font-style: normal;
    /* Emphasis by weight and colour, never by gradient fill. */
    color: var(--gold-bright);
    text-shadow: 0 0 44px rgba(212, 175, 55, 0.4);
}

.hero__lede {
    max-width: 52ch;
    margin: 24px 0 0;
    font-size: clamp(1.02rem, 1.5vw, 1.18rem);
    line-height: 1.7;
    color: rgba(238, 232, 219, 0.82);
    text-wrap: pretty;
}

.hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 38px;
}

.hero__note {
    margin: 22px 0 0;
    font-size: 0.88rem;
    color: rgba(226, 218, 203, 0.62);
}

.hero__note strong { color: var(--gold-bright); font-weight: 600; }

/* --- The live ledger: real numbers, read from the game tables. --- */

.hero__ledger {
    justify-self: end;
    width: 100%;
    max-width: 330px;
    padding: 26px 28px 24px;
    /* A specific material: smoked glass over the night, so the mountains
       stay visible behind it. */
    background: linear-gradient(160deg, rgba(28, 42, 74, 0.62), rgba(10, 16, 32, 0.5));
    border: 1px solid rgba(212, 175, 55, 0.26);
    border-radius: 3px;
    backdrop-filter: blur(16px) saturate(1.25);
    -webkit-backdrop-filter: blur(16px) saturate(1.25);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.09),
        0 24px 60px rgba(0, 0, 0, 0.42);
}

.hero__ledger-title {
    margin: 0 0 20px;
    font-family: 'Cinzel', Georgia, serif;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: rgba(226, 218, 203, 0.62);
}

.hero__ledger-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 11px 0;
    border-top: 1px solid rgba(244, 238, 224, 0.1);
}

.hero__ledger-row:first-of-type { border-top: 0; }

.hero__ledger-key { font-size: 0.86rem; color: rgba(226, 218, 203, 0.74); }

.hero__ledger-value {
    font-family: 'Cinzel', Georgia, serif;
    font-size: 1.3rem;
    font-weight: 600;
    color: var(--gold-bright);
    /* Counters must not jitter as their digits change. */
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
}

.hero__scroll {
    position: absolute;
    left: 50%;
    bottom: 26px;
    z-index: 2;
    transform: translateX(-50%);
    display: grid;
    place-items: center;
    width: 26px;
    height: 42px;
    border: 1px solid rgba(244, 238, 224, 0.32);
    border-radius: 99px;
}

.hero__scroll::after {
    content: '';
    width: 3px;
    height: 8px;
    border-radius: 99px;
    background: var(--gold);
    animation: scroll-tick 1.9s var(--ease-in-out) infinite;
}

@keyframes scroll-tick {
    0%, 100% { transform: translateY(0); opacity: 1; }
    55%      { transform: translateY(13px); opacity: 0.15; }
}

/* ------------------------------------------------------------ parchment --- */

.paper {
    position: relative;
    background: var(--parchment-0);
    padding: 108px 0;
}

/* A faint laid-paper texture: two hairline rules, not a noise image. */
.paper::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background:
        linear-gradient(to right, rgba(212, 175, 55, 0.07) 1px, transparent 1px) 0 0 / 96px 100%,
        linear-gradient(to bottom, rgba(212, 175, 55, 0.05) 1px, transparent 1px) 0 0 / 100% 96px;
    mask-image: radial-gradient(120% 90% at 50% 0%, #000 0%, transparent 78%);
    -webkit-mask-image: radial-gradient(120% 90% at 50% 0%, #000 0%, transparent 78%);
}

.paper > * { position: relative; }

/* Two tones, so consecutive sections separate without a hard rule. */
.paper--tint { background: var(--parchment-1); }

/* A gold rule with a diamond at its centre, closing a section heading. */
.rule-flourish {
    display: flex;
    align-items: center;
    gap: 14px;
    margin: 0 0 26px;
}

.rule-flourish::before,
.rule-flourish::after {
    content: '';
    height: 1px;
    flex: 1;
    max-width: 90px;
    background: linear-gradient(to right, transparent, var(--parchment-3), transparent);
}

.rule-flourish i {
    width: 6px;
    height: 6px;
    background: var(--gold);
    transform: rotate(45deg);
    flex: none;
}

/* ---------------------------------------------------------------- world --- */

/* An editorial spread: the first region gets the room, the rest form a quiet
   ledger beside it. Not a grid of equal tiles. */
.world {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
    gap: 40px;
    align-items: start;
}

.world__feature {
    position: relative;
    overflow: hidden;
    border-radius: 3px;
    min-height: 420px;
    display: flex;
    align-items: flex-end;
    box-shadow: 0 24px 60px rgba(42, 33, 24, 0.18);
}

.world__feature img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 700ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
    .world__feature:hover img { transform: scale(1.04); }
}

.world__feature::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, rgba(15, 24, 48, 0.94) 0%, rgba(15, 24, 48, 0.62) 38%, rgba(15, 24, 48, 0.06) 72%);
}

.world__feature-body {
    position: relative;
    z-index: 1;
    padding: 34px 36px;
    color: var(--parchment-0);
}

.world__feature-body h3 {
    font-family: 'Cinzel', Georgia, serif;
    font-size: clamp(1.5rem, 2.6vw, 2.1rem);
    font-weight: 600;
    line-height: 1.14;
    margin: 0 0 12px;
    letter-spacing: -0.01em;
    text-wrap: balance;
}

.world__feature-body p {
    max-width: 46ch;
    margin: 0;
    color: rgba(238, 232, 219, 0.8);
    font-size: 0.98rem;
}

.world__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}

.world__item {
    display: grid;
    grid-template-columns: 92px minmax(0, 1fr);
    align-items: center;
    gap: 20px;
    padding: 18px 0;
    border-top: 1px solid var(--parchment-2);
    transition: transform 200ms var(--ease-out);
}

.world__item:first-child { border-top: 0; }

@media (hover: hover) and (pointer: fine) {
    .world__item:hover { transform: translateX(4px); }
}

.world__thumb {
    width: 92px;
    height: 62px;
    object-fit: cover;
    border-radius: 2px;
    box-shadow: 0 4px 14px rgba(42, 33, 24, 0.16);
}

.world__item-body h4 {
    margin: 0 0 3px;
    font-family: 'Cinzel', Georgia, serif;
    font-size: 1.02rem;
    font-weight: 600;
    color: var(--ink-900);
    line-height: 1.2;
}

.world__item-body p {
    margin: 0;
    font-size: 0.87rem;
    line-height: 1.5;
    color: var(--ink-500);
    /* Two lines is enough; the full text lives on the zone page. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* The level band. A measurement, so it is tabular and quiet. */
.world__levels {
    display: inline-block;
    margin-top: 6px;
    font-family: 'Cinzel', Georgia, serif;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    color: var(--gold-deep);
    font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------- bestiary --- */

/* A horizontal rail. Scroll-snap gives the section a dealt-card feel on touch
   without hijacking the wheel on desktop. */
.bestiary {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: clamp(228px, 24vw, 268px);
    gap: 22px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    padding: 6px 4px 26px;
    margin: 0 -4px;
    scrollbar-width: thin;
    scrollbar-color: var(--parchment-3) transparent;
}

.bestiary::-webkit-scrollbar { height: 8px; }
.bestiary::-webkit-scrollbar-track { background: var(--parchment-2); border-radius: 99px; }
.bestiary::-webkit-scrollbar-thumb { background: var(--parchment-3); border-radius: 99px; }
.bestiary::-webkit-scrollbar-thumb:hover { background: var(--gold-deep); }

/* The card: 5:4 art over a text foot, the trading-card proportion the monster
   art was drawn for. */
.card {
    position: relative;
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    background: linear-gradient(170deg, #fffdf8 0%, var(--parchment-1) 100%);
    border: 1px solid var(--parchment-3);
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 10px 26px rgba(42, 33, 24, 0.14);
    transition:
        transform 240ms var(--ease-out),
        box-shadow 240ms var(--ease-out),
        border-color 240ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
    .card:hover {
        transform: translateY(-8px) rotate(-0.5deg);
        box-shadow: 0 26px 54px rgba(42, 33, 24, 0.24);
        border-color: var(--gold);
    }
}

.card__art {
    position: relative;
    aspect-ratio: 5 / 4;
    overflow: hidden;
    background: var(--night-800);
    /* The inner bevel of a card frame, drawn in CSS. */
    box-shadow: inset 0 0 0 1px rgba(42, 33, 24, 0.16);
}

.card__art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 500ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
    .card:hover .card__art img { transform: scale(1.06); }
}

/* Rarity reads as a hairline across the frame, not a badge on top. */
.card__rarity {
    position: absolute;
    inset: auto 0 0 0;
    height: 3px;
    background: var(--rarity-common);
}

.card__rarity[data-rarity='uncommon'] { background: var(--rarity-uncommon); }
.card__rarity[data-rarity='rare']     { background: var(--rarity-rare); }
.card__rarity[data-rarity='elite']    { background: var(--rarity-elite); }
.card__rarity[data-rarity='boss']     { background: var(--rarity-boss); }

.card__body {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 16px 17px 18px;
    flex: 1;
}

.card__name {
    margin: 0;
    font-family: 'Cinzel', Georgia, serif;
    font-size: 0.98rem;
    font-weight: 600;
    line-height: 1.22;
    color: var(--ink-900);
    text-wrap: balance;
}

.card__meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin: 0;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    color: var(--ink-400);
    font-variant-numeric: tabular-nums;
}

.card__type { color: var(--gold-deep); }

.card__text {
    margin: 0;
    font-size: 0.86rem;
    line-height: 1.52;
    color: var(--ink-500);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* The stats strip closing the card, the way a card frame closes. */
.card__foot {
    margin: auto 0 0;
    padding-top: 12px;
    border-top: 1px solid var(--parchment-2);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    font-size: 0.74rem;
    color: var(--ink-400);
    font-variant-numeric: tabular-nums;
}

.card__exp { color: var(--ink-700); font-weight: 600; }

/* ----------------------------------------------------------------- news --- */

/* A pinned lead post, then the rest as a dated ledger. The lead is the reason
   the section exists, so it gets the space. */
.news {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
    gap: 48px;
    align-items: start;
}

.news__lead {
    display: block;
    text-decoration: none;
    color: inherit;
    border-radius: 3px;
    overflow: hidden;
    background: var(--parchment-0);
    border: 1px solid var(--parchment-2);
    box-shadow: 0 18px 44px rgba(42, 33, 24, 0.13);
    transition: transform 240ms var(--ease-out), box-shadow 240ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
    .news__lead:hover {
        transform: translateY(-5px);
        box-shadow: 0 30px 62px rgba(42, 33, 24, 0.2);
    }
}

.news__lead-art {
    display: block;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    background: var(--night-800);
}

.news__lead-art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 600ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
    .news__lead:hover .news__lead-art img { transform: scale(1.045); }
}

.news__lead-body { display: block; padding: 28px 30px 30px; }

/* The lead and its rows are anchors, so their parts are spans. They are given
   block flow explicitly or they stack inline and the card collapses. */
.news__lead-title,
.news__lead-excerpt,
.news__row-title,
.news__row-excerpt { display: block; }

.news__tags {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.news__lead-body .news__tags { margin-bottom: 14px; }
.news__row .news__tags { margin-bottom: 0; }

/* Category and version are the only pills on the page, and they are tags on a
   document rather than decoration. */
.tag {
    display: inline-flex;
    align-items: center;
    padding: 4px 11px;
    border: 1px solid var(--parchment-3);
    border-radius: 2px;
    background: var(--parchment-1);
    font-family: 'Cinzel', Georgia, serif;
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-500);
    font-variant-numeric: tabular-nums;
}

.tag--patch { border-color: rgba(212, 175, 55, 0.55); color: var(--gold-deep); background: rgba(212, 175, 55, 0.11); }
.tag--news  { border-color: rgba(63, 111, 181, 0.42); color: #2f5690; background: rgba(63, 111, 181, 0.09); }
.tag--event { border-color: rgba(181, 68, 47, 0.4); color: #9a3826; background: rgba(181, 68, 47, 0.08); }
.tag--maint { border-color: rgba(107, 90, 69, 0.4); color: var(--ink-500); }
.tag--pinned { border-color: transparent; background: var(--ink-900); color: var(--parchment-1); }

.news__lead-title {
    margin: 0 0 12px;
    font-family: 'Cinzel', Georgia, serif;
    font-size: clamp(1.3rem, 2.3vw, 1.72rem);
    font-weight: 600;
    line-height: 1.16;
    letter-spacing: -0.012em;
    color: var(--ink-900);
    text-wrap: balance;
    transition: color 180ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
    .news__lead:hover .news__lead-title { color: var(--gold-deep); }
}

.news__lead-excerpt {
    margin: 0;
    max-width: var(--measure);
    color: var(--ink-500);
    font-size: 0.98rem;
    line-height: 1.62;
}

.news__read {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 20px;
    font-family: 'Cinzel', Georgia, serif;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--gold-deep);
}

.news__read svg { transition: transform 200ms var(--ease-out); }

@media (hover: hover) and (pointer: fine) {
    .news__lead:hover .news__read svg { transform: translateX(5px); }
}

/* The ledger of everything else. */
.news__list { list-style: none; margin: 0; padding: 0; }

.news__row {
    display: block;
    padding: 22px 0 24px;
    border-top: 1px solid var(--parchment-2);
    text-decoration: none;
    color: inherit;
    transition: transform 200ms var(--ease-out);
}

.news__row:first-child { border-top: 0; padding-top: 0; }

@media (hover: hover) and (pointer: fine) {
    .news__row:hover { transform: translateX(4px); }
}

.news__row-title {
    margin: 9px 0 7px;
    font-family: 'Cinzel', Georgia, serif;
    font-size: 1.04rem;
    font-weight: 600;
    line-height: 1.26;
    color: var(--ink-900);
    text-wrap: balance;
    transition: color 180ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
    .news__row:hover .news__row-title { color: var(--gold-deep); }
}

.news__row-excerpt {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.56;
    color: var(--ink-500);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.news__date {
    font-size: 0.72rem;
    letter-spacing: 0.06em;
    color: var(--ink-400);
    font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------ invite/cta --- */

/* The last thing on the page is the ask. It returns to the night sky so the
   page ends where it began. */
.invite {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    padding: 116px 0;
    text-align: center;
    background: var(--night-900);
}

.invite__sky {
    position: absolute;
    inset: 0;
    z-index: -1;
    background:
        radial-gradient(90% 70% at 50% 100%, #2a4270 0%, rgba(42, 66, 112, 0) 60%),
        linear-gradient(to bottom, #0a1020 0%, #0d1526 55%, #16213f 100%);
}

.invite__sky::after {
    content: '';
    position: absolute;
    inset: 0;
    background-repeat: repeat;
    background-size: 520px 520px;
    background-image:
        radial-gradient(1.2px 1.2px at 60px 80px, rgba(255, 255, 255, 0.55), transparent),
        radial-gradient(1px 1px at 300px 200px, rgba(214, 232, 255, 0.4), transparent);
    mask-image: radial-gradient(100% 80% at 50% 50%, #000 0%, transparent 80%);
    -webkit-mask-image: radial-gradient(100% 80% at 50% 50%, #000 0%, transparent 80%);
}

.invite__inner {
    max-width: 660px;
    margin-inline: auto;
    padding-inline: 24px;
}

.invite__title {
    font-size: clamp(2.1rem, 5.4vw, 3.5rem);
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--parchment-0);
}

.invite__lede {
    max-width: 48ch;
    margin: 22px auto 0;
    color: rgba(238, 232, 219, 0.78);
    font-size: 1.04rem;
    text-wrap: pretty;
}

.invite__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    justify-content: center;
    margin-top: 40px;
}

.invite__foot {
    margin: 34px 0 0;
    font-size: 0.85rem;
    color: rgba(226, 218, 203, 0.52);
}

.invite__foot a { color: rgba(226, 218, 203, 0.74); }

/* --------------------------------------------------------------- footer --- */

.footer {
    background: var(--night-800);
    color: rgba(226, 218, 203, 0.62);
    padding: 52px 0 44px;
    font-size: 0.88rem;
}

.footer__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 26px;
}

.footer__brand {
    display: flex;
    align-items: center;
    color: var(--parchment-0);
    text-decoration: none;
}

.footer__brand span {
    font-family: 'Cinzel', Georgia, serif;
    font-size: 0.92rem;
    font-weight: 600;
    letter-spacing: 0.26em;
    text-transform: uppercase;
}

.footer__nav { display: flex; flex-wrap: wrap; gap: 24px; }

.footer__nav a {
    color: rgba(226, 218, 203, 0.62);
    text-decoration: none;
    font-size: 0.8rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    transition: color 160ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
    .footer__nav a:hover { color: var(--gold-bright); }
}

.footer__legal {
    width: 100%;
    margin: 0;
    padding-top: 24px;
    border-top: 1px solid rgba(244, 238, 224, 0.1);
    font-size: 0.8rem;
    color: rgba(226, 218, 203, 0.46);
}

/* --------------------------------------------------------------- states --- */

/* An empty rail still needs to say something. */
.empty-note {
    padding: 34px 30px;
    border: 1px dashed var(--parchment-3);
    border-radius: 3px;
    color: var(--ink-500);
    font-size: 0.95rem;
    text-align: center;
}

/* ----------------------------------------------------------- responsive --- */

@media (max-width: 1080px) {
    .hero__inner {
        grid-template-columns: minmax(0, 1fr);
        align-items: start;
        gap: 44px;
    }

    .hero__ledger {
        justify-self: start;
        max-width: 420px;
    }

    .world,
    .news {
        grid-template-columns: minmax(0, 1fr);
        gap: 40px;
    }
}

@media (max-width: 860px) {
    body.landing { font-size: 16.5px; }

    .paper { padding: 78px 0; }
    .section-head { margin-bottom: 38px; }

    /* The nav becomes a disclosure, but only under JS: without it the links
       stay inline in the bar and remain reachable. */
    .js .masthead__nav {
        display: none;
        position: absolute;
        top: 100%;
        right: 24px;
        left: 24px;
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        padding: 6px 0 14px;
        background: rgba(10, 16, 32, 0.97);
        border: 1px solid rgba(212, 175, 55, 0.24);
        border-top: 0;
        backdrop-filter: blur(14px);
        -webkit-backdrop-filter: blur(14px);
    }

    .js .masthead__nav[data-open='true'] { display: flex; }

    .masthead__link {
        padding: 15px 22px;
        border-top: 1px solid rgba(244, 238, 224, 0.09);
        font-size: 0.86rem;
    }

    .masthead__actions .btn--ghost { display: none; }

    .world__feature { min-height: 320px; }
    .world__feature-body { padding: 26px 24px; }

    .footer__inner { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 560px) {
    .shell,
    .hero__inner { width: min(100% - 34px, var(--shell)); }

    .hero { padding-top: 112px; }
    .hero__inner { padding-bottom: 88px; }

    .hero__actions .btn,
    .invite__actions .btn { width: 100%; }

    .world__item { grid-template-columns: 72px minmax(0, 1fr); gap: 14px; }
    .world__thumb { width: 72px; height: 52px; }

    .bestiary { grid-auto-columns: minmax(212px, 74vw); }

    .invite { padding: 84px 0; }
}

/* ------------------------------------------------------- reduced motion --- */

/* Honour the preference: keep the layout and the depth, drop the movement. The
   parallax plates stop drifting and nothing translates on reveal. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }

    .hero__stars,
    .hero__plate--clouds { animation: none; }

    .hero__stars { opacity: 0.85; }
    .hero__scroll { display: none; }
}

/* Elements revealed on scroll start hidden ONLY when JS is running, so the
   page is complete without it. The class is added by landing.js. */
.js-reveal {
    opacity: 0;
    transform: translateY(18px);
    transition:
        opacity 620ms var(--ease-out),
        transform 620ms var(--ease-out);
    /* Below the fold there is no urgency: reveal as soon as it is seen. */
    transition-delay: var(--reveal-delay, 0ms);
    will-change: opacity, transform;
}

.js-reveal[data-revealed='true'] {
    opacity: 1;
    transform: none;
    will-change: auto;
}

@media (prefers-reduced-motion: reduce) {
    .js-reveal {
        opacity: 1;
        transform: none;
    }
}

/* Printing never scrolls, so nothing would ever reveal and the sheet would
   come out blank below the fold. Paint the final state unconditionally. */
@media print {
    .js-reveal,
    .js-reveal[data-revealed='true'] {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
}
