/* Constellation block. Everything is scoped under .cn-wrap so the theme cannot reformat the
   canvas, and the graph cannot reformat the theme. */
.cn-wrap {
    position: relative;
    /* Break out of the theme's content column: a fitted map of 1,300 nodes needs the pixels,
       and inside a 760px article column it renders as dust. `full="false"` on the shortcode
       keeps it inline for narrow layouts. */
    width: 100vw;
    max-width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    min-height: 420px;
    border-radius: 12px;
    overflow: hidden;
    background: radial-gradient(circle at 50% 45%, #101522 0%, #070a11 100%);
    color: #eef;
    contain: layout paint;
}

.cn-wrap canvas {
    display: block;
    width: 100%;
    height: 100%;
    max-width: none;
    box-sizing: border-box;
    touch-action: none;
    cursor: grab;
}

.cn-wrap .cn-hint {
    position: absolute;
    left: 10px;
    bottom: 52px;      /* above the Fit button, which now owns the bottom-left corner */
    font-size: 12px;
    opacity: .62;
    pointer-events: none;
    max-width: 70%;
    line-height: 1.35;
}

.cn-wrap .cn-tip {
    position: absolute;
    display: none;
    background: rgba(0, 0, 0, .88);
    border: 1px solid rgba(255, 255, 255, .18);
    border-radius: 8px;
    padding: 4px 9px;
    font-size: 13px;
    pointer-events: none;
    max-width: 320px;
    z-index: 3;
}

.cn-wrap .cn-back {
    position: absolute;
    top: 10px;
    left: 10px;
    height: 34px;
    padding: 0 14px 0 10px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, .2);
    background: rgba(10, 12, 18, .82);
    color: #eef;
    font-size: 13px;
    text-decoration: none;
    z-index: 4;
}

.cn-wrap .cn-back:hover { background: rgba(30, 38, 56, .92); color: #fff; }
.cn-wrap .cn-back svg { width: 15px; height: 15px; fill: currentColor; opacity: .85; }

.cn-wrap.cn-has-back .cn-search { left: 124px; }

.cn-wrap .cn-topright {
    position: absolute;
    top: 10px;
    right: 10px;
    display: flex;
    align-items: center;
    gap: 8px;
    z-index: 4;
}

.cn-wrap .cn-help {
    height: 34px;
    padding: 0 14px;
    display: inline-flex;
    align-items: center;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, .2);
    background: rgba(10, 12, 18, .82);
    color: #eef;
    font-size: 13px;
    text-decoration: none;
    white-space: nowrap;
}
.cn-wrap .cn-help:hover { background: rgba(30, 38, 56, .92); color: #fff; }

.cn-wrap .cn-kofi {
    width: 20px; height: 20px; border-radius: 5px; display: block; flex: 0 0 auto;
}

.cn-wrap .cn-coffee {
    height: 34px;
    padding: 0 14px 0 10px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: 999px;
    border: 1px solid rgba(255, 200, 90, .38);
    background: rgba(255, 190, 60, .12);
    color: #ffe6b3;
    font-size: 13px;
    text-decoration: none;
}
.cn-wrap .cn-coffee:hover {
    background: rgba(255, 190, 60, .24);
    border-color: rgba(255, 200, 90, .7);
    color: #fff3d6;
}
@media (max-width: 640px) {
    /* The top-right corner cannot hold two pills on a phone: the tip jar stays there as an icon,
       and "How it works" moves to the bottom-right, which is empty (Fit is bottom-left). */
    .cn-wrap .cn-topright { position: static; }
    .cn-wrap .cn-coffee {
        position: absolute;
        top: 10px;
        right: 10px;
        padding: 0 10px;
        z-index: 4;              /* the tip jar is never the thing that ends up underneath */
    }
    .cn-wrap .cn-coffee .cn-coffee-label { display: none; }   /* mark only */
.cn-wrap .cn-help {
        position: absolute;
        right: 10px;
        bottom: 10px;
        height: 32px;
        padding: 0 12px;
        font-size: 12px;
    }
}

.cn-wrap .cn-search {
    position: absolute;
    top: 10px;
    left: 10px;
    width: 210px;
    max-width: 55%;
    padding: 6px 10px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, .18);
    background: rgba(10, 12, 18, .72);
    color: #eef;
    font-size: 14px;
    z-index: 3;
}

.cn-wrap .cn-fit {
    position: absolute;
    left: 10px;
    bottom: 10px;
    height: 34px;
    padding: 0 12px 0 9px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, .2);
    background: rgba(10, 12, 18, .82);
    color: #eef;
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    z-index: 3;
}
.cn-wrap .cn-fit:hover { background: rgba(30, 38, 56, .92); }
.cn-wrap .cn-fit svg { width: 15px; height: 15px; fill: currentColor; opacity: .85; }

/* expansion panel */
.cn-wrap .cn-panel {
    position: absolute;
    inset: 0;
    background: rgba(4, 6, 10, .55);
    display: flex;
    /* The description is a bottom sheet everywhere, not a dialog in the middle: the map is the
       point of the page, and a centred card hid it. It opens showing its top third, drags up to
       expand and down to close. */
    align-items: flex-end;
    justify-content: center;
    padding: 0;
    z-index: 10;
    /* The dim covers the map but must not CATCH anything: a phone in desktop mode (Opera,
       "desktop site") gets this layout, and there the backdrop swallowed every touch - panning
       and pinching did nothing at all while a card was open. The card itself stays clickable. */
    pointer-events: none;
}
.cn-wrap .cn-card { pointer-events: auto; }

.cn-wrap .cn-panel[hidden] { display: none; }

.cn-wrap .cn-card {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 18px;
    width: 100%;
    max-width: 1200px;
    height: 86vh; height: 86dvh; max-height: none;
    overflow: hidden;
    padding: 26px 22px 20px;
    border-radius: 16px 16px 0 0;
    border-bottom: 0;
    background: #0d1117;
    border: 1px solid rgba(255, 255, 255, .14);
    box-shadow: 0 -20px 60px rgba(0, 0, 0, .6);
    color: #eef;
    transform: translateY(52vh); transform: translateY(52dvh);   /* peek: the top third */
    transition: transform 300ms cubic-bezier(.22, .61, .36, 1);
    will-change: transform;
    pointer-events: auto;
}
.cn-wrap .cn-card.is-full { transform: translateY(0); }
.cn-wrap .cn-card.is-down { transform: translateY(100%); }
.cn-wrap .cn-card.is-dragging { transition: none; }
/* the grab strip is a real element: a drag on it can never be eaten by a native scroll */
.cn-wrap .cn-sheet-grab {
    display: block;
    position: absolute; top: 0; left: 0; right: 0; height: 58px;
    z-index: 2; touch-action: none; cursor: grab;
}
.cn-wrap .cn-sheet-grab::after {
    content: ''; position: absolute; top: 9px; left: 50%; transform: translateX(-50%);
    width: 46px; height: 4px; border-radius: 2px; background: rgba(255, 255, 255, .32);
}
.cn-wrap .cn-close { z-index: 3; top: 12px; right: 10px; }
.cn-wrap .cn-body { overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y;
    max-height: calc(86dvh - 48px); }

