

/* ============================================================
   Visual system – components
   Cards, forms, buttons, dialogs, toasts, and the other shared
   component styles. Selectors are the PHP/JS class names.
   ============================================================ */

/* ---------- Emoji ---------- */

/* A picture of what a label means, sitting beside it. Sized against the text
   rather than in rem so it keeps step with whatever it labels, and kept on one
   line with the word it belongs to: a link that wraps between its picture and
   its name reads as two things. */
.Emoji {
    font-size: 1.1em;
    line-height: 1;
    white-space: nowrap;

    /* The emoji fonts carry their own colour, and a theme tinting them would
       only mute them. */
    color: initial;
}

/* Beside words rather than against them. A picture that is the whole of a
   control needs no gap - there is nothing to be apart from. */
.Emoji:not(:only-child) {
    margin-inline-end: 0.4em;
}

.Emoji:not(:only-child):last-child {
    margin-inline: 0.4em 0;
}

/* ---------- Cards & surfaces ---------- */

/* Everything that reads as a raised surface, listed by what it IS rather than
   composed into each one's class attribute. .Card is the plain standalone one
   (about/terms/privacy build it directly); .Form covers every form carrying
   the shared identity (see FormForm), so its subclasses are all included. The
   rule below it zeroes the trailing margin inside one, and has to name the
   same set - keep the two lists in step. */
:is(
    .Card, .Form, .SearchBox, .ThemeSelector,
    .NavDropdownMenu, .ConfirmDialogCard,
    .TestResults, .TestSuitePanel
) {
    background-color: var(--surface);
    background-image: var(--surface-image, none);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-card);
    padding: 1rem;
    box-shadow: var(--shadow-card);
    margin-bottom: 1rem;
    overflow: hidden;
}

:is(
    .Card, .Form, .SearchBox, .ThemeSelector,
    .NavDropdownMenu, .ConfirmDialogCard,
    .TestResults, .TestSuitePanel
) > *:last-child {
    margin-bottom: 0;
}

.NavDropdownMenu {
    max-height: 90vh;
    overflow-y: auto;
}

/* ---------- Animations ---------- */

@keyframes spin {
    to { transform: rotate(360deg); }
}

@keyframes mount-in {
    from { opacity: 0; transform: translateY(0.5rem); }
    to   { opacity: 1; transform: translateY(0); }
}

.LoadingSpinner {
    display: flex;
    justify-content: center;
    padding: 1rem;
}

.LoadingSpinner::after {
    content: '';
    width: 1.5rem;
    height: 1.5rem;
    border: 2px solid var(--hairline);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
}

.MountIn {
    animation: mount-in 0.25s ease;
}

.SlidingOut {
    overflow: hidden;
    opacity: 0;
    transition: height 0.2s ease, opacity 0.2s ease;
}

@media (prefers-reduced-motion: reduce) {
    .SlidingOut { transition: none; }
}

/* ---------- A refused field ---------- */

/* Under the input it is about, in the colour everything that has gone wrong
   wears. Tied to the input by aria-describedby, so it is read out on reaching
   the box rather than found by hunting - which is the whole point of putting
   it here instead of in a toast floating at the edge of the screen. */
.FieldError {
    color: var(--danger);
    font-size: 0.8125rem;
    margin: 0.25rem 0 0;
}

/* The box itself, so the eye lands on which one before reading why. */
.Field :is(input, textarea)[aria-invalid='true'] {
    border-color: var(--danger);
    outline-color: var(--danger);
}

/* ---------- Skipping the navigation ---------- */

/* Out of the way until somebody tabs to it, then a real control in the corner.
   Moved off-screen rather than hidden: display:none and visibility:hidden both
   take it out of the tab order, which is the one thing it must stay in. */
.SkipLink {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1000;
    padding: 0.75rem 1rem;
    background-color: var(--surface);
    color: var(--ink);
    border: 1px solid var(--hairline);
    border-radius: 0 0 var(--radius-card) 0;
    transform: translateY(-120%);
}

.SkipLink:focus {
    transform: translateY(0);
}

/* The content it lands on is only focusable so the jump lands - it is not a
   control, and should not draw a ring as though it were. */
#PageContent:focus {
    outline: none;
}

/* ---------- Buttons ---------- */

