/* ============================================================================
 * kaliber-site-nav.css — THE SITE NAVIGATION. ONE FILE, ONE DESIGN.
 * ============================================================================
 *
 * WHY THIS FILE EXISTS (owner report, 2026-08-08)
 * -----------------------------------------------
 * Owner: "on build a Pal page it's using a fallback navigation bar instead of
 * the real template we use ... flea market page has the nav bar bug too ...
 * I want the navigation bar to remain consistent across all pages on the site
 * and not changing like it does on these pages".
 *
 * He is describing a real, measurable defect, and it was WORSE than "two
 * navigations". Measured on disk 2026-08-08 the site had THREE site-nav
 * geometries, authored independently, none of them sharing a line of source:
 *
 *   geometry            pages   where the CSS lived
 *   ------------------  ------  --------------------------------------------
 *   .bottom-nav-container   2   inline <style> in Mainpage.php and vip.php
 *   .side-nav-container     4   inline <style> in Shop/Gamezone/hq/Community
 *   .kaliber-public-nav    65   inline <style> in kaliber_public_base.html
 *
 * (Counts: `grep -c '<nav class="...">' *.php` in the prototype docroot, and
 * `grep -rl 'extends "kaliber_public_base.html"' dreamcoin_web/templates/`.)
 *
 * So the navigation changed shape three ways depending on which page you were
 * on, and a visitor walking Shop -> Player Flea Market -> Build-A-Buddy crossed
 * all three in three clicks. `kaliber-prototype-shared.css` had already
 * reconciled the COLOURS across two of the three; that stopped the palette
 * drifting but left the geometry — the thing the owner actually sees change —
 * declared in seven separate files.
 *
 * THE FIX IS ONE DECLARATION, NOT A SEVENTH COPY. This file is the single
 * source of truth for site-navigation geometry AND palette. It is served out of
 * the Flask static tree, which BOTH halves of the site can reach: `/static/` is
 * ProxyPassed to Flask on the kalibergaming.com vhost
 * (httpd-kaliber-palbot.conf:479), verified 200 for `/static/css/*` on www. So
 * the PHP prototype pages can link this exact file too — see "REMAINING WORK"
 * at the bottom. Adding the markup to a page WITHOUT deleting that page's own
 * inline nav CSS is how this drifted in the first place; don't.
 *
 * WHICH GEOMETRY WON, AND WHY
 * ---------------------------
 * The fixed bottom BAR, i.e. `.bottom-nav-container`.
 *
 *   * It is what the HOME page uses. That is the site's front door and the page
 *     the owner calls "the real template we use".
 *   * The owner asked for a consistent "navigation BAR".
 *   * It costs the content NO horizontal space. The 65 Flask pages on this
 *     shell are content-dense — the Item Market, the Pal Market, the public
 *     wiki, seven casino games with fixed-width boards — and a 90-140px left
 *     rail would have required a global horizontal inset on all of them. A
 *     `position: fixed` bar needs only vertical reservation, and the shell
 *     ALREADY has a published contract for exactly that (`--site-shell-bottom`,
 *     documented at kaliber_public_base.html:178-221 and consumed by
 *     casino_common.css:20 for `--casino-shell-height`).
 *
 * COLOURS ARE THE KALIBER PALETTE, NOT THE PROTOTYPE'S BRONZE, and that is a
 * continuation of a decision already made and already documented in
 * `kaliber-prototype-shared.css`: the prototype's resting nav is on the RETIRED
 * tenant's bronze `rgba(207,168,88,…)` with a hot-pink `#ff69b4` / `#ff1493`
 * active state. Those are not Kaliber colours. Both halves move onto violet
 * #8b5cf6 / pink #ec4899 / teal #5eead4 over #100d20 / #171130 / #1d1636. The
 * values below are byte-identical to the ones that sheet already publishes, so
 * a page linking either file resolves the same nav.
 *
 * THE BACKGROUND GRADIENT IS NOT TOUCHED BY THIS FILE. Owner, same message:
 * "it uses a pink and blue gradient filter over the background and I really
 * like it and want that applied to all the website templates." That treatment
 * lives on `body.kaliber-public-shell` in kaliber_public_base.html:164-177 and
 * is deliberately left exactly where it is. This file styles a nav; it must
 * never paint a page background, or the two would fight.
 * ============================================================================ */

