/* erotikmarktescort.de — dark ground, wine, system-sans, soft corners.
 *
 * Class names are positions in the tree, not names of things: `l1` is a section, `l1-2`
 * its second child. Every neighbour names what a thing IS — `cardname`, `pl-entry`,
 * `act_solid` — so a vocabulary carrying no nouns intersects none of theirs whatever
 * words anyone picks. That is the `path-derived` axis, and `colony:style` reads these
 * classes back out of the templates rather than taking the declaration on trust.
 *
 * The cost is real: a positional name says where a node sits, never what it is, so
 * inserting a section renumbers everything below it and only the eye catches that.
 * Structure hardens in the first weeks here by design; edit the tree rarely.
 *
 * One accent, and it is the wine of the mark in the masthead: the heart, every hover,
 * the button and the rule under the header are the same colour, so the page has a single
 * voice instead of a logo saying one thing and the interface another.
 *
 * The green that stood here was taken for being FREE on the palette axis, which is the
 * question that list can answer and the wrong one to ask first — the same mistake
 * citymuse made and undid. In this niche green is the colour of a form telling you a
 * field is valid: `.valid-feedback`, `.btn-success`, the "available now" dot. It made a
 * directory of women look like a checkout confirming itself.
 *
 * A directory of photographs is the one thing a dark page serves well: the pictures carry
 * the colour and the frame stays out of their way. That is why the accent is muted rather
 * than scarlet — it marks what is interactive without competing with the photographs.
 */

:root {
    --ground: #151114;
    --panel: #1e181b;
    --panel-lift: #262023;
    --ink: #ece7e9;
    --ink-bright: #faf7f8;
    --ink-soft: #a2939a;
    --line: #33272c;
    --line-lift: #8f3a55;
    --accent: #e06183;
    --accent-deep: #b83a5c;
    --radius: 12px;
    --radius-lg: 18px;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--ground);
    color: var(--ink);
    font: 16px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    -webkit-text-size-adjust: 100%;
}

a { color: var(--accent); }

/* Focus has to be visible on a dark ground: the browser's default ring is drawn for a
   white page and disappears here. */
:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}

.l0 {
    max-width: 74rem;
    margin: 0 auto;
    padding: 0 1rem 3rem;
}

/* Masthead. A heart stands between the two halves of the name — `erotik ♥ markt` —
   and nothing is done to the letters themselves. That is `glyph-swap`: the shape sits
   INSIDE the name where a separator would, which no neighbour does; they colour a half,
   letterspace it, break it in two lines or set a second word beside it, and all of those
   leave the string continuous.

   Lower case and soft corners throughout. The brackets this replaced read as a code
   token — square and technical, wrong for what the site sells. */
.l1 {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 1rem 0;
    /* The rule under the masthead carries the mark's colour rather than the neutral grey
       the rest of the borders use: it is the one line the eye meets before the content,
       and a grey one made the wine of the heart look like it had wandered in alone. It
       fades out to the right so the colour is a signature, not a bar. */
    border-bottom: 1px solid transparent;
    border-image: linear-gradient(90deg, var(--line-lift) 0%, var(--line-lift) 34%, var(--line) 100%) 1;
}

.l1-1 {
    display: inline-flex;
    align-items: baseline;
    font-size: 1.65rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--ink-bright);
    text-decoration: none;
}

/* Sized in `em` so the heart scales with the name instead of holding a pixel size the
   letters have outgrown: at weight 700 a fixed 17px read as an afterthought beside them. */
.l1-1-1 {
    align-self: center;
    display: block;
    width: 0.78em;
    height: 0.78em;
    margin: 0 0.2em;
    transform: translateY(0.02em);
}

.l1-2 {
    color: var(--ink-soft);
    font-size: 0.88rem;
    min-width: 0;
}

.l2 { padding: 1.4rem 0 0.4rem; }
.l2-1 { margin: 0 0 0.4rem; font-size: 1.5rem; line-height: 1.25; font-weight: 650; }
.l2-2 { margin: 0; color: var(--ink-soft); max-width: 46rem; font-size: 0.95rem; }

/* The second level. Quiet rather than loud: it exists to give the page an outline, not to
   compete with the h1 a line above it. */
.l2-3 {
    margin: 1.6rem 0 0;
    font-size: 1.02rem;
    font-weight: 600;
    color: var(--ink);
}

