/* barracks.css: Your Crew (barracks tile grid, toolbar, group tabs) and the pet detail page. */
/* ===== BARRACKS: tile grid, toolbar, group tabs ===== */
.pet-grid-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 16px;
    margin-top: 16px;
}
@media (min-width: 768px) and (max-width: 1024px) {
    .pet-grid-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) { .pet-grid-cards { grid-template-columns: minmax(0, 1fr); } }

/* Roster stat strip (sits inside #pet-grid so it refreshes with the filtered view) */
.roster-summary {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px 14px;
    margin-top: 14px;
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
}
.roster-summary__title { color: var(--text-muted); }
.roster-summary__stats { display: flex; flex-wrap: wrap; gap: 8px 22px; margin: 0; }
.roster-summary__stat { display: flex; align-items: baseline; gap: 6px; }
.roster-summary__stat dt { font-size: 0.78rem; color: var(--text-muted); }
.roster-summary__stat dd { margin: 0; font-size: 0.95rem; font-weight: 700; color: var(--text-primary); }
.roster-summary__species { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.roster-summary__species-chip {
    padding: 2px 10px;
    font-size: 0.8rem;
    color: var(--text-secondary);
    background: var(--bg-hover);
    border-radius: var(--radius-pill);
}
.roster-summary__species-chip span { color: var(--text-primary); font-weight: 700; }

.pet-card {
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    gap: 10px;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
@media (hover: hover) { .pet-card:hover { border-color: var(--color-primary); } }
.pet-card__link { display: block; text-align: center; color: inherit; }
@media (hover: hover) { .pet-card__link:hover { text-decoration: none; } }
.pet-card__media {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1 / 1;
    background: var(--bg-subtle);
    border-radius: var(--radius-md);
    overflow: hidden;
    margin-bottom: 10px;
}
.pet-card__media img { width: 100%; height: 100%; object-fit: contain; border-radius: var(--radius-md); }
.pet-card__name { margin: 0; font-size: 1.02rem; }
.pet-card__meta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    flex-wrap: wrap;
}
.pet-card__level {
    font-size: 0.66rem;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    background: var(--bg-subtle);
    border: 1px solid var(--border-subtle);
    color: var(--text-secondary);
}
.pet-card__swatches { display: flex; justify-content: center; gap: 0; }
.pet-card__stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 4px;
    padding: 8px 0;
    border-top: 1px solid var(--border-subtle);
    border-bottom: 1px solid var(--border-subtle);
}
.pet-card__stat { display: flex; flex-direction: column; align-items: center; gap: 1px; }
.pet-card__stat-label {
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.56rem;
    color: var(--text-muted);
}
.pet-card__stat-val { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text-primary); }
.pet-card__foot { display: flex; flex-direction: column; gap: 8px; margin-top: auto; align-items: stretch; }
.pet-card__foot .pet-group-manage { display: block; margin-top: 0; }
/* A card is only ~200px wide and .state-chip is nowrap by default, so a long chip
   ("🥚 Cooldown 2 days, 5 hours") spilled straight past the card border. Inside a
   card, chips wrap and stay within the content box instead; the precise timestamp
   lives in the title attribute either way. */
.pet-card > .state-chip,
.pet-card__foot .state-chip {
    align-self: center;
    max-width: 100%;
    white-space: normal;
    text-align: center;
    line-height: 1.35;
}
.stat-readout .state-chip {
    max-width: 100%;
    white-space: normal;
    overflow-wrap: anywhere;
    text-align: center;
    line-height: 1.35;
}

/* Rearrange mode (.pet-card--compact, set by _pet_card.html when is_reordering): the
   full card's mutation/tag/marketplace/busy/cooldown/sickness/rested chips, swatches,
   stats grid and squad/group/tag menus are dropped from the DOM entirely (see the
   template's own comment), so this only has to lay out what's left: image, name,
   breed, level, trait. A single wide row per pet, rather than the full card's tall
   vertical stack, is what actually lets more than one row fit on screen at once. */
