/* /chronology — the shelf rail.
 *
 * Contiguous runs of issues collected by one edition render as a run-group:
 * a book-spine rail on the left (cover, spine-set title, run length) beside
 * the issue rows it covers. Uncollected stretches read as dashed gaps in the
 * shelf. Gold (--accent-canonical) is reserved on this page for the rail —
 * every color here derives from theme tokens, so light/dark both hold.
 */

.chrono-toolbar {
    top: var(--nav-h);
    z-index: 5;
    padding: 0.5rem 0;
    background: var(--bg);
    border-bottom: 1px solid var(--border);
    /* fill the sliver between the nav's bottom edge and this bar */
    box-shadow: 0 -12px 0 0 var(--bg);
}

/* The desktop control row. Flex lives here, NOT in Bootstrap's d-flex: that
 * utility is !important and would beat the mobile display:none below, pinning
 * the three-line row on phones again (GH #122). */
.chrono-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

/* The mobile sheet trigger. Does not exist wherever the row fits inline; the
 * mobile block below turns it on and turns the row off. */
.chrono-filter-trigger {
    display: none;
}

/* base.html does not load styles.css (the global [x-cloak] home), so the
 * sheet's date row and the trigger's count badge would flash before Alpine's
 * first tick without this -- same reason as .chrono-datejump[x-cloak] below. */
.chrono-filters [x-cloak],
.chrono-filter-trigger [x-cloak] {
    display: none !important;
}

/* The era header is a full-width toggle button: chevron, title+stat, and a
 * Show/Hide hint on the right. Reset the native button chrome. */
.chrono-era-head {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    margin-bottom: 2px;
    padding: 6px 4px;
    background: none;
    border: 0;
    border-radius: var(--radius-sm);
    text-align: left;
    color: inherit;
    cursor: pointer;
    transition: background var(--motion-fast) var(--ease-standard);
}

.chrono-era-head:hover {
    background: var(--surface-2);
}

.chrono-era-head:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

.chrono-era-headings {
    display: flex;
    align-items: baseline;
    gap: 12px;
    flex-wrap: wrap;
    min-width: 0;
    flex: 1;
}

.chrono-era-chevron {
    flex: none;
    color: var(--text-dim);
    transform: rotate(-90deg);
    transition: transform var(--motion-med) var(--ease-standard);
}

.chrono-era--open .chrono-era-chevron {
    transform: rotate(0deg);
}

.chrono-era-hint {
    flex: none;
    font-size: 0.75rem;
    color: var(--text-dim);
    font-variant-numeric: tabular-nums;
}

/* Collapse animation: a 0fr→1fr grid row animates the real auto height of the
 * body without measuring it in JS. The inner clips overflow while closed. */
.chrono-era-body {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows var(--motion-med) var(--ease-standard);
}

.chrono-era--open .chrono-era-body {
    grid-template-rows: 1fr;
}

.chrono-era-body-inner {
    min-height: 0;
    overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
    .chrono-era-body,
    .chrono-era-chevron {
        transition: none;
    }
}

.chrono-era-title {
    font-family: var(--font-display);
    font-size: 1.15rem;
    letter-spacing: 0.01em;
    margin: 0;
}

.chrono-era-stat {
    margin: 0;
    font-size: 0.8rem;
    color: var(--text-dim);
    font-variant-numeric: tabular-nums;
}

/* --- Run groups: [spine rail | rows] --- */

.chrono-run {
    display: grid;
    grid-template-columns: 96px minmax(0, 1fr);
    column-gap: 16px;
    border-top: 1px solid var(--border);
    padding: 10px 0;
}

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

.chrono-rows {
    margin: 0;
}

/* The spine: gold edge, cover on top, title running down the rail. Sticky so
 * the book you're "inside" follows you through a long run. */
.chrono-spine {
    position: sticky;
    top: calc(var(--nav-h) + 58px); /* clear the sticky toolbar */
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    padding-left: 9px;
    border-left: 3px solid var(--accent-canonical);
    border-radius: 1px;
    text-decoration: none;
    color: var(--text-muted);
}

.chrono-spine:hover .chrono-spine-title,
.chrono-spine:focus-visible .chrono-spine-title {
    color: var(--text);
    text-decoration: underline;
}

.chrono-spine:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 3px;
}

.chrono-spine-cover {
    width: 72px;
    max-width: 100%;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}

.chrono-spine-title {
    font-size: 0.76rem;
    font-weight: 600;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    transition: color var(--motion-fast) var(--ease-standard);
}

/* Long runs (≥12 issues — enough row height that the rail never stretches
 * the group) give the rail real height: set the title vertically, like the
 * spine of the book itself. Shorter runs keep the horizontal clamp above. */
.chrono-run--tall .chrono-spine-title {
    writing-mode: vertical-rl;
    display: block;
    -webkit-line-clamp: unset;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-block-size: 280px;
    font-size: 0.8rem;
    letter-spacing: 0.02em;
}

