/* The collection page: every specimen on one canvas, arranged by taxonomy or by
   time (scripts/field.js). Built on the site's own tokens, so it wears the same
   parchment, and dark, as every other page. */

/* What the canvas needs that the rest of the site does not define. */
.field-page {
    --gutter: clamp(12px, 3vw, 28px);
    --header-h: 0px;
    --r-sm: 8px;
    --r: 12px;
    --r-lg: 16px;
    --r-xl: 22px;
    --ground-4: color-mix(in srgb, var(--ground-3) 80%, var(--ink));
    --lift-3: 0 30px 70px -24px rgba(34, 27, 18, 0.55), 0 0 0 1px var(--rule);
    --narrow: 100%;
    --fs-label: 0.75rem;
    --stage: #17120c;   /* behind a photograph in the specimen sheet */
}
/* The page is the canvas: the header above it, nothing to scroll. */
body.field-page { height: 100svh; display: flex; flex-direction: column; overflow: hidden; }
body.field-page main { position: relative; flex: 1; min-height: 0; }
.visually-hidden {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.field {
    position: absolute;
    inset: 0;
    overflow: hidden;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    cursor: grab;
    /* A quiet ground: a soft light in the middle, falling off to the edges. */
    background: radial-gradient(ellipse 80% 70% at 50% 46%, var(--ground-2), var(--ground) 70%);
}
.field.is-dragging { cursor: grabbing; }

.field-world {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
    transform-origin: 0 0;
}

.tile {
    position: absolute;
    left: 0;
    top: 0;
    width: 64px;
    height: 64px;
    overflow: hidden;
    background-color: var(--c, var(--ground-3));
    background-image: var(--atlas);
    background-size: calc(var(--cols) * 100%) calc(var(--rows) * 100%);
    background-position:
        calc(var(--col) / (var(--cols) - 1) * 100%)
        calc(var(--row) / max(var(--rows) - 1, 1) * 100%);
    opacity: 0;
    transition: transform 1.1s var(--ease), opacity 0.6s var(--ease);
}
.field.is-ready .tile { opacity: 1; }
.tile img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity 0.5s var(--ease);
}
.tile.has-hires img { opacity: 1; }
.tile::after {
    content: "";
    position: absolute;
    inset: 0;
    box-shadow: inset 0 0 0 0 var(--accent);
    transition: box-shadow 0.15s;
}
.tile:hover { z-index: 3; }
.tile:hover::after { box-shadow: inset 0 0 0 calc(2px / var(--k, 1)) var(--accent); }
.tile.is-current { z-index: 4; }
.tile.is-current::after { box-shadow: inset 0 0 0 calc(3px / var(--k, 1)) var(--accent); }
.tile.is-new::before {
    content: "";
    position: absolute;
    right: 5px;
    top: 5px;
    z-index: 2;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 8px var(--accent);
}
.field.is-dragging .tile { pointer-events: none; }

/* Labels keep a readable size on screen however far out the camera is. */
.field-labels { position: absolute; left: 0; top: 0; transition: opacity 0.3s; }
.field-labels.is-hidden { opacity: 0; }
.field-label {
    position: absolute;
    left: 0;
    top: 0;
    color: var(--ink);
    text-decoration: none;
    white-space: nowrap;
}
.field-label-inner {
    position: absolute;
    left: 0;
    bottom: 0;
    display: flex;
    align-items: baseline;
    gap: 0.4em;
    transform-origin: 0 100%;
    scale: max(1, calc(0.55 / var(--k, 1)));
}
.field-label-kicker {
    position: absolute;
    left: 0;
    bottom: 100%;
    font-family: var(--body);
    font-size: 11px;
    letter-spacing: var(--caps-tracking);
    text-transform: var(--caps);
    color: var(--ink-3);
}
.field-label-text {
    font-family: var(--display);
    font-size: 26px;
    font-weight: 800;
    font-stretch: var(--narrow);
    line-height: 1;
    text-transform: var(--caps);
}
.field-label-count {
    font-family: var(--body);
    font-size: 12px;
    color: var(--accent);
}
a.field-label:hover .field-label-text { color: var(--accent); }
/* A locality's name over its column only once there is room to read it; until then
   the tooltip names it. */