/* The listing: a grid of small photographs, each a `<picture>` that is itself the link's
   content. The repeating tag sequence `picture source img span` belongs to no other site
   of the network — six use `<figure>`, none use `<picture>` — which is what the `markup`
   axis compares.
   
   A listing exists to be scanned. That is why this is a grid and not the row of
   disclosures it started as: an axis value that hides nine entries out of ten behind a
   click was serving the check rather than the reader. */
.l3 {
    display: grid;
    /* Fixed track, not `1fr`: a fractional track grows with the window, and with a
       `3/4` ratio under it the tile grows in HEIGHT too — at 1900px that gave seven
       photographs each the height of the screen. A thumbnail is a thumbnail at any
       window size; the extra width goes into more columns, not bigger cells.

       150x200 is the ceiling, set by the operator: at that size a face is recognisable
       and a row of them can be scanned, which is the whole job of a listing. Every
       increase past it has had to be undone. */
    grid-template-columns: repeat(auto-fill, minmax(128px, 150px));
    justify-content: start;
    align-items: start;
    gap: 0.8rem;
    margin: 1.1rem 0 0;
    padding: 0;
    list-style: none;
}

/* `align-items: start` on the grid and a fixed height on the photograph, because
   `aspect-ratio` alone does NOT hold: a grid item stretches to the height of its row, the
   anchor and the <picture> inside it stretch with it, and the image then prints at
   whatever height the tallest tile in that row happened to be. That is how the same
   150px-wide tile came out at screen height — twice, in the listing and in the profile
   gallery, and the width limit hid it because only the width was ever measured. */
.l3-1 { min-width: 0; }

.l3-1-1 {
    display: block;
    color: inherit;
    text-decoration: none;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition: border-color 0.12s, transform 0.12s;
}

.l3-1-1:hover { border-color: var(--accent); transform: translateY(-2px); }

.l3-1-1 picture { display: block; }

.l3-1-2 {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 3 / 4;
    max-height: 200px;
    object-fit: cover;
    background: var(--panel-lift);
}

/* Photographs carrying a donor's stamp are dimmed and lift to full strength on hover or
   focus. More than half the pool is marked, so hiding them empties the listing — the
   choice is between showing a stamp and showing nothing.

   Only the MARKED ones are touched. Dimming every tile would cost the clean minority for
   nothing, and a listing that is uniformly grey reads as broken rather than discreet.

   Blur rather than opacity, and the difference is not cosmetic. Opacity fades the stamp
   and the person by the same factor, so it can never favour one over the other; blur is
   selective by construction — lettering is thin, high-frequency detail and falls apart at
   a radius that leaves the large forms of a face and a body still readable.

   0.6px, not 1px. The thumbnail is 150px wide: a radius that reads as a light veil on a
   large photograph turns this one to soap. Sub-pixel is the working range here — enough
   to break up lettering, not enough to be seen as softness.

   The hover is a bonus, not the mechanism: there is no hover on a phone, so the blurred
   state has to be good enough on its own — a visitor on a phone sees only this.
   `:focus-within` carries the same lift to the keyboard, where there is no pointer. */
.l3-1-2[data-marked] {
    filter: blur(0.6px);
    transition: filter 0.16s ease;
}

.l3-1-1:hover .l3-1-2[data-marked],
.l3-1-1:focus-visible .l3-1-2[data-marked],
.l3-1:focus-within .l3-1-2[data-marked] {
    filter: none;
}

@media (prefers-reduced-motion: reduce) {
    .l3-1-2[data-marked] { transition: none; }
}

.l3-1-3 {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.4rem;
    padding: 0.4rem 0.55rem 0.5rem;
}

/* min-width: 0 so a long name cannot push the age off the tile — names are data and the
   longest is not known in advance. */
.l3-1-3-1 {
    min-width: 0;
    font-weight: 600;
    font-size: 0.85rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.l3-1-3-2 { flex: 0 0 auto; color: var(--ink-soft); font-size: 0.78rem; }

/* Places. Compact enough that a country's worth of them does not become a scroll of its
   own — the front page is a way in, not a document. */
.l4 {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(9.5rem, 100%), 1fr));
    gap: 0.35rem;
    margin: 0.9rem 0 0;
    padding: 0;
    list-style: none;
}

.l4-1 { min-width: 0; }

