/*
Theme Name: Evenue Atlas
Description: The map is the page — a fixed two-pane instrument: ink panels floating over a desaturated map, one signal color reserved for state, a monospaced voice for coordinates and counts. Port of the legacy evenue-atlas design exploration onto the v2 starter structure.
Version: 0.5.1
Requires PHP: 8.1
Author: Evenue
Text Domain: evenue-atlas
Contract: 2.12.0
*/

/* Colors and fonts ride the --evenue-* tokens: brand = the signal (the ONE
   chromatic color, reserved for state), secondary = its deep press state,
   page-bg = the field, surface-bg = the floating panels, heading/body/muted
   text = the three type strengths. The monospaced apparatus voice, the
   fixed two-pane geometry, and the ring-and-dot pin are the design's own.
   Colour is reserved for state, never for decoration — on a map, a
   coloured thing must mean something. */

:root {
    --field: var(--evenue-page-bg);
    --panel: var(--evenue-surface-bg);
    --panel-raised: color-mix(in srgb, var(--evenue-surface-bg) 93%, var(--evenue-heading-text));
    --type: var(--evenue-heading-text);
    --type-soft: var(--evenue-body-text);
    --type-faint: var(--evenue-muted-text);
    --signal: var(--evenue-brand);
    --signal-deep: var(--evenue-secondary);
    --on-signal: var(--evenue-button-text);
    --rule: color-mix(in srgb, var(--evenue-heading-text) 12%, transparent);
    --rule-strong: color-mix(in srgb, var(--evenue-heading-text) 30%, transparent);

    --font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace; /* no --evenue-* token exists for a mono face */
    --t-coord: 0.6875rem;
    --t-meta: 0.8125rem;
    --t-name: clamp(1.125rem, 1rem + 0.5vw, 1.5rem);
    --t-title: clamp(1.75rem, 1.2rem + 2.2vw, 3rem);
    --track-coord: 0.14em;

    --radius-media: var(--evenue-image-radius);
    --radius-card: var(--evenue-container-radius);
    --radius-ui: 999px;
    --hair: var(--evenue-divider-h-weight);
    --card-shadow: var(--evenue-card-shadow);

    --gap: clamp(0.75rem, 1.5vw, 1.25rem);
    --inset: clamp(0.75rem, 1.6vw, 1.25rem);
    --panel-w: min(400px, 92vw);

    --ease: cubic-bezier(0.22, 1, 0.36, 1);
    --t-fast: 180ms;
    --t-base: 320ms;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--field);
    color: var(--type-soft);
    font-family: var(--evenue-body-font);
    letter-spacing: var(--evenue-body-letter-spacing);
    line-height: var(--evenue-body-line-height);
    font-size: 0.9375rem;
}
body.is-document { overflow: auto; height: auto; }
body.is-atlas { overflow: hidden; height: 100%; }

h1, h2, h3 {
    font-family: var(--evenue-heading-font);
    font-weight: 700;
    letter-spacing: var(--evenue-heading-letter-spacing);
    color: var(--type);
    margin: 0 0 0.5em;
}

a { color: inherit; text-decoration: none; }
:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; }
::selection { background: var(--signal); color: var(--on-signal); }

img { max-width: 100%; height: auto; display: block; }

/* The apparatus voice: every metadata string in the theme. */
.mono, .place__where, .place__coord, .card__kind, .card__meta, .doc__kind,
.doc__facts dt, .panel__nav a, .panel__counts, .listing__count, .panel__langs a, .panel__langs span, .ai-label, .legal {
    font-family: var(--font-mono);
    font-size: var(--t-coord);
    letter-spacing: var(--track-coord);
    text-transform: uppercase;
    color: var(--type-faint);
}
/* The badge shows only the short mark; its full label stays readable for
   screen readers. */
.ai-label__sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* The line under an image the plugin flags as AI-generated reads in this
   voice too, at body strength: the faint strength is the palette's muted
   text, and not every palette holds that at 4.5:1. */
