/* The library, the dialog adding books and the page of a book. */

/* --- Covers ----------------------------------------------------------------
 * Covers come in all shapes; everywhere they take the shape of a typical book.
 */

.book-cover {
    display: block;
    aspect-ratio: 2 / 3;
    overflow: hidden;
    border-radius: 6px;
    background: var(--linen);
}

.book-cover:hover {
    text-decoration: none;
}

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

/* A cover drawn for a book that has none: the title and the author on a spine-edged, muted colour. */
.book-cover-placeholder {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 0.5rem;
    height: 100%;
    padding: 1rem 0.875rem 0.875rem 1.25rem;
    background: var(--moss);
    box-shadow: inset 6px 0 0 rgb(0 0 0 / 0.18);
    color: var(--chalk);
}

.book-cover-title {
    display: -webkit-box;
    overflow: hidden;
    font-family: var(--font-serif);
    font-size: 1.1875rem;
    font-weight: 500;
    line-height: 1.15;
    overflow-wrap: anywhere;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 6;
    line-clamp: 6;
}

.book-cover-author {
    font-size: 0.625rem;
    font-weight: 400;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    opacity: 0.85;
}

/* As many as App\Twig\BookExtension::COVER_TONES. */
.book-cover-tone-0 { background-color: var(--cover-moss); }
.book-cover-tone-1 { background-color: var(--cover-slate); }
.book-cover-tone-2 { background-color: var(--cover-clay); }
.book-cover-tone-3 { background-color: var(--cover-ochre); }
.book-cover-tone-4 { background-color: var(--cover-plum); }
.book-cover-tone-5 { background-color: var(--cover-bark); }
.book-cover-tone-6 { background-color: var(--cover-teal); }
.book-cover-tone-7 { background-color: var(--cover-amber); }
.book-cover-tone-8 { background-color: var(--cover-rust); }
.book-cover-tone-9 { background-color: var(--cover-olive); }

/* --- Library ----------------------------------------------------------------- */

.library {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.library-filter {
    color: var(--ink-soft);
    font-size: 0.875rem;
}

.library-filter a {
    margin-left: 0.5rem;
    font-weight: 600;
}

.library-summary {
    color: var(--bark);
    font-size: 0.875rem;
}

.library-summary strong {
    color: var(--ink);
    font-weight: 600;
}

/* Books of the same kind under a heading, e.g. the ones added today. */
.book-group {
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
}

.book-group + .book-group {
    margin-top: 1rem;
}

.book-group-heading {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    white-space: nowrap;
}

.book-group-heading h2 {
    font-size: 1.375rem;
}

.book-group-heading span {
    color: var(--bark);
    font-size: 0.8125rem;
    font-weight: 500;
}

/* A line from the heading to the edge of the page. */
.book-group-heading::after {
    content: '';
    flex: 1;
    align-self: center;
    height: 1px;
    background: var(--thread);
}

.book-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(11rem, 100%), 1fr));
    gap: 1.25rem;
}

.book-card {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    min-width: 0;
    padding: 0.75rem;
    border: 1px solid var(--thread);
    border-radius: var(--radius-card);
    background: var(--paper);
}

.book-card-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.book-card h3,
.book-card-authors {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.book-card h3 {
    font-family: var(--font-sans);
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.3;
    letter-spacing: 0;
}

.book-card h3 a {
    color: var(--ink);
    font-weight: inherit;
}

.book-card-authors,
.book-card-series {
    color: var(--bark);
    font-size: 0.8125rem;
}

.book-card-authors a {
    color: inherit;
    font-weight: 400;
}

.book-card-series {
    font-size: 0.75rem;
}

.book-status {
    color: var(--bark);
    font-size: 0.8125rem;
}

.book-status-failed {
    color: var(--ember);
}

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    padding: 3.5rem 1.5rem;
    border: 1px dashed var(--thread-strong);
    border-radius: var(--radius-card);
    color: var(--bark);
    text-align: center;
}

.pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    margin-top: 0.75rem;
    color: var(--bark);
    font-size: 0.875rem;
}

/* --- Adding books -------------------------------------------------------------- */

.upload-form {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.dropzone {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    min-height: 16.25rem;
    padding: 2rem;
    border: 2px dashed var(--moss-pale);
    border-radius: var(--radius-card);
    background: var(--moss-haze);
    text-align: center;
}

.dropzone:focus-within,
.dropzone.is-dragover {
    border-color: var(--moss);
    background: var(--moss-mist);
}

.dropzone-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: 50%;
    background: var(--moss-mist);
    color: var(--moss);
}

.dropzone.is-dragover .dropzone-icon,
.dropzone:focus-within .dropzone-icon {
    background: var(--paper);
}

.dropzone-title {
    font-family: var(--font-serif);
    font-size: 1.5rem;
    font-weight: 500;
    line-height: 1.15;
}

.dropzone-hint {
    color: var(--bark);
    font-size: 0.875rem;
}

.dropzone-hint label {
    color: var(--moss);
    font-size: inherit;
    text-decoration: underline;
    cursor: pointer;
}

.dropzone input[type='file'] {
    max-width: 100%;
    font-size: 0.8125rem;
}

/*
 * With JavaScript the field covers the whole area, invisible: a click anywhere opens the file picker, files can be
 * dropped anywhere, and upload.js lists whatever was chosen. Without it the plain field of the browser takes a file.
 */
.js .dropzone input[type='file'] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.upload-limits {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    color: var(--bark);
    font-size: 0.8125rem;
    line-height: 1.45;
}

.upload-limits .icon {
    color: var(--bark-light);
}

