﻿/*
  RuneInsights design system.

  Dark by default, because the audience plays a dark game late at night, and built mobile first:
  the most common visit is a quick check of today's progress on a phone. Everything is driven by
  the tokens below so the whole app can be re-themed from one place.

  The palette is warm on purpose. Every other tracker on the internet is cool slate grey with blue,
  purple and green accents, which is precisely what this app must not look like. This one is lit
  like a lamp on old paper: brown-black ink underneath, parchment for type, and a single family of
  heat above it running moss to brass to gold to ember. Nothing here is a hue borrowed from a
  framework default.
*/

:root {
    --bg: #12100c;
    --bg-elevated: #191510;
    --surface: #1f1a14;
    --surface-hover: #29221a;
    --surface-sunken: #14110d;
    --border: #2f2720;
    --border-strong: #453a2d;

    /* Parchment rather than white, so nothing on the page is colder than the paper it sits on. */
    --text: #f1e7d5;
    --text-muted: #b0a189;
    --text-faint: #877866;

    /* RuneScape's experience-drop yellow. The brand, and reserved for progress itself. */
    --gold: #f2b632;
    --gold-dim: #8a6a1c;
    --gold-wash: rgba(242, 182, 50, 0.13);

    /* Brass is the near-neutral the feature sections share: warm enough to belong to the palette,
       quiet enough that it never competes with a number. */
    --brass: #a4907a;
    --brass-wash: rgba(164, 144, 122, 0.12);

    /* Moss for growth, ember for heat and the highest tiers, rust for anything going backwards.
       The tints exist for text that has to sit on top of its own wash and stay readable. */
    --moss: #9db35c;
    --moss-wash: rgba(157, 179, 92, 0.14);
    --moss-tint: #c6d78d;
    --ember: #e2703a;
    --ember-wash: rgba(226, 112, 58, 0.14);
    --rust: #c4503f;
    --rust-wash: rgba(196, 80, 63, 0.15);
    --rust-tint: #f0a794;

    --radius: 10px;
    --radius-lg: 14px;
    --radius-sm: 6px;

    --shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 8px 24px rgba(0, 0, 0, 0.3);

    --sidebar-width: 244px;
    --header-height: 60px;
    --bottom-nav-height: 64px;

    /* Fraunces carries the personality in headings. Numbers stay in a neutral sans, because
       tabular figures are what a progress tracker actually lives on. */
    --font-display: "Fraunces", Georgia, "Times New Roman", serif;
    --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-mono: "SF Mono", "Cascadia Mono", Consolas, "Liberation Mono", monospace;
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--bg);
    /* A single warm glow at the top edge, as if the page were lit from above. Fixed so it does not
       travel with the content and turn into a gradient people notice. */
    background-image: radial-gradient(1100px 520px at 50% -220px, rgba(242, 182, 50, 0.05), transparent 70%);
    background-attachment: fixed;
    color: var(--text);
    font-family: var(--font);
    font-size: 15px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
    margin: 0;
    font-family: var(--font-display);
    font-weight: 650;
    /* Fraunces is already generous in width, so the tight tracking a grotesque needs would only
       jam it up. */
    letter-spacing: -0.005em;
    line-height: 1.2;
}

h1 { font-size: 1.7rem; }
h2 { font-size: 1.2rem; }
h3 { font-size: 1rem; }

p { margin: 0 0 0.75rem; }
p:last-child { margin-bottom: 0; }

a {
    color: var(--ember);
    text-decoration: none;
}

a:hover { text-decoration: underline; }

/* ---------- App shell ---------- */

.app {
    display: flex;
    min-height: 100vh;
}

.app__sidebar {
    display: none;
    flex-direction: column;
    width: var(--sidebar-width);
    flex: 0 0 var(--sidebar-width);
    background: var(--bg-elevated);
    border-right: 1px solid var(--border);
    position: sticky;
    top: 0;
    height: 100vh;
}