.ai-label { display: block; color: var(--type-soft); }
.ai-label[hidden] { display: none; }

.skip-link {
    position: absolute;
    left: -9999px;
    z-index: 999;
    background: var(--signal);
    color: var(--on-signal);
    padding: 0.5rem 1rem;
    border-radius: var(--radius-ui);
    font-family: var(--font-mono);
    font-size: var(--t-meta);
}
.skip-link:focus { left: var(--inset); top: var(--inset); }

/* ---------- the one button ---------- */

.btn, .button {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: var(--evenue-button-padding-y) var(--evenue-button-padding-x);
    border: var(--evenue-button-border-width) solid var(--evenue-button-border-color);
    border-radius: var(--evenue-button-radius);
    background: var(--evenue-button-bg);
    color: var(--evenue-button-text);
    font-family: var(--font-mono);
    font-size: var(--evenue-button-font-size);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    cursor: pointer;
    overflow: hidden;
    isolation: isolate;
}
.btn::before, .button::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: var(--evenue-button-bg-hover);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform var(--t-base) var(--ease);
}
.btn:hover::before, .btn:focus-visible::before,
.button:hover::before, .button:focus-visible::before { transform: scaleX(1); }
.btn:hover, .btn:focus-visible, .button:hover, .button:focus-visible { color: var(--evenue-button-text-hover); }
.btn:hover .btn__mark { transform: translateX(0.3rem); }
.btn:active, .button:active { background: var(--evenue-button-bg-active); }
.btn__mark { display: inline-block; transition: transform var(--t-base) var(--ease); }

.btn--ghost {
    background: transparent;
    color: var(--type);
    box-shadow: inset 0 0 0 1px var(--rule-strong);
}

/* ---------- the atlas: fixed two-pane instrument ---------- */

.atlas {
    position: fixed;
    inset: 0;
    display: grid;
    grid-template-columns: var(--panel-w) 1fr;
}

.panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    background: var(--panel);
    border-right: var(--hair) solid var(--rule);
    z-index: 500;
}
.panel__head { display: grid; gap: 0.4rem; padding: var(--inset); border-bottom: var(--hair) solid var(--rule); }
.panel__mark {
    font-family: var(--evenue-heading-font);
    font-weight: 700;
    font-size: 1.25rem;
    letter-spacing: var(--evenue-heading-letter-spacing);
    color: var(--type);
    margin: 0;
}
.panel__mark img { height: 34px; width: auto; }
.panel__note { font-size: 0.8125rem; color: var(--type-faint); margin: 0; }
.panel__counts { display: flex; gap: 1rem; }
.panel__counts b { color: var(--signal); font-weight: 500; }
.panel__langs { display: flex; gap: 0.75rem; }
.panel__langs .current { color: var(--signal); }

/* From four languages up the codes fold into a disclosure. */
.lang-switcher--menu { position: relative; }
.lang-switcher--menu > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 0.4em; }
.lang-switcher--menu > summary::-webkit-details-marker { display: none; }
.lang-switcher--menu > summary::after { content: "\203a"; transform: rotate(90deg); transition: transform var(--t-base) var(--ease); }
.lang-switcher--menu[open] > summary::after { transform: rotate(-90deg); }
.lang-menu { position: absolute; top: 100%; left: 0; z-index: 700; display: grid; gap: 0.5rem; margin-top: 0.5rem; padding: 0.75rem 1rem; background: var(--panel-raised); border: var(--hair) solid var(--rule); border-radius: var(--radius-card); box-shadow: var(--card-shadow); }
.lang-menu .lang { color: var(--type); }

/* In-page jumps glide instead of cutting: #stay in the panel, #units on a house. Motion is a preference. */
@media (prefers-reduced-motion: no-preference) {
    html { scroll-behavior: smooth; }
    .panel__list { scroll-behavior: smooth; }
}