.pet-card--compact {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 12px;
    padding: 8px 40px 8px 12px;
}
.pet-card--compact .pet-card__link {
    display: flex;
    align-items: center;
    gap: 8px;
    text-align: left;
    flex: 1 1 auto;
    min-width: 0;
}
.pet-card--compact .pet-card__media {
    width: 40px;
    flex: 0 0 40px;
    margin-bottom: 0;
}
.pet-card--compact .pet-card__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.pet-card--compact .pet-card__meta {
    flex: 0 0 auto;
}
.pet-card--compact .trait-chip {
    flex: 0 0 auto;
}

/* Compact roster view (.pet-card--roster-compact, set by _pet_card.html when
   is_owner and user.preferences.barracks_view_compact): unlike rearrange mode above,
   this drops the trait chip and species eyebrow too. Nothing survives but the
   thumbnail, name, and level (plus a bare stat-point arrow, see .pet-card__stat-arrow
   below), so the grid packs into narrower tiles instead of the row layout rearrange
   mode uses. A fixed 6-column grid, not auto-fill: the point of this view is a neat,
   even block of thumbnails (4 rows of 6 for a full page of 24), which auto-fill's
   "as many 130px+ columns as fit" can't promise at every width. Stepped down at the
   same breakpoints the base .pet-grid-cards already uses, and placed later in this
   file than those, so it wins at every width it's active for: see the note on that
   base rule if this class is ever reordered. */