.lab-col { opacity: 0; transition: opacity 0.3s; pointer-events: none; }
.field.is-near .lab-col { opacity: 1; pointer-events: auto; }
.lab-col .field-label-inner { scale: 1; }
/* Specimens dated only to a wide bracket, after the chart: the bracket is the label. */
.lab-broad .field-label-text { font-size: 15px; color: var(--ink-2); }
.lab-broad .field-label-kicker { font-size: 10px; }
.lab-col .field-label-text {
    font-family: var(--body);
    font-size: 9px;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--ink-2);
}

/* The backdrop of the time arrangement: the ICS bands, equal width each. */
.field-back { position: absolute; left: 0; top: 0; }
.fb-band {
    position: absolute;
    left: 0;
    top: 0;
    background: linear-gradient(to top, color-mix(in srgb, var(--band) 26%, transparent), color-mix(in srgb, var(--band) 4%, transparent) 70%, transparent);
    border-left: 1px solid color-mix(in srgb, var(--band) 30%, transparent);
}
.fb-band::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -14px;
    height: 10px;
    background: var(--band);
}
.fb-band-name {
    position: absolute;
    left: 10px;
    bottom: -64px;
    font-family: var(--display);
    font-size: 26px;
    font-weight: 800;
    font-stretch: var(--narrow);
    text-transform: var(--caps);
    color: var(--band);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* Scaled up to stay legible, and narrowed by the same factor so it never
       spills into the next band. */
    width: calc((100% - 16px) / max(1, calc(0.5 / var(--k, 1))));
    transform-origin: 0 0;
    scale: max(1, calc(0.5 / var(--k, 1)));
}
/* A name too long for a narrow band reads down the page under it. */
.fb-band.is-tall .fb-band-name {
    bottom: auto;
    top: calc(100% + 30px);
    left: 50%;
    width: auto;
    overflow: visible;
    writing-mode: vertical-rl;
    transform: translateX(-50%);
}
/* Turned on its side for a portrait screen. */
.fb-band.is-v {
    background: linear-gradient(to right, color-mix(in srgb, var(--band) 24%, transparent), color-mix(in srgb, var(--band) 4%, transparent) 70%, transparent);
    border-left: 0;
    border-top: 1px solid color-mix(in srgb, var(--band) 30%, transparent);
}
.fb-band.is-v::after { left: -14px; right: auto; top: 0; bottom: 0; width: 10px; height: auto; }
.fb-band.is-v .fb-band-name { left: auto; right: 8px; bottom: auto; top: 8px; width: auto; transform-origin: 100% 0; text-align: right; }
.fb-band.is-v .fb-band-age { left: auto; right: 8px; bottom: auto; top: 44px; border-left: 0; transform-origin: 100% 0; }
.fb-band-age {
    position: absolute;
    left: -1px;
    bottom: -30px;
    padding-left: 5px;
    border-left: 1px solid var(--ink-3);
    font-family: var(--body);
    font-size: 12px;
    color: var(--ink-3);
    transform-origin: 0 0;
    scale: max(1, calc(0.5 / var(--k, 1)));
}


/* The world has no width of its own, so the global max-width on svg would crush these. */
.field-back svg { max-width: none; }

/* The tree's branches, one stroke at screen width however far out. */
.fb-tree { position: absolute; pointer-events: none; }
/* vector-effect ignores the camera's CSS scale, so the width is divided by it
   instead (--ks is set once the camera settles, to spare a repaint per frame). */
.fb-branches { fill: none; stroke: color-mix(in srgb, var(--ink) 26%, transparent); stroke-width: calc(1.4px / var(--ks, 0.1)); stroke-linecap: round; }