.panel__nav {
    display: flex;
    gap: 0.85rem;
    flex-wrap: wrap;
    padding: 0.65rem var(--inset);
    border-bottom: var(--hair) solid var(--rule);
}
.panel__nav a { position: relative; padding-bottom: 2px; }
.panel__nav a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    background: var(--signal);
    transform: scaleX(0);
    transform-origin: right center;
    transition: transform var(--t-base) var(--ease);
}
.panel__nav a:hover { color: var(--type); }
.panel__nav a:hover::after { transform: scaleX(1); transform-origin: left center; }
.panel__nav .panel__book { color: var(--signal); }

.panel__list { flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; }

.legal { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.4rem var(--gap); margin: 0; padding: 0 var(--inset) clamp(1.5rem, 4vh, 2.5rem); }
.panel .legal { justify-content: flex-start; padding: 0.65rem var(--inset); border-top: var(--hair) solid var(--rule); }
.legal a:hover { color: var(--type); }
.legal-note { margin: 0; padding: 0 var(--inset) 0.75rem; text-align: center; font-size: var(--t-meta); color: var(--type-faint); }
.panel .legal-note { padding: 0.65rem var(--inset) 0; border-top: var(--hair) solid var(--rule); text-align: left; }
.panel .legal-note + .legal { border-top: 0; padding-top: 0.4rem; }

/* A section head of the index: the set's name and its whole count, stuck at
   the top of the panel while the set's rows scroll under it. */
.panel__section {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--gap);
    margin: 0;
    padding: 0.7rem var(--inset) 0.55rem;
    background: var(--panel);
    border-bottom: var(--hair) solid var(--rule);
    font-family: var(--font-mono);
    font-size: var(--t-coord);
    font-weight: 500;
    letter-spacing: var(--track-coord);
    text-transform: uppercase;
    color: var(--type);
}
.panel__section-count { color: var(--signal); }
.place + .panel__section, .place--more + .panel__section { margin-top: 0.5rem; }

/* The index row: name / where / degree readout. */
.place {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0.15rem var(--gap);
    padding: 0.85rem var(--inset);
    border-bottom: var(--hair) solid var(--rule);
    width: 100%;
    text-align: left;
    position: relative;
    transition: background var(--t-fast);
}
.place::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: var(--evenue-divider-text-weight, 2px);
    background: var(--signal);
    transform: scaleY(0);
    transform-origin: top center;
    transition: transform var(--t-base) var(--ease);
}
.place__name {
    grid-column: 1;
    font-family: var(--evenue-heading-font);
    font-weight: 600;
    font-size: var(--t-name);
    line-height: 1.15;
    letter-spacing: var(--evenue-heading-letter-spacing);
    color: var(--type);
    transition: transform var(--t-base) var(--ease);
}
.place__where { grid-column: 1; }
.place__coord { grid-column: 2; grid-row: 1 / 3; align-self: center; text-align: right; opacity: 0.55; transition: opacity var(--t-fast), color var(--t-fast); }
@media (hover: hover) and (pointer: fine) {
    .place:hover { background: var(--panel-raised); }
    .place:hover .place__name { transform: translateX(0.35rem); }
    .place:hover .place__coord { opacity: 1; color: var(--signal); }
}
.place.is-bound, .place.is-selected, .place:focus-visible { background: var(--panel-raised); }
.place.is-bound::before, .place.is-selected::before, .place:focus-visible::before { transform: scaleY(1); }
.place.is-bound .place__coord, .place.is-selected .place__coord { opacity: 1; color: var(--signal); }

.atlas__map { background: var(--field); min-height: 0; }
.atlas__map .leaflet-container { width: 100%; height: 100%; background: var(--field); font-family: var(--font-mono); }

/* Leaflet pulled into the palette; desaturated dark tiles. The filter sits
   on the tile PANE (leaflet.css loads later and resets .leaflet-tile's own
   filter for its fade animation). */
