/* The JR Roost — design system.
 *
 * Custom properties, type scale and component vocabulary lifted from
 * jr-roost-v6.html, which remains authoritative for how things look.
 * See docs/design-decisions.md for what has changed since.
 *
 * Theme is a site-wide toggle, not per-page. */

:root{
  --serif:"Hoefler Text","Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  --hum:Optima,"Avenir Next","Gill Sans MT","Segoe UI",system-ui,sans-serif;
  --mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;

  --bg:#efe6d2; --surface:#faf5e9; --surface2:#f2e9d3; --surface3:#e9dfc6;
  --hover:#e5dac0; --hover2:#f4ecd9; --scrim:rgba(250,245,233,.86);
  --text:#2c281e; --textbody:#4d4636; --text2:#6b6350; --text3:#9d947e;
  --line:#cdbfa0; --line2:#e2d7bd; --line3:#ddcfae;
  --accent:#3f5c3a; --accentline:#7d9575; --onaccent:#faf5e9;
  --tick:#b3a284; --barbg:#b4c0a4; --bartrack:#ddd0b4; --spec:#8fa48a;
  --egg:#bcd6dd; --eggline:#93b6c0;
  --photo1:#e8dcc0; --photo2:#dfd0ad; --photoline:#c3b38d;
  --matbg:#d9cdb0; --matline:#b7a685; --matrow:#eee5cf; --matempty:#dbcfb4;
  --bannerbg:#2c281e; --bannertext:#efe6d2;
  --awayline:#c9a35c; --awaytext:#8a6a20;
  --provline:#c08a3c; --provtext:#8a5f18;
  /* sequential ramp for the diel heatmap */
  --h0:#e2d7bd; --h1:#dfe0c2; --h2:#bfcbae; --h3:#8ea683; --h4:#5d7d5a; --h5:#3f5c3a;
  /* Content that is not this station's own record. The same pale green in both
     themes -- it began as a cool grey here and a green there, but a panel that
     changes hue with the theme reads as two different components rather than
     one. Green in both makes "from the wider world" a single recognisable
     thing, and it is the one colour on the site that is not a habitat. */
  --aside:#c7e9c0; --asideline:#a4cf9c;

  /* constant in both themes: habitat identity + status */
  --forest:#3f5c3a; --wet:#3a6878; --grass:#c2913a; --berry:#a04539;
  /* Fourth guild, not in Wingspan: a warm slate that reads as built
     environment without competing with the three habitat colours. */
  --urban:#6b6a72;
  --onband:#faf5e9; --berrysoft:#a8776f;
  --amber:#d9a441; --amberline:#6b5a2c; --red:#c4685c; --redline:#6d3b34; --blue:#5f97ad;
  --unassigned:#9d947e;
}
[data-theme="dark"]{
  --bg:#1c2019; --surface:#252a21; --surface2:#2b3126; --surface3:#2b3126;
  --hover:#2e3429; --hover2:#2c3227; --scrim:rgba(28,32,25,.86);
  --text:#ded6c0; --textbody:#c6bfa9; --text2:#8d907c; --text3:#7c8071;
  --line:#39402f; --line2:#333a2b; --line3:#3d4534;
  --accent:#7fa06a; --accentline:#4f6b45; --onaccent:#1c2019;
  --tick:#5c6450; --barbg:#47523d; --bartrack:#2f3529; --spec:#6b8062;
  --egg:#46626a; --eggline:#66909a;
  --photo1:#313830; --photo2:#272d26; --photoline:#4a5240;
  --matbg:#222720; --matline:#39402f; --matrow:#2a3027; --matempty:#333a2c;
  --bannerbg:#11140f; --bannertext:#c9c0a8;
  --awayline:#a07c33; --awaytext:#d0a751;
  --provline:#c08a3c; --provtext:#d0a04e;
  --unassigned:#7c8071;
  --h0:#2f3529; --h1:#3c4632; --h2:#4f6540; --h3:#658451; --h4:#7fa06a; --h5:#a8c088;
  /* Same pale green as the light theme, deliberately: a panel lifted out of the
     page is what marks this as not the station's own record. Text inside it is
     overridden to dark ink, since the surrounding light-on-dark would be
     unreadable on a pale panel. */
  --aside:#c7e9c0; --asideline:#a4cf9c;
}

*{box-sizing:border-box}
html{color-scheme:light;background:var(--bg)}
[data-theme="dark"]{color-scheme:dark}
body{margin:0;font-family:var(--hum);background:var(--bg);color:var(--text);
  -webkit-font-smoothing:antialiased;transition:background .2s,color .2s}
h1,h2,h3,h4{font-family:var(--serif);font-weight:400;margin:0}
a{color:var(--accent)}
/* The browser default is a monospace that matches nothing else on the page, and
   its metrics differ enough from the body face to shift the line. .92em pulls it
   back to the same optical size. */
code{font-family:var(--mono);font-size:.92em}
.wrap{max-width:1150px;margin:0 auto;padding:0 18px}
@media(max-width:560px){
  .wrap{padding:0 14px}
  .masthead{padding:20px 0 12px}
  .sec{margin-top:24px}
  .sec h2{font-size:19px}
}

/* ---- nav ---- */
.nav{position:sticky;top:0;z-index:40;background:var(--bg);border-bottom:1px solid var(--line)}
.nav-in{max-width:1150px;margin:0 auto;padding:11px 18px;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.brand{font-family:var(--serif);font-size:20px;white-space:nowrap;text-decoration:none;color:inherit}
.brand span{font-family:var(--mono);font-size:9px;letter-spacing:.19em;text-transform:uppercase;
  color:var(--text2);display:block;margin-top:1px}
.links{display:flex;gap:1px;margin-left:auto;flex-wrap:wrap;align-items:center}
.nl{appearance:none;background:transparent;border:0;font:inherit;font-size:12.5px;color:var(--text2);
  padding:6px 9px;border-radius:6px;cursor:pointer;text-decoration:none}
.nl:hover{background:var(--hover);color:var(--text)}
.nl[aria-current="page"]{background:var(--accent);color:var(--onaccent);font-weight:600}
.nl:focus-visible{outline:2px solid var(--grass);outline-offset:2px}

/* Nav collapses rather than wrapping to three lines (HANDOFF §8). */
@media(max-width:560px){
  .nav-in{padding:9px 14px;gap:8px}
  .links{width:100%;margin-left:0;overflow-x:auto;-webkit-overflow-scrolling:touch;
    flex-wrap:nowrap;scrollbar-width:none}
  .links::-webkit-scrollbar{display:none}
  .nl{white-space:nowrap;padding:7px 10px}
}

.themebtn{appearance:none;border:1px solid var(--line);background:var(--surface);color:var(--text2);
  border-radius:999px;width:34px;height:34px;cursor:pointer;display:flex;align-items:center;
  justify-content:center;margin-left:6px;flex:0 0 34px;transition:border-color .15s,color .15s}
.themebtn:hover{border-color:var(--accent);color:var(--accent)}
.themebtn:focus-visible{outline:2px solid var(--grass);outline-offset:2px}
.themebtn svg{width:15px;height:15px;display:block}
.themebtn .moon{display:none}
[data-theme="dark"] .themebtn .sun{display:none}
[data-theme="dark"] .themebtn .moon{display:block}

.banner{background:var(--bannerbg);color:var(--bannertext);font-family:var(--mono);
  font-size:11px;padding:7px 18px;text-align:center;letter-spacing:.04em}

/* ---- page furniture ---- */
.page{padding-bottom:70px}
.masthead{padding:26px 0 14px;border-bottom:3px double var(--line)}
.eyebrow{font-family:var(--mono);font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--text2)}
/* The eyebrow is a caption. A link in it should read as one without becoming the
   loudest thing in a masthead whose whole job is the title beneath it, so it
   keeps the caption's ink and lets the underline do the work. */
.eyebrow a{color:inherit;text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:var(--accent)}
.eyebrow a:hover{color:var(--accent)}
.masthead h1{font-size:clamp(28px,5.6vw,42px);margin:6px 0 4px}
.sub{font-family:var(--serif);font-style:italic;color:var(--text2);font-size:15px}
.updated{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text3);margin-top:7px}
.updated a{color:var(--accent)}

/* ---- day navigation ----
   Browsing history costs nothing: every detection already carries its local
   timestamp, so this reads rows that exist rather than storing anything. */
.daynav{display:flex;align-items:center;gap:8px;margin-top:13px;flex-wrap:wrap}
.daybtn{font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;
  border:1px solid var(--line);border-radius:999px;padding:6px 12px;text-decoration:none;
  color:var(--text2);background:var(--surface);white-space:nowrap}
.daybtn:hover{border-color:var(--accent);color:var(--accent)}
.daybtn.off{opacity:.4;pointer-events:none}
.dayform{margin:0}
/* A date input sizes itself to the browser's own idea of the field, and mobile
   Chrome's estimate is short enough that "2026-08-09" plus the calendar button
   clipped the year. min-width holds the whole date; the field is content-sized
   rather than stretched, so it stays a control and not a bar. */
