:root {
    --bg:          #16100d;
    --bg-raised:   #3e2d24;
    --bg-input:    #16100d;
    --text:        #ede0cf;
    --subtle:      #9e8070;
    --leaf:        #5a8a4a;
    --leaf-light:  #7ab560;
    --sky:         #7abfcf;
    --sky-hover:   #5aafc0;
    --plum:        #6d5868;
    --gold:        #c8892a;
    --error:       #d97070;
    --success:     #7ab870;
    --radius:      0;
    --max-w:       480px;
    --font-display: 'Playfair Display', Georgia, serif;
    --font-body:    'DM Sans', system-ui, sans-serif;
}

/* ── Themes ── */
[data-theme="ocean"] {
    --bg:         #0b1520;
    --bg-raised:  #162535;
    --bg-input:   #0b1520;
    --text:       #c8d8e8;
    --subtle:     #5a7a9a;
    --leaf:       #2a8a7a;
    --leaf-light: #4aaa9a;
    --sky:        #5aafc0;
    --sky-hover:  #4a9fb0;
    --gold:       #c8a840;
    --error:      #d97070;
}
[data-theme="void"] {
    --bg:         #0e0a18;
    --bg-raised:  #1e1530;
    --bg-input:   #0e0a18;
    --text:       #d8cff4;
    --subtle:     #7060a0;
    --leaf:       #7050d0;
    --leaf-light: #9070f0;
    --sky:        #70c0d0;
    --sky-hover:  #50a0b0;
    --gold:       #d080c0;
    --error:      #e06878;
}
[data-theme="ash"] {
    --bg:         #111111;
    --bg-raised:  #252525;
    --bg-input:   #111111;
    --text:       #e0ddd8;
    --subtle:     #808080;
    --leaf:       #5a8a4a;
    --leaf-light: #7aaa6a;
    --sky:        #88aacc;
    --sky-hover:  #6a8aac;
    --gold:       #b89050;
    --error:      #d97070;
}
[data-theme="ember"] {
    --bg:         #120e08;
    --bg-raised:  #2a1e10;
    --bg-input:   #120e08;
    --text:       #f0e0c8;
    --subtle:     #806040;
    --leaf:       #d06020;
    --leaf-light: #f08040;
    --sky:        #c0a030;
    --sky-hover:  #a08020;
    --gold:       #e8c050;
    --error:      #e06050;
}
[data-theme="moss"] {
    --bg:         #080e08;
    --bg-raised:  #102010;
    --bg-input:   #080e08;
    --text:       #d0ecd0;
    --subtle:     #507050;
    --leaf:       #40a840;
    --leaf-light: #60c860;
    --sky:        #50b8a0;
    --sky-hover:  #40a890;
    --gold:       #a8c840;
    --error:      #d97070;
}
[data-theme="dusk"] {
    --bg:         #0e0818;
    --bg-raised:  #1e1428;
    --bg-input:   #0e0818;
    --text:       #e0d0f0;
    --subtle:     #705890;
    --leaf:       #c040a0;
    --leaf-light: #e060c0;
    --sky:        #8090e0;
    --sky-hover:  #6070c0;
    --gold:       #e0a040;
    --error:      #e06878;
}
[data-theme="slate"] {
    --bg:         #0a0e14;
    --bg-raised:  #141e28;
    --bg-input:   #0a0e14;
    --text:       #c8d8e8;
    --subtle:     #4a6080;
    --leaf:       #4080c0;
    --leaf-light: #6090d0;
    --sky:        #40c0d0;
    --sky-hover:  #30a0b0;
    --gold:       #c0a840;
    --error:      #d97070;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
[hidden] { display: none !important; }

body {
    font-family: var(--font-body);
    background: var(--bg);
    color: var(--text);
    line-height: 1.6;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

main {
    flex: 1;
}

/* ── Header ── */
header {
    /* 3-column grid: equal 1fr side columns flank an auto-width middle, so the
       tools cluster stays pinned to true center no matter the logo/nav widths. */
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    column-gap: 1.5rem;
    align-items: center;
    padding: 0.9rem 2rem;
    background: var(--bg-raised);
    box-shadow: 0 4px 6px color-mix(in srgb, var(--leaf) 45%, transparent);
    position: relative;
}
.logo { justify-self: start; }
nav { justify-self: end; }

.logo {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.5rem;
    text-decoration: none;
    color: var(--text);
    letter-spacing: 0.02em;
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.logo-icon {
    color: var(--leaf);
    height: 2.1rem;
    width: auto;
    flex-shrink: 0;
}

nav { display: flex; gap: 1.25rem; align-items: center; }
nav a {
    text-decoration: none;
    color: var(--subtle);
    font-size: 0.9rem;
    font-weight: 500;
    white-space: nowrap;
    transition: color 0.15s;
}
nav a:hover { color: var(--sky); }

/* Hamburger button — hidden on desktop, shown at the mobile breakpoint below. */
.nav-toggle { display: none; }

/* Desktop: give each header nav link a hit area that fills the full header
   height (top edge to bottom edge), not just its tight text box. The link
   stretches to the row, then padding + matching negative margin extend it into
   the header's own 0.9rem vertical padding without growing the bar. */
@media (min-width: 901px) {
    header nav { align-self: stretch; }
    header nav a {
        align-self: stretch;      /* only the links fill the height, not the theme picker */
        display: flex;
        align-items: center;
        box-sizing: content-box;
        padding-block: 0.9rem;
        margin-block: -0.9rem;
    }
}

/* ── Mobile header (≤900px): logo + randomizer stay in the bar; nav collapses
   into a hamburger dropdown, with the theme picker as an inline accordion. ── */
@media (max-width: 900px) {
    header { padding: 0.6rem 1rem; }

    /* Drop the utility hash chip on mobile (kept the randomizer, per choice A). */
    .header-tools .node-id-chip { display: none; }

    .nav-toggle {
        display: flex;
        flex-direction: column;
        justify-content: center;
        justify-self: end;
        gap: 4px;
        width: 2.4rem;
        height: 2.4rem;
        padding: 0.5rem;
        background: none;
        border: 1px solid var(--bg-raised);
        cursor: pointer;
        flex-shrink: 0;
    }
    .nav-toggle-bar {
        display: block;
        width: 100%;
        height: 2px;
        background: var(--text);
        transition: transform 0.2s, opacity 0.2s;
    }
    header.nav-open .nav-toggle-bar:nth-child(1) { transform: translateY(6px) rotate(45deg); }
    header.nav-open .nav-toggle-bar:nth-child(2) { opacity: 0; }
    header.nav-open .nav-toggle-bar:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

    /* Nav becomes a full-width dropdown panel under the header. Scoped to the
       header nav so it never touches the footer's <nav class="footer-nav">. */
    header nav {
        display: none;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        padding: 0.25rem 1rem 1rem;
        background: var(--bg-raised);
        box-shadow: 0 6px 8px color-mix(in srgb, var(--leaf) 30%, transparent);
        z-index: 300;
    }
    header.nav-open nav { display: flex; }
    header nav a {
        padding: 0.85rem 0.25rem;
        font-size: 1rem;
        border-top: 1px solid color-mix(in srgb, var(--subtle) 25%, transparent);
    }

    /* Theme picker: inline accordion instead of a floating overlay. */
    .theme-picker { width: 100%; }
    .theme-trigger { width: 100%; justify-content: space-between; padding: 0.85rem 0.25rem; }
    .theme-dropdown {
        position: static;
        min-width: 0;
        padding: 0.25rem 0 0.5rem;
        background: none;
        border: none;
    }
}

/* ── Footer ── */
footer {
    margin-top: 3rem;
    padding: 2rem;
    text-align: center;
    border-top: 1px solid var(--bg-raised);
}
footer p { margin: 0; }
footer a {
    color: var(--sky);
    text-decoration: none;
    font-size: 0.9rem;
}
footer a:hover {
    text-decoration: underline;
}

/* ── Content detail ── */
.content-detail { max-width: 700px; }
.content-cover {
    float: left;
    margin: 0.25rem 1.75rem 1rem 0;
    max-width: 200px;
    width: 100%;
    box-shadow: 4px 4px 0 rgba(0,0,0,0.5);
    display: block;
}
.content-detail h1 {
    font-family: var(--font-display);
    font-size: clamp(1.5rem, 4vw, 2.5rem);
    color: var(--text);
    margin-bottom: 0.35rem;
}
.content-meta {
    font-size: 0.85rem;
    color: var(--subtle);
    margin-bottom: 0.75rem;
    letter-spacing: 0.03em;
}
.content-description {
    color: var(--text);
    line-height: 1.7;
    font-size: 0.95rem;
    white-space: pre-wrap;
}

/* ── Owner remark (list backstory / per-item note) ──
   A bottom-of-page author note, deliberately bordered in a strong accent so it reads as
   commentary, not part of the content. Collapsed to 3 lines; JS adds .remark-body--expanded
   and reveals the toggle only when the text actually overflows. Absent → not rendered, so
   there's no empty box or leftover margin. */
.remark-block {
    margin-top: 2rem;
    padding: 1rem 1.25rem;
    border: 2px solid var(--gold);
    border-radius: var(--radius);
    background: var(--bg-raised);
}
.remark-label {
    margin: 0 0 0.5rem;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--gold);
}
.remark-body {
    color: var(--text);
    line-height: 1.6;
    font-size: 0.95rem;
    /* Clamp to 3 lines until expanded; nl2br <br>s count as line breaks within the box. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.remark-body--expanded {
    display: block;
    -webkit-line-clamp: unset;
    overflow: visible;
}
.remark-expand {
    margin-top: 0.5rem;
    padding: 0;
    background: none;
    border: none;
    color: var(--sky);
    font: inherit;
    font-size: 0.85rem;
    cursor: pointer;
}
.remark-expand:hover { text-decoration: underline; }
.remark-edit-btn { margin-top: 0.75rem; }
.remark-add-row  { margin-top: 1.5rem; }
.remark-form { margin-top: 1.5rem; flex-direction: column; align-items: stretch; gap: 0.6rem; }
.remark-form textarea {
    width: 100%;
    resize: vertical;
    font: inherit;
    line-height: 1.6;
    padding: 0.6rem 0.75rem;
    color: var(--text);
    background: var(--bg-raised);
    border: 1px solid var(--subtle);
    border-radius: var(--radius);
}
.remark-form-actions { display: flex; gap: 0.5rem; }

/* ── Theme picker ── */
.theme-picker { position: relative; display: flex; flex-direction: column; }
.theme-trigger { display: flex; align-items: center; gap: 0.3rem; cursor: pointer; }
.theme-toggle {
    background: none;
    border: 1px solid var(--bg-raised);
    color: var(--subtle);
    cursor: pointer;
    padding: 0.3rem;
    line-height: 1;
    display: flex;
    align-items: center;
    transition: color 0.15s, border-color 0.15s;
}
.theme-toggle:hover { color: var(--text); border-color: var(--subtle); }
.theme-dropdown {
    position: absolute;
    right: 0;
    top: calc(100% + 0.5rem);
    background: var(--bg-raised);
    border: 1px solid var(--leaf);
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: 0.4rem;
    z-index: 200;
    min-width: 140px;
}
.theme-swatch-btn {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    background: none;
    border: 1px solid transparent;
    color: var(--text);
    cursor: pointer;
    font-family: var(--font-body);
    font-size: 0.85rem;
    padding: 0.35rem 0.5rem;
    text-align: left;
    width: 100%;
    transition: border-color 0.15s;
}
.theme-swatch-btn:hover { border-color: var(--subtle); }
.theme-swatch-btn.active { border-color: var(--leaf); }
.swatch-preview {
    display: flex;
    width: 48px;
    height: 18px;
    flex-shrink: 0;
    overflow: hidden;
    border: 1px solid rgba(255,255,255,0.1);
}
.swatch-inline { cursor: pointer; }
.swatch-seg { flex: 1; }
.swatch-label { color: var(--text); }

/* ── Main ── */
main {
    max-width: 680px;
    margin: 3rem auto;
    padding: 0 1.5rem;
}

/* ── Hero ── */
.hero {
    text-align: center;
    margin-bottom: 2.75rem;
}
.hero h1 {
    font-family: var(--font-display);
    font-size: clamp(2rem, 8vw, 3.5rem);
    font-weight: 700;
    line-height: 1.15;
    margin-bottom: 0.875rem;
    color: var(--text);
    white-space: nowrap;
}
.hero p {
    color: var(--subtle);
    font-size: 1.05rem;
}

/* ── Auth card ── */
.auth-section {
    background: var(--bg-raised);
    border: 3px solid var(--leaf);
    border-radius: var(--radius);
    overflow: hidden;
    max-width: var(--max-w);
    margin: 0 auto;
}

.auth-tabs {
    display: flex;
    border-bottom: 2px solid var(--leaf);
}

.tab {
    flex: 1;
    padding: 0.85rem;
    background: none;
    border: none;
    cursor: pointer;
    font-family: var(--font-body);
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--subtle);
    transition: color 0.15s, background 0.15s;
}
.tab:hover { color: var(--text); }
.tab.active {
    color: var(--sky);
    background: var(--bg);
    font-weight: 600;
    border-bottom: 2px solid var(--sky);
    margin-bottom: -2px;
}

.auth-panel {
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
    padding: 1.75rem;
}

/* ── Inputs ── */
input[type="text"],
input[type="email"],
input[type="password"] {
    width: 100%;
    padding: 0.65rem 0.875rem;
    background: var(--bg-input);
    color: var(--text);
    border: 2px solid color-mix(in srgb, var(--leaf) 50%, transparent);
    border-radius: var(--radius);
    font-family: var(--font-body);
    font-size: 0.95rem;
    outline: none;
    transition: border-color 0.15s;
}
input::placeholder { color: var(--subtle); }
input:focus { border-color: var(--leaf); }

/* ── Buttons ── */
.btn-primary {
    width: 100%;
    padding: 0.7rem;
    background: var(--leaf);
    color: #fff;
    border: none;
    border-radius: var(--radius);
    font-family: var(--font-body);
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    letter-spacing: 0.02em;
    transition: background 0.15s;
}
.btn-primary:hover { background: var(--leaf-light); }

/* ── Messages ── */
.error-msg   { color: var(--error);   font-size: 0.875rem; }
.success-msg { color: var(--success); font-size: 0.875rem; }

/* ── Welcome (authed) ── */
.welcome h1 {
    font-family: var(--font-display);
    font-size: 1.75rem;
    margin-bottom: 0.5rem;
}
.welcome a { color: var(--sky); text-decoration: none; }
.welcome a:hover { text-decoration: underline; }

/* ── Node page ── */
.node-page {
    width: 100%;
    max-width: 900px;
    margin: 0 auto;
    padding: 1.5rem 1.5rem;
}
.node-header {
    margin-bottom: 0.75rem;
    padding-bottom: 0.5rem;
}
.node-type-label {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--subtle);
    margin-bottom: 0.4rem;
}
.node-header h1 {
    font-family: var(--font-display);
    font-size: 2rem;
    color: var(--text);
    margin-bottom: 0.5rem;
}
.node-description {
    color: var(--subtle);
    font-size: 0.95rem;
    margin-top: 0.4rem;
}
.empty-list {
    color: var(--subtle);
    font-style: italic;
    padding: 2rem 0;
}
.node-list {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.node-card {
    display: flex;
    align-items: center;
    gap: 1rem;
    background: var(--bg-raised);
    border: 2px solid transparent;
    border-radius: var(--radius);
    padding: 0.75rem 1rem;
    transition: border-color 0.15s;
}
.node-card:hover { border-color: var(--leaf); }
.node-rank {
    font-family: var(--font-display);
    font-size: 1.1rem;
    color: var(--gold);
    min-width: 1.8rem;
    text-align: right;
    flex-shrink: 0;
}
.node-card-link {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    text-decoration: none;
    flex: 1;
}
.node-card-title {
    color: var(--text);
    font-weight: 500;
}
.node-card-subtype {
    font-size: 0.75rem;
    color: var(--subtle);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* ── Avatar ── */
.avatar-img {
    display: block;
    image-rendering: pixelated;
    border: 2px solid var(--bg-raised);
    border-radius: var(--radius);
}
.profile-avatar-wrap {
    position: relative;
    flex-shrink: 0;
    display: inline-block;
}
/* Hover-reveal pencil buttons (avatar + bio) */
.hover-edit-btn {
    position: absolute;
    top: 6px;
    right: 6px;
    background: rgba(22, 16, 13, 0.75);
    border: 1px solid var(--bg-raised);
    border-radius: var(--radius);
    color: var(--gold);
    cursor: pointer;
    padding: 4px;
    line-height: 1;
    opacity: 0;
    z-index: 10;
    transition: opacity 0.15s, color 0.15s;
}
.hover-edit-btn:hover { color: var(--gold); }
.hover-edit-btn.visible { opacity: 1; }
.profile-top {
    display: flex;
    gap: 1.5rem;
    align-items: flex-start;
    margin-bottom: 1.5rem;
}
.flex-fill {
    flex: 1;
    min-width: 0;
}
.avatar-editor { margin-bottom: 1.5rem; }
/* Shared layout for every createPaintEditor() surface: profile avatar, list-art modal,
   /dev template-art tool. */
.paint-editor-top {
    /* Establish a query container so the palette swatches can size off THIS row's own
       width (cqw), not the viewport. The canvas (square, flex-fills the remainder) and
       the palette then keep matched heights at any container width — full-page /dev panel
       or the narrower list-art modal — instead of the canvas shrinking while the fixed
       palette stays tall and leaves dead space below it. */
    container-type: inline-size;
    --swatch: clamp(17px, 4.6cqw, 28px);
    --swatch-gap: clamp(2px, 0.65cqw, 4px);
    display: flex;
    gap: 1rem;
    align-items: flex-start;
    flex-wrap: nowrap;
}
.paint-canvas {
    border: 2px solid var(--leaf);
    border-radius: var(--radius);
    cursor: crosshair;
    flex: 1 1 auto;                /* fill the width left of the palette… */
    min-width: 0;
    max-width: 480px;              /* …but never larger than the palette column's height */
    aspect-ratio: 1 / 1;           /* canvas is square (480×480 buffer), so it scales 1:1 */
    width: auto;
    height: auto;
    image-rendering: pixelated;    /* crisp nearest-neighbor scaling, no HiDPI blur */
}
.paint-palette {
    display: grid;
    grid-template-columns: repeat(5, var(--swatch));
    gap: var(--swatch-gap);
    flex-shrink: 0;                /* keep the palette beside the canvas, not wrapped below */
}
.palette-swatch {
    width: var(--swatch);
    height: var(--swatch);
    border: 2px solid transparent;
    border-radius: var(--radius);
    cursor: pointer;
    padding: 0;
    transition: border-color 0.1s;
}
.palette-swatch:hover   { border-color: var(--text); }
.palette-swatch.selected { border-color: var(--leaf-light); outline: 2px solid var(--leaf-light); }

/* Tool row (pen / fill / undo / redo) appended below the palette swatches. Spans the
   full palette grid width and lays its icon buttons out in a row. */
.paint-tools {
    grid-column: 1 / -1;          /* full width under the 5-column swatch grid */
    /* Mirror the swatch grid exactly: 5 columns of var(--swatch), same gap. With 5
       tool buttons this lines each one up under a swatch and makes the row width
       follow the palette width precisely, scaling together via the cqw --swatch. */
    display: grid;
    grid-template-columns: repeat(5, var(--swatch));
    gap: var(--swatch-gap);
    margin-top: var(--swatch-gap);
}
.paint-tool {
    width: var(--swatch);
    height: var(--swatch);        /* exact swatch size; scales with the palette */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 2px solid var(--leaf);
    border-radius: var(--radius);
    background: var(--bg-raised);
    color: var(--text);
    cursor: pointer;
    transition: border-color 0.1s, background 0.1s;
}
.paint-tool:hover:not(:disabled) { border-color: var(--leaf-light); }
.paint-tool.selected { border-color: var(--leaf-light); background: var(--leaf); color: var(--bg); }
.paint-tool:disabled { opacity: 0.4; cursor: default; }
.paint-tool-icon {
    display: block;
    width: 64%; height: 64%;      /* scales with the swatch-sized button */
    background-color: currentColor;
    -webkit-mask-size: contain; mask-size: contain;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    -webkit-mask-position: center; mask-position: center;
}
.paint-tool[data-tool="pen"]  .paint-tool-icon { -webkit-mask-image: url('/assets/pencil.svg');                  mask-image: url('/assets/pencil.svg'); }
.paint-tool[data-tool="fill"] .paint-tool-icon { -webkit-mask-image: url('/assets/paint-bucket.svg');            mask-image: url('/assets/paint-bucket.svg'); }
.paint-tool[data-tool="erase"] .paint-tool-icon { -webkit-mask-image: url('/assets/eraser.svg');                 mask-image: url('/assets/eraser.svg'); }
.paint-tool[data-tool="undo"] .paint-tool-icon { -webkit-mask-image: url('/assets/arrow-counter-clockwise.svg'); mask-image: url('/assets/arrow-counter-clockwise.svg'); }
.paint-tool[data-tool="redo"] .paint-tool-icon { -webkit-mask-image: url('/assets/arrow-clockwise.svg');         mask-image: url('/assets/arrow-clockwise.svg'); }

/* ── Side-by-side tracer (/trace.php) ──
   Full-width dev page: a reference image (left) under a 32×32 grid overlay, beside the
   shared paint editor (right). The reference square mirrors the canvas's 32×32 grid so a
   cell on the left maps to the same cell on the right; an uploaded image is fit (contain,
   no distortion) into an inner box inset by --pad grid cells on every side. */
.trace-main {
    /* Override the base `main` 680px cap — this page is intentionally full-width. */
    max-width: none;
    margin: 0;
    padding: 1.5rem 2rem 3rem;
}
.trace-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2rem;
    align-items: start;
    /* One shared square size for BOTH panels so they match. The right canvas only gets its
       column minus the palette (~172px) and the inter-panel gap, so size off that smaller
       budget: half the viewport (minus page padding 64px + gap 32px = 96px → 48px/side)
       minus the palette column. Bounded by 82vh so a square can't exceed the screen height. */
    --panel: min(82vh, calc(50vw - 48px - 172px));
}
/* Both panels resolve to --panel: the reference fills its column then caps here; the canvas
   wrapper flex-grows into its column-minus-palette then caps at the same value → equal squares.
   The wrapper carries the border + size cap so the grid overlay can sit at inset:0 and align
   cell-for-cell with the canvas content. */
.trace-canvas-wrap {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
    max-width: var(--panel);
    aspect-ratio: 1 / 1;
    border: 2px solid var(--leaf);
    border-radius: var(--radius);
    overflow: hidden;
}
.trace-main .paint-canvas {
    /* Fills the wrapper, which now owns the border + max-width cap. */
    max-width: none;
    width: 100%;
    height: 100%;
    border: none;
    border-radius: 0;
    display: block;
}
.trace-canvas-grid {
    position: absolute;
    inset: 0;
    pointer-events: none;
    display: none;                 /* shown when the wrapper has .show-grid */
    --cell: calc(100% / 32);
    /* Same overlay as .trace-ref-grid: fine line every cell, heavier every 8. */
    background-image:
        repeating-linear-gradient(to right,  rgba(255,255,255,0.28) 0 1px, transparent 1px calc(100% / 4)),
        repeating-linear-gradient(to bottom, rgba(255,255,255,0.28) 0 1px, transparent 1px calc(100% / 4)),
        repeating-linear-gradient(to right,  rgba(255,255,255,0.12) 0 1px, transparent 1px var(--cell)),
        repeating-linear-gradient(to bottom, rgba(255,255,255,0.12) 0 1px, transparent 1px var(--cell));
}
.trace-canvas-wrap.show-grid .trace-canvas-grid { display: block; }
.trace-grid-toggle { cursor: pointer; }
.trace-col h3 {
    margin: 0 0 0.75rem;
}
.trace-ref {
    position: relative;
    aspect-ratio: 1 / 1;
    width: 100%;
    max-width: var(--panel);
    margin-left: auto;             /* hug the right edge of its column, beside the canvas */
    --cell: calc(100% / 32);
    --pad: 0;
    border: 2px solid var(--leaf);
    border-radius: var(--radius);
    background: var(--bg-raised);
    overflow: hidden;
}
.trace-ref-img {
    position: absolute;
    /* Inset the image by --pad cells on all four sides; contain keeps aspect (non-square
       images fit their bounding box without stretching). */
    inset: calc(var(--pad) / 32 * 100%);
    width: calc(100% - var(--pad) / 32 * 200%);
    height: calc(100% - var(--pad) / 32 * 200%);
    object-fit: contain;
    image-rendering: auto;
    display: none;                 /* shown once a file is chosen */
}
.trace-ref.has-img .trace-ref-img { display: block; }
.trace-ref-grid {
    position: absolute;
    inset: 0;
    pointer-events: none;
    /* Fine line every cell, heavier line every 8 cells (100%/4). */
    background-image:
        repeating-linear-gradient(to right,  rgba(255,255,255,0.28) 0 1px, transparent 1px calc(100% / 4)),
        repeating-linear-gradient(to bottom, rgba(255,255,255,0.28) 0 1px, transparent 1px calc(100% / 4)),
        repeating-linear-gradient(to right,  rgba(255,255,255,0.12) 0 1px, transparent 1px var(--cell)),
        repeating-linear-gradient(to bottom, rgba(255,255,255,0.12) 0 1px, transparent 1px var(--cell));
}
.trace-ref-empty {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--subtle);
    font-size: 0.9rem;
    text-align: center;
    padding: 1rem;
}
.trace-ref.has-img .trace-ref-empty { display: none; }
.trace-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1rem;
}
.trace-controls label {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--subtle);
    font-size: 0.9rem;
}
.trace-pad-input {
    width: 4rem;
}
@media (max-width: 760px) {
    /* Stacked: each panel gets the full column, so size off width alone (no palette to
       subtract from a half-viewport). */
    .trace-grid { grid-template-columns: 1fr; --panel: min(100%, 82vh); }
}

