/* Holotype UI — card.css
   The specimen card + result view: result panels, field notes,
   image/traits, skeleton card, card attributes, the MTG-shaped
   genome card / specimen plate, genotype panel, post-mating row.
   Part 5/7 of the former styles.css; files are linked
   from index.html in order, so the cascade is unchanged. */

        /* ---- Result panels ---- */

        /* Result panels — a leaf of the field ledger. A single copper
           margin rule, set into the left padding gutter clear of
           content, gives each panel the feel of a ruled ledger page.
           (An earlier all-over horizontal ruling read as a modern
           lined notebook — dropped in favour of period ruled tables
           for the data itself.) */
        .panel {
            background:
                linear-gradient(
                    to right,
                    transparent 15px,
                    rgba(201, 139, 86, 0.22) 15px,
                    rgba(201, 139, 86, 0.22) 16px,
                    transparent 16px),
                var(--surface);
            border: 1px solid var(--border);
            border-radius: var(--radius-lg);
            padding: 24px;
            /* The shared scored-leaf bevel over the panel's own drop shadow,
               so every section container shares the plates' light source.
               (.genome-card overrides this shadow, so the card is unchanged.) */
            box-shadow: var(--plate-inset), var(--shadow);
            margin-bottom: 20px;
        }
        .panel h2 {
            font-size: 16px;
            font-weight: 600;
            margin: 0 0 16px;
            text-transform: uppercase;
            letter-spacing: 0.04em;
            color: var(--text-muted);
        }

        /* ---- Field-notes leaves ----
           The result pane (#result-details) is not a stack of cards but
           a run of notebook leaves on one continuous page. A single
           copper margin rule runs the height of the page; each leaf is
           a section introduced by an engraved heading. No boxes. */
        #result-details {
            position: relative;
            padding-left: 30px;
        }
        #result-details::before {
            /* the ledger margin rule, drawn down the whole right page */
            content: "";
            position: absolute;
            top: 2px;
            bottom: 2px;
            left: 13px;
            width: 1px;
            background: rgba(201, 139, 86, 0.28);
        }
        /* Each leaf is held to a reading measure — a written page has
           a column, it doesn't run text the full width of the pane. */
        .leaf {
            margin: 0 0 34px;
            max-width: 680px;
        }
        .leaf:last-child { margin-bottom: 8px; }
        /* Engraved section heading — small-caps serif title, then a
           hairline rule running to the page edge, with a small fern
           ornament keyed out of its dark ground via mix-blend-mode. */
        .leaf-head {
            display: flex;
            align-items: center;
            gap: 12px;
            margin: 0 0 16px;
        }
        .leaf-head h2,
        .leaf-head h3 {
            margin: 0;
            font-family: var(--font-serif);
            font-size: 13px;
            font-weight: 600;
            letter-spacing: 0.2em;
            text-transform: uppercase;
            color: var(--copper);
            font-feature-settings: "smcp", "lnum";
            white-space: nowrap;
        }
        .leaf-head::after {
            content: "";
            flex: 1;
            height: 0;
            border-top: 1px solid var(--rule-strong);
        }
        .leaf-head-mark {
            width: 18px;
            height: 18px;
            flex-shrink: 0;
            background: url("/static/assets/ornament.png") center / contain no-repeat;
            mix-blend-mode: screen;
            opacity: 0.7;
        }
        /* Small caption under a leaf heading — e.g. the loci/bp tally. */
        .leaf-caption {
            font-family: var(--font-hand);
            font-size: 17px;
            color: var(--ink-pen);
            margin: -8px 0 14px;
        }

        /* ---- Image + Traits panel (with hover-to-highlight) ----
           Two-column layout: user's image on the left with an SVG overlay
           for trait regions, traits dl on the right. The trait labels and
           feature tags carry data-trait-key and data-trait-label so JS can
           map a hover event back to the matching regions. */

        /* .image-traits-grid is no longer used on the genome card
           (the MTG-portrait redesign stacks art on top of the rules
           box rather than placing them side-by-side). The .image-frame
           rules below still apply because the frame element is still
           rendered inside the new .genome-card-art-window. */
        .image-frame {
            position: relative;
            background: var(--surface-2);
            border: 1px solid var(--border);
            border-radius: var(--radius);
            overflow: hidden;
            aspect-ratio: 1;
        }
        #result-image {
            display: block;
            width: 100%;
            height: 100%;
            /* cover (not contain) fills the square window edge-to-edge with no
               letterbox bars; the creature renders are 1:1 so nothing is
               cropped. (contain left black bars in Safari when the frame
               resolved non-square.) */
            object-fit: cover;
            background: var(--bg);
        }
        #region-overlay {
            position: absolute;
            inset: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
        }
        /* Region rect: invisible by default; gets `is-active` when its
           trait is being hovered. Soft accent fill + bright outline so
           the user can immediately see the matched feature. */
        #region-overlay rect.region {
            fill: var(--accent);
            fill-opacity: 0;
            stroke: var(--accent);
            stroke-width: 0.6;       /* viewBox is 0..100 so values are pp */
            stroke-opacity: 0;
            transition: fill-opacity 120ms ease, stroke-opacity 120ms ease;
        }
        #region-overlay rect.region.is-active {
            fill-opacity: 0.18;
            stroke-opacity: 1;
        }
        #region-overlay text.region-label {
            font-size: 3px;          /* viewBox units */
            font-family: system-ui, -apple-system, sans-serif;
            font-weight: 600;
            fill: var(--accent);
            opacity: 0;
            transition: opacity 120ms ease;
            paint-order: stroke;
            stroke: var(--bg);
            stroke-width: 0.6;
            stroke-linejoin: round;
        }
        #region-overlay text.region-label.is-active {
            opacity: 1;
        }

        /* Trait cells become hover targets — subtle background flash so
           the user knows the row is interactive. */
        .traits-grid dt[data-trait-key],
        .traits-grid dd[data-trait-key] {
            cursor: help;
            border-radius: 4px;
            padding: 2px 6px;
            margin: -2px -6px;
            transition: background 120ms ease;
        }
        .traits-grid dt.is-hover,
        .traits-grid dd.is-hover {
            background: var(--accent-soft);
        }
        .feature-tag[data-trait-key] {
            cursor: help;
        }
        .feature-tag.is-hover {
            background: var(--accent-soft);
            color: var(--accent);
        }
        /* Colored disc next to each species name in the type line.
           The disc color matches that species' frame color, so the
           card's outer border (single-species solid or hybrid
           gradient) reads as "the colors of these species". Without
           the discs the user has no way to discover what the outline
           color means — see frameColorFor() in the JS. */
        .species-chip {
            display: inline-flex;
            align-items: center;
            gap: 5px;
        }
        .species-chip::before {
            content: "";
            width: 9px;
            height: 9px;
            border-radius: 50%;
            background: var(--chip);
            box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
            flex: 0 0 9px;
        }

        .image-frame .image-empty {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100%;
            color: var(--text-faint);
            font-size: 13px;
            text-align: center;
            padding: 16px;
            gap: 10px;
        }
        /* Pending-image placeholder shown while the eager-image-gen
           background task is rendering. The hand-inked specimen-plate
           asset sits behind the caption as a faint empty plate (screen
           blend keys its dark ground out), so the wait reads as "the
           plate awaits its drawing". Pulses slowly. */
        .image-pending {
            position: relative;
            width: 100%;
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .image-pending-plate {
            position: absolute;
            inset: 7%;
            width: 86%;
            height: 86%;
            object-fit: contain;
            mix-blend-mode: screen;
            animation: pending-pulse 2.8s ease-in-out infinite;
        }
        .image-pending-caption {
            position: relative;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 6px;
            text-align: center;
            padding: 16px;
        }
        .image-pending-label {
            font-family: var(--font-serif);
            font-weight: 500;
            color: var(--ink);
            font-size: 16px;
            font-style: italic;
            letter-spacing: 0.01em;
        }
        .image-pending-hint {
            font-family: var(--font-serif);
            color: var(--ink-faint);
            font-size: 11px;
            font-feature-settings: "smcp", "lnum";
            letter-spacing: 0.18em;
            text-transform: uppercase;
        }
        @keyframes pending-pulse {
            0%, 100% { opacity: 0.34; }
            50%      { opacity: 0.62; }
        }

        /* ---- Skeleton specimen card ----
           The genome card as rendered while a starter is being
           assembled. Fields the player already chose (name, species,
           species count) render solid; every field still being
           computed shows a shimmer bar so the card reads as "filling
           in", not "broken". renderSkeletonCard() paints it;
           populateGenomeCard() then replaces it wholesale. */
        .skeleton-bar {
            display: inline-block;
            width: 64%;
            height: 0.72em;
            vertical-align: middle;
            border-radius: 3px;
            /* A pale band swept by a copper highlight — keys off the
               same --rule / copper palette the finished card uses. */
            background: linear-gradient(
                100deg,
                var(--rule) 28%,
                rgba(201, 139, 86, 0.30) 50%,
                var(--rule) 72%);
            background-size: 220% 100%;
            animation: skeleton-sweep 1.5s linear infinite;
        }
        @keyframes skeleton-sweep {
            0%   { background-position: 170% 0; }
            100% { background-position: -70% 0; }
        }

        .traits-grid {
            display: grid;
            grid-template-columns: 120px 1fr;
            gap: 10px 16px;
            font-size: 14px;
        }
        .traits-grid dt {
            color: var(--text-muted);
            font-weight: 500;
        }
        .traits-grid dd {
            margin: 0;
        }

        /* Species mix — a ruled catalogue table (name · figure), not a
           chart. The JS still emits a .bar-track/.bar-fill; both are
           dropped so the row reads as a hairline-ruled ledger entry. */
        /* A compact ruled tally — capped narrow so each species name
           and its percentage sit close, not flung apart. */
        .species-bar {
            display: flex;
            align-items: baseline;
            justify-content: space-between;
            gap: 14px;
            max-width: 222px;
            padding: 5px 2px 4px;
            border-bottom: 1px solid var(--rule);
        }
        .species-bar:last-child { border-bottom: 0; }
        .species-bar .label {
            font-family: var(--font-serif);
            font-size: 14.5px;
            color: var(--ink);
        }
        .species-bar .bar-track { display: none; }
        .species-bar .pct {
            font-family: var(--font-serif);
            font-size: 14.5px;
            color: var(--ink-muted);
            font-variant-numeric: tabular-nums lining-nums;
            text-align: right;
        }

        /* ---- Card attributes ("Field measurements") ----
           The derived 1–10 stat block (attack/defense/speed/sense/vigor),
           shown at the head of the Observations pane as labelled copper
           bars — a quick legible read of what the creature *is*, beyond
           its rarity tier. Values come from the API (derive_attributes). */
        .attr-block {
            margin: 0 0 18px;
            padding: 12px 14px 10px;
            border: 1px solid var(--rule);
            border-left: 3px solid var(--copper);
            border-radius: 2px;
            background: var(--copper-dim);
        }
        .attr-block-head {
            display: flex;
            align-items: baseline;
            justify-content: space-between;
            margin-bottom: 9px;
            gap: 12px;
        }
        .attr-block-title {
            font-family: var(--font-serif);
            font-size: 11px;
            font-weight: 600;
            letter-spacing: 0.18em;
            text-transform: uppercase;
            color: var(--copper);
        }
        /* Overall power rating — the headline figure of the block. */
        .attr-power {
            display: inline-flex;
            align-items: baseline;
            gap: 5px;
            white-space: nowrap;
        }
        .attr-power-label {
            font-family: var(--font-serif);
            font-size: 10px;
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--ink-muted);
        }
        .attr-power-value {
            font-family: var(--font-serif);
            font-size: 22px;
            font-weight: 700;
            line-height: 1;
            color: var(--gold-leaf);
            font-variant-numeric: tabular-nums lining-nums;
        }
        .attr-row {
            display: grid;
            grid-template-columns: 64px 1fr 22px;
            align-items: center;
            gap: 10px;
            padding: 3px 0;
        }
        .attr-label {
            font-family: var(--font-serif);
            font-size: 13px;
            letter-spacing: 0.04em;
            color: var(--ink);
        }
        .attr-track {
            height: 7px;
            background: rgba(0, 0, 0, 0.28);
            border-radius: 4px;
            overflow: hidden;
        }
        .attr-fill {
            height: 100%;
            background: linear-gradient(90deg, var(--copper), var(--copper-hover));
            border-radius: 4px;
        }
        .attr-value {
            font-family: var(--font-serif);
            font-size: 13px;
            color: var(--ink-muted);
            font-variant-numeric: tabular-nums lining-nums;
            text-align: right;
        }

        .swatch {
            display: inline-block;
            width: 14px;
            height: 14px;
            border: 1px solid var(--border-2);
            border-radius: 1px;
            vertical-align: -2px;
            margin-right: 6px;
        }

        .feature-tag {
            display: inline-block;
            background: transparent;
            color: var(--ink-muted);
            border: 1px solid var(--rule-strong);
            border-radius: 0;
            padding: 2px 8px;
            font-size: 13px;
            margin: 0 4px 4px 0;
        }

        /* ---- Genome card (MTG-shaped portrait card) ----------------
           Top-of-result-page panel laid out like an actual MTG card:
           title bar at top, big art window (~5:4 aspect, full card
           width), type line strip, then a rules box where the traits
           dl shares horizontal space with a vertical stats column on
           the right (like MTG's power/toughness). Flavor text appears
           italic at the bottom of the rules box.

           --frame-a / --frame-b are inline CSS custom properties set
           by JS based on the dominant species (single-species → solid;
           hybrid → 90° gradient between species[0] and species[1]). */

        /* ---- Specimen plate (genome-card) ----
           A real trading-card silhouette: 5:7 aspect ratio, ~440 px
           wide so the whole card fits a typical browser column. The
           outer chrome is a thick rarity-keyed frame; inside that
           sits the existing hairline double-rule plate, the species
           accent stripe, and corner cartouches.

           Rarity ladder for the outer frame:
              common   → faint pewter
              uncommon → brass
              rare     → copper
              mythic   → animated gold-leaf foil

           --frame-rarity is the single token that drives the outer
           border color; .rarity-X class on the card overrides it.
           --frame-a / --frame-b are still set by JS from the species
           mix and drive the inner species accent stripe. */
        .genome-card {
            --frame-a: var(--copper);
            --frame-b: var(--copper);
            --frame-rarity: #6b6356;     /* common default — faint pewter */
            /* Gilt emphasis for the card's KEY text + high values: a SOLID,
               readable rarity colour with a soft same-hue glow (no muddy
               gradient clip). Keyed by rarity: common = silver/pewter, then
               brass / copper / gold. --card-rule is the 1px hairline tone. */
            --gilt: #dfe4ec;
            --gilt-glow: rgba(214, 221, 232, 0.40);
            --card-rule: #aab0b8;
            /* The ornate frame asset (rarity tier; overridden by a chosen
               cosmetic frame), applied as a border-image. --card-frame-slice is
               that asset's own border fraction, so a thin uniform border-width
               renders an EVEN frame on all four sides (no stretch distortion)
               at any card height. */
            --card-frame-img: url("/static/assets/frame-common.png");
            --card-frame-slice: 7.7%;
            isolation: isolate;

            width: 100%;
            max-width: 440px;
            /* Height is content-driven (square art + chrome). */
            margin: 0 auto;
            /* The frame is a thin even border-image; content sits just inside it
               (the border insets the content; the small padding adds breathing
               room). The children's own side margins are zeroed below. */
            border: 13px solid transparent;
            border-image: var(--card-frame-img) var(--card-frame-slice) / 1 / 0 stretch;
            padding: 8px 9px 9px;
            position: relative;
            color: var(--ink);
            display: flex;
            flex-direction: column;
            background: var(--bg-vellum);     /* shows behind the frame's open scrollwork */
            box-shadow:
                0 14px 36px rgba(0, 0, 0, 0.5),
                0 4px 10px rgba(0, 0, 0, 0.4);
        }
        /* Zero the children's own side margins (tuned for the old 9px border) so
           the inset comes only from the border + padding, evenly on all sides. */
        #genome-card > :not(.card-surface) {
            margin-left: 0;
            margin-right: 0;
        }
        /* The frame asset supplies the corners now — drop the cartouche marks. */
        #genome-card.fj-cartouche::after { content: none; }
        /* The pinned card is a static display — no pointer cursor and no hover
           change. (It used to be tappable-to-Observations, but the hover
           reframe/cursor read as glitches and Observations is the default result
           view anyway, so the tap affordance was removed.) */
        /* Rarity-keyed outer-frame color. Common is the default in
           .genome-card; the rest override --frame-rarity. */
        .genome-card.rarity-uncommon {
            --gilt: #e8cd92;
            --gilt-glow: rgba(200, 162, 110, 0.45);
            --card-rule: var(--brass);
            --card-frame-img: url("/static/assets/frame-uncommon.png");
            --card-frame-slice: 4.8%;
        }
        .genome-card.rarity-rare {
            --gilt: #edae7c;
            --gilt-glow: rgba(214, 160, 122, 0.5);
            --card-rule: var(--copper);
            --card-frame-img: url("/static/assets/frame-rare.png");
            --card-frame-slice: 6.8%;
        }
        .genome-card.rarity-mythic {
            --gilt: #eecf6a;
            --gilt-glow: var(--gold-leaf-glow);
            --card-rule: var(--gold-leaf);
            --card-frame-img: url("/static/assets/frame-mythic.png");
            --card-frame-slice: 5.5%;
            /* Mythic keeps a gold glow + the one-shot body foil sweep
               (.card-surface::after); the gold is carried by the frame asset. */
            box-shadow:
                0 0 22px var(--gold-leaf-glow),
                0 14px 36px rgba(0, 0, 0, 0.55);
        }
        /* ---- Dark-parchment card body (the hero card's surface) ----
           Dark brown-black parchment painted above the card's flat fill but
           below the content (z-index:-1 in the card's isolated stacking
           context), so the rarity frame trick is untouched. Text + line
           elements are the metallic-foil highlights on top of it. */
        .card-surface {
            position: absolute;
            inset: 0;
            z-index: -1;
            pointer-events: none;
            border-radius: 2px;
            /* Dark brown-black parchment: the plate-parchment grain multiplied
               over a deep brown ground (the .fj-plate idiom), under an edge
               vignette so it reads as aged sheet. Text + line elements are the
               metallic-foil highlights ON this dark ground (see below). */
            background:
                url("/static/assets/plate-parchment.png") center / 300px repeat,
                radial-gradient(128% 122% at 50% 36%,
                    transparent 48%, rgba(0, 0, 0, 0.55) 100%),
                linear-gradient(168deg, #241a11 0%, #15100a 100%);
            background-blend-mode: multiply, multiply, normal;
        }
        /* The fern motif washed into the upper-left corner: a single large
           curved frond (transparent-background asset — no box), keyed faintly
           into the metal so it reads as an etched corner mark. */
        .card-surface::before {
            content: "";
            position: absolute;
            top: -6px;
            left: -6px;
            width: 58%;
            height: 58%;
            background: url("/static/assets/card-fern.png") top left / contain no-repeat;
            opacity: 0.16;
            mix-blend-mode: soft-light;
            pointer-events: none;
        }
        /* Mythic: a single gold-foil sheen that sweeps once across the plate as
           the card appears (no looping — a one-shot flourish). */
        .genome-card.rarity-mythic .card-surface::after {
            content: "";
            position: absolute;
            inset: 0;
            border-radius: 2px;
            pointer-events: none;
            background: linear-gradient(115deg,
                transparent 38%, rgba(255, 246, 214, 0.5) 50%, transparent 62%);
            background-size: 240% 100%;
            mix-blend-mode: screen;
            animation: card-foil-sweep 2.4s ease-out 1 both;
        }
        @keyframes card-foil-sweep {
            0%   { background-position: 120% 0; opacity: 0; }
            18%  { opacity: 1; }
            100% { background-position: -40% 0; opacity: 0; }
        }
        @media (prefers-reduced-motion: reduce) {
            .genome-card.rarity-mythic .card-surface::after { animation: none; }
        }
        /* ---- Card text ----
           Most text is a quiet, readable warm-parchment ink (the foil was too
           busy everywhere). The full rarity FOIL is reserved for the key marks —
           creature name, plate number, rarity designation — plus a HIGH power or
           stat value (>=8 / a strong power), which is how those now read as
           special (no more brackets or underlines). */
        #genome-card .genome-card-plate,
        #genome-card .genome-card-title,
        #genome-card .rarity-label,
        #genome-card .set-chip,
        #genome-card .genome-card-specimen-tag,
        #genome-card .genome-card-typeline,
        #genome-card .card-power-value,
        #genome-card .card-power-label,
        #genome-card .card-power-meta .cpm-value,
        #genome-card .card-power-meta dt,
        #genome-card .attr-mini-value,
        #genome-card .attr-mini-label {
            color: #cdbf9c;                 /* toned-down readable ink */
            -webkit-text-fill-color: #cdbf9c;
            background: none;
            filter: none;
            animation: none;
            text-decoration: none;
            text-shadow: 0 1px 1px rgba(0, 0, 0, 0.55);
        }
        /* The KEY text + any high value: a SOLID gilt rarity colour (crisp,
           readable) with a soft same-hue glow — quietly radiant, no gradient
           muddiness. Bolder so it carries the emphasis. */
        #genome-card .genome-card-title,
        #genome-card .genome-card-plate,
        #genome-card .rarity-label,
        #genome-card .card-power-value.is-high,
        #genome-card .attr-mini-value.is-high {
            background: none;
            color: var(--gilt);
            -webkit-text-fill-color: var(--gilt);
            font-weight: 700;
            filter: none;
            animation: none;       /* kill the old mythic foil-shimmer on the now-solid text */
            text-shadow:
                0 0 7px var(--gilt-glow),
                0 0 14px var(--gilt-glow),
                0 1px 1px rgba(0, 0, 0, 0.55);
        }
        /* Section hairlines: a quiet dark rule (the bright foil lines were noisy). */
        #genome-card .genome-card-specimen-tag,
        #genome-card .genome-card-typeline,
        #genome-card .genome-card-power-row,
        #genome-card .genome-card-attrs {
            border-color: var(--rule);
        }
        /* Species-keyed accent stripe inside the frame — a 2 px band
           picked up from --frame-a/--frame-b, shown just below the
           inner double-rule. */
        .genome-card::before {
            content: "";
            position: absolute;
            top: 5px; left: 5px; right: 5px;
            height: 2px;
            background: linear-gradient(90deg, var(--frame-a), var(--frame-b));
            opacity: 0.7;
            z-index: 1;
            pointer-events: none;
        }
        /* Corner cartouches now come from the shared .fj-cartouche kit
           (components.css) — same filigree marks the Leaderboard plates
           wear, tuned onto the card's thick border via --fj-cart-inset
           above. Only the Mythic glow override stays card-specific. */
        /* Mythic cartouches glow gold-leaf instead of brass. */
        .genome-card.rarity-mythic::after {
            filter: hue-rotate(-12deg) brightness(1.2)
                    drop-shadow(0 0 4px var(--gold-leaf-glow));
        }

        .genome-card-title-bar {
            display: flex;
            align-items: flex-start;
            justify-content: space-between;
            gap: 12px;
            padding: 16px 20px 10px;
            position: relative;
        }
        /* "PLATE LXII" eyebrow — written above the title-bar via the
           ::before of the title element so the existing markup doesn't
           need to change. Set in JS by populateGenomeCard. */
        .genome-card-title-wrap {
            display: flex;
            flex-direction: column;
            gap: 4px;
            min-width: 0;
            flex: 1;
        }
        .genome-card-plate {
            font-family: var(--font-serif);
            font-size: 10.5px;
            font-weight: 600;
            letter-spacing: 0.22em;
            text-transform: uppercase;
            color: var(--copper);
            font-feature-settings: "smcp", "lnum";
        }
        .genome-card-title {
            margin: 0;
            font-family: var(--font-serif);
            font-size: 22px;
            font-weight: 500;
            letter-spacing: 0.005em;
            color: var(--ink);
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            min-width: 0;
        }
        .genome-card-title-meta {
            display: flex;
            flex-direction: column;
            align-items: flex-end;
            gap: 6px;
            flex-shrink: 0;
        }
        .set-chip {
            font-family: var(--font-mono);
            font-size: 10px;
            padding: 3px 8px;
            background: transparent;
            color: var(--ink-faint);
            border: 1px solid var(--rule);
            border-radius: 2px;
            letter-spacing: 0.08em;
        }
        /* Rarity ladder — bronze (common) → brass (uncommon) →
           copper-glow (rare) → gold-leaf foil (mythic). The tooltip
           still surfaces the exact mutation count. */
        .rarity-label {
            font-family: var(--font-serif);
            font-size: 11px;
            font-weight: 600;
            letter-spacing: 0.22em;
            text-transform: uppercase;
            cursor: help;
            line-height: 1;
            font-feature-settings: "smcp", "lnum";
        }
        /* Rarity ladder: neutral bone white (common) → soft champagne
           pastel (uncommon) → glowing copper (rare) → animated gold foil
           (mythic). Deliberately understated at the low end so the rare
           tiers pop. */
        .rarity-label.rarity-common   { color: var(--ink); }
        .rarity-label.rarity-uncommon { color: #d8c79c; }
        .rarity-label.rarity-rare {
            color: var(--copper-hover);
            text-shadow: 0 0 8px rgba(214, 160, 122, 0.45);
        }
        .rarity-label.rarity-mythic {
            background: linear-gradient(
                90deg,
                #b8860b 0%,
                var(--gold-leaf) 35%,
                #f4e4a6 50%,
                var(--gold-leaf) 65%,
                #b8860b 100%
            );
            background-size: 200% 100%;
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
            -webkit-text-fill-color: transparent;
            filter: drop-shadow(0 0 6px var(--gold-leaf-glow));
            animation: mythic-foil-shimmer 2.4s ease-out 1 both;
        }
        @keyframes mythic-foil-shimmer {
            0%   { background-position:   0% 50%; }
            100% { background-position: 200% 50%; }
        }
        /* Honour reduced-motion for the two looping flourishes that weren't
           yet gated — the mythic-label foil sweep and the image-pending
           pulse. The static styling (gold gradient / placeholder) stays. */
        @media (prefers-reduced-motion: reduce) {
            .rarity-label.rarity-mythic { animation: none; }
            .image-pending-plate { animation: none; }
        }

        /* Art window — the central plate. Hairline double-rule frame
           keyed to species, with the specimen tag rendered just below. */
        .genome-card-art-window {
            position: relative;
            margin: 4px 18px 0;
            /* A recessed dark mat the square portrait sits in. The art window is
               an ordinary flow box that simply hugs the square frame below —
               NOT a flex item whose size depends on aspect-ratio (Safari
               resolved that wider than the card and the portrait spilled past
               the right edge). The squareness lives on .image-frame instead. */
            padding: 6px;
            background: rgba(0, 0, 0, 0.34);
            border: 1px solid var(--rule-strong);
            border-radius: 2px;
            box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.6);
        }
        /* The portrait pins — the same specimen pins as this creature's library
           tile + note slips (colour keyed per creature via the `.pin-0..3`
           class on #genome-card → --pin-grad), one in each upper corner of the
           photo so a centred pin doesn't crowd the creature's head. A touch
           larger than the tile pins and nudged down onto the photo (rather than
           a single pin poking above the mat, which clashed with the frame). The
           pins are .specimen-pin elements rendered in .genome-card-art-window. */
        .genome-card-art-window .specimen-pin {
            top: 14px;
            width: 8px;
            height: 8px;
            box-shadow:
                0 1px 2px rgba(0, 0, 0, 0.6),
                inset 0 -1px 1px rgba(0, 0, 0, 0.3);
            z-index: 4;
        }
        /* Nudged in off the photo edge (the mat adds ~6px, so the pins sit
           inside the corners of the image rather than on its very edge). */
        .genome-card-art-window .specimen-pin.is-left  { left: 16px; }
        .genome-card-art-window .specimen-pin.is-right { right: 16px; }
        .genome-card-art-window .image-frame {
            /* Square derived from a DEFINITE width (the mat's content box), which
               every browser resolves the same way — no flex-height ambiguity. */
            width: 100%;
            aspect-ratio: 1;
            height: auto;
            min-height: 0;
            overflow: hidden;
            border: 1px solid var(--rule-strong);
            box-shadow:
                inset 0 0 0 1px var(--bg-vellum),
                inset 0 0 0 2px var(--frame-a);   /* species-keyed hairline */
            border-radius: 1px;
            background: var(--bg-ink);
        }

        /* Specimen tag — monospace identification strip. */
        .genome-card-specimen-tag {
            display: flex;
            justify-content: space-between;
            align-items: center;
            gap: 8px;
            margin: 6px 20px 0;
            padding: 5px 0;
            border-top: 1px solid var(--rule);
            font-family: var(--font-mono);
            font-size: 10px;
            color: var(--ink-faint);
            letter-spacing: 0.06em;
        }

        /* Type line — catalog metadata strip. */
        /* Type line — the species mix as small color-tinted taxonomic
           icons + weight %. Compact icons (vs the old name chips) let the
           percentages sit back on the card; overflow past the first six
           collapses into a "+N" pill (renderSpeciesTypeline). */
        .genome-card-typeline {
            margin: 8px 20px 0;
            padding: 8px 0 7px;
            border-top: 1px solid var(--rule);
            border-bottom: 1px solid var(--rule);
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            gap: 5px 9px;
        }
        .spp-eyebrow {
            font-family: var(--font-serif);
            font-size: 9px;
            font-weight: 600;
            letter-spacing: 0.18em;
            text-transform: uppercase;
            color: var(--ink-faint);
            font-feature-settings: "smcp", "lnum";
        }
        .spp-chips {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            gap: 4px 9px;
            min-width: 0;
        }
        .spp-chip {
            display: inline-flex;
            align-items: center;
            gap: 3px;
        }
        .spp-ico {
            width: 17px;
            height: 17px;
            flex: none;
            display: block;
        }
        .spp-pct {
            font-family: var(--font-serif);
            font-size: 11.5px;
            font-variant-numeric: tabular-nums lining-nums;
            color: var(--ink-muted);
            letter-spacing: 0.01em;
        }
        /* Hidden overflow chips flow inline with the rest once revealed. */
        .spp-more { display: contents; }
        .spp-more[hidden] { display: none; }
        .spp-more-toggle {
            font-family: var(--font-serif);
            font-size: 10px;
            font-weight: 600;
            color: var(--copper);
            background: var(--copper-dim);
            border: 1px solid var(--rule-strong);
            border-radius: 10px;
            padding: 1px 7px;
            cursor: pointer;
            letter-spacing: 0.02em;
            line-height: 1.4;
        }
        .spp-more-toggle:hover {
            color: var(--copper-hover);
            border-color: var(--copper);
        }

        /* Rules box: two-column grid — descriptive rules text on the
           left, marginal stats column on the right. */
        .genome-card-textbox {
            display: grid;
            grid-template-columns: 1fr auto;
            gap: 14px;
            padding: 12px 20px 16px;
            align-items: start;
            flex: 1;
            min-height: 0;
        }
        .genome-card-rules .traits-grid {
            grid-template-columns: 88px 1fr;
            font-size: 12.5px;
            gap: 6px 12px;
        }
        .genome-card-rules .traits-grid dt {
            font-family: var(--font-serif);
            font-size: 10px;
            text-transform: uppercase;
            letter-spacing: 0.14em;
            font-weight: 600;
            color: var(--ink-faint);
            align-self: center;
            font-feature-settings: "smcp", "lnum";
        }
        /* Flavor — italic serif quote with hanging pilcrow at the
           start. Top edge marked with a hairline rule. */
        /* Right-pane traits panel — receives the species table /
           color / pattern / structure / features / build dl plus the
           flavor quote. The card on the left only carries the title,
           art, type-line, and stat strip, so nothing overflows the
           5:7 silhouette. */
        .card-traits-pane {
            padding: 0;
        }
        .card-traits-pane .traits-grid {
            grid-template-columns: 110px 1fr;
            font-size: 14px;
            gap: 8px 16px;
        }
        .card-traits-pane .traits-grid dt {
            font-family: var(--font-serif);
            font-size: 11px;
            text-transform: uppercase;
            letter-spacing: 0.16em;
            font-weight: 600;
            color: var(--ink-faint);
            align-self: center;
            font-feature-settings: "smcp", "lnum";
        }
        /* Detail/result view: promote the field note from trailing card
           text to a featured element — a framed parchment panel with a
           copper "Field notes" eyebrow, so the naturalist's observation
           reads as the centrepiece of the Observations leaf. */
        .card-traits-pane .genome-card-flavor {
            margin-top: 18px;
            padding: 13px 16px 14px;
            font-size: 19.5px;
            display: block;
            -webkit-line-clamp: unset;
            line-clamp: unset;
            overflow: visible;
            border-top: none;
            border-left: 3px solid var(--copper);
            border-radius: 2px;
            background: var(--copper-dim);
        }
        .card-traits-pane .genome-card-flavor::before {
            content: "Field notes";
            display: block;
            font-family: var(--font-serif);
            font-size: 11px;
            font-weight: 600;
            letter-spacing: 0.18em;
            text-transform: uppercase;
            color: var(--copper);
            margin-bottom: 7px;
        }
        /* Empty (observe gave up) → fully blank: no panel, no eyebrow. */
        .card-traits-pane .genome-card-flavor:empty {
            background: none;
            border-left: none;
            padding: 0;
        }
        /* Drafting → drop the panel FRAME (border + padding) but NOT the
           background: the shimmer gradient lives on `background`, and
           `-webkit-text-fill-color: transparent` would make the text
           invisible if we cleared it here. */
        .card-traits-pane .genome-card-flavor.is-drafting {
            border-left: none;
            padding: 0;
        }
        .card-traits-pane .genome-card-flavor:empty::before,
        .card-traits-pane .genome-card-flavor.is-drafting::before {
            content: none;
        }

        /* Field note — the collector's handwritten observation on the
           specimen, set in the pen hand rather than typeset italic. */
        .genome-card-flavor {
            margin-top: 10px;
            padding-top: 10px;
            border-top: 1px solid var(--rule);
            font-family: var(--font-hand);
            font-size: 16px;
            color: var(--ink-pen);
            line-height: 1.32;
            letter-spacing: 0.01em;
            /* Trim long flavor on cards that are getting close to
               aspect-ratio overflow; keeps the silhouette card-shaped. */
            display: -webkit-box;
            -webkit-line-clamp: 4;
            -webkit-box-orient: vertical;
            overflow: hidden;
        }
        /* Pre-observe state: the field note is authored by observe() only
           after the image renders, so there's a short window where it's
           blank. Show "Drafting field notes…" with an ink-shimmer sweep —
           a copper highlight travelling left-to-right across the muted
           text, evoking ink being laid down as the note is written
           (rather than the old flat opacity pulse). */
        .genome-card-flavor.is-drafting {
            display: block;          /* gradient text-clip needs block, not -webkit-box */
            font-style: italic;
            color: var(--text-muted);
            background: linear-gradient(
                100deg,
                var(--text-muted) 0%, var(--text-muted) 42%,
                var(--copper) 50%,
                var(--text-muted) 58%, var(--text-muted) 100%
            );
            background-size: 220% 100%;
            -webkit-background-clip: text;
            background-clip: text;
            -webkit-text-fill-color: transparent;
            animation: ink-shimmer 1.9s ease-in-out infinite;
        }
        @keyframes ink-shimmer {
            0%   { background-position: 125% 0; }
            100% { background-position: -125% 0; }
        }
        /* Reduced-motion: no sweep — fall back to plain muted text. */
        @media (prefers-reduced-motion: reduce) {
            .genome-card-flavor.is-drafting {
                animation: none;
                background: none;
                -webkit-text-fill-color: var(--text-muted);
            }
            /* Settle the rarity flourishes to static gold — no shimmer,
               pop, or sparkle. */
            .genome-card.rarity-mythic .card-power-value {
                animation: none;
                background: none;
                -webkit-text-fill-color: var(--gold-leaf);
                color: var(--gold-leaf);
            }
            .attr-mini-value.is-max,
            .attr-value.is-max { animation: none; }
            .attr-mini-value.is-max::after,
            .attr-value.is-max::after { display: none; }
        }

        /* ---- Card stats: Power headline + battle-attribute strip ----
           Replaces the old Loci / BP / Het / Species / Mut strip (those
           barely varied between creatures and live elsewhere). A prominent
           gold Power figure with species & mutation counts beside it, then
           a five-cell row of abbreviated attributes. The full attribute
           bars stay in the right-pane "Field measurements" block. */
        .genome-card-power-row {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 12px;
            margin: 10px 20px 0;
            padding: 8px 0 6px;
            border-top: 1px solid var(--rule);
        }
        .card-power {
            display: inline-flex;
            align-items: baseline;
            gap: 6px;
        }
        .card-power-value {
            font-family: var(--font-serif);
            font-size: 30px;
            font-weight: 700;
            line-height: 1;
            /* Neutral by default; the rarity tier escalates the hue below
               (gold is reserved for Mythic so it stays meaningful). */
            color: var(--ink);
            font-variant-numeric: tabular-nums lining-nums;
            text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
        }
        /* Power number echoes the card's rarity ladder. */
        .genome-card.rarity-uncommon .card-power-value { color: #d8c79c; }
        .genome-card.rarity-rare .card-power-value {
            color: var(--copper-hover);
            text-shadow: 0 0 10px rgba(214, 160, 122, 0.5);
        }
        /* Mythic power borrows the rarity label's animated gold foil —
           the headline figure shimmers like the ★ MYTHIC tag for a
           cohesive top-tier flourish. */
        .genome-card.rarity-mythic .card-power-value {
            background: linear-gradient(
                90deg,
                #b8860b 0%,
                var(--gold-leaf) 35%,
                #f4e4a6 50%,
                var(--gold-leaf) 65%,
                #b8860b 100%
            );
            background-size: 200% 100%;
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
            -webkit-text-fill-color: transparent;
            text-shadow: none;
            filter: drop-shadow(0 0 10px var(--gold-leaf-glow));
            animation: mythic-foil-shimmer 2.4s ease-out 1 both;
        }
        .card-power-label {
            font-family: var(--font-serif);
            font-size: 10px;
            font-weight: 600;
            letter-spacing: 0.18em;
            text-transform: uppercase;
            color: var(--copper);
            font-feature-settings: "smcp", "lnum";
        }
        .card-power-meta {
            display: flex;
            gap: 14px;
            margin: 0;
        }
        .card-power-meta > div { text-align: center; }
        .card-power-meta .cpm-value {
            margin: 0;
            font-family: var(--font-serif);
            font-size: 15px;
            font-weight: 500;
            color: var(--ink);
            font-variant-numeric: tabular-nums lining-nums;
            line-height: 1.05;
        }
        .card-power-meta dt {
            margin: 2px 0 0;
            font-family: var(--font-serif);
            font-size: 8.5px;
            letter-spacing: 0.13em;
            text-transform: uppercase;
            color: var(--ink-faint);
            font-feature-settings: "smcp", "lnum";
        }
        .genome-card-attrs {
            display: flex;
            margin: 8px 18px 16px;
            padding: 7px 0;
            border-top: 1px solid var(--rule);
            border-bottom: 1px solid var(--rule);
        }
        .attr-mini {
            flex: 1;
            text-align: center;
            border-right: 1px solid var(--rule);
        }
        .attr-mini:last-child { border-right: none; }
        .attr-mini-value {
            margin: 0;
            font-family: var(--font-serif);
            font-size: 16px;
            font-weight: 500;
            color: var(--ink);
            font-variant-numeric: tabular-nums lining-nums;
            line-height: 1.05;
        }
        /* Card actions — small icon-only download / share, right-justified
           below the specimen card (kept OUTSIDE #genome-card so they don't drive
           the card's tappable hover). The card's corner cartouches overhang ~9px
           below it, so the row sits well clear of them. */
        .genome-card-actions {
            display: flex;
            justify-content: flex-end;
            gap: 8px;
            margin: 14px 4px 0;
        }
        .genome-card-actions[hidden] { display: none; }
        .card-action-btn {
            position: relative;
            width: 32px;
            height: 32px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            padding: 0;
            border: 1px solid var(--rule);
            border-radius: 3px;
            background: transparent;
            color: var(--ink-muted);
            cursor: pointer;
            transition: color var(--motion-quick), border-color var(--motion-quick),
                        background var(--motion-quick);
        }
        .card-action-btn svg {
            width: 17px; height: 17px;
            stroke: currentColor; fill: none;
            stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
        }
        .card-action-btn:hover:not(:disabled) {
            color: var(--copper);
            border-color: var(--copper);
            background: var(--copper-dim);
        }
        .card-action-btn:disabled { opacity: 0.4; cursor: not-allowed; }
        /* The frame opener carries a text glyph (◻) rather than an SVG icon, so
           give it a legible size to match the download/share icons. */
        #card-frame-btn { font-size: 18px; line-height: 1; }
        /* Custom tooltip (the native `title` was unreliable) — appears above the
           button on hover, like the dock-button tooltip. */
        .card-action-btn::after {
            content: attr(data-tooltip);
            position: absolute;
            bottom: calc(100% + 7px);
            right: 0;
            padding: 4px 9px;
            background: var(--bg-vellum);
            border: 1px solid var(--rule-strong);
            color: var(--ink);
            font-family: var(--font-serif);
            font-style: italic;
            font-size: 12px;
            white-space: nowrap;
            border-radius: 1px;
            opacity: 0;
            transform: translateY(4px);
            pointer-events: none;
            transition: opacity var(--motion-quick), transform var(--motion-quick);
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
            z-index: 60;
        }
        .card-action-btn:hover::after {
            opacity: 1;
            transform: translateY(0);
        }

        /* A maxed stat (10/10 — very rare) glows gold, with a one-time
           sparkle on reveal. Same treatment on the right-pane bars
           (.attr-value.is-max) so it reads the same wherever it appears. */
        .attr-mini-value.is-max,
        .attr-value.is-max {
            position: relative;
            color: var(--gold-leaf);
            font-weight: 700;
            text-shadow: 0 0 7px var(--gold-leaf-glow);
            animation: stat-max-pop 0.85s ease-out 1;
        }
        /* A small four-point glint that pops once at the upper-right of
           the figure as it's revealed, then fades. */
        .attr-mini-value.is-max::after,
        .attr-value.is-max::after {
            content: "\2726";          /* ✦ */
            position: absolute;
            top: -0.45em;
            right: -0.55em;
            font-size: 0.62em;
            color: var(--gold-leaf);
            opacity: 0;
            pointer-events: none;
            animation: stat-max-sparkle 0.85s ease-out 1;
        }
        @keyframes stat-max-pop {
            0%   { transform: scale(1);    text-shadow: 0 0 0 rgba(212, 175, 55, 0); }
            38%  { transform: scale(1.25); text-shadow: 0 0 14px var(--gold-leaf); }
            100% { transform: scale(1);    text-shadow: 0 0 7px var(--gold-leaf-glow); }
        }
        @keyframes stat-max-sparkle {
            0%   { opacity: 0; transform: scale(0.2) rotate(-30deg); }
            40%  { opacity: 1; transform: scale(1.1) rotate(0deg); }
            100% { opacity: 0; transform: scale(0.8) rotate(20deg); }
        }
        .attr-mini-label {
            margin: 3px 0 0;
            font-family: var(--font-serif);
            font-size: 8.5px;
            letter-spacing: 0.13em;
            text-transform: uppercase;
            color: var(--ink-faint);
            font-feature-settings: "smcp", "lnum";
        }

        /* ---- Genotype panel ----
           One row per locus; renders below the rules-box on offspring
           that carry an LLM-inferred phenotype_per_locus map. The
           genotype chip is colored by zygosity (homozygous wild-type /
           heterozygous carrier / homozygous recessive / hybrid species)
           and the expressed phenotype reads as a subtitle. Hovering
           the chip surfaces the dominance_note as a tooltip.

           Hidden when the genome has no phenotype_per_locus (legacy /
           image-derived creatures) — the JS toggles the section's
           hidden attribute so the chrome doesn't render an empty box. */
        /* The genotype leaf — no box; the leaf system carries spacing. */
        .genotype-panel {
            padding: 0;
        }
        .genotype-panel-title {
            font-size: 10px;
            text-transform: uppercase;
            letter-spacing: 0.12em;
            font-weight: 700;
            color: var(--text-muted);
            margin: 0 0 8px;
        }
        .genotype-row {
            display: grid;
            grid-template-columns: 90px auto 1fr;
            gap: 8px 12px;
            align-items: baseline;
            padding: 6px 0;
            border-bottom: 1px dashed var(--border-2);
        }
        .genotype-row:last-child {
            border-bottom: none;
        }
        .genotype-locus {
            font-size: 12px;
            font-weight: 700;
            letter-spacing: 0.04em;
            color: var(--text);
            font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
        }
        /* Zygosity label — a hairline-framed small-caps cartouche, not
           a rounded pill. The zg-* classes below keep the colour code. */
        .genotype-chip {
            display: inline-block;
            padding: 2px 8px;
            border-radius: 0;
            font-family: var(--font-serif);
            font-size: 11px;
            font-weight: 600;
            letter-spacing: 0.08em;
            text-transform: uppercase;
            font-feature-settings: "smcp", "lnum";
            border: 1px solid transparent;
            cursor: help;
        }
        /* Zygosity color coding (Field-Journal palette):
              wild-type     → sage   (homozygous, "as expected")
              carrier       → brass  (one wild + one recessive)
              recessive     → oxblood (expressed recessive)
              hybrid        → copper (cross-species heterozygous)
           JS picks the class from genotype + carrier_alleles. */
        .genotype-chip.zg-wild      { background: rgba(107, 143, 107, 0.16); border-color: rgba(107, 143, 107, 0.55); color: var(--sage); }
        .genotype-chip.zg-carrier   { background: rgba(184, 149, 106, 0.16); border-color: rgba(184, 149, 106, 0.55); color: var(--brass); }
        .genotype-chip.zg-recessive { background: var(--oxblood-bg);          border-color: var(--oxblood);            color: var(--oxblood-soft); }
        .genotype-chip.zg-hybrid    { background: var(--copper-dim);          border-color: var(--copper);             color: var(--copper); }
        .genotype-phenotype {
            font-family: var(--font-serif);
            font-style: italic;
            font-size: 13px;
            color: var(--ink-muted);
            line-height: 1.5;
        }
        .genotype-carriers-callout {
            margin-top: 10px;
            padding: 9px 12px;
            border: 1px dashed var(--rule-strong);
            border-radius: 1px;
            background: rgba(184, 149, 106, 0.06);
            font-family: var(--font-serif);
            font-style: italic;
            font-size: 12.5px;
            color: var(--ink-muted);
        }
        .genotype-carriers-callout strong {
            color: var(--brass);
            font-weight: 600;
            font-style: normal;
        }
        @media (max-width: 480px) {
            .genotype-row {
                grid-template-columns: 1fr auto;
                row-gap: 4px;
            }
            .genotype-phenotype {
                grid-column: 1 / -1;
            }
        }

        /* ---- Post-mating action row ----
           Shown on the result view when an offspring is being
           displayed (currentLibraryEntry.parent_a_id is set). Gives
           the player a clear next move so the loop doesn't dead-end
           after a finalized mating. */
        .post-mating-cta {
            margin-top: 14px;
            padding: 14px;
            border: 1px solid var(--border);
            border-radius: 8px;
            background: var(--surface-2);
            display: flex;
            flex-direction: column;
            gap: 10px;
        }
        .post-mating-cta-title {
            margin: 0;
            font-family: var(--font-hand);
            font-size: 20px;
            font-weight: 600;
            color: var(--ink-pen);
        }
        .post-mating-cta-actions {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
        }


/* ---- Cosmetic card frames (#97) ----
   A purchased frame--<key> class swaps the overlaid ornate frame asset for the
   cosmetic one in its own colour (overriding the rarity frame). Purely
   cosmetic — the .card-frame overlay reads --card-frame-img. */
.genome-card.frame--gilt      { --card-frame-img: url("/static/assets/frame-gilt.png");      --card-frame-slice: 16%; }
.genome-card.frame--obsidian  { --card-frame-img: url("/static/assets/frame-obsidian.png");  --card-frame-slice: 6%; }
.genome-card.frame--verdigris { --card-frame-img: url("/static/assets/frame-verdigris.png"); --card-frame-slice: 6.5%; }
.genome-card.frame--oxblood   { --card-frame-img: url("/static/assets/frame-oxblood.png");   --card-frame-slice: 11%; }
.genome-card.frame--bone      { --card-frame-img: url("/static/assets/frame-bone.png");      --card-frame-slice: 11%; }