.dayform input[type=date]{font-family:var(--mono);font-size:11px;color:var(--text);
  background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:5px 9px;
  min-width:152px}
.dayform input[type=date]:focus-visible{outline:2px solid var(--grass);outline-offset:2px}
@media(max-width:560px){
  .daynav{gap:6px;margin-top:11px}
  .daybtn{font-size:9px;padding:5px 10px}
  .dayform input[type=date]{min-width:146px}
}

/* ---- masthead artwork ---- */
.masthead-art{display:flex;align-items:center;justify-content:space-between;gap:20px}
.mh-text{min-width:0;flex:1}
/* The three illustrations are 1:1, 1:1 and 16:9. They all have transparent
   backgrounds, so contain in a fixed box hides the difference entirely -- no
   crop, and no width jump as the day turns. */
/* Tall enough to span the eyebrow through the status chips, so it reads as part
   of the masthead rather than a badge stuck beside the title. */
.mh-art{appearance:none;border:0;background:transparent;padding:0;margin:0;
  flex:0 0 auto;width:200px;height:172px;cursor:pointer;border-radius:10px;
  transition:transform .18s}
.mh-art img{width:100%;height:100%;object-fit:contain;display:block}
.mh-art:hover{transform:translateY(-2px) scale(1.03)}
.mh-art:focus-visible{outline:2px solid var(--grass);outline-offset:3px}
@media(max-width:820px){
  .mh-art{width:150px;height:130px}
}
@media(max-width:560px){
  .masthead-art{gap:12px}
  .mh-art{width:96px;height:88px}
}

/* ---- hidden video ---- */
.vidwrap{position:fixed;inset:0;z-index:200;background:rgba(20,18,12,.82);
  display:flex;align-items:center;justify-content:center;padding:20px;
  backdrop-filter:blur(3px)}