/* A node: its silhouette, its name and its count, held at one size on screen. */
.field-node-labels { position: absolute; left: 0; top: 0; z-index: 1; }
.fb-node { position: absolute; left: 0; top: 0; opacity: 0; pointer-events: none; transition: opacity 0.25s; cursor: zoom-in; }
.fb-node.is-shown { opacity: 1; pointer-events: auto; }
.fb-node-inner {
    position: absolute;
    left: 0;
    top: 0;
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 3px 6px 3px 3px;
    border-radius: 999px;
    background: var(--ground-2);
    box-shadow: 0 0 0 1px var(--rule-2), var(--lift);
    white-space: nowrap;
    transform-origin: 0 0;
    transform: translate(-50%, -50%);
}
.fb-node-icon {
    width: 26px;
    height: 26px;
    flex: none;
    padding: 3px;
    border-radius: 50%;
    background: var(--plate);
    object-fit: contain;
}
.fb-node-dot { width: 10px; height: 10px; margin: 0 4px 0 6px; border-radius: 50%; background: var(--ink-3); }
.fb-node-text { display: flex; align-items: baseline; gap: 6px; }
.fb-node-name {
    font-family: var(--display);
    font-size: 14px;
    font-weight: 800;
    font-stretch: var(--narrow);
    text-transform: var(--caps);
    line-height: 1.1;
    color: var(--ink);
}
.fb-node-count { font-family: var(--body); font-size: 11px; color: var(--accent); }
.fb-node.is-root .fb-node-inner { padding: 6px 14px 6px 6px; }
.fb-node.is-root .fb-node-name { font-size: 18px; }
.fb-node:hover .fb-node-inner { box-shadow: 0 0 0 1px var(--accent), var(--lift); }
/* The tree view's breadcrumb, under the mode switch. */
.field-path {
    position: absolute;
    top: calc(var(--header-h) + 66px);
    left: 50%;
    translate: -50% 0;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    justify-content: center;
    gap: 2px 4px;
    max-width: calc(100% - 2 * var(--gutter));
    padding: 4px 8px;
    border-radius: var(--r-sm);
    background: color-mix(in srgb, var(--ground-2) 92%, transparent);
    box-shadow: 0 0 0 1px var(--rule);
}
.field[data-mode="time"] .field-path,
.field-path:empty { display: none; }
.field-path-step {
    padding: 2px 6px;
    border: 0;
    border-radius: 4px;
    background: none;
    color: var(--ink-3);
    font-family: var(--body);
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    cursor: pointer;
}
.field-path-step:hover { color: var(--ink); background: var(--ground-3); }
.field-path-step[aria-current] { color: var(--ink); font-weight: 600; }
.field-path-sep { color: var(--ink-3); opacity: 0.5; font-size: 0.7rem; }
.field-path-open { margin-left: 4px; padding: 2px 6px; border-radius: 4px; color: var(--accent); font-size: 0.8rem; text-decoration: none; }
.field-path-open:hover { background: var(--accent); color: var(--on-accent); }
.fb-node-link {
    display: inline-grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    color: var(--ink-2);
    font-size: 12px;
    text-decoration: none;
}
.fb-node-link:hover { background: var(--accent); color: var(--on-accent); }

/* ── The instrument's controls ── */
/* Above the tree's names, which would otherwise slide over the controls. */
.field-ui { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.field-ui > * { pointer-events: auto; }

.field-modes {
    position: absolute;
    top: calc(var(--header-h) + 8px);
    left: 50%;
    translate: -50% 0;
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px;
    background: color-mix(in srgb, var(--ground-2) 96%, transparent);
    border: 1px solid var(--rule-2);
    border-radius: var(--r);
    box-shadow: var(--lift-2);
}
.field-mode-group { display: flex; }
.field-mode-group button {
    display: inline-flex;
    align-items: baseline;
    gap: 8px;
    height: 40px;
    padding: 0 18px;
    border: 0;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--ink-2);
    font-family: var(--display);
    font-size: 1.15rem;
    font-weight: 800;
    font-stretch: var(--narrow);
    text-transform: var(--caps);
    line-height: 40px;
    cursor: pointer;
    transition: background-color 0.2s, color 0.2s;
}
.field-mode-group button i {
    font-family: var(--body);
    font-size: 0.62rem;
    font-style: normal;
    font-weight: 500;
    color: var(--ink-3);
}
.field-mode-group button:hover { color: var(--ink); }
.field-mode-group button[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }
.field-mode-group button[aria-pressed="true"] i { color: var(--on-accent); opacity: 0.6; }

