/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

/* ---- Care screen (story 3057) ---- */
.care__art { flex: 0 0 auto; width: 84px; height: 84px; border-radius: 50%; overflow: hidden; display: grid; place-items: center; border: 3px solid var(--rarity, var(--bs-primary)); }
.care__art img { width: 100%; height: 100%; object-fit: cover; }
.care__stat { padding: .5rem .25rem; border-radius: .75rem; background: rgba(var(--bs-body-color-rgb), .05); }
.care__stat-label { font-size: .7rem; text-transform: uppercase; letter-spacing: .05em; opacity: .7; }
.care__stat-value { font-weight: 700; }
.care__fainted { background: rgba(var(--bs-body-color-rgb), .06); border: 1px dashed rgba(var(--bs-body-color-rgb), .2); }
.care--fainted .care__art { filter: grayscale(1) opacity(.7); }
.care__actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .5rem; } /* Feed · Water · Play — Collect lives in the wallet control above the card */
.care__actions form { display: contents; }
.care__action { display: flex; flex-direction: column; align-items: center; gap: .1rem; padding: .6rem .25rem; min-height: var(--fab-tap-target); line-height: 1.1; font-weight: 700; }
.care__action-emoji { font-size: 1.5rem; }
.care__action-wait { font-size: .7rem; font-weight: 600; opacity: .8; }
.brainrot-card__pending { font-size: .85rem; }

/* ---- Shop (story 3058) ---- */
.shop-card__icon { font-size: 2.25rem; line-height: 1; flex: 0 0 auto; }
.shop-ledger .fab-settings__row { align-items: flex-start; }
.care__alert { padding: .6rem .8rem; border-radius: .75rem; font-size: .9rem; }
.care__alert--danger { background: rgba(var(--bs-danger-rgb), .14); border: 1px solid rgba(var(--bs-danger-rgb), .4); }
.care__alert--warning { background: rgba(var(--bs-warning-rgb), .16); border: 1px solid rgba(var(--bs-warning-rgb), .45); }
/* Tools are rows, like the shop's item list: icon · name ×count · blurb, action on the right. No grid holes. */
/* Your tools (2026-09-13): four equipped tiles — icon + name, a tap uses it; the count sits in the corner */
.tools__grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .5rem; }
@media (max-width: 399.98px) { .tools__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.tools__form { display: contents; }
.tools__slot { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .35rem; min-height: 6rem; padding: .85rem .4rem .7rem; border-radius: 1rem; text-align: center; min-width: 0; }
.tools__slot.disabled, .tools__slot:disabled { opacity: .5; }
.tools__slot--empty { border: 1px dashed rgba(var(--bs-primary-rgb), .55); background: transparent; }
.tools__icon { font-size: 1.9rem; line-height: 1; }
.tools__name { font-size: .78rem; font-weight: 700; line-height: 1.15; }
.tools__slot .tools__count { position: absolute; top: .35rem; right: .5rem; font-size: .7rem; font-weight: 800; opacity: .85; }
.inventory .tools__icon { flex: 0 0 auto; width: 2.25rem; text-align: center; font-size: 1.75rem; }
.inventory .tools__count { font-weight: 800; }
.inventory__equipped { font-size: .7rem; padding: .1rem .5rem; }
/* The drawer's two pockets (Nick, 2026-09-17): a heading above each group of tools. */
.inventory__group { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; border-bottom: 1px solid var(--bs-border-color); }
.inventory__group:not(:first-child) { margin-top: .75rem; }
.fab-inventory { width: 26rem; max-width: 100vw; }
.fab-snap-btn { font-size: 1.2rem; }
.fuse__rules { padding-left: 1.1rem; } .fuse__rules li + li { margin-top: .2rem; }

/* The Shop, laid out rather than listed (Nick, 2026-09-18): a Featured row at the top, then one grid per tool section.
   Same tile in both, so a featured tool looks like itself down in its aisle. */
.shop-section { margin-bottom: 1.75rem; }
.shop-section__head { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; margin-bottom: .75rem; }
.shop-section__title { font-size: 1.15rem; font-weight: 800; margin: 0; }
.shop-section__where { margin: 0; font-size: .85rem; color: var(--bs-secondary-color); }
/* two tiles to a phone screen, and tiles worth looking at on a desktop */
.shop-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: .75rem; align-items: stretch; }
@media (min-width: 576px) { .shop-grid { grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); } }
/* the two staples are wordier than a tool, so the featured row gives every card more room */
.shop-grid--featured { grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); }
.shop-grid > * { min-width: 0; }

.shop-tile {
  display: flex; flex-direction: column; gap: .35rem; padding: .9rem .85rem 1rem; border-radius: 1.1rem; text-align: center;
  background: rgba(var(--bs-body-color-rgb), .05); border: 1px solid transparent;
}
.shop-tile--featured { background: rgba(var(--bs-primary-rgb), .12); border-color: rgba(var(--bs-primary-rgb), .35); }
.shop-tile__icon { font-size: 2.4rem; line-height: 1; }
.shop-tile__name { font-size: 1rem; font-weight: 800; margin: 0; }
.shop-tile__blurb { font-size: .8rem; line-height: 1.35; color: var(--bs-secondary-color); margin: 0 0 .2rem; }
.shop-tile__foot { display: flex; align-items: center; justify-content: center; gap: .5rem; flex-wrap: wrap; margin-top: auto; padding-top: .4rem; }
.shop-tile__owned { font-size: .75rem; color: var(--bs-secondary-color); }
.shop-tile__buy { margin-top: .6rem; }
.shop-tile__hint { font-size: .75rem; color: var(--bs-secondary-color); margin: .4rem 0 0; }
.shop-ledger__open { --bs-btn-padding-y: .5rem; }
/* A drawer whose pager sits in a footer: the frame and the pane inside it are the column between the header and that
   footer, so the list scrolls and the buttons stay put (Nick, 2026-09-18). */