.vidbox{position:relative;max-width:min(880px,100%);width:100%}
.vidbox video{width:100%;max-height:80vh;display:block;border-radius:12px;
  background:#000;box-shadow:0 12px 40px rgba(0,0,0,.5)}
.vidclose{position:absolute;top:-14px;right:-8px;width:34px;height:34px;border-radius:50%;
  border:1px solid var(--line);background:var(--surface);color:var(--text);
  font-size:20px;line-height:1;cursor:pointer;display:flex;align-items:center;
  justify-content:center;padding:0}
.vidclose:hover{border-color:var(--accent);color:var(--accent)}
.vidclose:focus-visible{outline:2px solid var(--grass);outline-offset:2px}
@media(max-width:560px){
  .vidwrap{padding:14px}
  .vidclose{top:-12px;right:-4px}
}

/* ---- an aside: content that is not this station's own record ----
 *
 * A double rule rather than a new colour. The masthead already uses one as a
 * divider, so it reads as part of the same vocabulary, and the habitat colours
 * stay reserved for habitat. The label sits on the border like a fieldset
 * legend, so the distinction is stated rather than merely implied. */
.sec.aside{border:3px double var(--asideline);border-radius:14px;padding:22px 22px 24px;
  margin-top:34px;position:relative;background:var(--aside)}
/* The tag straddles the panel border, so its background has to mask it -- the
   panel colour, not the page colour, or it reads as a chip sitting on top
   rather than a notch cut into the border. */
.aside-tag{position:absolute;top:-9px;left:20px;background:var(--aside);padding:0 9px;
  font-family:var(--mono);font-size:8.5px;letter-spacing:.18em;text-transform:uppercase;
  color:#5f5a48}
.sec.aside > h2{font-size:21px}

/* The panel is the same pale green in both themes, so everything sitting on it
   is treated the same way in both: translucent white boxes rather than the
   theme's own surface colour, which would be cream here and near-black there.
   Borders pick up the panel's own line colour. */
.sec.aside .powerbox{background:rgba(255,255,255,.5);border-color:var(--asideline)}
.sec.aside .credit{background:rgba(255,255,255,.55);border-color:var(--asideline)}
.sec.aside .lo{background:rgba(255,255,255,.55);border-color:var(--asideline);color:#2c281e}
.sec.aside .lo em{color:#3f5c3a;border-color:#7d9575}
.sec.aside .botd-meta,
.sec.aside .powerbox .src,
.sec.aside .credit{color:#5f5a48}

/* The map attribution sits on a pale basemap, so it needs the same treatment as
   everything else on this panel rather than the theme's --scrim and --text2,
   which are light-on-dark and vanish here. */
.sec.aside .maphint{background:rgba(255,255,255,.72);color:#5f5a48}

/* Only the ink needs the dark theme's help: the surrounding light-on-dark text
   colours would be unreadable on a pale panel. */
[data-theme="dark"] .sec.aside{color:#2c281e}
[data-theme="dark"] .sec.aside h2,
[data-theme="dark"] .sec.aside h3,
[data-theme="dark"] .sec.aside .botd-text .sci,
[data-theme="dark"] .sec.aside .sech,
[data-theme="dark"] .sec.aside .powerbox p{color:#2c281e}
@media(max-width:560px){
  .sec.aside{padding:18px 14px 18px;margin-top:28px}
  .aside-tag{left:14px;font-size:8px;letter-spacing:.14em}
}

/* ---- bird of the day ---- */
/* Borderless inside the aside frame: a card within a card reads as clutter. */
.botd{display:grid;grid-template-columns:280px 1fr;gap:20px;background:var(--surface);
  border:1px solid var(--line);border-radius:12px;overflow:hidden;margin-top:14px}
/* overflow:hidden on the card was clipping the bottom-left corner of the first
   outbound link, whose rounded border sat right on the edge. */
.sec.aside .botd{border:0;background:transparent;margin-top:16px;gap:22px;overflow:visible}
.sec.aside .botd .photo{border-radius:10px 10px 0 0}
.sec.aside .botd .credit{border-radius:0 0 10px 10px;border:1px solid var(--asideline);border-top:0}
.sec.aside .botd-text{padding:0}
.botd-photo .photo{aspect-ratio:1/1;height:auto}
.botd-text{padding:20px 22px 22px 0}
.botd-text h3{font-size:24px;line-height:1.1}
.botd-text .sci{font-family:var(--serif);font-style:italic;font-size:14px;color:var(--text2);margin-top:3px}
.botd-meta{font-family:var(--mono);font-size:9px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--text3);margin-top:8px}
.botd .powerbox{margin-top:13px}
.botd .links-out{margin-top:14px}
@media(max-width:700px){
  .botd{grid-template-columns:1fr}
  .botd-text{padding:0 16px 18px}
}
.sech{font-size:12.5px;color:var(--text2);margin:4px 0 14px;max-width:66ch;line-height:1.5}
.sec{margin-top:30px}
.sec h2{font-size:22px}

.statusrow{display:flex;gap:14px;flex-wrap:wrap;margin-top:13px}
.chip{display:flex;align-items:baseline;gap:6px;font-size:12px;color:var(--text2)}
.chip b{font-family:var(--mono);font-size:12.5px;color:var(--text);font-weight:600}
.live{width:7px;height:7px;border-radius:50%;background:var(--accent);align-self:center}
.live.stale{background:var(--amber)}

/* 1px grid gaps over a coloured background, rather than a border on each cell.
   Per-cell borders leave a dangling edge wherever the grid wraps, and the
   :last-child rule that hides it only ever works on the final cell. */
/* Compact: a summary, not the substance of the page. Each cell links to the
   section it summarises, so the number is a way in rather than a dead end. */
.tally{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));
  gap:1px;background:var(--line);border:1px solid var(--line);border-radius:11px;
  overflow:hidden;margin-top:18px}
.tally > *{background:var(--surface);padding:12px 14px 11px;display:flex;flex-direction:column;
  text-decoration:none;color:inherit;transition:background .14s}
.tally a:hover{background:var(--hover2)}
.tally a:focus-visible{outline:2px solid var(--grass);outline-offset:-2px}
.tally .n{font-family:var(--serif);font-size:25px;line-height:1}
.tally .l{font-family:var(--mono);font-size:8.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--text2);margin-top:5px}

/* Scrolled-to headings must clear the sticky nav. */
.sec[id]{scroll-margin-top:78px}
.tally .sub2{font-family:var(--mono);font-size:9px;color:var(--text3);margin-top:5px;letter-spacing:.04em}
/* The firsts block: today's on one line, and the last month's behind two nested
   disclosures. It was a section of its own further down and, open by default,
   pushed the habitat board off the screen -- so it lives here instead, where the
   page already announces firsts, and stays shut until asked. */
.newtoday{margin:12px 0 0;font-size:13px;color:var(--textbody);
  border-left:2px solid var(--berry);padding-left:11px;line-height:1.7}
.newtoday .newline{margin:0}
/* Scoped to .newline, NOT to .newtoday. These used to be descendant rules, and
   the cards inside the disclosures are anchors too -- left as they were, every
   card would pick up the serif underlined treatment meant for the inline list. */
.newline b{font-family:var(--mono);font-size:9px;letter-spacing:.14em;text-transform:uppercase;
  font-weight:400;color:var(--berry);margin-right:5px}
.newline a{font-family:var(--serif);font-size:14.5px;color:var(--text);text-decoration:none;
  border-bottom:1px solid var(--line)}
.newline a:hover{color:var(--berry);border-color:var(--berry)}

/* A first-of-record, marked where it was actually heard. */
.newtag{display:inline-block;font-family:var(--mono);font-size:7.5px;letter-spacing:.12em;
  text-transform:uppercase;background:var(--berry);color:#faf5e9;border-radius:3px;
  padding:1px 5px;margin-left:7px;vertical-align:1px}
.lane.isnew .name{font-weight:600}

/* ---- range map ----
   A class, not an id: the same map appears on the species page and inside the
   Bird of the Day card, and an id can only dress one of them. */
.mapbox.range .rangemap{height:clamp(260px,42vh,400px);width:100%;background:var(--mapsea)}

/* Shorter inside Bird of the Day. That card is a digression on a page about
   this station's own record, and a full-height world map there would outweigh
   everything above it. Enough to see the shape of a range, not more. */
.sec.aside .mapbox{margin-top:14px;border-color:var(--asideline)}
.sec.aside .mapbox.range .rangemap{height:clamp(160px,24vh,220px)}

/* The GBIF occurrence layer, blurred and recoloured to sit in the same visual
   family as a BirdWeather range polygon.
 *
 * GBIF returns binned hexagons because its input is occurrence records, not a
 * polygon -- no style it offers is continuous, and asking for finer bins only
 * makes smaller hexagons. Blurring the composited pane merges neighbours into
 * soft shapes and lets isolated strays fall away, which is as close to a shaded
 * polygon as point data can honestly get.
 *
 * On the pane, never on .leaflet-tile: a filter applied per tile blurs each one
 * inside its own box and leaves a visible seam along every tile edge.
 *
 * The three colour terms are not taste, they are solved. The most common opaque
 * pixel in green-noborder.poly is rgb(77,124,64); the BirdWeather polygons are
 * #3f5c3a = rgb(63,92,58). Running the CSS filter matrices over a grid of
 * hue/saturation/brightness finds exactly one combination that maps the first to
 * the second with zero error, and this is it. Do not nudge these by eye -- they
 * are a fit, and the whole point is that the two maps agree.
 *
 * The rest of GBIF's ramp follows to #4d6746, #596f50, #687a5d and on up, so
 * sparse areas stay the same hue and simply lighten. That is the density
 * information BirdWeather's flat fill does not carry, kept rather than crushed. */
.gbif-pane{filter:blur(2.5px) hue-rotate(3deg) saturate(0.75) brightness(0.76)}

/* Last-resort basemap, only ever visible if both CARTO and Esri have failed
   (see roost-basemap.js). OSM's standard style is far more saturated than the
   pale canvas the range polygons and route lines were drawn to sit on, and at
   full strength the map shouts over them. Knocking the colour back gets it
   close enough to Positron that nothing else needs to change. A filter, not a
   different tile set, because there is no paler keyless option left at this
   point in the chain -- this IS the fallback. */
.osm-pale{filter:saturate(.4) brightness(1.05)}

/* A static map is a picture, so it must behave like one under a thumb.
   roost-range.js already leaves every Leaflet handler switched off, which means
   the leaflet-touch-drag class that sets touch-action:none is never applied --
   this states the same thing in CSS rather than depending on that, since the
   failure mode is a card that eats the swipe meant for the page. pan-y, not
   auto: vertical scrolling always wins, and there is nothing to pan sideways
   to anyway. */
.mapbox.static .rangemap{touch-action:pan-y;cursor:default}

/* 560px, not 420px. Modern phones report 390-450px CSS width, so a 420px
   breakpoint sits below almost all of them and never fires -- which is why the
   phone view was the desktop layout, merely narrower. */
@media(max-width:560px){
  .tally{grid-template-columns:1fr 1fr;margin-top:14px}
  .tally > *{padding:10px 12px 9px}
  .tally .n{font-size:21px}
  .tally .l{font-size:7.5px;margin-top:4px;letter-spacing:.11em}
  .tally .sub2{font-size:7.5px;margin-top:3px}
}

/* ---- photo frame: attribution is part of the design ---- */
.photo{position:relative;background:linear-gradient(150deg,var(--photo1),var(--photo2));overflow:hidden}
.photo img{width:100%;height:100%;object-fit:cover;display:block}
.photo .ph-tag{position:absolute;top:9px;left:9px;font-family:var(--mono);font-size:8.5px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--text3);border:1px solid var(--photoline);
  border-radius:3px;padding:2px 6px;background:var(--scrim)}
.credit{font-family:var(--mono);font-size:9px;letter-spacing:.05em;color:var(--text3);
  padding:6px 10px;background:var(--surface);border-top:1px solid var(--line);
  display:flex;justify-content:space-between;gap:10px}
.credit a{color:var(--text3)}
.credit .nocredit{font-style:italic}

/* ---- habitat bands ---- */
.bands{display:flex;flex-direction:column}
.bands i{flex:1}
.band-forest{background:var(--forest)}
.band-grass{background:var(--grass)}
.band-wet{background:var(--wet)}
.band-urban{background:var(--urban)}
.band-unassigned{background:var(--unassigned)}

/* ---- eggs (confidence) ---- */
.eggs{display:flex;gap:4px;margin-top:9px;align-items:center}
.egg{width:11px;height:14px;border-radius:50% 50% 48% 48%/60% 60% 40% 40%;
  background:var(--egg);border:1px solid var(--eggline)}
.egg.off{background:transparent;border-style:dashed;border-color:var(--line)}
.eggl{font-family:var(--mono);font-size:9.5px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--text3);margin-left:5px}

/* ---- wingspan ruler ---- */
.ruler{margin-top:11px;border-top:1px solid var(--line);padding-top:6px;
  display:flex;justify-content:space-between;align-items:center}
.ticks{display:flex;gap:3px;align-items:flex-end;height:11px}
.ticks i{width:1px;background:var(--tick);height:5px}
.ticks i:nth-child(4n+1){height:10px}
.wspan{font-family:var(--mono);font-size:10px;color:var(--text3)}
.wspan.missing{font-style:italic;opacity:.65}
.attrib{font-family:var(--mono);font-size:8.5px;letter-spacing:.03em;color:var(--text3);
  line-height:1.5;margin:10px 0 0;max-width:64ch}

/* ---- Wingspan card (Field Guide top 10) ---- */
/* auto-fit, not auto-fill: auto-fill keeps empty tracks alive on a short final
   row, which reads as blank cards sitting in the grid. */
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));gap:16px}
.wcard{background:var(--surface);border:1px solid var(--line);border-radius:12px;overflow:hidden;
  display:flex;text-align:left;font:inherit;color:inherit;text-decoration:none;
  transition:box-shadow .16s,transform .16s;position:relative}
.wcard:hover{box-shadow:0 5px 16px rgba(60,50,25,.17);transform:translateY(-2px)}
.wcard .bands{width:9px;flex:0 0 9px}
.wcard .col{flex:1;min-width:0;display:flex;flex-direction:column}
/* The photo is the card's main feature. A fixed height crops tall and square
   images savagely and leaves them small on wide cards; an aspect ratio scales
   with the column instead. Subject placement is handled by the per-species
   focal point rather than by hoping the bird is centred. */
.wcard .photo{aspect-ratio:4/3;height:auto;min-height:180px}
.wcard .rank{position:absolute;top:10px;right:10px;z-index:2;width:26px;height:26px;border-radius:50%;
  background:var(--scrim);border:1px solid var(--line);font-family:var(--serif);font-size:12.5px;
  display:flex;align-items:center;justify-content:center}
.wcard .body{padding:13px 14px 14px;flex:1;display:flex;flex-direction:column}
.wcard .top{display:flex;justify-content:space-between;gap:10px;align-items:flex-start}
.wcard .nm{font-family:var(--serif);font-size:17px;line-height:1.15}
.wcard .sci{font-family:var(--serif);font-style:italic;font-size:12px;color:var(--text2);margin-top:2px}
.wcard .meta{font-family:var(--mono);font-size:8.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--text3);margin-top:7px}
.pts{flex:0 0 auto;width:36px;height:36px;border-radius:50%;border:1.5px solid var(--berry);
  color:var(--berry);display:flex;flex-direction:column;align-items:center;justify-content:center;
  font-family:var(--serif);font-size:13px;line-height:1}
.pts span{font-family:var(--mono);font-size:6.5px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--berrysoft);margin-top:1px}
.powerbox{background:var(--surface2);border:1px solid var(--line3);border-radius:8px;
  padding:11px 13px;margin-top:11px}