.app__main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    /* Room for the mobile bottom navigation. */
    padding-bottom: calc(var(--bottom-nav-height) + env(safe-area-inset-bottom, 0px));
}

.app__content {
    flex: 1 1 auto;
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding: 1rem;
}

@media (min-width: 900px) {
    .app__sidebar { display: flex; }
    .app__main { padding-bottom: 0; }
    .app__content { padding: 1.75rem 2rem 3rem; }
}

/* ---------- Branding ---------- */

.brand {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 1.125rem 1.25rem;
    border-bottom: 1px solid var(--border);
    text-decoration: none;
    color: var(--text);
}

.brand:hover { text-decoration: none; }

.brand__mark {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    /* Not a rounded square like every other app icon: one corner is cut square, so the mark reads
       as a stamped seal rather than a default. */
    border-radius: 9px 9px 9px 2px;
    background: linear-gradient(140deg, var(--gold), var(--ember));
    color: #201704;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.92rem;
    flex: 0 0 auto;
}

.brand__name {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.005em;
}

.brand__tagline {
    display: block;
    font-size: 0.7rem;
    color: var(--text-faint);
    font-weight: 500;
    letter-spacing: 0;
}

/* ---------- Navigation ---------- */

.nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 0.75rem;
    overflow-y: auto;
    flex: 1 1 auto;
}

.nav__section {
    padding: 1rem 0.75rem 0.375rem;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-faint);
}

.nav__link {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    font-weight: 500;
    font-size: 0.9rem;
    text-decoration: none;
    transition: background 0.12s, color 0.12s;
}

.nav__link:hover {
    background: var(--surface-hover);
    color: var(--text);
    text-decoration: none;
}

/* Selection is gold everywhere, so it never competes with a feature accent for the same job. */
.nav__link.active {
    background: var(--gold-wash);
    color: var(--gold);
}

.nav__link svg {
    width: 17px;
    height: 17px;
    flex: 0 0 auto;
    color: var(--accent, inherit);
}

.nav__link.active svg { color: inherit; }

.nav__badge {
    margin-left: auto;
    min-width: 19px;
    height: 19px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--rust);
    color: #fff;
    font-size: 0.68rem;
    font-weight: 700;
    display: grid;
    place-items: center;
}

.nav__footer {
    padding: 0.75rem;
    border-top: 1px solid var(--border);
}

/* Bottom navigation, phones only. */
.bottom-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 40;
    display: flex;
    height: calc(var(--bottom-nav-height) + env(safe-area-inset-bottom, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: rgba(25, 21, 16, 0.96);
    backdrop-filter: blur(12px);
    border-top: 1px solid var(--border);
}

.bottom-nav__link {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    color: var(--text-faint);
    font-size: 0.66rem;
    font-weight: 600;
    text-decoration: none;
    position: relative;
}

.bottom-nav__link svg { width: 21px; height: 21px; color: var(--accent, inherit); }

.bottom-nav__link.active { color: var(--gold); }
.bottom-nav__link.active svg { color: inherit; }
.bottom-nav__link:hover { text-decoration: none; }

.bottom-nav__dot {
    position: absolute;
    top: 8px;
    right: 50%;
    margin-right: -16px;
    width: 7px;
    height: 7px;
    border-radius: 999px;
    background: var(--rust);
}

@media (min-width: 900px) {
    .bottom-nav { display: none; }
}

/* ---------- Top bar ---------- */

.topbar {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    height: var(--header-height);
    padding: 0 1rem;
    background: rgba(18, 16, 12, 0.9);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--border);
}

.topbar__brand { display: flex; }

@media (min-width: 900px) {
    .topbar { padding: 0 2rem; }
    .topbar__brand { display: none; }
}

.topbar__spacer { flex: 1 1 auto; }

/* ---------- Page furniture ---------- */

.page-header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.75rem 1rem;
    margin-bottom: 1.25rem;
}

