/* The Friends, History, Shop and Events screens, and the parts of the attack and raid screens that they share.
   index.html loads the stylesheets in a fixed order (Game/docs/ui-style.md, "Stylesheets"). */

.rj-attack,
.rj-raid {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}

/* The attack and raid screens fill the shell's height, and the target's site takes the height the other rows leave
   (.rj-stage), so every structure and dig spot is on a 390 × 844 screen without scrolling. */
.rj-attack,
.rj-raid {
    min-height: 100%;
}

.rj-attack__title {
    margin: 0;
    font-size: 1.3rem;
    font-weight: 800;
}

.rj-attack__empty {
    margin: 0;
    color: var(--theme-text-muted, var(--ink-2));
}

/* The attack target picker shows the theme's mascot above an empty text and above Find a target. We draw the picker's
   mascot smaller, so the browser keeps Find a target on a 360 × 640 screen. */
.rj-attack__empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem 0;
    text-align: center;
}

.rj-attack__mascot {
    align-self: center;
    width: min(7rem, 35%);
    max-height: 22vh;
    height: auto;
    object-fit: contain;
    filter: drop-shadow(0 6px 8px rgba(0, 0, 0, 0.3));
}

.rj-attack__portrait {
    width: 3rem;
    height: 3rem;
}

.rj-attack__list {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.rj-spin__offer {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}

/* ---------------------------------------------------------------------------
   LiveOps events: the madness banner, the progress bar and the event panel (Game/docs/liveops-events.md). No animation,
   because Playwright waits for a button to stop moving before it taps it.
   --------------------------------------------------------------------------- */
.rj-madness {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.rj-madness__item {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0.6rem;
    padding: 0.5rem 0.75rem;
    border-radius: var(--r-card);
    border: 1px solid var(--theme-accent, var(--gold));
    background: color-mix(in srgb, var(--theme-accent, var(--gold)) 22%, transparent);
    color: var(--theme-text, var(--ink));
}

.rj-madness__item--attack { border-color: var(--theme-danger, var(--danger)); background: color-mix(in srgb, var(--theme-danger, var(--danger)) 20%, transparent); }

.rj-madness__name { font-weight: 800; }
.rj-madness__effect { font-weight: 700; }
.rj-madness__bets { font-size: 0.85rem; }
.rj-madness__timer { margin-left: auto; font-variant-numeric: tabular-nums; color: var(--theme-text-muted, var(--ink-3)); }

.rj-progress {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    text-decoration: none;
    color: var(--theme-text, var(--ink));
}

.rj-progress__event {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: 0.2rem 0.6rem;
    padding: 0.45rem 0.7rem;
    border-radius: var(--r-card);
    border: 1px solid color-mix(in srgb, var(--theme-text, white) 16%, transparent);
    background: var(--theme-surface, transparent);
}

.rj-progress__name { font-weight: 800; }

.rj-progress__bar {
    height: 0.6rem;
    border-radius: var(--r-pill);
    background: color-mix(in srgb, var(--theme-text, white) 16%, transparent);
    overflow: hidden;
}

.rj-progress__fill {
    display: block;
    height: 100%;
    border-radius: var(--r-pill);
    background: var(--theme-accent, var(--gold));
}

.rj-progress__text {
    grid-column: 1 / -1;
    color: var(--theme-text-muted, var(--ink-3));
}


.rj-home__badge {
    display: inline-block;
    min-width: 1.2rem;
    margin-left: 0.3rem;
    padding: 0 0.3rem;
    border-radius: var(--r-pill);
    background: var(--theme-accent, var(--gold));
    color: var(--theme-button-text, var(--on-gold));
    font-size: 0.75rem;
    text-align: center;
}

/* ===========================================================================
   The menu screens: Shop, Events, Friends and History (Game/docs/ui-style.md, "Menu screens"). Each screen is a column
   with MenuHeader on top (Home on a small panel, the title on a ribbon, the wallet bar) and the bottom navigation in a
   dock, which stays at the bottom of the screen while the content scrolls under it.
   =========================================================================== */
.rj-menu {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    min-height: 100%;
}

/* The dock holds the bottom navigation. It stays at the bottom of the screen, reaches into the shell's bottom padding
   and side gutters, and fades the content that scrolls under it into the theme's background. */
.rj-menu__dock {
    position: sticky;
    z-index: 5;
    bottom: calc(-1.25rem - var(--safe-b));
    margin: auto calc(-1 * var(--pad)) calc(-1.25rem - var(--safe-b));
    padding: 1.1rem var(--pad) calc(0.6rem + var(--safe-b));
    background: linear-gradient(180deg, transparent 0%, var(--theme-background, var(--ground)) 45%);
    pointer-events: none;
}

.rj-menu__dock .rj-bnav { pointer-events: auto; }

/* The bottom navigation marks the screen the player is on. */
.rj-shop .rj-bnav__item[data-testid="nav-shop"],
.rj-events-page .rj-bnav__item[data-testid="nav-events"],
.rj-friends .rj-bnav__item[data-testid="nav-friends"] {
    background: rgba(0, 0, 0, 0.22);
    box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
}

.rj-shop .rj-bnav__item[data-testid="nav-shop"] .rj-bnav__label,
.rj-events-page .rj-bnav__item[data-testid="nav-events"] .rj-bnav__label,
.rj-friends .rj-bnav__item[data-testid="nav-friends"] .rj-bnav__label { color: var(--ui-nav-active); }

.rj-menu-head {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
}

/* Home on the left, the ribbon in the middle, and an empty column on the right as wide as Home, so the ribbon stays in
   the middle of the screen. */
.rj-menu-head__row {
    display: grid;
    grid-template-columns: 3.4rem minmax(0, 1fr) 3.4rem;
    align-items: center;
    gap: 0.6rem;
}

.rj-menu-head__title {
    justify-self: center;
    max-width: calc(100% - 1.6rem);
    font-size: 1.5rem;
}

/* The router focuses the h1 after a navigation; the title is not a control. */
.rj-menu-head__title:focus { outline: none; }

/* An empty list: the theme's mascot and a speech bubble under it. */
.rj-menu-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.9rem;
    padding: 0.4rem 0;
}

.rj-menu-empty__mascot {
    width: min(9rem, 45%);
    height: auto;
    filter: drop-shadow(0 6px 8px rgba(0, 0, 0, 0.3));
}

.rj-menu-empty__text { max-width: 19rem; }

/* A framed card that is not a Panel component: the same frame as .rj-panel, for list rows and offer cards. */
.rj-friends__friend,
.rj-history__entry,
.rj-offer,
.rj-events__event {
    box-sizing: border-box;
    border: 3px solid var(--ui-panel-border);
    border-radius: var(--ui-radius-panel);
    background: linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-panel) 45%);
    box-shadow:
        inset 0 2px 0 rgba(255, 255, 255, 0.28),
        0 0 0 2px var(--ui-outline),
        0 5px 0 2px color-mix(in srgb, var(--ui-outline) 55%, transparent),
        0 10px 18px var(--ui-shadow);
    color: var(--ui-panel-ink);
}