.chrono-spine-count {
    font-size: 0.7rem;
    color: var(--text-dim);
    font-variant-numeric: tabular-nums;
}

.chrono-spine-owned {
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--status-success-fg);
}

.chrono-spine-owned::before {
    content: "✓ ";
}

/* Short runs (1-2 issues, common where the reading order interleaves
 * series) stay quiet: no cover, one-line label, row-height rail. The big
 * cover + vertical spine is reserved for the runs a book actually carries —
 * that contrast is the page's hierarchy. */
.chrono-run--short {
    padding: 4px 0;
}

.chrono-run--short .chrono-spine {
    position: static;
    gap: 1px;
}

.chrono-run--short .chrono-spine-cover {
    display: none;
}

.chrono-run--short .chrono-spine-title {
    font-size: 0.72rem;
    font-weight: 500;
    -webkit-line-clamp: 2;
}

/* --- Uncollected gaps: a hole in the shelf --- */

.chrono-run--gap .chrono-rail {
    border-left: 3px dashed var(--border);
    padding-left: 9px;
}

.chrono-run--gap .chrono-rows a {
    color: var(--text-muted);
}

.chrono-gap-label {
    position: sticky;
    top: calc(var(--nav-h) + 58px);
    display: inline-block;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-dim);
}

/* A phone in landscape does not have the vertical budget for both the site
 * navbar and this 86px control row. Keep every control in document flow and
 * let it scroll away; the narrow book spine can remain contextual, but no
 * longer needs to reserve space for a toolbar that is not pinned. */
@media (max-height: 480px) {
    .chrono-toolbar {
        position: static !important; /* overrides Bootstrap's .sticky-top */
    }

    .chrono-spine,
    .chrono-gap-label {
        top: calc(var(--nav-h) + .5rem);
    }
}

/* --- Mobile: the rail flips to a run header above its rows --- */

@media (max-width: 640px) {
    /* GH #122: the wrapped control row pinned 126px under the 60px navbar --
     * 22% of an iPhone 14, 28% of an SE. The row leaves the sticky bar for the
     * shared cc-filters bottom sheet (theme.css) and ONE 44px trigger stays.
     * 44 + 2 x 0.25rem + 1px border = 53px; 113px pinned with the navbar,
     * under the 120px / 18% acceptance line. */
    .chrono-toolbar {
        padding: 0.25rem 0;
    }

    .chrono-controls {
        display: none;
    }

    .chrono-filter-trigger {
        display: inline-flex;
        width: 100%;
        justify-content: flex-start;
    }

    /* The reader's position ("1970s · 1975 Mar") is the trigger's whole
     * visible text; the sr-only "Filters" span precedes it in the name. */
    .chrono-filter-summary {
        flex: 1 1 auto;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        text-align: left;
    }

    /* Inside the sheet every control meets the 44px tap floor the shared
     * cc-chip already has. form-select-sm / btn-sm measure ~31px otherwise. */
    .chrono-filters .form-select,
    .chrono-filters .btn {
        min-height: 44px;
    }

    .chrono-filters .form-check {
        min-height: 44px;
        display: flex;
        align-items: center;
        gap: 0.5rem;
        margin: 0;
    }

    /* An era jump is `location.hash = slug`, which scrolls the section head
     * to the top of the viewport -- under the sticky bar unless the
     * scrollport pads for it. 53px is the bar's height from the budget above.
     * Page-scoped: this sheet loads on /chronology only. */
    html {
        scroll-padding-top: calc(var(--nav-h) + 53px);
    }

    .chrono-run {
        grid-template-columns: 1fr;
        row-gap: 6px;
    }

    .chrono-spine,
    .chrono-gap-label {
        position: static;
        flex-direction: row;
        align-items: center;
        border-left-width: 3px;
    }

    .chrono-spine-cover {
        width: 34px;
        flex: none;
    }

    .chrono-run--tall .chrono-spine-title {
        writing-mode: horizontal-tb;
        white-space: normal;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        max-block-size: none;
    }

    .chrono-rows {
        padding-left: 12px;
    }
}

/* --- Shelf view: each era as a bookshelf of standing spines --- */

/* Uniform book height + row gap give a fixed vertical period, so a
 * repeating gradient paints a shelf line under every wrapped row. */
.chrono-shelf {
    --book-h: 200px;
    --shelf-gap: 14px;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    column-gap: 4px;
    row-gap: var(--shelf-gap);
    padding: 6px 8px 2px;
    /* one period = book height + row gap, so the line lands just under
     * every wrapped row of books */
    background: repeating-linear-gradient(
        to bottom,
        transparent 0,
        transparent calc(var(--book-h) + 2px),
        var(--border) calc(var(--book-h) + 2px),
        var(--border) calc(var(--book-h) + 5px),
        transparent calc(var(--book-h) + 5px),
        transparent calc(var(--book-h) + var(--shelf-gap))
    );
    background-origin: content-box;
}