.powerbox p{margin:0;font-size:12.5px;line-height:1.55;color:var(--textbody)}
.powerbox .src{font-family:var(--mono);font-size:8px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--text3);margin-top:8px;display:block}
.wcard .foot{margin-top:auto}

/* ---- species detail: the Wingspan card scaled up ---- */
.back{display:inline-block;font-family:var(--mono);font-size:10.5px;letter-spacing:.13em;
  text-transform:uppercase;color:var(--accent);text-decoration:none;padding:22px 0 0}
.bigcard{display:grid;grid-template-columns:11px 1.25fr .95fr;background:var(--surface);
  border:1px solid var(--line);border-radius:14px;overflow:hidden;margin-top:14px;
  box-shadow:0 2px 0 rgba(80,66,34,.07)}
.bigcard .bands{width:auto}
.bigcard .main{padding:24px 26px 22px}
.bigcard .side{border-left:1px solid var(--line);display:flex;flex-direction:column}
.bigcard .side .photo{flex:1;min-height:260px}
.headrow{display:flex;justify-content:space-between;gap:16px;align-items:flex-start}
.bigcard h2{font-size:clamp(24px,4.4vw,34px);line-height:1.08}
.bigcard .sci{font-family:var(--serif);font-style:italic;font-size:15px;color:var(--text2);margin-top:4px}
.alpha{font-family:var(--mono);font-size:10px;letter-spacing:.14em;color:var(--text3);margin-top:7px}
.bigcard .powerbox{margin-top:18px}
.bigcard .powerbox p{font-size:13.5px;line-height:1.62}
.metarow{display:flex;justify-content:space-between;align-items:flex-end;gap:16px;margin-top:18px;
  padding-top:14px;border-top:1px solid var(--line);flex-wrap:wrap}
.metarow .eggs,.metarow .ruler{margin-top:0}
.metarow .ruler{border-top:0;padding-top:0;gap:12px}

/* Photo above text on narrow screens (HANDOFF §8).
 *
 * Single column, NOT "11px 1fr". With three children and order:-1 on the photo,
 * a two-column grid auto-places the photo into the 11px track, the habitat band
 * into the wide one, and the text back into the 11px track -- so the photo
 * became a slice, the band became a huge grey rectangle, and every paragraph
 * wrapped one word per line.
 *
 * The band becomes a horizontal strip under the photo, which is also what the
 * smaller cards do, so the vocabulary stays consistent. */
@media(max-width:780px){
  .bigcard{grid-template-columns:1fr}
  .bigcard .side{border-left:0;order:-1}
  .bigcard .bands{flex-direction:row;height:6px;width:auto}
  .bigcard .main{padding:20px 18px}
  .bigcard .side .photo{min-height:0;aspect-ratio:4/3}
}
@media(max-width:560px){
  .statgrid{grid-template-columns:1fr 1fr}
  .statgrid b{font-size:19px}
  .metarow{gap:10px}
}

.statgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:10px;overflow:hidden;margin-top:16px}
.statgrid div{background:var(--surface);padding:15px 16px}
.statgrid b{font-family:var(--serif);font-size:22px;display:block;line-height:1}
.statgrid span{font-family:var(--mono);font-size:9px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--text2);display:block;margin-top:5px}

.twocol{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:18px}
.twocol.single{grid-template-columns:1fr}
@media(max-width:760px){.twocol{grid-template-columns:1fr}}
.pcard{background:var(--surface);border:1px solid var(--line);border-radius:10px;padding:16px 18px}
.pcard h4{font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--text2);margin-bottom:12px}
.bars{display:flex;gap:2px;align-items:flex-end;height:70px}
.bars i{flex:1;background:var(--barbg);border-radius:2px 2px 0 0;min-height:2px}
.bars i.hi{background:var(--accent)}
.axis{display:flex;gap:2px;margin-top:5px}
.axis span{flex:1;text-align:center;font-family:var(--mono);font-size:8px;color:var(--text3)}
/* Labelled ticks need room to breathe and a mark to sit against. */
.axis.ticks{margin-top:6px}
.axis.ticks span{white-space:nowrap;font-size:8.5px;position:relative;min-width:0}
.axis.ticks span:not(:empty)::before{content:"";position:absolute;top:-5px;left:50%;
  width:1px;height:3px;background:var(--tick)}
.roots{font-family:var(--serif);font-size:14px;line-height:1.75;margin:0}
.prov.ok{border-style:solid;border-color:var(--accentline);color:var(--accent)}
.rows div{display:flex;justify-content:space-between;gap:10px;padding:7px 0;
  border-bottom:1px solid var(--line2);font-size:12.5px;align-items:baseline}
.rows div:last-child{border-bottom:0}
.rows span{font-family:var(--mono);font-size:11px;color:var(--text2)}
.rows b{font-family:var(--serif);font-size:14px;color:var(--text);font-weight:400}

.links-out{display:flex;flex-wrap:wrap;gap:8px;margin-top:6px}
.lo{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--line);background:var(--bg);
  border-radius:8px;padding:9px 13px;font-size:12.5px;text-decoration:none;color:var(--text)}
.lo:hover{border-color:var(--accent);background:var(--surface2)}
.lo em{font-family:var(--mono);font-size:8.5px;letter-spacing:.09em;text-transform:uppercase;
  font-style:normal;color:var(--accent);border:1px solid var(--accentline);border-radius:3px;padding:1px 5px}

/* ---- notable (scarce elsewhere, present here) ---- */
.notable{display:grid;grid-template-columns:repeat(auto-fit,minmax(178px,1fr));gap:13px}
.ncard{background:var(--surface);border:1px solid var(--line);border-radius:11px;overflow:hidden;
  text-decoration:none;color:inherit;display:flex;flex-direction:column;position:relative;
  transition:box-shadow .16s,transform .16s}
.ncard:hover{box-shadow:0 4px 13px rgba(60,50,25,.16);transform:translateY(-2px)}
.ncard .photo{aspect-ratio:1/1;height:auto;min-height:130px}
.ncard .nb{padding:10px 12px 12px}
.ncard .nm{font-family:var(--serif);font-size:14px;line-height:1.18}
.ncard .sci{font-family:var(--serif);font-style:italic;font-size:11px;color:var(--text2);margin-top:2px}
.ncard .scarce{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--berry);margin-top:7px}
.ncard .scarce b{font-weight:600}

/* ---- habitat board ---- */
.mat{background:var(--matbg);border:2px solid var(--matline);border-radius:14px;padding:14px;margin-top:20px}
.hrow{display:flex;border-radius:9px;overflow:hidden;margin-bottom:10px;background:var(--matrow)}
.hrow:last-child{margin-bottom:0}
.hlabel{flex:0 0 108px;padding:12px 10px;color:var(--onband);display:flex;flex-direction:column;justify-content:center}
.hlabel b{font-family:var(--serif);font-size:15px;font-weight:400}
.hlabel span{font-family:var(--mono);font-size:9px;letter-spacing:.11em;text-transform:uppercase;
  opacity:.85;margin-top:3px}
.track{flex:1;padding:10px 8px;min-height:72px;overflow-x:auto}
.lane{display:flex;align-items:center;height:24px;position:relative;min-width:520px}
.lane .name{font-family:var(--serif);font-size:12px;position:absolute;left:0;top:50%;
  transform:translateY(-50%);z-index:2;background:linear-gradient(90deg,var(--matrow) 72%,transparent);
  padding-right:14px;white-space:nowrap;text-decoration:none;color:inherit}
.lane .name:hover{color:var(--berry)}
.dots{display:flex;gap:2px;width:100%;padding-left:132px}
.dots i{flex:1;border-radius:2px;min-height:3px}
.hours{display:flex;gap:2px;padding-left:132px;margin-top:4px;min-width:520px}
.hours span{flex:1;text-align:center;font-family:var(--mono);font-size:8px;color:var(--text2)}

/* On a phone the species name moves ABOVE its bars instead of sitting inside
   the row. The name was taking 132px of a ~340px track, which is what forced
   the horizontal scroll. Freed of it, all 24 bins fit the width -- which is
   what the board is for. */
@media(max-width:700px){
  .mat{padding:10px;border-radius:11px}
  .hrow{margin-bottom:8px}
  .hlabel{flex:0 0 76px;padding:10px 8px}
  .hlabel b{font-size:13px}
  .hlabel span{font-size:8px;margin-top:2px}
  .track{padding:9px 7px;overflow-x:visible;min-height:0}
  .lane{display:block;height:auto;min-width:0;margin-bottom:9px}
  .lane:last-child{margin-bottom:0}
  .lane .name{position:static;transform:none;background:none;padding:0 0 4px;
    display:block;font-size:12.5px;white-space:normal;line-height:1.2}
  .dots{padding-left:0;gap:1.5px}
  .hours{padding-left:0;min-width:0;gap:1.5px}
  .hours span{font-size:7.5px}
}