/* An input on a panel: a white field with the dark outline and an inner shadow. */
.rj-friends__input,
.rj-welcome__name {
    box-sizing: border-box;
    min-width: 0;
    min-height: 3rem;
    padding: 0 0.85rem;
    border: var(--ui-border) solid var(--ui-outline);
    border-radius: 0.85rem;
    background: #ffffff;
    box-shadow: inset 0 3px 0 rgba(0, 0, 0, 0.12);
    color: #1d1a16;
    font: inherit;
    font-size: 1.1rem;
    font-weight: 900;
}

.rj-friends__input:focus,
.rj-welcome__name:focus {
    outline: none;
    box-shadow: inset 0 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 3px var(--ui-primary-light);
}

/* A message chip on a panel: white text on green for good news and on red for a refusal. */
.rj-friends__message,
.rj-friends__copied {
    margin: 0;
    padding: 0.4rem 0.75rem;
    border: 2px solid var(--ui-outline);
    border-radius: 0.8rem;
    background: var(--ui-plus);
    color: #ffffff;
    font-weight: 900;
    line-height: 1.25;
    text-align: center;
    text-shadow: 0 1px 0 rgba(0, 0, 0, 0.35);
    animation: rj-ui-pop 0.35s var(--ui-pop) both;
}

.rj-friends__message.is-bad { background: var(--ui-danger); }

