/* Copyright (c) 2026 Bc. Jan Krejčí. All rights reserved.
   Proprietary and confidential. See LICENSE in the project root. */

/* ==========================================================================
   The photo viewer.

   The photograph is the only bright thing on the screen. Behind it the page
   does not vanish into black: it goes out of focus under dark smoked glass, so
   for the length of the flight the visitor sees the photograph lift off the
   page they were on, and at rest the page is still faintly there, the way a
   sheet of paper lifted off a desk still has the desk under it.

   Everything else — counter, close, arrows, caption — sits in translucent
   glass, arrives a beat after the photograph lands, one after another, and
   goes the moment the photograph is tapped, dragged or zoomed.

   Motion lives in chropyne-lightbox.js, on springs. Nothing here animates the
   photograph; this only says how things look.
   ========================================================================== */

/* The page underneath does not scroll while a photograph is open.

   On <body>, and only there. The Forge base stylesheet gives <body>
   `overflow-x: hidden` at full height, which works only because the body's
   overflow is handed on to the viewport while <html> has none of its own. Give
   <html> an `overflow` — the usual way to lock a page — and that hand-over
   stops: the body turns into a scroll box of its own, starting at the top, and
   the page jumped to its heading the moment a photograph was opened. */
html.ch-lb-open body {
    overflow: hidden;
}

/* The tiles hold still while the viewer is open, so the rectangle a
   photograph flies back into is the one it left, not a hovered one lifted by
   three pixels and zoomed by three percent. The hover returns, on its own
   transition, once the viewer has gone. */
html.ch-lb-open .ch-gallery__item,
html.ch-lb-open .ch-gallery__item img {
    transform: none !important;
    transition: none !important;
}

.ch-lb {
    position: fixed;
    inset: 0;
    z-index: 1000;
    color: #F4F3EE;
    -webkit-tap-highlight-color: transparent;
    font-family: 'Outfit', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

.ch-lb[hidden] { display: none; }

.ch-lb__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(12, 14, 15, .9);
    -webkit-backdrop-filter: blur(24px) saturate(1.35);
    backdrop-filter: blur(24px) saturate(1.35);
    opacity: 0;
}

/* The cost of a blur grows with its radius, and it is repainted on every frame
   of the flight. A phone gets a smaller one, which under 90 % dark reads the
   same, and keeps its frame rate. */
@media (pointer: coarse) {
    .ch-lb__backdrop {
        -webkit-backdrop-filter: blur(14px) saturate(1.3);
        backdrop-filter: blur(14px) saturate(1.3);
    }
}

/* --------------------------------------------------------------------------
   The photographs
   -------------------------------------------------------------------------- */

.ch-lb__stage {
    position: absolute;
    inset: 0;
    overflow: hidden;
    /* Every gesture is ours: the browser must not scroll, zoom the page or go
       back a page on a sideways swipe while a photograph is open. */
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
}

/* Three slides with a gap between them, so two photographs never touch while
   one is being swiped away — a strip of film, not a single long picture. */
.ch-lb__track {
    display: flex;
    gap: var(--lb-gap, 28px);
    width: 100%;
    height: 100%;
    will-change: transform;
}

.ch-lb__slide {
    position: relative;
    flex: 0 0 100%;
    height: 100%;
    display: grid;
    place-items: center;
    /* Room for the counter above and the caption below on a screen tall enough
       to spare it; a photograph is never shrunk for chrome on a phone. */
    padding: max(64px, env(safe-area-inset-top)) 24px max(88px, env(safe-area-inset-bottom));
    box-sizing: border-box;
}

/* No permanent will-change here: a layer promoted for good is rasterised once
   at its resting size, so zooming in showed a soft, stretched copy that then
   snapped sharp. The browser promotes the frame by itself while it moves. */
.ch-lb__frame {
    position: relative;
    width: 100%;
    height: 100%;
    transform-origin: center center;
}

.ch-lb__picture { display: contents; }

/* Pinned to all four sides of the frame rather than sized by a percentage:
   as a grid item with `height: 100%` it came out half the screen tall. */
.ch-lb__picture img {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    -webkit-user-drag: none;
    pointer-events: auto;
}

@media (max-width: 700px), (max-height: 500px) {
    .ch-lb__slide { padding: 0; }
}

.ch-lb.is-zoomed .ch-lb__stage { cursor: grab; }

/* The stand-in that flies between the tile and the screen. Its box is the
   whole photograph at rest; the script moves and scales it and crops it with
   clip-path, so the flight never touches layout. */
.ch-lb__ghost {
    position: fixed;
    z-index: 2;
    pointer-events: none;
    transform-origin: 50% 50%;
    will-change: transform, clip-path;
}

.ch-lb__ghost img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.ch-lb.is-flying .ch-lb__stage { visibility: hidden; }

/* --------------------------------------------------------------------------
   The controls
   -------------------------------------------------------------------------- */

/* Out of sight until the photograph has landed, then in one after another:
   the counter and close first, the arrows, the caption last. The stagger is
   short enough to read as one arrival and long enough to read as considered. */
.ch-lb__top,
.ch-lb__nav,
.ch-lb__caption {
    opacity: 0;
    transition:
        opacity 320ms cubic-bezier(.22, 1, .36, 1),
        transform 420ms cubic-bezier(.22, 1, .36, 1);
}