.Button {
    background-color: var(--surface-2);
    background-image: var(--button-image, none);
    color: var(--ink) !important;
    border: none;
    border-radius: var(--radius-pill);
    padding: 0.5rem 1rem;
    font-weight: 550;
    font-size: 0.875rem;
    line-height: 1.4;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, transform 0.1s ease, opacity 0.15s ease;
}

.Button:hover {
    background-color: color-mix(in srgb, var(--surface-2) 80%, var(--ink) 8%);
    /* Falls back to the resting image, so a theme with a gradient but no hover
       variant simply keeps the one it has rather than losing it on hover. */
    background-image: var(--button-image-hover, var(--button-image, none));
    color: var(--ink) !important;
}

.Button:active { transform: scale(0.97); }
.Button:disabled { opacity: 0.55; cursor: default; transform: none; }

/* Waiting on the server. Disabling alone only dims a control slightly and
   then nothing happens, which on anything slow reads as a press that did not
   land - so it pulses for as long as it is working. The animation beats the
   :disabled opacity above by being an animation, which is the whole reason
   this is not just another opacity rule. */
@keyframes throb {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.4; }
}

.Working {
    animation: throb 1.1s ease-in-out infinite;
    cursor: progress;
}

/* Somebody who has asked for less movement still needs to know it is working,
   so the pulse becomes a steady dimming rather than nothing at all. */
@media (prefers-reduced-motion: reduce) {
    .Working { animation: none; opacity: 0.5; }
}

/* Forms lay their fields out in a column, and the button that submits one sits
   at the trailing edge rather than stretching across it. */
.SubmitButton { align-self: flex-end; }


/* A checkbox or radio with a label wrapped round it is a control you press, so
   it takes the button's own colours and hover and keeps the box inside. The
   wrapping is what makes the whole of it the target rather than the box alone,
   so this only claims the ones built that way. */
label:has(> input[type='checkbox']),
label:has(> input[type='radio']) {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    background-color: var(--surface-2);
    background-image: var(--button-image, none);
    color: var(--ink);
    border-radius: var(--radius-pill);
    padding: 0.5rem 1rem;
    margin-bottom: 0;
    font-weight: 550;
    font-size: 0.875rem;
    line-height: 1.4;
    cursor: pointer;
    user-select: none;
    transition: background-color 0.15s ease, color 0.15s ease;
}

label:has(> input[type='checkbox']):hover,
label:has(> input[type='radio']):hover {
    background-color: color-mix(in srgb, var(--surface-2) 80%, var(--ink) 8%);
    background-image: var(--button-image-hover, var(--button-image, none));
    color: var(--ink);
}

a.Button {
    display: inline-block;
    text-align: center;
}

a.Button:hover { color: var(--ink) !important; }

emoji-picker.Active {
    opacity: 1;
    pointer-events: auto;
    display: flex;
}

.emoji-text {
    font-size: 1.25rem;
    line-height: 1;
    vertical-align: middle;
}

.emoji-only .emoji-text {
    font-size: 2.5rem;
    line-height: 1.3;
}

/* ---------- Forms (component classes) ---------- */

