/*
 * ---------------------------------------------------------------------
 *  STRANICA
 * ---------------------------------------------------------------------
 *
 *  The page itself: the numbers every other file measures against, the
 *  three columns, the two side panels, the list of titles with its sort
 *  bar, the details panel, and what happens when the window is too
 *  narrow to hold all three.
 *
 *  The :root block at the top is where a box's size, the lighting and
 *  the perspective are set. Nothing below it hard-codes those; they read
 *  them, so one number changed here moves every box on the page.
 */


:root {
    /*
     * ---- BOX SIZE -------------------------------------------
     *
     * The only three numbers that decide the shape. Every face
     * size and position is worked out from them, so a tall thin
     * book or a shallow DVD case is a three-line change.
     *
     * width  = across the cover
     * height = top to bottom
     * depth  = spine to page edge
     */
    --width:  204px;
    --height: 254px;
    --depth:   54px;

    /*
     * Resizes the whole box without touching the proportions:
     * .5 for a thumbnail, 2 for a poster. The perspective, the
     * ground shadow and the corner radius all follow it, so a
     * scaled box looks identical, just bigger or smaller.
     */
    --box-scale: 1.8;

    /* the sizes everything below actually uses */
    --box-width:  calc(var(--width)  * var(--box-scale));
    --box-height: calc(var(--height) * var(--box-scale));
    --box-depth:  calc(var(--depth)  * var(--box-scale));

    /*
     * How hard the corners and edges are. Keep it small: the six
     * faces are flat planes, so a large radius opens up notches
     * where they meet. A few pixels reads as worn cardboard.
     */
    --corner: calc(4px * var(--box-scale));

    /* half sizes, used to push each face out from the centre */
    --half-width:  calc(var(--box-width)  / 2);
    --half-height: calc(var(--box-height) / 2);
    --half-depth:  calc(var(--box-depth)  / 2);

    /*
     * ---- PERSPECTIVE ----------------------------------------
     *
     * How far away the viewer is. Small numbers put the eye
     * close to the box, so the edges splay out hard and it
     * looks wide angle; large numbers flatten it towards an
     * architectural, almost isometric look.
     *
     * Below roughly 600px the distortion gets strong enough to
     * shear the cover. 1600px is a calm, lens-like default.
     *
     * It is multiplied by --box-scale so zooming moves the box
     * rather than moving the camera: the box gets bigger and
     * keeps the same shape, instead of lunging at you.
     */
    --perspective: 500px;

    /*
     * Where the viewer is standing, relative to the box.
     * 50% 50% is dead in front of the centre; lower the second
     * number to look at it from slightly above, as if it were
     * sitting on a shelf below eye level.
     */
    --perspective-origin: 50% 50%;

    /*
     * ---- LIGHTING -------------------------------------------
     *
     * A single light, given as a direction rather than a place.
     * x is right, y is DOWN (the CSS convention), z is towards
     * you, so the default sits up and to the left, in front of
     * the box. The script re-lights every face as it turns.
     */
    --light-x: -0.45;
    --light-y: -0.65;
    --light-z:  1;

    /* how lit a face still is once it has turned fully away */
    --ambient: .55;

    /* strength of the moving highlight on the covers */
    --gloss: .5;

    /* strength of the cardboard tooth, 0 turns it off */
    --grain: .35;

    /*
     * ---- ARTWORK --------------------------------------------
     *
     * One image per face, but do not edit these: the script
     * rewrites them every time a game is picked off the shelf,
     * using the paths in games.js. They start empty, and an
     * empty face is simply black: no drawn-on cardboard, no
     * paper edges, nothing pretending to be a scan that is not
     * there.
     */
    --art-front:  none;
    --art-back:   none;
    --art-spine:  none;
    --art-pages:  none;
    --art-top:    none;
    --art-bottom: none;

    /*
     * The back defaults to the front art, dimmed so it does not
     * read as a second cover. Set both of these to 1 once you
     * give --art-back a proper back-cover image.
     */
    --back-brightness: 1;
    --back-saturation: 1;
}