.ch-lb__top { transform: translate3d(0, -10px, 0); }
.ch-lb__caption { transform: translate3d(0, 10px, 0); }
.ch-lb__nav--prev { transform: translate3d(-10px, 0, 0); }
.ch-lb__nav--next { transform: translate3d(10px, 0, 0); }

.ch-lb.is-settled .ch-lb__top,
.ch-lb.is-settled .ch-lb__nav,
.ch-lb.is-settled .ch-lb__caption {
    opacity: 1;
    transform: none;
}

.ch-lb.is-settled .ch-lb__top { transition-delay: 0ms; }
.ch-lb.is-settled .ch-lb__nav { transition-delay: 60ms; }
.ch-lb.is-settled .ch-lb__caption { transition-delay: 120ms; }

/* Tap the photograph, drag it, or look closer, and everything but the
   photograph gets out of the way. */
.ch-lb.is-bare .ch-lb__top,
.ch-lb.is-bare .ch-lb__nav,
.ch-lb.is-bare .ch-lb__caption,
.ch-lb.is-dragging .ch-lb__top,
.ch-lb.is-dragging .ch-lb__nav,
.ch-lb.is-dragging .ch-lb__caption,
.ch-lb.is-zoomed .ch-lb__caption,
.ch-lb.is-zoomed .ch-lb__nav {
    opacity: 0;
    pointer-events: none;
    transition-delay: 0ms;
    transition-duration: 180ms;
}

.ch-lb__top {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: max(14px, env(safe-area-inset-top)) max(14px, env(safe-area-inset-right)) 14px max(18px, env(safe-area-inset-left));
    pointer-events: none;
}

.ch-lb__top > * { pointer-events: auto; }

.ch-lb__count,
.ch-lb__btn {
    background: rgba(255, 255, 255, .1);
    -webkit-backdrop-filter: blur(16px) saturate(1.4);
    backdrop-filter: blur(16px) saturate(1.4);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08);
}

.ch-lb__count {
    padding: 7px 14px;
    border-radius: 999px;
    font-size: .88rem;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    letter-spacing: .03em;
}

.ch-lb__btn {
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    color: #F4F3EE;
    cursor: pointer;
    transition: background 160ms ease, transform 200ms cubic-bezier(.22, 1, .36, 1), opacity 320ms ease;
}

.ch-lb__btn svg {
    width: 24px;
    height: 24px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.ch-lb__btn:hover:not(:disabled) { background: rgba(255, 255, 255, .2); }
.ch-lb__btn:active:not(:disabled) { transform: scale(.9); }

.ch-lb__btn:focus-visible {
    outline: 2px solid #C79A62;
    outline-offset: 3px;
}

.ch-lb__nav {
    position: absolute;
    z-index: 3;
    top: 50%;
    margin-top: -24px;
}

.ch-lb__nav--prev { left: max(20px, env(safe-area-inset-left)); }
.ch-lb__nav--next { right: max(20px, env(safe-area-inset-right)); }
.ch-lb.is-settled .ch-lb__nav:disabled { opacity: 0; pointer-events: none; }

/* A finger has the swipe; arrows on a phone would sit on the photograph. */
@media (hover: none) and (pointer: coarse) {
    .ch-lb__nav { display: none; }
}

.ch-lb__caption {
    position: absolute;
    z-index: 3;
    left: 0;
    right: 0;
    bottom: 0;
    margin: 0;
    max-width: none;
    padding: 36px max(24px, env(safe-area-inset-right)) max(22px, env(safe-area-inset-bottom)) max(24px, env(safe-area-inset-left));
    background: linear-gradient(to top, rgba(12, 14, 15, .55), transparent);
    color: rgba(244, 243, 238, .92);
    font-size: .98rem;
    line-height: 1.5;
    text-align: center;
    text-wrap: balance;
    pointer-events: none;
}

.ch-lb__section {
    display: block;
    margin-bottom: 6px;
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: #D4AE7C;
}

/* --------------------------------------------------------------------------
   The tiles that open it
   -------------------------------------------------------------------------- */

/* Pressed, a tile gives a little under the finger — the acknowledgement that
   something is about to happen, in the moment before it does. */
.ch-gallery__open {
    display: block;
    width: 100%;
    padding: 0;
    border: 0;
    background: none;
    cursor: zoom-in;
    border-radius: var(--ch-radius, 4px);
    overflow: hidden;
    -webkit-tap-highlight-color: transparent;
    transition: transform 220ms cubic-bezier(.22, 1, .36, 1);
}

.ch-gallery__open:active { transform: scale(.965); }

/* Block, so the button is exactly the photograph: an inline image leaves a few
   pixels of baseline under it, and the flight would land that much too tall. */
.ch-gallery__open picture,
.ch-gallery__open img {
    display: block;
    width: 100%;
}

.ch-gallery__open:focus-visible {
    outline: 2px solid var(--ch-wood-600, #9A6A35);
    outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
    .ch-lb__top,
    .ch-lb__nav,
    .ch-lb__caption,
    .ch-lb__btn,
    .ch-gallery__open { transition: none; }

    .ch-gallery__open:active { transform: none; }
}