/* The camera, beside the arrangement it frames. */
.field-zoom {
    display: flex;
    align-items: center;
    gap: 2px;
    padding-left: 6px;
    margin-left: 2px;
    border-left: 1px solid var(--rule-2);
}
.field-zoom button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: 40px;
    min-width: 36px;
    padding: 0 8px;
    border: 0;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--ink-2);
    font-family: var(--body);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: var(--caps-tracking);
    text-transform: var(--caps);
    white-space: nowrap;
    cursor: pointer;
}
.field-zoom button:hover { background: var(--ground-3); color: var(--ink); }
.field-zoom .icon { width: 17px; height: 17px; }

.field-tools {
    position: absolute;
    right: var(--gutter);
    bottom: 24px;
    display: flex;
    align-items: center;
    gap: 8px;
}
.field-random {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    height: 46px;
    padding: 0 18px;
    border: 0;
    border-radius: var(--r);
    background: var(--accent);
    color: var(--on-accent);
    font-family: var(--body);
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: var(--caps-tracking);
    text-transform: var(--caps);
    cursor: pointer;
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 40%, transparent), var(--lift-2);
    transition: box-shadow 0.3s, transform 0.2s var(--ease);
}
.field-random:hover { box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 22%, transparent), var(--lift-2); }
.field-random:active { transform: scale(0.97); }
.field-random .icon { width: 18px; height: 18px; }

.field-tip {
    position: absolute;
    left: 0;
    top: 0;
    z-index: 20;
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-width: 280px;
    padding: 8px 12px;
    background: var(--ground-2);
    border: 1px solid var(--rule-2);
    border-left: 2px solid var(--accent);
    border-radius: var(--r-sm);
    box-shadow: var(--lift-2);
    pointer-events: none;
}
.field-tip[hidden] { display: none; }
.tip-taxon {
    font-family: var(--display);
    font-size: 1.1rem;
    font-weight: 800;
    font-stretch: var(--narrow);
    text-transform: var(--caps);
    line-height: 1.1;
}
.tip-meta { font-family: var(--body); font-size: 0.7rem; color: var(--ink-2); }

@media (max-width: 759px) {
    .field-modes { left: var(--gutter); right: var(--gutter); translate: none; }
    .field-mode-group { flex: 1; }
    .field-mode-group button { flex: 1; justify-content: center; padding: 0 6px; font-size: 1rem; }
    .field-mode-group button i { display: none; }
    /* Pinch zooms on a phone; the reset stays, as an icon with its word under it. */
    .field-zoom .field-zoom-step { display: none; }
    .field-zoom { padding-left: 4px; }
    .field-reset { flex-direction: column; gap: 1px !important; height: 40px; padding: 2px 6px !important; font-size: 0.56rem !important; letter-spacing: 0.02em !important; }
    .field-reset .icon { width: 15px; height: 15px; }
    .field-tools { left: var(--gutter); bottom: calc(16px + env(safe-area-inset-bottom)); }
    .field-tools { right: var(--gutter); }
    .field-random { flex: 1; justify-content: center; }
}