.fab-drawer-frame, .fab-drawer-pane { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.fab-drawer-pane > .offcanvas-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.fab-drawer-pane > .offcanvas-footer { flex: 0 0 auto; }

/* ---- Dex (story 3059) ---- */
.dex-progress { height: .6rem; }
.dex-progress__number { font-family: var(--fab-font-display, inherit); font-weight: 800; font-size: 1.5rem; line-height: 1; }
.dex-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr)); gap: .75rem; }
/* Seven across once the Index has its two columns (Nick, 2026-09-18); narrower than that, as many as fit. */
@media (min-width: 992px) { .dex-grid { grid-template-columns: repeat(7, minmax(0, 1fr)); } }
.dex-tile {
  display: block; width: 100%; padding: .6rem .5rem .7rem; border: 0; border-radius: 1rem; text-align: center;
  background: rgba(var(--bs-body-color-rgb), .05); color: inherit; text-decoration: none; cursor: pointer;
  transition: transform .15s ease, box-shadow .15s ease;
}
.dex-tile:hover, .dex-tile:focus-visible { color: inherit; transform: translateY(-2px); box-shadow: 0 8px 20px rgba(18, 6, 58, .18); outline: none; }
.dex-tile__art { position: relative; width: 4.5rem; height: 4.5rem; margin: 0 auto .5rem; border-radius: 50%; border: 3px solid; overflow: hidden; display: grid; place-items: center; background: rgba(var(--rarity-rgb, var(--bs-primary-rgb)), .14); }
.dex-tile__art img { width: 100%; height: 100%; object-fit: cover; }
.dex-tile__initial { font-family: var(--fab-font-display, inherit); font-weight: 800; font-size: 1.6rem; }
.dex-tile__count { position: absolute; right: -.15rem; bottom: -.15rem; padding: .05rem .45rem; border-radius: 999px; background: var(--fab-gold); color: var(--fab-ink); font-weight: 800; font-size: .75rem; border: 2px solid var(--bs-body-bg); }
.dex-tile__name { font-weight: 700; font-size: .9rem; line-height: 1.15; }
.dex-tile--uncaught .dex-tile__art { background: rgba(var(--bs-body-color-rgb), .08); border-style: dashed; }
.dex-tile--uncaught .dex-tile__art img { filter: grayscale(1) brightness(.25) contrast(1.2); opacity: .9; }
.dex-tile--uncaught .dex-tile__name { opacity: .8; }
.dex-sheet__mark { font-size: 2.5rem; line-height: 1; }

/* ---- Trading (story 3065; the tiles, arrows and selected state redone for story 3115) ---- */
.trade-pill { display: inline-flex; align-items: center; gap: .3rem; padding: .3rem .7rem; border-radius: 999px; font-size: .85rem; font-weight: 700; background: rgba(var(--bs-body-color-rgb), .07); }
.trade-pill.is-accepted { background: rgba(var(--bs-success-rgb), .18); color: var(--bs-success); }
/* The board: the two boxes with the swap arrows between them. Side by side from lg up; stacked on a phone, where the
   arrows turn to point down and up. */
.trade-board { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; align-items: stretch; }
.trade-arrows { display: flex; flex-direction: row; justify-content: center; align-items: center; gap: 1.5rem; align-self: center; padding: .25rem 0; }
.trade-arrow {
  display: block; width: 4.25rem; height: 2.25rem; background: var(--fab-gradient-primary);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 32'%3E%3Cpath d='M6 11h30V4l22 12-22 12v-7H6z' fill='%23000' stroke='%23000' stroke-width='5' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 32'%3E%3Cpath d='M6 11h30V4l22 12-22 12v-7H6z' fill='%23000' stroke='%23000' stroke-width='5' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  filter: drop-shadow(0 4px 10px rgba(255, 63, 191, .45));
  transform: rotate(90deg); /* stacked boxes: what I give goes down to theirs */
}
.trade-arrow--get { background: var(--fab-gradient-ice); filter: drop-shadow(0 4px 10px rgba(47, 230, 255, .45)); transform: rotate(-90deg); }
@media (min-width: 992px) {
  .trade-board { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); }
  .trade-arrows { flex-direction: column; gap: 1rem; padding: 0 .5rem; }
  .trade-arrow { width: 5.25rem; height: 2.75rem; transform: none; }
  .trade-arrow--get { transform: scaleX(-1); }
}
.trade-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr)); gap: .75rem; }
/* The celebration: a box each way with its tiles centred, the model view inside them */
.trade-board--done { text-align: center; }
.trade-board--done .trade-side { display: flex; flex-direction: column; align-items: center; min-width: 0; }
.trade-side__title { font-size: .8rem; text-transform: uppercase; font-weight: 800; letter-spacing: .04em; color: var(--bs-secondary-color); margin-bottom: .6rem; }
.trade-tiles--done { width: 100%; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 13rem)); justify-content: center; }

/* ---- Brainrot tile (Brainrots::Tile): the rooms card without its bars, everywhere a brainrot is just listed ---- */
.brainrot-tile { margin: 0; min-width: 0; }
.brainrot-tile > .card-body { display: flex; flex-direction: column; align-items: center; }
.brainrot-tile .brainrot-card__name { font-size: .95rem; line-height: 1.15; }
.brainrot-tile .brainrot-card__species { line-height: 1.15; }
.brainrot-tile--pick { cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent; transition: transform .15s, box-shadow .15s; }
@media (hover: hover) { .brainrot-tile--pick:hover { transform: translateY(-2px); } }
/* One selected state for every tier: the ice ring, the tick that pops in, and the line under the pill. The border
   keeps the rarity colour like every other card, so a common and a legendary read as "on" the same way. */
.brainrot-tile.is-on, .brainrot-tile:has(.brainrot-tile__check:checked) { transform: translateY(-2px); box-shadow: 0 0 0 3px var(--fab-ice), 0 0 22px rgba(47, 230, 255, .55); }
.brainrot-tile__tick {
  position: absolute; top: -.65rem; right: -.65rem; z-index: 1; width: 2rem; height: 2rem; display: grid; place-items: center;
  border-radius: 50%; background: var(--fab-gradient-ice); color: var(--fab-ink); font-weight: 900; font-size: 1.15rem; line-height: 1;
  border: 3px solid var(--fab-outline); transform: scale(0); transition: transform .18s cubic-bezier(.34, 1.56, .64, 1);
}
.brainrot-tile.is-on .brainrot-tile__tick, .brainrot-tile:has(.brainrot-tile__check:checked) .brainrot-tile__tick { transform: scale(1); }
.brainrot-tile__state { font-size: .78rem; font-weight: 700; line-height: 1.1; }
.brainrot-tile__on { display: none; color: var(--fab-ice); }
.brainrot-tile__off { opacity: .6; }
.brainrot-tile.is-on .brainrot-tile__on, .brainrot-tile:has(.brainrot-tile__check:checked) .brainrot-tile__on { display: inline; }
.brainrot-tile.is-on .brainrot-tile__off, .brainrot-tile:has(.brainrot-tile__check:checked) .brainrot-tile__off { display: none; }
.brainrot-tile:has(.brainrot-tile__check:focus-visible) { outline: 3px solid rgba(var(--bs-info-rgb), .6); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .brainrot-tile, .brainrot-tile__tick { transition: none; } }
/* The model view in a tile (the celebration): the viewer's own frame, square, sized to the tile */
.brainrot-tile__stage { width: 100%; margin-bottom: .5rem; }
.brainrot-tile__model { aspect-ratio: 1 / 1; max-height: none; border-radius: 1rem; }

