/**
 * BIBLIOTECA DIGITALE — shared front-end components.
 *
 * Primitives only: the book card and its cover ribbon, the lists that hold
 * it, badges, buttons, form fields, the carousel, one utility class, tables
 * and standalone inputs and selects, and the book-list toolbar. No
 * page decides anything here, and nothing here knows which plugin is
 * calling — a consumer picks a modifier and adds its own state class.
 *
 * Depends on `bd-tokens` for every colour, radius and size. Loading this file
 * without it still renders correctly: each token carries its own fallback
 * there, and nothing below invents a value.
 *
 * ── The three card layouts, and where each comes from ────────────────────────
 *
 *   --grid     cover on top, details below, no border and no fill, one
 *              hairline between cover and text.
 *              Grafica/7-PAGINA-LIBRI-DIGITALI_SETTEMBRE26.jpg
 *   --row      cover on the left, details on the right, --bd-radius, surface
 *              fill, 1px hairline border. This is the carousel card.
 *              Grafica/1_HP-GENERICA_SETTEMBRE26.jpg
 *   --compact  a single line: small cover, title, authors and editors, each
 *              truncated; the ISBN is hidden. The reader header bar and the
 *              booking page.
 *
 * ── Breakpoints ──────────────────────────────────────────────────────────────
 *
 * 980px and 767px, which are Divi 5's own two enabled breakpoints
 * (Framework/Breakpoint/Breakpoint.php). Divi carries them in no CSS variable
 * — they are baked into its generated media queries — so they are written out
 * here too, and changing Divi's breakpoint settings does not reach this file.
 * bd-core-shared's stylesheets (this file, modal.css and the phone type scale of
 * tokens.css) query only those two widths — a third would draw a boundary the
 * host layout does not have — and ComponentsSheetContractTest (this file,
 * modal.css) and DesignTokensContractTest (tokens.css) fail on any other
 * figure.
 *
 * @package BD_Shared
 */

/* ═══════════════════════════════════════════════════════════════════════════
   1. LISTS
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Why this one rule is !important ─────────────────────────────────────────
   Divi's own stylesheet carries

     #left-area ul, .entry-content ul, .et-l--body ul, .et-l--footer ul,
     .et-l--header ul { list-style-type: disc; padding: 0 0 23px 1em; … }

   at (0,1,1), and this selector is a single class at (0,1,0). Inside a Divi
   layout — which is every page of this site — Divi wins, so a plain
   `list-style: none` here does nothing: the bullets stay, and the list gains a
   1em left indent and 23px of bottom padding nobody asked for.

   Raising specificity instead would mean either tying Divi at (0,1,1) and
   depending on enqueue order, which Dynamic Assets is free to change, or
   doubling the class, which reads as a trick. Divi solves the same problem in
   its own module lists the same way.

   Every <ul> this file styles carries .bd-books-list, the carousel track
   included, so one selector covers all of them. */
.bd-books-list {
    list-style: none !important;
    margin: 0;
    padding: 0 !important;
}

/* Four columns by default (1.60.0, www.giappichelli.it's four 320px slots),
   stated and not derived: `auto-fill` gave a count that followed the screen,
   so each step down is written out instead. A page can state its own desktop
   count with `columns` (1-6), which arrives as a --cols-N modifier; the
   breakpoints below still cap it at two and one. No column gap: each card
   carries its own 45px inset (2a). 56px between rows. */
.bd-books-list--grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--bd-card-row-gap) 0;
}

.bd-books-list--grid.bd-books-list--cols-1 {
    grid-template-columns: 1fr;
}

.bd-books-list--grid.bd-books-list--cols-2 {
    grid-template-columns: repeat(2, 1fr);
}

.bd-books-list--grid.bd-books-list--cols-3 {
    grid-template-columns: repeat(3, 1fr);
}

.bd-books-list--grid.bd-books-list--cols-4 {
    grid-template-columns: repeat(4, 1fr);
}

.bd-books-list--grid.bd-books-list--cols-5 {
    grid-template-columns: repeat(5, 1fr);
}

.bd-books-list--grid.bd-books-list--cols-6 {
    grid-template-columns: repeat(6, 1fr);
}

/* The row card draws its own border, so with no gap two consecutive rows put
   their borders side by side and the pair reads as one 2px divider rather than
   as two cards. */
.bd-books-list--list {
    display: flex;
    flex-direction: column;
    gap: var(--bd-space-md);
}