.upload-files {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.upload-files-heading {
    display: flex;
    justify-content: space-between;
    color: var(--bark);
    font-size: 0.8125rem;
}

.upload-files-heading strong {
    color: var(--ink-soft);
    font-weight: 600;
}

.upload-files ul {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    /* Five rows and the gaps between them; more than that scrolls. */
    max-height: calc(5 * 3rem + 4 * 0.5rem);
    padding: 0;
    overflow-y: auto;
    list-style: none;
}

/*
 * A chosen file: its name and size, the mark of its state (see below) and the × taking it back – or, once it is
 * being sent, breaking that off. A file that could not be added says why in a line of its own.
 */
.upload-file {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto auto;
    /* The list scrolls rather than squeezes its rows. */
    flex-shrink: 0;
    align-items: center;
    gap: 0.25rem 0.75rem;
    min-height: 3rem;
    /* The × (2rem) with this padding and the border makes exactly the 3rem the list counts on. */
    padding: calc(0.5rem - 1px) 0.5rem calc(0.5rem - 1px) 0.75rem;
    border: 1px solid var(--thread);
    border-radius: var(--radius-control);
}

.upload-file > .icon {
    color: var(--moss);
}

.upload-file-name {
    overflow: hidden;
    font-size: 0.875rem;
    font-weight: 500;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.upload-file-size {
    color: var(--bark);
    font-size: 0.75rem;
    white-space: nowrap;
}

/*
 * The mark of the state: a spinner, a check mark, a warning. A file that waits has none, and the place of the mark
 * is folded away; when the mark comes, the place unfolds and the mark eases in, so whatever is next to it slides
 * rather than jumps.
 */
.upload-file-state {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 0;
    height: 2rem;
    overflow: hidden;
    color: var(--bark-light);
    transition: width 0.25s ease-out;
}

.upload-file:not([data-state='waiting'], [data-state='queued']) .upload-file-state {
    width: 2rem;
}

.upload-file-state > * {
    display: none;
    animation: upload-state-in 0.25s ease-out;
}

.upload-file-state [data-for='added'] {
    color: var(--moss);
}

.upload-file[data-state='sending'] [data-for='sending'],
.upload-file[data-state='added'] [data-for='added'],
.upload-file[data-state='failed'] [data-for='failed'] {
    display: inline-flex;
}

/*
 * A file that is through – added or not – is here to stay, and once the answer is in there is nothing to break off:
 * the × folds away the same way. The × of a file being sent breaks the sending off instead of taking the file back.
 */
.upload-file [data-upload-remove] {
    overflow: hidden;
    transition: width 0.25s ease-out, opacity 0.25s ease-out;
}

.upload-file[data-state='added'] [data-upload-remove],
.upload-file[data-state='failed'] [data-upload-remove],
.upload-file [data-upload-remove]:disabled {
    width: 0;
    opacity: 0;
    pointer-events: none;
}

.upload-file[data-state='sending'] [data-label='remove'],
.upload-file:not([data-state='sending']) [data-label='abort'] {
    display: none;
}

@keyframes upload-state-in {
    from {
        opacity: 0;
        transform: scale(0.6);
    }
}

.upload-file-reason {
    grid-column: 2 / -1;
    color: var(--ember);
    font-size: 0.8125rem;
    font-weight: 500;
    animation: upload-state-in 0.25s ease-out;
}

.upload-file-reason:empty {
    display: none;
}

.upload-file[data-state='failed'] > .icon,
.upload-file[data-state='failed'] .upload-file-state {
    color: var(--ember);
}

/* --- Book ---------------------------------------------------------------------- */

.book {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 2.5rem;
    padding-top: 0.5rem;
}

.book-aside {
    display: flex;
    flex: 1 1 16.25rem;
    flex-direction: column;
    gap: 0.875rem;
    max-width: 17.5rem;
}

.book-aside .button {
    width: 100%;
}

/* What became of the book on a device, under its name on the menu of the button sending the book. */
.delivery-status {
    display: inline-flex;
    gap: 0.25rem;
    align-items: center;
    color: var(--bark-light);
    font-size: 0.75rem;
    font-weight: 500;
}

.delivery-status-sent {
    color: var(--moss);
}

.delivery-status-failed {
    color: var(--ember);
}

.book-cover-large {
    border-radius: var(--radius-small);
    box-shadow: 0 18px 40px rgb(42 36 31 / 0.18);
}

.book-cover-large .book-cover-placeholder {
    padding: 1.75rem 1.5rem 1.5rem 2rem;
    box-shadow: inset 8px 0 0 rgb(0 0 0 / 0.18);
}

.book-cover-large .book-cover-title {
    font-size: 2.25rem;
    line-height: 1.1;
}

.book-cover-large .book-cover-author {
    font-size: 0.8125rem;
    letter-spacing: 0.06em;
}

.book-main {
    display: flex;
    flex: 1 1 30rem;
    flex-direction: column;
    gap: 1.875rem;
    min-width: 0;
}

.book-heading {
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
}

.book-heading h1 {
    font-size: 2.875rem;
    line-height: 1.1;
    overflow-wrap: anywhere;
}

.book-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.book-authors {
    color: var(--ink-soft);
    font-size: 1.0625rem;
}

.book-section {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.book-section h2 {
    font-size: 1.375rem;
}

.book-description {
    max-width: 42.5rem;
    line-height: 1.65;
}

.book-facts {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(13.75rem, 100%), 1fr));
    gap: 0.875rem 1.5rem;
    padding: 1.25rem 1.375rem;
    border: 1px solid var(--thread);
    border-radius: var(--radius-card);
    background: var(--paper);
}

.book-facts div {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.book-fact-wide {
    grid-column: 1 / -1;
}

.book-facts dt {
    color: var(--bark);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.book-facts dd {
    font-size: 0.875rem;
    font-weight: 500;
    overflow-wrap: anywhere;
}

.book-fact-missing {
    color: var(--bark);
}

@media (max-width: 40rem) {
    .book {
        gap: 1.5rem;
    }

    .book-aside {
        max-width: none;
    }

    .book-cover-large {
        align-self: center;
        width: min(14rem, 100%);
    }

    .book-heading h1 {
        font-size: 2.125rem;
    }
}