.pet-grid-cards--roster-compact {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 10px;
}
@media (min-width: 768px) and (max-width: 1024px) {
    .pet-grid-cards--roster-compact { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (width < 768px) {
    .pet-grid-cards--roster-compact { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
    .pet-grid-cards--roster-compact { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.pet-card--roster-compact {
    padding: 10px;
    gap: 6px;
}
.pet-card--roster-compact .pet-card__media {
    margin-bottom: 0;
}
.pet-card--roster-compact .pet-card__name {
    font-size: 0.88rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The bare ⬆ next to the level pill in compact view: same "ready to spend" colour as
   .state-chip--ready, but sized to match .pet-card__level rather than a full chip's
   text padding, since there's no label text here for the padding to wrap. */
.pet-card__stat-arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
    border-radius: var(--radius-pill);
    background: var(--bg-subtle);
    border: 1px solid color-mix(in srgb, var(--color-reward-ink) 50%, var(--border-color));
    color: var(--color-reward-ink);
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1;
}

.barracks-toolbar {
    display: flex;
    flex-direction: row;
    gap: 16px;
    flex-wrap: wrap;
    align-items: flex-end;
    margin: 16px 0;
    padding: 14px 16px;
    background: var(--bg-cool);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
}
.barracks-toolbar label {
    min-width: 160px;
    gap: 5px;
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-size: 0.66rem;
    color: var(--text-muted);
}
.barracks-filter-disclosure {
    display: block;
    flex: 0 0 100%;
    width: 100%;
}
.barracks-filter-disclosure > summary { display: none; }
.barracks-toolbar__fields {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    flex: 0 0 100%;
    width: 100%;
    min-width: 0;
    gap: 12px;
}
.barracks-toolbar select,
.barracks-toolbar input[type="search"] { font-family: var(--font-body); text-transform: none; letter-spacing: normal; font-size: 0.95rem; color: var(--text-primary); }
.barracks-toolbar input[type="search"] { margin: 0; }
/* Result count + clear-filters sit at the end of the toolbar row, pushed right. */
.barracks-toolbar__count {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    align-self: center;
}
.barracks-toolbar__count + .btn { align-self: center; }
.page-position { color: var(--text-muted); padding: 0 6px; }

@media (max-width: 1024px) {
    .barracks-toolbar { gap: 10px; padding: 12px; }
    .barracks-toolbar label { min-width: 140px; }
}
@media (max-width: 768px) {
    .barracks-toolbar { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
    .barracks-filter-disclosure { display: block; grid-column: 1 / -1; min-width: 0; }
    .barracks-filter-disclosure > summary {
        display: flex;
        align-items: center;
        justify-content: space-between;
        min-height: 44px;
        padding: 10px 12px;
        border: 1px solid var(--border-color);
        border-radius: var(--radius-md);
        color: var(--text-primary);
        font-weight: 700;
        cursor: pointer;
        list-style: none;
    }
    .barracks-filter-disclosure > summary::-webkit-details-marker { display: none; }
    .barracks-filter-disclosure > summary::after { content: '＋'; color: var(--color-primary); }
    .barracks-filter-disclosure[open] > summary::after { content: '−'; }
    .barracks-toolbar__fields { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; padding-top: 10px; flex: none; }
    .barracks-toolbar label { min-width: 0; }
    .barracks-toolbar__fields label:first-child { grid-column: auto; }
    .barracks-toolbar__count { margin-left: 0; min-width: 0; }
    .barracks-toolbar__count + .btn { justify-self: end; }
}
@media (max-width: 380px) {
    .barracks-toolbar__fields label:first-child { grid-column: 1 / -1; }
}

/* Stud Market's "Advanced search" disclosure: markings (checkbox, any-match) and
   generation (exact). Collapsed by default (see stud_market.html for why it opens
   itself when one of its own filters is already active), a plain <details> so it
   needs no JS and degrades cleanly with none. */
.stud-advanced-search {
    flex: 0 0 100%;
    width: 100%;
}
.stud-advanced-search > summary {
    cursor: pointer;
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.72rem;
    color: var(--text-muted);
}
.stud-advanced-search[open] > summary { margin-bottom: 10px; }
.stud-advanced-search__fields {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    align-items: flex-start;
    padding-top: 4px;
}
.marking-filter-list {
    border: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 6px 14px;
    max-width: 520px;
    min-width: 0;
}
.marking-filter-list legend {
    flex: 0 0 100%;
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-size: 0.66rem;
    color: var(--text-muted);
    padding: 0 0 5px;
}
.marking-filter-option {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-width: 120px;
    font-size: 0.85rem;
    color: var(--text-primary);
    font-weight: 400;
    text-transform: none;
    letter-spacing: normal;
}
@media (pointer: coarse) {
    /* Same "the 13px UA checkbox is the smallest target on the page" fix used for the
       dressing room's own checkbox rows: enlarge the checkbox and give its label row
       the standard 44px floor rather than leaving a tiny tap target. */
    .marking-filter-option { min-height: 44px; }
    .marking-filter-option input[type="checkbox"] { width: 20px; height: 20px; }
}

.pet-group-tabs {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 4px;
}
.pet-group-tab {
    display: inline-block;
    padding: 8px 14px;
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    color: var(--text-secondary);
    font-weight: 500;
    text-decoration: none;
}
@media (hover: hover) { .pet-group-tab:hover { background: var(--bg-hover); } }
.pet-group-tab-wrap { display: flex; align-items: center; position: relative; }
.pet-group-tab-wrap.active .pet-group-tab,
a.pet-group-tab.active {
    background: var(--bg-surface);
    color: var(--text-primary);
    border: 1px solid var(--border-color);
    border-bottom: 1px solid var(--bg-surface);
    margin-bottom: -1px;
}
.pet-group-tab-menu-btn {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 4px 6px;
}
.pet-group-tab-menu,
.pet-group-manage-menu {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 10;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 160px;
}
.pet-group-tab-menu form { flex-direction: row; max-width: none; }
.pet-group-add-form { flex-direction: row; max-width: none; align-items: center; gap: 8px; margin-left: 4px; }
.pet-group-add-form input { margin: 0; }
/* The containing block for the "+ New Group" / "Manage Tags" panels. Without
   `position: relative` here the absolutely-positioned .pet-group-tab-menu inside
   escapes to the initial containing block and renders a full viewport-height
   below the page, at the far left: the button appears to do nothing at all.
   game/test_css_positioning.py is the guard. */
.pet-group-tab-add { display: inline-block; position: relative; }

.pet-group-manage { display: inline-block; position: relative; margin-top: 8px; }
.pet-group-checkbox { flex-direction: row; align-items: center; gap: 8px; font-weight: 400; }

/* Group tabs: icon, color accent, default marker, reorder + edit menus.
   The color rides an inset top box-shadow on the tab link itself (inline style,
   set per-group), rather than a swatch square beside the icon: box-shadow
   respects the tab's own top-rounded border-radius, so the accent reads as a
   rounded color bar along the tab's top edge instead of a second glyph. The
   icon stays aria-hidden decoration; the tab's text name is still the primary
   distinguishing label (never colour alone), per the a11y rules. */
.pet-group-tabs__sortable { display: contents; }
.pet-group-tab--colored { padding-top: 10px; }
.pet-group-tab__icon { margin-right: 4px; }
.pet-group-tab__default { color: var(--color-reward); margin-left: 4px; }
.pet-group-tab.active[aria-pressed="true"],
.pet-group-tab.active { background: var(--bg-hover); }
.pet-group-edit-row { flex-direction: row; align-items: center; gap: 6px; flex-wrap: wrap; }
.pet-group-icon-input { width: 3.2em; text-align: center; }
.pet-group-tab-reorder { display: flex; gap: 6px; }

/* Preset tag chip: the card display, the pet-detail pill, and the card's quick-add
   search box. Tags carry no per-tag colour (a fixed preset catalog, emoji-only). */
.pet-tag-chip { color: var(--text-secondary); }
.pet-tag-preset-search input { margin: 0; width: 100%; }

/* Pet detail Manage section (assign preset tags + custom tabs), lifted from the donor
   codebase's dragon-detail "Manage" panel. Two columns on wide screens, stacked on
   narrow ones; each column is its own swap target (see _pet_detail_tags/tabs.html). */
.pet-detail-manage-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}
@media (max-width: 640px) {
    .pet-detail-manage-grid { grid-template-columns: 1fr; }
}
.pet-detail-manage-col h3 { margin: 0 0 8px; font-size: 0.95rem; }
/* Manage is folded by default (_pet_detail_manage.html): the summary is the panel header,
   with what the pet holds beside the title, and the open body keeps the panel's own type. */
.pet-manage-fold { margin: 0; font-size: inherit; color: inherit; }
.pet-manage-fold > summary { flex-wrap: wrap; gap: 4px 10px; }
.pet-manage-summary { font-weight: 400; font-size: 0.85rem; }
.pet-manage-fold > .pet-detail-manage-grid { margin-top: 12px; }
.pet-detail-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; min-height: 1.6em; }
.pet-tag-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 6px 3px 10px;
    border-radius: var(--radius-pill);
}
.pet-tag-pill__remove {
    background: none;
    border: none;
    color: inherit;
    cursor: pointer;
    line-height: 1;
    padding: 2px 4px;
    font-size: 0.9rem;
}
/* Split deliberately: only the :hover half takes the hover guard. Wrapping the pair
   together would put :focus-visible behind (hover: hover) too and delete the keyboard
   focus colour on every touch device, which is the opposite of the point. */
.pet-tag-pill__remove:focus-visible { color: var(--color-error); }
@media (hover: hover) { .pet-tag-pill__remove:hover { color: var(--color-error); } }
.pet-detail-add-select { width: 100%; }

/* Batch multi-select mode: per-card checkbox + the floating action bar. */
.pet-card__batch {
    position: absolute;
    top: 6px;
    left: 6px;
    z-index: 3;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 2px 4px;
    line-height: 0;
}
.barracks-batch-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin: 10px 0;
    padding: 10px 14px;
    background: var(--bg-surface);
    border: 1px solid var(--color-primary);
    border-radius: var(--radius-md);
}
.barracks-batch-bar__count { font-family: var(--font-mono); font-size: 0.85rem; color: var(--color-primary); }
.barracks-batch-bar__select {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    flex-basis: 100%;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border-color);
}
.barracks-batch-bar__close { margin-left: auto; }
/* Each batch form is a column (target list above its own action buttons) so the
   two buttons that act on the checked pets and the one that acts on every match
   can't be mistaken for each other across a single wrapped row. */
.barracks-batch-form {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    flex-direction: column;
    max-width: none;
    margin: 0;
}
.barracks-batch-form select { margin: 0; }
.barracks-batch-form__actions { display: flex; flex-wrap: wrap; gap: 6px; }
.barracks-batch-form__label { display: block; font-size: 0.85rem; margin-bottom: 4px; }
.barracks-batch-form__label .hint { font-weight: 400; }
.barracks-batch-select { min-width: 190px; }

/* ===== PET DETAIL PAGE ===== */
.pet-detail-nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 14px;
}
.pet-detail-position { font-size: 0.9em; }

