/* â”€â”€â”€ Wingspan theme â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
   Split out of site.css 2026-08-02. Everything here is scoped to
   [data-theme="wingspan"]; base styles stay in site.css.

   LOAD ORDER IS PART OF THE CONTRACT. _Layout links site.css, then every theme
   file, then themes/_shared.css. Theme rules carry an extra attribute selector,
   so they outrank base styles wherever they land - but do not reorder the links
   without re-reading _shared.css, which wins by POSITION rather than weight.

   The picker applies themes client-side with no reload (site.js), so every theme
   file ships on every page. Serving only the active theme would need the picker
   to fetch on demand first. */
/* Wingspan - the board's three habitat rows on bird-card stock. Forest green is the
   chrome band, wetland blue does the fill/line work, grassland gold carries links and
   buttons (deep on the page, bright as the spark on the green band). Every one of the
   three habitats has a job; the cream is the card stock they're printed on.

   PARKS COLLISION - Parks is also cream page + green chrome, so two separations are
   deliberate here and should not be "simplified" away: this green is warmer and a step
   LIGHTER than Parks' pine #27503f, and the card surfaces run a cool wetland wash
   against the warm page (Parks' run warm tan). That warm-page/cool-card split is the
   Calico move and it's what tells the two apart at a glance. If they ever read as
   siblings again, push THIS chrome further warm/light - don't touch Parks. */
