/* v2_app/assets/bands_tab.css — layout + component chrome for the Bands modal tab.

   Companion to tabs/bands.py. Layout (flex / grid / height / overflow) AND the
   repeated component chrome (rail rows, magnitude bars, segmented controls,
   stat tiles, the map card's title/legend bars) live here, so one rule styles
   every instance and the phone reflow can override class rules (the mobile
   media query can never beat an inline style). Anything that is per-instance
   or dynamic (a bar's width, a legend dot's size, the active row wash the
   callback swaps) stays inline in bands.py.

   Every value is a :root token from styles.css (--border, --forest-tint, --sp-3
   ...), which mirror theme.py, so the two layers never drift. The one literal
   here (the row hover grey) is copied from .rail-nav-row:hover in styles.css
   — the drawer's own hover — so the two rails always match.
   ============================================================================ */

/* ---- Root + body: the no-scroll two-column modal body (desktop) ---------- */
.bands-root {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    height: 100%;
    overflow: hidden;   /* belt-and-braces against accidental scroll */
}

.bands-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.bands-cols {
    display: flex;
    gap: var(--sp-3);
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
}

/* Whole-tab empty state (a region with no recoveries): centered in the body. */
.bands-empty-tab {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--sp-5) var(--sp-4);
}

/* ---- LEFT: species rail (a white card; chrome comes inline from _card_style) */
.bands-rail {
    flex: 0 0 236px;
    min-height: 0;
}

/* Card head: title + descriptor + the All | Migratory filter, over a hairline
   (the drawer's brand-cap seam) that frames the list beneath. */
.bands-rail-head {
    padding: var(--sp-3) var(--sp-3) var(--sp-3);
    border-bottom: 1px solid var(--border);
    flex: 0 0 auto;
}

/* The ranked species list scrolls inside the card; the wrapper carries a
   bottom fade (the mobile sheet's .sheet-list-fade idiom) signalling more. */
.bands-rail-scroll {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.bands-rail-scroll::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 28px;
    background: linear-gradient(180deg, rgba(255,255,255,0), var(--panel-bg));
    pointer-events: none;
}
.bands-rail-list {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding-bottom: var(--sp-2);
}

/* A rail row = the drawer nav row (drawer.rail_row_style): full width, the
   3px left accent + active wash set inline on the CONTAINER. Only the HEAD
   (.bands-row-tap) is clickable; the stats panel is a non-clickable sibling in
   the same container, so a tap on a stat can't collapse the accordion. Hover is
   the drawer's warm-grey step-off (.rail-nav-row:hover) on the container — a step
   OFF the active FOREST_TINT so the selected row and a hovered row never look the
   same. An active row's inline FOREST_TINT still wins over this rule. */
.bands-species-row {
    display: block;
    min-width: 0;        /* a grid/flex item, so a long name ellipses instead of widening */
}
/* The clickable head: carries the padding + the tap handler. */
.bands-row-tap {
    padding: var(--sp-2) var(--sp-3);
    cursor: pointer;
    user-select: none;
}
/* Pointer devices only, so a tapped row on a phone doesn't keep a stuck tint. */
@media (hover: hover) {
    .bands-species-row:hover { background-color: #f3f2ee; }
    /* Lift the resting chevron a step on hover (unselected rows only — a selected
       row's chevron stays forest via .is-active). */
    .bands-species-row:not(.is-active):hover .bands-row-chev { color: var(--text-secondary); }
}
/* Touch press feedback (no hover on touch): the tappable row head washes forest
   on press — mirrors .search-result-row:active / .sheet-cat-card:active. */
.bands-row-tap:active { background-color: var(--forest-tint); }

/* Line 1 of a row: name (inherits the row's weight/color) + a quiet count
   (+ a resting disclosure chevron trailing the count on every species row). */
.bands-row-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--sp-2);
}
.bands-row-name {
    min-width: 0;
    flex: 1 1 auto;      /* absorb the slack so count + chevron sit together right */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--fs-small);
}
/* Resting disclosure chevron on EVERY species row — the same quiet idiom as the
   Account rows' .acct-row-chev: a bi-chevron-down glyph in --border-strong at
   rest, the cue that the row is tappable. It sits inline trailing the count;
   line-height:1 + align-self:center keep it ON the line (the head aligns items
   to baseline) so the row height never grows. The open/closed state is carried
   by CSS off the row's classes — forest color on .is-active, a 180° rotation on
   .is-expanded — not a glyph swap. */