.pet-detail-hero { display: flex; gap: 24px; flex-wrap: wrap; }
/* One-time "what's next" strip after a Captain's first companion (pet_detail.html). */
.first-pet-next {
    display: flex;
    flex-direction: column;
    gap: 10px;
    border-left: 3px solid var(--color-primary);
}
.first-pet-next p { margin: 0; }
.first-pet-next__actions { display: flex; flex-wrap: wrap; gap: 8px; }
.pet-detail-name-row h1 { font-family: var(--font-display); font-size: clamp(1.6rem, 1.2rem + 1.8vw, 2.2rem); letter-spacing: -0.02em; }
.pet-detail-image-col { flex: 0 1 500px; min-width: 0; max-width: 100%; }
.pet-detail-image-col img { display: block; width: 100%; max-width: 500px; height: auto; border-radius: var(--radius-md); }
.pet-detail-image-col .btn { margin-top: 12px; }
.pet-detail-info-col { flex: 1 1 260px; display: flex; flex-direction: column; gap: 10px; }

/* Frame around _pet_image.html's own include: establishes the containing block
   for .pet-sparkle-fx's absolute overlay, without editing that shared partial
   (it's reused by the Mutation Workshop, Marking Studio, dressing room, etc.). */
.pet-detail-image-frame { position: relative; }