@media (max-width: 980px) {
    .bd-books-list--grid {
        grid-template-columns: repeat(2, 1fr);
    }

    /* The modifiers are (0,2,0), so the cap has to name them; --cols-1 keeps
       its single column from the desktop rule. */
    .bd-books-list--grid.bd-books-list--cols-2,
    .bd-books-list--grid.bd-books-list--cols-3,
    .bd-books-list--grid.bd-books-list--cols-4,
    .bd-books-list--grid.bd-books-list--cols-5,
    .bd-books-list--grid.bd-books-list--cols-6 {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 767px) {
    .bd-books-list--grid {
        grid-template-columns: 1fr;
    }

    .bd-books-list--grid.bd-books-list--cols-2,
    .bd-books-list--grid.bd-books-list--cols-3,
    .bd-books-list--grid.bd-books-list--cols-4,
    .bd-books-list--grid.bd-books-list--cols-5,
    .bd-books-list--grid.bd-books-list--cols-6 {
        grid-template-columns: 1fr;
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
   2. BOOK CARD
   ═══════════════════════════════════════════════════════════════════════════ */

.bd-book-card {
    position: relative;
    box-sizing: border-box;
    font-family: var(--bd-font-sans);
    color: var(--bd-text-slate);
}

.bd-book-card *,
.bd-book-card *::before,
.bd-book-card *::after {
    box-sizing: border-box;
}

.bd-book-card__cover {
    position: relative;   /* the containing block of .bd-ribbon (2e) */
    display: block;
    flex-shrink: 0;
}

.bd-book-card__cover img {
    display: block;
    width: 100%;
    height: auto;
}

/* WooCommerce's own placeholder, served by wc_placeholder_img() when a product
   has no cover. It is square where every jacket is portrait, so `contain` would
   leave the small grey tile floating in a tall box; it is a generic icon, so
   filling the box with it costs nothing and keeps the row height honest. */
.bd-book-card__cover img.woocommerce-placeholder {
    object-fit: cover;
}

/* --bd-space-xs between lines: the ISBN, title, authors and meta read as one
   block, and the ISBN no longer needs pulling up against the title. */
.bd-book-card__body {
    display: flex;
    flex-direction: column;
    gap: var(--bd-space-xs);
    min-width: 0;
}

.bd-book-card__title {
    margin: 0;

    /* Not redundant, and not a reset for its own sake: Divi styles every
       heading with `h1,h2,h3,h4,h5,h6 { padding-bottom: 10px }`, and these are
       border-box boxes, so those 10px would come out of the fixed two-line
       title box of the grid and the row (2a, 2b). */
    padding: 0;
    font-size: var(--bd-fs-h3);
    font-weight: var(--bd-fw-heading);
    line-height: 1.3;
    color: var(--bd-text-heading);
    overflow-wrap: anywhere;
}

.bd-book-card__title a {
    color: inherit;
    text-decoration: none;
}

.bd-book-card__title a:hover,
.bd-book-card__title a:focus-visible {
    text-decoration: underline;
}

/* `padding: 0` on these <p> rows (and the ISBN) is Divi's `p { padding-bottom:
   1em }` taken back: without it a one-line row stood 41px tall (1.53.0). */
.bd-book-card__authors {
    margin: 0;
    padding: 0;
    font-size: var(--bd-fs-sm);
    line-height: 1.4;
    color: var(--bd-text-slate);
}

/* One ISBN sits above the title as a small tabular-figure line. */
.bd-book-card__isbn {
    display: block;
    margin: 0;
    padding: 0;
    font-size: var(--bd-fs-xs);
    line-height: 1.4;
    letter-spacing: .04em;
    font-variant-numeric: tabular-nums;
    color: var(--bd-text-subtle);
}

/* The editors (curatori) line, drawn in place of the authors line when a book
   has editors, so it reads with the same voice: every layout rule below that
   styles __authors styles __editors too. Only the label stays subtler. */
.bd-book-card__editors {
    margin: 0;
    padding: 0;
    font-size: var(--bd-fs-sm);
    line-height: 1.4;
    color: var(--bd-text-slate);
}

.bd-book-card__editors-label {
    color: var(--bd-text-subtle);
}

.bd-book-card__meta {
    margin: 0;
    padding: 0;
    font-size: var(--bd-fs-sm);
    line-height: 1.4;
    color: var(--bd-text-slate);
}

.bd-book-card__meta--subtle {
    color: var(--bd-text-subtle);
}

.bd-book-card__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--bd-space-sm);
}

/* ── 2a. Grid: cover on top ──────────────────────────────────────────────────
   The www.giappichelli.it card (1.60.0, tokens.css 12): a slot with a 45px
   inset on its left, a 240x300 cover box, a hairline, a 275px text column
   in 14/20 type, the subject and the "..." on the card's floor. Every line
   has a fixed height and the foot is pinned down, so in a row of cards each
   element sits at the same y and every card is as tall as its neighbours.
   The inset drops to 0 on a phone (767px query below). */

.bd-book-card--grid {
    display: flex;
    flex-direction: column;
    gap: 0;
    min-width: 0;   /* a grid item: the nowrap author line must not widen its track */
    padding-left: var(--bd-card-inset);
}

.bd-book-card--grid .bd-book-card__cover {
    display: block;
    flex: none;
    width: min(var(--bd-card-cover-w), 100%);
    aspect-ratio: var(--bd-card-cover-ratio);
}

/* The jacket is contained inside the box's margin and padding, so a file of
   any ratio fits the same 168x210 content box and the box never changes. */
.bd-book-card--grid .bd-book-card__cover img {
    width: calc(100% - 2 * var(--bd-card-cover-inset-x));
    max-width: none;
    height: calc(100% - 2 * var(--bd-card-cover-inset-y));
    margin: var(--bd-card-cover-inset-y) var(--bd-card-cover-inset-x);
    padding: var(--bd-card-cover-pad-y) 0;
    object-fit: contain;
}

/* The hairline belongs to the text column (275px), drawn only under a cover. */
.bd-book-card--grid .bd-book-card__body {
    flex: 1 1 auto;
    gap: 0;
    max-width: var(--bd-card-content-w);
    padding-top: 5px;
}

.bd-book-card--grid .bd-book-card__cover + .bd-book-card__body {
    border-top: 1px solid var(--bd-hairline);
}

/* A card without an ISBN keeps its line empty, so its title does not rise
   above its neighbours'. A browser without :has() only loses that alignment. */
.bd-book-card--grid .bd-book-card__body:not(:has(> .bd-book-card__isbn)) {
    padding-top: calc(5px + var(--bd-card-lh-isbn));
}

.bd-book-card--grid .bd-book-card__isbn {
    font-size: var(--bd-card-fs-isbn);
    line-height: var(--bd-card-lh-isbn);
}

/* Two lines reserved on every card and cut at two (2d): that is what puts
   the author line at one y across a row. */
.bd-book-card--grid .bd-book-card__body > .bd-book-card__title {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    height: calc(2 * var(--bd-card-lh));
    min-height: 0;
    max-height: none;
    margin: 5px 0;
    overflow: hidden;
    font-size: var(--bd-card-fs);
    font-weight: var(--bd-card-fw-title);
    line-height: var(--bd-card-lh);
    -webkit-hyphens: auto;
    hyphens: auto;
    overflow-wrap: break-word;
}

/* Grid and carousel share this card. The editors line replaces the authors
   line, so it takes the same case and size; its "+N more" chip is the same
   bd-cs-book-authors-more element bd-cat-shortcodes draws in both rows.
   One line, after one blank 20px line under the title. */
.bd-book-card--grid .bd-book-card__authors,
.bd-book-card--grid .bd-book-card__editors {
    margin-top: var(--bd-card-lh);
    overflow: hidden;
    font-size: var(--bd-card-fs);
    line-height: var(--bd-card-lh);
    white-space: nowrap;
    text-overflow: ellipsis;
    text-transform: uppercase;
}

/* Only the names are capitalised: the "a cura di" label keeps its own case
   (1.54.0). */
.bd-book-card--grid .bd-book-card__editors-label {
    text-transform: none;
    letter-spacing: normal;
}

.bd-book-card--grid .bd-book-card__meta {
    font-size: var(--bd-card-fs);
    line-height: var(--bd-card-lh);
}

.bd-book-card--grid .bd-book-card__actions {
    justify-content: flex-end;
}

/* The foot row: the last meta line (the subject) on the left, the "..." on
   the right of the same line, vertically centred (1.54.0), on the card's
   floor (1.60.0). The meta keeps its typography and only gives up its block
   margins. The row wraps: a lone "..." stays beside the subject, while a
   wide set of labelled buttons (read links, watchlist, cancel loan) drops to
   its own right-aligned line instead of squeezing the subject or overflowing
   the card. */
.bd-book-card--grid .bd-book-card__foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--bd-space-sm);
    margin-top: auto;
    padding-top: var(--bd-space-sm);
}

.bd-book-card--grid .bd-book-card__foot > .bd-book-card__meta {
    flex: 1 1 8em;
    min-width: 0;
    margin: 0;
    overflow-wrap: anywhere;
}

.bd-book-card--grid .bd-book-card__foot > .bd-book-card__actions {
    flex: 0 1 auto;
    min-width: 0;
    margin-left: auto;
}

/* ── 2b. Row: cover on the left ──────────────────────────────────────────── */

.bd-book-card--row {
    display: flex;
    align-items: flex-start;
    gap: var(--bd-space-lg);
    height: 100%;
    padding: var(--bd-space-sm);
    border: 1px solid var(--bd-border-subtle);
    border-radius: var(--bd-radius);
    background-color: var(--bd-surface);
}

/* The box is 110x163 whatever the jacket measures, so every row is the same
   height and the covers line up down the column. `contain` rather than `cover`:
   a file off the ratio is shown whole, never cut. The width alone carries the
   media query below — the ratio does the rest. */
.bd-book-card--row .bd-book-card__cover {
    width: 110px;
    aspect-ratio: var(--bd-cover-ratio);
}

.bd-book-card--row .bd-book-card__cover img {
    height: 100%;
    object-fit: contain;
    border-radius: 2px;
    box-shadow: 0 2px 8px rgba(15, 23, 42, .12);
}