.page-header__text { min-width: 0; flex: 1 1 260px; }

.page-header__subtitle {
    margin: 0.2rem 0 0;
    color: var(--text-muted);
    font-size: 0.9rem;
}

.page-header__actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.section {
    margin-bottom: 1.75rem;
}

.section__header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
}

.section__header h2 { flex: 1 1 auto; min-width: 0; }

/* ---------- Feature accents ----------

  Challenges, friends and goals share one restrained brass tone. Giving each its own hue turned the
  dashboard into a swatch board and pulled attention away from the numbers, which are the only thing
  on the page worth being loud. Colour is spent on meaning instead: gold for progress, moss for
  gains, rust for losses.
*/

.accent--challenges,
.accent--friends,
.accent--goals,
.accent--journey,
.accent--pets {
    --accent: var(--brass);
    --accent-wash: var(--brass-wash);
}

.section__icon {
    flex: 0 0 auto;
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border-radius: 9px;
    background: var(--accent-wash, var(--surface-hover));
    color: var(--accent, var(--text-muted));
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent, transparent) 24%, transparent);
}

.section__icon svg { width: 16px; height: 16px; }

.section__icon--large { width: 38px; height: 38px; border-radius: 11px; }
.section__icon--large svg { width: 20px; height: 20px; }

.page-header .section__icon { align-self: center; }

/* ---------- Cards ---------- */

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1.125rem;
}

.card--flush { padding: 0; overflow: hidden; }

.card--interactive {
    transition: border-color 0.12s, background 0.12s;
}

.card--interactive:hover {
    border-color: var(--border-strong);
    background: var(--surface-hover);
    text-decoration: none;
}

.card__header {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    margin-bottom: 0.875rem;
}

.card__title {
    font-family: var(--font-display);
    font-size: 1rem;
    font-weight: 650;
    flex: 1 1 auto;
    min-width: 0;
}

.card__label {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-faint);
}

.card__footer {
    margin-top: 0.875rem;
    padding-top: 0.875rem;
    border-top: 1px solid var(--border);
}

/* ---------- Grids ---------- */

.grid {
    display: grid;
    gap: 0.875rem;
}

.grid--stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.grid--two { grid-template-columns: minmax(0, 1fr); }
.grid--three { grid-template-columns: minmax(0, 1fr); }