/* ── Profile detail view ── */
.profile-detail {
    max-width: 700px;
}
.profile-back {
    margin-bottom: 1.5rem;
    font-size: 0.9rem;
}
.profile-back a { color: var(--sky); text-decoration: none; }
.profile-back a:hover { text-decoration: underline; }
.profile-detail h1 {
    font-family: var(--font-display);
    font-size: clamp(1.4rem, 4vw, 2.5rem);
    color: var(--text);
    margin-bottom: 0.35rem;
    overflow-wrap: break-word;
}
.profile-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1.25rem;
}
.profile-tagline {
    font-size: 0.95rem;
    color: var(--gold);
    margin-top: 0.15rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.tagline-empty { font-style: italic; }
.tagline-wrap {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    max-width: 100%;
}
.tagline-hover-btn {
    position: static;
    top: auto;
    right: auto;
    flex-shrink: 0;
}
.profile-joined {
    font-size: 0.85rem;
    color: var(--subtle);
}
.profile-bio {
    position: relative;
    margin-top: 0.5rem;
}
.profile-bio p {
    color: var(--text);
    line-height: 1.6;
    white-space: pre-wrap;
}
.bio-empty { color: var(--subtle); font-style: italic; }
.bio-edit-form {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-top: 0.5rem;
}
.bio-edit-form textarea {
    background: var(--bg-input);
    border: 2px solid var(--leaf);
    border-radius: var(--radius);
    color: var(--text);
    font-family: var(--font-body);
    font-size: 0.9rem;
    padding: 0.5rem 0.6rem;
    resize: vertical;
    width: 100%;
}
.bio-edit-form textarea:focus { outline: none; border-color: var(--leaf-light); }

/* ── Profile header ── */
.profile-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.375rem;
    padding-bottom: 0.5rem;
}
.profile-header-top {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.4rem;
}
.profile-header-top .avatar-img {
    border-radius: var(--radius);
    flex-shrink: 0;
}
.profile-identity h1 {
    font-family: var(--font-display);
    font-size: clamp(1.25rem, 4vw, 2rem);
    color: var(--text);
    margin-bottom: 0.25rem;
    overflow-wrap: break-word;
}
.profile-nudge { margin-top: 0.5rem; font-size: 0.875rem; }
.profile-nudge a { color: var(--sky); text-decoration: none; }
.profile-nudge a:hover { text-decoration: underline; }
.list-controls { display: flex; align-items: center; gap: 0.5rem; margin-top: 1.25rem; margin-bottom: 0.2rem; }
#compress-btn { display: inline-flex; align-items: center; gap: 0.3rem; }
.compress-icon {
    display: block;
    width: 13px; height: 13px;
    background-color: currentColor;
    -webkit-mask-image: url('/assets/arrow-up-left.svg');
    mask-image: url('/assets/arrow-up-left.svg');
    -webkit-mask-size: contain; mask-size: contain;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    -webkit-mask-position: center; mask-position: center;
    flex-shrink: 0;
}
.inline-form {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.5rem;
}
.inline-form input {
    flex: 1;
    min-width: 0;
    background: var(--bg-input);
    border: 2px solid var(--leaf);
    border-radius: var(--radius);
    color: var(--text);
    font-family: var(--font-body);
    font-size: 0.9rem;
    padding: 0.35rem 0.6rem;
}
.inline-form input:focus { outline: none; border-color: var(--leaf-light); }
.inline-form input.shake,
.modal-input.shake {
    border-color: var(--error);
    animation: shake 0.35s ease;
}
.shake { animation: shake 0.35s ease-in-out; }
@keyframes shake {
    0%, 100% { transform: translateX(0); }
    20%       { transform: translateX(-6px); }
    40%       { transform: translateX(6px); }
    60%       { transform: translateX(-4px); }
    80%       { transform: translateX(4px); }
}
.btn-small {
    background: var(--leaf);
    color: var(--text);
    border: none;
    border-radius: var(--radius);
    font-family: var(--font-body);
    font-size: 0.85rem;
    font-weight: 600;
    padding: 0.35rem 0.75rem;
    cursor: pointer;
    transition: background 0.15s;
}
.btn-small:hover { background: var(--leaf-light); }
.btn-cancel { background: var(--bg-raised); border: 1px solid var(--subtle); }
.btn-cancel:hover { background: var(--subtle); }
.btn-danger { background: var(--error); }
.btn-danger:hover { background: var(--error); opacity: 0.85; }
.profile-stats {
    flex-shrink: 0;
    text-align: right;
}
.stat {
    font-size: 0.875rem;
    color: var(--subtle);
}
.stat strong {
    font-size: 1.5rem;
    font-family: var(--font-display);
    color: var(--gold);
    display: block;
    line-height: 1;
}