/* ---- recent birds strip ---- */
.facestrip{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;margin-top:14px}
.face{text-decoration:none;color:inherit;display:block;text-align:center}
.facephoto{display:block;width:100%;aspect-ratio:1/1;border-radius:50%;
  background:linear-gradient(150deg,var(--photo1),var(--photo2));background-size:cover;
  border:2px solid var(--line);transition:border-color .16s,transform .16s}
.face:hover .facephoto{border-color:var(--accent);transform:translateY(-2px)}
.facename{display:block;font-family:var(--serif);font-size:12px;line-height:1.2;margin-top:7px}
.facetime{display:block;font-family:var(--mono);font-size:8.5px;letter-spacing:.08em;
  color:var(--text3);margin-top:2px}
@media(max-width:560px){
  .facestrip{gap:7px}
  .facename{font-size:10.5px}
  .facetime{font-size:8px}
}

/* ---- new here lately ----
   The catch-up list: species first heard in the last month. Cards rather than a
   table, because this is a short list read by glancing rather than a dataset
   read by scanning, and because a photo is what makes "have I seen this one?"
   answerable at a glance. */
/* Collapsed, each of these is one small line stating a count -- enough to notice
   that six birds arrived while you were not looking, not enough to cost the
   habitat board its place on the screen. Deliberately the same weight as the
   "First time here today" label directly above, so the three read as one thing. */
.firsts-d{margin-top:2px}
.firsts-d > summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:8px;
  font-family:var(--mono);font-size:9px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--text2);padding:4px 0;border-radius:6px}
/* Safari still needs the vendor pseudo-element to drop the disclosure triangle;
   list-style alone leaves it in place there. */
.firsts-d > summary::-webkit-details-marker{display:none}
.firsts-d > summary:hover{color:var(--accent)}
.firsts-d > summary:focus-visible{outline:2px solid var(--grass);outline-offset:2px}
/* Chevron drawn from two borders on a rotated box, so it inherits the text
   colour and needs no asset. Right when closed, down when open. */
.firsts-d > summary::before{content:"";flex:0 0 auto;width:5px;height:5px;margin-left:3px;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:rotate(-45deg);transition:transform .16s}
.firsts-d[open] > summary::before{transform:rotate(45deg)}
/* No trailing rule any more: inline-flex inside the berry-bordered firsts block,
   a full-width divider would cut the block in half. */
.cnt{font-family:var(--mono);font-size:8.5px;background:var(--surface3);border-radius:9px;
  padding:2px 7px;color:var(--text3);letter-spacing:.06em}
.firsts-d > summary:hover .cnt{color:var(--text2)}
/* Indented and ruled off, so the second disclosure reads as part of the first
   rather than as a sibling that happens to sit below it. */
.firsts-d.nest{margin-top:6px;margin-bottom:2px;padding-left:12px;border-left:1px solid var(--line)}

/* margin-top because the nested group has no blurb above it — the cards would
   otherwise butt straight against their own summary line. */
.firsts{display:grid;grid-template-columns:repeat(auto-fill,minmax(268px,1fr));gap:9px;margin-top:5px}
.firstcard{display:flex;align-items:center;gap:11px;text-decoration:none;color:inherit;
  border:1px solid var(--line);border-radius:10px;background:var(--surface);
  padding:9px 12px 9px 9px;transition:border-color .16s,transform .16s,background .16s}
.firstcard:hover{border-color:var(--accent);background:var(--hover2);transform:translateY(-1px)}
.firstcard:focus-visible{outline:2px solid var(--grass);outline-offset:2px}
/* min-width:0 so a long scientific name ellipses instead of stretching the grid
   column and pulling every card in the row out of alignment. */