/* ---------------------------------------------------------------------------
   Friends
   --------------------------------------------------------------------------- */
.rj-friends__card {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    text-align: center;
}

.rj-friends__code {
    padding: 0.4rem 0.5rem 0.5rem;
    border-radius: 0.85rem;
    background: rgba(0, 0, 0, 0.22);
    box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.3);
    color: #ffffff;
    font-family: var(--ui-font-display);
    font-size: 2rem;
    font-weight: 400;
    letter-spacing: 0.08em;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
    -webkit-text-stroke: 0.18em var(--ui-outline);
    paint-order: stroke fill;
    text-shadow: 0 0.08em 0 var(--ui-outline);
    user-select: all;
}

.rj-friends__link {
    font-size: 0.75rem;
    font-weight: 800;
    color: var(--ui-panel-ink-2);
    word-break: break-all;
    user-select: all;
}

.rj-friends__share-icon {
    width: 1.35em;
    height: 1.35em;
}

/* The clipboard refused the invite link: the line and the link in a read-only field. */
.rj-friends__copy-by-hand {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    font-weight: 800;
}

.rj-friends__link-field {
    width: 100%;
    font-size: 0.8rem;
}

.rj-friends__add {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.8rem 0.9rem 0.6rem;
}

.rj-friends__label {
    font-family: var(--ui-font-display);
    font-size: 1.1rem;
    font-weight: 400;
    color: var(--ui-panel-ink);
}

.rj-friends__add-row {
    display: flex;
    gap: 0.5rem;
}

.rj-friends__add-row .rj-friends__input {
    flex: 1;
    letter-spacing: 0.06em;
}

.rj-friends__add-button { flex: none; }

.rj-friends__list {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.rj-friends__friend {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.5rem 0.7rem;
    border-radius: 1.05rem;
}

.rj-friends__portrait,
.rj-history__portrait {
    width: 3.1rem;
    height: 3.1rem;
    background: color-mix(in srgb, var(--ui-panel-ink) 14%, transparent);
    box-shadow: 0 0 0 2.5px var(--ui-outline), 0 3px 0 2.5px var(--ui-outline);
}

.rj-friends__name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: var(--ui-font-display);
    font-size: 1.2rem;
    font-weight: 400;
}

/* The friend's site on a small ribbon-coloured chip. */
.rj-friends__site {
    flex: none;
    padding: 0.15rem 0.6rem 0.2rem;
    border: 2px solid var(--ui-outline);
    border-radius: 999px;
    background: linear-gradient(180deg, var(--ui-ribbon-light), var(--ui-ribbon));
    box-shadow: 0 2px 0 var(--ui-outline);
    color: #ffffff;
    font-family: var(--ui-font-display);
    font-size: 0.85rem;
    font-weight: 400;
    -webkit-text-stroke: 0.16em var(--ui-outline);
    paint-order: stroke fill;
}

/* The code card and the add form fill most of the first screen, and the bottom navigation's dock covers the bottom of
   it, so the page draws the speech bubble above the mascot, with its tail under it, and keeps the mascot small. The
   player then sees the text without a scroll, at 360 × 640 and at 390 × 844 (the art director found the bubble under
   the dock at 390 × 844 on 2026-10-15). */
.rj-friends__empty-state { flex-direction: column-reverse; gap: 0.7rem; }
.rj-friends__empty-state .rj-tip::after { top: auto; bottom: -0.35rem; }
.rj-friends__mascot { max-height: 22vh; width: auto; object-fit: contain; }

@media (max-height: 700px) {
    .rj-friends__mascot { max-height: 18vh; }
    .rj-friends.rj-menu { gap: 0.7rem; }
    .rj-friends__code { padding: 0.2rem 0.5rem 0.3rem; font-size: 1.7rem; }
}

/* ---------------------------------------------------------------------------
   History: one card per attack or raid, with the attacker's portrait, the kind's symbol on it, what happened, and
   Revenge.
   --------------------------------------------------------------------------- */