/* ── RESERVED SPACE ──────────────────────────────────────────────────────────
 * The bar is `position: fixed`, so without this every page's last element sits
 * UNDER it. `--site-shell-bottom` is the shell's existing contract for "this
 * many pixels at the bottom edge are already spoken for"; it was declared `0px`
 * because this shell genuinely had no fixed bottom chrome. It does now, so the
 * honest value is published here, next to the thing that occupies the space,
 * rather than left as a stale 0 somewhere else.
 *
 * 120px = 10px top padding + 44px icon box + 6px gap + ~16px label + 10px
 * bottom padding + 25px viewport offset, rounded up. Measured against the
 * prototype's own numbers rather than guessed. The decorative centre logo
 * overflows ABOVE the bar and is `pointer-events: none`, so it reserves
 * nothing.
 *
 * ERRS HIGH on purpose, same rule as the shell's `--site-shell-top` floor: a
 * few pixels of extra gap is cosmetic, content hidden under the nav is the bug.
 */
body.kaliber-public-shell {
    --site-shell-bottom: 120px;
}

@media (max-width: 768px) {
    body.kaliber-public-shell {
        --site-shell-bottom: 100px;
    }
}

/* The layout's own bottom padding has to grow with it. Written as a `calc` off
 * the variable rather than a second literal so the two can never disagree. */
body.kaliber-public-shell .kaliber-public-layout {
    padding-bottom: calc(var(--site-shell-bottom, 120px) + 22px);
}

/* ── THE BAR ─────────────────────────────────────────────────────────────────
 * Geometry restated from the prototype's own declaration (Mainpage.php:393-414)
 * so the two are the same component: same width ratio, same max-width, same
 * pill radius, same 25px lift, same blur.
 *
 * `animation: none` is NOT redundant even though no keyframes are named here:
 * the prototype pages declare `animation: dynamicBronzeGlass 10s ease infinite`
 * over a `background-size: 200%` gradient in their INLINE style, and a page that
 * links this file while still carrying that rule would keep animating the bronze
 * this file is replacing. Same reason `kaliber-prototype-shared.css` states it.
 */
.bottom-nav-container {
    position: fixed;
    bottom: 25px;
    left: 50%;
    transform: translateX(-50%);
    /* Above page content, below the shell's overlay rung (`--site-overlay-z`,
     * 1110) so a modal or a casino win banner still covers the nav rather than
     * being covered by it. */
    z-index: 50;

    width: 80%;
    max-width: 950px;
    margin: 0 auto;
    padding: 10px 25px;
    border-radius: 50px;
    border: 1px solid rgba(139, 92, 246, .34);
    border-bottom: none;

    background: linear-gradient(150deg, rgba(23, 17, 48, .94), rgba(29, 22, 54, .88) 52%, rgba(16, 13, 32, .94));
    background-size: auto;
    animation: none;
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow: 0 14px 34px rgba(8, 5, 20, .62);
}

.bottom-nav-container .nav-list {
    display: flex;
    justify-content: space-between;
    align-items: center;
    list-style: none;
    margin: 0;
    padding: 0;
}

.bottom-nav-container .nav-item {
    flex: 1;
    text-align: center;
    /* The prototype's centre-logo <li> carries these inline; stated here so the
     * markup in the Jinja partial does not have to. */
    min-width: 0;
}

/* ── THE DECORATIVE CENTRE MASCOT ────────────────────────────────────────────
 * Part of the nav's identity on all six prototype pages, so it is part of "the
 * navigation is the same everywhere".
 *
 * `pointer-events: none` IS A SECURITY-SHAPED DEFAULT, not styling. On the
 * prototype this element is promoted to a Portal Dashboard link by
 * kaliber-prototype-shared.js ONLY after a same-origin capability endpoint
 * confirms the session holds the dashboard role, via
 * `.is-dashboard-authorized`. Anything that renders this image must leave it
 * inert by default; see the matching rules in kaliber-prototype-shared.css.
 */
.bottom-nav-container .nav-center-logo {
    height: 120px;
    width: 100%;
    object-fit: contain;
    margin-top: -20px;
    margin-bottom: -10px;
    position: relative;
    z-index: 100;
    transform: scale(1.25);
    pointer-events: none;
}

/* ── LINKS ───────────────────────────────────────────────────────────────────
 * Inter, because that is what `body.kaliber-public-shell` sets. Naming it here
 * is what makes the PHP half and the Flask half read as one component rather
 * than two fonts — the prototype's own family resolves to Arial-by-fallback
 * (its `Eurostile` face is `local()`-only and matches on almost nobody).
 *
 * THE `.side-nav-container` HALF OF THESE TWO SELECTORS IS GONE (2026-08-08).
 * It was here to reach the four prototype pages that still rendered a left rail
 * — Shop.php, Gamezone.php, hq.php, Community.php — while they were mid-
 * convergence. All four now emit `.bottom-nav-container`, `grep -rn
 * 'side-nav-container' <docroot>/*.php` returns comment text only, and a
 * selector that matches nothing on any page is not free: it is what convinces
 * the next reader the rail is still a supported geometry.
 */