/* The grid's 14/20 voice with no gaps (1.60.0): ISBN, a two-line title,
   author, subject and the chip stay shorter than the cover, so the cover
   decides the row's height with or without a chip. */
.bd-book-card--row .bd-book-card__body {
    flex: 1 1 auto;
    align-self: stretch;
    gap: 0;
}

.bd-book-card--row .bd-book-card__isbn {
    font-size: var(--bd-card-fs-isbn);
    line-height: var(--bd-card-lh-isbn);
}

/* As in the grid: two lines reserved and cut (2d). */
.bd-book-card--row .bd-book-card__body > .bd-book-card__title {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    flex: none;
    height: calc(2 * var(--bd-card-lh));
    min-height: 0;
    max-height: none;
    margin: 2px 0 0;
    overflow: hidden;
    font-size: var(--bd-card-fs);
    font-weight: var(--bd-card-fw-title);
    line-height: var(--bd-card-lh);
    -webkit-hyphens: auto;
    hyphens: auto;
    overflow-wrap: break-word;
}

/* One line each; the last lines keep clear of the "..." pinned bottom-right. */
.bd-book-card--row .bd-book-card__authors,
.bd-book-card--row .bd-book-card__editors,
.bd-book-card--row .bd-book-card__meta {
    max-width: calc(100% - var(--bd-card-more-size) - var(--bd-space));
    overflow: hidden;
    font-size: var(--bd-card-fs);
    line-height: var(--bd-card-lh);
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* The foot is a grid-only row: here its children stay items of the body
   column, so the row looks as it did before the foot existed and the actions
   are still pinned down by their own margin-top. */
.bd-book-card--row .bd-book-card__foot {
    display: contents;
}

.bd-book-card--row .bd-book-card__actions {
    order: 2;
    margin-top: auto;
    justify-content: flex-end;
}

/* A lone icon control (the "...") leaves the flow for the bottom-right
   corner, so it adds no line: a row with a chip is as tall as one without,
   on a phone's 84px cover too. Labelled buttons stay in the flow. */
.bd-book-card--row .bd-book-card__actions:has(> .bd-btn--icon:only-child, > :only-child > .bd-btn--icon:first-child) {
    position: absolute;
    right: var(--bd-space-sm);
    bottom: var(--bd-space-sm);
    margin: 0;
}

@media (max-width: 767px) {
    .bd-book-card--row .bd-book-card__cover {
        width: 84px;
    }

    /* One card per line: the slot inset and the column cap go. */
    .bd-book-card--grid {
        padding-left: 0;
    }

    .bd-book-card--grid .bd-book-card__body {
        max-width: none;
    }
}

/* ── 2c. Compact: one line ───────────────────────────────────────────────── */

.bd-book-card--compact {
    display: flex;
    align-items: center;
    gap: var(--bd-space);
    min-width: 0;
}

.bd-book-card--compact .bd-book-card__cover {
    width: 44px;
}

.bd-book-card--compact .bd-book-card__cover img {
    border-radius: 2px;   /* a cover is an image, not a control — the one exception to --bd-radius; the grid's jacket has none (1.60.0) */
    box-shadow: 0 1px 4px rgba(15, 23, 42, .18);
}

.bd-book-card--compact .bd-book-card__body {
    gap: 2px;
    overflow: hidden;
}

.bd-book-card--compact .bd-book-card__title {
    font-size: var(--bd-fs-md);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bd-book-card--compact .bd-book-card__authors {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Same as the row: no foot row on one line of chrome. */
.bd-book-card--compact .bd-book-card__foot {
    display: contents;
}

/* One line of chrome above the reader has no room for a code. */
.bd-book-card--compact .bd-book-card__isbn {
    display: none;
}

.bd-book-card--compact .bd-book-card__editors {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── 2d. Title length ────────────────────────────────────────────────────────
   Not a setting since 1.60.0: the "Long titles" option and its
   --clamp-title modifier are retired (the stored option is kept, unread).
   Grid and row titles always reserve and cut two lines (2a, 2b), because a
   fixed title box is what puts every element of a row at one y; compact
   truncates to one line (2c), so a title never pushes the reader down.

   The cut does not depend on `-webkit-line-clamp`, a deprecated prefixed
   property a minifier or a stale "Minify and Combine CSS" bundle may drop:
   the fixed `height` with `overflow: hidden` cuts on its own, and where the
   clamp survives the two agree to the pixel and add the ellipsis. That holds
   only because `padding` is zeroed on the base title rule: these are
   border-box boxes, and Divi's 10px under every heading would otherwise come
   out of the height. */

/* ── 2e. Cover ribbon ────────────────────────────────────────────────────────
   "New" / "Coming soon" as a sticker on the top-right corner of a cover,
   printed by BD_Core_Shared_Book_Card::ribbon_html(). It overhangs the jacket by
   --bd-ribbon-overhang on both axes: a label drawn inside the corner read as
   part of the cover art and went unnoticed, one that breaks the jacket's
   outline is seen as a badge. Unscoped on purpose: a surface that draws its
   own cover (bd-cat-quickview's preview sidebar) prints the same span inside
   its own `position: relative` wrapper and gets the same corner. The compact
   card never carries one: the renderer drops it.

   The overhang leaves the cover box, so no ancestor of a cover may clip it:
   the carousel track (6), a scroll container, reserves the room itself.

   Fixed tokens, never --bd-accent or --bd-blue, so an institution accent can
   neither recolour it nor erode its contrast. White on (WCAG 2.1 relative
   luminance, measured):
     --bd-success-ink #007E3F   5.18:1   AA for 11-12px bold text (>= 4.5:1)
     --bd-blue-dark   #00153F  17.81:1
   The label wraps rather than being cut: nothing here ellipsises it, and
   there is no nowrap because "COMING SOON" does not fit a 84px row cover on
   one line. The 2px white border keeps the shape legible on a dark jacket,
   where the fill alone would melt into the cover. */

.bd-ribbon {
    --bd-ribbon-overhang: 8px;

    position: absolute;
    top: calc(-1 * var(--bd-ribbon-overhang));
    right: calc(-1 * var(--bd-ribbon-overhang));
    z-index: 2;
    max-width: calc(100% + var(--bd-ribbon-overhang));
    padding: 5px 12px;
    border: 2px solid var(--bd-white);
    border-radius: var(--bd-radius);   /* the one radius rule (tokens.css 8): no pill */
    box-shadow: 0 2px 6px rgba(15, 23, 42, .35);
    font-family: var(--bd-font-sans);
    font-size: 12px;
    font-weight: var(--bd-fw-heading);
    line-height: 1.2;
    letter-spacing: .06em;
    text-align: center;
    text-transform: uppercase;
    pointer-events: none;   /* the cover link underneath stays clickable */
}

.bd-ribbon--new {
    background-color: var(--bd-success-ink);
    color: var(--bd-white);
}

.bd-ribbon--coming-soon {
    background-color: var(--bd-blue-dark);
    color: var(--bd-white);
}

/* The row cover is 110px (84px on a phone): smaller type and padding, and
   room for the overhang on the left too, so "COMING SOON" stays on one line
   on the 110px cover; on the 84px one it wraps to two rather than crossing
   the card's border, and any longer label wraps rather than being cut. The
   overhang is half the card's 8px padding and gap, so the sticker stays clear
   of both the card's border and the body text. */
.bd-book-card--row .bd-ribbon {
    --bd-ribbon-overhang: var(--bd-space-xs);

    /* max-content: a right-anchored box shrinks to the room left of its
       right edge (cover + one overhang), which max-width alone cannot widen. */
    width: max-content;
    max-width: calc(100% + 2 * var(--bd-ribbon-overhang));
    padding: 3px 6px;
    font-size: var(--bd-fs-xs);
    letter-spacing: .03em;
}

/* The grid cover box is 240x300 with the jacket contained in a 168x210
   content box (2a), so the ribbon goes on the jacket's own top-right corner:
   the box's inset plus padding from the top, and from the right the inset
   plus the side room a portrait jacket leaves in that content box (7.92% +
   30.3px of the box's width, measured in the approved mockup). max-width
   keeps a long label within the jacket plus the overhang. */
.bd-book-card--grid .bd-ribbon {
    top: calc(var(--bd-card-cover-inset-y) + var(--bd-card-cover-pad-y) - var(--bd-ribbon-overhang));
    right: calc(7.92% + 30.3px - var(--bd-ribbon-overhang));
    max-width: calc(58.9% + 2 * var(--bd-ribbon-overhang));
}

/* ── 2f. Status chip ─────────────────────────────────────────────────────────
   The badge drawn as one short line (1.60.0): `badge.short`, else the label,
   in an aria-hidden span; the full label is read from a visually hidden span
   in the body. In a grid card it lies in the cover band between the jacket
   and the hairline, the box's full width, absolutely positioned so a card
   with a chip is exactly as tall as one without. Anywhere else it is the
   body's last line, as wide as its text. The tone pairs are the badge's (3),
   so each keeps the contrast measured there; .bd-badge itself is untouched
   and still used outside the card. */

.bd-book-card__chip {
    display: inline-block;
    flex: none;
    align-self: flex-start;
    max-width: 100%;
    height: var(--bd-card-chip-h);
    margin-top: var(--bd-space-xs);
    padding: 0 var(--bd-space-xs);
    overflow: hidden;
    border-radius: var(--bd-radius);
    font-family: var(--bd-font-sans);
    font-size: var(--bd-fs-xs);
    font-weight: var(--bd-fw-heading);
    line-height: var(--bd-card-chip-h);
    letter-spacing: .04em;
    text-align: center;
    text-overflow: ellipsis;
    text-transform: uppercase;
    white-space: nowrap;
    background-color: var(--bd-neutral-soft);
    color: var(--bd-neutral);
}

.bd-book-card__cover > .bd-book-card__chip {
    position: absolute;
    right: 0;
    bottom: var(--bd-card-chip-bottom);
    left: 0;
    z-index: 2;
    display: block;
    max-width: none;
    margin: 0;
}

/* Clear of the "..." pinned in the row's bottom-right corner, and after the
   foot's subject: the row's foot is display: contents. */
.bd-book-card--row .bd-book-card__chip {
    order: 1;
    max-width: calc(100% - var(--bd-card-more-size) - var(--bd-space));
}

.bd-book-card__chip--success {
    background-color: var(--bd-success-soft);
    color: var(--bd-success-ink);
}

.bd-book-card__chip--warning {
    background-color: var(--bd-warning-soft);
    color: var(--bd-warning-ink);
}

.bd-book-card__chip--danger {
    background-color: var(--bd-danger-soft);
    color: var(--bd-danger);
}

.bd-book-card__chip--info {
    background-color: var(--bd-info-soft);
    color: var(--bd-info);
}

.bd-book-card__chip--neutral {
    background-color: var(--bd-neutral-soft);
    color: var(--bd-neutral);
}

/* ═══════════════════════════════════════════════════════════════════════════
   3. BADGES
   State travels in the label as well as the colour — which is why an
   institution accent landing near a status colour is harmless, and why these
   tones are fixed and never derived from --bd-accent.
   ═══════════════════════════════════════════════════════════════════════════ */

.bd-badge {
    display: inline-block;
    align-self: flex-start;
    padding: 6px 10px;
    border-radius: var(--bd-radius);
    font-family: var(--bd-font-sans);
    font-size: var(--bd-fs-xs);
    font-weight: var(--bd-fw-heading);
    line-height: 1.2;
    letter-spacing: .06em;
    text-transform: uppercase;
    background-color: var(--bd-neutral-soft);
    color: var(--bd-neutral);
}

.bd-badge--success {
    background-color: var(--bd-success-soft);
    color: var(--bd-success-ink);
}

.bd-badge--warning {
    background-color: var(--bd-warning-soft);
    color: var(--bd-warning-ink);
}

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

.bd-badge--info {
    background-color: var(--bd-info-soft);
    color: var(--bd-info);
}

.bd-badge--neutral {
    background-color: var(--bd-neutral-soft);
    color: var(--bd-neutral);
}

/* ═══════════════════════════════════════════════════════════════════════════
   4. BUTTONS
   The www.giappichelli.it standard (1.49.0, sizes and outline 1.52.0): a
   navy primary, a tinted secondary (--ghost) and a transparent --outline,
   all 1px navy border and --bd-btn-radius (3px), plus --danger for
   destructive actions and the bare-glyph icon button for every per-item
   action. Three sizes: --sm 36px, default 44px, --lg 52px (tokens.css 8b). Hover, focus and active change background, border colour
   and text colour ONLY: no padding, no icon. Every text/background pair is
   at least 4.5:1 in every state (WCAG 1.4.3), every border and the focus
   outline at least 3:1 (1.4.11), and keyboard focus always adds a 2px
   outline, never a colour change alone (2.4.7). Ratios: CHANGELOG 1.49.0.

   Why the state rules are !important: Divi's Customizer prints its button
   hover colours with !important on WooCommerce `.button` selectors, and
   bd-core-registration's buttons carry `button bd-btn`; without !important a
   hover there turns the text white on the light-blue fill (2.19:1). The
   state selectors exclude a disabled button, so a disabled one never
   changes on hover, and a menu item (the cancel-loan entry inside the "..."
   dropdown, any [role="menuitem"]), which keeps its own menu colours.
   ═══════════════════════════════════════════════════════════════════════════ */

.bd-btn {
    /* The three heights include the 1px border wherever the page has no
       global border-box reset (Divi has one): 44px, never 46px. */
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--bd-space-sm);
    padding: 0 var(--bd-space-lg);
    min-height: var(--bd-btn-h);   /* 44px: the Divi button preset's height; WCAG 2.5.5 target */
    border: 1px solid transparent;
    border-radius: var(--bd-btn-radius);
    font-family: var(--bd-font-sans);
    font-size: var(--bd-fs-md);
    font-weight: var(--bd-fw-medium);
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

/* Divi decorates every button with an icon in ::after (or ::before, with the
   Customizer's icon placement on the left) and widens its padding on hover,
   so a button would jump a few pixels under the cursor. */
.bd-btn::before,
.bd-btn::after {
    display: none !important;
}

/* Keyboard focus: the hover colours of each variant below PLUS this outline,
   navy on the page around the button (15.50:1 on white). */
.bd-btn:focus-visible {
    outline: 2px solid var(--bd-blue);
    outline-offset: 2px;
}

/* A theme's `a:hover` (0,1,1) underlines an anchor drawn as a button; this
   rule is (0,2,1) and keeps every <a class="bd-btn"> undecorated. */
a.bd-btn:hover,
a.bd-btn:focus-visible {
    text-decoration: none;
}

/* The :not() is load-bearing, and it is here because leaving it out broke the
   "..." trigger. This rule is (0,2,0) and `.bd-btn--icon`'s own `padding: 0`
   is (0,1,0), so on hover it won and gave a 40px-wide circle 24px of padding
   on each side. The content box collapsed to zero and the icon vanished under
   the cursor — the ring stayed, the three dots did not. An icon button has no
   padding to defend against Divi in the first place: its size is fixed.
   A menu item (the cancel-loan entry inside the "..." dropdown, any
   [role="menuitem"]) keeps its own menu padding and is excluded too.
   --bd-btn-hover-padding-x is a published contract: a consumer whose button
   has a different horizontal padding sets it on that button (or an ancestor)
   so the hover keeps that padding instead of jumping to --bd-space-lg. */
.bd-btn:not(.bd-btn--icon):not(.bd-btn-cancel-loan--menu-item):not([role="menuitem"]):hover {
    padding: 0 var(--bd-btn-hover-padding-x, var(--bd-space-lg)) !important;
}

.bd-btn--primary {
    background-color: var(--bd-blue-navy);
    border-color: var(--bd-blue-navy);
    color: var(--bd-text-invert);
}

/* The site's light-blue fill with NAVY text (7.06:1): its white text measures
   2.19:1. The border stays navy rather than the fill's #9BAEE4, which would
   leave the control's boundary at 2.19:1 on white (WCAG 1.4.11). */
.bd-btn--primary:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):hover,
.bd-btn--primary:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):focus-visible,
.bd-btn--primary:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):active {
    background-color: var(--bd-blue-light) !important;
    border-color: var(--bd-blue) !important;
    color: var(--bd-blue) !important;
}

/* Secondary (1.53.0): white, navy border and text (15.50:1); the states fill
   navy with white text (15.50:1), the ring added by :focus-visible above. */
.bd-btn--ghost {
    background-color: var(--bd-btn-secondary-bg);
    border-color: var(--bd-blue);
    color: var(--bd-blue);
}

.bd-btn--ghost:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):hover,
.bd-btn--ghost:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):focus-visible,
.bd-btn--ghost:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):active {
    background-color: var(--bd-btn-secondary-bg-hover) !important;
    border-color: var(--bd-blue) !important;
    color: var(--bd-btn-secondary-text-hover) !important;
}

