/* Dark background: the map is 20k luminous dots on emptiness, and the arcs
   need to read against it. */
:root {
    --bg: #10131a;
    --panel: #181d27;
    --line: #2a3240;
    --fg: #dfe4ec;
    --dim: #8b95a7;
    --dot: #6fa8ff;
    --hot: #ffd166;
    --arc: #ff7b6b;
    --dead: #8b7bb8;   /* dissolved twinnings */
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    height: 100%;
    background: var(--bg);
    color: var(--fg);
    font: 14px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
}

a { color: var(--dot); }

/* Map page: full-viewport map with a fixed-width sidebar. */
.layout {
    display: grid;
    grid-template-columns: 1fr 320px;
    height: 100vh;
}

#mapwrap {
    position: relative;
    overflow: hidden;
    background: var(--bg);
    cursor: grab;
}
#mapwrap.dragging { cursor: grabbing; }

#map { display: block; width: 100%; height: 100%; }

/* The graticule replaces coastlines as the spatial reference: without any
   landmass outline, a bare dot cloud gives the eye nothing to anchor scale
   or position to. */
.graticule { stroke: #222a36; stroke-width: 0.5; fill: none; }
.equator, .meridian { stroke: #313b4a; stroke-width: 0.8; }

.dot { fill: var(--dot); fill-opacity: 0.55; }
.dot.active { fill: var(--hot); fill-opacity: 1; }
.dot.twin { fill: #7ef7c8; fill-opacity: 1; }

.arc {
    stroke: var(--arc);
    fill: none;
    stroke-opacity: 0.8;
    stroke-linecap: round;
    pointer-events: none;
}

/* A dissolved twinning is not a current fact, so it must not look like one. */
.arc.ended {
    stroke: var(--dead);
    stroke-dasharray: 4 3;
    stroke-opacity: 0.9;
}
.dot.twin.ended { fill: var(--dead); }

/* Search box + results dropdown. */
.search { position: relative; margin-bottom: 14px; }

#q {
    width: 100%;
    padding: 6px 8px;
    background: #0d1017;
    border: 1px solid var(--line);
    border-radius: 4px;
    color: var(--fg);
    font: inherit;
}
#q:focus { outline: none; border-color: var(--hot); }

#results {
    position: absolute;
    z-index: 10;
    left: 0;
    right: 0;
    top: calc(100% + 2px);
    max-height: 260px;
    overflow-y: auto;
    margin: 0;
    padding: 0;
    list-style: none;
    background: #0d1017;
    border: 1px solid var(--line);
    border-radius: 4px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);
}
#results li {
    padding: 5px 8px;
    cursor: pointer;
    display: flex;
    align-items: baseline;
    gap: 6px;
}
#results li:hover, #results li.sel { background: #1b2230; }
#results .nm { color: var(--fg); }

/* Towns the year filter is currently hiding. Still selectable — pinning one
   is how you find out where it is — but visibly not part of the live map. */
#results li.out .nm { color: var(--dim); font-style: italic; }
#results li.out .n { color: var(--dim); }
#results .c { color: var(--dim); font-size: 12px; }
/* Twin count, pushed to the right edge. */
#results .n { margin-left: auto; color: var(--hot); font-size: 11px; }
#results .none { color: var(--dim); cursor: default; }

/* Timeline: histogram of twinnings per year, with the slider under it. */
.timeline { margin-bottom: 16px; }
.timeline label {
    display: block;
    font-size: 12px;
    color: var(--dim);
    margin-bottom: 4px;
}
#yearlabel { color: var(--fg); font-variant-numeric: tabular-nums; }

#hist { height: 46px; }
#hist svg { width: 100%; height: 46px; display: block; }
#histbars rect { fill: var(--dot); fill-opacity: 0.75; }
#histbars rect:hover { fill: var(--hot); fill-opacity: 1; }
/* Cover the years excluded by the slider window, one rect per side. */
#masklo, #maskhi { fill: var(--bg); fill-opacity: 0.72; pointer-events: none; }