.cn-wrap .cn-poster {
    width: 200px;
    /* The artwork decides its own shape. A fixed height here (88x128 on a phone, 0.69) cropped a
       3:4 poster to a landscape box; posters are posters, so the box follows the image and
       `contain` guarantees nothing is ever cut away to fill it. */
    height: auto;
    border-radius: 10px;
    flex: 0 0 auto;
    object-fit: contain;
    margin: 0;
}

/* Scoped to .cn-main, not .cn-body: the title row lives in the wrapper (so a phone can put it
   beside the poster), and scoping these to the body stripped the title's colour, rendering it
   black-on-dark (reported 2026-10-25). The wrapper covers the title row AND the body. */
.cn-wrap .cn-main, .cn-wrap .cn-body { min-width: 0; color: #e8eefc; }
/* Every heading inside the card needs an explicit colour: the theme styles headings black, and a
   colour-less rule here loses on the dark card (measured: "Same formula" rendered #000). */
.cn-wrap .cn-main h3 { margin: 0 0 8px; font-size: 1.25em; color: #ffffff; }
.cn-wrap .cn-main h4 {
    margin: 14px 0 6px;
    font-size: .82em;
    text-transform: uppercase;
    letter-spacing: .06em;
    opacity: .78;
    color: #cfe2ff;
}
.cn-wrap .cn-overview { margin: 0 0 10px; font-size: .94em; line-height: 1.5; opacity: .92; }
.cn-wrap .cn-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.cn-wrap .cn-tag {
    font-size: .74em;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(127, 180, 255, .14);
    border: 1px solid rgba(127, 180, 255, .32);
    color: #cfe2ff;
}
/* Spoilers are opt-in: the digest gives away the whole story, so it starts collapsed and the
   summary is the only thing visible until the reader asks for it. */
.cn-wrap .cn-spoiler { margin: 12px 0 2px; }
.cn-wrap .cn-spoiler summary {
    cursor: pointer;
    display: inline-block;
    font-size: .8em;
    padding: 3px 10px;
    border-radius: 999px;
    border: 1px dashed rgba(255, 159, 159, .45);
    background: rgba(255, 120, 120, .08);
    color: #ffd7d7;
    list-style: none;
}
.cn-wrap .cn-spoiler summary::-webkit-details-marker { display: none; }
.cn-wrap .cn-spoiler summary::before { content: '⚠ '; }
.cn-wrap .cn-spoiler[open] summary { border-style: solid; }
.cn-wrap .cn-spoiler p {
    margin: 8px 0 0;
    font-size: .9em;
    line-height: 1.55;
    color: #f0dcdc;
    background: rgba(255, 120, 120, .06);
    border-left: 2px solid rgba(255, 120, 120, .4);
    padding: 8px 12px;
    border-radius: 6px;
}

.cn-wrap .cn-rels { margin: 0 0 4px; display: flex; flex-wrap: wrap; gap: 6px; }
.cn-wrap .cn-rel {
    /* Squares, not pills: these are RESULTS (a title each), and the pill shape is the house
       format for controls/filters. Squares make the two lists read as content. */
    font-size: .84em;
    padding: 5px 10px;
    border-radius: 5px;
    background: rgba(255, 255, 255, .06);
    border: 1px solid rgba(255, 255, 255, .12);
    line-height: 1.35;
    color: inherit;
    font-family: inherit;
    cursor: pointer;
}
/* Kind colours, matching the graph's edge palette (plot #c88cff, formula #7fb4ff). */
.cn-wrap .cn-rel.cn-k-plot {
    background: rgba(200, 140, 255, .13);
    border-color: rgba(200, 140, 255, .42);
    color: #ebdcff;
}
.cn-wrap .cn-rel.cn-k-formula {
    background: rgba(127, 180, 255, .13);
    border-color: rgba(127, 180, 255, .42);
    color: #d9e8ff;
}
.cn-wrap .cn-rel.cn-k-name {
    background: rgba(255, 255, 255, .07);
    border-color: rgba(255, 255, 255, .22);
    color: #e8eefc;
}
.cn-wrap .cn-main h4.cn-k-plot { color: #d9bcff; }
.cn-wrap .cn-main h4.cn-k-formula { color: #a9ccff; }
.cn-wrap .cn-main h4.cn-k-name { color: #cfe2ff; }
.cn-wrap .cn-rel.cn-k-plot:hover, .cn-wrap .cn-rel.cn-k-plot:focus-visible {
    background: rgba(200, 140, 255, .3); border-color: #c88cff;
}
.cn-wrap .cn-rel.cn-k-formula:hover, .cn-wrap .cn-rel.cn-k-formula:focus-visible {
    background: rgba(127, 180, 255, .3); border-color: #7fb4ff;
}

.cn-wrap .cn-rel:hover, .cn-wrap .cn-rel:focus-visible {
    background: rgba(127, 180, 255, .18);
    border-color: rgba(127, 180, 255, .55);
    outline: none;
}
.cn-wrap .cn-count {
    font-size: .8em;
    font-weight: 400;
    opacity: .55;
    margin-left: 2px;
}
/* Share is an inline control beside the title now, NOT a corner button. The old absolute rule
   survived the markup change and kept the button floating above the heading. */
.cn-wrap .cn-share {
    position: static;
    top: auto;
    right: auto;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 24px;
    padding: 0 10px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, .22);
    background: rgba(255, 255, 255, .06);
    color: #eef;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    vertical-align: middle;
}
.cn-wrap .cn-share:hover { background: rgba(127, 180, 255, .18); border-color: rgba(127, 180, 255, .5); }
.cn-wrap .cn-head { align-items: center; }

.cn-wrap .cn-close {
    position: absolute;
    top: 6px;
    right: 8px;
    background: none;
    border: 0;
    color: #eef;
    font-size: 24px;
    line-height: 1;
    cursor: pointer;
    opacity: .7;
}
.cn-wrap .cn-close:hover { opacity: 1; }


.cn-wrap.cn-inline {
    width: 100%;
    max-width: none;
    margin-left: 0;
    margin-right: 0;
}

@media (min-width: 1600px) {
    .cn-wrap { min-height: 78vh; }
}

@media (max-width: 640px) {
    /* Phone: only the title row sits beside the poster. Row 1 = artwork | title + studio; row 2 =
       the rest of the card, full width underneath. `display: contents` on the wrapper lifts the
       title and the body out as two grid items, so the body is NOT trapped in the narrow column
       beside the poster (that was the mistake reported 2026-10-25). */
    .cn-wrap .cn-card {
        display: grid;
        grid-template-columns: 140px minmax(0, 1fr);
        grid-template-rows: auto minmax(0, 1fr);
        column-gap: 12px;
        row-gap: 10px;
        align-items: start;
    }
    /* Three classes, not two: `.cn-wrap .cn-main` and `.cn-wrap .cn-body` are defined LATER in
       this file, and at equal specificity the later rule won - so the wrapper stayed a flex column
       and the body never left the narrow column beside the poster (measured 2026-10-25). */
    .cn-wrap .cn-card .cn-main { display: contents; }
    .cn-wrap .cn-card .cn-poster-side { grid-column: 1; grid-row: 1; width: auto; }
    .cn-wrap .cn-card .cn-head { grid-column: 2; grid-row: 1; }
    .cn-wrap .cn-card .cn-body {
        grid-column: 1 / -1;
        grid-row: 2;
        max-height: none;
        min-height: 0;
        /* The card clips (overflow:hidden) and row 2 is minmax(0,1fr), but the card also sets
           align-items:start - which stopped the body filling its row, so it grew to its full
           content height and everything below the fold was clipped away, unreachable. Stretching
           the body back into the row is what makes it scroll. */
        align-self: stretch;
    }
    .cn-wrap .cn-poster { width: 140px; }
    .cn-wrap .cn-hint { display: none; }
    /* The body beside a 140px poster is only ~208px wide, and reserving 96px of it for the Share
       button squeezed the title to three lines. On a phone the title takes the full column, the
       studio follows it, and Share drops below - title first, which is what the card is for.
       Three classes, not two: the base `.cn-card .cn-head h3` rule sits LATER in this file, and at
       equal specificity it won, so the phone kept the 96px reservation (measured 2026-10-25). */
    .cn-wrap .cn-card .cn-head h3 { max-width: 100%; flex: 1 1 100%; }
    .cn-wrap .cn-card .cn-head .cn-studio { order: 2; }
    .cn-wrap .cn-card .cn-head .cn-share { order: 3; }
}

/* ==========================================================================
   Beta chrome — first-run card, legend, browse drawer, search results,
   filters, the tip jar, loading + error states, and ONE mobile layout.
   The public page loads assets/constellation.css and never sees any of this.
   ========================================================================== */

/* the ambient sky: its own canvas, above the map, below every control */
.cn-wrap .cn-stars {
    position: absolute; inset: 0; width: 100%; height: 100%;
    z-index: 2; pointer-events: none;
}
.cn-wrap #relGraph { position: relative; z-index: 1; }

/* A class that sets `display` outranks the [hidden] attribute, which is how the drawer and the
   filters popover ended up visible on every load. */
.cn-wrap [hidden] { display: none !important; }

/* --- one row of controls, Fit included ---------------------------------- */
.cn-wrap .cn-toolbar {
    position: absolute; left: 10px; bottom: 10px; z-index: 4;
    display: flex; align-items: stretch; gap: 6px;
}
.cn-wrap .cn-tbtn,
.cn-wrap .cn-toolbar .cn-fit {
    height: 34px; padding: 0 12px; display: inline-flex; align-items: center; gap: 6px;
    border-radius: 999px; cursor: pointer; font-size: 13px; line-height: 1;
    border: 1px solid rgba(255, 255, 255, .16); background: rgba(10, 12, 18, .82); color: #dfe6ff;
    position: static;
}
.cn-wrap .cn-tbtn:hover,
.cn-wrap .cn-toolbar .cn-fit:hover { background: rgba(30, 38, 56, .92); color: #fff; }
.cn-wrap .cn-tbtn-icon { width: 34px; padding: 0; justify-content: center; font-weight: 700; }

/* The globe toggle: a pill that lights up when the map can be turned. */
.cn-wrap .cn-3d-btn {
    font-weight: 600;
    letter-spacing: .04em;
}
.cn-wrap .cn-3d-btn.is-on {
    background: rgba(120, 145, 255, .26);
    border-color: rgba(150, 175, 255, .7);
    color: #eaf0ff;
}
.cn-wrap .cn-tn { color: #8fa3d8; font-size: 12px; }
.cn-wrap .cn-only-mobile { display: none; }

/* --- first-run card + legend ------------------------------------------- */
.cn-wrap .cn-intro {
    position: absolute; inset: 0; z-index: 8; display: flex; align-items: center; justify-content: center;
    background: rgba(5, 8, 14, .55); backdrop-filter: blur(2px);
}
.cn-wrap .cn-intro-card {
    width: min(520px, calc(100% - 28px)); padding: 22px 24px; border-radius: 16px;
    background: rgba(12, 16, 26, .97); border: 1px solid rgba(255, 255, 255, .14);
    box-shadow: 0 24px 70px rgba(0, 0, 0, .6); color: #eef;
}
/* the theme styles every heading black, which is invisible on a dark card */
.cn-wrap .cn-intro-card h2 {
    margin: 0 0 8px; font-size: 17px; line-height: 1.25; color: #f4f7ff;
}
.cn-wrap .cn-intro-card p { margin: 0 0 14px; color: #b9c4e6; font-size: 13px; line-height: 1.5; }
.cn-wrap .cn-legend { display: flex; flex-direction: column; gap: 7px; margin-bottom: 14px; font-size: 13px; }
.cn-wrap .cn-legend span { display: flex; align-items: center; gap: 8px; }
.cn-wrap .cn-legend em { color: #8b98c0; font-style: normal; font-size: 12px; }
.cn-wrap .cn-swatch { width: 12px; height: 12px; border-radius: 3px; flex: 0 0 auto; }
.cn-wrap .cn-sw-plot { background: #c88cff; }
.cn-wrap .cn-sw-formula { background: #7fb4ff; }
.cn-wrap .cn-sw-rim { background: rgba(200, 215, 255, .45); border-radius: 50%; }
.cn-wrap .cn-intro-picks { margin-bottom: 16px; font-size: 13px; color: #b9c4e6; }
.cn-wrap .cn-intro-picks span { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.cn-wrap .cn-pick {
    padding: 6px 11px; border-radius: 999px; cursor: pointer; font-size: 12px;
    border: 1px solid rgba(200, 140, 255, .45); background: rgba(200, 140, 255, .14); color: #f0e2ff;
}
.cn-wrap .cn-pick:hover { background: rgba(200, 140, 255, .26); }
.cn-wrap .cn-intro-go {
    width: 100%; padding: 11px; border-radius: 10px; cursor: pointer; font-size: 14px; font-weight: 600;
    border: 1px solid rgba(255, 255, 255, .18); background: rgba(120, 145, 255, .26); color: #fff;
}
.cn-wrap .cn-intro-go:hover { background: rgba(120, 145, 255, .4); }
.cn-wrap .cn-intro-coffee {
    margin-top: 12px; display: flex; align-items: center; justify-content: center; gap: 9px;
    padding: 9px 14px; border-radius: 10px; text-decoration: none; font-size: 13px;
    border: 1px solid rgba(255, 190, 60, .35); background: rgba(255, 190, 60, .10); color: #ffe6b3;
}
.cn-wrap .cn-intro-coffee:hover { background: rgba(255, 190, 60, .2); color: #fff3d6; }
.cn-wrap .cn-intro-coffee img { border-radius: 5px; display: block; }

/* the permanent legend, bottom-right on desktop, full width above the bar on a phone */
.cn-wrap .cn-legend-bar {
    position: absolute; right: 10px; bottom: 10px; z-index: 4;
    display: flex; gap: 4px; padding: 4px; border-radius: 999px;
    background: rgba(10, 12, 18, .82); border: 1px solid rgba(255, 255, 255, .12);
}
.cn-wrap .cn-lg {
    display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px;
    border: 0; border-radius: 999px; background: none; cursor: pointer;
    color: #b9c4e6; font-size: 11.5px; white-space: nowrap;
}
.cn-wrap .cn-lg:hover { background: rgba(120, 145, 255, .16); color: #eef; }
.cn-wrap .cn-lg .cn-swatch { width: 9px; height: 9px; }

/* --- search: a button on a phone, a sheet in the middle ---------------- */
.cn-wrap .cn-searchbtn {
    position: absolute; top: 10px; left: 10px; z-index: 3;
    /* As wide as its contents: the pill holds a magnifier and the word "Search", and a fixed
       210px left a third of it empty (reported 2026-10-24). */
    width: auto; min-width: 0; max-width: none; height: 36px; padding: 0 14px;
    /* shown on every viewport: desktop uses the SAME magnifier + "Search" control as the phone */
    display: inline-flex; align-items: center; gap: 8px; justify-content: center;
    border-radius: 999px; cursor: pointer; font-size: 14px;
    border: 1px solid rgba(255, 255, 255, .18); background: rgba(10, 12, 18, .72); color: #cfd8ff;
}
.cn-wrap.cn-has-back .cn-searchbtn { left: 124px; }
.cn-wrap .cn-searchbtn:hover { background: rgba(30, 38, 56, .9); color: #fff; }
.cn-wrap .cn-searchbtn svg { width: 17px; height: 17px; fill: currentColor; opacity: .8; }

.cn-wrap .cn-searchm {
    position: absolute; inset: 0; z-index: 9;
    display: flex; align-items: flex-start; justify-content: center; padding: 12vh 12px 12px;
    background: rgba(5, 8, 14, .55); backdrop-filter: blur(3px);
    opacity: 0; transition: opacity 160ms ease;
}
.cn-wrap .cn-searchm.is-open { opacity: 1; }
.cn-wrap .cn-searchm-card {
    width: min(560px, 100%); max-height: min(70vh, 560px);
    display: flex; flex-direction: column; overflow: hidden; border-radius: 16px;
    background: rgba(12, 16, 26, .985); border: 1px solid rgba(255, 255, 255, .14);
    box-shadow: 0 26px 70px rgba(0, 0, 0, .65);
    transform: translateY(14px) scale(.96); opacity: 0;
    transition: transform 200ms cubic-bezier(.2, .9, .25, 1), opacity 160ms ease;
}
.cn-wrap .cn-searchm.is-open .cn-searchm-card { transform: none; opacity: 1; }
.cn-wrap .cn-searchm-row {
    display: flex; align-items: center; gap: 10px; padding: 12px 14px;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
}
.cn-wrap .cn-searchm-row svg { width: 18px; height: 18px; fill: #8fa3d8; flex: 0 0 auto; }
.cn-wrap .cn-searchm-row input {
    flex: 1 1 auto; min-width: 0; background: none; border: 0; outline: none;
    color: #eef; font-size: 16px;                       /* 16px stops iOS zooming the page */
}
.cn-wrap .cn-searchm-x {
    border: 0; background: none; color: #9aa6cc; font-size: 22px; line-height: 1;
    cursor: pointer; padding: 0 4px;
}
.cn-wrap .cn-searchm-results { overflow-y: auto; padding: 6px; }

@media (prefers-reduced-motion: reduce) {
    .cn-wrap .cn-searchm, .cn-wrap .cn-searchm-card { transition: none; transform: none; }
}

/* --- search results ----------------------------------------------------- */
.cn-wrap .cn-results {
    position: absolute; z-index: 6; top: 54px; left: 10px; width: min(420px, calc(100% - 20px));
    max-height: min(60vh, 460px); overflow-y: auto; padding: 6px; border-radius: 12px;
    background: rgba(10, 13, 21, .97); border: 1px solid rgba(255, 255, 255, .13);
    box-shadow: 0 18px 50px rgba(0, 0, 0, .55);
}
.cn-wrap .cn-r-head {
    padding: 8px 10px 4px; font: 600 10px/1 ui-monospace, monospace; letter-spacing: .12em;
    text-transform: uppercase; color: #7f8bb5;
}
.cn-wrap .cn-r {
    width: 100%; display: flex; align-items: center; gap: 10px; text-align: left;
    padding: 7px 10px; border: 0; border-radius: 8px; background: none; color: #eef;
    cursor: pointer; font-size: 13px;
}
.cn-wrap .cn-r:hover, .cn-wrap .cn-r:focus-visible { background: rgba(120, 145, 255, .18); }
.cn-wrap .cn-r-poster { width: 26px; height: auto; object-fit: contain; border-radius: 4px; flex: 0 0 auto; }
.cn-wrap .cn-r-name { flex: 1 1 auto; }
.cn-wrap .cn-r-name .cn-r-lonely { display: block; color: #8fa3d8; font-style: normal; font-size: 11px; }
.cn-wrap .cn-r-meta { color: #8fa3d8; font-size: 12px; }
.cn-wrap .cn-r-empty { padding: 14px 12px; color: #9aa6cc; font-size: 13px; }

/* --- filters ------------------------------------------------------------ */
.cn-wrap .cn-pop {
    position: absolute; z-index: 6; left: 10px; bottom: 52px; padding: 10px 12px;
    display: flex; flex-direction: column; gap: 9px; min-width: 250px;
    border-radius: 12px; background: rgba(10, 13, 21, .98);
    border: 1px solid rgba(255, 255, 255, .13); font-size: 13px; color: #e6ecff;
}
.cn-wrap .cn-pop label { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.cn-wrap .cn-pop em { color: #8b98c0; font-style: normal; font-size: 11px; margin-left: auto; }
.cn-wrap .cn-pop-select { justify-content: space-between; gap: 10px; }
.cn-wrap .cn-pop-select select {
    flex: 1 1 auto; max-width: 170px; padding: 4px 6px; border-radius: 7px; font-size: 12px;
    background: rgba(20, 26, 40, .95); color: #e6ecff; border: 1px solid rgba(255, 255, 255, .16);
}

/* --- browse drawer ------------------------------------------------------ */
.cn-wrap .cn-drawer {
    position: absolute; z-index: 6; top: 54px; right: 10px; bottom: 54px; width: min(330px, calc(100% - 20px));
    display: flex; flex-direction: column; border-radius: 14px; overflow: hidden;
    background: rgba(9, 12, 19, .97); border: 1px solid rgba(255, 255, 255, .13);
    box-shadow: 0 18px 50px rgba(0, 0, 0, .55);
}
.cn-wrap .cn-drawer-head {
    position: relative; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    padding: 12px 14px; border-bottom: 1px solid rgba(255, 255, 255, .08);
}
.cn-wrap .cn-drawer-head h3 { margin: 0; font-size: 13px; letter-spacing: .04em; color: #cfd8ff; }
.cn-wrap .cn-tabs { display: flex; gap: 4px; }
.cn-wrap .cn-tab {
    padding: 4px 9px; border-radius: 999px; cursor: pointer; font-size: 11.5px;
    border: 1px solid rgba(255, 255, 255, .14); background: none; color: #9aa6cc;
}
.cn-wrap .cn-tab.is-on { background: rgba(120, 145, 255, .22); border-color: rgba(140, 165, 255, .5); color: #eef; }
.cn-wrap .cn-tbtn.cn-shuffle { letter-spacing: .01em; }
.cn-wrap .cn-drawer-shuffle {
    padding: 5px 10px; border-radius: 999px; cursor: pointer; font-size: 11.5px;
    border: 1px solid rgba(200, 140, 255, .4); background: rgba(200, 140, 255, .12); color: #f0e2ff;
}
.cn-wrap .cn-drawer-shuffle:hover { background: rgba(200, 140, 255, .24); }
.cn-wrap .cn-drawer-close {
    margin-left: auto; border: 0; background: none; color: #9aa6cc; font-size: 22px; line-height: 1;
    cursor: pointer; padding: 0 4px;
}
.cn-wrap .cn-drawer-body { overflow-y: auto; padding: 6px; }
.cn-wrap .cn-drawer-note { margin: 6px 8px 10px; color: #8b98c0; font-size: 12px; }
.cn-wrap .cn-island {
    width: 100%; display: grid; grid-template-columns: 1fr auto; gap: 2px 8px;
    padding: 8px 10px; border: 0; border-radius: 8px; background: none; color: #eef;
    text-align: left; cursor: pointer; font-size: 13px;
}
.cn-wrap .cn-island:hover, .cn-wrap .cn-island:focus-visible { background: rgba(120, 145, 255, .16); }
.cn-wrap .cn-island-name { font-weight: 600; letter-spacing: .02em; }
.cn-wrap .cn-island-sub { grid-column: 1; color: #93a0c8; font-size: 11px; text-transform: uppercase; }
.cn-wrap .cn-island-n { grid-row: 1; grid-column: 2; color: #8fa3d8; font-size: 12px; }

.cn-wrap .cn-drawer-list {
    margin-left: auto; font-size: 11.5px; color: #9aa6cc; text-decoration: none;
    border-bottom: 1px dotted rgba(154, 166, 204, .5);
}
.cn-wrap .cn-drawer-list:hover { color: #dfe6ff; }

/* --- card extras -------------------------------------------------------- */
.cn-wrap .cn-why {
    display: block; margin-top: 3px; color: #8b98c0; font-size: 10.5px; letter-spacing: .02em;
}
.cn-wrap .cn-tag-btn { cursor: pointer; border-style: dashed; }
.cn-wrap .cn-tag-btn:hover, .cn-wrap .cn-tag-btn:focus-visible {
    background: rgba(120, 145, 255, .22); border-color: rgba(140, 165, 255, .6); color: #fff;
}

/* --- install prompt ---------------------------------------------------- */
.cn-wrap .cn-install {
    position: absolute; z-index: 6; left: 50%; transform: translateX(-50%); bottom: 96px;
    display: flex; align-items: center; gap: 10px; padding: 9px 10px 9px 14px;
    border-radius: 999px; max-width: calc(100% - 24px);
    background: rgba(14, 20, 34, .97); border: 1px solid rgba(140, 165, 255, .35);
    color: #dfe6ff; font-size: 12.5px; box-shadow: 0 14px 40px rgba(0, 0, 0, .55);
}
.cn-wrap .cn-install span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cn-wrap .cn-install button {
    padding: 6px 12px; border-radius: 999px; cursor: pointer; font-size: 12.5px;
    border: 1px solid rgba(140, 165, 255, .5); background: rgba(120, 145, 255, .26); color: #fff;
}
.cn-wrap .cn-install .cn-install-x {
    padding: 0 7px; border: 0; background: none; color: #9aa6cc; font-size: 18px; line-height: 1;
}

/* --- loading / error / touch affordance -------------------------------- */
.cn-wrap .cn-loading {
    position: absolute; inset: 0; z-index: 6; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 14px;
    background: rgba(7, 10, 17, .55); backdrop-filter: blur(2px); color: #cfd8ff; font-size: 14px;
}
.cn-wrap .cn-spinner {
    width: 34px; height: 34px; border-radius: 50%;
    border: 2px solid rgba(200, 215, 255, .22); border-top-color: #c88cff;
    animation: cn-spin 900ms linear infinite;
}
@keyframes cn-spin { to { transform: rotate(360deg); } }
.cn-wrap .cn-error {
    position: absolute; z-index: 7; left: 50%; top: 50%; transform: translate(-50%, -50%);
    display: flex; flex-direction: column; gap: 8px; align-items: flex-start;
    padding: 18px 20px; border-radius: 14px; max-width: 340px;
    background: rgba(28, 16, 20, .96); border: 1px solid rgba(255, 120, 120, .35);
    color: #ffe7e7; font-size: 13px;
}
.cn-wrap .cn-error strong { font-size: 15px; color: #fff; }
.cn-wrap .cn-error span { color: #e7b9b9; }
.cn-wrap .cn-error button {
    margin-top: 6px; padding: 7px 14px; border-radius: 999px; cursor: pointer;
    border: 1px solid rgba(255, 160, 160, .5); background: rgba(255, 120, 120, .18); color: #fff;
}
.cn-wrap .cn-open-sel {
    position: absolute; z-index: 5; left: 50%; transform: translateX(-50%); bottom: 54px;
    padding: 10px 18px; border-radius: 999px; cursor: pointer; font-size: 13px; font-weight: 600;
    border: 1px solid rgba(200, 140, 255, .5); background: rgba(28, 18, 40, .95); color: #f6ecff;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .5); max-width: calc(100% - 40px);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ------------------------------------------------------------------ mobile ---- */
/* Not just narrow: a phone in "desktop site" mode reports ~800px and would otherwise get the
   desktop layout, with a card that covers the whole screen and no touch-sized controls. */
@media (max-width: 640px), (pointer: coarse) {
    /* one row, four cells, one baseline: Fit | Browse | Filters | ? */
    /* The row hugs its pills and centres itself, instead of stretching four buttons across the
       screen: "Browse" does not need to be as wide as "Filters" just because it sits beside it. */
    .cn-wrap .cn-toolbar {
        left: 50%; right: auto; transform: translateX(-50%); bottom: 10px;
        gap: 5px; justify-content: center; max-width: calc(100% - 16px);
    }
    .cn-wrap .cn-toolbar .cn-tbtn { flex: 0 0 auto; justify-content: center; padding: 0 10px; }
    .cn-wrap .cn-toolbar .cn-fit { flex: 0 0 auto; padding: 0 10px; }
    .cn-wrap .cn-toolbar .cn-fit span { display: none; }   /* icon only: four labels will not fit */
    /* Islands and Links are the two a phone needs; Unique lives as a tab in the Islands drawer,
       and the toy ("Surprise me") gives up its cell so the row still fits. */
    .cn-wrap .cn-desk { display: none; }
    .cn-wrap .cn-only-mobile { display: inline-flex; }
    .cn-wrap .cn-toolbar .cn-tn { display: none; }         /* the counts are desktop detail */
    .cn-wrap .cn-links { right: 8px; left: 8px; width: auto; bottom: 58px; max-height: 58%; }
    .cn-wrap .cn-help { display: none; }                   /* the guide lives behind "?" */

    /* the legend sits on exactly the same insets as the bar, one line above it */
    /* same for the legend: the pill wraps its three toggles and sits centred above the row */
    .cn-wrap .cn-legend-bar {
        left: 50%; right: auto; transform: translateX(-50%); bottom: 54px;
        justify-content: center; gap: 2px; padding: 3px; max-width: calc(100% - 16px);
    }
    .cn-wrap .cn-lg { flex: 0 0 auto; justify-content: center; padding: 4px 8px; font-size: 10px; }

    /* the inline field becomes a Search button; the typing happens in the sheet */
    .cn-wrap .cn-search { display: none; }
    /* no left/right pair here: both set with width:auto stretches the pill across the screen */
    .cn-wrap .cn-searchbtn { display: inline-flex; }
    /* ...but it stops short of the tip jar (42px wide + 10px inset + 8px gap) instead of running
       underneath it, which is what it used to do: the jar was completely covered. */
    .cn-wrap.cn-has-coffee .cn-searchbtn { right: 60px; }
    /* The top row is back · search · tip jar. A centred pill was positioned blind: it only
       cleared the back button because the label happened to be short, and a longer one ("Back to
       dosmigueles.com") ran straight underneath it. So the search now starts where the back
       button actually ENDS: constellation.js measures it into --cn-back-w on load and resize.
       These selectors have to outrank ".cn-wrap.cn-has-back" (left:124px) and
       ".cn-wrap.cn-has-coffee" (right:60px), or the pill stretches across the row. */
    .cn-wrap .cn-searchbtn,
    .cn-wrap.cn-has-back .cn-searchbtn,
    .cn-wrap.cn-has-coffee .cn-searchbtn,
    .cn-wrap.cn-has-back.cn-has-coffee .cn-searchbtn {
        left: calc(10px + var(--cn-back-w, 0px) + 8px);
        right: auto; transform: none;
        width: auto; white-space: nowrap;
        /* and it can never reach the tip jar, however long the back label is */
        max-width: calc(100% - var(--cn-back-w, 0px) - 88px);
    }
    /* Below ~380px, with a long back label, there is room for the magnifier but not the word:
       a 36px pill with "Sear…" cut off inside it reads as a bug. Icon only, same target. */
    @media (max-width: 380px) {
        .cn-wrap .cn-searchbtn span { display: none; }
        .cn-wrap .cn-searchbtn {
            width: 40px; min-width: 40px; padding: 0; justify-content: center;
        }
    }
    .cn-wrap .cn-searchm { padding: 8vh 10px 10px; }
    .cn-wrap .cn-results { top: 50px; left: 8px; width: calc(100% - 16px); }
    .cn-wrap .cn-pop { left: 8px; right: 8px; bottom: 54px; min-width: 0; }
    .cn-wrap .cn-drawer { top: auto; left: 8px; right: 8px; bottom: 54px; width: auto; max-height: 62vh; }
    .cn-wrap .cn-drawer-head { padding: 10px 34px 10px 12px; }
    .cn-wrap .cn-drawer-head h3 { flex: 1 1 100%; }
    .cn-wrap .cn-drawer-close { position: absolute; top: 8px; right: 10px; margin: 0; }
    .cn-wrap .cn-tabs { flex: 1 1 auto; }
    .cn-wrap .cn-tab { flex: 1 1 0; text-align: center; padding: 6px 4px; }
    .cn-wrap .cn-drawer-shuffle { padding: 6px 10px; font-size: 14px; line-height: 1; }

    /* the sheet itself is the same everywhere; a phone only tightens the padding and lets a
       peeked card swallow the gesture, because there is nothing to scroll while it is peeked */
    .cn-wrap .cn-card { max-width: none; gap: 12px; padding: 26px 14px 18px; }
    .cn-wrap .cn-card.is-peek { touch-action: none; }
    /* no fixed height: the poster keeps the shape of its own artwork (it used to be forced to
       128px inside a 140px column, which squashed every poster into a letterbox) */
    .cn-wrap .cn-intro-card { padding: 18px; }
    .cn-wrap .cn-open-sel { bottom: 48px; }
}

/* The one host difference: inside Jellyfin the card leads to the item's own page, where it can
   actually be played. Styled as the primary action so it reads as the point of the card. */
.cn-card .cn-play {
    display: inline-block;
    margin: 2px 8px 6px 0;
    padding: 7px 14px;
    border-radius: 999px;
    background: #7fb4ff;
    color: #08101e;
    font-weight: 700;
    font-size: 13px;
    text-decoration: none;
    line-height: 1.2;
}
.cn-card .cn-play:hover { background: #a9caff; }
.cn-card .cn-play:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.cn-card .cn-share[data-state="done"] { color: #9fe0b0; }
.cn-card .cn-share-url {
    display: block;
    margin: 4px 0 8px;
    font-size: 11px;
    word-break: break-all;
    color: #9db6e0;
}

/* Share belongs beside the title it shares, not floating under the heading. */
/* The title must NOT grow: with flex:1 it pushed Share to the far right of the card, which is
   not "by the title" - it is the other corner of the same row. */
.cn-card .cn-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-start; }
/* The studio, directly under the title: the small line that says who made it. It belongs to the
   right-hand column (beside the poster), never under the artwork. flex-basis 100% forces it onto
   its own line, so it reads as the title's subtitle rather than a third item in the title row. */
.cn-card .cn-studio {
    flex: 1 1 100%;
    margin: 3px 0 6px;
    font-size: 12px;
    line-height: 1.3;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #8fa2c8;
}
.cn-card .cn-head h3 { flex: 0 1 auto; margin: 0; max-width: calc(100% - 96px); }
.cn-card .cn-head .cn-share {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 10px;
    border-radius: 999px;
    border: 1px solid rgba(255,255,255,.22);
    background: rgba(255,255,255,.07);
    color: #dfe8ff;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}
.cn-card .cn-head .cn-share svg { width: 13px; height: 13px; fill: currentColor; }
.cn-card .cn-head .cn-share:hover { background: rgba(255,255,255,.14); }
.cn-card .cn-head .cn-share[data-state="done"] { color: #9fe0b0; border-color: rgba(159,224,176,.5); }
.cn-card .cn-share-box { margin: 6px 0 8px; }
.cn-card .cn-share-box input {
    width: 100%;
    box-sizing: border-box;
    padding: 6px 8px;
    border-radius: 8px;
    border: 1px solid rgba(120,160,255,.5);
    background: rgba(10,16,28,.9);
    color: #cfe0ff;
    font-size: 11px;
}

/* Ratings and reviews close the card: after the similar shows, where a reader decides. */
.cn-card .cn-ratings { margin-top: 10px; padding-top: 8px; border-top: 1px solid rgba(255,255,255,.12); }
.cn-card .cn-rating-line { margin: 2px 0 8px; font-size: 12px; color: #cfd9f2; }
.cn-card .cn-rating-stars { color: #ffd479; letter-spacing: 1px; }
.cn-card .cn-reviews { list-style: none; margin: 0; padding: 0; }

/* An explicit expand/collapse control: a 4px drag handle is not an affordance on a desktop. */
.cn-wrap .cn-expand {
    /* the X that used to sit to its right is gone, so this is the corner control now */
    position: absolute; top: 9px; right: 10px; z-index: 5;
    width: 26px; height: 26px; padding: 0; border: 0; border-radius: 50%;
    background: rgba(255,255,255,.08); color: #dbe6ff; cursor: pointer;
    display: grid; place-items: center;
}
.cn-wrap .cn-expand svg { width: 18px; height: 18px; fill: currentColor; transition: transform .2s; }
.cn-wrap .cn-expand:hover { background: rgba(255,255,255,.16); }
.cn-wrap .cn-expand.is-open svg { transform: rotate(180deg); }
.cn-wrap .cn-sheet-grab { cursor: pointer; }

/* The item page's share button sits beside the title, as a small round icon. */
.btnShare.btnShareInline {
    margin: 0 0 0 10px;
    width: 34px;
    height: 34px;
    min-width: 34px;
    border-radius: 50%;
    vertical-align: middle;
    background: rgba(255,255,255,.10);
    border: 1px solid rgba(255,255,255,.18);
}
.btnShare.btnShareInline .detailButton-content { padding: 0; }
.btnShare.btnShareInline .detailButton-icon { font-size: 18px; }
.btnShare.btnShareInline:hover { background: rgba(255,255,255,.2); }


/* The poster and its stars are one column: the number belongs under the artwork, not floating in
   the body's left edge (reported twice, 2026-10-24). */
/* The right-hand column on a desktop: the title row above, the scrolling body below. On a phone
   this wrapper is display:contents (see the phone block), so the title and the body become two
   separate grid items and the body can span the full width under the poster. */
.cn-wrap .cn-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}
.cn-wrap .cn-main > .cn-body { min-height: 0; }

.cn-wrap .cn-poster-side {
    flex: 0 0 auto;
    width: 200px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: stretch;
}
.cn-wrap .cn-poster-side .cn-poster { width: 100%; }
.cn-wrap .cn-poster-stars {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 13px;
    line-height: 1.2;
    color: #cfd9f2;
}
.cn-wrap .cn-poster-stars .cn-rating-stars { color: #ffd479; letter-spacing: 1px; font-size: 14px; }
.cn-wrap .cn-poster-score { font-weight: 700; color: #e8eefc; }
@media (max-width: 640px) {
    .cn-wrap .cn-poster-side { width: 140px; }
}


/* The rating stars must NOT be .cn-stars: that class is the ambient starfield canvas, whose rule
   is position:absolute; inset:0; width/height:100% - so every review's star span became a
   full-card overlay painted in the top-left corner (found 2026-10-24, on screen). */
.cn-wrap .cn-rating-stars, .cn-card .cn-rating-stars {
    position: static;
    inset: auto;
    width: auto;
    height: auto;
    color: #ffd479;
    letter-spacing: 1px;
}


/* The relationship results are square cards, not control pills. */
.cn-wrap .cn-rels { display: flex; flex-wrap: wrap; gap: 7px; }
.cn-wrap .cn-rel { border-radius: 5px; text-align: left; }
.cn-wrap .cn-rel .cn-why { display: block; font-size: .78em; opacity: .62; margin-top: 2px; }


/* The sheet's drag strip spans the top 58px of the card and sits above everything at z-index 2,
   so it swallowed the title row: clicking Share hit the strip and toggled the sheet instead of
   copying (reported 2026-10-24). The fix then was to lift the WHOLE title row above the strip -
   but that put the title (touch-action: auto) over the strip's band, so the browser claimed a
   downward drag in that band as a scroll, fired pointercancel, and the sheet never moved: only
   2 of 30 pointermoves arrived and the card snapped back to full (measured 2026-10-25).
   Only the CONTROLS need to sit above the strip, so the strip stays the hit target in its band. */
.cn-wrap .cn-head { position: relative; }
.cn-wrap .cn-head .cn-share { position: relative; z-index: 5; }
.cn-wrap .cn-expand, .cn-wrap .cn-close { z-index: 5; }


/* Reviews as cards, mirroring Jellyfin's Ratings block (bg rgba(30,30,30,.95), 12px radius,
   white user, grey timestamp, light-grey text). */
.cn-card .cn-reviews {
    list-style: none; margin: 0; padding: 0;
    /* Cards, not full-width rows: on a desktop the body is ~980px, and one review per line
       wasted it. Auto-fill keeps them readable and puts two or three side by side. */
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 10px;
}
@media (max-width: 640px) {
    .cn-card .cn-reviews { grid-template-columns: 1fr; }
}
.cn-card .cn-review {
    background: rgba(30, 30, 30, .95);
    border: 1px solid rgba(255, 255, 255, .10);
    border-radius: 12px;
    padding: 10px 12px 11px;
}
.cn-card .cn-review-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 5px;
}
.cn-card .cn-review-user { color: #ffffff; font-weight: 600; font-size: 13px; }
.cn-card .cn-review-score { color: #ffd700; font-size: 12px; font-weight: 600; }
.cn-card .cn-review-score .cn-rating-stars { letter-spacing: 1px; font-size: 12px; }
.cn-card .cn-review-when { color: #888888; font-size: 11.5px; margin-left: auto; }
.cn-card .cn-review-text { margin: 0; color: #cccccc; font-size: 12.8px; line-height: 1.5; }

/* ==========================================================================
   No scrollbars, anywhere in the map. The card body, the drawer and the result
   lists all scroll, and a visible bar inside a card that is itself a sheet reads
   as a second window. Scrolling still works: only the indicator is gone.
   ========================================================================== */
.cn-wrap .cn-body,
.cn-wrap .cn-drawer-body,
.cn-wrap .cn-results,
.cn-wrap .cn-searchm-results,
.cn-wrap .cn-pop,
.cn-wrap .cn-rels {
    scrollbar-width: none;          /* Firefox */
    -ms-overflow-style: none;       /* legacy Edge/IE */
}
.cn-wrap .cn-body::-webkit-scrollbar,
.cn-wrap .cn-drawer-body::-webkit-scrollbar,
.cn-wrap .cn-results::-webkit-scrollbar,
.cn-wrap .cn-searchm-results::-webkit-scrollbar,
.cn-wrap .cn-pop::-webkit-scrollbar,
.cn-wrap .cn-rels::-webkit-scrollbar,
.cn-wrap textarea::-webkit-scrollbar {
    width: 0;
    height: 0;
    background: transparent;
}
/* the page itself never scrolls: the map is the viewport */
html, body { overflow: hidden; }

/* ==========================================================================
   Desktop search looks exactly like the phone's: a pill with the magnifier and
   the word "Search", same height, colours and corner radius. It used to be a
   bare input, so the two viewports looked like different products.
   ========================================================================== */
.cn-wrap .cn-search {
    height: 36px;
    padding: 0 14px 0 38px;
    font-size: 14px;
    color: #cfd8ff;
    background-color: rgba(10, 12, 18, .72);
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23cfd8ff' fill-opacity='0.8'%3E%3Cpath d='M15.5 14h-.79l-.28-.27a6.5 6.5 0 1 0-.7.7l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0A4.5 4.5 0 1 1 14 9.5 4.5 4.5 0 0 1 9.5 14z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: 13px center;
    background-size: 17px 17px;
    box-sizing: border-box;
}
.cn-wrap .cn-search::placeholder { color: #cfd8ff; opacity: 1; }
.cn-wrap .cn-search:hover { background-color: rgba(30, 38, 56, .9); }
.cn-wrap .cn-search:focus {
    background-color: rgba(30, 38, 56, .95);
    border-color: rgba(127, 180, 255, .55);
    outline: none;
}


/* There is no separate desktop search field any more: the magnifier + "Search" pill is the
   control on every viewport, and it opens the same search sheet. The inline input stays in the
   DOM (tests and deep links drive it) but is never shown. */
.cn-wrap .cn-search { display: none !important; }

/* ==========================================================================
   On a phone the bottom chrome sat INSIDE the open card (toolbar at 800-834
   of an 844px viewport, card spanning 118-844), so it covered the last rows of
   the card - the "bottom of the screen looks cut off" report. The map controls
   are not needed while a sheet is open, so they step aside; and they now keep
   clear of the home indicator on a real device.
   ========================================================================== */
@media (max-width: 640px) {
    .cn-wrap:has(.cn-panel:not([hidden])) .cn-toolbar,
    .cn-wrap:has(.cn-panel:not([hidden])) .cn-legend-bar,
    .cn-wrap:has(.cn-panel:not([hidden])) .cn-searchbtn {
        display: none;
    }
    .cn-wrap .cn-toolbar { bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
    .cn-wrap .cn-legend-bar { bottom: calc(54px + env(safe-area-inset-bottom, 0px)); }
    /* the card's own body must not end under a home indicator either */
    .cn-wrap .cn-body { padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px)); }
}

/* ---- Links panel: the families, and the two switches that make them visible ------------ */
.cn-links {
    position: absolute;
    right: 12px;
    bottom: 56px;
    width: min(320px, calc(100% - 24px));
    max-height: min(62%, 470px);
    display: flex;
    flex-direction: column;
    background: rgba(9, 13, 22, .96);
    border: 1px solid rgba(143, 162, 200, .28);
    border-radius: 12px;
    z-index: 26;
    color: #cfdcf5;
    font-size: 13px;
    backdrop-filter: blur(6px);
}
.cn-links[hidden] { display: none; }
.cn-links-head {
    display: flex; align-items: center; gap: 8px;
    padding: 9px 12px;
    border-bottom: 1px solid rgba(143, 162, 200, .18);
}
.cn-links-head h3 { margin: 0; font-size: 13px; font-weight: 600; flex: 1; color: #eef3ff; }
.cn-links-body { overflow-y: auto; padding: 8px 10px 10px; }
.cn-links-sw {
    display: flex; align-items: center; gap: 7px;
    padding: 3px 4px; margin-bottom: 2px;
    color: #b8c6e4; font-size: 12px; cursor: pointer;
}
.cn-links-sw input { accent-color: #7fb4ff; }
.cn-links .cn-fam { width: 100%; }
.cn-links .cn-fam[aria-pressed="true"] {
    background: rgba(127, 180, 255, .2);
    outline: 1px solid rgba(127, 180, 255, .6);
}
.cn-tbtn.is-on { background: rgba(127, 180, 255, .24); border-color: rgba(127, 180, 255, .6); color: #eef3ff; }
@media (max-width: 700px) { .cn-links { width: 210px; bottom: 58px; } }