.bands-row-chev {
    flex: 0 0 auto;
    align-self: center;
    font-size: var(--fs-micro);
    line-height: 1;
    color: var(--border-strong);
    transition: transform 0.15s ease;
}
/* The "All species" roll-up never expands — an invisible ghost in the same slot
   keeps its count column aligned with the species rows below. */
.bands-row-chev.is-ghost { visibility: hidden; }
/* Selected row: the chevron follows the row's inline forest color, and rotates
   180° when its stats accordion is open. */
.bands-species-row.is-active .bands-row-chev { color: inherit; }
.bands-species-row.is-expanded .bands-row-chev { transform: rotate(180deg); }
/* Honor reduced-motion: the chevron still rotates to its open state, just with
   no tween. */
@media (prefers-reduced-motion: reduce) {
    .bands-row-chev { transition: none; }
}
.bands-row-count {
    flex: 0 0 auto;
    font-size: var(--fs-caption);
    font-weight: 400;
    color: var(--text-secondary);   /* quiet metric, §5 */
}

/* The one amber magnitude bar (rail rows + top-origin rows): a hairline-grey
   track with a pill-rounded fill. Fill width + color come inline. */
.bands-bar {
    width: 100%;
    height: 4px;
    margin-top: var(--sp-1);
    background-color: var(--border);
    border-radius: var(--radius-pill);
    overflow: hidden;
}
.bands-bar-fill {
    height: 100%;
    border-radius: var(--radius-pill);
}

/* ---- Segmented control (joined cells — controls.build_species_segment) --- */
.bands-seg {
    display: inline-flex;
    align-items: stretch;
    align-self: flex-start;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background-color: var(--panel-bg);
    overflow: hidden;
}
.bands-seg-cell {
    padding: 0 8px;      /* = controls._segment_style, the home-map control */
    min-height: 30px;
    border: none;
    outline: none;
    background-color: transparent;
    font-family: inherit;
    font-size: var(--fs-caption);
    font-weight: 500;
    color: var(--text-secondary);
    white-space: nowrap;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
}
/* 1px divider between cells; transparent under the active cell so the joined
   control never shifts width as the selection moves. */
.bands-seg-cell + .bands-seg-cell { border-left: 1px solid var(--border); }
.bands-seg-cell.is-on {
    background-color: var(--forest);
    color: var(--panel-bg);
    font-weight: 600;
}
.bands-seg-cell.is-on + .bands-seg-cell,
.bands-seg-cell + .bands-seg-cell.is-on { border-left-color: transparent; }

/* ---- Rail-head filter stack (All|Migratory + Any|Young|Adult + decade) ----
   The two segmented controls share one wrapping row (two independent
   dimensions); when the rail is too narrow for both they stack. The decade
   slider sits on its own line beneath, under its micro caption. */
.bands-filter-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    margin-top: var(--sp-2);
}
.bands-decade-wrap { margin-top: var(--sp-3); }
.bands-decade-wrap .bands-stats-caption { margin-bottom: var(--sp-1); }

/* dcc.Slider (rc-slider) restyled to the app's language: a hairline rail, a
   forest handle, forest active mark dots, and micro tick labels. Every value is
   a :root token so it tracks theme.py. included=false means only the chosen
   mark lights up (no filled track). */
