/* GrowNativePlants directory.
   One stylesheet, no framework, no webfont, no external request. Colours are
   named once as tokens so the dark theme is a token swap rather than a second
   sheet. */

:root {
  --bg: #fbfaf7;
  --bg-sunk: #f3f1ea;
  --card: #ffffff;
  --fg: #1f2119;
  --fg-soft: #4a4d43;
  --muted: #737667;
  --line: #e2dfd4;
  --line-firm: #cfcbbc;
  --accent: #3f5c31;
  --accent-soft: #eaf0e3;
  --accent-fg: #ffffff;
  --star: #a8761a;
  --shadow: 0 1px 2px rgba(31, 33, 25, .05), 0 6px 18px rgba(31, 33, 25, .05);
  --radius: 10px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #14160f;
    --bg-sunk: #1b1e16;
    --card: #1e2119;
    --fg: #eceadf;
    --fg-soft: #c3c2b5;
    --muted: #8f9284;
    --line: #2f332a;
    --line-firm: #454a3c;
    --accent: #9dc07d;
    --accent-soft: #232a1c;
    --accent-fg: #10130c;
    --star: #dfb45a;
    --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 6px 20px rgba(0, 0, 0, .28);
  }
}

:root[data-theme="dark"] {
  --bg: #14160f;
  --bg-sunk: #1b1e16;
  --card: #1e2119;
  --fg: #eceadf;
  --fg-soft: #c3c2b5;
  --muted: #8f9284;
  --line: #2f332a;
  --line-firm: #454a3c;
  --accent: #9dc07d;
  --accent-soft: #232a1c;
  --accent-fg: #10130c;
  --star: #dfb45a;
  --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 6px 20px rgba(0, 0, 0, .28);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 400 17px/1.65 "Iowan Old Style", "Palatino Linotype", Palatino,
        "Book Antiqua", Georgia, serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: inherit; text-decoration-color: var(--line-firm); }
a:hover { text-decoration-color: var(--accent); }

.skip {
  position: absolute; left: -9999px; background: var(--accent);
  color: var(--accent-fg); padding: .6rem 1rem; z-index: 20;
}
.skip:focus { left: .5rem; top: .5rem; }

main { max-width: 47rem; margin: 0 auto; padding: 2rem 1.25rem 5rem; }
main.wide { max-width: 78rem; }

/* ── Header ─────────────────────────────────────────────────────────────── */

.top {
  display: flex; flex-wrap: wrap; gap: .5rem 1.5rem;
  align-items: center; justify-content: space-between;
  padding: .85rem 1.5rem;
  border-bottom: 1px solid var(--line);
  background: var(--bg);
  position: sticky; top: 0; z-index: 10;
  backdrop-filter: saturate(140%) blur(6px);
}
.brand {
  display: inline-flex; align-items: baseline; gap: .5rem;
  text-decoration: none; letter-spacing: .01em;
}
.brand-mark {
  width: .7rem; height: .7rem; border-radius: 50%;
  background: var(--accent); align-self: center;
}
.brand-name { font-weight: 600; }
.brand-sub {
  color: var(--muted); font-size: .82rem; letter-spacing: .06em;
  text-transform: uppercase;
}
.top nav { display: flex; gap: 1.15rem; flex-wrap: wrap; }
.top nav a {
  color: var(--muted); text-decoration: none;
  font-size: .82rem; letter-spacing: .04em; text-transform: uppercase;
  padding: .15rem 0; border-bottom: 1px solid transparent;
}
.top nav a:hover { color: var(--fg); border-bottom-color: var(--accent); }

/* ── Type ───────────────────────────────────────────────────────────────── */

h1 { font-size: clamp(1.7rem, 1.2rem + 1.8vw, 2.5rem); line-height: 1.18;
     margin: .5rem 0 .7rem; font-weight: 600; letter-spacing: -.01em; }
h2 { font-size: 1.3rem; margin: 2.4rem 0 .6rem; font-weight: 600;
     letter-spacing: -.005em; }