/* Destructive (cancel a loan, clear all): the secondary's shape in the danger
   colours. --bd-danger text 5.61:1 on -soft, 5.05:1 on -soft-strong; the
   border 6.54:1 on white. Kept AFTER --ghost on purpose: both state rules are
   !important at the same specificity, so source order is what lets danger
   win on a `bd-btn--ghost bd-btn--danger` (bd-b2b-loans' cancel loan). */
.bd-btn--danger {
    background-color: var(--bd-danger-soft);
    border-color: var(--bd-danger);
    color: var(--bd-danger);
}

.bd-btn--danger:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):hover,
.bd-btn--danger:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):focus-visible,
.bd-btn--danger:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):active {
    background-color: var(--bd-danger-soft-strong) !important;
    border-color: var(--bd-danger) !important;
    color: var(--bd-danger) !important;
}

/* Outline (1.52.0): navy text and border on whatever is behind it (15.50:1 on
   white); the states fill navy with white text (15.50:1), the ring added by
   :focus-visible above. For a light background only: on a navy band the
   border would vanish. */
.bd-btn--outline {
    background-color: transparent;
    border-color: var(--bd-blue);
    color: var(--bd-blue);
}

.bd-btn--outline:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):hover,
.bd-btn--outline:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):focus-visible,
.bd-btn--outline:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):active {
    background-color: var(--bd-blue) !important;
    border-color: var(--bd-blue) !important;
    color: var(--bd-text-invert) !important;
}