.bottom-nav-container .nav-link {
    display: flex;
    flex-direction: column;
    align-items: center;
    font-family: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
    font-size: 1rem;
    font-weight: bold;
    text-decoration: none;
    color: #c6c1d8;
    text-shadow: 0 1px 3px rgba(8, 5, 20, .85);
    opacity: .8;
    transition: all .3s ease;
}

.bottom-nav-container .nav-link:hover {
    opacity: 1;
}

.nav-icon-box {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 44px;
    height: 44px;
    margin-bottom: 6px;
    border: 1px solid rgba(139, 92, 246, .32);
    border-radius: 12px;
    background: linear-gradient(135deg, rgba(139, 92, 246, .20), rgba(23, 17, 48, .62) 52%, rgba(94, 234, 212, .14));
    background-size: auto;
    animation: none;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    box-shadow: 0 4px 12px rgba(8, 5, 20, .55);
    transition: all .3s ease;
}

.nav-link i {
    font-size: 1.3rem;
    color: rgba(198, 193, 216, .72);
    transition: transform .3s ease, color .3s ease;
}

.nav-link:hover .nav-icon-box {
    transform: translateY(-3px);
    border-color: rgba(139, 92, 246, .65);
    box-shadow: 0 6px 16px rgba(139, 92, 246, .38);
}

/* Resets, not just recolours — carried over verbatim in intent from
 * kaliber-prototype-shared.css. The prototype's page rules paint these two with
 * an animated magenta gradient CLIPPED TO THE GLYPHS
 * (`-webkit-background-clip: text` + `-webkit-text-fill-color: transparent`). A
 * bare `color` cannot show through a transparent fill, so the fill and the clip
 * have to be handed back before the colour means anything. */
.nav-link:hover i,
.nav-link:hover span {
    background: none;
    animation: none;
    -webkit-background-clip: border-box;
    background-clip: border-box;
    -webkit-text-fill-color: currentColor;
    color: #5eead4;
    filter: drop-shadow(0 0 8px rgba(94, 234, 212, .55));
}

/* ── CURRENT PAGE ────────────────────────────────────────────────────────────
 * TWO SELECTORS, ONE STATE, ON PURPOSE. The PHP prototype marks the current
 * destination with `class="nav-link active"` (a server-rendered class); the
 * Jinja shell derives it from `request.path` and marks it with
 * `aria-current="page"`, which is the accessible spelling and the one a screen
 * reader announces. Neither half is being made to adopt the other's convention
 * — a class is not an accessible name, and an ARIA attribute is not something
 * the PHP pages currently emit — so both are styled identically here. Do not
 * "simplify" this to one selector; that silently unstyles one half of the site.
 */
.nav-link.active .nav-icon-box,
.nav-link[aria-current="page"] .nav-icon-box {
    background: linear-gradient(135deg, rgba(236, 72, 153, .34), rgba(139, 92, 246, .30) 54%, rgba(236, 72, 153, .34));
    background-size: auto;
    animation: none;
    border-color: rgba(236, 72, 153, .62);
    box-shadow: 0 0 18px rgba(139, 92, 246, .48);
}

.nav-link.active i,
.nav-link.active span,
.nav-link[aria-current="page"] i,
.nav-link[aria-current="page"] span {
    background: none;
    animation: none;
    -webkit-background-clip: border-box;
    background-clip: border-box;
    -webkit-text-fill-color: currentColor;
    color: #ec4899;
    text-shadow: 0 0 10px rgba(236, 72, 153, .75);
    filter: none;
}

.nav-link.active,
.nav-link[aria-current="page"] {
    opacity: 1;
}

/* ── SMALL SCREENS ───────────────────────────────────────────────────────────
 * The prototype's own breakpoint and its own numbers (Mainpage.php:519-533), so
 * the bar collapses identically on both halves of the site. */
@media (max-width: 768px) {
    .bottom-nav-container {
        width: 95%;
        bottom: 15px;
        padding: 8px 12px;
    }

    .nav-link {
        font-size: .75rem;
    }

    .nav-link i {
        font-size: 1.1rem;
    }

    .nav-icon-box {
        width: 34px;
        height: 34px;
        border-radius: 8px;
    }

    .bottom-nav-container .nav-center-logo {
        height: 85px;
        margin-top: -15px;
        margin-bottom: -5px;
        transform: scale(1.2);
    }
}