.rj-history__list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.rj-history__entry {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.7rem;
    padding: 0.6rem 0.6rem 0.6rem 0.75rem;
    border-radius: 1.05rem;
}

/* A stripe on the left edge in the kind's colour: red for a hit, the ribbon colour for a raid, green for a blocked attack. */
.rj-history__entry::before {
    content: "";
    position: absolute;
    top: 0.55rem;
    bottom: 0.55rem;
    left: -3px;
    width: 5px;
    border-radius: 0 4px 4px 0;
    background: var(--ui-danger);
}

.rj-history__entry.is-raid::before    { background: var(--ui-ribbon); }
.rj-history__entry.is-blocked::before { background: var(--ui-plus); }

.rj-history__who {
    position: relative;
    display: block;
}

.rj-history__kind {
    position: absolute;
    right: -0.55rem;
    bottom: -0.45rem;
    width: 1.75rem;
    height: 1.75rem;
    object-fit: contain;
    filter: drop-shadow(0 2px 0 var(--ui-outline)) drop-shadow(0 2px 3px rgba(0, 0, 0, 0.35));
}

.rj-history__body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.2rem;
}

.rj-history__name {
    font-family: var(--ui-font-display);
    font-size: 1.1rem;
    font-weight: 400;
}

.rj-history__text {
    font-weight: 800;
    line-height: 1.25;
}

/* The coins a raid took, on a red chip. */
.rj-history__coins {
    padding: 0.1rem 0.55rem 0.15rem;
    border: 2px solid var(--ui-outline);
    border-radius: 999px;
    background: var(--ui-danger);
    color: #ffffff;
    font-family: var(--ui-font-display);
    font-size: 0.9rem;
    font-weight: 400;
    font-variant-numeric: tabular-nums;
    -webkit-text-stroke: 0.15em var(--ui-outline);
    paint-order: stroke fill;
}

.rj-history__when {
    font-size: 0.75rem;
    font-weight: 800;
    color: var(--ui-panel-ink-2);
}

.rj-history__revenge-mark {
    display: inline-block;
    margin-left: 0.35rem;
    padding: 0 0.4rem;
    border-radius: 999px;
    background: var(--ui-danger);
    color: #ffffff;
    font-weight: 900;
}

.rj-history__revenge {
    padding: 0.2rem 0.6rem;
    font-size: 0.95rem;
}

/* ---------------------------------------------------------------------------
   The shop and the offer cards (Game/docs/offers.md): hero cards for the featured and out-of-spins offers, with their
   heading on a ribbon over the card's top edge, and a row of tiles for the spin packs.
   --------------------------------------------------------------------------- */
.rj-shop__section {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}

/* A plain section heading (the catalogue's, and the spin screen's out-of-spins line): display text with the outline. */
.rj-shop__heading:not(.rj-ribbon) {
    margin: 0;
    color: #ffffff;
    font-family: var(--ui-font-display);
    font-size: 1.2rem;
    font-weight: 400;
    line-height: 1.15;
    -webkit-text-stroke: 0.18em var(--ui-outline);
    paint-order: stroke fill;
    text-shadow: 0 0.08em 0 var(--ui-outline);
}

/* A hero section's ribbon sits over the top edge of its card. */
.rj-shop__section--hero > .rj-shop__heading {
    position: relative;
    z-index: 2;
    align-self: center;
    max-width: calc(100% - 2.6rem);
    margin-bottom: -1.5rem;
    font-size: 1.1rem;
    white-space: normal;
}

.rj-shop__grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.6rem;
    /* Room above the tiles for the best-value ribbon. */
    padding-top: 0.55rem;
}

.rj-shop__notice {
    margin: 0;
    font-size: 0.78rem;
    font-weight: 800;
    color: var(--theme-text, var(--ink));
    text-align: center;
}

/* The purchase message: a green or red toast with the close button. */
.rj-shop__message {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem 0.55rem 0.3rem 0.9rem;
    border: var(--ui-border) solid var(--ui-outline);
    border-radius: 1rem;
    background: linear-gradient(180deg, var(--ui-plus-light) 0%, var(--ui-plus) 55%);
    box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.35), 0 4px 0 var(--ui-outline);
    color: #ffffff;
    font-weight: 900;
    line-height: 1.25;
    text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
    animation: rj-ui-pop 0.35s var(--ui-pop) both;
}