.atlas__map .leaflet-tile-pane { filter: invert(1) hue-rotate(180deg) grayscale(0.75) brightness(0.75); }
.leaflet-control-zoom a {
    background: var(--panel) !important;
    color: var(--type) !important;
    border-color: var(--rule) !important;
}
.leaflet-control-attribution {
    background: color-mix(in srgb, var(--field) 72%, transparent) !important;
    color: var(--type-faint) !important;
    font-family: var(--font-mono);
    font-size: 0.6rem !important;
}
.leaflet-control-attribution a { color: var(--type-faint) !important; }

/* Ring-and-dot pin — legible at any zoom, grows without shifting its point. */
.pin {
    position: relative;
    display: block;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--signal) 22%, transparent);
    box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--signal) 85%, transparent) inset;
    transition: transform var(--t-base) var(--ease), background var(--t-fast);
}
.pin::after {
    content: "";
    position: absolute;
    inset: 6px;
    border-radius: 50%;
    background: var(--signal);
}
.pin.is-lifted { transform: scale(1.55); background: color-mix(in srgb, var(--signal) 42%, transparent); }

.cluster {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--field) 88%, transparent);
    box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--signal) 60%, transparent) inset;
    color: var(--signal);
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.04em;
}

/* Floating detail card. */
.card {
    position: absolute;
    left: calc(var(--panel-w) + var(--inset));
    bottom: var(--inset);
    width: min(360px, calc(100vw - var(--panel-w) - 2 * var(--inset)));
    background: var(--panel);
    border-radius: var(--radius-card);
    box-shadow: var(--card-shadow);
    overflow: hidden;
    z-index: 600;
    opacity: 0;
    transform: translateY(12px);
    visibility: hidden;
    transition: opacity var(--t-base) var(--ease), transform var(--t-base) var(--ease), visibility 0s linear var(--t-base);
}
.card.is-open { opacity: 1; transform: none; visibility: visible; transition-delay: 0s; }
.card__close {
    position: absolute;
    top: 0.6rem;
    right: 0.6rem;
    z-index: 2;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    border: 0;
    background: color-mix(in srgb, var(--field) 72%, transparent);
    backdrop-filter: blur(6px);
    color: var(--type);
    cursor: pointer;
    font-size: 0.9rem;
}
/* The frame's ratio sits on the picture, so the AI caption line can follow it inside the figure. */
.card__figure { margin: 0; }
.card__figure img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; background: var(--panel-raised); }
.card__figure > .ai-label { padding: 0.6rem var(--inset) 0; }
.card__body { display: grid; gap: 0.5rem; padding: var(--inset); }
.card__kind { color: var(--signal); }
.card__title { font-family: var(--evenue-heading-font); font-weight: 700; font-size: var(--t-name); line-height: 1.12; color: var(--type); margin: 0; }
.card__body .btn { justify-self: start; }

/* Mobile: map on top at 45vh, index below, card above the seam. */
@media (max-width: 860px) {
    .atlas { grid-template-columns: 1fr; grid-template-rows: 45vh 1fr; }
    .atlas__map { grid-row: 1; }
    .panel { grid-row: 2; border-right: 0; border-top: var(--hair) solid var(--rule); }
    .card { left: var(--inset); right: var(--inset); width: auto; bottom: calc(55vh + var(--inset)); }
}

/* No JS (or no Leaflet): the server-rendered index is the ground truth. */
html:not(.js) .atlas { position: static; display: block; }
html:not(.js) .atlas__map { display: none; }
html:not(.js) body, html:not(.js) { overflow: auto; height: auto; }

/* ---------- breadcrumbs: where a document sits ---------- */

/* The atlas has no chrome and nothing sticks: the trail opens every
   document and listing, one line in the degree-readout voice, scrollable
   on phones. The front page — the instrument itself — has no trail. */