.zbirka * {
    box-sizing: border-box;
}

body {
    margin: 0;
}

/*
 * Everything the collection is lives inside this one element.
 *
 * On the page of its own that is the whole window; inside a page that
 * has other things on it — a WordPress page, a builder's section —
 * it is a box on that page and nothing outside it is touched. Putting
 * this on <body> instead, as it was, turned every page that loaded the
 * stylesheet into a three column grid, whatever else was on it.
 *
 * The height is a variable, and it defaults to filling whatever holds
 * it. A page that is nothing but the collection says 100vh itself; a
 * section 600 pixels tall gives it 600, and neither has to know about
 * the other.
 */
.zbirka {
    height: var(--zbirka-height, 100%);

    /*
     * If nothing above it has a height to be a percentage of, this is
     * what stops it collapsing to nothing. A box needs room to stand.
     */
    min-height: 320px;

    /* shelf | box | details */
    display: grid;
    grid-template-columns: 260px 1fr 300px;

    background:
        radial-gradient(circle at 50% 40%, #2c2c2c 0%, #0d0d0d 70%);

    font-family: Arial, sans-serif;
    color: white;

    overflow: hidden;

    /* stop text from being selected while dragging */
    user-select: none;
    -webkit-user-select: none;
}

/*
 * Both panels want the details on the right of the box. To put
 * them together down the left instead, give the details panel
 * `order: -1` and change the columns above to 260px 300px 1fr.
 */

/* ---- the two side panels share a look ---------------------- */

.panel {
    display: flex;
    flex-direction: column;

    min-height: 0;   /* lets the scrolling child actually scroll */

    background: rgba(0,0,0,.35);

    backdrop-filter: blur(6px);
}

.shelf {
    border-right: 1px solid rgba(255,255,255,.08);
}

.details {
    border-left: 1px solid rgba(255,255,255,.08);
}

.panel h2 {
    margin: 0;
    padding: 20px 20px 12px;

    font-size: 11px;
    font-weight: bold;
    letter-spacing: 2px;
    text-transform: uppercase;

    color: rgba(255,255,255,.4);
}

/* ---- the shelf --------------------------------------------- */

.search {
    margin: 0 16px 12px;
    padding: 9px 12px;

    background: rgba(255,255,255,.06);

    border: 1px solid rgba(255,255,255,.1);
    border-radius: 6px;

    color: white;
    font-family: inherit;
    font-size: 13px;

    /* the field is the one place typing is expected */
    user-select: text;
}

.search:focus {
    outline: none;

    border-color: rgba(255,255,255,.3);
    background: rgba(255,255,255,.09);
}

.search::placeholder {
    color: rgba(255,255,255,.3);
}

/*
 * Razvrstavanje. Redoslijed je svojstvo police, ne pretrage, pa
 * traka stoji ispod polja za pretragu i vrijedi i kad je popis
 * suzen. "Ručno" je redoslijed iz games.js, sve dok se naslov
 * ne povuče na novo mjesto.
 */
.sort {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;

    margin: 0 16px 6px;
}

/*
 * Druga traka nosi ono što vrijedi samo za odabranu skupinu:
 * smjer, i kod veličine po kojoj se mjeri. Odvojena je jer nije
 * izbor iste vrste kao gore, i nestaje kad nema što ponuditi
 * (ručni redoslijed nema ni smjer ni mjeru).
 */
.sort-options {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;

    margin: 0 16px 12px;
}

.sort-options:empty {
    display: none;
}

/*
 * Gumbi dijele slobodan prostor, ali se ne stišću ispod svog
 * natpisa: kad ih u redak stane manje nego što ih ima, red se
 * prelomi umjesto da se "Veličina" odsiječe na pola.
 */
.sort button,
.sort-options button {
    flex: 1 0 auto;

    white-space: nowrap;

    padding: 6px 4px;

    background: rgba(255,255,255,.04);

    border: 1px solid rgba(255,255,255,.08);
    border-radius: 5px;

    color: rgba(255,255,255,.45);

    font-family: inherit;
    font-size: 10px;
    letter-spacing: 1px;
    text-transform: uppercase;

    cursor: pointer;
}

.sort button:hover,
.sort-options button:hover {
    color: rgba(255,255,255,.8);
    background: rgba(255,255,255,.08);
}

.sort button[aria-pressed="true"],
.sort-options button[aria-pressed="true"] {
    background: rgba(216,196,138,.16);
    border-color: rgba(216,196,138,.4);
    color: #e8dcb8;
}

/* podskupine stoje niže od skupina, pa su sitnije i tiše */
.sort-options button {
    padding: 5px 4px;

    background: none;
    font-size: 9px;
}

/*
 * Smjer nije izbor između ponuđenih mogućnosti nego prekidač,
 * pa nema uključeno stanje: piše što je sada, a klik to obrne.
 * Širi je od ostalih jer nosi cijelu rečenicu, i prelomi se u
 * novi red kad mjere uz njega više ne stanu.
 */
.sort-options .direction {
    flex: 1 0 auto;

    min-width: 86px;

    border-color: rgba(255,255,255,.14);
    color: rgba(255,255,255,.6);
}

.list {
    flex: 1;

    overflow-y: auto;

    padding: 0 10px 20px;
}

.list button {
    display: block;

    width: 100%;

    margin-bottom: 2px;
    padding: 10px 12px;

    background: none;
    border: 0;
    border-radius: 6px;

    color: rgba(255,255,255,.75);

    font-family: inherit;
    font-size: 14px;
    text-align: left;

    cursor: pointer;
}

.list button:hover {
    background: rgba(255,255,255,.06);
    color: white;
}

.list button[aria-current="true"] {
    background: rgba(255,255,255,.12);
    color: white;

    /* the marker rail down the left of the selected title */
    box-shadow: inset 3px 0 0 #d8c48a;
}

/*
 * Sitni podatak desno od naslova. Godina dok je popis složen
 * ručno ili po abecedi, inače ono po čemu je složen: žanr ili
 * mjere kutije. Žanrovi znaju biti dugi, pa se skraćuju umjesto
 * da naslov guraju u drugi red.
 */
.list .year {
    float: right;

    max-width: 55%;

    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;

    opacity: .4;
    font-size: 12px;

    /* nudge onto the same baseline as the title */
    line-height: 20px;
}

/*
 * Premještanje. Naslov koji se vuče ostaje na mjestu blijed, a
 * crta pokazuje gdje će sjesti kad se pusti: bez nje se, dok
 * pokazivač lebdi između dva reda, ne vidi u koji od njih ide.
 */
.list button[draggable="true"] {
    cursor: grab;
}

.list button.dragging {
    opacity: .35;
    cursor: grabbing;
}

.list button.drop-before {
    box-shadow: inset 0 2px 0 #d8c48a;
}

.list button.drop-after {
    box-shadow: inset 0 -2px 0 #d8c48a;
}

/* odabrani naslov zadržava svoju traku i dok je meta ispuštanja */
.list button[aria-current="true"].drop-before {
    box-shadow: inset 3px 0 0 #d8c48a, inset 0 2px 0 #d8c48a;
}

.list button[aria-current="true"].drop-after {
    box-shadow: inset 3px 0 0 #d8c48a, inset 0 -2px 0 #d8c48a;
}

.empty {
    padding: 4px 12px;

    color: rgba(255,255,255,.3);
    font-size: 13px;
    font-style: italic;
}

/* ---- the details ------------------------------------------- */

.details-body {
    flex: 1;

    overflow-y: auto;

    padding: 0 20px 24px;
}

.details h1 {
    margin: 0 0 2px;

    font-size: 22px;
    line-height: 1.2;
}

.details .year-line {
    margin-bottom: 18px;

    color: rgba(255,255,255,.45);
    font-size: 13px;
}

.details .blurb {
    margin-bottom: 20px;

    color: rgba(255,255,255,.7);
    font-size: 13px;
    line-height: 1.6;
}

.details dl {
    margin: 0;

    display: grid;
    grid-template-columns: auto 1fr;
    gap: 8px 14px;

    font-size: 13px;
}

.details dt {
    color: rgba(255,255,255,.4);
    white-space: nowrap;
}

.details dd {
    margin: 0;
    color: rgba(255,255,255,.85);
}

/* a value that is honestly missing, rather than a real one */
.details .unmeasured {
    color: rgba(255,255,255,.35);
    font-style: italic;
}

.details .related {
    margin-top: 20px;
}

/*
 * Naslovnice u redu, kao kutije jedna do druge na polici — isti
 * obrazac za obje verzije: .details .related unutar prikazivača
 * ([zbirka]) i .zbirka-related-list, koji [igra-povezano] ispisuje
 * sam za sebe na Oxygen predlošku pojedine igre.
 */
.details .related h3,
.zbirka-related-list h3 {
    margin: 0 0 10px;

    color: rgba(255,255,255,.4);
    font-size: 13px;
    font-weight: normal;
}

.details .related ul,
.zbirka-related-list ul {
    margin: 0;
    padding: 0;

    list-style: none;

    display: flex;
    flex-wrap: wrap;
    gap: 14px;
}

.details .related a,
.zbirka-related-list a {
    display: flex;
    flex-direction: column;
    gap: 6px;

    width: 84px;

    color: rgba(255,255,255,.7);
    font-size: 12px;
    line-height: 1.3;
    text-decoration: none;
    text-align: center;
}

.details .related img,
.zbirka-related-list img {
    width: 84px;
    height: 110px;

    /*
     * contain, ne cover: kutija je gotovo uvijek viša nego šira, i
     * cilj je vidjeti cijelu naslovnicu, ne isječak koji ispuni
     * kvadrat.
     */
    object-fit: contain;
    border-radius: 3px;

    background: rgba(255,255,255,.05);
    box-shadow: 0 2px 6px rgba(0,0,0,.4);
}

.details .related a:hover,
.zbirka-related-list a:hover {
    color: #fff;
}

.details .related a:hover img,
.zbirka-related-list a:hover img {
    box-shadow: 0 2px 6px rgba(0,0,0,.4), 0 0 0 1px rgba(255,255,255,.3);
}

/* ---- the middle ------------------------------------------- */

.stage {
    position: relative;

    display: flex;
    align-items: center;
    justify-content: center;

    overflow: hidden;

    /*
     * The grab handle is the whole middle column, not just the
     * box. Zoomed out the box is a small target, and chasing it
     * with the mouse to start a drag is annoying. Keeping it off
     * the panels means the shelf still scrolls normally.
     */
    cursor: grab;

    /*
     * Every touch that lands here is ours: one finger turns the box,
     * two pinch it. Without this the browser claims them first and
     * scrolls or zooms the page instead, and the box never moves.
     */
    touch-action: none;
}

.stage:active {
    cursor: grabbing;
}

/* ---- the menu at the top, on a phone ----------------------- */

/*
 * Off on a wide screen: the shelf down the left already lists every
 * title, and does it better. The media query at the bottom is what
 * turns this on, and the shelf off.
 */
.topbar {
    display: none;

    padding: 10px 12px;

    background: rgba(0,0,0,.45);
    border-bottom: 1px solid rgba(255,255,255,.08);
}

.pick {
    width: 100%;

    padding: 12px;

    background: rgba(255,255,255,.06);

    border: 1px solid rgba(255,255,255,.14);
    border-radius: 7px;

    color: white;

    font-family: inherit;

    /*
     * 16px is the threshold below which iOS zooms the whole page in
     * on a field as it is focused, and never quite zooms back out.
     */
    font-size: 16px;
}

/*
 * The drop-down itself is drawn by the phone, not by us, and it
 * does not inherit the dark page. Stated so the list is not black
 * text on black.
 */
.pick option {
    background: #1a1a1a;
    color: white;
}


/* ---- one game on its own ----------------------------------- */

/*
 * Sama kutija, bez zbirke oko nje.
 *
 * Isti prikazivač i isti elementi — skripte ih traže poimence, pa ih
 * ovdje nema smisla izostaviti — samo maknuti s očiju: popis, ploča s
 * detaljima i prekidač pogleda. Ostaje kutija koja se okreće, otvara i
 * ima svoj stol.
 *
 * Polica i hrbati su namjerno maknuti: polica od jedne kutije nije
 * polica. Topbar, panel.shelf i .views se u solo pogledu uopće ne
 * renderiraju (zbirka_markup() u render.php), pa im ovdje ne treba ni
 * pravilo za skrivanje.
 */
.zbirka.solo {
    display: block;

    /* [igra] uvijek puni svog roditelja, bez obzira gdje je stavljen */
    width: 100% !important;
    height: 100% !important;
}

/* bez ploče s detaljima cijela je širina kutijina */
.zbirka.solo .stage {
    width: 100%;
    height: 100%;
}

.zbirka.solo .panel.details {
    display: none;
}

/* osim kad je izričito zatražena */
.zbirka.solo.with-details {
    display: grid;
    grid-template-columns: 1fr 300px;
}

.zbirka.solo.with-details .panel.details {
    display: flex;
}


/* ---- narrow windows ---------------------------------------- */

@media (max-width: 900px) {

    .zbirka {
        grid-template-columns: 200px 1fr;
        grid-template-rows: 1fr;
    }

    /* the details are the first thing to go */
    .details {
        display: none;
    }
}


/* ---- phones ------------------------------------------------ */

/*
 * One column: the menu, the box, and the details under it.
 *
 * The shelf panel goes entirely -- searching and sorting a list of
 * this size on a phone is more work than picking from a menu -- and
 * the details come back, because with the panels gone there is room
 * for them and nowhere else for them to be.
 */
@media (max-width: 700px) {

    .zbirka {
        /*
         * dvh, not vh: on a phone vh is the height with the address
         * bar hidden, so a 100vh page starts out taller than the
         * screen and the details sit below the fold until scrolled.
         */
        height: 100dvh;

        grid-template-columns: 1fr;
        grid-template-rows: auto 1fr auto;
    }

    /*
     * A smaller box to open on. The default above is sized for a
     * desktop stage; on a phone it fills the middle edge to edge with no room to
     * turn it, and a box that reaches the sides is also the most
     * expensive thing on the screen to redraw. The pinch still
     * reaches the same limits from here.
     */
    :root {
        --box-scale: 0.85;
    }

    .topbar {
        display: block;
    }

    /* replaced by the menu above */
    .shelf {
        display: none;
    }

    .details {
        display: flex;

        /*
         * A third of the screen, and it scrolls inside that: the box
         * is what the page is for, so a long blurb shortens the
         * reading area rather than the box.
         */
        max-height: 24dvh;

        border-left: 0;
        border-top: 1px solid rgba(255,255,255,.08);
    }

    /* the game's own title says the same thing, one line lower */
    .details h2 {
        display: none;
    }

    .details-body {
        padding: 16px 16px 20px;
    }

    .details h1 {
        font-size: 19px;
    }

    /* the switch and the hint move in off the edges */
    .views {
        top: 10px;
    }

    .instructions {
        bottom: 10px;

        padding: 0 12px;
        font-size: 11px;
    }
}