@media (min-width: 640px) {
    .grid--stats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .grid--three { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 900px) {
    .grid--two { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); }
    .grid--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ---------- Stat tiles ---------- */

.stat {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0.875rem 1rem;
}

.stat__label {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-faint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.stat__value {
    margin-top: 0.25rem;
    font-size: 1.4rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

.stat__value--gold { color: var(--gold); }

.stat__meta {
    margin-top: 0.1rem;
    font-size: 0.78rem;
    color: var(--text-muted);
}

/* ---------- Buttons ---------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    padding: 0.5rem 0.95rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    transition: background 0.12s, border-color 0.12s, opacity 0.12s;
    white-space: nowrap;
}

.btn:hover {
    background: var(--surface-hover);
    text-decoration: none;
}

.btn:disabled,
.btn[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
}

.btn--primary {
    background: var(--gold);
    border-color: var(--gold);
    color: #201704;
}

.btn--primary:hover { background: #ffc846; }

.btn--danger {
    color: var(--rust-tint);
    border-color: rgba(196, 80, 63, 0.45);
}

.btn--danger:hover { background: var(--rust-wash); }

.btn--ghost {
    background: transparent;
    border-color: transparent;
    color: var(--text-muted);
}

.btn--ghost:hover { background: var(--surface-hover); color: var(--text); }

.btn--small { padding: 0.3rem 0.6rem; font-size: 0.8rem; }
.btn--block { width: 100%; }

.btn svg { width: 15px; height: 15px; }

/* ---------- Forms ---------- */

.field {
    display: block;
    margin-bottom: 0.875rem;
}

.field__label {
    display: block;
    margin-bottom: 0.3rem;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-muted);
}

.field__hint {
    margin-top: 0.3rem;
    font-size: 0.78rem;
    color: var(--text-faint);
}

.input,
.select {
    width: 100%;
    padding: 0.55rem 0.75rem;
    background: var(--surface-sunken);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    color: var(--text);
    font-family: inherit;
    font-size: 0.9rem;
}

.input:focus,
.select:focus {
    outline: none;
    border-color: var(--gold-dim);
    box-shadow: 0 0 0 3px var(--gold-wash);
}

.input::placeholder { color: var(--text-faint); }

.form-row {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.form-row > .input { flex: 1 1 200px; width: auto; }

/* ---------- Messages ---------- */

.alert {
    display: flex;
    gap: 0.6rem;
    padding: 0.7rem 0.875rem;
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
    margin-bottom: 1rem;
    border: 1px solid transparent;
}

.alert--error {
    background: var(--rust-wash);
    border-color: rgba(196, 80, 63, 0.38);
    color: var(--rust-tint);
}

.alert--success {
    background: var(--moss-wash);
    border-color: rgba(157, 179, 92, 0.35);
    color: var(--moss-tint);
}

/* Nudges and hints. Deliberately the quietest of the three: it is information, not an event. */
.alert--info {
    background: var(--brass-wash);
    border-color: rgba(164, 144, 122, 0.3);
    color: #d9c9b1;
}

.alert--dismissible {
    align-items: flex-start;
}

.alert--dismissible .alert__text {
    flex: 1 1 auto;
    min-width: 0;
}

.alert__dismiss {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin: -0.15rem -0.25rem -0.15rem 0.25rem;
    padding: 0.25rem;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: inherit;
    opacity: 0.55;
    cursor: pointer;
}

.alert__dismiss svg {
    width: 14px;
    height: 14px;
}

.alert__dismiss:hover,
.alert__dismiss:focus-visible {
    opacity: 1;
    background: rgba(255, 255, 255, 0.06);
}

/* A nudge that opens what it names. Rendered as a button, so undo the browser chrome and add
   just enough affordance — a chevron and a hover lift — without turning information into noise. */
.alert--clickable {
    width: 100%;
    align-items: center;
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color 120ms ease, background 120ms ease;
}

.alert--clickable:hover,
.alert--clickable:focus-visible {
    border-color: rgba(164, 144, 122, 0.6);
    background: rgba(164, 144, 122, 0.16);
}

.alert--clickable .alert__text { flex: 1 1 auto; min-width: 0; }

.alert--clickable svg {
    width: 14px;
    height: 14px;
    flex: 0 0 auto;
    opacity: 0.6;
}

.alert--clickable:hover svg { opacity: 1; }

.validation-message {
    display: block;
    margin-top: 0.3rem;
    color: var(--rust-tint);
    font-size: 0.8rem;
}

/* ---------- Badges and pills ---------- */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    background: var(--surface-hover);
    color: var(--text-muted);
    border: 1px solid var(--border);
    white-space: nowrap;
}

.badge svg { width: 12px; height: 12px; flex: 0 0 auto; }

.badge--gold { background: var(--gold-wash); color: var(--gold); border-color: var(--gold-dim); }
.badge--moss { background: var(--moss-wash); color: var(--moss-tint); border-color: rgba(157, 179, 92, 0.32); }
.badge--brass { background: var(--brass-wash); color: var(--brass); border-color: rgba(164, 144, 122, 0.32); }
.badge--ember { background: var(--ember-wash); color: var(--ember); border-color: rgba(226, 112, 58, 0.32); }
.badge--rust { background: var(--rust-wash); color: var(--rust-tint); border-color: rgba(196, 80, 63, 0.32); }

/* Takes whichever accent the surrounding block owns, so a badge never has to restate the colour. */
.badge--accent {
    background: var(--accent-wash, var(--surface-hover));
    color: var(--accent, var(--text-muted));
    border-color: color-mix(in srgb, var(--accent, transparent) 30%, transparent);
}

.delta { font-variant-numeric: tabular-nums; font-weight: 650; }
.delta--up { color: var(--moss); }
.delta--flat { color: var(--text-faint); }

/* ---------- Progress ---------- */

.progress {
    height: 7px;
    border-radius: 999px;
    background: var(--surface-sunken);
    overflow: hidden;
}

.progress__bar {
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--gold-dim), var(--gold));
    transition: width 0.4s ease;
}