.CheckboxField {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.CheckboxField input { width: auto; margin: 0; }
.CheckboxField label { display: inline; margin-bottom: 0; }

.TextareaField textarea {
    width: 100%;
    resize: vertical;
}

/* Every wording the button can show, stacked in one cell so the widest of
   them sets the width once and toggling never resizes it. */
.ToggleButton {
    display: inline-grid;
    grid-template-areas: 'label';
    place-items: center;
}

.ToggleButtonLabel { grid-area: label; }

.ToggleButtonLabel.Inactive { visibility: hidden; }

.ProgressBar {
    display: none;
    width: 100%;
    height: 0.4rem;
    border-radius: var(--radius-pill);
    overflow: hidden;
    margin-top: 0.5rem;
    accent-color: var(--accent);
}

.ProgressBar.Active { display: block; }

label.visually-hidden { margin-bottom: 0; }

/* ---------- Quill editor ---------- */

.ql-toolbar.ql-snow {
    background-color: var(--surface);
    border-color: var(--hairline);
    border-top-left-radius: var(--radius-card);
    border-top-right-radius: var(--radius-card);
}

.ql-container.ql-snow {
    border-color: var(--hairline);
    border-bottom-left-radius: var(--radius-card);
    border-bottom-right-radius: var(--radius-card);
    font-size: 0.9375rem;
}

.ql-editor {
    background-color: var(--surface);
    color: var(--ink);
    min-height: 4.5rem;
    border-bottom-left-radius: var(--radius-card);
    border-bottom-right-radius: var(--radius-card);
}

.ql-editor.ql-blank::before {
    color: var(--muted);
    opacity: 1;
    font-style: normal;
    font-size: 0.9375rem;
}

.ql-snow .ql-stroke { stroke: var(--ink); }
.ql-snow .ql-fill,
.ql-snow .ql-stroke.ql-fill { fill: var(--ink); }
.ql-snow .ql-picker { color: var(--ink); }
.ql-snow .ql-picker-options {
    background-color: var(--surface);
    border-color: var(--hairline);
}

/* ---------- People ---------- */

.User { display: flex; align-items: flex-start; }

.User h2 { margin-bottom: 0.1rem; }

/* ---------- Search ---------- */

.SearchBox {
    position: relative;
    display: flex;
    align-items: center;
    padding: 0.5rem;
}

.SearchInput {
    width: 100%;
    border: none;
    background-color: transparent;
    font-size: 1rem;
}

.SearchInput:focus { box-shadow: none; }

.SearchClearButton {
    display: none;
    flex: none;
    padding: 0 0.25rem;
    border: none;
    background: none;
    color: var(--danger) !important;
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}

.SearchBox.HasQuery .SearchClearButton { display: block; }

/* The tags offered while somebody types. It lies over the top of the results,
   which is unavoidable - it belongs to the field and has to sit under it - so
   what matters is that it is never taller than the screen it is on and never
   stays up a moment longer than it is wanted. TagSuggestions.js closes it on
   Escape, on a click anywhere else, on leaving the field and on choosing. */
.TagSuggestions {
    position: absolute;
    z-index: 20;
    top: 100%;
    right: 0;
    left: 0;
    margin: 0.25rem 0 0;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--surface);
    box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 25%);
    list-style: none;

    /* Bounded by the screen rather than by how many there are. dvh rather than
       vh because a phone's address bar is part of vh and is not part of the
       room a list actually has. The ten never reach this on a desktop; a short
       screen in landscape reaches it at three. */
    overflow-y: auto;
    max-height: 24rem;
    max-height: min(24rem, 55dvh);
    overscroll-behavior: contain;
}

.TagSuggestion {
    display: flex;
    gap: 0.5rem;
    align-items: baseline;
    justify-content: space-between;
    padding: 0.5rem 0.75rem;
    cursor: pointer;
}

.TagSuggestionTitle {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.TagSuggestion .VideoCount {
    flex: none;
    color: var(--muted);
    font-size: 0.85em;
}

.TagSuggestion:hover,
.TagSuggestion.Chosen {
    background-color: var(--surface-hover, rgb(127 127 127 / 15%));
}

/* The words for the language offer, rendered by the server because they are in
   a language this page is not in. LanguagePrompt.js takes them into a dialog
   and takes this away; it is never something to read in place. */
.LanguagePrompt { display: none; }

/* ---------- Confirm dialog ---------- */

.ConfirmDialogOverlay {
    position: fixed;
    inset: 0;
    z-index: 40;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: color-mix(in srgb, black 45%, transparent);
    padding: 1rem;
}

.ConfirmDialogCard {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    width: min(24rem, 100%);
    box-shadow: var(--shadow-pop);
}

.ConfirmDialogMessage {
    color: var(--ink);
}

.ConfirmDialogInput {
    resize: vertical;
}

/* Every dialog offers its choices the same way, whoever built it: a row at the
   trailing edge, the one somebody is reaching for last and so rightmost. */
.DialogActions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 0.5rem;
}

/* Shaped like every other button on the site: the same pill, and no stretching
   to the width of the row they sit in. */
.DialogActions .Button {
    flex: none;
    border-radius: var(--radius-pill);
}

/* ---------- Test results ---------- */

.TestResultsBadge {
    display: inline-block;
    align-self: flex-start;
    padding: 0.25rem 0.5rem;
    border-radius: var(--radius-ctl);
    font-weight: 600;
    margin-bottom: 0.5rem;
}

