/*
 * tags.css - the tag strip, the search page and the vocabulary tab (Circle 15;
 * folder strips and inherited chips, 1.10.87; the folder drawer and the search
 * page's own row, 1.10.88)
 *
 * Neutral on purpose: a theme stays what it is -- CSS and fonts, no logic --
 * and a theme that never heard of tags still paints them.
 *
 * The search page (1.11.19) is drawn only with variables every theme defines:
 * --font-color-text, --font-color-highlight, --font-color-accent(-transparent),
 * --background-primary and --background-highlight. The older rules -- the chips,
 * the drawer, the naming queue -- still name --border-color and --accent-color,
 * which NO theme defines, so what they paint is their fallback: a grey edge and
 * the text colour. This header used to say otherwise.
 */

.tag-section {
    margin: 0.5rem 0 0.75rem;
}

.tag-section h3 {
    margin: 0 0 0.4rem;
}

.tag-list {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0;
    padding: 0;
}

.tag-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.15rem 0.5rem;
    border: 1px solid var(--border-color, rgba(128, 128, 128, 0.4));
    border-radius: 1rem;
    font-size: 0.85rem;
    line-height: 1.4;
}

a.tag-chip,
.tag-chip-link {
    text-decoration: none;
    color: inherit;
}

a.tag-chip:hover,
.tag-chip-link:hover {
    text-decoration: underline;
}

.tag-chip-on {
    border-color: var(--accent-color, currentColor);
    font-weight: 600;
}

.tag-chip-remove {
    background: none;
    border: none;
    cursor: pointer;
    color: inherit;
    font-size: 1rem;
    line-height: 1;
    padding: 0 0.1rem;
}

.tag-chip-restore {
    background: none;
    border: none;
    cursor: pointer;
    color: inherit;
    font-size: 0.9rem;
    line-height: 1;
    padding: 0 0.1rem;
}

/* --- a word that came from the folder (1.10.87) -------------------------- */

/* Inherited, not said about this picture: the dashed edge is the whole
   difference, so the word itself still reads as a word. */
.tag-chip-inherited {
    border-style: dashed;
}

/* Refused for this picture. The chip stays, because the folder still says it
   and taking the refusal back has to be possible from here -- so the label is
   struck through rather than removed. */
.tag-chip-rejected {
    opacity: 0.55;
}

.tag-chip-rejected .tag-chip-link {
    text-decoration: line-through;
}

/* --- the folder's words, pulled up from the bottom left (1.10.88) -------- */

/* Fixed, so the page's three-row grid never has to make room for it: the strip
   used to be a fourth child of body.content-grid, which took the row the
   pictures were meant for and left the add box under the theme's own layers,
   where no click reached it. Above the mobile nav bar, which is fixed too.  */
.tag-drawer {
    position: fixed;
    left: 0;
    bottom: calc(var(--mobile-nav-h, 0px) + env(safe-area-inset-bottom, 0px));
    z-index: 900;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    max-width: min(32rem, 100vw);
    /* The empty space beside the tab is the gallery's, not the drawer's. */
    pointer-events: none;
}

.tag-drawer > * {
    pointer-events: auto;
}

.tag-drawer-tab {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0;
    padding: 0.3rem 0.8rem;
    border: 1px solid var(--border-color, rgba(128, 128, 128, 0.4));
    border-left: none;
    border-radius: 0 0.6rem 0 0;
    background: var(--background-highlight, rgba(20, 20, 20, 0.92));
    color: var(--font-color-text, inherit);
    font: inherit;
    font-size: 0.8rem;
    line-height: 1.6;
    cursor: pointer;
}

.tag-drawer-tab:hover {
    border-color: var(--accent-color, currentColor);
}

.tag-drawer-arrow {
    font-size: 0.7em;
    transition: transform 0.15s ease-in-out;
}

.tag-drawer[data-open="1"] .tag-drawer-arrow {
    transform: rotate(180deg);
}

.tag-drawer-count {
    font-variant-numeric: tabular-nums;
    opacity: 0.7;
}

/* The panel itself: it grows upward from the tab and scrolls on its own rather
   than growing past the top of the window. */