.bands-decade-slider { padding: 2px 8px 0; }
.bands-decade-slider .rc-slider-rail {
    height: 4px;
    background-color: var(--border);
}
.bands-decade-slider .rc-slider-track { background-color: transparent; }
.bands-decade-slider .rc-slider-dot {
    width: 8px; height: 8px; bottom: -2px;
    border-color: var(--border-strong);
    background-color: var(--panel-bg);
}
.bands-decade-slider .rc-slider-dot-active { border-color: var(--forest); }
.bands-decade-slider .rc-slider-handle {
    width: 14px; height: 14px; margin-top: -5px;
    opacity: 1;
    border: 2px solid var(--forest);
    background-color: var(--forest);
}
.bands-decade-slider .rc-slider-handle:hover,
.bands-decade-slider .rc-slider-handle:active,
.bands-decade-slider .rc-slider-handle:focus-visible,
.bands-decade-slider .rc-slider-handle-dragging.rc-slider-handle-dragging {
    border-color: var(--forest-dark);
    box-shadow: 0 0 0 4px var(--forest-tint);
}
.bands-decade-slider .rc-slider-mark-text {
    font-family: inherit;
    font-size: var(--fs-micro);
    color: var(--text-tertiary);
}
.bands-decade-slider .rc-slider-mark-text-active {
    color: var(--text-secondary);
    font-weight: 600;
}

/* ---- RIGHT column ---------------------------------------------------------- */
.bands-right {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    min-height: 0;
}

/* Map card: a padded title bar over the full-bleed map over a legend footer,
   each separated by a hairline (the Overview map card's framing). */
.bands-map-card { flex: 0 0 246px; }

/* All-species view: no detail card, so the map grows to fill the column. */
.bands-map-card.is-full { flex: 1 1 auto; }

.bands-card-bar {
    padding: var(--sp-2) var(--sp-3);
    flex: 0 0 auto;
}
.bands-map-head { border-bottom: 1px solid var(--border); }
.bands-map-foot { border-top: 1px solid var(--border); }
.bands-map-area {
    flex: 1 1 auto;
    min-height: 0;
    position: relative;
    /* The Scattergeo map keeps true shape and letterboxes when the card aspect
       doesn't match the fit (_FILL_ASPECT ~= this area's real shape). This ocean
       backing matches the map's own ocean fill + geo bgcolor, so any thin residual
       gap reads as water, not an empty band. */
    background: var(--band-map-ocean);
    overflow: hidden;
    /* The map pans on drag (desktop) — but on touch, let a vertical finger swipe
       SCROLL THE PAGE (the tab stacks + scrolls on mobile) instead of being
       trapped panning the map; horizontal drags still pan. Also blocks the
       two-finger pinch-zoom the map doesn't want. */
    touch-action: pan-y;
}

/* Size legend: an uppercase group label (reuses .ov-legend-group-label) on the
   same line as the reflowing chips; the dot is sized inline to its bin. */
.bands-legend {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-1) var(--sp-3);
}
.bands-legend-label { margin-bottom: 0; }   /* inline with the chips, or alone as the no-points caption */
.bands-legend-dot {
    display: inline-block;
    flex: 0 0 auto;
    border-radius: 50%;
    /* Matches the map bubbles: a transparent fill (set inline via rgba) + a hard
       dark edge (inline 1px border). No opacity/halo here — the alpha is baked
       into the inline background color. */
    box-sizing: border-box;
}

/* Inline per-species stats drop-down ----------------------------------------
   A NON-clickable sibling of the clickable row head, inside the active wash (so a
   tap here can't collapse the accordion). It carries its OWN horizontal padding
   now (the container is unpadded — padding lives on .bands-row-tap), so the list
   aligns under the head and the hairline insets to match. */