/* ── The specimen sheet ─────────────────────────────────────────────────── */
.sheet {
    position: fixed;
    z-index: 800;
    top: calc(var(--header-h) + 8px);
    right: 8px;
    bottom: 8px;
    width: min(440px, calc(100vw - 16px));
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--ground-2);
    border: 1px solid var(--rule-2);
    border-radius: var(--r-lg);
    box-shadow: var(--lift-3);
    transform: translateX(calc(100% + 24px));
    transition: transform 0.45s var(--ease);
}
.sheet[hidden] { display: none; }
.sheet.is-open { transform: none; }

.sheet-media {
    position: relative;
    flex: none;
    aspect-ratio: 4 / 3;
    background: var(--stage);
    touch-action: pan-y;
}
/* Taken out of flow so a tall photograph is letterboxed inside the frame instead of
   stretching it and pushing the details off the screen. */
.sheet-photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.sheet-prev-photo,
.sheet-next-photo {
    position: absolute;
    top: 50%;
    translate: 0 -50%;
    display: none;
    place-items: center;
    width: 38px;
    height: 38px;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    cursor: pointer;
}
.sheet-prev-photo { left: 10px; }
.sheet-next-photo { right: 10px; }
.sheet.has-many .sheet-prev-photo,
.sheet.has-many .sheet-next-photo { display: grid; }
.sheet-prev-photo .icon, .sheet-next-photo .icon { width: 18px; height: 18px; }
.sheet-count {
    position: absolute;
    left: 12px;
    top: 10px;
    padding: 3px 8px;
    border-radius: 4px;
    background: rgba(0, 0, 0, 0.6);
    color: #fff;
    font-family: var(--body);
    font-size: 0.68rem;
}
.sheet-count:empty { display: none; }
/* The caption belongs to the photograph it describes, so it sits on it. */
.sheet-media { margin: 0; }
.sheet-caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    margin: 0;
    padding: 28px 14px 10px;
    background: linear-gradient(0deg, rgba(0, 0, 0, 0.82), rgba(0, 0, 0, 0.5) 60%, transparent);
    color: #fff;
    font-size: 0.86rem;
    line-height: 1.4;
    pointer-events: none;
}
.sheet-caption:empty { display: none; }

.sheet-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px 20px 20px;
    overflow-y: auto;
}
.sheet-top { display: flex; align-items: center; gap: 10px; }
.sheet-id { font-family: var(--body); font-size: 0.7rem; color: var(--ink-3); letter-spacing: 0.06em; }
.sheet-new {
    padding: 2px 8px;
    border-radius: 4px;
    background: color-mix(in srgb, var(--accent) 16%, transparent);
    color: var(--accent);
    font-family: var(--body);
    font-size: 0.64rem;
    letter-spacing: var(--caps-tracking);
    text-transform: var(--caps);
}
.sheet-new[hidden] { display: none; }
.sheet-close {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    margin-left: auto;
    border: 1px solid var(--rule-2);
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--ink);
    cursor: pointer;
}
.sheet-close:hover { border-color: var(--accent); color: var(--accent); }
.sheet-close .icon { width: 16px; height: 16px; }
.sheet-path { display: flex; flex-wrap: wrap; gap: 2px 10px; margin: 0; }
.sheet-path:empty { display: none; }
.sheet-path a {
    font-family: var(--body);
    font-size: 0.68rem;
    letter-spacing: 0.04em;
    color: var(--ink-3);
    text-decoration: none;
}
.sheet-path a:not(:last-child)::after { content: " /"; margin-left: 10px; opacity: 0.5; }
.sheet-path a:hover { color: var(--accent); }
.sheet-taxa {
    font-family: var(--display);
    font-size: clamp(2.2rem, 4vw, 3rem);
    font-weight: 800;
    font-stretch: var(--narrow);
    line-height: 0.92;
    text-transform: var(--caps);
    overflow-wrap: anywhere;
}
.sheet-taxa a { text-decoration: none; }
.sheet-taxa a:hover { color: var(--accent); }
.sheet-when {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 6px 12px;
    padding: 10px 12px 10px 14px;
    border-radius: var(--r-sm);
    background: var(--ground-3);
    box-shadow: inset 4px 0 0 var(--band);
}
.sheet-when[hidden] { display: none; }
.sheet-age { font-family: var(--display); font-size: 1.3rem; font-weight: 700; font-stretch: 85%; }
.sheet-band {
    font-family: var(--body);
    font-size: 0.68rem;
    letter-spacing: var(--caps-tracking);
    text-transform: var(--caps);
    color: var(--band);
}
:root:not([data-theme="dark"]) .sheet-band { color: var(--ink-2); }
.sheet-place {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    width: fit-content;
    color: var(--ink);
    font-size: 1rem;
    text-decoration: none;
}
.sheet-place[hidden] { display: none; }
.sheet-place:hover .sheet-place-name { color: var(--accent); }
.sheet-place-name { text-decoration: underline; text-decoration-color: var(--rule-2); text-underline-offset: 4px; }
.sheet-actions { display: flex; align-items: center; gap: 8px; margin-top: auto; padding-top: 8px; }
.sheet-link { flex: 1; }
.sheet-nav { display: flex; gap: 6px; }
.sheet-nav button {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border: 1px solid var(--rule-2);
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--ink);
    cursor: pointer;
}
.sheet-nav button:hover { border-color: var(--accent); color: var(--accent); }
.sheet-nav .icon { width: 18px; height: 18px; }

