/* ================================================================= *
 |  IMAGE LIGHTBOX  —  ?lightbox=new   (Phase 2, 2026-07-25)
 |
 |  Opt-in replacement for the legacy #fringe-modal look (a fixed 1140px
 |  modal-xl panel, the image stretched to fill it, and a full-width grey
 |  caption strip welded underneath).
 |
 |  The idea here is the inverse: there is no panel. The image is the only
 |  surface, sized to the viewport and never upscaled, and the caption is
 |  sized to the *image* — so a 400px still gets a 400px caption instead of
 |  a 1136px slab. Everything is scoped under `.fx-lb` (the modal) or
 |  `body.fx-lb-on`, so the file is inert on the legacy markup.
 |
 |  Loaded from layouts/app.blade.php only when ?lightbox=new is present.
 * ================================================================= */

/* ---- backdrop ------------------------------------------------------
   Bootstrap's .modal-backdrop is a sibling of the modal appended to <body>, so
   it can only be reached through a body class. `fx-lb-open` is set by the script
   for as long as the LIGHTBOX is the open modal — not just `fx-lb-on`, or this
   would also darken the backdrop behind the other modals a page may carry (the
   character appearances list, the list-of-sciences one).
   Same dark ground as the navbar/footer, with the blur those two already use. */
body.fx-lb-open .modal-backdrop.show {
    background-color: #05070b;
    opacity: .9;
}
@supports (backdrop-filter: blur(6px)) {
    body.fx-lb-open .modal-backdrop.show {
        opacity: .8;
        backdrop-filter: blur(8px) saturate(.85);
    }
}

/* ---- affordance on the triggers ------------------------------------
   The legacy page gives no hint that these images open. */
body.fx-lb-on [data-bs-target="#fringe-modal"] {
    cursor: zoom-in;
}
body.fx-lb-on [data-bs-target="#fringe-modal"]:focus-visible {
    outline: 3px solid var(--md-accent, #0056b7);
    outline-offset: 3px;
}


/* ================================================================= *
 |  THE DIALOG
 * ================================================================= */

.fx-lb {
    /* the light-on-dark accent; --md-accent-lit only exists under .md-skin */
    --fx-accent: var(--md-accent-lit, #8fbfe8);
    --fx-btn: rgba(12, 15, 20, .62);
}

.fx-lb .fx-lb__dialog {
    max-width: none;
    width: auto;
    margin: 0;
    min-height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: clamp(1rem, 4vh, 3rem) clamp(.75rem, 2.5vw, 2.5rem);
    /* Bootstrap only closes on a click whose target IS the .modal element, and
       the dialog covers it completely — so without this, clicking the empty
       space beside the picture does nothing. Passing those clicks through
       restores "click outside to close"; the figure takes its own back. */
    pointer-events: none;
}

.fx-lb .fx-lb__figure {
    pointer-events: auto;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: fit-content;
    max-width: 100%;
    margin: 0;
}

.fx-lb .fx-lb__frame {
    position: relative;
    align-self: center;
    line-height: 0;
    max-width: 100%;
}

/* No width/height of our own beyond the caps: `auto` + max-* means the image
   renders at its natural size when it fits and shrinks to fit when it doesn't.
   It is therefore never upscaled and never cropped — the two things the legacy
   modal did to every image, because a flex column stretched it to the panel. */
.fx-lb .fx-lb__img {
    display: block;
    width: auto;
    height: auto;
    max-width: min(1600px, 90vw);
    max-height: min(1200px, 78vh);
    border-radius: 10px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, .55),
                0 0 0 1px rgba(255, 255, 255, .09);
    transition: opacity .18s ease;
}
/* While the next picture decodes the current one stays in place, dimmed, so the
   figure keeps its size and the caption under it doesn't reflow (js preloads
   before swapping). On the very first open there is nothing to hold the size —
   `is-cold` hides the figure outright rather than showing a collapsed frame. */
.fx-lb.is-loading .fx-lb__img { opacity: 0 }
.fx-lb.is-cold .fx-lb__figure { visibility: hidden }


/* ================================================================= *
 |  CAPTION  —  as wide as the picture, not as wide as a panel
 * ================================================================= */

.fx-lb .fx-lb__caption {
    /* The trick that makes the caption track the image: a definite width of 0
       contributes nothing to the figure's fit-content sizing (so long caption
       text can't widen the figure past the picture), and min-width:100% then
       fills whatever width the image actually resolved to. */
    width: 0;
    min-width: 100%;
    box-sizing: border-box;
    margin-top: .9rem;
    text-align: left;
}

.fx-lb .fx-lb__desc {
    margin: 0;
    max-width: 78ch;
    color: rgba(255, 255, 255, .9);
    font-family: var(--md-font, Helvetica, Arial, "Helvetica Neue", sans-serif);
    font-size: 1rem;
    line-height: 1.5;
}
.fx-lb .fx-lb__desc:empty { display: none }
.fx-lb .fx-lb__desc a { color: var(--fx-accent) }

/* Episode / timestamp / position — the three things that were previously
   <br/>-joined into the same centred grey line as the description. */
.fx-lb .fx-lb__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem .45rem;
    margin: .6rem 0 0;
}
.fx-lb .fx-lb__meta:empty { display: none }
.fx-lb .fx-lb__desc:empty + .fx-lb__meta { margin-top: 0 }