/* Below ~430px seven destinations plus a mascot cannot all keep a label without
 * dropping under the shell's 13px legibility floor. The LABELS go, the icons
 * and the accessible names stay — `.nav-link` keeps its text in an
 * `aria-label`, so a screen reader is unaffected. Hiding the mascot here rather
 * than shrinking it further buys back ~14% of the row for the icons. */
@media (max-width: 430px) {
    .bottom-nav-container .nav-link span {
        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;
    }

    .bottom-nav-container .nav-item.is-mascot {
        display: none;
    }

    .nav-icon-box {
        margin-bottom: 0;
    }
}

/* ── PRINT ───────────────────────────────────────────────────────────────────
 * A fixed bar repeats on every printed page. The public wiki pages on this
 * shell are the ones people actually print. */
@media print {
    .bottom-nav-container {
        display: none;
    }
}

/* ============================================================================
 * THE ITEM LIST IS NOT IN THIS FILE, AND IT IS NOT IN ANY PAGE EITHER
 * ============================================================================
 * Second pass, same day. Converging the LOOK was only half the job. The
 * destination LIST was still hand-written in seven places — once in each of the
 * six PHP prototype pages and once in templates/_site_nav.html — and that is
 * what actually bit: when somebody noticed the two halves disagreed, they
 * reconciled the lists by DELETING "Leaderboards", the one item the PHP copies
 * had never been given. A live public page lost its only site-wide entry point
 * so that two hand-maintained copies would match.
 *
 * Owner, on seeing that: "Just make all pages use same template. apache or flask
 * idc they need to match and we can't just get rid of pages because they don't
 * match...."
 *
 * So there is now exactly ONE list, and it is a data file both renderers read:
 *
 *   dreamcoin_web/templates/_site_nav_items.html   THE LIST. Labels, hrefs,
 *                                                  icons, current-page match
 *                                                  rules, and the mascot's
 *                                                  position in the order.
 *   dreamcoin_web/templates/_site_nav.html         renders it for the 65 Jinja
 *                                                  pages (imports the list).
 *   <docroot>/kaliber-site-nav.php                 renders it for the 6 PHP
 *                                                  pages (reads the same file
 *                                                  off disk, json_decodes it).
 *   THIS FILE                                      renders neither. It is the
 *                                                  look, and only the look.
 *
 * Both renderers emit the same markup one item per line at the same indentation,
 * which is what lets "the nav is identical everywhere" be PROVEN rather than
 * asserted: fetch any two pages, cut the <nav> block out of each, strip the
 * current-page marker, hash. Measured across 23 live URLs spanning both
 * renderers on 2026-08-08 — /, /vip, /shop, /shop/kc-coins, /shop/items-pals,
 * /shop/kits, /game-zone, /casino, /hq, /hq/pals, /hq/live-map, /hq/armory/items,
 * /community, /community/bounties, /community/tournaments, /leaderboards,
 * /auction, /auction/pals, /intelligence/, /intelligence/pals, /tournaments,
 * /tournaments/archive, /tournaments/hall-of-fame — that hash had exactly ONE
 * distinct value.
 *
 * THE ROW IS SEVEN DESTINATIONS PLUS THE MASCOT AGAIN, which is the count the
 * <=430px rule below was originally written against, so nothing about the
 * responsive behaviour needed to change to restore Leaderboards.
 *
 * ============================================================================
 * THE VISUAL CONVERGENCE — READ BEFORE ADDING AN EIGHTH COPY OF THIS
 * ============================================================================
 * Finished 2026-08-08. This file is the ONLY place site-navigation geometry
 * and palette are declared, for ALL 71 pages:
 *
 *   * the 65 Jinja templates that extend `kaliber_public_base.html`, whose
 *     markup comes from `templates/_site_nav.html`;
 *   * all SIX PHP prototype pages — Mainpage.php, vip.php, Shop.php,
 *     Gamezone.php, hq.php, Community.php — each of which now carries
 *     `<link rel="stylesheet" href="/static/css/kaliber-site-nav.css?v=...">`
 *     as the LAST stylesheet in its <head>, and none of which carries a single
 *     nav rule of its own any more.
 *
 * WHAT THE SECOND PASS ACTUALLY REMOVED, so you can recognise a regression:
 *
 *   * Mainpage.php and vip.php: their inline `.bottom-nav-container` blocks and
 *     the five nav declarations inside their `@media (max-width: 768px)` rules,
 *     all of which this file already restated verbatim.
 *   * Shop.php, Gamezone.php, hq.php, Community.php: the entire LEFT RAIL —
 *     `#sideNavWrapper` / `.side-nav-wrapper` / `.side-nav-container`, the
 *     `.nav-toggle-btn` slide-out handle, and the `toggleSideNav()` controller —
 *     replaced by the same `<nav class="bottom-nav-container">` markup the other
 *     pages use. Four geometries became one; the site now has exactly one.
 *   * THE GUTTERS THE RAIL LEFT BEHIND, which is the half of this change that is
 *     easy to forget and immediately visible when you do: `.view-container`
 *     carried `padding-left: 140px` on Shop / Gamezone / Community, and hq.php
 *     carried FOUR separate insets (`.map-view-container` 150px, `#view-pal-info`
 *     160px, `.breeding-view-container` 140px, `#view-reference` 130px). All
 *     removed. A bar costs no horizontal space; leaving the inset parks every
 *     view 140px right of centre against nothing.
 *   * The bottom padding on those same scroll containers went 60px -> 150px
 *     (hq's map 28px -> 140px), because a `position: fixed` bar 25px off the
 *     bottom edge and ~115px tall covers ~140px that used to be content.
 *   * `kaliber-prototype-shared.css` lost its ~115-line nav colour block and its
 *     `.side-nav-wrapper` / `.nav-toggle-btn` rules. That block existed to
 *     reconcile six inline copies from one place; with the copies gone it was
 *     just a seventh declaration waiting to disagree with this one. The two
 *     `.nav-center-logo` DASHBOARD-GATE rules stayed there on purpose — see the
 *     comment in that file for why they must not move here.
 *
 * IF YOU CHANGE THE NAV, CHANGE THIS FILE. That is now literally true, and the
 * only way the owner's report stays fixed: "I want the navigation bar to remain
 * consistent across all pages on the site and not changing like it does on these
 * pages."
 *
 * THE MASCOT WAS CONVERTED, AND THE NUMBERS ARE MEASURED
 * ------------------------------------------------------
 * `/Dancing.gif` is 22,699,472 bytes (`Content-Length: 22699472` on the live
 * URL): 1920x1080, 176 frames, 5.87s, transparent background. It is served from
 * one HTTP cache entry across both halves of the site, but it was still 22.7 MB
 * on first paint of every page that shows this nav.
 *
 * `/Dancing.webp` is now served in front of it via <picture> on both halves —
 * same 176 frames, same 1920x1080 framing scaled to 480x270, same infinite loop,
 * same alpha — at 1,077,492 bytes. 4.7% of the original; 21,621,980 bytes saved;
 * 21.1x smaller. The GIF stays as the <picture> fallback and is not deleted.
 *
 * NOT CROPPED, DELIBERATELY: the opaque content is bbox 794x805 inside the
 * 1920x1080 canvas, so cropping to it would change the element's aspect ratio
 * from 16:9 to ~1:1 and, under this file's `object-fit: contain`, render the
 * mascot ~2.4x larger. That is a redesign of the nav, not a compression pass.
 *
 * NO ffmpeg ON THE BUILD BOX (`ffmpeg -version` -> not found; no ImageMagick
 * either), so the WebP was produced with Pillow 12.3.0. A muted looping <video>
 * (WebM/VP9 or AV1) would very likely beat 1 MB by another large factor and is
 * the obvious next step IF ffmpeg is ever installed — but it is a bigger change
 * than swapping an <img> source, because the dashboard capability gate in
 * kaliber-prototype-shared.js selects `.nav-center-logo` on an <img>.
 *
 * TWO CHEAPER VARIANTS WERE BUILT AND MEASURED, AND NEITHER WAS SHIPPED. They
 * are recorded here so nobody has to re-measure to have the conversation:
 *
 *   480x270  q60  176 frames (30fps)   1,077,492 bytes   <- SHIPPED
 *   480x270  q45  176 frames (30fps)   1,002,016 bytes   7% smaller, visibly
 *                                                        softer. Not worth it.
 *   480x270  q60   88 frames (15fps)     558,340 bytes   48% smaller, but it
 *                                                        halves the animation.
 *
 * Dropping the mascot to 15fps is a real 519 KB and a legitimate option, but it
 * changes how the thing MOVES, and the owner has opinions about how this site
 * looks. That is his call, not a compression detail — so the full-rate file is
 * what ships until he says otherwise.
 * ============================================================================ */