.bands-stats-panel {
    padding: var(--sp-2) var(--sp-3) var(--sp-3);
    border-top: 1px solid var(--border);
}
.bands-stats-thin {
    font-size: var(--fs-small);
    color: var(--text-secondary);
}
.bands-stat-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--sp-2);
    padding: 3px 0;   /* a touch more vertical breathing room than the old 2px */
}
.bands-stat-label {
    font-size: var(--fs-caption);
    font-weight: 400;
    color: var(--text-secondary);   /* quiet descriptor (§5) */
    flex: 0 0 auto;
}
.bands-stat-value {
    font-size: var(--fs-small);
    /* Regular weight, not semibold: the quiet-metric rule (§5) — these values are
       supporting metrics, so they read calm (primary color carries them, not a
       loud weight). */
    font-weight: 400;
    color: var(--text);
    text-align: right;
    min-width: 0;
    /* Plain numeric values (e.g. "1,307 / 3,834 mi") WRAP rather than ellipsis-
       truncate: on the narrow 236px desktop rail a long label would otherwise cut
       the number ("1,307 / 3,83…"). Mobile has the width to keep it on one line, so
       it's unchanged there. Top-origin values opt out below (.has-share) — they
       truncate only the NAME via .bands-stat-name, never the share. */
    overflow-wrap: anywhere;
    white-space: normal;
}
/* A value that is "<name> · <share>" (Top origin): only the NAME truncates, the
   "· NN%" share stays pinned, so a long origin never swallows its own percent. */
.bands-stat-value.has-share {
    display: flex;
    align-items: baseline;
    justify-content: flex-end;
    overflow: visible;
}
.bands-stat-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.bands-stat-share { flex: 0 0 auto; white-space: nowrap; }
/* Bars block now LEADS the panel, so it sits flush at the top — the panel's own
   top padding is the only gap above it; no top margin that would read as an
   orphaned divider. The stat list below carries the section-break hairline. */
.bands-stats-origins { margin-top: 0; }
/* The stat list is the SECOND section, under the Top-origins bars, so it carries
   the section-break hairline. Scoped to follow the bars block (adjacent sibling)
   so a bars-less panel — none exist today, but belt-and-braces — would collapse to
   a plain list with no orphaned hairline under the panel's own top border. */
.bands-stats-origins + .bands-stat-list {
    margin-top: var(--sp-3);
    padding-top: var(--sp-3);
    border-top: 1px solid var(--border);
}
.bands-stats-caption {
    font-size: var(--fs-micro);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-tertiary);
    margin-bottom: var(--sp-1);
}

/* Top-origin mini-bars (shared .bands-origin-row atom). */
.bands-origin-row { margin-bottom: var(--sp-1); }
.bands-origin-row:last-child { margin-bottom: 0; }
/* Regular weight: the origin name sits INSIDE the active (semibold) species row,
   so without this it would inherit that semibold and read loud. Quiet it to match
   the stat values (§5). */
.bands-origin-row .bands-row-name { color: var(--text); font-weight: 400; }

/* ---- Dynamic premium gate (free user, non-default selection) ---------------
   Band Insights self-gates: at a non-default selection a free user's whole band
   body blurs (reusing .pw-blur from paywall_gates.css) and a subscribe CTA
   floats centered over it. The wrap fills the body slot and positions the
   overlay; the CTA sits as a SIBLING of .pw-blur (never a child — .pw-blur sets
   pointer-events:none, which would kill the button). Every value is a :root
   token (mirrors theme.py). */
