/* The page ground comes from theme.css. A hardcoded colour here would be wrong
   in one of the two flavors, which the design system counts as a defect.
   The rules below the page width still belong to the screens not yet migrated. */
html, body {
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-sans);
}

/* A modal dialog stops pointers reaching the page, not the wheel scrolling
   it: while one is open, the page behind it holds still. */
html:has(dialog:modal) {
    overflow: hidden;
}

/* The page width, shared by the top bar and the content under it so their
   edges line up on every frame. This file is loaded by public pages, which
   mirror under dir="rtl", so it names no side: logical properties only. */
.shell {
    margin-inline: auto;
    max-inline-size: 1200px;
    padding-inline: 1.25rem;
}

/* The site name at the start of every bar (BrandLink), led by the mark. The
   mark keeps its Latte colors in both flavors: it is one identity, not a
   themed control. */
.brand {
    align-items: center;
    color: var(--text);
    display: inline-flex;
    font-size: 1.15rem;
    font-weight: 800;
    letter-spacing: -.01em;
    text-decoration: none;
}

/* The brand is the way home, so it answers the pointer like any link: the
   name takes the accent, and the mark hops on hover and squashes on press.
   Reboot's a:hover outranks a single class, which this rule also settles. */
.brand:hover {
    color: var(--accent-text);
}

.brand-mark {
    block-size: 1.75rem;
    inline-size: 1.75rem;
    margin-inline-end: .5rem;
}

.brand:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
    .brand {
        transition: color .18s ease;
    }

    /* The mark pivots on its paws, so the squash reads as landing. */
    .brand-mark {
        transform-origin: 50% 85%;
        transition: transform .35s cubic-bezier(.34, 1.56, .64, 1);
    }

    .brand:hover .brand-mark {
        animation: brand-hop .5s cubic-bezier(.34, 1.56, .64, 1);
    }

    .brand:active .brand-mark {
        animation: none;
        transform: scale(1.18, .78);
        transition-duration: .07s;
    }
}

@keyframes brand-hop {
    35% {
        transform: translateY(-6px) scale(.96, 1.06);
    }

    70% {
        transform: translateY(0) scale(1.06, .94);
    }
}

/* A link inside prose, wherever a page has not styled its own. theme.css
   re-points --accent-text to raw mauve in Mocha, so the one declaration reads
   against either ground. Reboot's underline is what marks the link, and the two
   scoped rules that already colour a body link set no hover either, so this
   adds none. */
a {
    color: var(--accent-text);
}

.content {
    margin-inline: auto;
    max-inline-size: 1200px;
    padding-block: 2rem 4rem;
}

h1:focus {
    outline: none;
}

/* A card that is itself a link. The heading is the anchor and is stretched over
   the whole surface, so the card is one target and one focus stop and needs no
   button of its own. The idiom lives here rather than beside each card because
   a whole-surface link is a mechanism, not a decoration: what each card adds is
   how it lights up, which stays with the card. */
.link-card {
    position: relative;
}

.card-link {
    color: var(--text);
    text-decoration: none;
}

.card-link::after {
    content: "";
    inset: 0;
    position: absolute;
}

.link-card:hover .card-link {
    text-decoration: underline;
}

/* The ring belongs to the card, not to the anchor inside it. */
.card-link:focus-visible {
    outline: none;
}

/* The warning glyph is drawn before the text rather than painted at a fixed
   side of the box, so it stays at the inline start in either direction. */
.blazor-error-boundary {
    background: #b32121;
    color: white;
    padding: 1rem;
}

    .blazor-error-boundary::before {
        background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat center/contain;
        block-size: 1.6rem;
        content: "";
        display: inline-block;
        inline-size: 1.8rem;
        margin-inline-end: .9rem;
        vertical-align: middle;
    }

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* What a download address answers with instead of a file (DownloadUnavailable,
   DownloadQuotaSpent), and a report form instead of its answer
   (ReportLimitReached): one message, read in one place, a narrow column in the
   middle of the page, the way a visitor who expected something else reads what
   happened instead. Global because the pages share it and scoped CSS cannot be
   shared. */
.download-notice {
  display: grid;
  gap: 1rem;
  margin: 4rem auto;
  max-width: 36rem;
  padding: 0 1.25rem;
}

.download-notice h1 {
  font-size: 1.6rem;
  margin: 0;
}

.download-notice p {
  color: var(--text-muted);
  margin: 0;
}

.download-notice a {
  color: var(--accent-text);
}

/* A record's facts as labelled pairs: the game page's details and what the
   download confirmation page is about to send the visitor to. Nothing here
   names a side; the labels are the shared .section-label. */
.facts {
  display: grid;
  gap: .9rem;
  margin: 0;
}

.facts dd {
  font-size: .92rem;
  margin: .35rem 0 0;
}

/* Side by side wherever the width allows. */
.facts-columns {
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
}

/* The tints a game's cover is drawn on, two of the theme's own hues, legible in
   Latte and in Mocha alike. One is the game's for good (GameCard.CoverTint), so
   a game is the same colour on every page that draws its cover — a catalog
   card, a tile of the home page — and in both flavors; the frame that paints
   them reads --cover-from and --cover-to. */
.cover-0 {
  --cover-from: var(--ctp-mauve);
  --cover-to: var(--ctp-red);
}

.cover-1 {
  --cover-from: var(--ctp-green);
  --cover-to: var(--ctp-yellow);
}

.cover-2 {
  --cover-from: var(--ctp-yellow);
  --cover-to: var(--ctp-red);
}

.cover-3 {
  --cover-from: var(--ctp-mauve);
  --cover-to: var(--ctp-green);
}