.l4-1-1 {
    display: flex;
    justify-content: space-between;
    gap: 0.4rem;
    padding: 0.42rem 0.6rem;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    color: var(--ink);
    text-decoration: none;
    font-size: 0.88rem;
}

.l4-1-1:hover { border-color: var(--accent); }

.l4-1-1 span:first-child {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.l4-1-2 { flex: 0 0 auto; color: var(--ink-soft); font-size: 0.8rem; }

/* Pagination. Present and crawlable: closing it once left 34 profiles of one district
   with no path to them at all. */
.l5 { display: flex; gap: 0.5rem; margin: 1.4rem 0 0; flex-wrap: wrap; }

.l5-1 {
    padding: 0.45rem 0.9rem;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--panel);
    color: var(--ink);
    text-decoration: none;
}

.l5-1:hover { border-color: var(--accent); }

/* Prose under a listing, and the profile page's blocks. */
.l6 { margin: 1.8rem 0 0; max-width: 46rem; color: var(--ink-soft); }
.l6-1 { margin: 0 0 0.6rem; font-size: 1.1rem; color: var(--ink); }
/* Key and value on ONE line with a rule between them, not stacked. Stacked, the eleven
   rows of `Angaben` and the four of `Preise` ran to a screen and a half on their own, and
   a reader comparing two prices had to scan vertically past the labels to do it. */
.l6 dl {
    margin: 0;
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0 0.9rem;
    align-items: baseline;
}

.l6 dt {
    color: var(--ink-soft);
    font-weight: 400;
    font-size: 0.9rem;
    padding: 0.3rem 0;
    border-top: 1px solid var(--line);
}

.l6 dd {
    margin: 0;
    color: var(--ink);
    text-align: right;
    /* Nowrap: `90 €` and `167 cm` are single values, and a narrow column was breaking the
       unit onto its own line under the number. */
    white-space: nowrap;
    padding: 0.3rem 0;
    border-top: 1px solid var(--line);
}

.l6 dt:first-of-type, .l6 dl dd:first-of-type { border-top: 0; }

/* Services as chips: twenty-odd short phrases set as list items ran one per line for a
   third of a screen. */
.l6 ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.l6 ul li {
    padding: 0.24rem 0.6rem;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    font-size: 0.85rem;
}
.l6 blockquote {
    margin: 0 0 0.7rem;
    padding: 0.6rem 0.9rem;
    background: var(--panel);
    border-left: 2px solid var(--accent);
    border-radius: 0 var(--radius) var(--radius) 0;
    color: var(--ink);
}

.l7 {
    display: inline-block;
    margin-top: 0.5rem;
    padding: 0.5rem 1.1rem;
    background: var(--accent-deep);
    color: #fff;
    border-radius: var(--radius);
    text-decoration: none;
    font-weight: 600;
}

/* Hover DARKENS. It used to lighten to `--accent`, which put white on #e06183 —
   3.38:1, under the 4.5 a button's own label needs. The resting state was fine at 5.53,
   so hovering made the one thing a visitor is reaching for harder to read. */