.bands-gate-wrap {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
/* The blurred body fills the wrap, so the blur covers the whole tab (map + rail
   + controls), not just its natural content height. */
.bands-gate-wrap > .pw-blur {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
/* The centered CTA card, above the blur. It holds the SAME E-1 inline CTA as the
   Overview tab's gated species breakdown (gating.inline_cta), so the alignment
   MATCHES Overview: left-aligned headline + green-check bullets, full-width
   button, and the T&C line centering itself via its own inline style — hence NO
   text-align:center here (that would re-center the headline/bullets and break
   parity). Panel background / border / radius / shadow from tokens so it reads as
   a solid card over the muted body. Width is capped and fits comfortably at 390px
   (the side gutter is kept via calc). */
.bands-gate-cta {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 3;
    width: calc(100% - var(--sp-5));
    max-width: 320px;
    box-sizing: border-box;
    background-color: var(--panel-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    padding: var(--sp-4);
}
/* The inline CTA is DESIGNED to sit in-flow beneath a blurred block, so it carries
   a top hairline + top margin/padding (.pw-inline-cta in paywall_gates.css). Here
   it is the SOLE content of the floating card, so null those out — no double chrome,
   no awkward top gap inside the card. */
.bands-gate-cta .pw-inline-cta {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}
/* Desktop: let the Band Insights root HOLD the fixed modal body height so its
   rail scrolls internally (the tab's "no-scroll 520px" design) instead of the
   whole modal body stretching to the tall content. Without this, #modal-tab-content
   is flex:1 0 auto (styles.css) so .bands-root{height:100%} resolves to full
   content height (~1583px) and the gate's vertically-centered CTA lands off the
   bottom of the viewport. Scoped by :has() to ONLY the bands root (no other tab
   is affected) and to desktop (mobile stacks + scrolls the whole modal). */
@media (min-width: 769px) {
    #modal-tab-content:has(> .bands-root) { flex: 1 1 auto; min-height: 0; }
}

/* ---- MOBILE-ONLY Band elements — HIDDEN on desktop ------------------------
   The Option-1 mobile redesign (species shortlist + "See all" sheet + a promoted
   stats card) adds these elements; the DESKTOP rail/detail is unchanged, so they
   are display:none here and only revealed inside the phones media query below. */
.bands-m-filters-label,
.bands-m-stats,
.bands-seeall,
.bands-sheet-scrim,
.bands-sheet-head { display: none; }

/* ---- Phones: stack the columns; shrink the selector to a shortlist --------- */
@media (max-width: 768px) {
    .bands-root { height: auto; overflow: visible; }
    .bands-cols { flex-direction: column; overflow: visible; }
    .bands-rail { flex: none; }

    /* The rail card now holds only the Filters (head) + the species SHORTLIST.
       Drop the desktop "Statistics" title/descriptor and label the card
       "Filters" — the toggles filter the whole tab; the region total shows in the
       All-species row, and the per-species stats get their own card below. */
    .bands-rail-title { display: none; }
    .bands-m-filters-label {
        display: block;
        font-family: var(--font-display);
        font-size: var(--fs-h2);
        font-weight: var(--fw-semibold);
        color: var(--text);
        margin-bottom: var(--sp-2);
    }

    /* Species list: single column (no 2-col grid — names never truncate). The
       inline per-species stats are hidden on mobile (the selected stats live in
       .bands-m-stats below), and the SHORTLIST caps at the All-species roll-up +
       the top 5 species (child 1 = roll-up, child 2 = divider, children 3-7 =
       species 0-4), with a "See all" row beneath. The sheet (.is-open) shows all. */
    .bands-rail-scroll { max-height: none; }
    .bands-rail-list { display: block; max-height: none; }
    .bands-rail-list .bands-stats-panel { display: none; }
    /* Inline expand is a desktop affordance; on mobile the row just selects (stats
       show in the card below), so drop the per-row chevron — a tap on the already-
       selected row then has no visible disclosure to spin. */
    .bands-rail-list .bands-row-chev { display: none; }
    .bands-rail:not(.is-open) .bands-rail-list > :nth-child(n+8) { display: none; }
    /* No inner scroll in the shortlist, so the "more" fade would mislead — the
       See-all row is the affordance. The open sheet re-enables the fade. */
    .bands-rail:not(.is-open) .bands-rail-scroll::after { display: none; }

    /* The "See all N species" row — a quiet full-width tappable row (the
       Account-row idiom); JS (bands_sheet.js) opens the sheet. */
    .bands-seeall {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: var(--sp-3);
        border-top: 1px solid var(--border);
        font-size: var(--fs-small);
        font-weight: var(--fw-medium);
        color: var(--forest);
        cursor: pointer;
        user-select: none;
    }
    .bands-seeall:active { background-color: var(--forest-tint); }
    .bands-seeall-chev { font-size: 12px; color: var(--text-tertiary); }

    /* The selected species' stats, promoted to their own card (the mockup's
       Statistics card) between the species shortlist and the map. Chrome lives
       here (not inline) so the base rule above can keep it off desktop. */
    .bands-m-stats {
        display: block;
        background: var(--panel-bg);
        border: 1px solid var(--border);
        border-radius: var(--radius-md);
        box-shadow: var(--shadow-sm);
        padding: var(--sp-3);
    }
    /* The promoted stats panel carries its own horizontal padding; zero it inside
       the card so the stats align to the card's padding, not double-inset. */
    .bands-m-stats .bands-stats-panel { padding-left: 0; padding-right: 0; }

    /* ---- The "See all" bottom sheet (in-modal overlay) ----------------------
       Opened by adding .is-open to .bands-rail (bands_sheet.js). The shared list
       is promoted to a fixed bottom panel and the scrim + head frame it. The sheet
       lives INSIDE the modal's stacking context, so these z-indexes only need to
       beat the modal header (3) and tab strip (2); the comfortable 2000+ leaves
       headroom. A species pick clears .is-open in bands_sheet.js, closing it. */
    .bands-rail.is-open .bands-sheet-scrim {
        display: block;
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: 2000;
        touch-action: none;
    }
    .bands-rail.is-open .bands-sheet-head {
        display: flex;
        align-items: center;
        justify-content: center;
        position: fixed;
        left: 0; right: 0;
        bottom: calc(85vh - 52px);
        height: 52px;
        background: var(--panel-bg);
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
        z-index: 2002;
    }
    .bands-sheet-grip {
        position: absolute;
        top: 8px; left: 50%;
        transform: translateX(-50%);
        width: 36px; height: 4px; border-radius: 2px;
        background: var(--border);
    }
    .bands-sheet-title {
        font-family: var(--font-display);
        font-size: var(--fs-h2);
        font-weight: var(--fw-semibold);
        color: var(--text);
    }
    .bands-sheet-close {
        position: absolute;
        right: 4px; top: 50%;
        transform: translateY(-50%);
        width: 44px; height: 44px;              /* full touch target */
        display: flex; align-items: center; justify-content: center;
        font-size: 18px; color: var(--text-secondary);
        cursor: pointer;
    }
    .bands-rail.is-open .bands-rail-scroll {
        display: flex;
        position: fixed;
        left: 0; right: 0; bottom: 0;
        height: calc(85vh - 52px);
        max-height: none;
        background: var(--panel-bg);
        overflow: hidden;
        z-index: 2001;
    }
    /* overscroll-behavior stops the list's scroll from chaining to the modal body
       behind the scrim once it hits either end. */
    .bands-rail.is-open .bands-rail-list {
        max-height: none;
        overflow-y: auto;
        overscroll-behavior: contain;
    }
    .bands-rail.is-open .bands-rail-scroll::after { display: block; }
    .bands-rail.is-open .bands-seeall { display: none; }

    /* The gate CTA (the taller Overview inline_cta) is centered in the stacked
       body; cap its offset so the subscribe button stays on-screen on short
       phones (<=740px tall) instead of centering below the fold. */
    .bands-gate-cta { top: min(50%, 420px); }

    /* The map card grows and pins the MAP-AREA to the fit aspect (~1.2) so the
       Scattergeo fills edge to edge at every width. */
    .bands-map-card,
    .bands-map-card.is-full { flex: none; height: auto; }
    .bands-map-area { flex: none; aspect-ratio: 1.2; height: auto; }

    /* Afield tap targets: the segmented cells step up toward TOUCH_MIN. */
    .bands-seg-cell { min-height: 36px; padding: 0 12px; }

    /* The decade slider gains a bigger handle + more rail padding for a thumb.
       rc-slider's box IS the tap band: 42px tall with 14px top/bottom padding
       (toward TOUCH_MIN) without moving the value math (horizontal only). */
    .bands-decade-slider { padding: 2px 10px 0; }
    .bands-decade-slider .rc-slider { height: 42px; padding: 14px 0; }
    .bands-decade-slider .rc-slider-mark { top: 27px; }
    .bands-decade-slider .rc-slider-handle {
        width: 18px; height: 18px; margin-top: -7px;
    }
}