.breadcrumbs { margin-bottom: clamp(1rem, 2.5vh, 1.5rem); font-family: var(--font-mono); font-size: var(--t-coord); letter-spacing: var(--track-coord); text-transform: uppercase; color: var(--type-faint); }
.breadcrumbs ol { display: flex; gap: 0.75rem; list-style: none; margin: 0; padding: 0; overflow-x: auto; white-space: nowrap; scrollbar-width: none; }
.breadcrumbs ol::-webkit-scrollbar { display: none; }
.breadcrumbs li { display: flex; gap: 0.75rem; align-items: center; }
.breadcrumbs li + li::before { content: "\203a"; color: var(--signal); }
.breadcrumbs a { color: var(--type-faint); }
.breadcrumbs a:hover, .breadcrumbs a:focus-visible { color: var(--type); }
.breadcrumbs [aria-current] { color: var(--type); }

/* ---------- documents: the reading column ---------- */

.doc {
    width: min(70ch, calc(100% - 4 * var(--inset)));
    margin-inline: auto;
    padding-block: clamp(3rem, 9vh, 6rem);
}
.doc__back { margin-bottom: clamp(1.25rem, 3vh, 2rem); }
/* The plate's frame (ratio, ground, corners) sits on the picture, so a flagged
   image's AI caption line follows it inside the figure instead of being clipped. */
.doc__figure { margin: 0 0 clamp(1.25rem, 3vh, 2rem); }
.doc__figure img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; background: var(--panel); border-radius: var(--radius-card); }
.doc__figure > .ai-label { padding-top: 0.6rem; }
.doc__kind { display: block; color: var(--signal); }
.doc__body + .doc__kind, .doc__gallery + .doc__kind { margin-top: clamp(1.5rem, 4vh, 2.5rem); }
.doc__kind + .doc__facts { margin-top: 0.5rem; }
.doc__title { font-size: var(--t-title); line-height: 1.06; margin: 0.5rem 0 0; }
.doc__facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 0.85rem var(--gap);
    margin: clamp(1.25rem, 3vh, 2rem) 0 0;
    padding-top: clamp(1rem, 2.5vh, 1.5rem);
    border-top: var(--hair) solid var(--rule);
}
.doc__facts dt { margin: 0; }
.doc__facts dd { margin: 0.2rem 0 0; color: var(--type); }
.doc__facts dd { overflow-wrap: anywhere; } /* an e-mail address has no break opportunity; in the second column it ran off a phone */
.doc__facts { align-items: start; }

/* An amenity ledger is a list of names with occasional notes, not a run of
   facts: the name leads in the type colour, the note follows quietly. Set
   the other way round, a two-line price note in body type shouted over the
   name it belonged to, and rows of wildly different height left the grid
   ragged. */
.doc__facts--notes dt { color: var(--type); }
.doc__facts--notes dd { font-size: 0.875rem; line-height: 1.5; color: var(--type-faint); }
.doc__facts--notes dd a { color: var(--type-faint); }
.doc__facts--notes dd a:hover { color: var(--signal); }

/* A mark that heads a section of the document — the rooms, the programme,
   what is in the room — is a heading, not the kind line under the title: at
   the coordinate size it vanished between two ledgers. */
.doc__index > .doc__kind, .doc__body + .doc__kind, .doc__gallery + .doc__kind { font-size: 0.8125rem; color: var(--type); padding-top: 0.75rem; }
.doc__index > .doc__kind { padding-inline: 0.25rem; }
.doc__body { margin-top: clamp(1.5rem, 4vh, 2.5rem); font-size: clamp(1rem, 0.92rem + 0.35vw, 1.1875rem); line-height: 1.66; }
.doc__body > * + * { margin-top: 1em; }
.doc__body a { color: var(--evenue-link); text-decoration: underline; text-underline-offset: 0.2em; }
.doc__facts dd a { color: var(--evenue-link); text-decoration: underline; text-underline-offset: 0.2em; }
.doc__body h2 { font-size: 1.5rem; font-weight: 400; line-height: 1.15; }
.doc__body h3 { font-size: 1.2rem; font-weight: 400; line-height: 1.15; }
.doc__gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 200px), 1fr));
    gap: 0.75rem;
    margin-top: clamp(1.5rem, 4vh, 2.5rem);
}
.doc__gallery img { aspect-ratio: 4 / 3; object-fit: cover; width: 100%; border-radius: var(--radius-media); }
/* The house document's section bar: stuck at the top of the page while the
   document scrolls, sections on the left, the one action in signal at the
   end. Anchor targets on that page clear it. */