h3 { font-size: .95rem; margin: 1.4rem 0 .35rem; color: var(--muted);
     font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
p { margin: .7rem 0; }
.lede { font-size: 1.08rem; color: var(--fg-soft); max-width: 42rem; }
.kicker {
  color: var(--accent); font-size: .78rem; letter-spacing: .12em;
  text-transform: uppercase; margin: 0; font-weight: 600;
}
.src, .credit, .count, .fnote { color: var(--muted); font-size: .84rem; }
.morph { color: var(--fg-soft); font-size: .95rem; font-style: italic; }
.note {
  color: var(--muted); font-size: .89rem;
  border-left: 2px solid var(--line-firm); padding: .15rem 0 .15rem .8rem;
  margin: .8rem 0;
}
.empty { color: var(--muted); }

.crumb { font-size: .84rem; color: var(--muted); margin: 0 0 .3rem;
         display: flex; flex-wrap: wrap; gap: .4rem; }
.crumb .sep { opacity: .5; }
.crumb a { text-decoration: none; }
.crumb a:hover { text-decoration: underline; }

/* ── Hero and figures ───────────────────────────────────────────────────── */

.hero { padding: 1rem 0 .5rem; }
.hero h1 { max-width: 26ch; }
.cta { display: flex; gap: .6rem; flex-wrap: wrap; margin: 1.4rem 0; }
.button {
  display: inline-block; background: var(--accent); color: var(--accent-fg);
  padding: .6rem 1.15rem; border-radius: var(--radius); text-decoration: none;
  font-size: .95rem; font-weight: 600; border: 1px solid var(--accent);
}
.button:hover { filter: brightness(1.08); }
.button.ghost { background: transparent; color: var(--fg);
                border-color: var(--line-firm); }
.more { font-size: .92rem; }

.figures {
  display: grid; gap: .8rem; margin: 2rem 0 0;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  border-top: 1px solid var(--line); padding-top: 1.2rem;
}
.figures div { margin: 0; }
.figures dt { color: var(--muted); font-size: .78rem; letter-spacing: .04em;
              text-transform: uppercase; }
.figures dd { margin: .15rem 0 0; font-size: 1.5rem; font-weight: 600;
              font-variant-numeric: tabular-nums; }

.split {
  display: grid; gap: 1.6rem; align-items: center;
  grid-template-columns: 1fr minmax(16rem, 22rem);
  margin-top: 2.6rem;
}
.pitch {
  background: var(--accent-soft); border-radius: var(--radius);
  padding: 1.4rem 1.5rem; margin-top: 2.8rem;
}
.pitch h2 { margin-top: 0; }

.mapfig { margin: 0; background: var(--bg-sunk); border: 1px solid var(--line);
          border-radius: var(--radius); padding: .7rem; }
.mapfig.inline { max-width: 24rem; }
.wide-map { padding: 1.2rem; }
.ecomap { display: block; width: 100%; height: auto; }
/* Alberta and Saskatchewan are nearly square, so a map that fills a wide page
   is also about as tall as the page. Cap it and centre it: past this size the
   drawing gains nothing, it just pushes the legend below the fold. */
.wide-map .ecomap { max-width: 40rem; margin: 0 auto; }
/* Neighbouring land, in grey and a shade darker than the subject provinces, so
   BC / MT / NT / MB read as "context, not classified" rather than as a seventh
   ecoregion. Before V2.66 they were absent and the two provinces floated. */
.ecomap-context { fill: #d7d6cd; stroke: #c6c5bb; stroke-width: .4; }
/* Every province and state in the window, unioned, painted first. Catches the
   hairline gaps that independent simplification leaves on shared borders. */
.ecomap-land { fill: #d7d6cd; stroke: none; }
/* Alberta and Saskatchewan: the wash the ecoregion fills sit on. Visible only
   where a fill does not reach, which is now a real question rather than a
   rhetorical one: the fills come from data with gaps in it. */
.ecomap-prov { fill: #eceada; stroke: none; }
.ecomap-region { stroke: #8b8878; stroke-width: .5; stroke-opacity: .55; }
/* Water, drawn over the fills. A river that disappears under a polygon is
   worse than no river: it reads as a rendering bug rather than a boundary. */
.ecomap-lake { fill: #b9cfdd; stroke: #93b3c6; stroke-width: .4; }
.ecomap-river {
  stroke: #93b3c6; stroke-width: .9; stroke-opacity: .9;
  stroke-linecap: round; stroke-linejoin: round;
}
/* The hatch is the second channel for regions whose colour alone does not
   separate from a neighbour under colour-vision deficiency. It never replaces
   the fill; it sits over it. See src/ecoregion_palette.py:HATCHED. */
.ecomap-hatch { stroke: none; pointer-events: none; }
.ecomap-border {
  fill: none; stroke: #6d6a5e; stroke-width: 1.1; stroke-opacity: .85;
  stroke-linejoin: round;
}
.ecomap-city { fill: #2b2d24; stroke: #fff; stroke-width: .8; }
.ecomap-place {
  font: 500 8.5px/1 ui-sans-serif, system-ui, sans-serif;
  fill: #2b2d24; pointer-events: none; paint-order: stroke;
  stroke: rgba(255,255,255,.75); stroke-width: 2.2px;
}
/* The province codes sit on the boreal fill, which is dark. They carry the
   same halo the city labels do, or AB and SK disappear into the green. */
.ecomap-prov-label {
  font: 700 13px/1 ui-sans-serif, system-ui, sans-serif;
  fill: #5c5a4f; letter-spacing: .14em; pointer-events: none; opacity: .9;
  paint-order: stroke; stroke: rgba(255,255,255,.6); stroke-width: 3px;
}
.ecomap-label {
  font: 600 9.5px/1 ui-sans-serif, system-ui, sans-serif;
  fill: #4a4a42; letter-spacing: .03em; pointer-events: none;
  paint-order: stroke; stroke: rgba(255,255,255,.7); stroke-width: 2.4px;
}
/* Region names sit on their own colour now, so the halo does the legibility
   work and the fill only has to be dark enough to read against six hues. */
.ecomap-label.on { fill: #23261d; stroke: rgba(255,255,255,.85);
                   stroke-width: 2.8px; }

/* The colour key. Markup rather than SVG so it wraps on a phone. */
.ecokey {
  display: flex; flex-wrap: wrap; gap: .3rem .9rem; margin-top: .8rem;
  padding-top: .7rem; border-top: 1px solid rgba(0,0,0,.09);
}
.ecokey-item {
  display: inline-flex; align-items: baseline; gap: .38rem;
  font-size: .82rem; color: #3c3f33; text-decoration: none;
  padding: .12rem .2rem; border-radius: 5px;
}
a.ecokey-item:hover { background: rgba(0,0,0,.06); }
.ecokey-item.on { font-weight: 600; }
.ecokey-sw {
  width: .78rem; height: .78rem; border-radius: 3px; flex: none;
  align-self: center; box-shadow: inset 0 0 0 1px rgba(0,0,0,.18);
}
.ecokey-where { color: #7a7d6e; font-size: .76rem; }
/* The map keeps its own light palette in both themes: it is a printed figure,
   and a dark-mode map of a light-mode place reads as a different diagram. */
.mapfig { background: #f6f5f0; }
.ecowrap { display: grid; gap: 1.2rem;
           grid-template-columns: minmax(14rem, 20rem) 1fr; align-items: start; }

/* ── Chips ──────────────────────────────────────────────────────────────── */

.chips { display: flex; flex-wrap: wrap; gap: .45rem; margin: .9rem 0; }
.chip {
  display: inline-flex; align-items: center; gap: .4rem;
  border: 1px solid var(--line-firm); border-radius: 2rem;
  padding: .28rem .8rem; font-size: .9rem; text-decoration: none;
  background: var(--card); line-height: 1.3;
}
.chip:hover { border-color: var(--accent); background: var(--accent-soft); }
.chip .n {
  color: var(--muted); font-size: .78rem; font-variant-numeric: tabular-nums;
  padding-left: .1rem;
}
.chips.big .chip { padding: .45rem 1rem; font-size: .95rem; }
.dot {
  width: .78rem; height: .78rem; border-radius: 50%; flex: 0 0 auto;
  border: 1px solid rgba(128, 128, 128, .45); display: inline-block;
}
.dot.big { width: 1.05rem; height: 1.05rem; margin-right: .45rem;
           vertical-align: -.12rem; }
.star { color: var(--star); }
.badges { display: flex; flex-wrap: wrap; gap: .35rem; margin: .6rem 0 0; }
.badge {
  font-size: .78rem; border: 1px solid var(--line-firm); border-radius: .3rem;
  padding: .12rem .5rem; color: var(--muted); background: var(--bg-sunk);
}

/* ── Cards ──────────────────────────────────────────────────────────────── */

.grid {
  display: grid; gap: .75rem; margin: 1.1rem 0;
  grid-template-columns: repeat(auto-fill, minmax(16.5rem, 1fr));
}
.card {
  display: flex; gap: .8rem; align-items: center; text-decoration: none;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: .55rem; overflow: hidden;
  transition: border-color .12s ease, transform .12s ease;
}
.card:hover { border-color: var(--accent); transform: translateY(-1px);
              box-shadow: var(--shadow); }
.card[hidden] { display: none; }
.thumb {
  width: 4.2rem; height: 4.2rem; flex: 0 0 4.2rem; border-radius: 7px;
  overflow: hidden; background: var(--bg-sunk);
}
.thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.nophoto {
  display: block; width: 100%; height: 100%;
  background:
    repeating-linear-gradient(135deg, var(--bg-sunk) 0 6px,
                              var(--line) 6px 7px);
}
.cardbody { display: flex; flex-direction: column; min-width: 0; gap: .05rem; }
.cardbody strong { font-size: .96rem; font-weight: 600; }
.cardbody em { color: var(--muted); font-size: .82rem; }
.cardbody .meta {
  color: var(--muted); font-size: .8rem; display: flex; align-items: center;
  gap: .32rem; margin-top: .12rem;
}

/* ── Species page ───────────────────────────────────────────────────────── */

.species .sci { font-style: italic; color: var(--muted); margin: .1rem 0 0; }
.spechead { margin-bottom: 1rem; }
.hero-photo { margin: 1.3rem 0; }
.hero-photo img {
  width: 100%; max-height: 27rem; object-fit: cover;
  border-radius: var(--radius); display: block; box-shadow: var(--shadow);
}
.hero-photo .credit { margin: .45rem 0 0; }

table.facts { border-collapse: collapse; width: 100%; margin: .6rem 0; }
table.facts th, table.facts td {
  text-align: left; padding: .48rem .6rem; border-bottom: 1px solid var(--line);
  vertical-align: top; font-size: .94rem;
}
table.facts tr:last-child th, table.facts tr:last-child td { border-bottom: 0; }
table.facts th {
  width: 12rem; color: var(--muted); font-weight: 400; font-size: .86rem;
  letter-spacing: .02em;
}
table.facts .chip { padding: .16rem .6rem; font-size: .86rem; }

ul.animals, ul.ranges { margin: .4rem 0; padding-left: 1.1rem; }
ul.animals li, ul.ranges li { margin: .22rem 0; }
ul.ranges { list-style: none; padding-left: 0; }
ul.ranges li { padding-left: .9rem; position: relative; }
ul.ranges li::before {
  content: ""; position: absolute; left: 0; top: .62em;
  width: .4rem; height: .4rem; border-radius: 50%; background: var(--accent);
}
/* A region with a polygon gets its own colour instead of the generic dot, so
   the line and the shape on the map beside it are visibly the same thing. */
ul.ranges li.haskey { padding-left: 0; }
ul.ranges li.haskey::before { content: none; }
ul.ranges li.haskey .ecokey-sw { margin-right: .42rem; }
/* The list is a hierarchy: an ecozone, then the ecoregions inside it. Without
   this, "Prairies 406 species" and "Aspen Parkland 372 species" read as
   siblings when one contains the other, and the second number looks like it
   should be added to the first. Indentation is the whole fix. */
/* Numbered keys on a focus map, and the matching pip in the legend.
   Hue is the ecozone and lightness the ecoregion inside it, which works for two
   or three siblings and collapses at ten: a search over lightness, chroma and
   hue-rotation together found the best sibling separation that still clears the
   cross-ecozone colour-vision floor is deltaE 1.7, which is the same colour. So
   the number carries identity and the fill keeps saying which system it belongs
   to. */
.ecomap-num circle { fill: #fbfaf6; fill-opacity: .92; stroke: #4a4a44;
                     stroke-width: .9; }
.ecomap-num text { font: 600 10px/1 system-ui, sans-serif; fill: #23261d; }
.ecokey-n { display: inline-flex; align-items: center; justify-content: center;
            width: 1.15rem; height: 1.15rem; margin-right: .3rem; flex: none;
            border: 1px solid #4a4a44; border-radius: 50%;
            font-size: .68rem; font-weight: 600; }
ul.ranges li.eco-zone { margin-top: .6rem; font-weight: 600; }
ul.ranges li.eco-zone:first-child { margin-top: 0; }
ul.ranges li.eco-region { margin-left: 1.1rem; }
ul.cols { columns: 2; column-gap: 2rem; }

/* ── Search page ────────────────────────────────────────────────────────── */

.searchhead { margin-bottom: 1.2rem; }
.searchlayout {
  display: grid; gap: 1.8rem;
  grid-template-columns: minmax(15rem, 17rem) 1fr; align-items: start;
}
.filters {
  position: sticky; top: 4.4rem; max-height: calc(100vh - 5.6rem);
  display: flex; flex-direction: column; padding-right: .3rem;
}
/* The count and the active filters stay put while the facet list scrolls
   under them. Reported: "the number of plants the current selection includes
   should be visible the entire time; currently it disappears if I scroll down
   the characteristic list." */
.fhead {
  position: sticky; top: 0; z-index: 2; background: var(--bg);
  padding-bottom: .4rem; border-bottom: 1px solid var(--line);
}
.fscroll { overflow-y: auto; padding-top: .5rem; }
.fbar { display: flex; gap: .4rem; }
.filters input[type=search] {
  flex: 1; padding: .55rem .7rem; border: 1px solid var(--line-firm);
  border-radius: var(--radius); background: var(--card); color: var(--fg);
  font: inherit; font-size: .92rem;
}
.filters input[type=search]:focus {
  outline: 2px solid var(--accent); outline-offset: 1px;
}
.filters button {
  font: inherit; font-size: .84rem; padding: .3rem .7rem; cursor: pointer;
  border: 1px solid var(--line-firm); border-radius: var(--radius);
  background: var(--card); color: var(--fg);
}
.filters button:hover { border-color: var(--accent); }
.filters .count {
  margin: .5rem 0 .3rem; font-variant-numeric: tabular-nums;
  font-size: 1.05rem; font-weight: 600; color: var(--fg);
}
.active { display: flex; flex-wrap: wrap; gap: .3rem; margin-bottom: .5rem; }
.active button {
  font-size: .78rem; padding: .16rem .55rem; border-radius: 2rem;
  background: var(--accent-soft); border-color: var(--accent);
}
.fgroup { margin-top: .9rem; }
.fgroup:first-child { margin-top: 0; }
.fgroup h3 { margin: 0 0 .2rem; font-size: .72rem; }
/* Two columns of collapsed facets, so the whole list fits a laptop screen
   without scrolling. An open facet spans both, because its options need the
   width. */
.facets { display: grid; grid-template-columns: 1fr 1fr; gap: 0 .7rem; }
.facet { border-bottom: 1px solid var(--line); min-width: 0; }
.facet[open] { grid-column: 1 / -1; }
.facet > summary {
  cursor: pointer; list-style: none; padding: .3rem .1rem;
  font-size: .86rem; display: flex; justify-content: space-between;
  align-items: center; gap: .4rem; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis;
}
.facet > summary::-webkit-details-marker { display: none; }
.facet > summary::after {
  content: "+"; color: var(--muted); font-size: 1rem; line-height: 1;
}
.facet[open] > summary::after { content: "\2212"; }
.facet > summary .on {
  background: var(--accent); color: var(--accent-fg); border-radius: 2rem;
  font-size: .72rem; padding: .04rem .42rem; margin-left: auto;
  font-variant-numeric: tabular-nums;
}
.facet .opts {
  display: flex; flex-direction: column; gap: .2rem;
  max-height: 15rem; overflow-y: auto; padding: .2rem 0 .6rem;
}
.facet .opts label {
  display: flex; align-items: center; gap: .45rem; font-size: .89rem;
  cursor: pointer; padding: .1rem 0; color: var(--fg-soft);
}
.facet .opts label:hover { color: var(--fg); }
.fnote { margin: .1rem 0 .3rem; }
#noresults { padding: 2rem 0; }

/* ── Footer ─────────────────────────────────────────────────────────────── */

.foot {
  border-top: 1px solid var(--line); background: var(--bg-sunk);
  padding: 2rem 1.25rem 3.5rem; color: var(--muted); font-size: .87rem;
}
.foot-inner { max-width: 47rem; margin: 0 auto; }
.foot-lede { color: var(--fg-soft); font-size: 1rem; }
.foot p { margin: .55rem 0; }

img { max-width: 100%; }

@media (max-width: 62rem) {
  .searchlayout, .split, .ecowrap { grid-template-columns: 1fr; }
  .filters { position: static; max-height: none; }
  .fscroll { overflow: visible; }
  .facets { grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); }
  .facet .opts { max-height: none; }
  ul.cols { columns: 1; }
}
@media (max-width: 40rem) {
  .facets { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 34rem) {
  body { font-size: 16px; }
  main { padding: 1.25rem 1rem 3rem; }
  .top { padding: .7rem 1rem; }
  .brand-sub { display: none; }
}