@media (max-width: 760px) {
    .sheet {
        top: auto;
        left: 0;
        right: 0;
        bottom: 0;
        width: auto;
        max-height: 86svh;
        border-radius: var(--r-xl) var(--r-xl) 0 0;
        border-bottom: 0;
        transform: translateY(100%);
    }
    .sheet-media { aspect-ratio: auto; height: min(34svh, 62vw); }
    .sheet-taxa { font-size: 2.2rem; }
    .sheet-body { padding-bottom: calc(18px + env(safe-area-inset-bottom)); }
}

/* A multi-fossil specimen's extra copies, shown only in the tree. */
.tile.is-folded { opacity: 0 !important; pointer-events: none; }

/* A tip's name reads up its own stem, above its stack of specimens. */
.fb-node.is-tip .fb-node-inner { transform: rotate(-90deg) translate(10px, -50%); }
/* Its silhouette and link stay upright; only the words turn. */
.fb-node.is-tip :is(.fb-node-icon, .fb-node-link) { transform: rotate(90deg); }

/* On a phone the breadcrumb is one line that scrolls, not a block over the tree. */
@media (max-width: 759px) {
    .field-path {
        flex-wrap: nowrap;
        justify-content: flex-start;
        overflow-x: auto;
        scrollbar-width: none;
        white-space: nowrap;
        left: var(--gutter);
        right: var(--gutter);
        translate: none;
        max-width: none;
    }
    .field-path::-webkit-scrollbar { display: none; }
    .field-path-step, .field-path-sep, .field-path-open { flex: none; }
}
/* ── Ways of drawing the tree: a column at the right edge ── */
.field-styles {
    position: absolute;
    right: var(--gutter);
    top: 50%;
    translate: 0 -50%;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 4px;
    background: color-mix(in srgb, var(--ground-2) 96%, transparent);
    border: 1px solid var(--rule-2);
    border-radius: var(--r);
    box-shadow: var(--lift-2);
    transition: opacity 0.25s, translate 0.25s;
}
#field[data-mode="time"] .field-styles { opacity: 0; translate: 12px -50%; pointer-events: none; }
.field-styles button {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 40px;
    padding: 0 14px 0 10px;
    border: 0;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--ink-2);
    font-family: var(--display);
    font-size: 0.95rem;
    font-weight: 800;
    font-stretch: var(--narrow);
    text-transform: var(--caps);
    cursor: pointer;
    transition: background-color 0.2s, color 0.2s;
}
.field-styles button .icon { width: 22px; height: 22px; flex: none; }
.field-styles button:hover { color: var(--ink); background: var(--ground-3); }
.field-styles button[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }
@media (max-width: 759px) {
    .field-styles { right: 8px; top: 46%; }
    .field-styles button { position: relative; width: 40px; padding: 0; justify-content: center; }
    /* Icons only on a phone; the names stay for screen readers. */
    .field-styles button span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}