[data-theme="wingspan"] {
    /* ── PAGE: bird-card stock. Warmer and lighter than Parks' paper. ── */
    --bg: #f8f2e4;
    /* Cards/surfaces: bird-card stock, warm cream.
       These went pale SKY briefly on 2026-08-02 and came back the same day after seeing a
       grid of them. Worth recording WHY, because "more blue" is a reasonable instinct and
       will come round again: the blue was fine in isolation, but a page is mostly cards, so
       tinting the card stock tints the whole page and the meadow art stops being the thing
       you notice. Blue does more work here than it did before that experiment - the nav
       accent, the section-header bands, the inputs - it just does it in BANDS and details,
       on cream, which is also how the game uses it.
       So: if this comes up again, spend the blue on bands, not on stock. */
    --bg2: #fbf7ed;
    --bg3: #f3ecdc;
    --surface: #e7dcc4;
    --border: #d6c8ab;
    --border2: #bfae8c;
    --text: #1f261f;
    --text-mid: #4f5a4d;
    --text-dim: #616b5d;
    /* ── ACCENT: grassland gold, deep enough to carry text on the cream page. ── */
    --amber: oklch(0.52 0.11 80);
    --amber-dim: oklch(0.43 0.09 80);
    --amber-bg: oklch(0.93 0.04 85);
    /* ── SECONDARY: wetland blue - borders, fills, the under-nav line. ── */
    --cyan: #2f7d9e;
    --cyan-dim: rgba(47, 125, 158, 0.45);
    /* Likes are PINK in this theme, matching the eggs in the nest corner art rather than
       the default warm red. This is the single source of truth for the colour - the egg
       glyph on the card's brown band derives its lighter shade from this var with
       color-mix, so retinting likes here carries everywhere instead of drifting apart.
       Chosen dark enough to clear AA on the cream page (~5.3:1), which is the binding
       constraint; the brown band is handled by the derivation, not by a second hex. */
    --heart: #d1477a;
    /* ── CHROME (nav): tobacco leather. ──
       The band is dark and even, so the ink is CREAM and the accent is bright goldfinch
       gold. See the .site-nav rule further down for how the leather and its saddle stitch
       are built; this is just the palette.

       --nav-bg IS NOT WHAT YOU SEE. wingspan-nav.webp is opaque (plain lossy WebP, no
       alpha channel) and tiles across the whole band, so this colour is only ever visible
       if that file fails to load. It is kept in step with the art as a fallback, and it is
       also the value ThemeCatalog hands the browser as theme-color. Retinting the nav
       means editing the IMAGE - changing this hex alone does nothing on screen. Measured
       2026-08-02 when the art came out at rgb(115,61,32) against this var's #8a5533. */
    --nav-bg: #8a5533;
    --nav-border: #4a2c18;
    --nav-fg: #f0e2d0;
    --nav-fg-dim: #cdb69c;
    --nav-fg-strong: #fff8ee;
    /* Sky, not goldfinch gold (owner call 2026-08-02) - the same #bfe0ef as the goal-card
       band on the section headers, so the nav highlight and the page headings are visibly
       the same mark. It also reads considerably better on the leather than the gold did:
       6.2:1 against the band's measured tone, where the gold sat at 3.6:1 and only cleared
       its bar by counting as large text in the wordmark. Carries the "Games" half of the
       logo, the link hover, and the active chip below. */
    --nav-accent: #bfe0ef;
    --nav-accent-dim: rgba(191, 224, 239, 0.5);
    --nav-accent-bg: rgba(255, 255, 255, 0.12);
    --nav-btn-border: rgba(240, 226, 208, 0.4);
    /* The under-nav accent line is off: the saddle stitch below sits INSIDE the band
       and is the edge detail, so a second line under it would read as a double rule. */
    --nav-gradient: transparent;
    --nav-texture: none;
    --footer-bg: #40694c;
    --footer-border: #33563e;
    /* Opaque white, not the old pale green: the footer is a painting now, and a tinted
       near-white reads as dirty against water and reeds. Same call Calico made. */
    --footer-fg: #ffffff;
    --footer-accent: #e8b53f;
    /* Footer band: golden meadow at its TOP edge falling away into deep water. Cropped
       that way deliberately so the footer continues the meadow page above it instead of
       butting against it - an earlier all-water band read as a hard horizontal cut
       across the page.

       Only the bottom 48% of the painting is used, at its NATIVE resolution and aspect.
       Do not squash this one: an earlier version compressed the crop to 117px tall,
       which the browser then had to blow back up ~4x to fill the band - it rendered
       visibly soft and low-res. The crop's natural aspect already fits, so squashing
       bought nothing and cost the resolution. Any remaining softness is the source art's
       own ceiling (1774px wide, upscaled ~1.9x on an ultrawide); the only fix for that
       is larger source art.

       WHY A SCRIM RATHER THAN HAND-TUNED NUMBERS: the crop fraction, .footer-inner's
       padding-top and the band's own height are mutually dependent - padding-top is part
       of what makes the band tall, so raising it to push the links clear of the grass
       also stretches the grass down to meet them again. Chasing that by hand does not
       converge, and an early version shipped with the first link row sitting on pale
       grass at ~40% overlap.

       So the gradient layer guarantees the outcome instead: transparent across the top
       where the grass does the blending, then darkening from ~30% down so the link rows
       always sit on a dark field wherever the waterline actually lands. That decouples
       the art from the layout - the crop can now be chosen for how it LOOKS rather than
       for where the text happens to fall. */
    --footer-texture:
        linear-gradient(to bottom,
            rgba(14, 42, 62, 0) 0%,
            rgba(14, 42, 62, 0) 30%,
            rgba(14, 42, 62, 0.14) 50%,
            rgba(14, 42, 62, 0.18) 100%),
        url("/images/wingspan-footer.webp");
    --footer-texture-repeat: no-repeat, no-repeat;
    --footer-texture-position: center, center;
    --footer-texture-size: auto, cover;
    /* Feathers over the green band, barely there. Per the Calico honeycomb lesson: if
       this reads flat, scale the tile UP at this opacity rather than raising it. */
    --nav-texture: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'%3E%3Cg fill='none' stroke='%23ffffff' stroke-opacity='0.045' stroke-width='1.1' stroke-linecap='round'%3E%3Cpath d='M12 6 C20 14 20 28 12 38 C4 28 4 14 12 6 Z'/%3E%3Cpath d='M12 10 V35'/%3E%3Cpath d='M42 26 C50 34 50 48 42 58 C34 48 34 34 42 26 Z'/%3E%3Cpath d='M42 30 V55'/%3E%3C/g%3E%3C/svg%3E");
    --nav-texture-size: 60px 60px;
    /* Egg (Wingspan's scoring tokens) as the list bullet, the way Calico's became
       sewing buttons. Owner-supplied silhouette; viewBox trimmed to the art bounds so it
       isn't swimming in the source's 512 padding.

       THREE colours, in the habitat trio the scrollbar already uses - forest green,
       grassland gold, wetland blue - cycled down a list by nth-child below (owner call
       2026-08-02). A clutch of eggs is mixed, not monochrome, and the trio is already
       this theme's signature elsewhere. The gold is deepened from the nav's goldfinch
       #e8b53f: these are 10px shapes on a cream page, and at that size the bright gold
       reads as a smudge rather than a colour.
       Only the fill differs between the three - if the silhouette is ever redrawn, all
       three need the same new path. */
    --egg-green: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='13' viewBox='102 51 308 410'%3E%3Cpath d='m256 51.199c-65.5 1.1992-154.52 114.02-153.6 247.46 0.82031 117.22 81.5 162.54 153.6 162.14 72.102 0.39844 152.78-44.898 153.6-162.14 0.92188-133.46-88.102-246.26-153.6-247.46z' fill='%2340694c'/%3E%3C/svg%3E");
    --egg-gold: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='13' viewBox='102 51 308 410'%3E%3Cpath d='m256 51.199c-65.5 1.1992-154.52 114.02-153.6 247.46 0.82031 117.22 81.5 162.54 153.6 162.14 72.102 0.39844 152.78-44.898 153.6-162.14 0.92188-133.46-88.102-246.26-153.6-247.46z' fill='%23c98f2b'/%3E%3C/svg%3E");
    --egg-blue: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='13' viewBox='102 51 308 410'%3E%3Cpath d='m256 51.199c-65.5 1.1992-154.52 114.02-153.6 247.46 0.82031 117.22 81.5 162.54 153.6 162.14 72.102 0.39844 152.78-44.898 153.6-162.14 0.92188-133.46-88.102-246.26-153.6-247.46z' fill='%232f7d9e'/%3E%3C/svg%3E");
    /* Single-colour alias for the non-list markers (Print Resources rows), which are one
       per row rather than a sequence and so have nothing to cycle against. */
    --egg-bullet: var(--egg-blue);
}
/* The footer band runs light (grass) at the top and dark (water) below, so the link
   rows are pushed DOWN off the grass and onto the water where white text reads. The
   bottom padding leaves some open water under them rather than ending flush. */