/* Sparkle button + share cluster share one row. .pet-detail-share also backs
   .profile-share (its own margin-top is load-bearing there), so the shared
   spacing lives on this wrapper instead of being edited on that class. */
.pet-detail-actions-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 16px;
}
.pet-detail-actions-row .pet-detail-share { margin-top: 0; }
.pet-sparkle-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 5px 12px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border-color);
    background: var(--bg-subtle);
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.4;
    cursor: pointer;
}
.pet-sparkle-btn.is-active {
    border-color: var(--color-primary);
    background: color-mix(in srgb, var(--color-primary) 16%, var(--bg-subtle));
    color: var(--text-primary);
}
@media (hover: hover) {
    .pet-sparkle-btn:hover { border-color: var(--color-primary); }
}

/* Decorative overlay, fired briefly after a successful sparkle by the
   pet-sparkled HX-Trigger event (see pet_detail.html's .pet-detail-image-frame
   x-data and toggle_pet_sparkle_view). Confined to the image's own box via the
   .pet-detail-image-frame containing block above. */
.pet-sparkle-fx {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    contain: paint;
}
.pet-sparkle-glyph {
    position: absolute;
    font-size: 2rem;
    opacity: 0;
    animation: pet-sparkle-pop 1.2s ease-out;
}
.pet-sparkle-glyph:nth-child(1) { top: 8%; left: 12%; animation-delay: 0s; }
.pet-sparkle-glyph:nth-child(2) { top: 15%; right: 10%; animation-delay: 0.15s; }
.pet-sparkle-glyph:nth-child(3) { top: 40%; left: 45%; animation-delay: 0.3s; }
@keyframes pet-sparkle-pop {
    0%   { opacity: 0; transform: scale(0.5) rotate(-8deg); }
    35%  { opacity: 1; transform: scale(1.15) rotate(6deg); }
    100% { opacity: 0; transform: scale(0.9) rotate(0deg); }
}
/* Belt-and-suspenders alongside the global body.reduced-motion / prefers-reduced-motion
   wildcard clamp (which already crushes animation-duration/iteration-count to near-zero):
   still shows the glyphs so a reduced-motion player gets the same acknowledgment, just
   static rather than popping/rotating. Same tradeoff .hatch-modal__sparkles already makes. */