.TestResultsPass {
    background-color: var(--accent-soft);
    color: var(--accent-strong);
}

.TestResultsFail {
    background-color: var(--danger-soft);
    color: var(--danger);
}

.TestResultsOutput {
    margin: 0;
    padding: 0.5rem;
    border-radius: var(--radius-ctl);
    background-color: var(--surface-2);
    color: var(--ink);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;
    line-height: 1.5;
    white-space: pre-wrap;
    overflow-x: auto;
}

/* ---------- Error & error list ---------- */

.Error { color: var(--danger); }

.ErrorList {
    background-color: var(--danger-soft);
    border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent);
    border-radius: var(--radius-ctl);
    padding: 0.5rem 1rem;
    list-style: none;
    margin: 0;
    color: var(--danger);
}

/* ---------- Settings sections (fold‑outs) ---------- */

.SettingsSection {
    border-top: 1px solid var(--hairline);
}

.SettingsSection:last-of-type {
    border-bottom: 1px solid var(--hairline);
}

.SettingsSection > summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    cursor: pointer;
    padding-block: 1rem;
    list-style: none;
    font-family: var(--display-font);
    font-weight: 640;
    font-size: 1.2rem;
    line-height: 1.2;
    letter-spacing: -0.01em;
}

.SettingsSection > summary::-webkit-details-marker {
    display: none;
}

.SettingsSection > summary:hover {
    color: var(--accent);
}

.SettingsSection > summary::after {
    content: '';
    flex: none;
    width: 0.5rem;
    height: 0.5rem;
    border-right: 2px solid var(--muted);
    border-bottom: 2px solid var(--muted);
    transform: rotate(45deg);
    transition: transform 0.15s ease;
}

.SettingsSection[open] > summary::after {
    transform: rotate(-135deg);
}

.SettingsSection[open] > :last-child {
    margin-bottom: 1.25rem;
}

/* ---------- Toasts ---------- */
.ToastContainer {
    position: fixed;
    bottom: 1rem;
    right: 1rem;
    z-index: 30;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    width: min(22rem, calc(100vw - 2rem));
}

.Toast {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    background-color: var(--surface);
    border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-pop);
    padding: 0.5rem 1rem;
    color: var(--ink);
    font-size: 0.875rem;
    opacity: 0;
    transform: translateY(0.5rem);
    transition: opacity 0.2s ease, transform 0.2s ease;
}

.Toast.Active {
    opacity: 1;
    transform: translateY(0);
}

.ToastMessage {
    flex: 1 1 auto;
}

.ToastCloseButton {
    background: none;
    border: none;
    padding: 0;
    line-height: 1;
    color: var(--muted);
    cursor: pointer;
    transition: color 0.15s ease;
}

.ToastCloseButton:hover {
    color: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
    .Toast {
        transition: none;
    }
}
/* ---------- Content grids and cards ---------- */

