/*
 * Styles for the shared media controls: the upload picker, the preview grid, and the viewer.
 *
 * Loaded by the shared layout on every page, for the same reason tabs.css is: the controls are
 * shared, so any page that renders one gets its appearance without also remembering to add a
 * stylesheet link. Everything here is namespaced under .media- so it cannot reach anything else.
 *
 * Colours come from the site's own custom properties so both themes work without a second palette.
 */

/* Every preview occupies the same box whatever shape the picture is, so a column of them lines up.
   object-fit keeps the picture's own proportions inside that box rather than stretching it. */
.media-preview-image {
    display: block;
    width: 48px;
    height: 48px;
    border-radius: 6px;
    object-fit: cover;
    object-position: center top;
}

.media-caption {
    font-size: 0.85rem;
    line-height: 1.3;
}

.media-title {
    display: block;
    font-weight: 600;
    overflow-wrap: anywhere;
}

.media-meta {
    display: block;
    color: var(--text-muted, #666);
}

/* "Not ready to show" rather than a warning about what unpublished does not mean: the object stays
   at its address either way, and the badge is not the place to explain that. */
.media-badge-draft {
    display: inline-block;
    padding: 0 0.35rem;
    border-radius: 0.25rem;
    background: var(--warning-surface, #fef3c7);
    color: var(--warning-text, #92400e);
    font-size: 0.75rem;
    font-weight: 600;
}

/* The file picker and the paste target, side by side: two ways to answer one question. Wraps on a
   narrow screen rather than squeezing the picker, which is the one that must stay usable. */
.media-add-source {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
}

.media-add-source input[type="file"] {
    /* site.css gives every input width:100%, which would push the paste target onto its own row. */
    width: auto;
    flex: 0 1 auto;
    margin-bottom: 0;
}

/* Dashed, because a dashed border is the established "drop something here" idiom and this box is
   not a button that does something on its own. */
.media-add-paste {
    /* 160, not 220. Measured: the form column is 516px and the file picker takes 299 of it, so a
       220px basis did not fit beside it and wrapped to its own row -- which is the one thing this
       control must not do, since sitting beside the picker is what says the two are alternatives.
       It still grows into whatever is left. */
    flex: 1 1 160px;
    min-width: 0;
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8px 12px;
    border: 2px dashed var(--line, #e2e5ea);
    border-radius: 8px;
    color: var(--text-muted, #666);
    font-size: 13px;
    text-align: center;
    cursor: copy;
}

/* Focus has to be obvious: this is reachable by Tab and is where a keyboard user aims a paste. */
.media-add-paste:focus-visible,
.media-add-paste.media-add-paste-active {
    border-color: var(--blue, #2563eb);
    border-style: solid;
    color: var(--navy, #0f172a);
    outline: none;
}

/* The replace form's file input, given room rather than sitting flush against the paragraph that
   explains it. The action row below it carries its own margin from .admin-create-actions. */
.media-replace-form input[type="file"] {
    display: block;
    margin-top: 10px;
}

/* The "this owner already has one" question, shown only when there is something to displace. */
.media-add-displace fieldset {
    border: 1px solid var(--line, #e2e5ea);
    border-radius: 8px;
    padding: 12px 14px;
    margin: 0;
}

.media-add-displace legend {
    font-weight: 600;
    padding: 0 6px;
}

/* The picture being displaced, beside what it is, so the choice is made looking at the thing it
   affects rather than at its title. */
.media-add-current {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 10px;
}

.media-add-current-shot {
    width: 56px;
    height: 56px;
    object-fit: cover;
    border-radius: 6px;
    background: var(--surface-muted, #f1f3f5);
}

/* Each answer is a whole row, so the label is part of the target rather than a word beside it.

   THE SELECTOR IS DELIBERATELY TWO CLASSES DEEP. site.css:806 styles every `label` as a bold block
   and every `input` as a full-width bordered box, which is right for a text field and wrong for a
   tick: a radio rendered at width:100% with padding and a border draws its glyph centred in an
   invisible full-width box, which is what put the circle in the middle of the row with its text
   stranded beside it. `.media-add-row .media-add-choice` outranks `.media-add-row > label`, so this
   holds whether the choice sits directly in the row or inside the fieldset. */
.media-add-row .media-add-choice {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    margin-bottom: 0;
    /* An option is not a field label. Bolding both makes the question and its answers compete. */
    font-weight: 400;
    cursor: pointer;
}

.media-add-row .media-add-choice input[type="radio"],
.media-add-row .media-add-choice input[type="checkbox"] {
    /* Undoing the text-field treatment, one property at a time rather than with `all: unset`,
       which would also discard the browser's own tick rendering and accessibility affordances. */
    width: auto;
    flex: none;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
}

.media-add-row .media-add-choice span {
    /* The text takes the rest of the row and wraps within it, rather than pushing the tick around. */
    flex: 1 1 auto;
}

/* A draft photograph on an administrative screen, badged so it stays obvious that a coach is not
   seeing this. Wrapping rather than a pseudo-element because CSS cannot put generated content
   inside an <img>, and absolute rather than inline so the badge costs no layout: a draft
   photograph occupies exactly the space a published one does, and a row of athletes does not
   change height because one of them is unpublished. */
.athlete-photo-draft {
    position: relative;
    display: inline-flex;
}

.athlete-photo-draft > .media-badge-draft {
    position: absolute;
    left: 50%;
    bottom: 0;
    transform: translateX(-50%);
    white-space: nowrap;
    /* The badge is a label on the picture, not a target. Clicks belong to whatever the photograph
       sits inside -- usually a link to the athlete. */
    pointer-events: none;
}

/* The viewer dialog's own chrome.

   .fs-dialog sets padding:0 and a 420px width, which suits the confirmation prompts it was written
   for and not a photograph: the picture ran edge to edge in a narrow column and the Close button sat
   against the border, so the dialog read as unfinished. .fs-dialog-body had no rule at all --
   nothing anywhere in the product styled it. */
.media-viewer-dialog {
    width: min(720px, calc(100vw - 32px));
}

.media-viewer-dialog .fs-dialog-body {
    padding: clamp(18px, 4vw, 24px);
}

/* The round dismiss button, shown only on a narrow screen.

   On a phone the Close button at the bottom can be a whole screen of scrolling away, below a tall
   photograph, which reads as a dialog you cannot get out of. This is the control every phone
   application puts in that corner, so it needs no explaining.

   It is hidden on a wide screen rather than always shown: there the Close button is already visible
   without scrolling, and two ways to dismiss one dialog is clutter, not choice. */
.media-viewer-topbar {
    display: none;
}

@media (max-width: 640px) {
    .media-viewer-topbar {
        /* Sticky, not absolute: the dialog scrolls, and a button that scrolls away with the picture
           is the problem this is meant to solve. Zero height so it takes no space of its own and the
           picture still starts at the top of the dialog. */
        display: block;
        position: sticky;
        top: 0;
        z-index: 2;
        height: 0;
        overflow: visible;
    }

    .media-viewer-dismiss {
        position: absolute;
        top: 10px;
        right: 10px;
        /* 44px is the smallest target a finger hits reliably. */
        width: 44px;
        height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        padding: 0;
        border: 0;
        border-radius: 50%;
        cursor: pointer;
        /* Dark translucent, because it sits over a photograph whose colours are unknown: a light
           button disappears against a light picture. */
        color: #fff;
        background: rgba(17, 24, 39, 0.62);
        backdrop-filter: blur(3px);
        -webkit-backdrop-filter: blur(3px);
        box-shadow: 0 2px 10px rgba(10, 14, 22, 0.28);
    }

    .media-viewer-dismiss svg {
        width: 22px;
        height: 22px;
    }

    .media-viewer-dismiss:hover,
    .media-viewer-dismiss:focus-visible {
        background: rgba(17, 24, 39, 0.82);
    }

    .media-viewer-dismiss:focus-visible {
        outline: 2px solid #fff;
        outline-offset: 2px;
    }

    /* The dialog fills a phone screen, the way a phone application's image view does. */
    .media-viewer-dialog {
        width: calc(100vw - 16px);
    }

    /* One margin for everything in the dialog, so the caption, the facts table and the button all
       begin and end on the same two vertical lines. The desktop padding (up to 24px) costs about a
       seventh of a phone's width, which is what pushed the text into a narrower column than the
       button below it and made the two look unrelated. */
    .media-viewer-dialog .fs-dialog-body {
        padding: 14px;
    }

    .media-viewer-dialog .fs-dialog-actions {
        padding: 12px 14px;
    }

    /* Full width, the way a phone application's dismiss button is. It also makes the button the
       same width as the lines of text above it, which is the point: they read as one block rather
       than as a column of text with an unrelated control underneath. */
    .media-viewer-dialog .fs-dialog-actions .btn {
        width: 100%;
    }
}

.media-viewer-dialog .fs-dialog-actions {
    margin-top: 0;
    padding: 14px clamp(18px, 4vw, 24px);
    border-top: 1px solid var(--line, #e5e7eb);
}

.media-viewer {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

/* A tall picture must not push the buttons off the bottom of the screen. The dialog scrolls, but a
   viewer you have to scroll to close is a viewer that looks broken. */
.media-viewer-dialog .media-viewer-image {
    max-height: min(60vh, 560px);
    object-fit: contain;
    background: var(--surface-muted, #f4f4f5);
}

.media-viewer .media-title {
    margin: 0.25rem 0 0;
    font-size: 1.05rem;
}

/* The facts read as a table, not as a scattered grid.

   The shared .fs-facts layout puts fields in three columns, which suits a profile of short values
   and not this: one field here is a hundred-character address, so it was squeezed into a third of
   the width and wrapped over four lines while two thirds of the row sat empty. Scoped to
   .media-viewer so every other page using .fs-facts is untouched. */
.media-viewer .fs-facts {
    display: block;
    margin: 0.85rem 0 0;
    border: 1px solid var(--line, #e5e7eb);
    border-radius: 0.5rem;
    overflow: hidden;
}

.media-viewer .fs-fact {
    display: grid;
    grid-template-columns: minmax(110px, 26%) 1fr;
    gap: 0 1rem;
    align-items: baseline;
    padding: 0.5rem 0.75rem;
    border-top: 1px solid var(--line, #e5e7eb);
}

.media-viewer .fs-fact:first-child {
    border-top: 0;
}

/* Striping, so the eye tracks across a row rather than drifting between columns. */
.media-viewer .fs-fact:nth-child(even) {
    background: var(--surface-muted, #f8fafc);
}

.media-viewer .fs-fact dt {
    margin: 0;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted, #6b7280);
}

.media-viewer .fs-fact dd {
    margin: 0;
    /* A long address breaks anywhere rather than pushing the dialog wider than the screen. */
    overflow-wrap: anywhere;
}

/* Below the label, not beside it, once the row is too narrow to hold both. */
@media (max-width: 640px) {
    .media-viewer .fs-fact {
        grid-template-columns: 1fr;
        gap: 2px;
    }
}

/* A state worth seeing at a glance: whether the product shows this, and whether it is really here
   or borrowed from somebody else's server. */
.media-fact-chip {
    display: inline-block;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.5;
    vertical-align: baseline;
}

.media-fact-chip.is-on,
.media-fact-chip.is-stored {
    color: var(--success-text, #166534);
    background: var(--success-bg, #dcfce7);
}

.media-fact-chip.is-off {
    color: var(--warning-text, #92400e);
    background: var(--warning-bg, #fef3c7);
}

.media-fact-chip.is-link {
    color: var(--info-text, #1e40af);
    background: var(--info-bg, #dbeafe);
}

.media-fact-when {
    color: var(--text-muted, #6b7280);
}

.media-viewer-frame,
.media-viewer-video,
.media-viewer-image {
    width: 100%;
    max-width: 100%;
    border: 0;
    border-radius: 0.4rem;
}

.media-viewer-frame,
.media-viewer-video {
    aspect-ratio: 16 / 9;
}

.media-viewer-image {
    height: auto;
}

.media-viewer-description {
    margin: 0;
    color: var(--text-muted, #666);
    /* Same reason as .media-viewer .fs-fact dd above, and it was missed here. A description often
       carries a source address -- "Public domain. Source: https://commons.wikimedia.org/..." -- and
       an unbroken one pushed the whole page wider than the screen: 487px of content in a 390px
       viewport on the media item page, measured. */
    overflow-wrap: anywhere;
}

/* The generated placeholder. Inline SVG, never a data: URI -- a data: URI needs its own
   Content-Security-Policy allowance, and a later narrowing of that policy would silently blank
   every placeholder on the site with nothing in any log to say why. */
.media-placeholder {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
}

/* An athlete photograph reuses the avatar's box so the two are interchangeable in place: the
   monogram rules already set the size, the shadow and the responsive shrink, and only the shape and
   the crop have to be added for a real picture. Repeating the sizes here instead would mean two
   copies of the phone breakpoint, and one of them would eventually be missed. */
img.profile-avatar,
img.compare-report-photo {
    border-radius: 50%;
    object-fit: cover;
    /* Faces sit near the top of a portrait, so a centre crop cuts foreheads. */
    object-position: center top;
}

/* A wrapper that exists only to hold an id the photo element itself cannot keep, because that
   element is replaced in place. display:contents removes the wrapper from layout entirely, so the
   photograph or monogram inside behaves exactly as it did when it was the hero's direct child. */
.hero-avatar-slot {
    display: contents;
}

/* Row actions wrap rather than widening the column: a media list is already wide, and a horizontal
   scrollbar caused by three buttons is a worse trade than two lines in one cell. */
.media-row-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    justify-content: flex-end;
}

/* The add and item pages: the form beside a preview of what will actually be stored, collapsing to
   one column when there is no room for two. The preview is the point of having a page rather than a
   dialog, so it gets equal width rather than a sidebar's worth. */
.media-add-layout {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: 20px;
    align-items: start;
}

.media-add-row {
    margin-bottom: 16px;
}

.media-add-row > label {
    display: block;
    font-weight: 600;
    margin-bottom: 4px;
}

.media-add-row input[type="text"],
.media-add-row input[type="url"],
.media-add-row select,
.media-add-row textarea {
    width: 100%;
}

/* A required field that has been left empty, marked only after somebody has touched it. Outlining
   an untouched field in red on page load reads as an error the reader has already made. The colour
   is not the only signal -- the label carries the asterisk and the refusal says what is wrong --
   because a red border alone says nothing to anyone who cannot see it. */
.media-add-invalid {
    border: 2px solid var(--danger, #b91c1c);
    outline: none;
}

.media-add-invalid:focus-visible {
    outline: 2px solid var(--danger, #b91c1c);
    outline-offset: 2px;
}

.media-add-rules {
    margin: 6px 0 0;
    font-size: 0.85rem;
    color: var(--text-muted, #666);
}

.media-add-error {
    margin: 12px 0 0;
    color: var(--danger, #b91c1c);
    font-weight: 600;
}

.media-add-preview-shots {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    margin-bottom: 16px;
}

.media-add-shot {
    margin: 0;
}

.media-add-shot img {
    display: block;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--surface-soft);
}

.media-add-shot figcaption {
    margin-top: 4px;
    font-size: 0.8rem;
    color: var(--text-muted, #666);
}

.media-item-viewer {
    margin-bottom: 16px;
}


/* The media panel above a scouting report's key characteristics.

   One line until asked. The toggle reads as a control rather than a heading, because the panel is
   supporting material for the report beside it and should not compete with the report's own
   headings for attention. */
/* Its own panel above the report, so the pictures read as belonging to the athlete rather than to
   the revision being read. */
.report-media-card {
    position: relative;
    margin-bottom: 20px;
}

.report-media-heading {
    margin: 0 0 10px;
    /* Room for the dismiss button, so a long heading cannot run underneath it. */
    padding-right: 44px;
}

/* The X, in the corner where a panel's close control belongs. */
.report-media-dismiss {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 50%;
    background: transparent;
    color: var(--text-muted, #6b7280);
    cursor: pointer;
}

.report-media-dismiss:hover,
.report-media-dismiss:focus-visible {
    border-color: var(--line, #e5e7eb);
    background: var(--surface-muted, #f4f4f5);
    color: inherit;
}

/* What the panel leaves behind. Sized like any other secondary button, because that is what it is:
   one control in place of the panel, never both at once. */
.report-media-show {
    margin-bottom: 20px;
}

/* Author CSS beats the browser's built-in `[hidden] { display: none }` rule at equal specificity,
   and `.btn` sets `display: inline-block` — so the button stayed visible beside the very panel it
   exists to reopen. The same trap is called out in tabs.css and multi-select-dialog.css; this is
   the third element to fall into it, so it is spelled out again rather than assumed known. */
.report-media-show[hidden] {
    display: none;
}

.report-media-card[hidden] {
    display: none;
}

.report-media-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 10px;
}

/* A tile is a button so it is reachable by keyboard and announced as something that opens. Its
   padding and border are stripped because the picture is the control. */
.report-media-tile {
    display: block;
    padding: 0;
    border: 1px solid var(--line, #e5e7eb);
    border-radius: 0.5rem;
    overflow: hidden;
    background: none;
    cursor: pointer;
    line-height: 0;
}

/* The picture that fills a tile. Scoped to a direct child so it cannot also catch the small glyph
   inside the host strip: written as a bare `svg` descendant it did, and blew a 14px arrow up to
   the full width of the tile while pushing the site's name out of sight. */
.report-media-tile > img,
.report-media-tile > svg,
.report-media-tile > .media-placeholder,
.report-media-tile > .media-preview-link > img,
.report-media-tile > .media-preview-link > svg,
.report-media-tile > .media-preview-link > .media-placeholder {
    display: block;
    width: 100%;
    height: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

.report-media-tile:hover {
    border-color: var(--accent, #2f6f62);
}

.report-media-tile:focus-visible {
    outline: 2px solid var(--accent, #2f6f62);
    outline-offset: 2px;
}

@media (max-width: 640px) {
    .report-media-grid {
        grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    }
}


/* A link to another site. A card that says where it goes, because the page itself cannot be shown
   here: the sites people paste refuse to be framed, so an iframe would be an empty box. */
.media-viewer-link {
    padding: 1rem;
    border: 1px solid var(--line, #e5e7eb);
    border-radius: 0.5rem;
    background: var(--surface-muted, #f8fafc);
}

.media-viewer-link-host {
    margin: 0 0 0.6rem;
    font-weight: 700;
    font-size: 0.95rem;
    word-break: break-all;
}

.media-viewer-link-note {
    margin: 0.6rem 0 0;
    font-size: 0.8rem;
    color: var(--text-muted, #6b7280);
}

/* A document we serve ourselves, shown in the page. Taller than a video frame because a page of
   text at 16:9 is a letterbox. */
.media-viewer-pdf {
    aspect-ratio: 3 / 4;
    max-height: min(70vh, 720px);
}


/* A link tile: the generated square with the site's own icon and host laid over it, so an article
   is recognisable at a glance rather than being one more coloured rectangle. */
.media-preview-link {
    position: relative;
    display: block;
    line-height: 0;
}

.media-preview-link-face {
    position: absolute;
    inset: auto 0 0 0;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.5rem;
    /* Dark translucent, because it sits over a colour derived from the item's id and cannot know
       what that colour will be. */
    background: rgba(17, 24, 39, 0.68);
    color: #fff;
    line-height: 1.3;
}

/* Held at its own size in every context, so a container rule that sizes pictures cannot inflate
   it. This is the second half of the same bug: scoping the rule above fixes the report grid, and
   this keeps any other list from repeating it. */
.media-preview-link-face svg,
.report-media-tile .media-preview-link-face svg,
.athlete-table .media-preview-link-face svg {
    width: 14px;
    height: 14px;
    aspect-ratio: auto;
    flex: none;
    object-fit: fill;
}

.media-preview-link-host {
    font-size: 0.7rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* "Use as this school's logo" (_SchoolLogoAdoptDialog): the logo shown now beside the new picture,
   so the rights question is answered looking at both. */
.school-logo-adopt-pictures {
    display: flex;
    gap: 24px;
    margin-bottom: 12px;
}

.school-logo-adopt-pictures figure {
    margin: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}

.school-logo-adopt-pictures img,
.school-logo-adopt-empty {
    width: 96px;
    height: 96px;
    object-fit: contain;
    border-radius: 8px;
    background: var(--surface-soft);
}

.school-logo-adopt-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    color: var(--muted, #6b7280);
}

.school-logo-adopt fieldset {
    border: 0;
    margin: 0;
    padding: 0;
}

.school-logo-adopt legend {
    font-weight: 600;
    margin-bottom: 6px;
}