/* Dual-handle slider: two range inputs stacked in the same space. Only the
   thumbs receive pointer events, so whichever handle is under the cursor
   takes the drag and the one underneath is not blocked by the other's track. */
.dual {
    position: relative;
    height: 18px;
    margin-top: 2px;
}

/* The visible track is drawn by us, once, behind both inputs. Each input
   still draws its own native track, and the second one — being later in the
   DOM — painted over the first one's thumb, hiding the left handle. Making
   both native tracks transparent is what fixes that; without it no z-index
   helps, because the offending pixels belong to the top input's own track. */
.dual::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 4px;
    margin-top: -2px;
    background: var(--line);
    border-radius: 2px;
}

.dual input[type="range"] {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 18px;
    margin: 0;
    background: none;
    -webkit-appearance: none;
    appearance: none;
    pointer-events: none;   /* re-enabled on the thumbs below */
}

.dual input[type="range"]::-webkit-slider-runnable-track {
    background: transparent;
    border: none;
    height: 18px;
}
.dual input[type="range"]::-moz-range-track {
    background: transparent;
    border: none;
    height: 18px;
}
/* Firefox also fills the span left of the thumb; that would paint over the
   other handle just as the track did. */
.dual input[type="range"]::-moz-range-progress { background: transparent; }

.dual input[type="range"]::-webkit-slider-thumb {
    pointer-events: auto;
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 14px;
    margin-top: 2px;
    border-radius: 50%;
    background: var(--hot);
    border: 2px solid var(--bg);
    cursor: grab;
}
.dual input[type="range"]::-moz-range-thumb {
    pointer-events: auto;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--hot);
    border: 2px solid var(--bg);
    cursor: grab;
}

/* Highlight the selected span between the two thumbs. */
#yearfill {
    position: absolute;
    top: 50%;
    height: 4px;
    margin-top: -2px;
    background: var(--hot);
    border-radius: 2px;
    pointer-events: none;
}

/* Ends of the slider track, labelling the histogram's axis. */
.axis {
    display: flex;
    justify-content: space-between;
    color: var(--dim);
    font-size: 10px;
    font-variant-numeric: tabular-nums;
    margin-top: -2px;
}

.meta { color: var(--dim); font-size: 11px; }
.chk { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
.chk input { accent-color: var(--hot); }

/* Year annotation in the twin list. */
#twins .yr { color: var(--hot); font-variant-numeric: tabular-nums; font-size: 12px; }
#twins .dead { color: var(--dead); font-size: 11px; }

/* Sidebar */
aside {
    background: var(--panel);
    border-left: 1px solid var(--line);
    padding: 16px;
    overflow-y: auto;
}

aside h1 {
    font-size: 15px;
    margin: 0 0 4px;
    letter-spacing: 0.02em;
}

.sub { color: var(--dim); font-size: 12px; margin-bottom: 16px; }

#info h2 { font-size: 17px; margin: 0 0 2px; }
#info .country { color: var(--dim); font-size: 13px; margin-bottom: 10px; }
#info .count { color: var(--hot); font-size: 12px; margin-bottom: 8px; }

#twins { list-style: none; padding: 0; margin: 0; }
#twins li {
    padding: 4px 0;
    border-bottom: 1px solid var(--line);
}
#twins .c { color: var(--dim); font-size: 12px; }

.hint { color: var(--dim); font-size: 13px; }

footer {
    margin-top: 20px;
    padding-top: 12px;
    border-top: 1px solid var(--line);
    color: var(--dim);
    font-size: 11px;
}

kbd {
    background: #222a36;
    border: 1px solid var(--line);
    border-radius: 3px;
    padding: 0 4px;
    font-size: 11px;
}

/* Place page (the no-JS path) */
.page { max-width: 720px; margin: 0 auto; padding: 32px 20px; }
.page h1 { margin-bottom: 0; }
.page ul { padding-left: 18px; }
.page li { margin: 4px 0; }
.nocoord { color: var(--dim); }
.page .yr { color: var(--hot); font-variant-numeric: tabular-nums; font-size: 13px; }
.page .dead { color: var(--dead); font-size: 12px; }
