/*
 * Yggdrasil sitewide theme — self-hosted fonts + app-shell chrome.
 *
 * SCOPE GUARD: global chrome (navbar/footer/typography) lives in the Tailwind
 * layer (tailwind.css / tailwind.src.css); component behaviour styling lives in
 * ygg-ui.css. This file keeps only:
 *   1. @font-face for the self-hosted IBM Plex families (GDPR: no CDN fonts).
 *   2. The fixed footer + 64px icon-rail app-shell layout.
 *   3. The desktop-only gate shown at phone widths.
 * It MUST NOT restyle annotation viewers — viewer pages inherit this file.
 *
 * Bootstrap is gone as of the 2.0 rebuild; the chromatic overrides and the
 * Bootstrap dark remap that used to live here went with it.
 *
 * Tokens live in tokens.css (loaded first).
 */

/* ---- Self-hosted webfonts (IBM Plex Sans + Mono) ----------------------- */
@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal; font-weight: 400; font-display: swap;
    src: url('../fonts/ibm-plex-sans-latin-400-normal.woff2') format('woff2');
}
@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal; font-weight: 500; font-display: swap;
    src: url('../fonts/ibm-plex-sans-latin-500-normal.woff2') format('woff2');
}
@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal; font-weight: 600; font-display: swap;
    src: url('../fonts/ibm-plex-sans-latin-600-normal.woff2') format('woff2');
}
@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal; font-weight: 700; font-display: swap;
    src: url('../fonts/ibm-plex-sans-latin-700-normal.woff2') format('woff2');
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal; font-weight: 400; font-display: swap;
    src: url('../fonts/ibm-plex-mono-latin-400-normal.woff2') format('woff2');
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal; font-weight: 500; font-display: swap;
    src: url('../fonts/ibm-plex-mono-latin-500-normal.woff2') format('woff2');
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal; font-weight: 600; font-display: swap;
    src: url('../fonts/ibm-plex-mono-latin-600-normal.woff2') format('woff2');
}

/* ==========================================================================
 * Yggdrasil 2.0 chrome — sticky footer, full-width nav, branding assets.
 * Plain CSS (loaded after tailwind.css, so these override compiled utilities).
 * ======================================================================== */

/* Fixed footer: pinned to the viewport bottom at all times; body reserves room
 * so content is never hidden behind it. (Landing blanks the footer + is its own
 * 100vh overflow-hidden viewport, so it's unaffected.) */
:root {
    --ygg-footer-h: 3rem;
    --ygg-maintenance-h: 2rem;
}
body { min-height: 100vh; padding-bottom: var(--ygg-footer-h); }
.maintenance-banner {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 2100;
    height: var(--ygg-maintenance-h);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 1rem;
    overflow: hidden;
    border-bottom: 1px solid #dfbd35;
    background: #f5dc69;
    color: #493900;
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1;
}
.maintenance-banner span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
body.has-maintenance-banner { padding-top: var(--ygg-maintenance-h); }
body.has-maintenance-banner .ygg-nav,
body.has-maintenance-banner .ygg-topbar { top: var(--ygg-maintenance-h); }
body.has-maintenance-banner .ygg-toast-container {
    top: calc(var(--ygg-maintenance-h) + 1rem);
}
body.has-maintenance-banner main.landing {
    min-height: calc(100vh - var(--ygg-maintenance-h));
}
:root[data-theme="dark"] .maintenance-banner {
    border-bottom-color: #b79520;
    background: #d8bb43;
    color: #211a00;
}
.ygg-footer {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 40;
}

/* Full-width navbar: brand flush-left, profile flush-right (drop max-width). */
.ygg-nav-inner { max-width: none; }
.ygg-topbar { z-index: 100; }

/* Tree logo beside the wordmark in the navbar. */
.ygg-brand-logo { height: 1.6rem; width: auto; display: block; }

/* Footer: AImageLab credit logo. */
.footer-aimagelab { height: 1.45rem; width: auto; display: inline-block; }

/* ==========================================================================
 * App shell — 64px fixed icon rail (working pages opt in via body.has-rail).
 * Additive layout: the rail is position:fixed and the body reserves 64px on
 * the left, so the existing document flow (main + fixed footer) is untouched
 * except for the horizontal offset. Landing/auth pages don't set the class.
 * ======================================================================== */