/* The species page (2026-09-18): a fact list down the right, and the variants grid under the model. */
.fab-facts { display: grid; grid-template-columns: auto 1fr; gap: .4rem .9rem; align-items: baseline; margin: 0; }
.fab-facts dt { font-size: .8rem; font-weight: 700; color: var(--bs-secondary-color); text-transform: uppercase; letter-spacing: .04em; white-space: nowrap; }
.fab-facts dd { margin: 0; font-weight: 600; }
.fab-facts dd .text-body-secondary { font-weight: 500; }
@media (max-width: 400px) { .fab-facts { grid-template-columns: 1fr; gap: .1rem; } .fab-facts dd { margin-bottom: .5rem; } }

.fab-variants { display: grid; grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr)); gap: .75rem; }
.fab-variant { display: flex; flex-direction: column; align-items: center; gap: .4rem; padding: .75rem .5rem; border-radius: 1rem; background: rgba(var(--rarity-rgb, var(--bs-body-color-rgb)), .1); border: 2px solid transparent; }
.fab-variant__art { width: 100%; aspect-ratio: 1; display: grid; place-items: center; font-size: 2rem; }
.fab-variant__art img { width: 100%; height: 100%; object-fit: contain; }
.fab-variant__face { font-weight: 800; font-size: 1.75rem; color: var(--rarity, var(--bs-primary)); }
.fab-variant__name { font-size: .8rem; font-weight: 700; text-align: center; }
.fab-variant--soon { background: transparent; border-style: dashed; border-color: rgba(var(--bs-primary-rgb), .45); color: var(--bs-secondary-color); }

/* Among friends (Nick, 2026-09-18): a small board per measure, your own row picked out. */
.fab-board { list-style: none; margin: 0; padding: 0; display: grid; gap: .35rem; }
.fab-board__row { display: flex; align-items: center; gap: .6rem; padding: .35rem .5rem; border-radius: .7rem; }
.fab-board__row.is-you { background: rgba(var(--bs-primary-rgb), .14); font-weight: 700; }
.fab-board__rank { width: 1.25rem; text-align: center; font-weight: 800; color: var(--bs-secondary-color); }
.fab-board__row.is-you .fab-board__rank { color: var(--bs-primary); }
.fab-board__name { flex: 1 1 auto; min-width: 0; }
.fab-board__value { font-weight: 800; white-space: nowrap; }
.fab-board__unit { font-weight: 500; font-size: .75rem; color: var(--bs-secondary-color); }


/* Room decorations (Nick, 2026-09-18): coins buy the ground your rooms stand on. Every look is CSS only, so a new one
   is a line in Decor::Catalogue and a rule here. The same classes paint the little swatches in the Shop and the
   Decorate drawer, which is why each layer is sized in percentages: a swatch is the same picture, smaller. */
/* On <body> the decoration is the backdrop of the whole screen (Nick, 2026-09-19). Two fixed pseudo-elements do it:
   `background: inherit` hands body's decoration to ::before, which pins it to the viewport so every percentage in a
   decoration resolves against the screen rather than against a page that may be ten screens long. That is the job
   `background-attachment: fixed` would do, without asking iOS Safari to do it, which it has never done well. ::after
   lays a veil over it so the game's own light text survives a bright backdrop.
   Both sit at z-index -1: above the page's background, below everything in the page, and raising NOTHING. Lifting
   `main` over a veil instead made it a stacking context, and the Decorate drawer inside it was then trapped under the
   footer. */
body[class*="fab-room-scene--"]::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: inherit;
}
body[class*="fab-room-scene--"]::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1; /* same layer as ::before, later in order, so the veil lies over the decoration and under the game */
  pointer-events: none;
  background: linear-gradient(180deg, rgb(12 4 38 / 26%) 0%, rgb(12 4 38 / 5%) 38%, rgb(12 4 38 / 22%) 100%);
}

/* Light backdrops eat the page's own light text. The footer becomes a chip, and the line under the greeting gets a
   shadow, only where a decoration is up. */
body[class*="fab-room-scene--"] .fab-footer__text {
  display: inline-block;
  padding: 0.3rem 0.8rem;
  border-radius: 999px;
  background: rgb(12 4 38 / 62%);
  color: rgb(255 255 255 / 92%);
}
body[class*="fab-room-scene--"] .fab-rooms-head__greeting .text-body-secondary {
  color: #fff;
  text-shadow: 0 1px 3px rgb(12 4 38 / 95%), 0 0 12px rgb(12 4 38 / 80%);
}

.fab-room-scene--plain { background: var(--bs-secondary-bg); }