/* The bubbles and boxes: a thin rim at screen width, a faint fill per level. */
.fb-shapes { position: absolute; pointer-events: none; }
.fb-shape {
    fill: color-mix(in srgb, var(--ink) 3%, transparent);
    stroke: color-mix(in srgb, var(--ink) 22%, transparent);
    stroke-width: calc(1.2px / var(--ks, 0.1));
}
.fb-shape.d0 { fill: transparent; stroke-dasharray: calc(3px / var(--ks, 0.1)) calc(6px / var(--ks, 0.1)); }
.fb-shape.is-leaf { fill: color-mix(in srgb, var(--ink) 6%, transparent); }

/* A name anchored at its left end (boxes, outline) rather than its middle. */
.fb-node.is-left .fb-node-inner { transform: translate(0, -50%); }
/* Life's tree and the unclassified's question mark, where others have a silhouette. */
.fb-node-glyph {
    display: grid;
    place-items: center;
    color: var(--ground);
    font-family: var(--display);
    font-size: 17px;
    font-weight: 800;
    line-height: 1;
}
.fb-node-glyph svg { width: 18px; height: 18px; }
.fb-node.is-root .fb-node-icon { width: 32px; height: 32px; }

/* A node's painted plate fills its round mark, a little larger than a silhouette. */
.fb-node-icon.is-plate { width: 34px; height: 34px; padding: 0; object-fit: cover; }
.fb-node.is-root .fb-node-icon.is-plate { width: 40px; height: 40px; }

/* On the parchment site: names in their own case, and Life's tree in ink. */
.fb-node-name { text-transform: none; letter-spacing: 0; }
.fb-node-glyph { color: var(--ink); }
:root[data-theme="dark"] .fb-node-glyph { color: #221b12; }
/* On parchment the paler period colours (Pliocene, Pleistocene…) need darkening to be read. */
:root:not([data-theme="dark"]) .fb-band-name { color: color-mix(in srgb, var(--band) 55%, var(--ink)); }
/* With a specimen open on a wide screen, the random button steps left of its panel. */
@media (min-width: 761px) {
    .field-tools { transition: right 0.45s var(--ease); }
    html.sheet-open .field-tools { right: calc(min(440px, 100vw - 16px) + 8px + var(--gutter)); }
}

/* The site's global element styles (centred images with a margin, heading margins)
   are for documents; on the canvas and in the panel every element is placed. */
.field img, .sheet img { margin: 0; max-width: none; }
.sheet-body > * { margin: 0; }
.sheet-taxa {
    font-size: clamp(1.6rem, 3vw, 2.1rem);
    font-weight: 400;
    line-height: 1.1;
    text-transform: none;
}
.sheet-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 44px;
    padding: 0 18px;
    border-radius: 999px;
    background: var(--accent);
    color: var(--on-accent);
    text-decoration: none;
}
.sheet-link .icon { width: 18px; height: 18px; }
.sheet-link:hover { filter: brightness(1.08); }
/* The panel's buttons stay in reach however long its text runs. */
.sheet-actions {
    position: sticky;
    bottom: -20px;
    margin: 0 -20px -20px;
    padding: 10px 20px 20px;
    background: var(--ground-2);
    border-top: 1px solid var(--rule);
}
@media (max-width: 759px) {
    .sheet-taxa { font-size: 1.5rem; }
    .sheet-actions { bottom: calc(-18px - env(safe-area-inset-bottom)); margin-bottom: calc(-18px - env(safe-area-inset-bottom)); padding-bottom: calc(18px + env(safe-area-inset-bottom)); }
}
/* The world is a GPU layer only where a mouse drives it (see field.js: layered). */
@media (pointer: fine) { .field-world { will-change: transform; } }