.rj-shop__message.is-failed { background: linear-gradient(180deg, var(--ui-danger-light) 0%, var(--ui-danger) 55%); }
.rj-shop__message-text { flex: 1; padding-bottom: 0.2rem; }

.rj-offer {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    padding: 0.55rem 0.45rem 0.45rem;
    text-align: center;
}

.rj-offer__name {
    margin: 0;
    color: #ffffff;
    font-family: var(--ui-font-display);
    font-size: 0.95rem;
    font-weight: 400;
    line-height: 1.05;
    -webkit-text-stroke: 0.18em var(--ui-outline);
    paint-order: stroke fill;
    text-shadow: 0 0.08em 0 var(--ui-outline);
}

/* A tile keeps the name on two lines' height, so the art and the buttons of the three tiles line up. */
.rj-offer--catalogue .rj-offer__name {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 2.1em;
}

.rj-offer__art-box {
    position: relative;
    width: 88%;
    aspect-ratio: 1;
    border-radius: 0.8rem;
    background: radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--ui-primary-light) 55%, transparent) 0%, transparent 68%);
}

.rj-offer__art {
    width: 100%;
    height: 100%;
    object-fit: contain;
    filter: drop-shadow(0 4px 5px rgba(0, 0, 0, 0.35));
}

/* The pack's size on a chip at the bottom of its art. */
.rj-offer__size {
    position: absolute;
    left: 50%;
    bottom: -0.2rem;
    transform: translateX(-50%);
    min-width: 2.4rem;
    padding: 0.05rem 0.5rem 0.1rem;
    border: 2px solid var(--ui-outline);
    border-radius: 0.6rem;
    background: linear-gradient(180deg, var(--ui-ribbon-light), var(--ui-ribbon) 60%);
    box-shadow: 0 2px 0 var(--ui-outline);
    color: #ffffff;
    font-family: var(--ui-font-display);
    font-size: 1.05rem;
    font-weight: 400;
    text-align: center;
    font-variant-numeric: tabular-nums;
    -webkit-text-stroke: 0.16em var(--ui-outline);
    paint-order: stroke fill;
}

.rj-offer__contents {
    margin: 0;
    padding: 0;
    list-style: none;
    font-family: var(--ui-font-display);
    font-size: 1.1rem;
    font-weight: 400;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
}

/* A tile shows the pack's size on its art, so the contents line is for screen readers only. */
.rj-offer--catalogue .rj-offer__contents {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.rj-offer__buy {
    margin-top: auto;
    line-height: 1.05;
}

.rj-offer--catalogue .rj-offer__buy {
    padding: 0.2rem 0.3rem calc(0.2rem + var(--ui-edge));
    font-size: 1rem;
}

.rj-offer__price { white-space: nowrap; }

.rj-offer__demo {
    font-size: 0.62rem;
    opacity: 0.95;
}

.rj-offer__sold-out {
    margin-top: auto;
    padding: 0.3rem 0.9rem;
    border: 2px solid var(--ui-outline);
    border-radius: 0.6rem;
    background: rgba(0, 0, 0, 0.35);
    color: #ffffff;
    font-family: var(--ui-font-display);
    font-size: 1.05rem;
    font-weight: 400;
    transform: rotate(-4deg);
}

/* The best-value pack: a red ribbon across its top edge and a glow in the theme's main colour. */
.rj-offer.is-best {
    border-color: var(--ui-primary);
    box-shadow:
        inset 0 2px 0 rgba(255, 255, 255, 0.28),
        0 0 0 2px var(--ui-outline),
        0 0 0 6px color-mix(in srgb, var(--ui-primary-light) 55%, transparent),
        0 5px 0 2px color-mix(in srgb, var(--ui-outline) 55%, transparent),
        0 10px 18px var(--ui-shadow);
}

/* The best-value tile moves its content down, so the ribbon does not cover the name. */
.rj-offer--catalogue.is-best { padding-top: 0.95rem; }

.rj-offer__best {
    position: absolute;
    z-index: 2;
    top: -0.9rem;
    left: 50%;
    transform: translateX(-50%) rotate(-3deg);
    padding: 0.1rem 0.45rem 0.15rem;
    border: 2px solid var(--ui-outline);
    border-radius: 0.45rem;
    background: linear-gradient(180deg, var(--ui-danger-light), var(--ui-danger) 60%);
    box-shadow: 0 2px 0 var(--ui-outline);
    color: #ffffff;
    font-family: var(--ui-font-display);
    font-size: 0.75rem;
    font-weight: 400;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    white-space: nowrap;
    -webkit-text-stroke: 0.16em var(--ui-outline);
    paint-order: stroke fill;
}

/* A hero card: the art on the left with a glow behind it, the name and contents on the right, and a wide buy button. */
.rj-offer--featured,
.rj-offer--out-of-spins {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1fr);
    grid-template-areas:
        "art name"
        "art contents"
        "buy buy";
    align-items: center;
    gap: 0.4rem 0.7rem;
    /* The bottom padding keeps the buy button clear of the guide's arrow when the guide points at the event bar under
       the out-of-spins card on the spin screen. */
    padding: 1.8rem 0.9rem 1.35rem;
    text-align: left;
}