.bd-btn[disabled],
.bd-btn[aria-disabled="true"],
.bd-btn.is-disabled {
    border-color: var(--bd-blue-muted);
    background-color: var(--bd-white);
    color: var(--bd-blue-muted);
    cursor: not-allowed;
}

.bd-btn--primary[disabled],
.bd-btn--primary[aria-disabled="true"],
.bd-btn--primary.is-disabled {
    background-color: var(--bd-blue-muted);
    border-color: var(--bd-blue-muted);
    color: var(--bd-white);
}

/* A disabled outline keeps its transparent fill; a disabled icon button keeps
   no fill and a decorative --bd-border circle, its glyph --bd-border-strong
   (3.20:1 on white, 2.94:1 on --bd-blue-wash, where WCAG exempts an
   inactive control; #9BAEE4 measured 2.19:1). */
.bd-btn--outline[disabled],
.bd-btn--outline[aria-disabled="true"],
.bd-btn--outline.is-disabled {
    background-color: transparent;
}

.bd-btn--icon[disabled],
.bd-btn--icon[aria-disabled="true"],
.bd-btn--icon.is-disabled {
    background-color: transparent;
    border-color: var(--bd-border);
    color: var(--bd-border-strong);
}

/* An unavailable action that still opens the "why" dialog (BD_Core_Shared_Modal)
   is a working control, not a disabled one: subtle text (5.23:1) and a
   --bd-border-strong boundary (3.20:1) on white, whatever its style. */
.bd-btn.is-disabled.bd-modal-opener:not(.bd-btn--icon) {
    background-color: var(--bd-white);
    border-color: var(--bd-border-strong);
    color: var(--bd-text-subtle);
}

/* ── Sizes ───────────────────────────────────────────────────────────────────
   Small (36px) for dense contexts (table row actions, inline list actions,
   card actions), large (52px) for the one main action of a form or a cart.
   Each combines with --primary, --ghost, --outline or --danger; an icon
   button has its own size and never takes either. Each sets
   --bd-btn-hover-padding-x to its own side padding, so the Divi hover defence
   above keeps it instead of jumping to --bd-space-lg. No consumer sheet
   resizes a .bd-btn. */

.bd-btn--sm {
    --bd-btn-hover-padding-x: var(--bd-btn-pad-x-sm);

    min-height: var(--bd-btn-h-sm);
    padding: 0 var(--bd-btn-pad-x-sm);
    font-size: var(--bd-btn-fs-sm);
}

.bd-btn--lg {
    --bd-btn-hover-padding-x: var(--bd-btn-pad-x-lg);

    min-height: var(--bd-btn-h-lg);
    padding: 0 var(--bd-btn-pad-x-lg);
    font-size: var(--bd-btn-fs-lg);
}

/* ── 4a. Icon button: a navy circle ─────────────────────────────────────────
   1.53.0: a 1px navy circle at rest, so the round control reads as one (the
   bare glyph of 1.52.0 was an invisible shape); glyph and border 15.50:1 on
   white, 14.22:1 on --bd-blue-wash. Hover and active fill it --bd-blue-tint
   (navy on the tint 13.65:1), keyboard focus the same plus the 2px ring.
   The hit area travels in --bd-btn-icon-size so a card modifier can set it
   once: 44px in the catalogue grid (the .bd-btn height), 34px in a row or
   compact card, 40px elsewhere (the carousel sets its arrows to 44px, 6a). */