:root { --ygg-rail-w: 64px; }
.ygg-rail {
    position: fixed;
    top: 0;
    left: 0;
    width: var(--ygg-rail-w);
    height: 100vh;
    z-index: 45;
}
body.has-maintenance-banner .ygg-rail {
    top: var(--ygg-maintenance-h);
    height: calc(100vh - var(--ygg-maintenance-h));
}
body.has-rail { padding-left: var(--ygg-rail-w); }
body.has-rail .ygg-footer { left: var(--ygg-rail-w); }
/* Phone-only drawer controls: invisible at every desktop and tablet width. */
.ygg-rail-toggle,
.ygg-rail-backdrop { display: none; }
@media (max-width: 640px) {
    /* Collapse the rail off-canvas on very small screens; content reclaims width.
       The topbar's hamburger ([data-mobile-toggle], nav.js) sets body.rail-open,
       which slides it back in as a labelled drawer over a backdrop. */
    body.has-rail { padding-left: 0; }
    body.has-rail .ygg-rail {
        transform: translateX(-100%);
        transition: transform .2s;
        /* Above the sticky topbar (100) so the drawer covers it, below modals. */
        z-index: 1010;
    }
    body.has-rail.rail-open .ygg-rail {
        transform: none;
        width: min(16rem, 80vw);
        align-items: stretch;
        padding-left: 0.75rem;
        padding-right: 0.75rem;
        box-shadow: var(--ygg-shadow-pop);
    }
    /* The rail's items are icon-only with the name in `title`; in the drawer
       there is room, so print it -- no hover on a phone to reveal a tooltip. */
    body.has-rail.rail-open .ygg-rail-item {
        width: auto;
        justify-content: flex-start;
        gap: 0.75rem;
        padding: 0 0.75rem;
    }
    body.has-rail.rail-open .ygg-rail-item::after {
        content: attr(title);
        font-size: 0.875rem;
    }
    /* The logo is the way home; in the drawer it says so, like the items do. */
    body.has-rail.rail-open .ygg-rail-logo {
        width: auto;
        height: 2.25rem;
        justify-content: flex-start;
        gap: 0.75rem;
        padding: 0 0.75rem 0 0.375rem;
        background: transparent;
        color: var(--ygg-text-muted);
        text-decoration: none;
    }
    body.has-rail.rail-open .ygg-rail-logo img {
        box-sizing: content-box;
        padding: 6px;
        border-radius: var(--ygg-radius-lg);
        background: var(--ygg-accent-soft);
    }
    body.has-rail.rail-open .ygg-rail-logo::after {
        content: "Home";
        font-size: 0.875rem;
    }
    body.has-rail .ygg-rail-toggle { display: flex; flex-shrink: 0; }
    body.has-rail.rail-open .ygg-rail-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 1005;
        background: rgba(0, 0, 0, 0.4);
    }
    body.has-rail.rail-open { overflow: hidden; }
    body.has-rail .ygg-footer { left: 0; }

    /* A fixed footer eats a tenth of a phone screen on every page; let it
       scroll away with the content instead. */
    .ygg-footer { position: static; }
    body { padding-bottom: 0; }
    .ygg-topbar { padding-left: 0.75rem; padding-right: 0.75rem; gap: 0.5rem; }
}

/* Phone touch on the viewers (runtime/touch.js): one finger scrolls the page,
   two work the view. Cornerstone stamps `touch-action: none` inline on every
   viewport element, which keeps the browser from scrolling at all from there --
   and on a phone the viewers are most of the page. Letting the browser pan from
   them is half of it; the script sends two-finger gestures to the view. */
@media (max-width: 640px) {
    [data-viewport-uid],
    [data-touch-view] { touch-action: pan-x pan-y !important; }
    /* Except in a drive container, where one finger rotates or moves the view
       (maxillo IOS and CBCT): there the page must not scroll under the finger. */
    [data-touch-drive] [data-viewport-uid] { touch-action: none !important; }
}

/* Device-scoped visibility helpers. Phones get the demo only
   (common/mobile.py): `.ygg-desktop-only` hides what a phone must not offer --
   sign-in, register, write controls the read-only guest cannot use -- even when
   the server did not recognise the device. `.ygg-mobile-only` is the converse. */
.ygg-mobile-only { display: none; }
@media (max-width: 640px) {
    .ygg-desktop-only { display: none !important; }
    .ygg-mobile-only { display: revert; }
}

/* ==========================================================================
 * Desktop-only gate — for a real signed-in user on a phone.
 *
 * Phones get the public demo only (common/mobile.py). Public pages and the
 * demo guest have a phone layout, so base.html leaves the gate out for them
 * (`mobile_ok`). A signed-in user's working pages -- upload, the editors, the
 * admin dashboards -- were never laid out for a 390px column, so there base.html
 * still carries this interstitial, invisible at desktop widths and painted over
 * everything here. The media query decides *when* it shows; colours are all
 * --ygg-* tokens, so it follows the data-theme stamp with no dark rules of its own.
 *
 * The landscape clause catches a rotated phone (~850px wide, so a bare
 * max-width would let it through); max-height keeps laptops out.
 * ======================================================================== */
.ygg-desktop-gate { display: none; }

@media (max-width: 640px), (orientation: landscape) and (max-height: 480px) {
    /* Lock scrolling only while the gate is actually on the page. It used to be
       unconditional, which was harmless while every page carried the gate; now
       the demo pages have none, and a bare `html, body` here froze them at one
       screen. Without `:has()` the page merely scrolls behind the fixed gate. */
    html:has(.ygg-desktop-gate),
    html:has(.ygg-desktop-gate) body { overflow: hidden; }
    .ygg-desktop-gate {
        display: flex;
        position: fixed;
        inset: 0;
        /* Above the maintenance banner (2100), toasts (2000) and modals (1050). */
        z-index: 3000;
        align-items: center;
        justify-content: center;
        padding: 1.5rem;
        background: var(--ygg-surface-alt);
    }
    .ygg-desktop-gate__card {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 0.75rem;
        max-width: 22rem;
        padding: 2rem 1.5rem 1.75rem;
        border: 1px solid var(--ygg-border);
        border-radius: var(--ygg-radius-lg);
        background: var(--ygg-surface);
        box-shadow: var(--ygg-shadow-card-light);
        text-align: center;
    }
    .ygg-desktop-gate__logo {
        width: 4.5rem;
        height: auto;
        animation: ygg-gate-float 3.2s ease-in-out infinite;
    }
    .ygg-desktop-gate__title {
        margin-top: 0.5rem;
        font-size: 1.125rem;
        line-height: 1.4;
    }
    .ygg-desktop-gate__text {
        margin: 0;
        color: var(--ygg-text-muted);
        font-size: 0.875rem;
        line-height: 1.55;
    }
}

@keyframes ygg-gate-float {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-6px); }
}
@media (prefers-reduced-motion: reduce) {
    .ygg-desktop-gate__logo { animation: none; }
}