.rj-offer--featured .rj-offer__name,
.rj-offer--out-of-spins .rj-offer__name {
    grid-area: name;
    align-self: end;
    font-size: 1.45rem;
}

.rj-offer--featured .rj-offer__art-box,
.rj-offer--out-of-spins .rj-offer__art-box {
    grid-area: art;
    width: 100%;
    max-width: 9rem;
    justify-self: center;
}

.rj-offer--featured .rj-offer__contents,
.rj-offer--out-of-spins .rj-offer__contents {
    grid-area: contents;
    align-self: start;
}

.rj-offer--featured .rj-offer__buy,
.rj-offer--out-of-spins .rj-offer__buy,
.rj-offer--featured .rj-offer__sold-out,
.rj-offer--out-of-spins .rj-offer__sold-out {
    grid-area: buy;
}

.rj-offer--featured .rj-offer__sold-out,
.rj-offer--out-of-spins .rj-offer__sold-out { justify-self: center; }

/* ---------------------------------------------------------------------------
   Events: each progress event as a card with its banner art, its name and a timer chip on the banner, the player's
   points and a bar to the next milestone, and the milestones as a track. No animation moves a Claim button, because
   Playwright waits for a button to stop moving before it taps it; the glow around a ready milestone changes only
   its opacity.
   --------------------------------------------------------------------------- */
.rj-events {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.rj-events__event {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* The banner: the art fills it, a dark band at its bottom carries the event's name, and the timer chip is in its top
   right corner. Without art the banner takes the ribbon colour. */
.rj-events__hero {
    position: relative;
    isolation: isolate;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    min-height: 6.5rem;
    padding: 0.6rem 0.75rem 0.5rem;
    background: linear-gradient(180deg, var(--ui-ribbon-light), var(--ui-ribbon-dark));
}

.rj-events__hero::after {
    content: "";
    position: absolute;
    z-index: -1;
    inset: 0;
    background: linear-gradient(180deg, transparent 40%, rgba(0, 0, 0, 0.6) 100%);
}

.rj-events__banner {
    position: absolute;
    z-index: -2;
    inset: 0;
    width: 100%;
    max-width: none;
    height: 100%;
    object-fit: cover;
    object-position: 50% 40%;
}

.rj-events__name {
    margin: 0;
    color: #ffffff;
    font-family: var(--ui-font-display);
    font-size: 1.55rem;
    font-weight: 400;
    line-height: 1.05;
    -webkit-text-stroke: 0.18em var(--ui-outline);
    paint-order: stroke fill;
    text-shadow: 0 0.08em 0 var(--ui-outline);
}

.rj-events__timer {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    max-width: calc(100% - 1rem);
    padding: 0.15rem 0.55rem 0.15rem 0.25rem;
    border: 2px solid var(--ui-outline);
    border-radius: 999px;
    background: var(--ui-pill-bg);
    box-shadow: 0 2px 0 var(--ui-outline);
    color: var(--ui-pill-ink);
    font-family: var(--ui-font-display);
    font-size: 0.82rem;
    font-weight: 400;
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
}

.rj-events__clock {
    flex: none;
    width: 1.15rem;
    height: 1.15rem;
}

.rj-events__clock circle { fill: var(--ui-primary-light); stroke: var(--ui-outline); stroke-width: 2.2; }
.rj-events__clock path   { fill: none; stroke: var(--ui-outline); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }

.rj-events__score {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.75rem 0.75rem 0.15rem;
}

.rj-events__tokens {
    flex: none;
    margin: 0;
    padding: 0.1rem 0.6rem 0.15rem;
    border: 2px solid var(--ui-outline);
    border-radius: 999px;
    background: linear-gradient(180deg, var(--ui-ribbon-light), var(--ui-ribbon) 60%);
    box-shadow: 0 2px 0 var(--ui-outline);
    color: #ffffff;
    font-family: var(--ui-font-display);
    font-size: 1.05rem;
    font-weight: 400;
    -webkit-text-stroke: 0.16em var(--ui-outline);
    paint-order: stroke fill;
}

.rj-events__bar {
    flex: 1;
    height: 1.05rem;
    overflow: hidden;
    border: 2px solid var(--ui-outline);
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.3);
    box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.35);
}