/* ── 5×5 grid ── */
/* ── List layout: profile header + card grid in one auto-fill grid ──
   The header and the grid each span the full column block (1 / -1), so the block
   stays centered while the header's left edge always lands on the grid's first
   column — kept consistent at every width. (A plain centered wrapper can't do this:
   an auto-fill grid inside a shrink-to-fit box collapses to one column.) */
.list-layout {
    --card-w: 154px;
    display: grid;
    grid-template-columns: repeat(auto-fill, var(--card-w));
    justify-content: center;
    column-gap: 1.25rem;
    row-gap: 0;
}
.list-layout > * { grid-column: 1 / -1; min-width: 0; }

.grid-25 {
    --card-w: 154px;
    --card-h: 231px;
    display: grid;
    /* Fixed-size cards (locked width + height ⇒ locked 2:3 ratio). Columns reflow
       to fewer-per-row as the container narrows, rather than squeezing the cards. */
    grid-template-columns: repeat(auto-fill, var(--card-w));
    grid-auto-rows: var(--card-h);
    /* Left-align the tracks so the grid's left edge sits at the container's left
       padding — the same line the profile header/Edit sit on — at every width. */
    justify-content: start;
    gap: 1.25rem;
}
.grid-slot {
    border-radius: var(--radius);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 0.35rem;
    position: relative;
    text-decoration: none;
    font-family: var(--font-body);
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
}
.slot-top {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.slot-bottom {
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.slot-rank {
    position: absolute;
    top: 0.25rem;
    left: 0.25rem;
    font-family: var(--font-display);
    font-size: 0.9rem;
    color: var(--gold);
    line-height: 1;
}
.grid-slot--filled {
    background: var(--bg-raised);
    border: 2px solid color-mix(in srgb, var(--leaf) 30%, transparent);
    box-shadow: 0 0 10px color-mix(in srgb, var(--leaf) 80%, transparent);
}
.grid-slot--filled:hover {
    border-color: color-mix(in srgb, var(--leaf) 60%, transparent);
    box-shadow: 0 0 14px color-mix(in srgb, var(--leaf) 100%, transparent);
}
.slot-title {
    color: var(--text);
    font-size: 0.95rem;
    font-weight: 500;
    line-height: 1.3;
    text-align: center;
    word-break: break-word;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.slot-subtype {
    font-size: 0.8rem;
    color: var(--subtle);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.slot-subtype--typed { color: var(--gold); }
.typed-list-badge { color: var(--gold); text-transform: uppercase; letter-spacing: 0.08em; }
.template-badge { color: var(--gold); line-height: 1; vertical-align: middle; margin-right: 0.2rem; }
.list-title-wrap { display: inline-flex; align-items: center; gap: 0.5rem; max-width: 100%; }
.list-title-btn { position: static; top: auto; right: auto; flex-shrink: 0; opacity: 1; color: var(--subtle); }
.list-title-btn:hover { color: var(--gold); }
.slot-template-icon { color: var(--gold); line-height: 1; }
.modal-custom-label { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; color: var(--subtle); cursor: pointer; user-select: none; }
.modal-custom-label input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    width: 15px;
    height: 15px;
    border: 2px solid var(--subtle);
    border-radius: var(--radius);
    background: var(--bg-input);
    cursor: pointer;
    flex-shrink: 0;
    position: relative;
    transition: background 0.15s, border-color 0.15s;
}
.modal-custom-label input[type="checkbox"]:checked {
    background: var(--leaf);
    border-color: var(--leaf);
}
.modal-custom-label input[type="checkbox"]:checked::after {
    content: '';
    position: absolute;
    left: 50%;
    top: 45%;
    width: 4px;
    height: 8px;
    border: 2px solid var(--bg);
    border-top: none;
    border-left: none;
    transform: translate(-50%, -50%) rotate(45deg);
}
select.modal-input {
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='16' height='16' fill='%239e8070'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.6rem center;
    padding-right: 2rem;
    cursor: pointer;
}
.modal-sub-tabs { display: flex; border-bottom: 1px solid var(--bg-raised); margin-bottom: 0.5rem; }
#modal-list-create-panel, #modal-list-follow-panel { display: flex; flex-direction: column; gap: 0.75rem; }
.sub-tab {
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    color: var(--subtle);
    cursor: pointer;
    font-family: var(--font-body);
    font-size: 0.8rem;
    font-weight: 500;
    padding: 0.3rem 0.75rem;
    margin-bottom: -1px;
    transition: color 0.15s, border-color 0.15s;
}
.sub-tab:hover { color: var(--text); }
.sub-tab.active { color: var(--sky); border-bottom-color: var(--sky); }

.modal-list-type { display: flex; flex-direction: column; gap: 0.4rem; }
.modal-list-type-label { font-size: 0.8rem; color: var(--subtle); }
.grid-slot--empty {
    background: transparent;
    border: 2px dashed var(--bg-raised);
    color: inherit;
    align-items: center;
    justify-content: center;
}
.grid-slot--empty:hover {
    border-color: var(--leaf);
    background: var(--bg-raised);
}
.grid-slot--empty .slot-rank {
    top: 0.25rem;
    left: 0.25rem;
}
.slot-add {
    font-size: 1.5rem;
    color: var(--subtle);
    line-height: 1;
    transition: color 0.15s;
}
.grid-slot--empty:hover .slot-add { color: var(--leaf); }
.grid-slot--blank {
    background: transparent;
    border: 2px solid var(--bg-raised);
    opacity: 0.4;
}
.grid-slot--cover {
    padding: 0;
    overflow: hidden;
    position: relative;
}
.slot-delete-btn {
    position: absolute;
    top: 0.2rem;
    right: 0.2rem;
    z-index: 10;
    background: var(--gold);
    border: none;
    color: var(--bg);
    cursor: pointer;
    font-size: 0.85rem;
    line-height: 1;
    padding: 0.15rem 0.4rem;
    display: none;
}
.grid-25.edit-mode .slot-delete-btn { display: block; }
/* Social-list art pencil: shown in edit mode alongside the delete button (top-left, so it
   clears the delete button at top-right). Not shown during normal viewing of your own lists. */
.slot-art-edit-btn {
    position: absolute;
    top: 0.2rem;
    left: 0.2rem;
    z-index: 10;
    background: var(--gold);
    border: none;
    color: var(--bg);
    cursor: pointer;
    line-height: 0;
    padding: 0.25rem;
    border-radius: var(--radius);
    display: none;
}
.slot-art-edit-btn svg { display: block; }
.grid-25.edit-mode .slot-art-edit-btn { display: block; }
.modal-box--sm { width: min(340px, calc(100vw - 2rem)); }
/* Wide enough to show the paint canvas (480px) beside the palette (~156px) + gap,
   matching the full-size /dev art editor instead of cramping the canvas. Tighter gap
   keeps the heading/canvas/actions stack compact like the dev panel. */
.confirm-remove-heading { margin: 0; font-family: var(--font-display); font-size: 1.1rem; }
.confirm-remove-sub { margin: 0; font-size: 0.85rem; color: var(--subtle); }
.confirm-remove-sub a { color: var(--gold); }
.grid-slot--ghost { opacity: 0.3; border: 2px solid var(--leaf) !important; }
.grid-slot--filled { position: relative; }
.slot-cover-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center top;
    display: block;
}
/* Deezer art (artist/album/song) is 1:1 — fit it whole and anchor to the top of
   the portrait card instead of cropping; the leftover space falls to the bottom. */
.grid-slot--square-art .slot-cover-img { object-fit: contain; }
/* Square-art titles sit in the gap below the art — allow up to 3 lines (like plain
   cards) before ellipsis, rather than the 2-line clamp other cover cards use. */
.grid-slot--square-art .slot-title--cover { -webkit-line-clamp: 3; }
/* Reserve the square (its height == card width) with padding-top, then center the
   title in the leftover gap below it. Rank/follow are absolute, so unaffected. */
.grid-slot--square-art .slot-cover-overlay {
    padding-top: 100%;
    justify-content: center;
}
.slot-avatar-img {
    inset: auto;
    width: 75%;
    height: 75%;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    object-fit: cover;
    image-rendering: pixelated;
}
.user-list-img {
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: top;
    transform: none;
}
.slot-cover-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 0.35rem;
    gap: 0.2rem;
}
.slot-rank--cover {
    position: absolute;
    top: 0.25rem;
    left: 0.25rem;
    font-family: var(--font-display);
    font-size: 0.9rem;
    color: var(--gold);
    line-height: 1;
}
.slot-title--cover {
    color: var(--text);
    font-size: 0.9rem;
    font-weight: 600;
    line-height: 1.25;
    text-align: center;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.grid-slot--yt-video .slot-title--cover { -webkit-line-clamp: 3; }
.grid-25--hide-titles .slot-title--cover {
    display: none;
}
.grid-25--hide-titles .cover-failed .slot-title--cover {
    display: block;
}
/* PLACE cards have no photo (Google forbids storing place images), so instead of an <img> they
   reserve the same top square as avatars/music/YT cards (grid-slot--square-art) and center a
   tinted pushpin glyph in it (both axes). The title + category vertically center in the gap
   below the square, courtesy of the shared square-art overlay rule (padding-top: 100%). */
.grid-slot--place .slot-place-art {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--gold);
}
.grid-slot--place .slot-place-art svg {
    width: 42%;
    height: auto;
    opacity: 0.9;
}
.slot-place-type {
    text-align: center;
    font-size: 0.7rem;
    color: var(--subtle);
    line-height: 1.15;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
/* PLACE detail header: title on top, then the pushpin glyph at left paired with the type +
   location stacked in two rows (pin-next-to-address pattern). */
.place-head {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-bottom: 0.75rem;
}
.place-hero {
    display: inline-flex;
    flex: none;
    color: var(--gold);
}
.place-hero svg { width: 2.4rem; height: 2.4rem; }
.place-meta { display: flex; flex-direction: column; }
.place-meta .node-type-label { margin-bottom: 0.2rem; }   /* row gap to the location below */
.place-meta .content-meta { margin-bottom: 0; }            /* place-head provides trailing space */
/* Click-to-load map: a framed, iframe-sized box shows a map-like skeleton behind a centered
   "Show map" button. On click the whole box's contents are replaced by the iframe, which fills
   it 1:1 (same border/radius/size), so the swap reads as the placeholder "becoming" the map. */
.place-map {
    position: relative;
    width: 100%;
    height: 320px;
    margin-top: 1rem;
    border: 1px solid var(--bg-raised);
    border-radius: var(--radius);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
/* Abstract "map" loading state: a faint green block (park) + a few streets, gently pulsing. */
.place-map-skeleton {
    position: absolute;
    inset: 0;
    background-color: var(--bg-raised);
    background-image:
        radial-gradient(circle at 76% 32%, color-mix(in srgb, var(--leaf) 16%, transparent) 0 11%, transparent 11.5%),
        linear-gradient(118deg, transparent 0 45%, color-mix(in srgb, var(--subtle) 20%, transparent) 45% 47.5%, transparent 47.5%),
        linear-gradient(0deg, transparent 0 68%, color-mix(in srgb, var(--subtle) 14%, transparent) 68% 69.5%, transparent 69.5%),
        linear-gradient(90deg, transparent 0 28%, color-mix(in srgb, var(--subtle) 14%, transparent) 28% 29.5%, transparent 29.5%);
    animation: place-map-pulse 2.2s ease-in-out infinite;
}
@keyframes place-map-pulse { 0%, 100% { opacity: 0.65; } 50% { opacity: 1; } }
.place-map-show { position: relative; z-index: 1; }   /* sit above the absolute skeleton */
.place-map-frame {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
}
.slot-follow-badge--cover {
    position: absolute;
    top: 0.3rem;
    right: 0.3rem;
}
.slot-follow-badge {
    position: absolute;
    top: 0.3rem;
    right: 0.3rem;
    color: var(--sky);
    line-height: 1;
    pointer-events: none;
    opacity: 0.8;
}
.slot-type-icon {
    color: var(--leaf-light);
    line-height: 1;
    flex-shrink: 0;
    pointer-events: none;
}

@media (max-width: 500px) {
    /* Trim page gutters so two fixed-width cards fit on a phone; auto-fill then
       reflows to 1 column on very narrow screens. */
    .node-page { padding: 1rem 0.75rem; }
}

/* ── Node ID chip ── */
.node-id-chip {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    background: none;
    border: 1px solid var(--subtle);
    border-radius: var(--radius);
    color: var(--subtle);
    font-family: 'Courier New', monospace;
    font-size: 1.125rem;
    letter-spacing: 0.05em;
    padding: 0.3rem 0.75rem;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s;
}
.node-id-chip:hover { color: var(--text); border-color: var(--subtle); }
.node-id-chip.copied { color: var(--success); border-color: var(--success); }
.node-id-hash { color: var(--gold); }

/* ── Header tools: hash chip + dice randomizer ──
   In normal flow as the middle flex child (logo · tools · nav), so the header's
   space-between distribution keeps it roughly centered while letting all three
   groups compress together as the viewport narrows. It was absolutely pinned to
   screen-center, which took it out of flow and let the nav slide under it. */
.header-tools {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}
/* Undo the chip's standalone absolute-centering so it sits inline in the tools
   flex row, on one line, with all 6 hex characters visible. */
.header-tools .node-id-chip {
    position: static;
    left: auto;
    transform: none;
    flex-shrink: 0;
    white-space: nowrap;
}

.randomizer { display: flex; align-items: center; gap: 0.4rem; }

.dice-btn {
    position: relative;
    width: 34px;
    height: 30px;
    background: none;
    border: 1px solid var(--subtle);
    border-radius: var(--radius);
    color: var(--gold);
    cursor: pointer;
    padding: 0;
    transition: border-color 0.15s, background 0.15s;
}
.dice-btn:hover { border-color: var(--text); background: color-mix(in srgb, var(--gold) 12%, transparent); }
/* Two staggered dice to read as a thrown pair. */
.dice {
    position: absolute;
    width: 16px;
    height: 16px;
    background-color: currentColor;
    -webkit-mask-size: contain; mask-size: contain;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    -webkit-mask-position: center; mask-position: center;
}
.dice--a {
    -webkit-mask-image: url('/assets/dice-two.svg'); mask-image: url('/assets/dice-two.svg');
    left: 4px; top: 2px; transform: rotate(-14deg);
}
.dice--b {
    -webkit-mask-image: url('/assets/dice-five.svg'); mask-image: url('/assets/dice-five.svg');
    right: 3px; bottom: 2px; transform: rotate(13deg); opacity: 0.9;
}
/* The roll animation is driven by the Web Animations API in randomizer.js. */

.rand-toggles { display: flex; gap: 0.1rem; }
.rand-toggle {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;                   /* small space between icon and indicator */
    width: 26px;
    height: 28px;
    background: none;
    border: 1px solid transparent;
    border-radius: var(--radius);
    color: var(--leaf-light);
    cursor: pointer;
    padding: 0;
    transition: color 0.15s, opacity 0.15s;
}
.rand-toggle:hover { color: var(--text); }
.rand-toggle:not(.active) { color: var(--subtle); opacity: 0.4; }   /* type excluded */
/* Colored tab indicator beneath the icon, shown only when the type is enabled.
   Always present (transparent when off) so toggling doesn't shift the icon. */
.rand-toggle::after {
    content: "";
    width: 14px;                /* match the icon width */
    height: 2px;
    background: transparent;
    transition: background 0.15s;
}
.rand-toggle.active::after { background: var(--gold); }

/* Guest state: visible but inert, nudging toward sign-in. */
.randomizer[data-authed="0"] .dice-btn { opacity: 0.45; }
.randomizer[data-authed="0"] .rand-toggle { opacity: 0.3; cursor: default; pointer-events: none; }
.dice-btn--disabled { opacity: 0.4; cursor: not-allowed; }

/* ── LIST node ranked list ── */
.node-list--ranked { list-style: none; }
.node-card--empty { opacity: 0.45; }
.node-card--empty .node-rank { color: var(--subtle); }
.node-card-add {
    background: none;
    border: none;
    color: var(--subtle);
    font-size: 1.1rem;
    cursor: pointer;
    padding: 0 0.5rem;
    flex: 1;
    text-align: left;
    transition: color 0.15s;
}
.node-card-add:hover { color: var(--leaf); }
.node-card-blank { color: var(--bg-raised); flex: 1; padding: 0 0.5rem; }

/* ── Add-to-slot modal ── */
.modal {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
}
.modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(10, 8, 6, 0.8);
}
.modal-box {
    position: relative;
    background: var(--bg-raised);
    border: 2px solid var(--leaf);
    border-radius: var(--radius);
    padding: 1.5rem;
    width: min(500px, calc(100vw - 2rem));
    max-height: calc(100vh - 4rem);
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
/* Art editor modal: override the base .modal-box width/padding so its editor row is
   as wide as the full-page /dev panel (≈636px inner), making the canvas + palette render
   at the same size. Must follow .modal-box in source order to win (equal specificity). */
.modal-box--art { width: min(700px, calc(100vw - 2rem)); gap: 0.6rem; padding: 1rem; }
.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.modal-header h2 { font-family: var(--font-display); font-size: 1.2rem; }
.modal-close {
    background: none;
    border: none;
    color: var(--subtle);
    font-size: 1rem;
    cursor: pointer;
    padding: 0.2rem 0.4rem;
    line-height: 1;
    transition: color 0.15s;
}
.modal-close:hover { color: var(--text); }
.modal-type-pills { display: flex; gap: 0.5rem; }
.type-pill {
    flex: 1;
    padding: 0.4rem 0.75rem;
    background: var(--bg);
    border: 2px solid transparent;
    border-radius: var(--radius);
    color: var(--subtle);
    font-family: var(--font-body);
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s;
}
.type-pill:hover { color: var(--text); }
.type-pill.active { color: var(--sky); border-color: var(--sky); }
.modal-type-pills--locked .type-pill { flex: 0 0 auto; }
.type-pill.active:disabled { color: var(--sky); border-color: var(--sky); cursor: default; }
.modal-section { display: flex; flex-direction: column; gap: 0.75rem; }
.category-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.cat-chip {
    padding: 0.3rem 0.65rem;
    background: var(--bg);
    border: 2px solid transparent;
    border-radius: var(--radius);
    color: var(--subtle);
    font-family: var(--font-body);
    font-size: 0.8rem;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s;
}
.cat-chip:hover { color: var(--text); }
.cat-chip.active { color: var(--leaf-light); border-color: var(--leaf); }
.cat-chip:disabled { cursor: default; opacity: 1; }
.modal-typed-hint { font-size: 0.8rem; color: var(--subtle); font-style: italic; }
.modal-input {
    width: 100%;
    padding: 0.6rem 0.75rem;
    background: var(--bg);
    border: 2px solid color-mix(in srgb, var(--leaf) 40%, transparent);
    border-radius: var(--radius);
    color: var(--text);
    font-family: var(--font-body);
    font-size: 0.9rem;
    outline: none;
    transition: border-color 0.15s;
}
.modal-input:focus { border-color: var(--leaf); }
.modal-input::placeholder { color: var(--subtle); }
.modal-search-link { font-size: 0.85rem; color: var(--sky); text-decoration: none; }
.modal-search-link:hover { text-decoration: underline; }
.modal-search-results { display: flex; flex-direction: column; gap: 0.25rem; margin-top: 0.25rem; }
.search-result-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: var(--bg);
    border: 1px solid transparent;
    border-radius: var(--radius);
    color: var(--text);
    font-family: var(--font-body);
    font-size: 0.875rem;
    padding: 0.4rem 0.75rem;
    text-align: left;
    cursor: pointer;
    width: 100%;
    transition: border-color 0.15s;
}
.search-result-item:hover { border-color: var(--leaf); }
.search-result-nodeid { color: var(--subtle); font-family: 'Courier New', monospace; font-size: 0.75rem; margin-left: auto; }
.modal-search-empty { font-size: 0.85rem; color: var(--subtle); font-style: italic; }
.user-preview-inner {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    background: var(--bg);
    border: 1px solid var(--leaf);
    border-radius: var(--radius);
    padding: 0.5rem 0.75rem;
}
.user-preview-icon { color: var(--leaf-light); line-height: 1; flex-shrink: 0; }
.user-preview-name { font-weight: 500; font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1; }
.user-preview-nodeid { font-family: 'Courier New', monospace; font-size: 0.75rem; color: var(--subtle); margin-left: auto; }
.modal-error-wrap { min-height: 1.25em; }
.modal-actions { display: flex; align-items: center; gap: 0.5rem; justify-content: flex-end; margin-top: 0.25rem; }
/* Art editor modal left-aligns its actions to match the full-page /dev art tool. */
.modal-box--art .modal-actions { justify-content: flex-start; }
.modal-success { color: var(--success); font-size: 0.875rem; margin-right: auto; }

/* ── Footer ── */
footer {
    padding: 2rem;
    display: flex;
    justify-content: center;
    align-items: center;
}
.footer-nav {
    display: flex;
    gap: 2rem;
    justify-content: center;
}
.footer-nav a {
    color: var(--text);
    text-decoration: none;
    font-size: 0.9rem;
}
.footer-nav a:hover {
    text-decoration: underline;
}

/* ── YouTube ── */
.youtube-embed-wrapper {
    position: relative;
    padding-bottom: 56.25%;
    height: 0;
    overflow: hidden;
    margin: 1rem 0 1.25rem;
    border-radius: var(--radius);
}
.youtube-embed-wrapper iframe {
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 100%;
    border: 0;
    border-radius: var(--radius);
}
.content-detail--channel { display: flex; flex-direction: column; align-items: flex-start; }
.channel-thumbnail {
    width: 96px;
    height: 96px;
    border-radius: var(--radius);
    object-fit: cover;
    margin-bottom: 0.75rem;
}
.external-link-trigger { margin-top: 1.25rem; }

/* ── YouTube channel card: the icon + 2×2 thumb grid are packed into the same square
   art area used by avatars/list/music cards (grid-slot--cover + square-art), with the
   title in the shared cover overlay. The thumb grid fills the square's full width at the
   bottom; the icon shrinks into whatever space remains above it. ── */
.slot-yt-square {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    aspect-ratio: 1 / 1;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    overflow: hidden;
}
.slot-yt-channel-logo {
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    padding: 0.5rem;
    box-sizing: border-box;
}
.slot-yt-channel-placeholder {
    max-width: 48%;
    max-height: 72%;
    width: auto;
    height: auto;
    object-fit: contain;
    opacity: 0.92;
}
.slot-yt-channel-thumbs {
    display: grid;
    grid-template-columns: 1fr 1fr;
    width: 100%;
    flex-shrink: 0;
}
/* Each cell sizes itself to a 16:9 box matching the thumbnail's own ratio, so the
   grid never forces a squarer cell that would crop the image under object-fit. */
.slot-yt-channel-thumbs img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    display: block;
}

/* ── YouTube grid card variants ── */
.grid-slot--yt-video .slot-cover-img {
    object-fit: contain;
    object-position: center center;
    background: #000;
}
.grid-slot--yt-video .slot-cover-overlay {
    background: linear-gradient(to top, rgba(0,0,0,0.72) 0%, transparent 55%);
}
.slot-yt-play {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -60%);
    pointer-events: none;
    line-height: 1;
    opacity: 0.8;
    transition: opacity 0.15s;
}
.grid-slot--yt-video:hover .slot-yt-play { opacity: 1; }
.grid-slot--yt-channel { background: #000; }

/* ── Feedback & Dev pages ── */
.content-page {
    max-width: 700px;
    width: 100%;
    margin: 2rem auto;
    padding: 0 2rem;
    box-sizing: border-box;
}
.dev-tab-panel {
    width: 100%;
    box-sizing: border-box;
}
.dev-art-hint { color: var(--subtle); font-size: 0.85rem; margin: 0.5rem 0 1rem; max-width: 48ch; }
.dev-art-hint code { background: var(--bg-raised); padding: 0.05rem 0.3rem; border-radius: 3px; }
.dev-art-status { color: var(--leaf-light); font-size: 0.85rem; align-self: center; }
.feedback-page .content-container h1,
.dev-page .content-container h1 {
    font-family: var(--font-display);
    font-size: 2rem;
    margin: 0 0 1.5rem 0;
    color: var(--text);
}
.feedback-section {
    margin-bottom: 2.5rem;
}
.feedback-section h2 {
    font-family: var(--font-display);
    font-size: 1.25rem;
    margin: 0 0 0.5rem 0;
    color: var(--text);
}
.feedback-intro {
    font-size: 0.9rem;
    color: var(--text);
    opacity: 0.7;
    margin: 0 0 1rem 0;
}
.feedback-empty {
    font-size: 0.9rem;
    color: var(--text);
    opacity: 0.5;
}

/* Feature voting rows */
.feature-list { display: flex; flex-direction: column; gap: 0.75rem; }
.feature-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    background: var(--bg-raised);
    border: 1px solid color-mix(in srgb, var(--leaf) 20%, transparent);
    border-radius: var(--radius);
    padding: 0.75rem 1rem;
}
.feature-info { display: flex; flex-direction: column; gap: 0.2rem; flex: 1; min-width: 0; }
.feature-title { font-weight: 600; font-size: 0.95rem; color: var(--text); }
.feature-desc  { font-size: 0.85rem; color: var(--text); opacity: 0.7; }
.feature-attr  { font-size: 0.8rem; color: var(--text); opacity: 0.55; }
.feature-attr a { color: var(--sky); text-decoration: none; }
.feature-attr a:hover { text-decoration: underline; }