@media (prefers-reduced-motion: reduce) {
    .pet-sparkle-glyph { animation: none; opacity: 1; }
}
body.reduced-motion .pet-sparkle-glyph { animation: none; opacity: 1; }

/* Persistent ambient effect (unlocked at pets.services.SPARKLE_FX_UNLOCK_THRESHOLD
   sparkles, owner-toggled): distinct from the one-shot burst above. */
.pet-sparkle-ambient {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    contain: paint;
}
.pet-sparkle-ambient-glyph {
    position: absolute;
    font-size: 1.1rem;
    opacity: 0;
    animation: pet-sparkle-twinkle 2.6s ease-in-out infinite;
}
.pet-sparkle-ambient-glyph:nth-child(1) { top: 10%; left: 8%; animation-delay: 0s; }
.pet-sparkle-ambient-glyph:nth-child(2) { top: 22%; right: 14%; animation-delay: 0.6s; }
.pet-sparkle-ambient-glyph:nth-child(3) { top: 55%; left: 18%; animation-delay: 1.2s; }
.pet-sparkle-ambient-glyph:nth-child(4) { top: 68%; right: 10%; animation-delay: 1.8s; }
.pet-sparkle-ambient-glyph:nth-child(5) { top: 40%; left: 50%; animation-delay: 2.2s; }
@keyframes pet-sparkle-twinkle {
    0%, 100% { opacity: 0; transform: scale(0.6); }
    50%      { opacity: 0.9; transform: scale(1); }
}
/* Unlike the one-shot acknowledgment burst above (which still shows a static
   glint under reduced motion, since it's confirming a click), this is pure
   ongoing decoration with no informational payload: hidden outright rather
   than frozen-visible, matching reduced_motion's own "non-essential
   animations" framing exactly. */
@media (prefers-reduced-motion: reduce) {
    .pet-sparkle-ambient { display: none; }
}
body.reduced-motion .pet-sparkle-ambient { display: none; }

.pet-sparkle-fx-toggle,
.pet-sparkle-fx-locked { margin-top: 10px; font-size: 0.85rem; }

.pet-detail-name-row { display: flex; align-items: center; gap: 10px; }
.pet-detail-name-row h1 { margin: 0; }
.pet-detail-name-editor { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.pet-detail-name-editor input {
    padding: 6px 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: var(--bg-surface);
    color: var(--text-primary);
}

.swatch-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.swatch-label { color: var(--text-muted); font-size: 11px; text-transform: uppercase; width: 40px; flex-shrink: 0; }

.appearance-grid {
    display: grid;
    grid-template-columns: minmax(140px, 180px) minmax(180px, 1fr) minmax(200px, 1fr);
    gap: 20px;
}
@media (max-width: 700px) { .appearance-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) { .appearance-grid { grid-template-columns: 1fr; } }
.appearance-col { display: flex; flex-direction: column; gap: 8px; }
.appearance-col h3 { margin: 0 0 4px 0; font-size: 15px; color: var(--text-primary); }
.appearance-col-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.appearance-col-header h3 { margin: 0; }

.marking-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: var(--bg-subtle);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--border-color);
    padding: 7px 10px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    color: var(--text-primary);
}

/* Marking Studio's current-layers list: a leading info cluster (swatch, name,
   opacity) grouped so .marking-row's justify-content:space-between splits it from
   the trailing Remove form instead of spreading every child evenly. */