.tag-section-folder {
    order: -1;                          /* above the tab, which stays at the bottom */
    box-sizing: border-box;
    width: min(32rem, calc(100vw - 1rem));
    max-height: min(50vh, 26rem);
    overflow-y: auto;
    margin: 0;
    padding: 0.6rem 1rem 0.8rem;
    border: 1px solid var(--border-color, rgba(128, 128, 128, 0.4));
    border-left: none;
    border-radius: 0 0.6rem 0 0;
    background: var(--background-highlight, rgba(20, 20, 20, 0.92));
}

.tag-section-folder h3 {
    font-size: 0.9rem;
}

@media screen and (prefers-reduced-motion: reduce) {
    .tag-drawer-arrow {
        transition: none;
    }
}

.tag-folder-note {
    margin: 0.4rem 0 0;
    font-size: 0.8rem;
    opacity: 0.7;
}

.tag-empty,
.tag-search-message {
    opacity: 0.7;
    font-size: 0.85rem;
}

.tag-add {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.5rem;
}

.tag-add-label {
    flex: 1 1 8rem;
    min-width: 6rem;
}

.tag-add-message {
    flex-basis: 100%;
    font-size: 0.8rem;
    opacity: 0.8;
}

/* Everything the search page has between its header and its footer, in ONE
   row of body.content-grid (1.10.88). The grid has three rows and hands the
   middle one to the results; a form and a facet list placed beside them took
   rows of their own, and the leftover 1fr stretched the field into a box as
   tall as the window. Inside a wrapper they simply flow.

   The wrapper places itself (1.10.89). It first borrowed `.main` for the job,
   which is the one class here that cannot do it: `.main` in style.css is
   `display: grid; grid-template-columns: subgrid`, so the wrapper became a
   second three-column grid and auto-placed the form, the facets, the results
   and the "more" link back into the 10% / 1fr / 10% columns -- the same
   squeezed field, one level down. Nothing below may reintroduce a grid here:
   the point of the wrapper is that its children are in normal flow. */
.tag-search-body {
    grid-column: main-start / main-end;
    grid-row: 2;
    width: 100%;
    max-width: 110rem;
    justify-self: center;
    /* #gallery-title is positioned absolutely over the header, so whatever
       comes first under the header has to clear it. On a gallery page that is
       .gallery-container and it clears the title itself; here the form is
       first, so the wrapper does it once for everything inside. */
    margin-top: calc(3 * var(--titleline-top));
}

/* ... and then the results grid must not clear the title a second time. */
.tag-search-body .gallery-container {
    margin-top: 0;
}

/* A message is not a picture (1.10.89). It is rendered inside the results grid,
   whose columns are one --gallery-unit wide because that is what a thumbnail
   needs -- so "Pick a tag, or type part of a name." arrived as a column of
   two-word lines. It takes the whole row instead. */
.gallery-container > .tag-search-message {
    grid-column: 1 / -1;
    text-align: center;
    padding: 1.5rem 1rem;
    font-size: 0.95rem;
}

/* --- one field for names and tags (1.11.19) ----------------------------- */

/* The field and its button, one row. The field is the site's own control --
   the pill with the highlight edge that style.css gives every input and button
   -- and the button beside it is a UIButton like every other on the site.
   Until 1.11.19 the form restyled its own button into a thin grey square that
   matched nothing, and the tags were a second block of links under the field. */
.tag-search-form {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    margin: 0 auto;
    padding: 0.75rem 1rem 0;
    max-width: 48rem;
}

/* What the list is placed against: the list hangs under the field, the width
   of the field, and the button stays where it is. */
.tag-search-field {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
}

/* The pill. The chosen tags sit in it in front of the text, so it grows a line
   when they no longer fit in one -- hence a radius a pill keeps at one line and
   a rounded box keeps at two, rather than style.css's 2rem. min-height is the
   button's own 1.77rem -- a button is border-box by default, so that is its
   whole height, edge included -- and the two stand level. */
.tag-search-box {
    box-sizing: border-box;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.4rem;
    min-height: 1.77rem;
    padding: 0 0.3rem 0 0.85rem;
    font-size: calc(1rem - 0.05vh);
    color: var(--font-color-text);
    background-color: var(--background-highlight);
    border: 0.1rem solid var(--font-color-highlight);
    border-radius: 1.1rem;
    cursor: text;
    transition: border-color 0.2s ease-in-out, background-color 0.2s ease-in-out;
}

/* What input:focus-visible does to every other field, done to the pill. */
.tag-search-box:focus-within {
    border-color: var(--font-color-accent);
    background-color: var(--background-primary);
}

