body { font-family: system-ui, sans-serif; max-width: 56rem; margin: 3rem auto; padding: 0 1rem; }
header { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap;
         gap: 0.5rem; border-bottom: 1px solid #e5e2dc; padding-bottom: 0.75rem; margin-bottom: 2rem; }
header h1 { margin: 0; }
header nav a { margin-left: 1.25rem; }
h2 { font-size: 1.05rem; margin: 0 0 0.5rem; }
/* Undoes the page-wide block `span`, which would break a heading over three lines. */
h2 span { display: inline; font-weight: inherit; margin: 0; }
nav.tabs { display: flex; gap: 0.5rem; margin: -1rem 0 1.75rem; }
nav.tabs button { font-size: 0.95rem; padding: 0.4rem 1rem; margin: 0; cursor: pointer;
                  background: none; border: 0; border-bottom: 2px solid transparent; color: #446; }
nav.tabs button[aria-selected="true"] { border-bottom-color: #446; font-weight: 600; color: inherit; }
section[hidden] { display: none; }
.cols { display: flex; gap: 2.5rem; align-items: flex-start; }
form.settings { flex: 0 0 15rem; }
aside.side { flex: 1; min-width: 0; }
label { display: block; margin: 0 0 1.25rem; }
span { display: block; font-weight: 600; margin-bottom: 0.25rem; }
small { color: #666; font-weight: 400; }
select { font-size: 1rem; padding: 0.4rem; }
input { font-size: 1rem; padding: 0.4rem; width: 8rem; }
input[type=range] { width: 100%; padding: 0; margin: 0; }
.field { margin: 0 0 1.25rem; }
.sub { display: block; margin: 0.6rem 0 0; font-weight: 400; }
.sub small { display: block; margin-bottom: 0.15rem; }
.sub select { width: 100%; }
.src { display: flex; align-items: center; gap: 0.4rem; font-weight: 400; margin: 0 0 0.3rem; }
.src input { width: auto; padding: 0; }
.src .src { margin: 0; }  /* the row holding a radio and its number box */
.src input[type=number] { width: 3.25rem; padding: 0.25rem 0.3rem; }
button { font-size: 1rem; padding: 0.5rem 1.25rem; margin-top: 0.5rem; }
button:disabled { opacity: 0.45; }
/* A setting the chosen mode does not read: shown, so its value is not a surprise on the way back. */
.off { opacity: 0.45; }
a { color: #446; }
/* The bubble hangs off the label's span, not the badge, so it starts at the
   column edge and cannot run out of the 15rem form. */
label > span, .field > span { position: relative; }
/* Bottom margin: `middle` aligns to the x-height, a Title Case label to the cap. */
.hint { display: inline-flex; align-items: center; justify-content: center;
        width: 0.9rem; height: 0.9rem; margin: 0 0 0.125rem 0.05em; vertical-align: middle;
        font-size: 0.78rem; font-weight: 700; line-height: 1; color: #6b675f;
        border: 1px solid #aaa59c; border-radius: 50%; cursor: help; user-select: none; }
.hint::before { content: "i"; }
/* `focus-visible`: a mouse click focuses the span too, and the bubble would
   then outlive the tap that closed it. */
.hint:hover, .hint:focus-visible, .hint.open { color: #446; border-color: #446; }
.hint::after { content: attr(aria-label); position: absolute; left: 0; top: 100%; z-index: 2;
               width: max-content; max-width: 13rem; margin-top: 0.3rem;
               padding: 0.35rem 0.55rem; border-radius: 4px; background: #446; color: #fff;
               font: 400 0.85rem/1.35 system-ui, sans-serif; white-space: pre-line;
               visibility: hidden; }
.hint:hover::after, .hint:focus-visible::after, .hint.open::after { visibility: visible; }
dl.status { display: grid; grid-template-columns: auto 1fr; gap: 0.35rem 1rem;
            background: #f4f2ee; padding: 1rem 1.25rem; border-radius: 6px; margin: 0 0 1.75rem; }
dl.status dt { color: #666; }
dl.status dd { margin: 0; }
dl.status dd span { display: inline; font-weight: inherit; margin: 0; }
dl.status dd.update { display: flex; align-items: center; gap: 0.5rem; }
dl.status dd.update button { margin: 0; }
time { border-bottom: 1px dotted #bbb; cursor: help; }
/* White, not the panel's own #f4f2ee, or the box vanishes into it. `user-select:
   all` takes the whole line in one click - plain http has no clipboard API. */
pre.cmd { font: 0.85rem/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
          background: #fff; border: 1px solid #e5e2dc; border-radius: 4px;
          padding: 0.15rem 0.5rem; margin: 0; user-select: all; overflow-x: auto; }
.ok, .bad, .warn { display: inline; font-weight: inherit; margin: 0; }
.ok { color: #3a7d44; }
.bad { color: #a4392f; }
.warn { color: #8a6d1f; }
p.note { display: block; font-size: 0.9rem; margin: 0.6rem 0 0; }
.block { margin: 0 0 1.75rem; }  /* the Save button carries no bottom margin of its own */
form.detector input { width: 100%; max-width: 22rem; }
form.detector button { margin-right: 0.5rem; }
form.detector summary { cursor: pointer; color: #446; }
form.detector details { margin-bottom: 1.25rem; }
/* Open, the last field inside carries the gap to the buttons itself. */
form.detector details[open] { margin-bottom: 0; }
form.detector details[open] summary { margin-bottom: 0.75rem; }
#test-result { display: inline; }
form.inline { display: inline; }
form.inline button { font-size: 0.8rem; padding: 0.1rem 0.5rem; margin: 0 0 0 0.5rem; }
ul.species { list-style: none; padding: 0; margin: 0 0 1.75rem;
             display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, max-content));
             justify-content: start; gap: 0.15rem 2.5rem; }
ul.species li { padding: 0.1rem 0; }
ul.species li.noart { color: #aaa; }
ul.species li.noart small { color: #aaa; }
ul.species small a { color: inherit; text-decoration-color: #bbb; }
ul.species small a:hover { color: #446; text-decoration-color: currentColor; }
ul.species li.empty { color: #999; }
/* An empty list because something is wrong, not because no bird has called yet. */
ul.species li.problem { color: #a4392f; }
.preview img { display: block; width: 100%; height: 100%; box-sizing: border-box;
               border: 1px solid #ddd; border-radius: 6px; }
.rendering { display: none; align-items: center; justify-content: center; gap: 0.6rem;
             color: #666; }
/* The box is the page's own shape - --aspect is the panel turned by the rotation
   in the form - so a re-render moves the list under it only when the page would. */
.preview { --aspect: 4 / 3; aspect-ratio: var(--aspect);
           width: min(100%, calc(60vh * var(--aspect)));
           display: flex; align-items: center; justify-content: center;
           margin: 0 0 1.75rem; position: relative; }
/* The band a mat would cover, shaded over the page while the margin is dragged. */
.mat { position: absolute; inset: 0; pointer-events: none;
       border: 0 solid rgba(70, 60, 50, 0.45); border-radius: 6px; }
.preview.loading .rendering { display: flex; }
.preview.loading img { display: none; }
/* margin: undoes the page-wide `span` rule, which offsets it from the caption. */
.spinner { width: 1.1rem; height: 1.1rem; margin: 0; border: 2px solid #ddd;
           border-top-color: #888; border-radius: 50%; animation: spin 0.8s linear infinite; }
.spinner.inline { display: inline-block; vertical-align: -0.15rem; }
#bar { width: 7rem; height: 0.55rem; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation: none; } }
@media (max-width: 40rem) {
  .cols { flex-direction: column; }
  form.settings { flex: none; }
}