.rj-events__fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(180deg, var(--ui-primary-light) 0%, var(--ui-primary) 60%, var(--ui-primary-dark) 100%);
    box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.45);
}

.rj-ladder {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    margin: 0;
    padding: 0.55rem 0.7rem 0.8rem;
    list-style: none;
}

/* A milestone: its node on the track, the reward's art and amount, the points it needs, and Claim or Claimed. */
.rj-ladder__step {
    position: relative;
    display: grid;
    grid-template-columns: 1.75rem minmax(0, 1fr) auto;
    grid-template-areas:
        "node reward action"
        "node goal   action";
    align-items: center;
    column-gap: 0.6rem;
    min-height: 3.1rem;
    padding: 0.3rem 0.45rem 0.3rem 0.35rem;
    border-radius: 0.9rem;
    background: color-mix(in srgb, var(--ui-panel-ink) 9%, transparent);
}

/* The track between two nodes; it takes the main colour once the player has the points of the lower milestone. */
.rj-ladder__step + .rj-ladder__step::before {
    content: "";
    position: absolute;
    z-index: 0;
    top: -0.75rem;
    left: calc(0.35rem + 0.875rem - 3px);
    width: 6px;
    height: 1.4rem;
    border-radius: 3px;
    background: color-mix(in srgb, var(--ui-panel-ink) 25%, transparent);
}

.rj-ladder__step.is-passed + .rj-ladder__step.is-passed::before { background: var(--ui-primary); }

.rj-ladder__node {
    grid-area: node;
    position: relative;
    z-index: 1;
    display: grid;
    place-items: center;
    box-sizing: border-box;
    width: 1.75rem;
    height: 1.75rem;
    border: 2.5px solid var(--ui-outline);
    border-radius: 50%;
    background: color-mix(in srgb, var(--ui-panel-ink) 22%, var(--ui-panel));
}

.rj-ladder__step.is-passed .rj-ladder__node {
    background: radial-gradient(circle at 40% 35%, var(--ui-primary-light) 0%, var(--ui-primary) 70%);
}

.rj-ladder__step.is-claimed .rj-ladder__node { background: var(--ui-plus); }

.rj-ladder__node svg {
    width: 1.1rem;
    height: 1.1rem;
    fill: none;
    stroke: #ffffff;
    stroke-width: 3.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.rj-ladder__reward {
    grid-area: reward;
    display: flex;
    align-items: center;
    gap: 0.45rem;
    min-width: 0;
    font-family: var(--ui-font-display);
    font-size: 1.05rem;
    font-weight: 400;
    line-height: 1.1;
}

.rj-ladder__icon {
    flex: none;
    width: 2.1rem;
    height: 2.1rem;
    object-fit: contain;
    filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.3));
}

.rj-ladder__goal {
    grid-area: goal;
    font-size: 0.75rem;
    font-weight: 800;
    color: var(--ui-panel-ink-2);
}