/* The text box is bare inside the pill: its edge, its focus and its hover all
   belong to the pill now -- including the ring a theme's decorative.css puts
   around every focused input. `height: auto` because style.css gives every
   input `height: -webkit-fill-available` (1.11.6), which a flex line is
   definite enough to act on. */
.tag-search-box input[type="search"] {
    flex: 1 1 8rem;
    min-width: 6rem;
    height: auto;
    margin: 0;
    padding: 0.1rem 0;
    border: none;
    border-radius: 0;
    background: transparent;
    color: inherit;
    font-size: inherit;
    outline: none;
    box-shadow: none;
}

.tag-search-box input[type="search"]:hover,
.tag-search-box input[type="search"]:focus,
.tag-search-box input[type="search"]:focus-visible {
    scale: none;
    transform: none;
    outline: none;
    box-shadow: none;
    background: transparent;
}

.tag-search-box input[type="search"]::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
}

.tag-search-box input[type="search"]::placeholder {
    color: var(--font-color-text);
    opacity: 0.55;
}

/* The chosen tags. */
.tag-search-tokens {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    min-width: 0;
    margin: 0;
    padding: 0;
    list-style: none;
}

.tag-search-tokens[hidden] {
    display: none;
}

.tag-search-tokens .tag-chip {
    gap: 0.15rem;
    padding: 0.05rem 0.15rem 0.05rem 0.6rem;
    border-color: var(--font-color-accent);
    color: var(--font-color-text);
    font-size: 0.85em;
}

/* A button once the script has run, a link before it: one look for both. */
.tag-search-tokens .tag-chip-remove {
    display: inline-grid;
    grid-template-columns: 1fr;
    place-items: center;
    box-sizing: border-box;
    width: 1.3rem;
    min-width: 0;
    height: 1.3rem;
    margin: 0;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--font-color-highlight);
    font-size: 1rem;
    line-height: 1;
    text-decoration: none;
    text-transform: none;
}

.tag-search-tokens .tag-chip-remove:hover,
.tag-search-tokens .tag-chip-remove:focus-visible {
    scale: none;
    transform: none;
    background: var(--font-color-accent-transparent);
    color: var(--font-color-accent);
}

.tag-search-submit {
    flex: none;
    margin: 0;
}

/* The tag list. Without the script it is simply there, under the field, and the
   checkboxes are a form; tag-search.js makes it the field's drop-down. */
.tag-search-options {
    margin-top: 0.6rem;
    padding: 0.4rem;
    border: 0.1rem solid var(--font-color-highlight);
    border-radius: 1rem;
    background-color: var(--background-primary);
}

.tag-search-options[hidden] {
    display: none;
}

/* Over the results, under the site's modals. The tag drawer (900) is never on
   this page, but the list would sit above it if it were. A theme's
   --background-primary may be see-through (one theme ships #000000f5), and
   the results would show through the list, so it is laid over the theme's
   --background-highlight rather than over the page. */
.tag-search-enhanced .tag-search-options {
    background-color: var(--background-highlight);
    background-image: linear-gradient(var(--background-primary), var(--background-primary));
    position: absolute;
    top: calc(100% + 0.3rem);
    left: 0;
    right: 0;
    z-index: 950;
    margin: 0;
    max-height: min(60vh, 28rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    box-shadow: 0 0.6rem 1.6rem rgba(0, 0, 0, 0.45);
}

.tag-search-group {
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

.tag-search-group[hidden] {
    display: none;
}

.tag-search-group + .tag-search-group {
    margin-top: 0.25rem;
}

.tag-search-group legend {
    padding: 0.35rem 0.6rem 0.15rem;
    font-size: 0.72rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--font-color-highlight);
}

.tag-search-group-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
    gap: 0.1rem 0.3rem;
}

/* A row: its checkbox, its word. style.css gives every label side margins and
   80% type, and every checkbox a top margin, for the forms it was written for. */
.tag-search-option {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin: 0;
    padding: 0.35rem 0.6rem;
    border-radius: 0.6rem;
    font-size: 0.95rem;
    line-height: 1.3;
    color: var(--font-color-text);
    cursor: pointer;
}

.tag-search-option[hidden] {
    display: none;
}

.tag-search-option input[type="checkbox"] {
    flex: none;
    margin: 0;
}