/* ── Filters: a button beside Random, its panel opening upward ── */
.field-filter { position: relative; }
.field-filter-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 46px;
    padding: 0 16px;
    border: 1px solid var(--rule-2);
    border-radius: var(--r);
    background: var(--ground-2);
    color: var(--ink);
    font-family: var(--body);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    box-shadow: var(--lift-2);
}
.field-filter-toggle .icon { width: 18px; height: 18px; }
.field-filter-count { font-weight: 500; color: var(--ink-3); }
.field-filter.is-filtered .field-filter-toggle { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), var(--lift-2); }
.field-filter.is-filtered .field-filter-count { color: var(--accent); font-weight: 700; }
.field-filter-panel {
    position: absolute;
    right: 0;
    bottom: calc(100% + 10px);
    width: min(380px, calc(100vw - 2 * var(--gutter)));
    max-height: min(62svh, 560px);
    overflow-y: auto;
    overscroll-behavior: contain;
    touch-action: pan-y;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px;
    background: var(--ground);
    border: 1px solid var(--rule-2);
    border-radius: var(--r-lg);
    box-shadow: var(--lift-3);
}
.field-filter-panel[hidden] { display: none; }
.field-filter-q {
    width: 100%;
    box-sizing: border-box;
    height: 40px;
    padding: 0 12px;
    border: 1px solid var(--rule-2);
    border-radius: var(--r-sm);
    background: var(--ground-3);
    color: var(--ink);
    font: inherit;
    font-size: 0.95rem;
}
.field-filter-q:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.field-filter-heading { margin: 4px 0 0; font-size: 0.75rem; color: var(--ink-3); }
.field-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.field-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 32px;
    padding: 0 12px;
    border: 1px solid var(--rule-2);
    border-radius: 999px;
    background: transparent;
    color: var(--ink);
    font: inherit;
    font-size: 0.85rem;
    cursor: pointer;
}
.field-chip:hover { border-color: var(--accent); }
.field-chip.is-on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.field-chip-swatch { width: 10px; height: 10px; flex: none; border-radius: 50%; box-shadow: 0 0 0 1px var(--rule); }
/* A chosen country's localities, under it. */
.field-chip-sub { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 4px 10px; padding-left: 10px; border-left: 2px solid var(--rule-2); }
.field-chip-sub .field-chip { min-height: 28px; font-size: 0.8rem; }
.field-filter-clear {
    align-self: flex-start;
    padding: 6px 2px;
    border: 0;
    background: none;
    color: var(--accent);
    font: inherit;
    font-size: 0.85rem;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}
.field-filter:not(.is-filtered) .field-filter-clear { visibility: hidden; }
@media (max-width: 759px) {
    .field-filter-toggle { padding: 0 14px; }
    .field-filter-panel { right: auto; left: 0; }
}

/* Nothing matches: said in the middle of the canvas, with the way back. */
.field-empty {
    position: absolute;
    left: 50%;
    top: 50%;
    translate: -50% -50%;
    display: none;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 18px 24px;
    background: var(--ground-2);
    border: 1px solid var(--rule-2);
    border-radius: var(--r-lg);
    box-shadow: var(--lift-2);
    text-align: center;
}
.field.is-empty .field-empty { display: flex; }
.field-empty p { margin: 0; font-size: 1.05rem; }
.field-empty-clear { padding: 8px 16px; border: 0; border-radius: 999px; background: var(--accent); color: var(--on-accent); font: inherit; cursor: pointer; }
/* A clade chip carries its painted plate; suggestions sit just under the search box. */
.field-chip-plate { width: 22px; height: 22px; margin-left: -6px; border-radius: 50%; object-fit: cover; flex: none; }
.field-suggest:empty { display: none; }
.field-suggest .field-chip { border-style: dashed; }