.feature-votes { display: flex; gap: 0.4rem; align-items: center; flex-shrink: 0; }
.vote-btn {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    background: var(--bg-raised);
    border: 1px solid color-mix(in srgb, var(--leaf) 25%, transparent);
    color: var(--text);
    border-radius: var(--radius);
    padding: 0.3rem 0.55rem;
    font-size: 0.85rem;
    cursor: pointer;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.vote-btn:disabled { opacity: 0.4; cursor: default; }
.vote-btn--up:hover:not(:disabled)   { border-color: var(--leaf); color: var(--leaf); }
.vote-btn--down:hover:not(:disabled) { border-color: var(--error); color: var(--error); }
.vote-btn--up.vote-btn--active   { border-color: var(--leaf); color: var(--leaf); background: color-mix(in srgb, var(--leaf) 12%, transparent); }
.vote-btn--down.vote-btn--active { border-color: var(--error); color: var(--error); background: color-mix(in srgb, var(--error) 12%, transparent); }

/* Feedback form */
.feedback-type-select { margin-bottom: 0.5rem; }
.feedback-textarea {
    width: 100%;
    min-height: 6rem;
    resize: vertical;
    margin-bottom: 0.5rem;
    box-sizing: border-box;
    font-family: var(--font-body);
}
.feedback-actions { display: flex; gap: 0.5rem; align-items: center; }

.feedback-status { margin-top: 1rem; }
.feedback-reply {
    background: var(--bg-raised);
    border-left: 3px solid var(--leaf);
    padding: 0.6rem 0.8rem;
    border-radius: var(--radius);
    margin-top: 0.5rem;
}
.feedback-reply-label { font-size: 0.8rem; font-weight: 600; color: var(--leaf); display: block; margin-bottom: 0.25rem; }
.feedback-reply p { margin: 0; font-size: 0.9rem; color: var(--text); }
.feedback-read-receipt { font-size: 0.85rem; color: var(--leaf); opacity: 0.8; margin: 0; }

/* Dev page */
.dev-tabs { display: flex; gap: 0; margin-bottom: 1.5rem; border-bottom: 2px solid color-mix(in srgb, var(--leaf) 20%, transparent); }
.dev-tabs .tab {
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    padding: 0.5rem 1.2rem;
    cursor: pointer;
    font-family: var(--font-body);
    font-size: 0.95rem;
    color: var(--text);
    opacity: 0.6;
    transition: opacity 0.12s, border-color 0.12s;
}
.dev-tabs .tab.active { opacity: 1; border-bottom-color: var(--leaf); }
.dev-tabs .tab:hover  { opacity: 0.9; }
.dev-unread-badge {
    display: inline-block;
    background: var(--error);
    color: #fff;
    border-radius: var(--radius);
    font-size: 0.7rem;
    padding: 0 0.4rem;
    margin-left: 0.3rem;
    vertical-align: middle;
    line-height: 1.5;
}

.dev-feedback-list { display: flex; flex-direction: column; gap: 1rem; }
.dev-feedback-item {
    background: var(--bg-raised);
    border: 1px solid color-mix(in srgb, var(--leaf) 20%, transparent);
    border-radius: var(--radius);
    padding: 0.85rem 1rem;
}
.dev-feedback-item--read { opacity: 0.65; }
.dev-feedback-meta {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-bottom: 0.5rem;
    font-size: 0.85rem;
}
.dev-feedback-user  { font-weight: 600; color: var(--text); }
.dev-feedback-type  { background: color-mix(in srgb, var(--gold) 18%, transparent); color: var(--gold); border-radius: var(--radius); padding: 0.1rem 0.4rem; font-size: 0.75rem; }
.dev-feedback-date  { color: var(--text); opacity: 0.5; }
.dev-feedback-read-mark { color: var(--leaf); opacity: 0.7; font-size: 0.8rem; }
.dev-feedback-comment { margin: 0 0 0.75rem 0; font-size: 0.9rem; color: var(--text); white-space: pre-wrap; }
.dev-reply-area { display: flex; gap: 0.5rem; align-items: flex-start; }
.dev-reply-input { flex: 1; resize: vertical; font-family: var(--font-body); font-size: 0.85rem; }

/* Dev features */
.dev-add-feature-form { margin-bottom: 1.5rem; padding: 1rem; background: var(--bg-raised); border-radius: var(--radius); }
.dev-add-feature-form button[type="submit"] { width: auto; }
.dev-add-feature-form h3 { margin: 0 0 0.75rem 0; font-size: 1rem; color: var(--text); }
.dev-add-feature-form .modal-input { margin-bottom: 0.5rem; width: 100%; box-sizing: border-box; }
.dev-user-search-row { position: relative; }
.dev-attr-selected { font-size: 0.85rem; color: var(--leaf); margin-left: 0.5rem; }
.dev-user-results {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--bg-raised);
    border: 1px solid color-mix(in srgb, var(--leaf) 30%, transparent);
    border-radius: var(--radius);
    list-style: none;
    margin: 0;
    padding: 0;
    z-index: 50;
    max-height: 180px;
    overflow-y: auto;
}
.dev-user-results li { padding: 0.5rem 0.75rem; cursor: pointer; font-size: 0.9rem; color: var(--text); }
.dev-user-results li:hover { background: color-mix(in srgb, var(--leaf) 10%, transparent); }