.bd-btn--icon {
    --bd-btn-icon-size: 40px;

    width: var(--bd-btn-icon-size);
    height: var(--bd-btn-icon-size);
    min-height: 0;
    padding: 0 !important;
    border-radius: var(--bd-radius-circle);
    background-color: transparent;
    border-color: var(--bd-blue);
    color: var(--bd-blue);
}

.bd-btn--icon:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):hover,
.bd-btn--icon:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):focus-visible,
.bd-btn--icon:not([disabled]):not([aria-disabled="true"]):not(.is-disabled):not([role="menuitem"]):not(.bd-btn-cancel-loan--menu-item):active {
    background-color: var(--bd-blue-tint) !important;
    border-color: var(--bd-blue) !important;
    color: var(--bd-blue) !important;
}

.bd-btn--icon svg {
    display: block;
    width: 50%;
    height: 50%;
    fill: currentColor;
}

.bd-book-card--grid .bd-btn--icon,
.bd-book-card--row .bd-btn--icon {
    --bd-btn-icon-size: var(--bd-card-more-size);

    position: relative;
}

/* In the grid's foot the 32px circle keeps a 44px line (1.60.0). */
.bd-book-card--grid .bd-btn--icon {
    margin: 6px 0;
}

/* The 44px hit area of the 32px card "..." (WCAG 2.5.5): an empty box
   overhanging the circle by 7px, 6px past the 1px border. It outranks the
   `display: none !important` that keeps Divi's icon out of every button. */
.bd-book-card--grid .bd-btn--icon::before,
.bd-book-card--row .bd-btn--icon::before {
    content: "";
    position: absolute;
    inset: -7px;
    display: block !important;
}

/* ── Line icons (BD_Core_Shared_Icons) ────────────────────────────────────────────
   Stroke glyphs sized by the surrounding text. `fill: none` is restated in CSS
   because a presentation attribute loses to any stylesheet rule: the icon
   button's own `svg { fill: currentColor }` above would otherwise fill every
   outline solid. */
.bd-icon {
    display: inline-block;
    width: 1.25em;
    height: 1.25em;
    flex: none;
    vertical-align: middle;
    fill: none;
}

.bd-btn--icon .bd-icon {
    fill: none;
}