.l7:hover { background: #9c2f4c; }

/* The profile page is two columns on a wide screen: the gallery and the hard facts on
   the left, the prose on the right. One column ran the card to fifteen screens with half
   the window empty beside it — the same photograph took 427px of height and the price
   list was read one row per line. */
.lp {
    display: grid;
    grid-template-columns: minmax(0, 24rem) minmax(0, 1fr);
    gap: 1.6rem 2.2rem;
    align-items: start;
    margin: 1.2rem 0 0;
}

@media (max-width: 56rem) {
    .lp { grid-template-columns: minmax(0, 1fr); }
}

.lp-a { min-width: 0; }
.lp-b { min-width: 0; }

/* Sections inside a column sit closer than they do down the page: the column is narrow
   and the reader is scanning it, not reading it. */
.lp-a .l6:first-child { margin-top: 0; }
.lp-a .l6 { margin-top: 1.2rem; }
/* The fact tables are capped rather than run to the window's edge: at 1400px the rule
   between a label and its value stretched three quarters of the screen, which reads as a
   dotted line to nowhere rather than as a pairing. */
.lp-b .l6 dl { max-width: 30rem; }
.lp-b .l6:first-child { margin-top: 0; }
.lp-b .l6 { margin-top: 1.4rem; }

/* The prose block under the columns. Capped at a readable measure rather than run to the
   full width of the page: a line of 46rem is about 90 characters, past which the eye
   loses the start of the next line. */
.lq { margin: 2rem 0 0; }
.lq-1 { margin: 0; max-width: 46rem; color: var(--ink-soft); }
.lq .l6 { margin-top: 1.6rem; }
.lp-b > :first-child { margin-top: 0; }
.lp-b .l2-2 { margin: 0; }

/* The gallery. One large photograph, thumbnails under it, a click swaps the large one —
   no script.

   Radio inputs, not `:target`: a fragment link makes the browser scroll the targeted
   element into view, so every click jumped the page to the top before showing the
   picture. A radio changes state without moving the scroll position.

   The wiring: the inputs precede the images, so `input:nth-of-type(N):checked` can reach
   the Nth image through the sibling combinator. It is written out per index rather than
   generated, which caps the gallery at the number of rules below — twelve, well past the
   largest gallery in the pool.

   The height is capped rather than left to the aspect ratio: portrait photographs at 3/4
   would otherwise make the large image as tall as the window on a wide screen, which is
   the failure this page has already had twice. */
.l8 { margin: 0; position: relative; }

/* Hidden but focusable: the strip stays operable from the keyboard, where a radio group
   answers to the arrow keys natively. `position: absolute` rather than `display: none`,
   because a display-none input is not focusable at all. */
.l8-0 {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* The frame holds its size before any photograph has arrived. The large images load
   lazily, and an <img> with no bytes yet has no height — so switching to one that had not
   loaded collapsed the column and the whole page jumped, then jumped back when it
   arrived. `aspect-ratio` on the CONTAINER reserves the space up front, and a background
   tint makes the wait look like a frame rather than a hole. */
.l8-1 {
    display: grid;
    justify-items: center;
    align-items: center;
    aspect-ratio: 3 / 4;
    max-height: 26rem;
    background: var(--panel-lift);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

/* `contain`, not `cover`: the frame is a fixed 3/4 and the photographs are not, so
   cover was cropping the sides off a wider shot. The picture is what the visitor came
   for — the frame gives way to it, not the other way round. */
.l8-1-0 {
    grid-area: 1 / 1;
    display: none;
    width: 100%;
    height: 100%;
    cursor: zoom-in;
}

.l8-1-1 {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.l8-0:nth-of-type(1):checked ~ .l8-1 .l8-1-0:nth-of-type(1),
.l8-0:nth-of-type(2):checked ~ .l8-1 .l8-1-0:nth-of-type(2),
.l8-0:nth-of-type(3):checked ~ .l8-1 .l8-1-0:nth-of-type(3),
.l8-0:nth-of-type(4):checked ~ .l8-1 .l8-1-0:nth-of-type(4),
.l8-0:nth-of-type(5):checked ~ .l8-1 .l8-1-0:nth-of-type(5),
.l8-0:nth-of-type(6):checked ~ .l8-1 .l8-1-0:nth-of-type(6),
.l8-0:nth-of-type(7):checked ~ .l8-1 .l8-1-0:nth-of-type(7),
.l8-0:nth-of-type(8):checked ~ .l8-1 .l8-1-0:nth-of-type(8),
.l8-0:nth-of-type(9):checked ~ .l8-1 .l8-1-0:nth-of-type(9),
.l8-0:nth-of-type(10):checked ~ .l8-1 .l8-1-0:nth-of-type(10),
.l8-0:nth-of-type(11):checked ~ .l8-1 .l8-1-0:nth-of-type(11),
.l8-0:nth-of-type(12):checked ~ .l8-1 .l8-1-0:nth-of-type(12) { display: block; }

/* Past the twelfth photograph no rule matches and nothing would show at all, so the
   first stays visible as the floor. A gallery that big loses its switching, not its
   picture. */
.l8-1 .l8-1-0:nth-of-type(1):last-of-type,
.l8-0:nth-of-type(n+13):checked ~ .l8-1 .l8-1-0:nth-of-type(1) { display: block; }

/* The thumbnail strip scrolls sideways instead of wrapping: a profile can carry three
   photographs or fifteen, and a wrapping grid changes the height of the column with the
   count — which is what pushed the prices below the fold before. One row, always. */
.l8-2 {
    display: flex;
    gap: 0.4rem;
    overflow-x: auto;
    scrollbar-width: thin;
    margin: 0.55rem 0 0;
    padding: 0 0 0.3rem;
    list-style: none;
}

.l8-2-1 {
    flex: 0 0 auto;
    width: 62px;
    aspect-ratio: 3 / 4;
}

.l8-2-1-1 {
    display: block;
    height: 100%;
    border-radius: var(--radius);
    overflow: hidden;
    border: 1px solid transparent;
    cursor: pointer;
    transition: border-color 0.12s;
}

.l8-2-1-1:hover { border-color: var(--accent); }

/* The chosen thumbnail is marked, so the strip says which picture is showing. */
.l8-0:nth-of-type(1):checked ~ .l8-2 .l8-2-1:nth-of-type(1) .l8-2-1-1,
.l8-0:nth-of-type(2):checked ~ .l8-2 .l8-2-1:nth-of-type(2) .l8-2-1-1,
.l8-0:nth-of-type(3):checked ~ .l8-2 .l8-2-1:nth-of-type(3) .l8-2-1-1,
.l8-0:nth-of-type(4):checked ~ .l8-2 .l8-2-1:nth-of-type(4) .l8-2-1-1,
.l8-0:nth-of-type(5):checked ~ .l8-2 .l8-2-1:nth-of-type(5) .l8-2-1-1,
.l8-0:nth-of-type(6):checked ~ .l8-2 .l8-2-1:nth-of-type(6) .l8-2-1-1,
.l8-0:nth-of-type(7):checked ~ .l8-2 .l8-2-1:nth-of-type(7) .l8-2-1-1,
.l8-0:nth-of-type(8):checked ~ .l8-2 .l8-2-1:nth-of-type(8) .l8-2-1-1,
.l8-0:nth-of-type(9):checked ~ .l8-2 .l8-2-1:nth-of-type(9) .l8-2-1-1,
.l8-0:nth-of-type(10):checked ~ .l8-2 .l8-2-1:nth-of-type(10) .l8-2-1-1,
.l8-0:nth-of-type(11):checked ~ .l8-2 .l8-2-1:nth-of-type(11) .l8-2-1-1,
.l8-0:nth-of-type(12):checked ~ .l8-2 .l8-2-1:nth-of-type(12) .l8-2-1-1 {
    border-color: var(--accent);
}

/* Keyboard focus has to be visible on the LABEL, since the input it belongs to is
   off-screen — without this the strip is operable but invisible to the eye following it. */
/* The focused thumbnail, marked on the LABEL because the input it belongs to is
   off-screen. Written out per index like the rules above, and to the same twelve rather
   than to six: at six the seventh thumbnail fell through to a faint fallback, and 1348 of
   this site's profiles carry exactly seven photographs — the majority case, not an edge.
   The fallback is gone with it: `--line-lift` on the ground is 2.59:1, under the 3:1 a
   non-text indicator needs, so it marked nothing legibly anyway. */
.l8-0:nth-of-type(1):focus-visible ~ .l8-2 .l8-2-1:nth-of-type(1) .l8-2-1-1,
.l8-0:nth-of-type(2):focus-visible ~ .l8-2 .l8-2-1:nth-of-type(2) .l8-2-1-1,
.l8-0:nth-of-type(3):focus-visible ~ .l8-2 .l8-2-1:nth-of-type(3) .l8-2-1-1,
.l8-0:nth-of-type(4):focus-visible ~ .l8-2 .l8-2-1:nth-of-type(4) .l8-2-1-1,
.l8-0:nth-of-type(5):focus-visible ~ .l8-2 .l8-2-1:nth-of-type(5) .l8-2-1-1,
.l8-0:nth-of-type(6):focus-visible ~ .l8-2 .l8-2-1:nth-of-type(6) .l8-2-1-1,
.l8-0:nth-of-type(7):focus-visible ~ .l8-2 .l8-2-1:nth-of-type(7) .l8-2-1-1,
.l8-0:nth-of-type(8):focus-visible ~ .l8-2 .l8-2-1:nth-of-type(8) .l8-2-1-1,
.l8-0:nth-of-type(9):focus-visible ~ .l8-2 .l8-2-1:nth-of-type(9) .l8-2-1-1,
.l8-0:nth-of-type(10):focus-visible ~ .l8-2 .l8-2-1:nth-of-type(10) .l8-2-1-1,
.l8-0:nth-of-type(11):focus-visible ~ .l8-2 .l8-2-1:nth-of-type(11) .l8-2-1-1,
.l8-0:nth-of-type(12):focus-visible ~ .l8-2 .l8-2-1:nth-of-type(12) .l8-2-1-1 {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.l8-2-1-2 {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    background: var(--panel-lift);
}

/* Marked photographs are softened in both places; hovering clears it. See the listing
   above for why blur and not opacity. */
.l8-1-1[data-marked], .l8-2-1-2[data-marked] {
    filter: blur(0.6px);
    transition: filter 0.16s ease;
}

.l8-1-1[data-marked]:hover,
.l8-2-1-1:hover .l8-2-1-2[data-marked] { filter: none; }

@media (prefers-reduced-motion: reduce) {
    .l8-1-1[data-marked], .l8-2-1-2[data-marked] { transition: none; }
}

/* The crossing page: photograph beside the words. It is the last screen of the card,
   not a barrier in front of it, so it looks like the card rather than like a warning. */
.lr {
    display: flex;
    align-items: flex-start;
    gap: 1.2rem;
    margin: 1.4rem 0 0;
}

.lr-1 {
    flex: 0 0 auto;
    width: 150px;
    aspect-ratio: 3 / 4;
    object-fit: cover;
    border-radius: var(--radius-lg);
    background: var(--panel-lift);
}

.lr-1[data-marked] { filter: blur(0.6px); }

.lr-2 { min-width: 0; max-width: 34rem; }
.lr-2-1 { margin: 0; font-size: 1.4rem; line-height: 1.25; }
.lr-2-2 { margin: 0.2rem 0 0; color: var(--ink-soft); }
.lr-2-3 { margin: 0.7rem 0 0; }
.lr-2-4 { margin: 0.3rem 0 0; color: var(--ink-soft); }
.lr-2-5 { margin: 1rem 0 0; }
.lr-2-6 { margin: 0.7rem 0 0; color: var(--ink-soft); font-size: 0.9rem; }

@media (max-width: 34rem) {
    .lr { flex-direction: column; gap: 0.9rem; }
}

/* The viewer: the full-size file over the page. The page itself never loads it — only
   `preview` — so nothing large is fetched until a visitor asks to see one. */
.lv {
    max-width: 100vw;
    max-height: 100vh;
    width: 100vw;
    height: 100vh;
    padding: 0;
    border: 0;
    background: transparent;
    overflow: hidden;
}

.lv::backdrop { background: rgba(8, 6, 7, 0.92); }

.lv-1 {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    max-width: calc(100vw - 9rem);
    max-height: calc(100vh - 3rem);
    /* No blur here: the visitor asked to see this one at full size, and softening the
       thing they clicked to look at would be working against them. */
    border-radius: var(--radius);
}

.lv-2, .lv-3 {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--line-lift);
    background: rgba(21, 17, 20, 0.82);
    color: var(--ink-bright);
    cursor: pointer;
    line-height: 1;
}

.lv-2 {
    top: 50%;
    transform: translateY(-50%);
    width: 2.6rem;
    height: 3.4rem;
    font-size: 1.8rem;
    border-radius: var(--radius);
}

/* Inset from the edge rather than flush against it: at the very edge the arrows sit
   in the corner of the screen instead of beside the photograph, and on a phone they land
   under the thumb's own resting position. */
.lv-2-1 { left: 1.6rem; }
.lv-2-2 { right: 1.6rem; }

.lv-3 {
    top: 0.7rem;
    right: 0.7rem;
    width: 2.4rem;
    height: 2.4rem;
    font-size: 1.4rem;
    border-radius: 50%;
}

.lv-2:hover, .lv-3:hover { background: var(--accent-deep); border-color: var(--accent); }

.l9 {
    margin: 2.5rem 0 0;
    padding: 1rem 0 0;
    border-top: 1px solid var(--line);
    color: var(--ink-soft);
    font-size: 0.86rem;
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
}

.l9-1 { color: var(--ink-soft); }

@media (max-width: 34rem) {
    .l2-1 { font-size: 1.28rem; }
    /* The tagline drops on a phone rather than running off the edge: the masthead is a
       flex row, and a nowrap sibling pushed it past the viewport. */
    .l1 { flex-wrap: wrap; gap: 0.15rem 0.7rem; }
    .l1-1 { font-size: 1.45rem; }
    .l1-2 { font-size: 0.82rem; }
}