.dev-feature-list { display: flex; flex-direction: column; gap: 0.6rem; }
.dev-feature-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    background: var(--bg-raised);
    border: 1px solid color-mix(in srgb, var(--leaf) 20%, transparent);
    border-radius: var(--radius);
    padding: 0.6rem 0.8rem;
}
.dev-feature-info { display: flex; flex-direction: column; gap: 0.15rem; flex: 1; min-width: 0; }
.dev-feature-votes { display: flex; align-items: center; gap: 0.6rem; flex-shrink: 0; font-size: 0.85rem; }
.vote-up-label   { color: var(--leaf); }
.vote-down-label { color: var(--error); }
/* API kill switches (APIs tab) — same card rhythm as feature rows; off state goes red. */
.dev-api-switches { display: flex; flex-direction: column; gap: 0.6rem; max-width: 32rem; }
.dev-api-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    background: var(--bg-raised);
    border: 1px solid color-mix(in srgb, var(--leaf) 20%, transparent);
    border-radius: var(--radius);
    padding: 0.6rem 0.8rem;
}
.dev-api-row--off { border-color: color-mix(in srgb, var(--error) 35%, transparent); }
.dev-api-info { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.dev-api-name { font-weight: 600; }
.dev-api-cost { font-size: 0.8rem; color: var(--subtle); }
.dev-api-toggle { display: flex; align-items: center; gap: 0.5rem; cursor: pointer; flex-shrink: 0; }
.dev-api-state { font-size: 0.8rem; color: var(--subtle); min-width: 4.5rem; text-align: right; }
.dev-api-row--off .dev-api-state { color: var(--error); }
.dev-api-switch { width: 1.1rem; height: 1.1rem; accent-color: var(--leaf); cursor: pointer; }
.btn-danger {
    background: color-mix(in srgb, var(--error) 15%, transparent);
    color: var(--error);
    border: 1px solid color-mix(in srgb, var(--error) 35%, transparent);
}
.btn-danger:hover { background: color-mix(in srgb, var(--error) 25%, transparent); }

/* Analytics */
.analytics-controls {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 1rem;
}
.analytics-toggle-group {
    display: flex;
    border: 1px solid color-mix(in srgb, var(--leaf) 30%, transparent);
    border-radius: var(--radius);
    overflow: hidden;
}
.analytics-toggle {
    background: transparent;
    color: var(--subtle);
    border: none;
    padding: 0.35rem 0.85rem;
    font-size: 0.85rem;
    cursor: pointer;
    font-family: var(--font-body);
    transition: background 0.15s, color 0.15s;
}
.analytics-toggle + .analytics-toggle {
    border-left: 1px solid color-mix(in srgb, var(--leaf) 30%, transparent);
}
.analytics-toggle.active {
    background: color-mix(in srgb, var(--leaf) 20%, transparent);
    color: var(--text);
}
.analytics-toggle:hover:not(.active) {
    background: color-mix(in srgb, var(--leaf) 10%, transparent);
    color: var(--text);
}
.analytics-label {
    font-size: 0.8rem;
    color: var(--subtle);
    margin: 0 0 0.75rem;
}
.analytics-chart-wrap {
    position: relative;
    width: 100%;
}

/* ── Social-list similarity panel (owner only) ── */
.list-similarity {
    max-width: 700px;
    margin: 2rem auto 0;
    padding: 1.25rem 1.5rem;
    background: var(--bg-raised);
}
.similarity-heading {
    font-family: var(--font-display);
    font-size: 1.25rem;
    margin: 0 0 1rem;
}
.similarity-empty {
    color: var(--subtle);
    font-size: 0.9rem;
    margin: 0;
}
.similarity-mainstream {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.35rem 0.6rem;
    padding-bottom: 1rem;
    margin-bottom: 1rem;
    border-bottom: 1px solid var(--border);
}
.similarity-mainstream-pct {
    font-family: var(--font-display);
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--gold);
    line-height: 1;
}
.similarity-mainstream-label {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--subtle);
}
.similarity-info {
    cursor: help;
    color: var(--subtle);
}
.similarity-mainstream-sub {
    flex-basis: 100%;
    font-size: 0.8rem;
    color: var(--subtle);
}
.similarity-list {
    display: flex;
    flex-direction: column;
}
.similarity-row {
    --row-accent: var(--subtle);   /* moderate match by default */
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 0.4rem 0.6rem 0.75rem;
    border-bottom: 1px solid color-mix(in srgb, var(--row-accent) 35%, transparent);
    transition: background 0.15s;
}
/* Accent bar as a pseudo-element (not a border) so it doesn't miter-join the
   bottom rule into a taper at the corner. */