.firstmeta{min-width:0;flex:1;display:flex;flex-direction:column;gap:1px}
.firstmeta b{font-family:var(--serif);font-weight:400;font-size:14.5px;line-height:1.15;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.firstmeta .sci{font-family:var(--serif);font-style:italic;font-size:11px;color:var(--text2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.firstwhen{font-family:var(--mono);font-size:8.5px;letter-spacing:.07em;color:var(--text3);
  margin-top:2px}
/* The detection count since. Right-aligned and quiet: it answers "was this a
   one-off or has it settled in", which is the second question, not the first. */
.firstn{font-family:var(--mono);font-size:12px;color:var(--text2);flex:0 0 auto;
  padding-left:4px}
@media(max-width:560px){
  .firsts{grid-template-columns:1fr}
  .firstmeta b{font-size:13.5px}
}

/* ---- live feed ---- */
.feed{border:1px solid var(--line);border-radius:10px;background:var(--surface);overflow:hidden;margin-top:12px}
/* Column header. The row is time / play / species / confidence, and a bare
   number in the last column is not self-explanatory. */
.feedhead{background:var(--surface3);border-bottom:1px solid var(--line);padding-top:8px;padding-bottom:8px}
.feedhead:hover{background:var(--surface3)}
.feedhead > *{font-family:var(--mono)!important;font-size:8.5px!important;letter-spacing:.14em;
  text-transform:uppercase;color:var(--text2)!important}
.feedhead .play-h{flex:0 0 30px;text-align:center}
.rec{display:flex;gap:12px;align-items:center;padding:11px 14px;border-bottom:1px solid var(--line2)}
.rec:last-child{border-bottom:0}
.rec:hover{background:var(--hover2)}
/* One width for both a single time and a range, or every row with a grouped
   run knocks the play buttons and names out of alignment with the rows above. */
.rec .t{font-family:var(--mono);font-size:10.5px;color:var(--text2);
  width:92px;flex:0 0 92px;font-variant-numeric:tabular-nums}
.rec .t.span{color:var(--text3)}
.rec .runs{font-family:var(--mono);font-size:10px;letter-spacing:.06em;color:var(--berry);
  margin-left:7px;vertical-align:1px}
.rec .who{flex:1;min-width:0}
.rec .who b{font-family:var(--serif);font-size:14.5px;font-weight:400;display:block}
.rec .who .sci{font-family:var(--serif);font-style:italic;font-size:11px;color:var(--text2)}
.rec .who a{text-decoration:none;color:inherit}
.rec .who a:hover b{color:var(--berry)}
.play{width:30px;height:30px;border-radius:50%;border:1px solid var(--line);background:transparent;
  display:flex;align-items:center;justify-content:center;cursor:pointer;flex:0 0 30px;color:var(--accent)}
.play:hover{background:var(--accent);color:var(--onaccent)}
.play[disabled]{opacity:.3;cursor:default}
.conf{font-family:var(--mono);font-size:11px;color:var(--text2);width:38px;text-align:right;flex:0 0 38px}
.play.playing{background:var(--accent);color:var(--onaccent)}

/* ---- spectrogram ---- */
.specrow{display:none;padding:0 14px 14px;background:var(--surface2);
  border-bottom:1px solid var(--line2)}
.specrow.open{display:block}
.specwrap{position:relative;border:1px solid var(--line);border-radius:8px;overflow:hidden;
  background:var(--h0)}
.spec-canvas{display:block;width:100%;height:140px}
.spec-head{position:absolute;top:0;bottom:0;width:1.5px;background:var(--berry);
  left:0;pointer-events:none;opacity:.85}
.spec-note{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;color:var(--text2);
  background:var(--surface2);text-align:center;padding:0 14px}
.spec-axis{display:flex;justify-content:space-between;gap:10px;margin-top:5px;
  font-family:var(--mono);font-size:8.5px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--text3)}
.spec-legend{color:var(--berry)}
@media(max-width:560px){
  .specrow{padding:0 10px 10px}
  .spec-canvas{height:112px}
  .spec-axis{font-size:8px}
}
.awaytag{font-family:var(--mono);font-size:8px;letter-spacing:.1em;text-transform:uppercase;
  border:1px solid var(--awayline);color:var(--awaytext);border-radius:3px;padding:1px 5px}

/* ---- tools + ledger ---- */
.tools{display:flex;gap:9px;flex-wrap:wrap;align-items:center;margin:16px 0 12px}
.search{flex:1;min-width:190px;border:1px solid var(--line);border-radius:8px;background:var(--surface);
  padding:9px 12px;font:inherit;font-size:13.5px;color:var(--text)}
.fchip{appearance:none;border:1px solid var(--line);background:var(--surface);border-radius:999px;
  font:inherit;font-size:12px;color:var(--text2);padding:7px 13px;cursor:pointer}
.fchip[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:var(--onaccent)}
.count{font-family:var(--mono);font-size:11px;color:var(--text2);margin-left:auto}

.tbox{border:1px solid var(--line);border-radius:10px;overflow:auto;background:var(--surface);max-height:620px}
table.led{border-collapse:collapse;width:100%;min-width:800px}
table.led thead th{position:sticky;top:0;z-index:2;background:var(--surface3);font-family:var(--mono);
  font-size:9.5px;letter-spacing:.11em;text-transform:uppercase;color:var(--text2);font-weight:400;
  text-align:left;padding:11px 12px;border-bottom:1px solid var(--line);cursor:pointer;
  white-space:nowrap;user-select:none}
table.led thead th:hover{color:var(--accent)}
table.led thead th[aria-sort] .arrow{color:var(--accent)}
table.led td{padding:10px 12px;border-bottom:1px solid var(--line2);font-size:13px}
table.led tbody tr:hover{background:var(--hover2)}
table.led a{text-decoration:none;color:inherit}
.cn{font-family:var(--serif);font-size:14.5px;display:block}
.sn{font-family:var(--serif);font-style:italic;font-size:11.5px;color:var(--text2)}
.fam span{font-family:var(--mono);font-size:9.5px;color:var(--text3);display:block}
.num{font-family:var(--mono);font-size:12px;text-align:right}
.where i{font-style:normal;font-family:var(--mono);font-size:9px;letter-spacing:.08em;
  text-transform:uppercase;border-radius:3px;padding:2px 6px;border:1px solid var(--line);color:var(--text2)}
.where i.away{border-color:var(--awayline);color:var(--awaytext)}
.where i.both{border-color:var(--accentline);color:var(--accent)}
.where i.hab-forest{border-color:var(--forest);color:var(--forest)}
.where i.hab-grass{border-color:var(--grass);color:var(--grass)}
.where i.hab-wet{border-color:var(--wet);color:var(--wet)}
.where i.hab-urban{border-color:var(--urban);color:var(--urban)}
.where i.hab-unassigned{border-style:dashed;border-color:var(--line);color:var(--text3)}
[data-theme="dark"] .where i.hab-forest{border-color:var(--accent);color:var(--accent)}
/* ---- field guide: compact list with expandable detail ---- */
table.led.compact tbody tr.srow{cursor:pointer}
/* Thumbnail left of the name. A placeholder rather than nothing when a species
   has no photo, so rows stay aligned instead of ragged. */
.rthumb{flex:0 0 34px;width:34px;height:34px;border-radius:50%;background-size:cover;
  background-position:50% 50%;background-color:var(--photo1);border:1px solid var(--line);
  display:inline-block;vertical-align:middle}
.rthumb[data-empty]{background-image:linear-gradient(150deg,var(--photo1),var(--photo2))}
.rname{display:inline-block;vertical-align:middle;min-width:0}
table.led.compact td.species-cell{display:flex;align-items:center;gap:11px}
table.led.compact tbody tr.srow.open{background:var(--hover2)}
table.led.compact tbody tr.srow .species-cell{position:relative;padding-left:26px}
table.led.compact tbody tr.srow .species-cell::before{content:"▸";position:absolute;left:11px;
  top:11px;color:var(--text3);font-size:10px;transition:transform .15s}
table.led.compact tbody tr.srow.open .species-cell::before{content:"▾"}
tr.drow > td{background:var(--surface2);padding:0!important}
.detail{padding:14px 16px 16px 26px}
.dbits{display:flex;flex-wrap:wrap;gap:10px 26px}
.dbits span{font-size:12.5px;color:var(--text)}
.dbits b{display:block;font-family:var(--mono);font-size:8.5px;letter-spacing:.13em;
  text-transform:uppercase;color:var(--text3);margin-bottom:3px;font-weight:400}
.dbits em{font-style:normal;font-family:var(--mono);font-size:9.5px;color:var(--text3);
  display:block;margin-top:2px}
.dbits i{font-style:normal;font-family:var(--mono);font-size:9px;letter-spacing:.08em;
  text-transform:uppercase;border:1px solid var(--line);border-radius:3px;padding:2px 6px;
  color:var(--text2)}
.dbits i.away{border-color:var(--awayline);color:var(--awaytext)}
.dbits i.both{border-color:var(--accentline);color:var(--accent)}
.dbits i.hab-forest{border-color:var(--forest);color:var(--forest)}
.dbits i.hab-grass{border-color:var(--grass);color:var(--grass)}
.dbits i.hab-wet{border-color:var(--wet);color:var(--wet)}
.dbits i.hab-urban{border-color:var(--urban);color:var(--urban)}
.dbits i.hab-unassigned{border-style:dashed;color:var(--text3)}
.dhour{margin-top:14px}
.dhour b{display:block;font-family:var(--mono);font-size:8.5px;letter-spacing:.13em;
  text-transform:uppercase;color:var(--text3);margin-bottom:5px;font-weight:400}
.phen.wide{width:100%;max-width:340px;height:30px}
/* The compact Field Guide list stays a table at every width. Three columns fit
   a phone, and the expandable row exists so the rest does not need to. */
@media(max-width:700px){
  .tbox.compact{border:1px solid var(--line);border-radius:10px;
    background:var(--surface);overflow:auto}
  table.led.compact{display:table;min-width:0;width:100%}
  table.led.compact thead{display:table-header-group}
  table.led.compact tbody{display:table-row-group}
  /* :not([hidden]) matters. A bare display:table-row outranks the browser's
     [hidden]{display:none}, so every detail row rendered open on a phone. */
  table.led.compact tr:not([hidden]){display:table-row;background:transparent;border:0;
    margin:0;padding:0;border-radius:0}
  table.led.compact tr[hidden]{display:none}
  table.led.compact td{display:table-cell;width:auto;justify-content:unset;
    padding:9px 10px;border-bottom:1px solid var(--line2)}
  table.led.compact td::before{content:none;display:none}
  table.led.compact td.species-cell{display:flex;padding-left:10px}
  table.led.compact tbody tr.srow .species-cell::before{content:none}
  table.led.compact .rthumb{flex-basis:28px;width:28px;height:28px}
  table.led.compact .cn{font-size:13px}
  table.led.compact .sn{font-size:10.5px}
  table.led.compact th{font-size:8px;padding:9px 10px}
  table.led.compact tr.drow > td{display:table-cell;padding:0;border-bottom:1px solid var(--line2)}
  .detail{padding:12px 14px}
  .phen.wide{max-width:100%}
}

.phen{display:flex;gap:1.5px;align-items:flex-end;height:22px;width:118px}
.phen i{flex:1;background:var(--barbg);border-radius:1px;min-height:2px}
.phen i.hi{background:var(--accent)}

/* Wide tables reflow to stacked cards below ~700px rather than scrolling
   horizontally (HANDOFF §8). This was written when the Field Guide list had
   seven columns and genuinely could not fit. It now has three, plus an
   expandable detail row, so it opts out below -- only the genuinely wide tables
   in Archive still reflow. */
@media(max-width:700px){
  .tbox{max-height:none;border:0;background:transparent;overflow:visible}
  table.led{min-width:0;display:block}
  table.led thead{display:none}
  table.led tbody,table.led tr,table.led td{display:block;width:100%}
  table.led tr{background:var(--surface);border:1px solid var(--line);border-radius:10px;
    margin-bottom:10px;padding:4px 2px}
  table.led td{border-bottom:1px solid var(--line2);display:flex;justify-content:space-between;
    align-items:baseline;gap:12px;padding:9px 13px}
  table.led td:last-child{border-bottom:0}
  table.led td::before{content:attr(data-label);font-family:var(--mono);font-size:9px;
    letter-spacing:.11em;text-transform:uppercase;color:var(--text3);flex:0 0 auto}
  table.led td.species-cell{display:block}
  table.led td.species-cell::before{display:block;margin-bottom:3px}
  .num{text-align:right}
}

/* ---- panels, notes, empty states ---- */
.panel{background:var(--surface);border:1px solid var(--line);border-radius:9px;padding:16px}
.panel h4{font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--text2);margin-bottom:10px}
.pnote{font-size:12px;color:var(--text2);line-height:1.55;margin:0 0 12px;max-width:66ch}
.panel-error{border-color:var(--redline)}
.panel-error h4{color:var(--red)}
.err{font-family:var(--mono);font-size:11px;white-space:pre-wrap;color:var(--red);margin:0}

.empty{border:1px dashed var(--line);border-radius:10px;padding:22px 18px;text-align:center;
  color:var(--text2);background:var(--surface2)}
.empty b{font-family:var(--serif);font-size:15px;font-weight:400;color:var(--text);display:block;margin-bottom:5px}
.empty span{font-size:12px;line-height:1.55;display:block;max-width:52ch;margin:0 auto}

.caveat{border-left:2px solid var(--amberline);padding-left:12px;margin-top:10px}
.caveat p{font-size:12px;color:var(--text2);line-height:1.55;margin:0 0 9px}
.caveat b{color:var(--amber);font-weight:500;font-family:var(--mono);font-size:10.5px;
  letter-spacing:.08em;text-transform:uppercase;display:block;margin-bottom:2px}
.prov{display:inline-block;font-family:var(--mono);font-size:8.5px;letter-spacing:.1em;
  text-transform:uppercase;border:1px dashed var(--provline);color:var(--provtext);
  border-radius:3px;padding:2px 7px;margin-left:8px;vertical-align:2px}

.foot{margin-top:44px;padding-top:16px;border-top:1px solid var(--line);
  font-family:var(--mono);font-size:10px;letter-spacing:.06em;color:var(--text3);
  display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;align-items:baseline}
.foot .byline{opacity:.72}

/* The way in to /artwork. It must read as part of the byline, so it takes the
   surrounding ink and no underline -- an easter egg that announces itself is
   just a link. A tap target the size of a four-digit year is small, hence the
   padding: it stays invisible and becomes reachable with a thumb. Focus is the
   exception; a keyboard user has no way to find this by hovering, and hiding it
   from them buys nothing.

   NOT .egg -- that is the confidence egg, 475 lines up and in use since the
   first build. This rule shipped as .egg and squared them off and overlapped
   them, because it is later in the file and its negative margin ate the flex
   gap. Anything named for the easter egg has to say so. */
.yearegg{color:inherit;text-decoration:none;padding:3px 4px;margin:-3px -4px;border-radius:4px}
.yearegg:hover{color:var(--accent)}
.yearegg:focus-visible{outline:2px solid var(--grass);outline-offset:1px}

/* ---- /artwork: the masthead illustrations ---- */
.plates{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:18px;margin-top:20px}
.plate{border:1px solid var(--line);border-radius:12px;background:var(--surface);
  padding:16px 16px 14px;display:flex;flex-direction:column;gap:11px}
/* The one currently on the Today page, called out so the page answers "which am
   I looking at right now" without anyone checking a clock. */
.plate.on{border-color:var(--grass);box-shadow:0 0 0 1px var(--grass)}
.plate-h h2{font-size:17px;margin:0}
.plate-when{font-family:var(--mono);font-size:9px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--text2);margin-top:4px}
/* Checkerboard, because every one of these is transparent and the point of the
   page is partly to show that. --bg behind it so the squares read in both themes.
   It is a <button> when there is a clip behind it, hence the appearance reset --
   and the whole plate is the target, which on a phone matters more than any
   badge does. */
