/* bass-family.nodejavascript.com — the site's own identity.
 *
 * Theme colour #0e7490, background #04141c (a near-black of the same hue), and a
 * drawing of overlapping rings — fish scales — on its own masked layer. All four of
 * the identity values are unique in the fleet; the counts are 3 radial + 3 linear.
 *
 * Two rules from the house standard are load-bearing here and are marked:
 *   [hidden] must win over a class that declares display  (see [hidden] below)
 *   the sticky bar must span the VIEWPORT, so <body> carries no padding
 */

:root {
  --theme: #0e7490;
  --theme-bright: #22b8d8;
  --bg: #04141c;
  --panel: #072430;
  --text: #dceaf0;
  --text-muted: #8aa8b6;
  --hairline: #16404f;
  --yellow: #fbbf24;
  --container: 1080px;
  --consent-height: 0px;
}

* { box-sizing: border-box; }

/* 🔴 The user-agent rule for [hidden] is a DEFAULT, so any author rule that declares
   display (here .consentAsk { display:flex }) would beat it and leave the question on
   screen underneath its own settings panel. This line is required, not decorative. */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* No padding on the body: the sticky bar has to reach both edges of the viewport, and a
   body padding would inset it. The column below carries its own inset. */
body {
  margin: 0;
  padding: 0 0 var(--consent-height);
  background-color: var(--bg);
  background-image:
    radial-gradient(ellipse 70% 50% at 12% -5%, rgba(14, 116, 144, 0.30), transparent 60%),
    radial-gradient(ellipse 60% 45% at 88% 8%, rgba(34, 184, 216, 0.16), transparent 62%),
    radial-gradient(ellipse 90% 60% at 50% 108%, rgba(14, 116, 144, 0.22), transparent 70%),
    linear-gradient(168deg, rgba(4, 20, 28, 0) 0%, rgba(7, 36, 48, 0.55) 48%, rgba(4, 20, 28, 0) 100%),
    linear-gradient(102deg, rgba(14, 116, 144, 0.10) 0%, rgba(4, 20, 28, 0) 40%, rgba(34, 184, 216, 0.07) 100%),
    linear-gradient(180deg, rgba(4, 20, 28, 0) 55%, rgba(2, 12, 18, 0.6) 100%);
  background-attachment: fixed;
  color: var(--text);
  font: 16px/1.65 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial,
    sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* The drawing: a dot matrix — a grid of dots with a second, smaller and fainter dot set
   between them, so it reads as a screened field rather than as graph paper. Masked so it
   dissolves rather than stopping at an edge. Its own fixed layer, below the content.
   🔴 THIS IS THE SITE'S ABSTRACT AND IT IS PART 5d-ii OF THE HOUSE RULES: every site paints
   one of its own, and it must be a drawing rather than a gradient wash — a wash is what nine
   of ten sites shipped while the checker called them compliant. The two dot sets are on the
   SAME 20px lattice with the second offset half a cell, which is what makes them interleave;
   two different pitches would moiré instead. */
.dvs-pattern {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(circle at 50% 50%, rgba(34, 184, 216, 0.15) 0 2.1px, transparent 2.3px),
    radial-gradient(circle at 50% 50%, rgba(14, 116, 144, 0.22) 0 1.2px, transparent 1.4px);
  background-size: 20px 20px;
  background-position: 0 0, 10px 10px;
  /* 🔴 PULLED AWAY FROM THE TOP LEFT, WHERE THE INTRO IS. The pattern is a texture, and a texture
     under a paragraph is noise: concentrating the fade around the hero rather than over the lede
     keeps the words clean and still lets the lattice read at the edges. */
  -webkit-mask-image: radial-gradient(ellipse 96% 58% at 50% 34%, #000 0%, rgba(0, 0, 0, 0.4) 62%, transparent 88%);
  mask-image: radial-gradient(ellipse 96% 58% at 50% 34%, #000 0%, rgba(0, 0, 0, 0.4) 62%, transparent 88%);
}

.top,
main,
.site-footer { position: relative; z-index: 1; }

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--theme);
  color: #04141c;
  padding: 10px 16px;
  z-index: 20;
}
.skip:focus { left: 8px; top: 8px; }
/* ── The map ──────────────────────────────────────────────────────────────── */
/* The map lives inside the detail card, so it needs no box of its own — the card is the box.
   It spans the full width under everything else, because the readable answer ("this is what
   it is, this is the water, these are the places") belongs at the top and the picture of the
   range belongs beneath it. */
.detail-map {
  grid-column: 1 / -1;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--hairline);
}
.detail-map .aside { max-width: 76ch; }
.worldmap {
  display: block;
  width: 100%;
  /* height comes from the viewBox's own 2:1 ratio, which is set in the markup before any
     script runs — so the box is reserved from the first paint and nothing jumps. */
  height: auto;
}