.similarity-row::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--row-accent);
}
.similarity-row:last-child { border-bottom-color: transparent; }
.similarity-row:hover { background: color-mix(in srgb, var(--row-accent) 8%, transparent); }
/* Match-strength colour scale: green (near-exact) → gold (strong) → muted. */
.similarity-row--exact  { --row-accent: var(--leaf-light); }
.similarity-row--strong { --row-accent: var(--gold); }
.similarity-row-main {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.2rem 0.5rem;
    min-width: 0;
}
.similarity-title {
    color: var(--link);
    text-decoration: none;
    font-size: 0.95rem;
}
.similarity-title:hover { text-decoration: underline; }
.similarity-user {
    color: var(--subtle);
    text-decoration: none;
    font-size: 0.85rem;
}
a.similarity-user:hover { color: var(--leaf-light); text-decoration: underline; }
/* Near-exact matches: surface the person, since the lists barely differ. */
.similarity-row--exact .similarity-user {
    color: var(--leaf-light);
    font-weight: 600;
    font-size: 0.95rem;
}
.similarity-row--exact .similarity-title {
    color: var(--subtle);
    font-size: 0.85rem;
}
.similarity-row-pct {
    flex-shrink: 0;
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--text);
    background: color-mix(in srgb, var(--row-accent) 20%, transparent);
    padding: 0.15rem 0.5rem;
    border-radius: var(--radius);
}
.similarity-more-wrap {
    margin-top: 1rem;
    text-align: center;
}