.bd-book-card--compact .bd-btn--icon {
    --bd-btn-icon-size: 34px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   5. FORM FIELDS
   Shared by the support form, the registration and profile forms and the
   catalogue's facet panel. The border is --bd-border-strong and not
   --bd-border: a control's boundary needs 3:1 (WCAG 1.4.11), and the
   decorative hairline is at 1.29:1.
   ═══════════════════════════════════════════════════════════════════════════ */

.bd-form-field {
    display: flex;
    flex-direction: column;
    gap: var(--bd-space-xs);
    margin-bottom: var(--bd-space-md);
}

.bd-form-field > label {
    font-family: var(--bd-font-sans);
    font-size: var(--bd-fs-sm);
    font-weight: var(--bd-fw-medium);
    color: var(--bd-text);
}

.bd-form-field input[type="text"],
.bd-form-field input[type="email"],
.bd-form-field input[type="search"],
.bd-form-field input[type="tel"],
.bd-form-field input[type="url"],
.bd-form-field input[type="password"],
.bd-form-field select,
.bd-form-field textarea {
    width: 100%;
    padding: var(--bd-space) var(--bd-space-md);
    border: 1px solid var(--bd-border-strong);
    border-radius: var(--bd-radius);
    background-color: var(--bd-white);
    font-family: var(--bd-font-sans);
    font-size: var(--bd-fs-md);
    color: var(--bd-text);
}

.bd-form-field input::placeholder,
.bd-form-field textarea::placeholder {
    color: var(--bd-text-subtle);
}

.bd-form-field input:focus,
.bd-form-field select:focus,
.bd-form-field textarea:focus {
    outline: 2px solid var(--bd-accent);
    outline-offset: 1px;
    border-color: var(--bd-accent);
}

.bd-form-field--invalid input,
.bd-form-field--invalid select,
.bd-form-field--invalid textarea {
    border-color: var(--bd-danger);
}

.bd-form-field__hint {
    font-size: var(--bd-fs-sm);
    color: var(--bd-text-subtle);
}

.bd-form-field__error {
    font-size: var(--bd-fs-sm);
    color: var(--bd-danger);
}

/* ═══════════════════════════════════════════════════════════════════════════
   6. CAROUSEL
   The track alone is the whole component without JavaScript: a native
   scroll-snap strip that already works with a keyboard and a trackpad.
   bd-core-shared/assets/js/carousel.js adds the arrows and the dots on top and
   removes nothing.
   ═══════════════════════════════════════════════════════════════════════════ */

.bd-carousel {
    /* No side gutter (1.53.0): the strip spans the whole frame, so its first
       and last card sit on the x of the section title, the header and the
       footer. The arrows (6a) live in a control row under the strip at every
       width, never beside it. */
    --bd-carousel-arrow-size: 44px;

    position: relative;
}

.bd-carousel__track {
    /* The caller's figure — per_view in the shortcode, written inline on the
       <ul> — is the DESKTOP count and nothing more. An inline custom property
       beats every rule in this file, so the breakpoints below never touch it:
       they lower the cap, and the count actually drawn is the smaller of the
       two. 3 is what the mockups draw when nobody says otherwise. */
    --bd-carousel-per-view: 3;
    --bd-carousel-per-view-cap: 6;
    --bd-carousel-per-view-shown: min(var(--bd-carousel-per-view), var(--bd-carousel-per-view-cap));

    /* 0 between grid cards, which carry their own 45px inset (1.60.0); a
       strip of bordered row cards keeps 16px so two borders never touch. */
    --bd-carousel-gap: 0px;

    display: flex;
    flex-wrap: nowrap;
    gap: var(--bd-carousel-gap);
    margin: 0;
    min-width: 0;
    /* !important because .bd-books-list above needs it against Divi, and the
       track carries that class too — without it this padding would lose to its
       own stylesheet and the native scrollbar would have nowhere to sit. */
    padding: 0 0 var(--bd-space-sm) !important;
    list-style: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: thin;
}

/* overflow-x: auto makes the track clip vertically too, so a cover ribbon
   overhanging the top of a card (2e) would be cut. The room is reserved only
   on a track that holds a ribbon: a strip without one keeps its position. A
   browser without :has() cuts the overhang, never the label. */
.bd-carousel__track:has(.bd-ribbon) {
    padding-top: 8px !important;   /* = --bd-ribbon-overhang, set on .bd-ribbon itself */
}

.bd-carousel__track:has(> .bd-book-card--row) {
    --bd-carousel-gap: var(--bd-space-md);
}

.bd-carousel__track > * {
    flex: 0 0 calc(
        (100% - (var(--bd-carousel-per-view-shown) - 1) * var(--bd-carousel-gap))
        / var(--bd-carousel-per-view-shown)
    );
    scroll-snap-align: start;
}

/* The "..." sits on the card's floor in a strip whatever card layout a
   caller puts there. A track's cards are already all the same height — they
   are flex items of a row that stretches them — so without this the control
   would float just under the text at a different height on each card. The
   grid card already pins its foot (2a); this covers any other layout. */
.bd-carousel__track > .bd-book-card .bd-book-card__body {
    flex: 1 1 auto;
}

.bd-carousel__track > .bd-book-card .bd-book-card__foot,
.bd-carousel__track > .bd-book-card .bd-book-card__body > .bd-book-card__actions {
    margin-top: auto;
}

/* Only once the script has taken over: before that the strip must keep its
   own visible scrollbar, or a viewer without JS has no way to move it. */
.bd-carousel.is-enhanced .bd-carousel__track {
    scroll-behavior: smooth;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.bd-carousel.is-enhanced .bd-carousel__track::-webkit-scrollbar {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .bd-carousel.is-enhanced .bd-carousel__track {
        scroll-behavior: auto;
    }
}

/* ── 6a. The control row ────────────────────────────────────────────────────
   Once the script has run, the carousel is a wrapping flex row: the strip
   takes a whole line and the arrows and dots form the line beneath it,
   prev · dots · next (DOM order is track, prev, next, dots). The arrows are
   .bd-btn--icon at --bd-carousel-arrow-size (44px, the .bd-btn height). With
   a single page carousel.js hides the arrows and the dots alike, so no empty
   control row is left under the strip. Under 767px the dots take a line of
   their own and prev and next sit side by side beneath them (6c). */

.bd-carousel.is-enhanced {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: var(--bd-space-md);
}

.bd-carousel.is-enhanced .bd-carousel__track {
    flex: 1 1 100%;
    min-width: 0;
}

.bd-carousel .bd-carousel__arrow {
    --bd-btn-icon-size: var(--bd-carousel-arrow-size);
}

/* `.bd-btn` is display: inline-flex, which beats the UA's `[hidden] { display:
   none }`: without this a hidden arrow would still be drawn. */
.bd-carousel__arrow[hidden] {
    display: none;
}

.bd-carousel__arrow--prev { order: 1; }
.bd-carousel__dots        { order: 2; }
.bd-carousel__arrow--next { order: 3; }

/* ── 6b. Dots ────────────────────────────────────────────────────────────── */

.bd-carousel__dots {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* carousel.js sets `hidden` on a single page; the author `display: flex`
   above would otherwise beat the UA's `[hidden] { display: none }` and leave
   an empty band under the strip. */
.bd-carousel__dots[hidden] {
    display: none;
}

/* 24x24 is WCAG 2.5.8's minimum target; the 8px disc the mockups draw is
   painted by ::before, so the discs keep their 16px visual spacing inside the
   targets and a finger gets three times the surface. carousel.js measures
   cards, never dots, so nothing there depends on this size. */
.bd-carousel__dot {
    position: relative;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 0;
    border-radius: var(--bd-radius-circle);
    background: transparent;
    cursor: pointer;
}

.bd-carousel__dot::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 8px;
    height: 8px;
    border-radius: var(--bd-radius-circle);
    background-color: #C9CEDD;
    transform: translate(-50%, -50%);
    transition: background-color .15s ease, transform .15s ease;
}

.bd-carousel__dot[aria-current="true"]::before {
    background-color: var(--bd-blue);
    transform: translate(-50%, -50%) scale(1.25);
}

.bd-carousel__dot:focus-visible {
    outline: 2px solid var(--bd-blue);
    outline-offset: 0;
}

/* The overflow marker past the eighth page. Not a control: it says the strip
   runs on, and the arrows are what reach the rest. */
.bd-carousel__dots-more {
    margin-left: var(--bd-space-sm);
    font-family: var(--bd-font-sans);
    font-size: var(--bd-fs-sm);
    line-height: 1;
    color: var(--bd-text-subtle);
}

/* ── 6c. Breakpoints ─────────────────────────────────────────────────────── */

@media (max-width: 980px) {
    .bd-carousel__track {
        --bd-carousel-per-view-cap: 2;
    }
}

@media (max-width: 767px) {
    .bd-carousel__track {
        --bd-carousel-per-view-cap: 1;
    }

    /* One row of up to eight 24px dots plus the two 44px arrows does not fit a
       phone: the next arrow wrapped alone under the dots. So the dots take the
       whole row and the two arrows sit side by side beneath them. */
    .bd-carousel.is-enhanced .bd-carousel__dots {
        flex: 1 1 100%;
    }

    .bd-carousel__arrow--prev { order: 3; }
    .bd-carousel__arrow--next { order: 4; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   7. UTILITIES
   ═══════════════════════════════════════════════════════════════════════════ */

/* Read by assistive technology, invisible on screen: the standard clip
   pattern (the same as core's .screen-reader-text, which a theme may not
   ship on the front end). */
.bd-visually-hidden {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   8. TABLES
   One table for every plugin (1.53.0): a --bd-bg-subtle header row with
   heading-colour 600 text (14.22:1), 15px cells, a decorative --bd-border
   hairline under every row. An action cell holds .bd-btn--sm.

   Why the class is written twice: Divi styles tables through its content
   wrappers (`.entry-content table`, `.entry-content tr td`, up to (0,1,3)),
   and a single `.bd-table th` (0,1,1) would lose its padding, border and
   colours to them. `.bd-table.bd-table th` is (0,2,1) and wins without
   !important, so a consumer can still override with the same doubling.
   ═══════════════════════════════════════════════════════════════════════════ */

.bd-table.bd-table {
    width: 100%;
    margin: 0;
    border: 0;
    border-collapse: collapse;
    border-spacing: 0;
    font-family: var(--bd-font-sans);
    font-size: var(--bd-fs-md);
    color: var(--bd-text);
    text-align: start;
}

.bd-table.bd-table th,
.bd-table.bd-table td {
    padding: var(--bd-space-sm) var(--bd-space-md);
    border: 0;
    border-bottom: 1px solid var(--bd-border);
    font-size: var(--bd-fs-md);
    line-height: 1.4;
    text-align: start;
    vertical-align: middle;
}

.bd-table.bd-table th {
    background-color: var(--bd-bg-subtle);
    color: var(--bd-text-heading);
    font-weight: var(--bd-fw-medium);
}

/* ── 8a. Stacked on phones ───────────────────────────────────────────────────
   `.bd-table--stack` reflows under 767px into one card per row (WCAG 1.4.10:
   no horizontal scroll at 320 CSS px). The header row is visually hidden but
   still read; each cell prints its own label from `data-label`, in a left
   column 40% wide drawn inside the cell's own left padding, so a cell holding
   text, a link and buttons keeps them together on the right. A cell without
   `data-label` (an action cell) takes the whole width. */

@media (max-width: 767px) {
    .bd-table--stack.bd-table--stack thead {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        clip-path: inset(50%);
        white-space: nowrap;
        border: 0;
    }

    .bd-table--stack.bd-table--stack,
    .bd-table--stack.bd-table--stack tbody,
    .bd-table--stack.bd-table--stack tr {
        display: block;
    }

    .bd-table--stack.bd-table--stack tr {
        display: grid;
        gap: var(--bd-space-xs);
        margin: 0 0 var(--bd-space-sm);
        padding: var(--bd-space-sm) var(--bd-space-md);
        border: 1px solid var(--bd-border);
        border-radius: var(--bd-radius);
    }

    .bd-table--stack.bd-table--stack td {
        display: flow-root;
        min-width: 0;
        padding: 0 0 0 40%;
        border: 0;
        overflow-wrap: anywhere;
    }

    /* The label sits in the cell's 40% left padding: percentages of a margin
       are of the cell's content box (60% of the row), so 200%/3 of it is the
       row's 40%. Floated, so a two-line label grows the cell, never overlaps. */
    .bd-table--stack.bd-table--stack td::before {
        content: attr(data-label);
        float: left;
        box-sizing: border-box;
        width: calc(200% / 3);
        margin-left: calc(-200% / 3);
        padding-right: var(--bd-space-sm);
        color: var(--bd-text-subtle);
        font-weight: var(--bd-fw-medium);
    }

    .bd-table--stack.bd-table--stack td:not([data-label]),
    .bd-table--stack.bd-table--stack td[data-label=""] {
        padding-left: 0;
    }

    .bd-table--stack.bd-table--stack td:not([data-label])::before,
    .bd-table--stack.bd-table--stack td[data-label=""]::before {
        content: none;
    }
}

/* ── 8b. Scroll wrapper ──────────────────────────────────────────────────────
   For a wide data table that must stay a table on every width. The consumer
   gives the wrapper tabindex="0", role="region" and an aria-label naming the
   table, so a keyboard user can focus it and scroll it with the arrow keys
   (WCAG 2.1.1); focus draws the 2px navy ring. */

/* position: relative is load-bearing: a visually hidden header label
   (.bd-visually-hidden, position: absolute) inside the table otherwise takes
   the page as its containing block, escapes the overflow clip and widens the
   whole page (measured: a 900px table pushed a 360px page to 791px). */
.bd-table-scroll {
    position: relative;
    max-width: 100%;
    overflow-x: auto;
}

.bd-table-scroll:focus-visible {
    outline: 2px solid var(--bd-blue);
    outline-offset: 2px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   9. INPUTS AND SELECTS
   A standalone field, outside a .bd-form-field (5): a filter bar, a table
   toolbar, a profile row. 44px (--bd-btn-h, the button height, so a field
   and a button line up), --sm 36px; 15px text, 12px sides, a 1px
   --bd-border-strong boundary (3.20:1 on white, WCAG 1.4.11), --bd-radius,
   white. Width is the consumer's layout; nothing else is.

   Doubled class for the same reason as the table: Divi's base sheet styles
   `input[type="text"]` (0,1,1) with a #BBBBBB border (1.92:1) and 2px
   padding. The height travels in --bd-field-h so --sm can lower it with a
   single class.
   ═══════════════════════════════════════════════════════════════════════════ */

.bd-input.bd-input,
.bd-select.bd-select {
    box-sizing: border-box;
    max-width: 100%;
    min-height: var(--bd-field-h, var(--bd-btn-h));
    margin: 0;
    padding: 0 12px;
    border: 1px solid var(--bd-border-strong);
    border-radius: var(--bd-radius);
    background-color: var(--bd-white);
    color: var(--bd-text);
    font: inherit;
    font-size: var(--bd-fs-md);
    line-height: 1.4;
}

textarea.bd-input.bd-input {
    padding: var(--bd-space-sm) 12px;
}

.bd-input--sm,
.bd-select--sm {
    --bd-field-h: var(--bd-btn-h-sm);
}

.bd-input.bd-input::placeholder {
    color: var(--bd-text-subtle);
    opacity: 1;
}

/* Keyboard and pointer focus alike (a text field matches :focus-visible on
   both): the 2px navy ring, as the buttons, 15.50:1 on white. */
.bd-input.bd-input:focus-visible,
.bd-select.bd-select:focus-visible {
    outline: 2px solid var(--bd-blue);
    outline-offset: 2px;
}

/* Disabled: muted, exempt from contrast, no pointer. */
.bd-input.bd-input:disabled,
.bd-select.bd-select:disabled {
    border-color: var(--bd-border);
    background-color: var(--bd-bg-subtle);
    color: var(--bd-text-subtle);
    cursor: not-allowed;
}

/* ═══════════════════════════════════════════════════════════════════════════
   10. BOOK-LIST TOOLBAR
   BD_Core_Shared_Book_List_Toolbar (1.56.0): search, format and category filters
   and the list/grid/carousel switch above a personal book list. Fields are
   .bd-input/.bd-select (9), buttons .bd-btn (4). One wrapping row: at 360px
   every control takes its own line, never a horizontal scroll (WCAG 1.4.10).
   Colours: navy on white 15.50:1, white on navy 15.50:1, navy on
   --bd-blue-tint 13.65:1; the switch boundary --bd-border-strong 3.20:1
   (1.4.11); focus is the 2px navy ring (2.4.7).
   ═══════════════════════════════════════════════════════════════════════════ */

.bd-list-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--bd-space-sm) var(--bd-space-md);
    margin: 0 0 var(--bd-space-md);
    min-width: 0;
}

/* 32rem basis: the form takes the first line and the switch wraps after it. */
.bd-list-toolbar__form {
    display: flex;
    flex: 1 1 32rem;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--bd-space-sm);
    min-width: 0;
    margin: 0;
}

/* Growing fields: every row ends on the frame's right edge, never mid-width. */
.bd-list-toolbar__field {
    flex: 1 1 10rem;
    min-width: 0;
    max-width: 100%;
}

.bd-list-toolbar__field--search {
    flex: 2 1 14rem;
}

/* EPUB/PDF needs little room: the category select keeps the rest. */
.bd-list-toolbar__field--format {
    flex: 0 1 9rem;
}

.bd-list-toolbar__search.bd-input,
.bd-list-toolbar__select.bd-select {
    width: 100%;
}

/* Visible until the script runs, so a mouse user without JavaScript can
   apply a select; once enhanced, hidden until it has focus, and visible for
   the whole time the form holds a pending keyboard change (`is-pending`),
   wherever focus is. */
.bd-list-toolbar__form.is-enhanced:not(.is-pending) .bd-list-toolbar__submit:not(:focus) {
    position: absolute;
    width: 1px;
    height: 1px;
    min-height: 0;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* margin-left: auto keeps the switch on the right when it wraps; the 8px gap
   keeps a link's 2px ring at 2px offset clear of the navy current link. */
.bd-list-toolbar__views {
    display: inline-flex;
    flex: 0 0 auto;
    gap: var(--bd-space-sm);
    margin-left: auto;
    align-self: flex-start;
}

.bd-list-toolbar__view {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--bd-btn-h);
    height: var(--bd-btn-h);
    border: 1px solid var(--bd-border-strong);
    border-radius: var(--bd-btn-radius);
    background-color: var(--bd-white);
    color: var(--bd-blue-navy);
    text-decoration: none;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

.bd-list-toolbar__view:hover {
    border-color: var(--bd-blue-navy);
    background-color: var(--bd-blue-tint);
    color: var(--bd-blue-navy);
    text-decoration: none;
}

.bd-list-toolbar__view:focus-visible {
    outline: 2px solid var(--bd-blue);
    outline-offset: 2px;
    text-decoration: none;
}

.bd-list-toolbar__view.is-active,
.bd-list-toolbar__view.is-active:hover {
    border-color: var(--bd-blue-navy);
    background-color: var(--bd-blue-navy);
    color: var(--bd-text-invert);
}

.bd-list-toolbar__view-icon {
    width: 16px;
    height: 16px;
    fill: currentColor;
}

@media (max-width: 767px) {
    .bd-list-toolbar__field,
    .bd-list-toolbar__field--search,
    .bd-list-toolbar__field--format {
        flex: 1 1 100%;
    }
}