.progress--thin { height: 4px; }

.progress__bar--moss { background: linear-gradient(90deg, #55662c, var(--moss)); }

.progress-meta {
    display: flex;
    justify-content: space-between;
    gap: 0.75rem;
    margin-top: 0.35rem;
    font-size: 0.78rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

/* ---------- Tables ---------- */

.table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}

.table th {
    padding: 0.6rem 0.875rem;
    text-align: left;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-faint);
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
    background: var(--surface-sunken);
}

.table td {
    padding: 0.6rem 0.875rem;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background: var(--surface-hover); }

/* Both selectors are needed: ".table th" sets a left alignment that a bare ".table__number" loses
   to on specificity, which left the headers sitting away from the numbers beneath them. */
.table th.table__number,
.table td.table__number {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.table__row--clickable { cursor: pointer; }

.table__row--highlight {
    background: var(--gold-wash);
}

.table__row--highlight:hover { background: rgba(242, 182, 50, 0.18); }

.boss-kills-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 0.75rem;
}

.boss-kill-card {
    text-align: left;
    width: 100%;
    cursor: pointer;
    background: var(--surface);
    border: 1px solid var(--border);
    color: inherit;
}

.boss-kill-card:hover {
    border-color: var(--border-strong);
    background: var(--surface-hover);
}

.boss-kill-card__head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 0.5rem;
}

.boss-kill-card__meta {
    margin-top: 0.45rem;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    color: var(--text-muted);
    font-size: 0.8rem;
}

.overlay {
    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgba(0, 0, 0, 0.58);
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 1rem;
}

.modal-card {
    width: min(920px, 100%);
    max-height: min(84vh, 1000px);
    overflow: hidden;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    background: var(--bg-elevated);
    box-shadow: var(--shadow);
    display: flex;
    flex-direction: column;
}

.modal-card__header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.9rem 1rem;
    border-bottom: 1px solid var(--border);
}

.modal-card__body {
    overflow: auto;
    padding: 0.9rem 1rem;
}

.drop-prices {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.35rem;
}

.compare-table th,
.compare-table td {
    padding: 0.7rem 1rem;
}

.compare-table tbody tr:nth-child(even) {
    background: rgba(255, 255, 255, 0.02);
}

.compare-table__value {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.15rem;
}

.compare-table__player-col {
    width: 9.5rem;
}

.compare-table__label-col {
    width: 8rem;
}

.compare-table__gap-col {
    width: 6.5rem;
}

/* ---------- Skill grid ---------- */

.skills {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
    gap: 0.5rem;
}

.skill {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 0.6rem 0.7rem;
}

.skill--maxed { border-color: var(--gold-dim); }

.skill__top {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
}