.ms-marking-list { display: flex; flex-direction: column; gap: 8px; }
.ms-marking-row__info { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Marking Studio's Placement picker: a pet's existing layers are read-only rows
   (.ms-placement-existing, an indented .marking-row variant) with a selectable
   .inline-row radio slot above/below/between them for where the NEW marking goes.
   :has(input:checked) mirrors .mw-swatch's own selected-state treatment. */
.ms-placement-list { display: flex; flex-direction: column; gap: 2px; }
.ms-placement-slot { display: flex; align-items: center; gap: 8px; padding: 4px 8px; border-radius: var(--radius-sm); }
.ms-placement-slot:has(input:focus-visible) { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.ms-placement-slot:has(input:checked) { background: var(--bg-hover); font-weight: 600; }
.ms-placement-existing {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: 22px;
    padding: 6px 10px;
    background: var(--bg-subtle);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--border-color);
    border-radius: var(--radius-sm);
    font-size: 13px;
    color: var(--text-secondary);
}
.marking-meta { display: flex; align-items: center; gap: 8px; }

.mutation-row {
    display: flex;
    justify-content: space-between;
    align-items: start;
    background: var(--bg-subtle);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--color-primary);
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    color: var(--text-primary);
}
/* The Glimmer "strip this pet back to no mutation" action: its own form (it must
   not inherit the purchase form's fields), so it needs its own separation. Laid
   out as the same explanation/action pair as the .mw-commit bar directly above it
   (and overriding the global 420px form width for the same reason .mw-form does)
   so the page's two spends line up instead of one being full-width and the
   other a narrow left-hugging column. */
.mutation-remove-form {
    margin-top: 24px;
    padding-top: 20px;
    border-top: 1px solid var(--border-color);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(260px, 340px);
    gap: 20px;
    align-items: end;
    max-width: none;
}
.mutation-remove-form > div { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.mutation-remove-form p { margin: 0; }
.mutation-remove-form .btn { width: 100%; justify-content: center; }

.mutation-row strong { display: block; font-size: 13px; }
.mutation-row small { color: var(--text-muted); font-size: 11px; display: block; margin-top: 2px; }

.stat-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; }
@media (max-width: 700px) { .stat-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 480px) { .stat-grid { grid-template-columns: repeat(2, 1fr); } }
.stat-card {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 12px;
    border-radius: var(--radius-md);
    border-left: 3px solid transparent;
    background: var(--bg-subtle);
    border: 1px solid var(--border-color);
}
.stat-card--might    { border-left-color: var(--color-error); }
.stat-card--grace    { border-left-color: var(--color-info); }
.stat-card--instinct { border-left-color: var(--color-warning); }
.stat-card--accent   { border-left-color: var(--color-primary); }
.stat-label { font-family: var(--font-mono); font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.06em; }
.stat-val { font-family: var(--font-mono); font-size: 22px; font-weight: 700; color: var(--text-primary); font-variant-numeric: tabular-nums; }

.lineage-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 580px) { .lineage-grid { grid-template-columns: 1fr; } }
.lineage-parent-row { display: flex; flex-direction: column; gap: 8px; }
.lineage-offspring-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.lineage-card {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 10px 12px;
    border-radius: var(--radius-md);
    text-decoration: none;
    border: 1px solid var(--border-color);
    background: var(--bg-subtle);
    transition: transform .15s, box-shadow .15s;
    color: var(--text-primary);
}
@media (hover: hover) { .lineage-card:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); } }
.lineage-card strong { font-size: 13px; display: block; }
.lineage-card--parent { border-left: 3px solid var(--color-warning); }
.lineage-card--child  { border-left: 3px solid var(--color-info); }
.lineage-card--released { opacity: 0.65; cursor: default; }
@media (hover: hover) { .lineage-card--released:hover { transform: none; box-shadow: none; } }
.lineage-empty {
    background: var(--bg-subtle);
    border: 2px dashed var(--border-color);
    border-radius: var(--radius-md);
    padding: 14px;
    font-size: 13px;
    color: var(--text-muted);
}
.lineage-empty a { color: var(--color-primary); }