.plate-img{appearance:none;-webkit-appearance:none;border:0;font:inherit;color:inherit;width:100%;
  position:relative;border-radius:9px;padding:8px;display:flex;align-items:center;justify-content:center;
  background-color:var(--bg);
  background-image:linear-gradient(45deg,var(--line) 25%,transparent 25%,transparent 75%,var(--line) 75%),
                   linear-gradient(45deg,var(--line) 25%,transparent 25%,transparent 75%,var(--line) 75%);
  background-size:16px 16px;background-position:0 0,8px 8px}
button.plate-img{cursor:pointer;transition:transform .16s ease}
button.plate-img:hover{transform:translateY(-2px)}
button.plate-img:focus-visible{outline:2px solid var(--grass);outline-offset:2px}
.plate-img img{width:100%;max-width:240px;height:auto;display:block}

/* Today hides its clip on purpose; this page is the opposite, so the badge says
   plainly that the picture plays. It sits over the artwork rather than under it
   so the plate stays one object to aim at. */
.plate-play{position:absolute;left:10px;bottom:10px;display:inline-flex;align-items:center;gap:6px;
  font-family:var(--mono);font-size:8.5px;letter-spacing:.14em;text-transform:uppercase;
  background:var(--scrim);color:var(--text2);padding:5px 9px;border-radius:6px}
button.plate-img:hover .plate-play{color:var(--accent)}

.plate-f{font-family:var(--mono);font-size:8.5px;letter-spacing:.08em;color:var(--text3);
  word-break:break-all}

/* ---- analysis: heatmap and dual bars ---- */
.hgbox{border:1px solid var(--line);border-radius:8px;background:var(--surface);overflow:auto;max-height:430px}
.hg{border-collapse:separate;border-spacing:2px;min-width:660px;padding:8px}
.hg thead th{position:sticky;top:0;z-index:3;background:var(--surface);font-family:var(--mono);
  font-size:9px;font-weight:400;color:var(--text2);padding:5px 0 4px;text-align:center}
.hg td.sp{font-size:12.5px;text-align:right;padding-right:10px;white-space:nowrap;
  font-family:var(--serif);position:sticky;left:0;background:var(--surface);z-index:2}
.hg td.sp a{text-decoration:none;color:inherit}
.hg td.sp a:hover{color:var(--berry)}
.cell{width:20px;height:17px;border-radius:3px;background:var(--h0)}
.cell.h0{background:var(--h0)}.cell.h1{background:var(--h1)}.cell.h2{background:var(--h2)}
.cell.h3{background:var(--h3)}.cell.h4{background:var(--h4)}.cell.h5{background:var(--h5)}
.legend{display:flex;align-items:center;gap:6px;margin-top:10px;font-size:10.5px;
  color:var(--text2);font-family:var(--mono);flex-wrap:wrap}
.swatch{width:16px;height:11px;border-radius:2px;background:var(--h0)}
.swatch.h0{background:var(--h0)}.swatch.h1{background:var(--h1)}.swatch.h2{background:var(--h2)}
.swatch.h3{background:var(--h3)}.swatch.h4{background:var(--h4)}.swatch.h5{background:var(--h5)}

/* Two series stacked, each labelled with its own peak. Superimposing them on a
   shared unlabelled axis meant no height could be read as a value. */
.series{margin-bottom:12px}
.series:last-of-type{margin-bottom:6px}
.series-head{display:flex;justify-content:space-between;align-items:baseline;gap:10px;
  font-family:var(--mono);font-size:9px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--text2);margin-bottom:5px}
.series-head b{color:var(--text);font-weight:400}
.bars.short{height:46px}
.bars.short.alt i{background:var(--grass);opacity:.75}
.bars.tall{height:104px;gap:3px}
/* Outside the active window: present, but visibly not part of the story. */
.bars.tall i.quiet{opacity:.32}

.showall{appearance:none;border:1px solid var(--line);background:var(--surface);
  border-radius:999px;font:inherit;font-size:11.5px;color:var(--text2);
  padding:7px 15px;cursor:pointer;margin-top:11px}
.showall:hover{border-color:var(--accent);color:var(--accent)}
.showall:focus-visible{outline:2px solid var(--grass);outline-offset:2px}
.hg tr.extra{display:none}
.hg.showing-all tr.extra{display:table-row}

@media(max-width:560px){
  .hg{min-width:560px}
  .cell{width:16px;height:15px}
  .hg td.sp{font-size:11.5px;max-width:120px;overflow:hidden;text-overflow:ellipsis}
}

/* ---- maps ---- */
.mapbox{position:relative;border:1px solid var(--line);border-radius:12px;overflow:hidden;
  background:var(--surface2);margin-top:16px}
.mapbox #map,.mapbox #routemap{height:clamp(300px,52vh,460px);width:100%}
.mapbox.route #routemap{height:clamp(320px,58vh,520px)}
.maphint{position:absolute;left:12px;bottom:12px;z-index:500;font-family:var(--mono);font-size:9.5px;
  letter-spacing:.06em;color:var(--text2);background:var(--scrim);padding:5px 9px;border-radius:6px}

/* Egg pins as divIcon: the prototype's border-radius transfers unchanged. */
.eggpin{display:block;width:22px;height:28px;
  border-radius:50% 50% 48% 48%/60% 60% 40% 40%;
  background:var(--berry);border:2px solid #faf5e9;box-shadow:0 2px 5px rgba(0,0,0,.4)}
.eggpin.quiet{background:var(--unassigned)}
.eggpin.small{width:16px;height:20px;background:var(--wet);border-width:1.5px}
.eggpin.clutch{width:34px;height:42px;background:var(--forest);color:#faf5e9;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:12px;padding-top:2px}

/* Touch targets: Leaflet's defaults are too small on a phone (HANDOFF §8). */
.leaflet-touch .leaflet-bar a{width:34px;height:34px;line-height:34px}
.leaflet-container{font-family:var(--hum)}
.mappop b{font-family:var(--serif);font-size:15px;font-weight:400;display:block}
.mappop i{font-family:var(--serif);font-size:11.5px;color:#6b6350;display:block;margin-top:1px}
.mappop span{font-family:var(--mono);font-size:10px;color:#6b6350;display:block;margin-top:6px}
.mappop a{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
  display:inline-block;margin-top:8px}

/* ---- outing card + list ---- */
.ocard2{margin-top:16px;background:var(--surface);border:1px solid var(--line);border-radius:12px;
  overflow:hidden;display:block;text-decoration:none;color:inherit;transition:box-shadow .16s}
.ocard2:hover{box-shadow:0 5px 16px rgba(60,50,25,.16)}
.ocard2 .ob{padding:20px 22px}
.ocard2 .k{font-family:var(--mono);font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--berry)}
.ocard2 h3{font-size:23px;margin:6px 0 3px}
.ocard2 .osub{font-family:var(--mono);font-size:11px;color:var(--text2)}
.dstats{display:grid;grid-template-columns:repeat(auto-fit,minmax(105px,1fr));gap:1px;
  background:var(--line);border-top:1px solid var(--line);border-bottom:1px solid var(--line);margin-top:15px}
.dstats div{background:var(--surface);padding:13px 14px}
.dstats b{font-family:var(--serif);font-size:23px;display:block;line-height:1}
.dstats span{font-family:var(--mono);font-size:9px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--text2);display:block;margin-top:5px}
.golink{font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--accent);margin-top:16px;display:block}

.olist{border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--surface);margin-top:12px}
.orow{display:flex;align-items:center;gap:14px;padding:13px 16px;border-bottom:1px solid var(--line2);
  text-decoration:none;color:inherit}