.skill__name {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-muted);
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.skill__level {
    font-size: 1rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.skill__level--maxed { color: var(--gold); }

.skill__xp {
    font-size: 0.72rem;
    color: var(--text-faint);
    font-variant-numeric: tabular-nums;
    margin-bottom: 0.35rem;
}

.skill__gain {
    font-size: 0.72rem;
    font-weight: 650;
    color: var(--moss);
    margin-top: 0.3rem;
}

/* ---------- Trend chart ---------- */

.chart {
    position: relative;
    display: flex;
    align-items: flex-end;
    gap: 2px;
    height: 120px;
    padding-top: 0.5rem;
}

/* Horizontal marker for the average day, laid over the bars. */
.chart__average {
    position: absolute;
    left: 0;
    right: 0;
    height: 0;
    border-top: 1px dashed rgba(255, 255, 255, 0.8);
    pointer-events: none;
}

.chart__col {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    align-items: flex-end;
    height: 100%;
    border-radius: 2px 2px 0 0;
    background: var(--surface-sunken);
    position: relative;
}

.chart__fill {
    width: 100%;
    border-radius: 2px 2px 0 0;
    background: linear-gradient(180deg, var(--gold), var(--gold-dim));
    min-height: 2px;
    transition: height 0.3s ease;
}

.chart__fill--empty { background: var(--border); min-height: 2px; }

.chart__axis {
    display: flex;
    justify-content: space-between;
    margin-top: 0.4rem;
    font-size: 0.7rem;
    color: var(--text-faint);
}

/* ---------- Player identity ---------- */

.player {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    min-width: 0;
}

.avatar {
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    border-radius: 999px;
    background: var(--surface-hover);
    border: 1px solid var(--border-strong);
    color: var(--text-muted);
    font-weight: 700;
    font-size: 0.85rem;
    flex: 0 0 auto;
    text-transform: uppercase;
}

.avatar--large { width: 56px; height: 56px; font-size: 1.2rem; }
.avatar--gold { background: var(--gold-wash); border-color: var(--gold-dim); color: var(--gold); }

.player__name {
    font-weight: 650;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.player__meta {
    font-size: 0.78rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ---------- Misc ---------- */

.muted { color: var(--text-muted); }
.faint { color: var(--text-faint); }
.mono { font-family: var(--font-mono); }
.numeric { font-variant-numeric: tabular-nums; }
.small { font-size: 0.8rem; }
.center { text-align: center; }
.nowrap { white-space: nowrap; }

.stack { display: flex; flex-direction: column; gap: 0.875rem; }
.stack--tight { gap: 0.5rem; }
.row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.row--between { justify-content: space-between; }
.spacer { flex: 1 1 auto; }

.empty {
    padding: 2rem 1rem;
    text-align: center;
    color: var(--text-muted);
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius);
}

.empty__title {
    font-family: var(--font-display);
    font-weight: 650;
    color: var(--text);
    margin-bottom: 0.25rem;
}

.divider { height: 1px; background: var(--border); margin: 1rem 0; }

.tabs {
    display: flex;
    gap: 0.25rem;
    padding: 0.25rem;
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    overflow-x: auto;
}

.tabs__tab {
    padding: 0.35rem 0.75rem;
    border: none;
    background: transparent;
    border-radius: 4px;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

.tabs__tab:hover { color: var(--text); }
.tabs__tab.active { background: var(--surface-hover); color: var(--text); }

.streak {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    color: var(--gold);
    font-weight: 700;
    font-size: 0.85rem;
}

/* ---------- Journey ----------

  A step is one card, and the run of them is a path. The step number is drawn as a marker rather
  than written as "Step 4", because the count of them behind you is the whole reward.
*/

.journey-step__number {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    border-radius: 999px;
    background: var(--gold-wash);
    border: 1px solid var(--gold-dim);
    color: var(--gold);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.9rem;
    font-variant-numeric: tabular-nums;
}

.journey-step--done .journey-step__number {
    background: var(--moss-wash);
    border-color: rgba(157, 179, 92, 0.32);
    color: var(--moss-tint);
}

.journey-step__reason {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--gold);
    margin-bottom: 0.15rem;
}

.journey-step--done .journey-step__reason { color: var(--text-faint); }

.journey-step__members {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    margin-top: 0.875rem;
}

.journey-member {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.2rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface-sunken);
    color: var(--text-muted);
    font-size: 0.76rem;
    font-weight: 600;
    max-width: 100%;
    overflow: hidden;
}

.journey-member svg { width: 12px; height: 12px; flex: 0 0 auto; }

.journey-member--done {
    background: var(--moss-wash);
    border-color: rgba(157, 179, 92, 0.32);
    color: var(--moss-tint);
}

/* The teaser for what comes next. Unreadable on purpose: knowing that there is another step is
   the incentive, and knowing what it is would let somebody skip ahead to the easy one. */
.journey-next {
    margin-top: 0.875rem;
    border-style: dashed;
    background: var(--surface-sunken);
}

.journey-next__label {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-faint);
    margin-bottom: 0.5rem;
}