[data-theme="wingspan"] .footer-inner { padding-top: 310px; padding-bottom: 40px; }
/* Dissolve the footer's top edge into the meadow above it. Masking the whole band is
   what makes this a real blend rather than a colour-match: the top ~110px fades to
   fully transparent, so what shows through is the actual page background at that
   scroll position, and the two can never drift apart the way a hand-picked seam colour
   would. The band's 1px border-top goes with it - a hairline is exactly the hard edge
   being removed.

   Safe only because .footer-inner holds its content 124px down: the mask fades
   everything in the element, text included, so the clear zone has to end before the
   first link row. If that padding is ever reduced below the mask's end stop, the top
   row of links starts fading out. */
[data-theme="wingspan"] .footer-line {
    border-top: none;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 50px);
    mask-image: linear-gradient(to bottom, transparent 0, #000 50px);
}
/* Card foot as a bird card's detail band. On the real cards the coloured band runs along
   the BOTTOM carrying the power text, not down the side - an earlier version put the three
   habitat colours as a stripe on every card's left edge and it read as visual noise
   repeated across a whole grid, competing with the print photos it was meant to frame.
   The habitat trio moved to the scrollbar instead (below), where it is present without
   being multiplied.

   Bleeds to the card's edges with a negative margin matching .lu-print-card-body's 10px
   padding. margin-top stays `auto` - that is what pins the foot to the bottom of a
   flex-column card, so writing a fixed top margin here would break the grid's alignment. */