.orow:last-child{border-bottom:0}
.orow:hover{background:var(--hover2)}
.orow .oi{flex:0 0 10px;height:40px;border-radius:5px}
.orow .on{flex:1;min-width:0}
.orow .on b{font-family:var(--serif);font-size:15px;font-weight:400;display:block}
.orow .on span{font-family:var(--mono);font-size:10px;color:var(--text2);letter-spacing:.05em}
.orow .os{font-family:var(--mono);font-size:10.5px;color:var(--text2);text-align:right;
  white-space:nowrap;line-height:1.6}

.otiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(158px,1fr));gap:13px;margin-top:14px}
.otile{background:var(--surface);border:1px solid var(--line);border-radius:11px;overflow:hidden;
  text-decoration:none;color:inherit;display:flex;flex-direction:column;
  transition:box-shadow .16s,transform .16s}
.otile:hover{box-shadow:0 4px 13px rgba(0,0,0,.16);transform:translateY(-2px)}
.otile .bandstrip{height:5px;display:flex}
.otile .bandstrip i{flex:1}
.otile .photo{aspect-ratio:4/3;height:auto}
/* These tiles are a third the width of a species card, so a long provenance
   line -- "Louis Agassiz Fuertes (1874-1927) artist, authors of the written
   work variously listed a..." -- ran to four lines under a small photo and
   made the grid rows wildly uneven. Clamped to two lines here: enough to
   still read as attribution, and the full credit is on the species page every
   tile links to. The licence keeps its own line and never wraps, so it stays
   the fixed right-hand anchor it is everywhere else. The licence is clamped
   too, but it is two or three words and never reaches the limit. */
.otile .credit{gap:8px;align-items:flex-start}
.otile .credit > *{min-width:0;display:-webkit-box;-webkit-box-orient:vertical;
  -webkit-line-clamp:2;line-clamp:2;overflow:hidden}
.otile .ob2{padding:10px 12px 12px}
.otile .nm{font-family:var(--serif);font-size:14px;line-height:1.18}
.otile .sci{font-family:var(--serif);font-style:italic;font-size:11px;color:var(--text2);margin-top:2px}

/* ---- archive: plain-language status ---- */
.status-card{border:1px solid var(--line);border-left:3px solid var(--accent);border-radius:10px;
  background:var(--surface);padding:16px 18px;margin-top:20px}
.status-card.warn{border-left-color:var(--amber)}
.status-head{display:flex;align-items:center;gap:9px}
.status-head b{font-family:var(--serif);font-size:17px;font-weight:400}
.status-card p{font-size:13px;line-height:1.6;color:var(--textbody);margin:9px 0 0;max-width:70ch}

.todo{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:12px;margin-top:14px}
.todo-item{background:var(--surface);border:1px solid var(--line);border-radius:10px;padding:15px 16px;
  text-decoration:none;color:inherit;display:block}
.todo-item:not(.quiet):hover{border-color:var(--accent);box-shadow:0 3px 10px rgba(60,50,25,.13)}
.todo-item b{font-family:var(--serif);font-size:30px;line-height:1;display:block}
.todo-item span{font-size:12.5px;color:var(--text2);display:block;margin-top:5px}
.todo-item em{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  font-style:normal;color:var(--accent);display:block;margin-top:9px}
.todo-item.quiet em{color:var(--text3)}

details.tech{margin-top:34px;border-top:1px solid var(--line);padding-top:8px}
details.tech > summary{cursor:pointer;list-style:none;padding:10px 0;display:flex;
  align-items:baseline;gap:12px;flex-wrap:wrap}
details.tech > summary::-webkit-details-marker{display:none}
details.tech > summary h2{font-size:19px;display:inline}
details.tech > summary::before{content:"▸";color:var(--text3);font-size:12px}
details.tech[open] > summary::before{content:"▾"}
details.tech > summary span{font-size:12px;color:var(--text3)}
.techh{font-size:15px;margin:22px 0 4px}

.edphotoedit{margin-top:2px;border-top:1px dashed var(--line);padding-top:8px}
.edphotoedit summary{cursor:pointer;font-family:var(--mono);font-size:9px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--text3);padding:3px 0}
.edphotoedit summary:hover{color:var(--accent)}
.edphotoedit label{margin-top:7px}
.edhint{font-size:11px;color:var(--text3);line-height:1.5;margin:8px 0 2px}
.radio{display:flex;gap:11px;align-items:flex-start;padding:11px 0;border-bottom:1px solid var(--line2)}
.radio:last-of-type{border-bottom:0}
.radio input{margin-top:3px;width:16px;height:16px;accent-color:var(--accent);flex:0 0 16px}
.radio b{font-family:var(--serif);font-size:15px;font-weight:400;display:block}
.radio em{font-style:normal;font-size:12px;color:var(--text2);line-height:1.55;display:block;margin-top:3px}
.edfields input[type=number]{flex:1;min-width:0;border:1px solid var(--line);border-radius:7px;
  background:var(--bg);color:var(--text);font:inherit;font-size:12.5px;padding:7px 9px}

/* ---- archive editor ---- */
.notice{border-radius:9px;padding:12px 15px;font-size:13px;margin-top:16px;border:1px solid var(--line)}
.notice.ok{border-color:var(--accentline);color:var(--accent);background:var(--surface2)}
.notice.bad{border-color:var(--redline);color:var(--red);background:var(--surface2)}

.editbar{display:flex;align-items:center;gap:14px;margin:18px 0 10px;position:sticky;top:56px;
  z-index:20;background:var(--bg);padding:8px 0}
.editbar.bottom{position:static}
.btn{appearance:none;border:1px solid var(--accent);background:var(--accent);color:var(--onaccent);
  font:inherit;font-size:13px;padding:9px 18px;border-radius:8px;cursor:pointer}
.btn:hover{filter:brightness(1.08)}
.btn:focus-visible{outline:2px solid var(--grass);outline-offset:2px}

.edrows{display:flex;flex-direction:column;gap:10px}
.edrow{display:grid;grid-template-columns:132px 1fr 300px;gap:16px;align-items:center;
  background:var(--surface);border:1px solid var(--line);border-radius:11px;padding:11px}
.edrow.done{border-color:var(--accentline)}
.edrow.dirty{box-shadow:inset 3px 0 0 var(--berry)}
/* No photo column on outing rows. */
.edrow.outrow{grid-template-columns:1fr 340px}
@media(max-width:820px){.edrow.outrow{grid-template-columns:1fr}}
.edrow.outrow a.edct{display:inline-block;margin-top:9px;color:var(--accent);text-decoration:none}
@media(max-width:820px){
  .edrow{grid-template-columns:96px 1fr}
  .edfields{grid-column:1 / -1}
}

/* Sized 4:3 to match the card crop, so what you set is what you get. */
.edphoto{aspect-ratio:4/3;border-radius:8px;background-size:cover;background-repeat:no-repeat;
  background-color:var(--photo1);position:relative;cursor:crosshair;overflow:hidden;
  border:1px solid var(--photoline)}
.edphoto .focal{position:absolute;width:13px;height:13px;border-radius:50%;
  border:2px solid #fff;background:rgba(160,69,57,.85);transform:translate(-50%,-50%);
  box-shadow:0 0 0 1px rgba(0,0,0,.45);pointer-events:none}

.ednm{font-family:var(--serif);font-size:16px}
.edct{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text3);margin-left:9px}
.edsci{font-family:var(--serif);font-style:italic;font-size:12px;color:var(--text2);margin-top:2px}
.edfam{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text3);margin-top:7px}

.edfields{display:flex;flex-direction:column;gap:8px}
.edfields label{display:flex;align-items:center;gap:9px;font-size:12px;color:var(--text2)}
.edfields label span{flex:0 0 74px}
.edfields select,.edfields input[type=text]{flex:1;min-width:0;border:1px solid var(--line);
  border-radius:7px;background:var(--bg);color:var(--text);font:inherit;font-size:12.5px;padding:7px 9px}
.edfields label.chk span{flex:0 0 auto}
.edfields input[type=checkbox]{width:16px;height:16px;accent-color:var(--accent)}

.skip{position:absolute;left:-9999px}
.skip:focus{left:8px;top:8px;z-index:100;background:var(--surface);padding:8px 12px;
  border:1px solid var(--accent);border-radius:6px}