.chrono-book-slot {
    position: relative;
    display: flex;
    align-items: flex-end;
}

/* One run = one standing book. The surface is a narrow slice of the run's
 * own cover art (or a title-hashed tint), scrimmed by ::before so the
 * spine-set title always reads in both themes. */
.chrono-book {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: center;
    height: var(--book-h);
    border-radius: 3px 3px 1px 1px;
    background-size: cover;
    background-position: center top;
    box-shadow:
        inset -4px 0 8px rgba(0, 0, 0, 0.38),
        inset 2px 0 3px rgba(255, 255, 255, 0.10),
        0 1px 3px rgba(0, 0, 0, 0.35);
    text-decoration: none;
    transition: transform var(--motion-fast) var(--ease-standard);
}

.chrono-book::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: linear-gradient(
        180deg,
        rgba(12, 9, 6, 0.78),
        rgba(12, 9, 6, 0.42) 42%,
        rgba(12, 9, 6, 0.82)
    );
}

/* Art-less spines already carry a dark title-hashed tint; the heavy art
 * scrim would flatten them all to black. Light shading keeps the hue. */
.chrono-book--plain::before {
    background: linear-gradient(
        180deg,
        rgba(0, 0, 0, 0.30),
        rgba(255, 255, 255, 0.06) 45%,
        rgba(0, 0, 0, 0.38)
    );
}

.chrono-book:hover,
.chrono-book:focus-visible {
    transform: translateY(-10px);
    z-index: 7; /* above the sticky toolbar so the reveal card never clips */
}

.chrono-book:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 3px;
}

.chrono-book-title {
    position: relative;
    writing-mode: vertical-rl;
    color: #f5efe4;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    line-height: 1;
    max-block-size: calc(var(--book-h) - 52px);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    padding-top: 12px;
}

.chrono-book-count {
    position: relative;
    color: rgba(245, 239, 228, 0.72);
    font-size: 0.62rem;
    font-variant-numeric: tabular-nums;
    padding-bottom: 7px;
}

/* Owned books get the gold base band — the shelf's only accent. */
.chrono-book--owned::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 4px;
    border-radius: 0 0 1px 1px;
    background: var(--accent-canonical);
}

/* Uncollected stretch: an empty slot in the shelf. */
.chrono-book-gap {
    height: calc(var(--book-h) - 44px);
    border: 1px dashed var(--border);
    border-radius: 3px;
    opacity: 0.55;
}

/* Hover/focus reveal: full cover, title, run range. Pointer-events off so
 * it never flickers the hover state it depends on. */
.chrono-book-card {
    position: absolute;
    top: calc(100% + 8px); /* below the book: never clips under the sticky toolbar */
    left: 50%;
    transform: translateX(-50%);
    width: 188px;
    display: none;
    flex-direction: column;
    gap: 4px;
    padding: 8px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
    pointer-events: none;
    text-align: left;
}

.chrono-book:hover .chrono-book-card,
.chrono-book:focus-visible .chrono-book-card {
    display: flex;
}

.chrono-book-card img {
    width: 100%;
    border-radius: var(--radius-sm);
}

/* Both lines are clamped: the card is a fixed 188px wide, and the catalog
   carries 108-char edition titles and runs whose issue label names two long
   series ("... From The Marvel Vault #1 · Defenders: ... #1 · +1 more"). Left
   unbounded they stack into a tall slab hanging off the shelf. */
.chrono-book-card-title {
    color: var(--text);
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}

.chrono-book-card-meta {
    color: var(--text-muted);
    font-size: 0.72rem;
    font-variant-numeric: tabular-nums;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}

.chrono-book-card-owned {
    color: var(--status-success-fg);
    font-size: 0.72rem;
    font-weight: 600;
}

/* The era body clips overflow for its collapse animation; while open, let
 * lifted books and reveal cards escape (collapse re-clips instantly). */
.chrono-era--open .chrono-era-body-inner {
    overflow: visible;
}

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

    .chrono-book:hover,
    .chrono-book:focus-visible {
        transform: none;
    }
}

@media (max-width: 640px) {
    .chrono-shelf {
        --book-h: 150px;
    }

    .chrono-book-card {
        width: 150px;
    }
}

/* Date jump (toolbar) ----------------------------------------------------- */

/* Not `d-flex`: Bootstrap's display utilities are !important, so they beat the
   inline display:none that x-show writes and the picker would stay visible
   with no years in it (pinned by tests/test_alpine_x_show_display.py). */
.chrono-datejump {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

/* base.html does not load styles.css, which is where the global [x-cloak]
   rule lives -- without this the year/month selects flash empty before Alpine
   evaluates x-show and hides them. */
.chrono-datejump[x-cloak] {
    display: none !important;
}

.chrono-row-date {
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Reads as an upward continuation of the era, not a primary action: the
   window below it is what the reader asked for. */
.chrono-load-earlier {
    display: block;
    margin-inline: auto;
}