/* Sun, a couple of clouds, then blades of grass that stop where the grass does. */
.fab-room-scene--meadow {
  background-color: #7fc95f;
  background-image:
    radial-gradient(circle at 87% 12%, #fff6b0 0 3%, rgb(255 246 176 / 40%) 3.4% 4.4%, transparent 4.8%),
    radial-gradient(circle at 17% 13%, #ffffff 0 3.2%, transparent 3.7%),
    radial-gradient(circle at 24% 16%, rgb(255 255 255 / 85%) 0 2.4%, transparent 2.9%),
    radial-gradient(circle at 62% 9%, rgb(255 255 255 / 75%) 0 2.2%, transparent 2.7%),
    repeating-linear-gradient(112deg, rgb(48 124 48 / 24%) 0 5px, transparent 5px 15px),
    linear-gradient(#a8e4ff 0 34%, #7fc95f 34%);
  background-size: 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 66%, 100% 100%;
  background-position: 0 0, 0 0, 0 0, 0 0, 0 100%, 0 0;
  background-repeat: no-repeat;
}

/* Stars of three sizes over a night that gets lighter towards the ground. */
.fab-room-scene--night {
  background-color: #141a3c;
  background-image:
    radial-gradient(circle at 81% 14%, #fff6cf 0 2.4%, rgb(255 246 207 / 22%) 2.8% 3.8%, transparent 4.2%),
    radial-gradient(circle at 20% 22%, rgb(255 255 255 / 90%) 0 1.3px, transparent 2px),
    radial-gradient(circle at 68% 12%, rgb(255 255 255 / 70%) 0 1.6px, transparent 2.3px),
    radial-gradient(circle at 44% 64%, rgb(255 255 255 / 55%) 0 1px, transparent 1.8px),
    linear-gradient(#0b1030 0 55%, #35236e 100%);
  background-size: 100% 100%, 90px 90px, 150px 150px, 70px 70px, 100% 100%;
  background-position: 0 0, 0 0, 0 0, 0 0, 0 0;
  background-repeat: no-repeat, repeat, repeat, repeat, no-repeat;
}

/* Sky, a strip of sea with foam on it, then sand. */
.fab-room-scene--beach {
  background-color: #f2dba6;
  background-image:
    repeating-linear-gradient(90deg, rgb(255 255 255 / 60%) 0 14px, transparent 14px 34px),
    radial-gradient(circle at 13% 13%, #ffe680 0 3%, rgb(255 230 128 / 40%) 3.4% 4.4%, transparent 4.8%),
    repeating-linear-gradient(98deg, rgb(198 160 96 / 22%) 0 3px, transparent 3px 19px),
    linear-gradient(#a8e4ff 0 28%, #2f9fd0 28% 44%, #f4dea8 44%);
  background-size: 100% 7px, 100% 100%, 100% 62%, 100% 100%;
  background-position: 0 36%, 0 0, 0 100%, 0 0;
  background-repeat: repeat-x, no-repeat, no-repeat, no-repeat;
}

/* Sherbet stripes, wide enough that a card sits on two or three of them. */
.fab-room-scene--candy {
  background-color: #ffd7e9;
  background-image: repeating-linear-gradient(48deg, #ffb8d8 0 22px, #fff5fa 22px 44px, #ffdfae 44px 66px, #fff5fa 66px 88px);
}

/* Outrun (Nick, 2026-09-20, from a reference he sent): a sliced sun, mountains on the skyline, a hot horizon and a
   grid running away to it. Three tricks make it work with nothing but gradients.
   The sun's slices are FULL-WIDTH dark bands: against the near-black sky they are invisible, so they only read where
   they cross the sun. The grid's verticals are a repeating CONIC gradient centred on the horizon, which is what
   perspective is: a fan from the vanishing point. Its horizontals are hand-placed rather than repeating, because
   evenly spaced is exactly what perspective is not.
   There is deliberately NO skyline. Four goes at mountains with gradients alone gave either upside-down triangles (a
   conic wedge coming out as its own complement at this aspect ratio) or bald domes sitting in the wrong place. Peaks
   want a real shape, so if they are wanted they should be a small SVG rather than a fifth guess.
   The sun and the mountains are sized in PIXELS: a circle needs equal width and height, and a percentage of a viewport
   is not. The horizon sits low so the sun has sky to stand in rather than hiding behind the room cards. */
.fab-room-scene--arcade {
  background-color: #150c2b;
  background-image:
    linear-gradient(180deg, transparent 0.0% 28.57%, rgb(255 92 214 / 55%) 28.57% 30.01%, transparent 30.01% 44.44%, rgb(255 92 214 / 55%) 44.44% 46.52%, transparent 46.52% 54.55%, rgb(255 92 214 / 55%) 54.55% 57.03%, transparent 57.03% 61.54%, rgb(255 92 214 / 55%) 61.54% 64.3%, transparent 64.3% 66.67%, rgb(255 92 214 / 55%) 66.67% 69.63%, transparent 69.63% 70.59%, rgb(255 92 214 / 55%) 70.59% 73.71%, transparent 73.71% 73.68%, rgb(255 92 214 / 55%) 73.68% 76.93%, transparent 76.93% 76.19%, rgb(255 92 214 / 55%) 76.19% 79.54%, transparent 79.54% 78.26%, rgb(255 92 214 / 55%) 78.26% 81.69%, transparent 81.69% 80.0%, rgb(255 92 214 / 55%) 80.0% 83.5%, transparent 83.5% 81.48%, rgb(255 92 214 / 55%) 81.48% 85.04%, transparent 85.04% 82.76%, rgb(255 92 214 / 55%) 82.76% 86.37%, transparent 86.37% 83.87%, rgb(255 92 214 / 55%) 83.87% 87.53%, transparent 87.53% 84.85%, rgb(255 92 214 / 55%) 84.85% 88.54%, transparent 88.54% 85.71%, rgb(255 92 214 / 55%) 85.71% 89.44%, transparent 89.44% 86.49%, rgb(255 92 214 / 55%) 86.49% 90.25%, transparent 90.25% 87.18%, rgb(255 92 214 / 55%) 87.18% 90.97%, transparent 90.97% 87.8%, rgb(255 92 214 / 55%) 87.8% 91.62%, transparent 91.62% 88.37%, rgb(255 92 214 / 55%) 88.37% 92.21%, transparent 92.21% 88.89%, rgb(255 92 214 / 55%) 88.89% 92.74%, transparent 92.74% 100%),
    repeating-conic-gradient(from 180deg at 50% 0%, rgb(255 92 214 / 45%) 0deg 0.3deg, transparent 0.3deg 4.4deg),
    linear-gradient(180deg, transparent 0 63.5%, rgb(255 220 240 / 95%) 63.5% 64.3%, transparent 64.3% 100%),
    radial-gradient(ellipse 60% 7% at 50% 64.0%, rgb(255 92 150 / 70%), transparent 72%),
    repeating-linear-gradient(180deg, transparent 0 11px, rgb(18 10 38 / 90%) 11px 17px),
    radial-gradient(circle at 50% 50%, #ffc08a 0 14%, #ff5ca8 46%, #a93bd6 76%, transparent 77%),
    radial-gradient(circle at 18% 22%, rgb(255 255 255 / 75%) 0 1.1px, transparent 1.8px),
    radial-gradient(circle at 72% 14%, rgb(255 180 220 / 65%) 0 1.3px, transparent 2px),
    linear-gradient(180deg, #1d0e4a 0 34%, #37196a 50.0%, #52206a 62.0%, #2a1147 64.0%, #150c2b 100%);
  background-size:
    100% 36.0%, 100% 36.0%,
    100% 100%, 100% 100%,
    300px 300px, 300px 300px,
    150px 150px, 210px 210px,
    100% 100%;
  background-position:
    0 100%, 0 100%,
    0 0, 0 0,
    50% calc(64.0% - 300px), 50% calc(64.0% - 300px),
    0 0, 0 0, 0 0;
  background-repeat:
    no-repeat, no-repeat,
    no-repeat, no-repeat,
    no-repeat, no-repeat,
    repeat, repeat,
    no-repeat;
}

/* Embers from below, cracks across the rock. */
.fab-room-scene--lava {
  background-color: #1b0b07;
  background-image:
    radial-gradient(ellipse 34% 30% at 24% 104%, rgb(255 168 61 / 85%) 0 30%, transparent 70%),
    radial-gradient(ellipse 30% 26% at 74% 108%, rgb(255 96 30 / 80%) 0 30%, transparent 70%),
    repeating-linear-gradient(72deg, rgb(255 120 40 / 16%) 0 2px, transparent 2px 26px),
    linear-gradient(#2b120c 0 50%, #8a2a10 100%);
}

/* The swatch: the same picture, shrunk, wherever a decoration is offered or picked. */
.fab-decor__swatch {
  display: block;
  width: 100%;
  height: 4rem;
  border-radius: var(--bs-border-radius);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 15%);
}
.fab-decor-card .fab-decor__swatch { margin-bottom: 0.75rem; }
.fab-decor-card.is-yours { box-shadow: inset 0 0 0 2px var(--bs-primary); }

.fab-decor-picker { display: grid; gap: 0.6rem; }
.fab-decor-picker form { display: contents; }
.fab-decor-option {
  display: grid;
  grid-template-columns: 4.5rem 1fr auto;
  align-items: center;
  gap: 0.85rem;
  width: 100%;
  padding: 0.6rem;
  border: 0;
  border-radius: var(--bs-border-radius-lg);
  background: var(--bs-secondary-bg);
  color: var(--bs-body-color);
  text-align: left;
  text-decoration: none;
}
.fab-decor-option .fab-decor__swatch { height: 3rem; }
.fab-decor-option__text { display: grid; gap: 0.1rem; min-width: 0; }
.fab-decor-option__name { font-weight: 700; }
.fab-decor-option__note { font-size: 0.8rem; color: var(--bs-secondary-color); }
.fab-decor-option:disabled { box-shadow: inset 0 0 0 2px var(--bs-primary); opacity: 1; }
.fab-decor-option--locked .fab-decor__swatch { filter: saturate(0.55) brightness(0.85); }
.fab-decor-option--locked .fab-decor-option__name { opacity: 0.75; }
.fab-decor-option__lock { color: var(--bs-secondary-color); }

/* The username typeahead on the Friends page (Nick, 2026-09-18): a panel that hangs under the box rather than pushing
   the card about. It is absolute from md up, where there is room for it to float, and in the flow on a phone, where a
   floating panel over a thumb-sized list is worse than one that simply follows the box. */
.fab-typeahead { position: relative; }
.fab-typeahead__panel {
  display: grid;
  gap: 0.25rem;
  margin-top: 0.4rem;
  padding: 0.4rem;
  border-radius: var(--bs-border-radius-lg);
  background: var(--bs-body-bg);
  box-shadow: 0 0.75rem 2rem rgb(0 0 0 / 28%), inset 0 0 0 1px var(--bs-border-color);
}
.fab-typeahead__row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.4rem 0.5rem;
  border-radius: var(--bs-border-radius);
}
.fab-typeahead__row:hover, .fab-typeahead__row:focus-within { background: var(--bs-secondary-bg); }
.fab-typeahead__empty { padding: 0.5rem; font-size: 0.875rem; color: var(--bs-secondary-color); }

@media (min-width: 768px) {
  .fab-typeahead__results { position: absolute; z-index: 5; inset-inline: 0; }
}

/* Admin Abuse (Nick, 2026-09-19): the show. Roblox admin abuse works because everyone is in one room watching, so all
   of this exists to make a scattered map feel like a room: a banner that says somebody is here, shouts that land on
   every screen at once, and gifts that arrive with enough noise to be worth telling a friend about.
   Everything is pointer-events: none. The map underneath stays playable while it rains. */
.fab-hunt-banner.fab-abuse-banner {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: linear-gradient(120deg, #ff3b3b, #ff8a29);
  color: #fff;
  font-weight: 700;
}
.fab-abuse-banner__dot {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  background: #fff;
  animation: fab-abuse-pulse 1.1s ease-in-out infinite;
}
@keyframes fab-abuse-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.35; transform: scale(0.72); } }

.fab-abuse-shouts, .fab-abuse-headlines, .fab-abuse-coins {
  position: fixed;
  inset: 0;
  z-index: 1080; /* over the map and its sheets, under the confirm dialog */
  pointer-events: none;
  overflow: hidden;
}
.fab-abuse-shouts { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding-top: calc(var(--fab-below-chip) + 3rem); } /* under the chip, its Tools tab and the live banner (story 3194) */
/* A column, not a row: two gifts landing together read as one after another, never as a pair of cards side by side. */
.fab-abuse-headlines { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.6rem; }

.fab-abuse-shout {
  max-width: min(32rem, 92vw);
  padding: 0.7rem 1.1rem;
  border-radius: 999px;
  background: linear-gradient(120deg, #9b3dff, #ff3fbf);
  color: #fff;
  font-weight: 700;
  text-align: center;
  box-shadow: 0 0.6rem 1.8rem rgb(12 4 38 / 45%);
  opacity: 0;
  transform: translateY(-1.2rem) scale(0.94);
  transition: opacity 220ms ease, transform 260ms cubic-bezier(0.2, 1.3, 0.4, 1);
}
.fab-abuse-shout.is-in { opacity: 1; transform: none; }

.fab-abuse-headline {
  display: grid;
  justify-items: center;
  gap: 0.35rem;
  padding: 1.1rem 1.6rem;
  border-radius: var(--bs-border-radius-xl);
  background: rgb(12 4 38 / 86%);
  box-shadow: 0 0 0 1px rgb(255 255 255 / 14%), 0 1rem 2.5rem rgb(12 4 38 / 55%);
  color: #fff;
  text-align: center;
  opacity: 0;
  transform: scale(0.8);
  animation: fab-abuse-headline 2.6s ease forwards;
}
.fab-abuse-headline__icon { font-size: 2.6rem; line-height: 1; }
.fab-abuse-headline__text { font-size: 1.15rem; font-weight: 700; }
@keyframes fab-abuse-headline {
  0% { opacity: 0; transform: scale(0.8); }
  12% { opacity: 1; transform: scale(1.06); }
  20% { transform: scale(1); }
  80% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.04) translateY(-0.6rem); }
}

.fab-abuse-coin {
  position: absolute;
  top: -2.5rem;
  font-size: 1.6rem;
  animation: fab-abuse-fall var(--fall-time, 2s) linear var(--fall-delay, 0s) forwards;
}
@keyframes fab-abuse-fall {
  from { transform: translateY(0) rotate(0); opacity: 1; }
  to { transform: translateY(105vh) rotate(var(--spin, 360deg)); opacity: 0.85; }
}

/* A marker dropping out of the sky onto its place, with a squash as it lands. The delay is set per marker so a
   handful arrive one after another: that is the difference between rain and a redraw. */
.fab-spawn.is-raining { animation: fab-abuse-drop 900ms cubic-bezier(0.3, 1.5, 0.5, 1) var(--fall-delay, 0s) both; }
@keyframes fab-abuse-drop {
  0% { transform: translateY(-70vh) scale(0.7); opacity: 0; }
  55% { opacity: 1; }
  70% { transform: translateY(0) scale(1.14, 0.86); }
  85% { transform: translateY(-0.5rem) scale(0.96, 1.05); }
  100% { transform: translateY(0) scale(1); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .fab-abuse-banner__dot, .fab-abuse-coin, .fab-spawn.is-raining, .fab-abuse-headline { animation-duration: 1ms; animation-iteration-count: 1; }
  .fab-abuse-shout { transition-duration: 1ms; }
}

/* The console. Big targets: this is played fast, with an audience waiting. */
.fab-abuse__bar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 0.75rem; }
.fab-abuse__onair { display: flex; align-items: center; gap: 0.4rem; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.08em; color: var(--fab-lava); }
.fab-abuse__dot { width: 0.55rem; height: 0.55rem; border-radius: 50%; background: var(--fab-lava); animation: fab-abuse-pulse 1.1s ease-in-out infinite; }
.fab-abuse__clock { font-size: 1.6rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.fab-abuse__meters { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.5rem; margin-bottom: 1rem; }
.fab-abuse__meters > div { display: grid; gap: 0.1rem; padding: 0.5rem; border-radius: var(--bs-border-radius); background: var(--bs-secondary-bg); text-align: center; }
.fab-abuse__meter-n { font-weight: 700; font-variant-numeric: tabular-nums; }
.fab-abuse__meters span:last-child { font-size: 0.75rem; color: var(--bs-secondary-color); }
.fab-abuse__acts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.6rem; }
.fab-abuse__acts form { display: contents; }
.fab-abuse__act {
  display: grid;
  justify-items: center;
  gap: 0.15rem;
  width: 100%;
  padding: 0.9rem 0.5rem;
  border: 0;
  border-radius: var(--bs-border-radius-lg);
  background: var(--fab-gradient-primary);
  color: #fff;
}
.fab-abuse__act-icon { font-size: 1.8rem; line-height: 1; }
.fab-abuse__act-name { font-weight: 700; }
.fab-abuse__act-blurb { font-size: 0.75rem; opacity: 0.85; }
.fab-abuse__secret, .fab-abuse__shout { margin-top: 1rem; }
.fab-abuse__feed { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; gap: 0.3rem; font-size: 0.8rem; }
.fab-abuse__feed li { display: flex; gap: 0.5rem; align-items: baseline; color: var(--bs-secondary-color); }
.fab-abuse__feed-when { font-variant-numeric: tabular-nums; opacity: 0.7; }
.fab-abuse__feed-count { margin-left: auto; white-space: nowrap; }

/* Admin Abuse, round two (Nick, 2026-09-19): a sunburst behind the headline, emotes drifting up the right, a live bar
   for players who are not on the map, and luck in the corner. */

/* The Lucky Block's own light, borrowed: this is the same kind of moment, so it should feel like one. */
.fab-abuse-headline { position: relative; overflow: visible; }
.fab-abuse-headline__body { position: relative; z-index: 1; display: grid; justify-items: center; gap: 0.35rem; }
.fab-abuse-headline__rays {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 150vmax;
  height: 150vmax;
  translate: -50% -50%;
  z-index: 0;
  pointer-events: none;
  background: repeating-conic-gradient(from 0deg, transparent 0 4deg, rgb(255 209 102 / 16%) 4deg 7deg, transparent 7deg 13deg);
  mask-image: radial-gradient(circle, transparent 0 6%, #000 14%, transparent 46%);
  -webkit-mask-image: radial-gradient(circle, transparent 0 6%, #000 14%, transparent 46%);
  opacity: 0;
  animation: fab-abuse-rays 2.8s ease-out forwards, fab-lucky-turn 18s linear infinite;
}
@keyframes fab-abuse-rays { 0% { opacity: 0; } 14% { opacity: 0.55; } 70% { opacity: 0.4; } 100% { opacity: 0; } }

.fab-abuse-headline__burst {
  position: absolute;
  inset: -40%;
  z-index: 0;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(circle, #fff6d5 0%, rgb(255 201 60 / 80%) 32%, transparent 70%);
  opacity: 0;
  animation: fab-abuse-burst 800ms ease-out forwards;
}
@keyframes fab-abuse-burst { 0% { opacity: 0.9; transform: scale(0.3); } 100% { opacity: 0; transform: scale(1.25); } }

.fab-abuse-headline__ring {
  position: absolute;
  inset: -10%;
  z-index: 0;
  border-radius: 50%;
  border: 4px solid rgb(255 209 102 / 90%);
  opacity: 0;
  pointer-events: none;
  animation: fab-abuse-ring 900ms cubic-bezier(0.16, 0.84, 0.44, 1) forwards;
}
.fab-abuse-headline__ring--late { animation-delay: 160ms; border-width: 2px; }
@keyframes fab-abuse-ring { 0% { opacity: 0.85; transform: scale(0.45); } 100% { opacity: 0; transform: scale(1.7); } }

/* Coins: more of them, drifting rather than dropping straight (Nick wanted a downpour). */
.fab-abuse-coin {
  font-size: var(--size, 1.6rem);
  animation: fab-abuse-fall var(--fall-time, 2s) linear var(--fall-delay, 0s) forwards;
}
@keyframes fab-abuse-fall {
  from { transform: translate(0, 0) rotate(0); opacity: 1; }
  to { transform: translate(var(--drift, 0), 108vh) rotate(var(--spin, 360deg)); opacity: 0.9; }
}

/* Faces from the room, rising up the right like smoke: each takes its own lane and its own wobble. */
.fab-abuse-emotes { position: fixed; inset: 0 0 0 auto; width: 9rem; z-index: 1080; pointer-events: none; overflow: hidden; }
.fab-abuse-emote {
  position: absolute;
  right: var(--lane, 1rem);
  bottom: 6rem;
  font-size: var(--size, 1.6rem);
  opacity: 0;
  animation: fab-abuse-rise var(--rise-time, 3.5s) cubic-bezier(0.3, 0.1, 0.4, 1) forwards;
}
@keyframes fab-abuse-rise {
  0% { opacity: 0; transform: translate(0, 0) rotate(0) scale(0.6); }
  12% { opacity: 1; transform: translate(0, -1rem) rotate(0) scale(1); }
  50% { transform: translate(calc(var(--sway) * -1), -40vh) rotate(var(--tilt)) scale(1.05); }
  100% { opacity: 0; transform: translate(var(--sway), -80vh) rotate(calc(var(--tilt) * -1)) scale(0.85); }
}

/* Somebody did something. Quieter than a shout, and in the SAME column as one: two stacks fought each other and the
   ON AIR banner over the same few pixels. */
.fab-abuse-notice {
  max-width: min(28rem, 92vw);
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  background: rgb(12 4 38 / 88%);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 14%);
  color: #fff;
  font-size: 0.85rem;
  font-weight: 600;
  text-align: center;
  opacity: 0;
  transform: translateY(-0.6rem);
  transition: opacity 200ms ease, transform 240ms ease;
}
.fab-abuse-notice.is-in { opacity: 1; transform: none; }

/* Off the map: a bar above the tab bar, so nobody misses that it is happening. */
.fab-abuse-bar {
  position: fixed;
  left: 50%;
  translate: -50%;
  bottom: calc(5.5rem + env(safe-area-inset-bottom));
  z-index: 1035;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  max-width: min(30rem, calc(100vw - 1.5rem));
  padding: 0.5rem 0.6rem 0.5rem 0.9rem;
  border-radius: 999px;
  background: linear-gradient(120deg, #ff3b3b, #ff8a29);
  color: #fff;
  box-shadow: 0 0.6rem 1.6rem rgb(12 4 38 / 45%);
}
.fab-abuse-bar__dot { width: 0.55rem; height: 0.55rem; border-radius: 50%; background: #fff; flex: none; animation: fab-abuse-pulse 1.1s ease-in-out infinite; }
.fab-abuse-bar__link { display: grid; min-width: 0; color: inherit; text-decoration: none; line-height: 1.2; }
.fab-abuse-bar__link strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fab-abuse-bar__go { font-size: 0.75rem; opacity: 0.9; }
.fab-abuse-bar__close { margin-left: auto; flex: none; border: 0; background: rgb(255 255 255 / 18%); color: #fff; border-radius: 50%; width: 1.9rem; height: 1.9rem; display: grid; place-items: center; }

/* Luck, and the faces to answer with, on the map. */
.fab-hunt-luck {
  position: absolute;
  top: var(--fab-below-chip);
  left: 0.75rem;
  z-index: 2;
  padding: 0.35rem 0.7rem;
  border-radius: 999px;
  background: linear-gradient(120deg, #2fbf62, #9cf06b);
  color: #06260f;
  font-weight: 800;
  font-size: 0.9rem;
  box-shadow: 0 0.4rem 1rem rgb(12 4 38 / 35%);
}
.fab-hunt-emotes {
  position: absolute;
  right: 0.75rem;
  bottom: calc(6.5rem + env(safe-area-inset-bottom));
  z-index: 3;
  display: grid;
  gap: 0.35rem;
}
.fab-hunt-emote {
  width: 2.6rem;
  height: 2.6rem;
  border: 0;
  border-radius: 50%;
  background: rgb(12 4 38 / 72%);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 18%);
  font-size: 1.25rem;
  line-height: 1;
}
.fab-hunt-emote:active { transform: scale(0.88); }

/* The console's luck group. */
.fab-abuse__luck { margin-top: 1rem; }
.fab-abuse__luck-now { font-weight: 800; color: var(--fab-slime); }
.fab-abuse__luck-group { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0.4rem; }
.fab-abuse__luck-group form { display: contents; }
.fab-abuse__luck-btn {
  padding: 0.55rem 0.25rem;
  border: 0;
  border-radius: var(--bs-border-radius);
  background: var(--bs-secondary-bg);
  color: var(--bs-body-color);
  font-weight: 700;
}
.fab-abuse__luck-btn.is-on { background: linear-gradient(120deg, #2fbf62, #9cf06b); color: #06260f; opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .fab-abuse-headline__rays, .fab-abuse-headline__burst, .fab-abuse-headline__ring, .fab-abuse-emote { animation-duration: 1ms; animation-iteration-count: 1; }
  .fab-abuse-notice { transition-duration: 1ms; }
}

/* A tool lying on the map, waiting to be walked to (Nick, 2026-09-20). Deliberately unlike a brainrot pin: a soft
   square with a glow under it, so nobody taps it expecting a catch. */
.fab-pickup__pin { position: relative; display: grid; place-items: center; width: 52px; height: 58px; }
.fab-pickup__icon {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 0.9rem;
  background: linear-gradient(135deg, #ffd166, #ff8a29);
  box-shadow: 0 0.35rem 0.8rem rgb(12 4 38 / 45%), inset 0 0 0 2px rgb(255 255 255 / 55%);
  font-size: 1.25rem;
  line-height: 1;
  animation: fab-pickup-bob 2.4s ease-in-out infinite;
}
.fab-pickup__glow {
  position: absolute;
  bottom: 0.15rem;
  width: 1.8rem;
  height: 0.5rem;
  border-radius: 50%;
  background: rgb(255 201 60 / 45%);
  filter: blur(3px);
  animation: fab-pickup-shadow 2.4s ease-in-out infinite;
}
@keyframes fab-pickup-bob { 0%, 100% { transform: translateY(0) rotate(-3deg); } 50% { transform: translateY(-6px) rotate(3deg); } }
@keyframes fab-pickup-shadow { 0%, 100% { transform: scale(1); opacity: 0.45; } 50% { transform: scale(0.75); opacity: 0.25; } }

/* The curtain. Two panels close over the screen, the goodbye sits in the gap, then they lift. */
.fab-abuse-curtain { position: fixed; inset: 0; z-index: 1085; pointer-events: none; display: grid; place-items: center; }
.fab-abuse-curtain__panel {
  position: absolute;
  left: 0;
  right: 0;
  height: 52%;
  background: linear-gradient(180deg, #2a0b4a, #12063a);
  box-shadow: 0 0 2rem rgb(0 0 0 / 55%);
  transition: transform 900ms cubic-bezier(0.4, 0, 0.2, 1);
}
.fab-abuse-curtain__panel--top { top: 0; transform: translateY(-101%); }
.fab-abuse-curtain__panel--bottom { bottom: 0; transform: translateY(101%); }
.fab-abuse-curtain.is-closing .fab-abuse-curtain__panel--top,
.fab-abuse-curtain.is-closing .fab-abuse-curtain__panel--bottom { transform: translateY(0); }
.fab-abuse-curtain.is-opening .fab-abuse-curtain__panel--top { transform: translateY(-101%); }
.fab-abuse-curtain.is-opening .fab-abuse-curtain__panel--bottom { transform: translateY(101%); }

.fab-abuse-curtain__card {
  position: relative;
  z-index: 1;
  display: grid;
  justify-items: center;
  gap: 0.3rem;
  padding: 0 1.5rem;
  text-align: center;
  color: #fff;
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 400ms ease 700ms, transform 500ms ease 700ms;
}
.fab-abuse-curtain.is-closing .fab-abuse-curtain__card { opacity: 1; transform: none; }
.fab-abuse-curtain.is-opening .fab-abuse-curtain__card { opacity: 0; transition-delay: 0ms; }
.fab-abuse-curtain__wave { font-size: 3rem; line-height: 1; animation: fab-abuse-wave 1.6s ease-in-out infinite; }
.fab-abuse-curtain__text { font-size: clamp(1.4rem, 6vw, 2.1rem); font-weight: 800; text-wrap: balance; }
.fab-abuse-curtain__who { font-size: 0.9rem; opacity: 0.75; }
@keyframes fab-abuse-wave { 0%, 100% { transform: rotate(-18deg); } 50% { transform: rotate(18deg); } }

.fab-abuse__tools { margin-top: 1rem; }
.fab-abuse__bye { display: flex; gap: 0.4rem; margin-top: 0.4rem; max-width: 18rem; }

@media (prefers-reduced-motion: reduce) {
  .fab-pickup__icon, .fab-pickup__glow, .fab-abuse-curtain__wave { animation: none; }
  .fab-abuse-curtain__panel, .fab-abuse-curtain__card { transition-duration: 1ms; }
}

/* Asleep (Nick, 2026-09-20): the card goes quiet, the bars stand still, and the sleeper bobs. */
.care__asleep { background: rgb(47 123 255 / 12%); box-shadow: inset 0 0 0 1px rgb(47 123 255 / 30%); }
.care--asleep .care__art { filter: saturate(0.85) brightness(0.92); }
.care--asleep .need-bar__fill { animation: none; }
.care__zzz { animation: fab-care-zzz 2.8s ease-in-out infinite; }
@keyframes fab-care-zzz { 0%, 100% { transform: translateY(0) rotate(-6deg); } 50% { transform: translateY(-5px) rotate(6deg); } }
@media (prefers-reduced-motion: reduce) { .care__zzz { animation: none; } }

/* A clover out, and a brainrot being told to wait (Nick, 2026-09-20). */
.fab-hunt-banner--clover { background: linear-gradient(120deg, #2fbf62, #9cf06b); color: #06260f; font-weight: 800; }
.fab-spawn.is-snoozing .fab-spawn__disc { animation: fab-spawn-snooze 1.1s ease-in-out 2; }
@keyframes fab-spawn-snooze {
  0%, 100% { transform: scale(1) rotate(0); }
  30% { transform: scale(1.12) rotate(-8deg); }
  60% { transform: scale(1.06) rotate(8deg); }
}
@media (prefers-reduced-motion: reduce) { .fab-spawn.is-snoozing .fab-spawn__disc { animation: none; } }

/* Asleep, on the rooms grid (Nick, 2026-09-20): the corner the ghost uses, so one glance says who is out. */
.brainrot-card__zzz { position: absolute; top: 0.5rem; right: 0.75rem; font-size: 1.25rem; animation: fab-care-zzz 2.8s ease-in-out infinite; }
.brainrot-card--asleep .brainrot-card__art { filter: saturate(0.85) brightness(0.92); }
@media (prefers-reduced-motion: reduce) { .brainrot-card__zzz { animation: none; } }

/* The Codes machine (Nick, 2026-09-20): our keypad, not the phone's. Chunky keys, a lit screen, and the same purple
   the rest of the game is made of rather than the grey plastic of the reference. */
.fab-codes .modal-content { border-radius: var(--bs-border-radius-xl); }
.fab-codes__screen {
  display: block;
  margin-bottom: 0.9rem;
  padding: 0.75rem 0.5rem;
  border-radius: var(--bs-border-radius);
  background: #0d0726;
  box-shadow: inset 0 0 0 2px rgb(255 255 255 / 12%), inset 0 0.4rem 1rem rgb(0 0 0 / 45%);
  color: #6ef0a8;
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-align: center;
  text-shadow: 0 0 0.6rem rgb(110 240 168 / 65%);
}
.fab-codes__pad { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.5rem; }
.fab-codes__key {
  padding: 0.85rem 0.25rem;
  border: 0;
  border-radius: var(--bs-border-radius);
  background: linear-gradient(180deg, #4a2a8f, #351d6b);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 16%), 0 0.2rem 0 rgb(0 0 0 / 35%);
  color: #fff;
  font-size: 1.2rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.fab-codes__key:active { transform: translateY(2px); box-shadow: inset 0 0 0 1px rgb(255 255 255 / 16%); }
.fab-codes__key--del { background: linear-gradient(180deg, #8a3550, #62203a); font-size: 0.9rem; }
.fab-codes__key--go { background: linear-gradient(180deg, #2fbf62, #1d8a47); font-size: 0.9rem; }
.fab-codes__key--go:disabled { background: linear-gradient(180deg, #3a3550, #2a2540); color: rgb(255 255 255 / 45%); }
.fab-codes__hint { margin: 0.8rem 0 0; font-size: 0.8rem; color: var(--bs-secondary-color); text-align: center; }

/* Composing a code in the back office: one row per reward, every field on show so the form is one shape. */
/* One gift per box, and only the fields that gift needs (Nick, 2026-09-22). A box is a box so it reads as one thing
   rather than a row of unrelated dropdowns. */
.fab-code-rewards { display: grid; gap: 0.75rem; }
.fab-code-reward {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 0.6rem;
  margin: 0;
  padding: 0.75rem;
  border: 0;
  border-radius: var(--bs-border-radius-lg);
  background: var(--bs-secondary-bg);
}
.fab-code-reward.is-empty { opacity: 0.6; }
.fab-code-reward__n { flex: 0 0 100%; margin: 0; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--bs-secondary-color); }
.fab-code-reward__field { display: grid; gap: 0.2rem; flex: 1 1 11rem; min-width: 0; margin: 0; }
.fab-code-reward__field > span { font-size: 0.8rem; font-weight: 600; }
.fab-code-reward__blurb { flex: 0 0 100%; margin: 0; font-size: 0.8rem; color: var(--bs-secondary-color); }