.journey-next__blur {
    filter: blur(4px);
    opacity: 0.55;
    user-select: none;
}

.journey-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.75rem;
}

/* Reads as on until turned off, so the resting state of a journey is everything in play. */
.journey-filter {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.7rem;
    background: var(--moss-wash);
    border: 1px solid rgba(157, 179, 92, 0.32);
    border-radius: 999px;
    color: var(--moss-tint);
    font-family: inherit;
    font-size: 0.82rem;
    cursor: pointer;
}

.journey-filter:hover { border-color: var(--moss-tint); }

.journey-filter svg { width: 13px; height: 13px; }

.journey-filter--off {
    background: var(--rust-wash);
    border-color: rgba(196, 80, 63, 0.32);
    color: var(--rust-tint);
    text-decoration: line-through;
}

.journey-filter--off:hover { border-color: var(--rust-tint); }

.journey-filter:disabled { opacity: 0.5; cursor: not-allowed; }

/* The dashboard's compact cards: journeys and challenges each become one small card so several
   sit on one row, with the tall detail card behind a click. Everything inside is a span because
   the card itself is a button, and buttons only permit phrasing content. */

.grid--minis {
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}

.mini-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.45rem;
    padding: 0.8rem 0.9rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    font-family: inherit;
    font-size: 0.875rem;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.12s, background 0.12s;
}

.mini-card:hover {
    border-color: var(--border-strong);
    background: var(--surface-hover);
}

.mini-card__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.mini-card__name {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-faint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mini-card__name--urgent { color: var(--gold); }

.mini-card__title {
    font-family: var(--font-display);
    font-weight: 650;
    font-size: 0.95rem;
    line-height: 1.3;
    /* Two lines at most, so every card on the row stays the same manageable height. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.mini-card .progress { display: block; margin-top: auto; }
.mini-card .progress__bar { display: block; }

.mini-card__meta {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ---------- Modal ----------

  A bottom sheet on phones, where thumbs live, and a centred dialog once there is room. */

.modal {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding: 1rem;
    background: rgba(10, 8, 5, 0.62);
    backdrop-filter: blur(3px);
}

@media (min-width: 640px) {
    .modal { align-items: center; }
}

.modal__dialog {
    width: 100%;
    max-width: 560px;
    max-height: calc(100vh - 2rem);
    overflow-y: auto;
    padding: 1rem 1.125rem 1.125rem;
    background: var(--bg-elevated);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow);
}

.modal__header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.875rem;
}

.modal__footer {
    margin-top: 0.875rem;
    padding-top: 0.875rem;
    border-top: 1px solid var(--border);
}

/* Blazor's own error UI, restyled to match. */
#blazor-error-ui {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    display: none;
    padding: 0.75rem 1.25rem;
    background: var(--rust);
    color: #fff;
    font-size: 0.875rem;
    text-align: center;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    float: right;
    font-weight: 700;
}

.blazor-error-boundary {
    padding: 1rem;
    background: var(--rust-wash);
    border: 1px solid var(--rust);
    border-radius: var(--radius);
    color: var(--rust-tint);
}

.loading {
    display: inline-block;
    width: 15px;
    height: 15px;
    border: 2px solid var(--border-strong);
    border-top-color: var(--gold);
    border-radius: 999px;
    animation: spin 0.7s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}