.worldmap .graticule line { stroke: #10323f; stroke-width: 0.6; }
.worldmap .landmass { fill: #0a1e28; stroke: none; }
.worldmap .coastline { fill: none; stroke: #24596b; stroke-width: 0.8; }

.worldmap .region path {
  fill: transparent;
  transition: fill 0.2s;
}
.worldmap .region.sea path { fill: rgba(75, 147, 196, 0.06); }
.worldmap .region.land path { fill: rgba(78, 201, 160, 0.06); }

/* the selected family's range */
.worldmap .region.on path { fill: rgba(34, 184, 216, 0.42); }
.worldmap .region.sea.on path { fill: rgba(34, 184, 216, 0.34); }
.worldmap .region.land.on path { fill: rgba(78, 201, 160, 0.42); }

.map-caption {
  margin: 14px 0 0;
  font-size: 13.5px;
  color: var(--text);
}
/* ── The bar ───────────────────────────────────────────────────────────────── */
.top {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 12px 20px;
  background: rgba(4, 20, 28, 0.82);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--hairline);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  color: inherit;
  text-decoration: none;
}
.brand .mark { display: flex; }
.brand svg { width: 26px; height: 26px; }
.brand b {
  display: block;
  font-size: 15px;
  font-weight: 650;
  letter-spacing: 0.2px;
  line-height: 1.1;
}
.brand small {
  display: block;
  font-size: 11.5px;
  letter-spacing: 0.4px;
  line-height: 1.1;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* ── The column ────────────────────────────────────────────────────────────── */
main {
  max-width: var(--container);
  margin: 0 auto;
  padding: 32px 20px 60px;
}

.hero { padding: 26px 0 8px; }
.eyebrow {
  margin: 0 0 10px;
  font-size: 12.5px;
  letter-spacing: 0.9px;
  text-transform: uppercase;
  color: var(--theme-bright);
}
h1 {
  margin: 0 0 18px;
  font-size: clamp(2rem, 5.5vw, 3.35rem);
  line-height: 1.06;
  letter-spacing: -1px;
  font-weight: 700;
}
.lede {
  margin: 0;
  max-width: 68ch;
  font-size: 1.075rem;
  color: #c2d8e2;
}

.hero-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin: 30px 0 0;
  padding: 0;
  list-style: none;
}

.hero-stats li {
  background: linear-gradient(180deg, rgba(14, 116, 144, 0.16), rgba(7, 36, 48, 0.32));
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 14px 16px;
}
.hero-stats b {
  display: block;
  font-size: 1.75rem;
  line-height: 1.1;
  color: var(--theme-bright);
  font-variant-numeric: tabular-nums;
}
.hero-stats span { font-size: 12.5px; color: var(--text-muted); }

/* The denominator under the species count. Quieter than the lede, because it is a correction to a
   number rather than a thing to read first — but not hidden, because the number is wrong without
   it. Tabular figures so the counts do not shuffle as they fill in. */
.hero-note {
  margin: 14px 0 0;
  max-width: 68ch;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-muted);
}
.hero-note span { color: var(--text); font-variant-numeric: tabular-nums; }

.block { margin-top: 58px; scroll-margin-top: 84px; }

h2 {
  margin: 0 0 14px;
  font-size: 1.5rem;
  letter-spacing: -0.3px;
}
.block > p { max-width: 72ch; color: #c2d8e2; }
.block > p:first-of-type { margin-top: 0; }

.aside {
  margin-top: 16px;
  padding-left: 14px;
  border-left: 2px solid var(--theme);
  font-size: 0.94rem;
  color: var(--text-muted);
}

/* ── The shape ─────────────────────────────────────────────────────────────── */
.traits { margin: 20px 0 0; padding: 0; list-style: none; display: grid; gap: 10px; }
.traits li {
  padding: 12px 16px;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  background: rgba(7, 36, 48, 0.34);
  color: #c2d8e2;
}
.traits b { color: var(--text); }

/* ── The tree ──────────────────────────────────────────────────────────────── */
.tree-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 22px 0 14px;
}
.filter { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  font: inherit;
  font-size: 13.5px;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1px solid var(--hairline);
  background: rgba(7, 36, 48, 0.5);
  color: var(--text-muted);
  cursor: pointer;
}
.chip:hover { color: var(--text); border-color: var(--theme); }
.chip.is-on {
  background: var(--theme);
  border-color: var(--theme);
  color: #04141c;
  font-weight: 600;
}
.chip:focus-visible,
.linkish:focus-visible,
a:focus-visible { outline: 2px solid var(--theme-bright); outline-offset: 2px; }

.legend {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 12.5px;
  color: var(--text-muted);
}
.sw { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.sw + .legend, .legend .sw { margin-right: 2px; }
.sw-marine { background: #4b93c4; }
.sw-freshwater { background: #4ec9a0; }
.sw-both { background: linear-gradient(90deg, #4b93c4 50%, #4ec9a0 50%); }
.legend .sw:not(:first-child) { margin-left: 10px; }

.tree-wrap {
  border: 1px solid var(--hairline);
  border-radius: 14px;
  background: rgba(4, 20, 28, 0.55);
  padding: 14px 10px;
  overflow-x: auto;
}
.cladogram { display: block; min-width: 720px; width: 100%; height: auto; }

.cladogram .branch { fill: none; stroke: #1d5567; stroke-width: 1.25; }
.cladogram .node-label {
  font: 13px ui-sans-serif, system-ui, sans-serif;
  fill: var(--text);
  cursor: pointer;
}
.cladogram .node-label.clade {
  font-size: 12.5px;
  font-weight: 650;
  fill: var(--text);
  letter-spacing: 0.2px;
}
.cladogram .node-label.family { fill: var(--text); }
.cladogram .node-label .sub {
  font-size: 10.5px;
  fill: var(--text-muted);
}
.cladogram .tick { stroke-width: 3; stroke-linecap: round; }
.cladogram .tick.marine { stroke: #4b93c4; }
.cladogram .tick.freshwater { stroke: #4ec9a0; }
.cladogram .tick.both { stroke: #8fd6c2; }
.cladogram .hit { cursor: pointer; fill: transparent; }
.cladogram .thumb-ground { fill: #0d2129; }
.cladogram .thumb-frame { fill: none; stroke: var(--hairline); stroke-width: 0.8; }
/* 🔴 SCOPED TO THE ROW, NOT TO ANY `g`. The rows live inside a layer that is itself a `<g>`,
   so `.cladogram g:hover` made the LAYER count as hovered and every label inside it matched —
   measured, one hover recoloured 42 of 55 labels. `g:hover` matched two elements: the row and
   the layer holding all thirty-four of them. */
.cladogram g[data-node]:hover .thumb-frame { stroke: var(--theme); }
.cladogram g[data-dim="1"] { opacity: 0.16; transition: opacity 0.2s; }
.cladogram g[data-dim="0"] { opacity: 1; transition: opacity 0.2s; }
.cladogram g[data-node]:hover .node-label { fill: var(--theme-bright); }
.cladogram g.is-sel .node-label { fill: var(--yellow); }
.cladogram g.is-sel .branch { stroke: var(--yellow); }

/* ── the hover card ─────────────────────────────────────────────────────────── */
/* The quick look at a row: the fish, and every common name pictured under it. It carries no
   map — the big map and the cards below already do that, and a third one here would only
   repeat them. Anchored to the row it describes, so it is always clear which one it is. */
.hovercard {
  position: fixed;
  z-index: 60;
  /* 🔴 THE WIDTH IS WHAT MAKES THE WRAP HAPPEN. With ten short names and a photograph, a wide
     card lets every name sit beside the picture and nothing ever reaches under it — measured,
     at 430px not one name fell below the photograph and the card was a row of text beside a
     photo. At 330px the names run past the bottom of the picture and continue underneath it,
     at a cost of 40px of height. */
  width: 330px;
  max-width: calc(100vw - 24px);
  max-height: 70vh;
  /* 🔴 VERTICALLY, NEVER SIDEWAYS. A hover card on a diagram is anchored to a row, and a
     sideways scrollbar inside it is a control nobody can use with the pointer they are
     already using. Anything too long wraps instead. */
  overflow-y: auto;
  overflow-x: hidden;
  padding: 11px 13px 13px;
  border: 1px solid var(--theme);
  border-radius: 13px;
  background: #06202b;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
  /* the card is a picture and some text — nothing in it is a target, so nothing in it should
     take the pointer away from the tree underneath it */
  pointer-events: none;
}

/* 🔴 THE PICTURE FLOATS, SO THE NAMES RUN BESIDE IT AND THEN UNDER IT. A flex row would trap
   every name in a narrow column beside the picture and never let one start below it. */
.hovercard img {
  float: left;
  display: block;
  width: 150px;
  height: auto;
  margin: 0 12px 8px 0;
  aspect-ratio: 16 / 10;
  object-fit: contain;
  background: #0d2129;
  border-radius: 8px;
}
.hovercard .hc-who {
  display: block;
  margin-bottom: 8px;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.hovercard .hc-who b { color: var(--theme-bright); }
.hovercard .hc-names {
  /* stated rather than inherited: a bare `.names` on this page is a grid, and this is not one */
  display: block;
  margin: 0;
  font-size: 12.8px;
  line-height: 1.5;
  color: var(--text);
  overflow-wrap: break-word;
}
.hovercard .hc-more {
  clear: both;
  margin: 8px 0 0;
  font-size: 11.5px;
  color: var(--text-muted);
}

.detail {
  margin-top: 16px;
  border: 1px solid var(--hairline);
  border-left: 3px solid var(--theme);
  border-radius: 12px;
  background: rgba(7, 36, 48, 0.42);
  padding: 18px 20px;
  min-height: 108px;
}
.detail-empty { margin: 0; color: var(--text-muted); }
.detail h3 { margin: 0 0 2px; font-size: 1.15rem; }
.detail .rank { margin: 0 0 10px; font-size: 12.5px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; }
.detail p { margin: 0 0 10px; max-width: 74ch; color: #c2d8e2; }
.detail dl { display: flex; flex-wrap: wrap; gap: 6px 22px; margin: 12px 0 0; font-size: 13.5px; }
.detail dt { color: var(--text-muted); white-space: nowrap; }
.detail dd { margin: 0 0 0 6px; color: var(--text); }
.detail dl > div { display: flex; gap: 6px; }
.hab { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px; }
.hab.marine { background: rgba(75, 147, 196, 0.2); color: #8ec4e8; }
.hab.freshwater { background: rgba(78, 201, 160, 0.18); color: #7fdcc0; }
.hab.both { background: rgba(143, 214, 194, 0.16); color: #a9e2d3; }

/* ── every fish on the branch, under the facts in the detail card ──────────── */
.detail-fish { margin-top: 16px; }
.detail-fish-head {
  margin: 0 0 8px;
  font-size: 12.5px;
  color: var(--text-muted);
  max-width: 74ch;
}
.detail-fish-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 8px;
  /* 🔴 CAPPED AND SCROLLED WITHIN, NOT LEFT TO GROW. Every fish is still here — but an uncapped
     strip made the panel 1,500 pixels tall for one family and several thousand for a clade, so
     the document grew on every click and the page lurched under the reader. Measured 4 October
     2026: walking the tree row by row, the next row ended up under the sticky header because
     the previous click had pushed the page down. The count in the heading is what says the list
     is complete; the cap is what keeps the page still. */
  max-height: 336px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-gutter: stable;
  padding-right: 4px;
}
.detail-fish-card {
  display: grid;
  grid-template-rows: 72px auto;
  padding: 0;
  border: 1px solid var(--hairline);
  border-radius: 9px;
  background: rgba(4, 20, 28, 0.55);
  color: var(--text-muted);
  font: inherit;
  font-size: 11.5px;
  line-height: 1.25;
  text-align: center;
  cursor: pointer;
  overflow: hidden;
}
.detail-fish-card img { width: 100%; height: 72px; object-fit: cover; display: block; }
.detail-fish-card span { padding: 5px 5px 7px; }
.detail-fish-card:hover { border-color: var(--theme-bright); color: var(--text); }
.detail-fish-card:focus-visible { outline: 2px solid var(--theme-bright); outline-offset: 2px; }
/* 🔴 WHERE THE READER LANDED. A smooth scroll of several thousand pixels ends on a card the
   eye still has to find; this says "here" without moving anything. The square is outlined
   permanently so the answer survives the animation — and survives `prefers-reduced-motion`,
   where the outline is the whole cue. */
.detail-fish-card.is-current {
  border-color: var(--theme-bright);
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--theme-bright);
}
#fish-grid button.is-picked { outline: 3px solid var(--theme-bright); outline-offset: 3px; }

/* ── arriving on a fish you clicked ────────────────────────────────────────── */
@keyframes picked-ring {
  0%   { outline: 3px solid rgba(34, 184, 216, 0); outline-offset: 4px; }
  18%  { outline: 3px solid rgba(34, 184, 216, 0.95); outline-offset: 6px; }
  100% { outline: 3px solid rgba(34, 184, 216, 0); outline-offset: 16px; }
}
@keyframes picked-pop {
  from { opacity: 0.25; transform: scale(0.97); }
  to   { opacity: 1; transform: none; }
}
@keyframes picked-edge {
  from { border-left-color: var(--theme-bright); box-shadow: 0 0 0 5px rgba(34, 184, 216, 0.16); }
  to   { border-left-color: var(--theme); box-shadow: 0 0 0 0 rgba(34, 184, 216, 0); }
}

.detail.just-picked { animation: picked-edge 1700ms ease-out 1; }
.detail.just-picked > .photo {
  border-radius: 12px;
  animation: picked-ring 1700ms ease-out 1;
}
.detail.just-picked > .photo img { animation: picked-pop 700ms ease-out 1; }

/* Somebody who has asked for less motion still gets told which fish arrived — the marked
   square and the panel's own heading carry it. Only the movement goes. */
@media (prefers-reduced-motion: reduce) {
  .detail.just-picked,
  .detail.just-picked > .photo,
  .detail.just-picked > .photo img { animation: none; }
  .detail.just-picked > .photo { outline: 3px solid var(--theme-bright); outline-offset: 6px; }
}

/* ── questions people ask ──────────────────────────────────────────────────── */
/* The three questions the FAQPage markup answers. Ordinary prose on purpose — they are a section
   of the page, not a widget. They are also the only headings here that read like a query, which
   matters on a site whose title is the hostname and so carries no query at all. */
.qa h3 { margin: 20px 0 6px; font-size: 1.03rem; font-weight: 600; }
.qa h3:first-child { margin-top: 0; }
.qa p { margin: 0; max-width: 74ch; color: #c2d8e2; }

/* ── Photographs ───────────────────────────────────────────────────────────── */
.detail.has-photo {
  display: grid;
  grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
  gap: 22px;
  align-items: start;
}

.photo { margin: 0; }
.photo img {
  display: block;
  width: 100%;
  height: auto;
  /* 🔴 FITTED, NEVER CROPPED. `cover` cut the head or the tail off a wide fish and made the
     whole page useless for the one thing it is for — comparing one fish with another. The
     box is a fixed shape so the grid stays even; the photograph is not touched. */
  aspect-ratio: 16 / 10;
  object-fit: contain;
  border-radius: 10px;
  background: #0d2129;
}
.photo figcaption {
  margin-top: 9px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-muted);
}
.photo figcaption b { color: var(--text); font-weight: 600; }
.photo figcaption i { font-style: italic; }
.photo figcaption a { color: var(--theme-bright); }

.fish-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
  /* more room down the page than across it — the cards are what the reader is scanning */
  gap: 28px 16px;
  margin-top: 22px;
}
.fish {
  font: inherit;
  text-align: left;
  padding: 0;
  border: 1px solid var(--hairline);
  border-radius: 13px;
  background: rgba(7, 36, 48, 0.42);
  color: inherit;
  overflow: hidden;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  transition: border-color 0.15s, transform 0.15s;
}
.fish:hover { border-color: var(--theme); transform: translateY(-2px); }
.fish img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: contain;
  background: #0d2129;
}
.fish-body { display: block; padding: 12px 14px 14px; }
.fish-body b { display: block; font-size: 1rem; }
.fish-body i { display: block; font-size: 12.5px; color: var(--theme-bright); }
.fish-family {
  display: block;
  margin-top: 5px;
  font-size: 11.5px;
  letter-spacing: 0.3px;
  color: var(--text-muted);
}
.fish-body small {
  display: block;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--hairline);
  font-size: 11.5px;
  line-height: 1.45;
  color: #7d9aa8;
}

/* A card the filter has excluded. `hidden` alone loses to the grid's display rule, so the
   card is taken out of the grid explicitly rather than left as a gap. */
.fish[hidden] { display: none; }

.fish-tools {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 22px;
}
.filter-note {
  margin: 0;
  font-size: 12.5px;
  color: var(--text-muted);
}

/* ── the map on a fish card ─────────────────────────────────────────────────── */
/* The coastline is borrowed from the shared defs through <use>, so the same path serves
   every card. Only the regions that fish's family touches are drawn — at this size the
   other seventeen would be noise. */
.mini {
  display: block;
  width: 100%;
  height: auto;
  margin-top: auto;
  border-top: 1px solid var(--hairline);
}
.mini-sea { fill: #061a22; }
.mini .region path { stroke: rgba(34, 184, 216, 0.35); stroke-width: 0.8; }
.mini .region.sea path { fill: rgba(75, 147, 196, 0.45); }
.mini .region.land path { fill: rgba(78, 201, 160, 0.45); }

/* the shared coastline is defined here, out of the page flow */
#map-defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

h3.sub {
  margin: 30px 0 8px;
  font-size: 1.05rem;
  color: var(--text);
}
.credits {
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 7px;
  font-size: 13px;
  color: var(--text-muted);
}
.credits li {
  padding-left: 14px;
  border-left: 2px solid var(--hairline);
  line-height: 1.55;
}
.credits b { color: var(--text); font-weight: 600; }
.credits a { color: var(--theme-bright); }
.credits .credit-where { display: block; color: #6f8c9a; }

/* ── Crossings ─────────────────────────────────────────────────────────────── */
.crossings { margin: 20px 0 0; padding: 0; list-style: none; display: grid; gap: 12px; }
.crossings li {
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: rgba(7, 36, 48, 0.34);
  padding: 14px 18px;
}
.crossings h3 { margin: 0 0 2px; font-size: 1rem; }
.crossings .when { font-size: 12.5px; color: var(--theme-bright); letter-spacing: 0.3px; }
.crossings p { margin: 8px 0 0; color: #c2d8e2; font-size: 0.95rem; }
.crossings .ev { margin-top: 8px; font-size: 0.9rem; color: var(--text-muted); }
.crossings .ev b { color: #a9c4d0; font-weight: 600; }

/* ── Names ─────────────────────────────────────────────────────────────────── */
.names {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(272px, 1fr));
  gap: 20px;
  margin-top: 22px;
}
.names h3 { margin: 0 0 10px; font-size: 0.95rem; letter-spacing: 0.4px; text-transform: uppercase; color: var(--text-muted); }
.names ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.names li {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 9px 13px;
  border-radius: 9px;
  border: 1px solid var(--hairline);
  background: rgba(7, 36, 48, 0.34);
  font-size: 0.94rem;
}
.names .tick { font-weight: 700; flex: none; }
.names .kin .tick { color: #4ec9a0; }
.names .notkin .tick { color: #4b93c4; }
.names .fam { display: block; font-size: 12px; color: var(--text-muted); }

/* The same argument for five more words. One row per word: the word and the family it actually
   belongs to on the left, the fish wearing it on the right. The fish are BUTTONS, because the
   answer to "this is called a perch" is "here is where it really sits", and that is a click. */
.borrowed { margin-top: 26px; display: grid; gap: 16px; }
.borrowed-row {
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 14px 16px;
  background: rgba(7, 36, 48, 0.3);
}
.borrowed-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.borrowed-head b { font-size: 1.05rem; color: var(--theme-bright); }
.borrowed-head .home { font-size: 12.5px; color: var(--text-muted); }
.borrowed ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.borrowed-fish {
  display: flex;
  align-items: baseline;
  gap: 10px;
  width: 100%;
  text-align: left;
  padding: 8px 12px;
  border-radius: 9px;
  border: 1px solid transparent;
  background: rgba(4, 20, 28, 0.45);
  color: var(--text);
  font: inherit;
  font-size: 0.93rem;
  cursor: pointer;
}
.borrowed-fish:hover { border-color: var(--theme-bright); }
.borrowed-fish[disabled] { cursor: default; opacity: 0.75; }
.borrowed-fish .tick { font-weight: 700; flex: none; }
.borrowed .is-home .tick { color: #4ec9a0; }
.borrowed .is-away .tick { color: #4b93c4; }
.borrowed-fish .fam { display: block; font-size: 12px; color: var(--text-muted); }
.borrowed-fish .also { display: block; font-size: 12px; color: var(--text-muted); font-style: italic; }

/* ── Sources ───────────────────────────────────────────────────────────────── */
.sources { margin: 20px 0 0; padding: 0; list-style: none; display: grid; gap: 12px; }
.sources li {
  border: 1px solid var(--hairline);
  border-radius: 10px;
  padding: 13px 16px;
  background: rgba(7, 36, 48, 0.3);
}
.sources a { color: var(--theme-bright); }
.sources .note { display: block; margin-top: 4px; font-size: 13px; color: var(--text-muted); }

a { color: var(--theme-bright); }

/* ── The footer ────────────────────────────────────────────────────────────── */
.site-footer {
  border-top: 1px solid var(--hairline);
  background: rgba(4, 20, 28, 0.6);
  padding: 30px 20px 40px;
  max-width: var(--container);
  margin: 0 auto;
}
.footer-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  color: var(--text-muted);
}
.footer-brand .mark { display: flex; }
.footer-brand svg { width: 22px; height: 22px; }
.footer-brand b { color: var(--text); }
.footer-links {
  margin: 0 0 10px;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  font-size: 13.5px;
  color: var(--text-muted);
}
.footer-copy { margin: 0; font-size: 12.5px; color: var(--text-muted); }

.linkish {
  font: inherit;
  font-size: 13.5px;
  background: none;
  border: 0;
  padding: 0;
  color: var(--theme-bright);
  cursor: pointer;
  text-decoration: underline;
}

/* ── The cookie gate ───────────────────────────────────────────────────────── */
.consentAsk,
.consentPrefs {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  background: rgba(4, 20, 28, 0.97);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--hairline);
  padding: 18px 20px;
  box-shadow: 0 -12px 34px rgba(0, 0, 0, 0.45);
}
.consentAsk { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; justify-content: space-between; }
.consentAsk p { margin: 0; max-width: 62ch; font-size: 14px; color: #c2d8e2; }
.consentAsk .btns { display: flex; gap: 10px; flex: none; }
.consentAsk button {
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  padding: 10px 20px;
  border-radius: 9px;
  border: 1px solid var(--theme);
  background: var(--theme);
  color: #04141c;
  cursor: pointer;
  min-width: 132px;
}
.consentAsk button.reject { background: transparent; color: var(--text); }
.consentPrefs .inner { max-width: var(--container); margin: 0 auto; }
.consentPrefs h2 { margin: 0 0 12px; font-size: 1.05rem; }
.consentPrefs label { display: flex; align-items: flex-start; gap: 10px; font-size: 14px; max-width: 66ch; }
.consentPrefs input { margin-top: 4px; flex: none; }
.consentPrefs .btns { display: flex; gap: 10px; margin-top: 16px; }
.consentPrefs .btns button {
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  padding: 9px 18px;
  border-radius: 9px;
  border: 1px solid var(--theme);
  background: var(--theme);
  color: #04141c;
  cursor: pointer;
}
.consentPrefs .btns button.ghost { background: transparent; color: var(--text); }

@media (max-width: 720px) {
  .detail.has-photo { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 620px) {
  .consentAsk .btns { width: 100%; }
  .consentAsk button { flex: 1; min-width: 0; }
  .cladogram { min-width: 640px; }
}