.fx-lb .fx-lb__chip {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .2rem .6rem;
    border: 1px solid rgba(255, 255, 255, .2);
    border-radius: 999px;
    font-family: var(--md-display, system-ui, sans-serif);
    font-size: .72rem;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--fx-accent);
    white-space: nowrap;
}
.fx-lb .fx-lb__chip svg {
    width: .85em;
    height: .85em;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: .8;
}
/* "3 / 4" is orientation, not content — it should not read as loudly. */
.fx-lb .fx-lb__chip--count {
    color: rgba(255, 255, 255, .5);
    border-color: rgba(255, 255, 255, .13);
    letter-spacing: .06em;
}


/* ================================================================= *
 |  CHROME  —  close + prev/next
 * ================================================================= */

.fx-lb .fx-lb__btn {
    position: absolute;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, .18);
    border-radius: 50%;
    background: var(--fx-btn);
    color: #fff;
    line-height: 0;
    transition: background-color .15s ease, border-color .15s ease, transform .15s ease;
}
@supports (backdrop-filter: blur(4px)) {
    .fx-lb .fx-lb__btn { backdrop-filter: blur(6px) }
}
.fx-lb .fx-lb__btn svg {
    width: 1.25rem;
    height: 1.25rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.fx-lb .fx-lb__btn:hover {
    background: rgba(22, 27, 34, .85);
    border-color: rgba(255, 255, 255, .38);
}
.fx-lb .fx-lb__btn:focus-visible {
    outline: 3px solid var(--fx-accent);
    outline-offset: 2px;
}
.fx-lb .fx-lb__btn[hidden] { display: none }

.fx-lb .fx-lb__close { top: .6rem; right: .6rem }
.fx-lb .fx-lb__nav   { top: 50%; margin-top: -1.375rem }
.fx-lb .fx-lb__nav--prev { left: .6rem }
.fx-lb .fx-lb__nav--next { right: .6rem }
.fx-lb .fx-lb__nav--prev:hover { transform: translateX(-2px) }
.fx-lb .fx-lb__nav--next:hover { transform: translateX(2px) }


/* ================================================================= *
 |  NARROW SCREENS
 * ================================================================= */

@media (max-width: 575.98px) {
    .fx-lb .fx-lb__dialog { padding: 1rem .5rem }
    .fx-lb .fx-lb__img {
        max-width: 96vw;
        max-height: 66vh;   /* leave room for the caption without scrolling */
        border-radius: 8px;
    }
    .fx-lb .fx-lb__desc { font-size: .94rem }
    /* Thumb-reachable rather than mid-image, and out of the way of the picture. */
    .fx-lb .fx-lb__btn { width: 2.5rem; height: 2.5rem }
    .fx-lb .fx-lb__nav { top: auto; bottom: .6rem; margin-top: 0 }
}

@media (prefers-reduced-motion: reduce) {
    .fx-lb .fx-lb__img,
    .fx-lb .fx-lb__btn { transition: none }
    .fx-lb .fx-lb__nav--prev:hover,
    .fx-lb .fx-lb__nav--next:hover { transform: none }
}