.SceneList,
.GalleryList,
.PerformerList {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 1rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.SceneList > li,
.GalleryList > li,
.PerformerList > li {
    display: contents;
}

.SceneCard,
.GalleryCard,
.PerformerCard {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    color: var(--ink);
    text-decoration: none;
}

.CardThumb {
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: 0.5rem;
    background: var(--surface-2);
    box-shadow: var(--shadow-card);
}

.PerformerCard .CardThumb {
    aspect-ratio: 3 / 4;
}

.CardThumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.SceneCard:hover .CardThumb img,
.GalleryCard:hover .CardThumb img,
.PerformerCard:hover .CardThumb img,
.PerformerChip:hover .CardThumb img {
    transform: scale(1.03);
    transition: transform 0.15s ease-out;
}

.DurationBadge,
.CardThumb .ImageCount {
    position: absolute;
    right: 0.35rem;
    bottom: 0.35rem;
    padding: 0.05rem 0.35rem;
    border-radius: 0.25rem;
    background: rgb(0 0 0 / 0.75);
    color: #fff;
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
}

.CardTitle {
    font-weight: 600;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.SceneCard .RelativeTime,
.GalleryCard .RelativeTime,
.PerformerCard .VideoCount {
    color: var(--muted);
    font-size: 0.82rem;
}

/* ---------- Tag chips ---------- */

.TagList,
.SceneTagList,
.GalleryTagList,
.ScenePerformerList,
.GalleryPerformerList {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.TagList {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
}

.TagCard,
.TagChip {
    display: inline-flex;
    align-items: baseline;
    gap: 0.4rem;
    padding: 0.3rem 0.7rem;
    border: 1px solid var(--hairline);
    border-radius: 999px;
    background: var(--surface);
    color: var(--ink);
    text-decoration: none;
}

.TagCard .VideoCount {
    color: var(--muted);
    font-size: 0.8rem;
}

.PerformerChip {
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3rem 0.7rem;
    border: 1px solid var(--hairline);
    border-radius: 999px;
    background: var(--surface);
    color: var(--ink);
    text-decoration: none;
}

.PerformerChip .CardThumb {
    width: 2rem;
    aspect-ratio: 1;
    border-radius: 50%;
    box-shadow: none;
}

.PerformerChip .CardTitle {
    font-weight: 500;
    -webkit-line-clamp: 1;
}

/* ---------- Detail pages ---------- */

.SceneEmbed {
    width: 100%;
    aspect-ratio: 16 / 9;
    border: 0;
    border-radius: 0.5rem;
    background: #000;
    box-shadow: var(--shadow-card);
}

.ContentMeta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1rem;
    margin: 0.75rem 0;
    color: var(--muted);
}

/* Pushed to the end of the row on a line wide enough to hold them, and simply
   next in the row on one that is not - a phone puts them on their own line
   under the duration rather than squeezing five things onto one. */
.ContentControls {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
    margin-left: auto;
}

/* The flag is a control standing beside the thumbs, so it is shaped like one:
   the same pill, padding and weight the Button class gives them, rather than
   the bare faded glyph it is under a comment - there it sits in a line of
   text, here it sits in a row of buttons. */
.ContentControls .ReportButton {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    background-color: var(--surface-2) !important;
    background-image: var(--button-image, none);
    border-radius: var(--radius-pill);
    padding: 0.5rem 1rem;
    font-weight: 550;
    font-size: 0.875rem;
    line-height: 1.4;
    opacity: 1;
}

.ContentControls .ReportButton:hover {
    background-color: color-mix(in srgb, var(--surface-2) 80%, var(--ink) 8%) !important;
    background-image: var(--button-image-hover, var(--button-image, none));
    opacity: 1;
}

@media (max-width: 30rem) {
    .ContentControls {
        margin-left: 0;
    }
}

.ContentMeta .DurationBadge {
    position: static;
    background: var(--surface-2);
    color: var(--ink);
}

.ContentDescription {
    max-width: 70ch;
    color: var(--ink);
}

.Scene,
.Gallery {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.Performer,
.Tag {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    margin-bottom: 1.25rem;
}

.Performer img {
    width: 10rem;
    border-radius: 0.5rem;
    box-shadow: var(--shadow-card);
}

/* ---------- Gallery images and lightbox ---------- */

.GalleryImageList {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 0.5rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.GalleryImageList > li {
    display: contents;
}

.GalleryImage img {
    width: 100%;
    height: auto;
    display: block;
    border-radius: 0.35rem;
}

.Lightbox {
    position: fixed;
    inset: 0;
    z-index: 1050;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    background: rgb(0 0 0 / 0.92);
}

.Lightbox img {
    max-width: calc(100vw - 7rem);
    max-height: 100vh;
    object-fit: contain;
}

/* Which of how many, along the bottom. Also what names the window, so somebody
   arriving by keyboard is told where in the gallery they have landed rather
   than only that something opened. */
.LightboxCaption {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    margin: 0;
    padding: 0.75rem;
    color: rgb(255 255 255 / 0.85);
    font-size: 0.875rem;
    text-align: center;
    pointer-events: none;
}

.LightboxPrevButton,
.LightboxNextButton {
    flex: 0 0 auto;
    width: 2.75rem;
    height: 2.75rem;
    border: 0;
    border-radius: 50%;
    background: rgb(255 255 255 / 0.12);
    color: #fff;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
}

/* ---------- Age gate ---------- */

.AgeGate {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgb(0 0 0 / 0.85);
    backdrop-filter: blur(14px);
}

body:has(.AgeGate) {
    overflow: hidden;
}

.AgeGateDialog {
    max-width: 32rem;
    padding: 2rem;
    border-radius: 0.75rem;
    background: var(--surface);
    color: var(--ink);
    box-shadow: var(--shadow-pop);
}

.AgeGateDialog .DialogActions {
    margin-top: 1.25rem;
}

/* The quieter of the two choices, and still a button. */
.AgeGateLeaveButton {
    text-decoration: none;
}

/* ---------- Translation editor ---------- */

.TranslationTypeField {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.TranslationBase {
    padding: 0.5rem 0.75rem;
    border-left: 3px solid var(--hairline);
    color: var(--muted);
}

.TranslationBase:empty {
    display: none;
}

/* ---------- Reports ---------- */

/* Under the controls row, and invisible until the flag in that row opens it -
   no card, no space taken, nothing to reflow when it appears. */
.SceneReportForm {
    display: contents;
}

.SceneReportForm fieldset {
    display: none;
}

.SceneReportForm.Open fieldset {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    width: 100%;
    max-width: 40rem;
    margin: 0 0 1rem;
    padding: 0;
    border: none;
}

.SceneReportList {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.SceneReportCard {
    padding: 1rem;
    border: 1px solid var(--hairline);
    border-radius: 0.5rem;
    background: var(--surface);
}

.SceneReportActions {
    display: flex;
    gap: 0.75rem;
    margin-top: 0.5rem;
}

.SceneTombstone {
    padding: 2rem;
    border: 1px solid var(--hairline);
    border-radius: 0.5rem;
    background: var(--surface-2);
    color: var(--muted);
}

/* ---------- The same page in every language ---------- */

/* At the foot, wrapping rather than scrolling: it is fifty short names and a
   reader hunting for theirs should see the whole set at once. Each name is
   left in its own script's direction - a Hebrew or Arabic name reads its own
   way inside a list running the page's. */
.LanguageLinks {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 0.75rem;
    margin-top: 2rem;
    padding-top: 1rem;
    border-top: 1px solid var(--hairline);
    font-size: 0.8125rem;
}

.LanguageLink {
    color: var(--muted);
    unicode-bidi: isolate;
}

.LanguageLink:hover { color: var(--accent); }

/* The one already being read: still listed, since it is one of this page's
   addresses, but not offered as somewhere to go. */
.LanguageLink[aria-current='true'] {
    color: var(--ink);
    font-weight: 600;
}

/* ---------- Thumbs up, thumbs down ---------- */

.VoteButtons {
    display: flex;
    gap: 0.5rem;
}

.VoteButton {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.VoteCount {
    font-variant-numeric: tabular-nums;
}

/* The one this reader pressed. A toggle that looks the same pressed as unpressed
   is a button you cannot tell you have used. */
.VoteButton[aria-pressed='true'] {
    background-color: var(--accent);
    background-image: var(--accent-image, none);
    color: var(--accent-ink) !important;
}

/* ---------- Comments ---------- */

/* The notice standing in for an empty list takes the room the list would have
   had, so nothing shifts when the first item arrives and replaces it. */
.EmptyListNotice {
    margin: 1rem 0;
}

.CommentList {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    list-style: none;
    /* The same rem above the first comment as between any two of them - the
       tags sit directly against it otherwise. */
    margin: 1rem 0;
    padding: 0;
}

.Comment {
    padding: 0.75rem;
    border: 1px solid var(--hairline);
    border-radius: var(--radius-ctl);
    background-color: var(--surface);
}

.CommentHead {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin-bottom: 0.25rem;
    font-size: 0.8125rem;
    color: var(--muted);
}

.CommentAuthor {
    font-weight: 600;
    color: var(--ink);
}

/* Whatever somebody typed, kept as they typed it - line breaks included -
   without letting a long unbroken string push the column wider than the page. */
.CommentBody {
    margin: 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* ---------- Reporting ---------- */

/* A flag and nothing else: no padding of a button's, no background, so it sits
   in a comment's head as a mark rather than a control competing with the name
   beside it. */
.ReportButton {
    background: none !important;
    border: none;
    padding: 0.1rem 0.25rem;
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity 0.15s ease;
}

.ReportButton:hover { opacity: 1; }

.CommentReportButton { margin-left: auto; }