[data-theme="wingspan"] .lu-print-card-foot {
    background: #8c5830;
    color: #f2e6d8;
    margin: auto -10px 0;
    padding: 6px 10px;
}
[data-theme="wingspan"] .lu-print-card-foot .lu-host-line { color: #ecdac6; }
[data-theme="wingspan"] .lu-print-card-foot .lu-byline-by { color: #d9c3aa; }
[data-theme="wingspan"] .lu-print-card-foot .lu-designer-link { color: #f2cd82; }
/* The count rides var(--amber) by default, which in this theme is the deep grassland gold -
   near-identical in value to the brown band behind it, so it vanished when the band landed.

   Glyph and number are coloured SEPARATELY here, on purpose. The number is text and has to
   clear AA on the brown, which no pink light enough to look pink can do. The egg is a solid
   shape, where a ~2.6:1 separation reads fine. So the number goes cream and the egg carries
   the pink - derived from --heart with color-mix rather than hardcoded, so it stays tied to
   the likes colour if that is ever retuned. */
[data-theme="wingspan"] .lu-print-card-foot .lu-print-card-hearts { color: #f3e4d4; }
[data-theme="wingspan"] .lu-print-card-foot .lu-print-card-hearts svg {
    color: color-mix(in srgb, var(--heart) 48%, #ffffff);
}
/* The same brown detail band on the other two card families (owner call 2026-08-02), so a
   Wingspan page reads as one deck rather than bird cards next to plain ones:
     .lu-card-flags   - game cards: /boardgames, /MyGames, /wishlist
     .lu-card-actions - print cards on My Prints and My Future Prints
   Both are already the bottom row of their card and both are direct children of .lu-card,
   which has no padding of its own, so unlike .lu-print-card-foot these need no negative
   margin to bleed - they only need vertical padding, which .lu-card-flags did not have.
   .lu-card-actions drops its border-top: the band's own edge is the separator now, and
   keeping both drew a hairline across the top of the brown.

   Neither selector needs a page scope. .lu-card-actions appears on exactly these two views,
   and .lu-card-flags on exactly the three game-card views. If either class is reused
   somewhere that should NOT get a band, this is where to add the exclusion. */
[data-theme="wingspan"] .lu-card-flags,
[data-theme="wingspan"] .lu-card-actions {
    background: #8c5830;
    color: #f2e6d8;
}
[data-theme="wingspan"] .lu-card-flags { padding: 7px 12px; }
[data-theme="wingspan"] .lu-card-actions { border-top: none; padding: 0.6rem 1rem; }
/* Everything riding the band is recoloured for it. The site's buttons rest on transparent
   with --text-mid / --text-dim / --amber ink, all of which are page colours chosen against
   cream and none of which survive on brown - --amber especially, being near the band's own
   value (the same trap the heart count hit above).
   HOVER is deliberately left alone: .lu-btn:hover paints its own pale --amber-bg fill, so
   the hovered state is already a light chip and reads fine on the band. */
[data-theme="wingspan"] .lu-card-flags .lu-card-prints { color: #f2e6d8; }
[data-theme="wingspan"] .lu-card-flags .lu-card-prints.has-prints { color: #ffe9bd; }
/* Wishlist priority badges, same treatment as the toggles: cream label so every rung is
   legible on the brown, and the rung itself carried by the border. The badge's border is
   currentColor, so setting the label colour recolours the border too - hence the per-rung
   border-color right after, in lightened versions of the page scale (the hot red of
   "Must have" was the worst offender on this band, at roughly 2:1). */
[data-theme="wingspan"] .lu-card-flags .lu-wish-priority-badge { color: #f2e6d8; }
[data-theme="wingspan"] .lu-card-flags .lu-wish-prio-1 { border-color: #ffb3a7; }
[data-theme="wingspan"] .lu-card-flags .lu-wish-prio-2 { border-color: #f2cd82; }
[data-theme="wingspan"] .lu-card-flags .lu-wish-prio-3 { border-color: #9fd4e8; }
[data-theme="wingspan"] .lu-card-flags .lu-wish-prio-4 { border-color: rgba(242, 230, 216, 0.5); }
[data-theme="wingspan"] .lu-card-flags .lu-icon-btn,
[data-theme="wingspan"] .lu-card-actions .lu-btn,
[data-theme="wingspan"] .lu-card-actions .lu-icon-btn {
    color: #f2e6d8;
    border-color: rgba(242, 230, 216, 0.45);
}
/* Lit toggles keep the CREAM label and carry their state in the FILL and border instead of
   in the text colour. On a dark band that is the only way to do it accessibly: the wetland
   blue and grassland gold that mark these states on the cream page both land near 3.5:1 as
   ink on brown, while cream holds 4.7:1 whatever the state. */
[data-theme="wingspan"] .lu-card-flags .lu-icon-btn.active,
[data-theme="wingspan"] .lu-card-actions .lu-icon-btn.active {
    color: #f2e6d8;
    background: rgba(255, 255, 255, 0.16);
    border-color: rgba(242, 230, 216, 0.75);
}
[data-theme="wingspan"] .lu-card-flags .lu-icon-btn-has.active { border-color: #9fd4e8; }
[data-theme="wingspan"] .lu-card-flags .lu-icon-btn-need.active { border-color: #f2cd82; }
/* Breathing room above the band on the browse cards, where the Printed / Want toggles now
   sit directly on top of it. The foot's own top margin is `auto`, which collapses to zero
   on a card with no spare height - so the gap has to come from the toggles. */
[data-theme="wingspan"] .lu-print-card-toggles { margin-bottom: 6px; }
/* Print-page hero furniture gets SOLID surfaces (owner call 2026-08-02). This is the other
   half of pulling the page veil back: the art gets to be louder because everything that
   matters stops borrowing the page as its background. The facts strip and the heart were
   bare text straight on the meadow, and the Free pill's site-wide fill is rgba at 0.14 -
   86% art. Panels are --bg2 with the card hairline, so they read as the same family as the
   cards; translucency here would just re-import the problem the veil had. */
[data-theme="wingspan"] .lu-pd-facts {
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 7px 14px;
}
[data-theme="wingspan"] .lu-stl-heart-btn,
[data-theme="wingspan"] .lu-stl-heart-static {
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 5px;
}
[data-theme="wingspan"] .lu-stl-host-btn { background: var(--bg2); }
/* Pills go fully opaque. The Free pill keeps its green but as a solid chip with white ink
   (the site-wide translucent green + green-on-green ink needs a flat page to work); the
   category badge trades the pale amber wash for the solid surface tone so it stops
   disappearing into the meadow at equal value. */
[data-theme="wingspan"] .lu-pd-free { background: #2a8446; color: #ffffff; }
[data-theme="wingspan"] .lu-stl-category-badge {
    background: var(--surface);
    border-color: var(--border2);
    color: var(--amber-dim);
}
[data-theme="wingspan"] .lu-heart-glyph-heart { display: none; }
[data-theme="wingspan"] .lu-heart-glyph-egg { display: inline; }
[data-theme="wingspan"] .lu-print-card-hearts svg { width: 0.72em; height: 0.96em; vertical-align: -0.16em; }
/* The leather band. Declared here rather than through --nav-texture so the sizing and
   position can be set independently of the base .site-nav rule's hardcoded
   `background-repeat`.

   A TEXTURE, and that is why it finally works. Five earlier attempts put art with
   STRUCTURE in this band - a forest scene, edge tree clusters, a treeline, a sky with a
   horizon - and every one fought the same losing battle: the band is ~63:1, so art with
   recognisable shapes either gets magnified until only a smear survives, or has to be
   tiled and repeats visibly. Leather grain has neither problem: nothing to crop wrongly,
   and tiling is invisible. If this is ever swapped for art containing objects, expect all
   of that to come back.

   GRAIN SCALE is set by background-size, and it is the opposite of the intuition. Cover-
   fitting the source rendered it near 1:1, which made the pebbling ~20px against a 52px
   band - far too coarse, and it fought the logo. Shrinking the grain means displaying the
   texture SMALLER than native, which necessarily means repeating it. So the file is a
   4-way MIRRORED tile (opposite edges identical by construction, so the seam cannot
   show) laid at a fixed 2400px instead of cover. Grain now lands around 7px. Want it
   finer still? Lower the 2400px. Coarser? Raise it. Do not switch back to cover.

   Darkened 18% at conversion, not with a CSS overlay: an overlay would flatten the grain
   it is trying to preserve, while baking it in keeps the leather's own tonal variation.

   THE STITCH is CSS, not baked into the image, and deliberately so: painted into the art
   it would stretch and drift with every viewport instead of holding a fixed 8px off the
   band's edge. The idea is Calico's hand-rolled saddle stitch, run finer here - 9px
   thread, 7px gap, 2px thick at 30% alpha, against Calico's 14/10/3 - because this sits
   on leather at nav scale rather than around a quilt card. Alpha went 55% -> 30% (owner
   call 2026-08-02): the whole point is stitching set INTO the leather, and anything
   stronger reads as a dashed rule drawn ON it. Three knobs, all in the two lines below:
   thread and gap are the gradient stops, thickness and period are background-size,
   opacity is the rgba alpha.
   --nav-gradient is switched off to stop it drawing a second rule underneath.

   The leather is dark and even, so the ink is CREAM and the accent is bright goldfinch
   gold, with no scrim - exactly what the pale-band versions had to fake with a gradient.
   Measured 2026-08-02: mean tone 69/255, and cream ink clears AA at 5.3:1 even over the
   lightest patch of grain. */
[data-theme="wingspan"] .site-nav {
    background-image:
        repeating-linear-gradient(to right,
            rgba(236, 205, 166, 0.30) 0 9px,
            transparent 9px 16px),
        url("/images/wingspan-nav.webp");
    background-repeat: repeat-x, repeat;
    background-position: left calc(100% - 8px), center;
    background-size: 16px 2px, 2400px auto;
}
/* Cards get a hairline. .lu-card carries no border at all site-wide, which is fine on
   themes whose page and card colours are far apart - but here they are neighbours, and on
   the meadow art the card edge was doing no work at all. --border, so it moves with the
   surface colour rather than needing a second edit if the cards are ever retinted.
   NOT a panel behind the cover images: that was tried and rejected (2026-07-12) as
   clutter on the two-up cards, and this is deliberately the lighter touch - one line at
   the card's own edge, nothing added between the images. */
[data-theme="wingspan"] .lu-card { border: 1px solid var(--border); }
/* Page titles keep the site's own display face (owner call 2026-08-02). This theme briefly
   set them in Patrick Hand for a field-notebook voice; it read as a novelty face against
   everything else on the page and came off. Only the COLOUR is themed now.
   Patrick Hand went out of _Layout's Google Fonts link with it - this was its only user,
   and every visitor was fetching it whatever theme they were on. */
[data-theme="wingspan"] .lu-page-title { color: var(--amber); }
/* Section headers as goal-card headers: on Wingspan's bonus/goal cards the title sits in
   a pale sky-blue band with dark text, so .lu-title gets the same treatment rather than
   just being tinted blue. That distinction matters - the blue is a BACKGROUND on those
   cards, and at the lightness that makes it recognisable it would fail contrast as text
   on the cream page (roughly 2:1). As a band with dark ink on it, it clears AA at ~8:1.

   inline-block so the band hugs its text instead of running the full column width, which
   is what makes it read as a card header rather than a section rule. Gold stays on the
   handwritten page title above, so the two levels stay distinct.

   The LEFT edge dissolves like the tail of a brush stroke (owner call 2026-08-02): a hard
   vertical edge sitting on the page's left margin read as a pasted-on rectangle against
   watercolour art. Two details do the work. The gradient is angled 100deg rather than a
   flat 90, so the wash clears at the top-left a few px before the bottom-left - an even
   vertical fade reads as a gradient, a tilted one reads as a brush lifting. And the left
   padding is opened to 30px so the fade happens in empty band BEFORE the first letter,
   rather than under it. Contrast is unaffected either way: dark ink on the blue and dark
   ink on the cream page both clear AA, so the band can dissolve freely. Right side stays
   crisp - that is where the stroke is pressed down. */
/* "You are here" as a watercolour mark rather than a UI chip, so the active nav item and
   the section heading below it read as the same hand (owner call 2026-08-02).

   `background: none` and a cleared border are load-bearing: the base .nav-link.active
   paints a solid --nav-accent fill with a matching border, which is the box this replaces. */
/* An UNDERSTROKE, not a filled chip. Three filled versions were tried - washed left edge,
   washed both edges, elliptical fade - and every one read as a box, because the problem was
   never the hue or the softness of the ramp. It is VALUE. Any pale shape on this leather is
   a huge tonal jump, so the eye finds its boundary no matter how gently the alpha ramps;
   softening the edge just moves where the boundary is read, it does not remove it. On the
   cream page the same wash works precisely because pale blue on cream is barely a step at
   all. Cream or gold in place of the blue would have changed nothing - both are lighter
   than the leather still.
   A thin bar has no interior for a boundary to enclose, so it dissolves honestly: at 3px
   tall the eye reads a tapering mark rather than an edge, and the linear fade at each end
   finally does what it does on the headers.
   Reviving an underline here is safe in THIS theme specifically: the bar was dropped
   site-wide in 2026-07 for doubling up with the accent line at the band's bottom edge, and
   Wingspan sets --nav-gradient: transparent (the saddle stitch is its edge detail), so
   there is no second line to collide with. .nav-link already carries position: relative for
   exactly this. */
[data-theme="wingspan"] .nav-link.active {
    color: var(--nav-accent);
    background: none;
    border-color: transparent;
}
[data-theme="wingspan"] .nav-link.active::after {
    content: "";
    position: absolute;
    left: 12px;
    right: 12px;
    bottom: 2px;
    height: 3px;
    border-radius: 2px;
    background: linear-gradient(to right,
        rgba(191, 224, 239, 0) 0,
        #bfe0ef 20%,
        #bfe0ef 80%,
        rgba(191, 224, 239, 0) 100%);
}
[data-theme="wingspan"] .lu-title {
    display: inline-block;
    background-image: linear-gradient(100deg,
        rgba(191, 224, 239, 0) 0,
        rgba(191, 224, 239, 0.5) 24px,
        #bfe0ef 52px);
    color: #1b3a49;
    padding: 3px 12px 4px 30px;
    border-radius: 3px;
}
/* Filter bars (2026-08-02). The site runs TWO input systems - Bootstrap .form-control /
   .form-select on the browse, My Games and wishlist rows, and .lu-input on the Designers
   and admin rows - and they did not match each other: one was a grey-blue, the other a
   beige darker than the cards it sat on. Both now land on the same near-white sky, a shade
   above the card blue rather than below it, which is what an editable field should be.
   Named here rather than left to --bg3: an input has to sit ABOVE its card, so it tracks
   the card colour without being it.
   Radius 5px, not the 8-12px a bigger softening would want: the site's vocabulary is 2-4px
   (cards 4, chips and icon buttons 2, the section band 3), so 5 reads as the soft end of
   the existing family instead of making inputs the roundest thing on the page. */
[data-theme="wingspan"] .form-control,
[data-theme="wingspan"] .form-select,
[data-theme="wingspan"] .lu-input {
    /* A shade bluer than the near-white it launched with (owner call 2026-08-02: "very
       light blue to match the background") - the sky wash in the page art, one step up in
       lightness so an editable field still reads raised off whatever it sits on. */
    background-color: #eef7fb;
    border-color: #a8c8db;
    border-radius: 5px;
}
/* Search was briefly filled forest green; now the goal-card sky with the same dark ink as
   .lu-title (owner call 2026-08-02) - the button, the section bands and the nav accent are
   deliberately one blue. Ink clears AA on this fill at ~8:1.
   Filled but NOT promoted to a primary CTA - every select in these rows carries
   data-submit-on-change and submits itself, so the button only matters for the free-text
   field, and sizing it like the page's main action would make the loudest control the one
   least often clicked. */
[data-theme="wingspan"] .lu-bg-search-btn {
    background: #bfe0ef;
    border-color: #9dc0ce;
    color: #1b3a49;
    border-radius: 5px;
}
[data-theme="wingspan"] .lu-bg-search-btn:hover {
    background: #abd3e6;
    border-color: #8cb4c6;
    color: #142d3a;
}
/* The habitat trio lives here now: forest green over grassland gold over wetland blue,
   running down the scrollbar thumb. One instance on the page instead of one per card,
   which is why it reads as a signature rather than as noise.
   WebKit/Blink only. Firefox's `scrollbar-color` takes two flat colours and cannot do a
   gradient, so it falls back to the default bar - acceptable, since this is decoration
   and nothing depends on it. */
[data-theme="wingspan"] ::-webkit-scrollbar { width: 11px; }
[data-theme="wingspan"] ::-webkit-scrollbar-thumb {
    background: linear-gradient(to bottom,
        #40694c 0 33.34%,
        #e8b53f 33.34% 66.67%,
        #2f7d9e 66.67% 100%);
    border-radius: 6px;
}
/* Native checkboxes/radios in the wetland blue. */
[data-theme="wingspan"] { accent-color: #2f7d9e; }
[data-theme="wingspan"] option:checked,
[data-theme="wingspan"] option:hover {
    background-color: #40694c;
    color: #ffffff;
}
/* Egg bullets on EVERY bulleted list in main, cycling green - gold - blue down the list
   (owner call 2026-08-02; this used to be `ul:not([class])`, which missed every list the
   site gives a class to).

   Why an exclusion list rather than the old `:not([class])`: a class does not mean "do not
   decorate me", it usually just means the list has spacing rules. What actually must be
   left alone is the handful of lists that deliberately show NO marker - `list-style: none`
   loses to this selector, so without naming them their markers would come back. The two
   below are the site's only marker-less ULs; lists that kill their markers with an INLINE
   style (the Admin ones) already win on their own and need no entry here. If a new
   marker-less list appears and sprouts eggs, add it to this list.

   nth-child on the LI, not the UL, is what makes the cycle work: list-style-image is
   inherited, so a per-item rule is the only place the three colours can differ. Written
   as 3n+1/2/3 rather than 3n+1/2/0 so the three read in order at a glance. */
[data-theme="wingspan"] main ul:not(.lu-fil-list):not(.lu-unbox-lead-list) > li:nth-child(3n+1) {
    list-style-image: var(--egg-green);
}
[data-theme="wingspan"] main ul:not(.lu-fil-list):not(.lu-unbox-lead-list) > li:nth-child(3n+2) {
    list-style-image: var(--egg-gold);
}
[data-theme="wingspan"] main ul:not(.lu-fil-list):not(.lu-unbox-lead-list) > li:nth-child(3n+3) {
    list-style-image: var(--egg-blue);
}
/* Print Resources rows: the egg leads each link row (the row is a flex container, so
   the ::before rides its 16px gap as the first item). */
[data-theme="wingspan"] .lu-resources-row::before {
    content: "";
    flex: 0 0 26px;
    width: 22px;
    height: 26px;
    background-image: var(--egg-bullet);
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
/* Page background: the MEADOW zone of the player mat - the golden middle row. Bespoke
   body rule because there is no --page-texture var (that machinery was built and
   removed; Calico's quilt tile is a body rule for the same reason).

   The three page zones deliberately mirror the mat top-to-bottom: forest/sky at the
   nav, meadow across the page, water at the footer. That stack IS the theme; treat the
   three as a set, and if one is re-generated, re-check the other two still read as
   bands of the same painting.

   A SCENE, not a texture, so it deliberately does not tile - fixed and cover-fitted,
   one image behind the whole page, content scrolling over it.

   The art measures 222/255, so body text (#1f261f) clears AA on it with room to spare.
   The cream veil is not rescuing contrast - it is taking the edge off the saturation so
   a whole page of it doesn't tire the eye. Raise it if the colour shouts, lower it
   toward 0 if the scene reads washed out.

   Positioned CENTRE, not top. This art has a horizon (sky above, meadow below), and it
   is wider than most viewports - so on a tall window cover crops the sides and shows
   everything, but on an ultrawide it crops VERTICALLY. Anchored top, an ultrawide would
   show sky only and lose the meadow entirely; centred, the horizon stays on screen at
   every shape. Re-check this if the art is ever swapped for something without a
   horizon, where top-anchoring is usually better.

   READING BAND (top layer): a second, stronger cream veil sized to a fixed 1620px and
   centred, so it lightens the scene only where the text sits and leaves the painting at
   full strength out at the margins. Owner call 2026-08-02 - the meadow is the busiest,
   most saturated part of the art and it runs straight through the content column.
   Deliberately NOT a percentage-width band: content is a fixed 1320-1400px container, so
   a percentage would drift off it as the window widens. 1620px clears the widest
   container by ~110px a side, which is exactly the feather distance - so the fade-out
   always happens outside the text, never under it. On windows narrower than 1620px the
   band simply overflows and the feathered ends fall off-screen, which is the right
   behaviour: no room for margin art anyway.

   PULLED BACK to 0.33 on 2026-08-02 (owner: let more of the painting through). It stacks on
   the 0.22 all-over veil for ~0.48 total in the middle, down from ~0.58.
   0.45 total is the FLOOR, and the limit is not body text - measured against the darkest
   patch of the art, rgb(201,169,73), body ink holds 8:1 even with no band at all. It is the
   MUTED text (--text-mid, the lead paragraph under a page title) that binds: it sits
   directly on the art with no panel behind it and crosses 4.5:1 at almost exactly 0.45. So
   there is roughly 3 points of headroom here, not 20. Anything below that needs the lead
   paragraph to get a surface of its own first. */
[data-theme="wingspan"] body {
    background-image:
        linear-gradient(to right,
            rgba(250, 246, 234, 0) 0,
            rgba(250, 246, 234, 0.33) 110px,
            rgba(250, 246, 234, 0.33) calc(100% - 110px),
            rgba(250, 246, 234, 0) 100%),
        linear-gradient(rgba(250, 246, 234, 0.22), rgba(250, 246, 234, 0.22)),
        url("/images/wingspan-page.webp");
    background-size: 1620px 100%, auto, cover;
    background-position: center, center, center center;
    background-repeat: no-repeat, no-repeat, no-repeat;
    background-attachment: fixed, fixed, fixed;
}
/* background-attachment:fixed is janky-to-broken on mobile browsers (iOS Safari in
   particular ignores it and blows the image up). Small screens get the plain cream
   page - the art is decoration, and phones need the pixels for content anyway. */
@media (max-width: 767px) {[data-theme="wingspan"] body { background-image: none; }}
/* Wingspan's owned glyph is a feather - same swap Calico does with the paw, but it needs
   its own BOX. The feather's viewBox is 223x347, so `meet` inside the meeple's 12x12 square
   fits it by height and renders it about 7.7px wide - a sliver too thin to read as a
   feather at all. Given a box at its own 0.64:1 ratio it fills the space instead, and the
   height goes up to 17px because a narrow shape needs more of it to be recognisable than a
   chunky one does. Exactly the fix the egg glyph needed against the heart's wider box. */
[data-theme="wingspan"] .lu-owned-glyph-meeple { display: none; }
[data-theme="wingspan"] .lu-owned-glyph-feather { display: inline; }
[data-theme="wingspan"] .lu-owned-icon { width: 11px; height: 17px; vertical-align: -4px; }
/* The hummingbird perches at the end of the Ctrl-K search row, the way Calico's cat curls
   there (owner call 2026-08-02). 64px against Calico's 75px is not a smaller bird, it is
   the same 50px height at this art's 1.25:1 (250x200) instead of the cat's wider box.
   Sizing both by HEIGHT is what keeps the two rows identical; giving this one 75px would
   just pad the sides and render the bird smaller.

   BREAKPOINT is 640px, not the 1200px Calico uses. 1200px was the wrong constraint and it
   is why this did not appear for the owner: the palette is a fixed 560px panel, so viewport
   width says nothing about whether the row has room - it has the same room at 700px as at
   2560px. 640px is simply where the panel stops being viewport-width. (Calico's cat is left
   at 1200px deliberately: not my call to change another theme's art without asking.) */
@media (min-width: 640px) {
    [data-theme="wingspan"] .cmdk-input-wrap::after {
        content: "";
        flex: 0 0 64px;
        height: 50px;
        margin: -14px 0;
        background: url("/images/wingspan-tr.webp") no-repeat center / contain;
    }
}

/* Let the meadow show through the modal scrim (owner call 2026-08-02). The site default is
   rgba(6,5,12,0.66) plus a 2px blur - built for the dark themes, where the page behind is
   near-black anyway and the scrim costs nothing. Over watercolour it throws away the thing
   worth looking at. Warm and much lighter here, with the blur halved.
   Safe to lighten this far because the scrim is not doing contrast work: the palette panel
   is opaque --bg2, so every bit of text sits on its own surface. The scrim only has to say
   "the page behind is not what you are talking to". */
[data-theme="wingspan"] .cmdk-overlay,
[data-theme="wingspan"] .kbd-overlay {
    background: rgba(58, 42, 26, 0.32);
    backdrop-filter: blur(1px);
}
/* Wingspan corner art. Same convention and geometry as Calico's: root-element
   pseudo-elements (not body, so they never collide with the homepage's body::before noise
   overlay), fixed, pointer-events:none, z-index under the nav, anchored to the viewport
   corner. NOTE these rules are per-theme by design - there is no generic
   "{theme}-tr.webp lights up automatically" mechanism, despite the naming convention.
   Both render nothing and break nothing until the two files are dropped in. */
[data-theme="wingspan"]::before,
[data-theme="wingspan"]::after {
    content: "";
    position: fixed;
    pointer-events: none;
    z-index: 40;
    background-repeat: no-repeat;
    background-size: contain;
}
/* Hummingbird, upper-right. Box matches the art's 1.25:1 (250x200 after trimming) so
   `contain` fills it exactly - a square box would just pad the short side and make the
   bird render smaller than its width suggests. A touch larger than Calico's 96px heart
   because this is a detailed watercolor, not a flat glyph. */
[data-theme="wingspan"]::before {
    top: 84px;
    right: 18px;
    width: 116px;
    height: 93px;
    opacity: 0.55;
    background-image: url("/images/wingspan-tr.webp");
    background-position: right top;
}
/* Wood duck, bottom-left, 1.4:1 (250x179). Sits ON the viewport floor - a standing
   bird works here for the same reason a nest would and a flying one wouldn't: the
   silhouette has a flat baseline to rest on. The source art was square with ~99px of
   transparent padding under the feet; it is trimmed to the alpha bounds so the duck
   meets the floor instead of hovering over it. Box matches the trimmed ratio so
   `contain` fills it exactly - a taller box would just pad above the head. */
[data-theme="wingspan"]::after {
    left: 16px;
    bottom: 16px;
    width: 146px;
    height: 105px;
    opacity: 0.55;
    background-image: url("/images/wingspan-bl.webp");
    background-position: left bottom;
}
/* Narrower than the widest column plus its margins: the art can reach content, so it goes
   watermark-faint and larger. See the anchoring note on Calico's pair above for why this
   threshold moved from 1199 to 1699. */
@media (max-width: 1699px) {[data-theme="wingspan"]::before { width: 150px; height: 120px; opacity: 0.15; }[data-theme="wingspan"]::after  { width: 182px; height: 130px; opacity: 0.17; }}
/* Phones: removed entirely so content and the game cover own the space. */
@media (max-width: 767px) {[data-theme="wingspan"]::before,
    [data-theme="wingspan"]::after { display: none; }}