/* With reward art the points line starts under the amount, not under the art. */
.rj-ladder__reward:has(.rj-ladder__icon) + .rj-ladder__goal { padding-left: 2.55rem; }

.rj-ladder__claim,
.rj-ladder__claimed { grid-area: action; }

.rj-ladder__claim { padding: 0.2rem 0.75rem; }

.rj-ladder__claimed {
    padding: 0.1rem 0.55rem 0.15rem;
    border: 2px solid var(--ui-outline);
    border-radius: 999px;
    background: var(--ui-plus);
    color: #ffffff;
    font-family: var(--ui-font-display);
    font-size: 0.85rem;
    font-weight: 400;
    -webkit-text-stroke: 0.15em var(--ui-outline);
    paint-order: stroke fill;
}

.rj-ladder__step.is-claimed { opacity: 0.72; }

/* A milestone ready to claim: a light band in the main colour and a glow that fades in and out. */
.rj-ladder__step.is-reached {
    background: color-mix(in srgb, var(--ui-primary) 24%, transparent);
    box-shadow: inset 0 0 0 2px var(--ui-primary);
}

.rj-ladder__step.is-reached::after {
    content: "";
    position: absolute;
    inset: -3px;
    border-radius: 1.05rem;
    box-shadow: 0 0 10px 2px var(--ui-primary-light);
    pointer-events: none;
    animation: rj-ladder-glow 1.2s ease-in-out infinite alternate;
}

@keyframes rj-ladder-glow {
    from { opacity: 0.25; }
    to   { opacity: 1; }
}

.rj-events-page .rj-menu-empty { padding-top: 1rem; }

.rj-events__message {
    margin: 0;
    padding: 0.4rem 0.75rem;
    border: 2px solid var(--ui-outline);
    border-radius: 0.8rem;
    background: var(--ui-danger);
    color: #ffffff;
    font-weight: 900;
    text-align: center;
}

/* The madness windows on the events screen: a ribbon-coloured banner, red for an attack madness. The home and spin
   screens keep the plain banner above. */
.rj-events-page .rj-madness__item {
    align-items: center;
    padding: 0.6rem 0.8rem;
    border: var(--ui-border) solid var(--ui-outline);
    border-radius: 1rem;
    background: linear-gradient(180deg, var(--ui-ribbon-light) 0%, var(--ui-ribbon) 55%, var(--ui-ribbon-dark) 100%);
    box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.35), 0 4px 0 var(--ui-outline);
    color: #ffffff;
    text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
}

.rj-events-page .rj-madness__item--attack {
    background: linear-gradient(180deg, var(--ui-danger-light) 0%, var(--ui-danger) 55%, var(--ui-danger-dark) 100%);
}

.rj-events-page .rj-madness__name {
    font-family: var(--ui-font-display);
    font-size: 1.2rem;
    font-weight: 400;
    -webkit-text-stroke: 0.18em var(--ui-outline);
    paint-order: stroke fill;
    text-shadow: 0 0.08em 0 var(--ui-outline);
}

.rj-events-page .rj-madness__effect,
.rj-events-page .rj-madness__bets { font-weight: 900; }

.rj-events-page .rj-madness__timer {
    padding: 0.05rem 0.5rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.3);
    color: #ffffff;
    font-family: var(--ui-font-display);
    font-weight: 400;
    text-shadow: none;
}

/* The answer to an invite link (MetaLayout.razor; css/base.css draws its layout): a green or red toast. */
.rj-invite-notice {
    border: var(--ui-border) solid var(--ui-outline);
    border-radius: 1rem;
    background: linear-gradient(180deg, var(--ui-plus-light) 0%, var(--ui-plus) 55%);
    box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.35), 0 4px 0 var(--ui-outline);
    font-weight: 900;
    text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
}

.rj-invite-notice.is-good,
.rj-invite-notice.is-bad { color: #ffffff; }

.rj-invite-notice.is-bad { background: linear-gradient(180deg, var(--ui-danger-light) 0%, var(--ui-danger) 55%); }

@media (prefers-reduced-motion: reduce) {
    .rj-friends__message,
    .rj-friends__copied,
    .rj-shop__message,
    .rj-ladder__step.is-reached::after { animation: none; }
}