.doc__nav {
    position: sticky;
    top: 0;
    z-index: 3;
    display: flex;
    gap: 0.4rem 1.25rem;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    margin-top: clamp(1rem, 2.5vh, 1.5rem);
    padding: 0.75rem 0.25rem;
    background: var(--evenue-page-bg);
    border-top: var(--hair) solid var(--rule);
    border-bottom: var(--hair) solid var(--rule);
}
.doc__nav::-webkit-scrollbar { display: none; }
.doc__nav a { position: relative; flex-shrink: 0; white-space: nowrap; color: var(--type); padding-bottom: 2px; }
.doc__nav a::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--signal); transform: scaleX(0); transform-origin: right center; transition: transform var(--t-base) var(--ease); }
.doc__nav a:hover::after { transform: scaleX(1); transform-origin: left center; }
.doc__nav-book { margin-left: auto; color: var(--signal); }
body:has(.doc__nav) [id] { scroll-margin-top: 3.25rem; }
.doc__foot { display: flex; gap: var(--gap); flex-wrap: wrap; align-items: center; margin-top: clamp(1.5rem, 4vh, 2.5rem); padding-top: clamp(1rem, 2.5vh, 1.5rem); border-top: var(--hair) solid var(--rule); }
.doc__index { margin-top: clamp(1.5rem, 4vh, 2.5rem); border-top: var(--hair) solid var(--rule); }
.doc__index .place { padding-inline: 0.25rem; }

/* ---------- listings: the index without the map ---------- */

.listing {
    width: min(880px, calc(100% - 2 * var(--inset)));
    margin-inline: auto;
    padding-block: clamp(3rem, 9vh, 6rem);
}
.listing__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding-bottom: 0.75rem;
    border-bottom: var(--hair) solid var(--rule);
}
.listing__title { font-size: var(--t-title); margin: 0; }
.listing .place { padding-inline: 0.25rem; }

/* The house filters: the panel nav's idiom — mono links, the signal for the current one. */
/* One line, never a stack: the row scrolls sideways (drag on a pointer,
   swipe on a phone) and hides its scrollbar like the trail. */
.listing__filters { display: flex; flex-wrap: nowrap; gap: 0.4rem 1rem; padding: 0.75rem 0.25rem; border-bottom: var(--hair) solid var(--rule); overflow-x: auto; scrollbar-width: none; cursor: grab; }
.listing__filters::-webkit-scrollbar { display: none; }
.listing__filters > * { flex-shrink: 0; white-space: nowrap; }
.listing__filters.dragging { cursor: grabbing; scroll-behavior: auto; }
.listing__filters.dragging a { pointer-events: none; }
.listing__filters-label { opacity: 0.7; }

/* The listing's one form: what on the left, when on the right, in the
   coordinate voice — hairline fields, no fills. */