/* The row is what is clicked, never the box inside it: a click that lands on
   the box flips it before the script can ask, and cancelling that click puts
   it back after the script has set it. */
.tag-search-enhanced .tag-search-option input[type="checkbox"] {
    pointer-events: none;
}

.tag-search-option:has(input:checked) > span {
    font-weight: 600;
}

.tag-search-option:hover,
.tag-search-option.tag-search-active {
    background-color: var(--background-highlight);
    color: var(--font-color-highlight);
}

/* What Enter would pick. */
.tag-search-option.tag-search-active {
    box-shadow: inset 0 0 0 1px var(--font-color-accent);
}

/* The last row: search the names for what is typed. */
.tag-search-names .svg-icon {
    flex: none;
    width: 1em;
    height: 1em;
}

.tag-search-group:not([hidden]) ~ .tag-search-names {
    margin-top: 0.3rem;
    border-top: 1px solid var(--font-color-accent-transparent);
    border-radius: 0 0 0.6rem 0.6rem;
}

.tag-search-more {
    margin: 0.5rem 0;
    text-align: center;
}

@media screen and (max-width: 30rem) {
    .tag-search-form {
        padding-inline: 0.5rem;
        gap: 0.4rem;
    }

    .tag-search-group-list {
        grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
    }
}

/* --- the vocabulary tab in the admin backend (1.10.84) ------------------- */

.tag-admin-category {
    margin-bottom: 1rem;
}

.tag-admin-category h3 {
    margin: 0 0 0.3rem;
    font-size: 0.9rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    opacity: 0.8;
}

.tag-admin-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    padding: 0.25rem 0;
}

.tag-admin-label {
    flex: 1 1 10rem;
    min-width: 7rem;
}

.tag-admin-files {
    min-width: 4rem;
    font-size: 0.8rem;
    opacity: 0.8;
    text-align: right;
}

/* The folders carrying the word, beside the files (1.10.87). */
.tag-admin-dirs {
    min-width: 2.5rem;
    font-size: 0.8rem;
    opacity: 0.6;
    text-align: right;
}

.tag-admin-message {
    font-size: 0.85rem;
    min-height: 1.2em;
}

.tag-admin-empty {
    opacity: 0.7;
    font-size: 0.85rem;
}

/* --- the naming queue in the admin backend (Circle 16, 1.11.3) ----------- */

.face-review-tabs {
    display: flex;
    gap: 0.4rem;
    margin-bottom: 0.5rem;
}

/* Which list is open. Not a colour of its own: the accent the theme already
   defines, so a theme that never heard of faces still shows the difference. */
.face-review-tab-on {
    border-color: var(--accent-color, currentColor);
    font-weight: 600;
}

.face-review-counts {
    font-size: 0.8rem;
    opacity: 0.75;
    margin: 0 0 0.6rem;
    font-variant-numeric: tabular-nums;
}

/* A grid the eye can go down: every card the same width, the crop always in the
   same place, so forty faces read as forty faces and not as forty layouts. */
.face-review-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
    gap: 0.75rem;
    margin-bottom: 0.75rem;
}

.face-review-card {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 0.5rem;
    border: 1px solid var(--border-color, rgba(128, 128, 128, 0.4));
    border-radius: 6px;
}

.face-review-crop {
    display: block;
    line-height: 0;
}

.face-review-crop img {
    width: 100%;
    height: auto;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: 4px;
    background: var(--background-highlight, rgba(20, 20, 20, 0.5));
}

.face-review-guess {
    margin: 0;
    font-size: 0.78rem;
    opacity: 0.85;
}

.face-review-named-label {
    margin: 0;
    font-weight: 600;
    overflow-wrap: anywhere;
}

/* One line, on every card (1.11.6). style.css gives every input on the site
   `height: -webkit-fill-available`, which computes to `height: stretch` and does
   nothing until the containing block has a definite height -- which a card has,
   being a grid item stretched to its row. So the name box quietly grew to
   swallow whatever the guess line above it did not use, and a card with no
   guess showed a 70px-tall text field. An explicit height ends that here rather
   than site-wide, where every other input would have to be re-checked. */
.face-review-name {
    width: 100%;
    min-width: 0;
    height: auto;
}

/* The buttons keep the card's bottom edge, which until now was the stretched
   input's accident rather than anyone's intention. */
.face-review-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: auto;
}

.face-review-empty {
    opacity: 0.7;
    font-size: 0.85rem;
}