.listing__form { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; padding: 0.75rem 0.25rem; border-bottom: var(--hair) solid var(--rule); }
.listing__search { flex: 0 1 220px; margin-right: auto; }
.listing__when { display: inline-flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.listing__form input, .listing__form select {
    font-family: var(--font-mono);
    font-size: var(--t-coord);
    letter-spacing: var(--track-coord);
    color: var(--type);
    background: transparent;
    border: 0;
    border-bottom: var(--hair) solid var(--rule-strong, var(--rule));
    padding: 0.45rem 0.25rem;
    min-width: 0;
    max-width: 100%;
}
/* The house select would take the width of its longest name; the column is 70ch. */
.listing__form select { max-width: 13rem; text-overflow: ellipsis; }
.listing__form input::placeholder { color: var(--type-faint); text-transform: uppercase; }
.listing__form input:focus, .listing__form select:focus { outline: none; border-bottom-color: var(--signal); }
.listing__form .btn { padding-block: 0.5rem; }
.listing__reset { color: var(--signal); }
@media (max-width: 640px) { .listing__search { flex-basis: 100%; margin-right: 0; } }
/* What is narrowing the listing right now, and the way off it. */
.listing__filters--on { border-bottom: 0; padding-bottom: 0.25rem; }
.listing__filters--on a { color: var(--signal); }
.listing__filters a { position: relative; padding-bottom: 2px; }
.listing__filters a::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--signal); transform: scaleX(0); transform-origin: right center; transition: transform var(--t-base) var(--ease); }
.listing__filters a:hover { color: var(--type); }
.listing__filters a:hover::after, .listing__filters a.is-current::after { transform: scaleX(1); transform-origin: left center; }
.listing__filters a.is-current { color: var(--signal); }

/* An index inside a document is named, in the kind voice, with its count. */
.doc__index > .doc__kind { padding: 0.85rem 0.25rem 0.35rem; }

/* The pager: two ghost buttons, the degree-readout voice between them. */
.pager { display: flex; align-items: center; justify-content: space-between; gap: var(--gap); margin-top: clamp(1.25rem, 3vh, 2rem); padding-top: clamp(1rem, 2.5vh, 1.5rem); border-top: var(--hair) solid var(--rule); }
.pager .btn.is-off { opacity: 0.35; }
.pager__position { white-space: nowrap; }

/* The way into the rest of a capped set: a row that is a link to the listing. */
.place--more .place__name { font-family: var(--font-mono); font-size: var(--t-meta); letter-spacing: var(--track-coord); text-transform: uppercase; color: var(--type-faint); }
.place--more:hover .place__name { color: var(--type); }
.place--more .place__coord { opacity: 1; }

/* ---------- document gallery lightbox ---------- */

.starter-lightbox {
    display: none;
    position: fixed;
    inset: 0;
    background: color-mix(in srgb, var(--field) 92%, transparent);
    z-index: 2000;
    align-items: center;
    justify-content: center;
}
.starter-lightbox.open { display: flex; }
.starter-lightbox img { max-width: 88vw; max-height: 86vh; object-fit: contain; border-radius: var(--radius-media); }
.starter-lightbox button {
    position: absolute;
    background: none;
    border: none;
    color: var(--type);
    font-size: 2.4rem;
    cursor: pointer;
    padding: 12px 20px;
    line-height: 1;
}
.lb-close { top: 12px; right: 16px; }
.lb-prev { left: 8px; top: 50%; transform: translateY(-50%); }
.lb-next { right: 8px; top: 50%; transform: translateY(-50%); }
/* The AI label of a gallery image, repeated under it; a floating panel like the rest of the instrument. */
.starter-lightbox .lb-ai { position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%); width: max-content; max-width: calc(100% - 2rem); text-align: center; margin: 0; padding: 4px 12px; background: var(--panel); color: var(--type); font-size: 0.75rem; letter-spacing: 0.06em; }

/* Booking embed: 290px holds the booking widget's stacked form, a second
   status line included. A shorter frame gets a denser form, never a cut one. */
.booking-embed { display: block; width: 100%; height: 290px; border: 0; }

/* Gallery tiles: the picture sits in a tile, so an image the plugin flags as
   AI-generated carries its label on the tile itself, not only in the lightbox.
   The label lets clicks through to the picture, which opens the lightbox. */
.gallery-tile { position: relative; display: block; }
.gallery-tile > img { display: block; }
.gallery-tile > .ai-label { position: absolute; left: 0.5rem; bottom: 0.5rem; max-width: calc(100% - 1rem); margin: 0; padding: 0.25rem 0.5rem; background: var(--panel); color: var(--type); pointer-events: none; }
