﻿/* ============================================================
   ZabDesk Shared Sticky Top Header Bar  (/css/zn_topbar.css)
   Loaded by inc_menu/zn_topbar.inc on every page that uses the
   shared header. Brand wordmark base styles (.zn-wordmark,
   .zn-wm-accent) live in /css/responsive.css.
   Palette: SZABIST blue #0A2F5A Â· accent gold #F5A623
   v20260912b: raised hamburger breakpoint from 1024px to 1200px,
               added mid-size (1201-1400px) font/gap adjustments
   v20260913u: added .zn-user-avatar (circular SVG) + margin-left:auto
               on .zn-user so the cluster is always right-aligned on
               desktop (not just on mobile ≤1320px breakpoint)
   v20260913w: user name + sign out are now SAME size (13px), SAME weight (600),
               SAME baseline (line-height:1 + align-self:center). Sign out pill
               now has a visible gold-tinted border so it doesn't look like a
               superscript next to the user name.
   v20260914b: added .zn-topbar .zn-wordmark { color: #fff } — "ZAB" was invisible
               on sub-app pages (topbar bg #0A2F5A matched wordmark color).
   ============================================================ */

/* pages with the new topbar: hide the legacy logo/user bar and strip the
   legacy #header banner decorations (height/background) so the box collapses
   around the new topbar â€” the topbar is INSIDE #header on role pages, so the
   header itself must stay rendered but invisible when empty */
body.zn-has-topbar .header-top-bar { display: none !important; }
body.zn-has-topbar #header {
    height: auto !important;
    min-height: 0 !important;
    background: none !important;
    padding: 0 !important;
    margin: 0 !important;
    border: 0 !important;
    box-shadow: none !important;
}

/* full-viewport-width header even when rendered inside the fixed-width
   legacy #wrapper / #header columns (index.asp topbar is already full-width) */
body.zn-has-topbar { overflow-x: clip; }
/* The vw-based bleed below is only needed when #wrapper is a fixed-width legacy
   column. On phones #wrapper is already full width, and 100vw includes the
   vertical scrollbar width — so the bleed overshoots by half the scrollbar
   (~5px each side), shifting the bar left and clipping content on the right
   edge. Scope it to tablet/desktop where the legacy columns actually exist. */
@media (min-width: 768px) {
    #wrapper .zn-topbar {
        margin-left: calc(-50vw + 50%);
        margin-right: calc(-50vw + 50%);
    }
}

/* ---------- sticky top header bar: brand lockup left, horizontal nav right ---------- */
.zn-topbar {
    position: sticky;
    top: 0;
    z-index: 1000;
    background: #0A2F5A;
    border-bottom: 3px solid #F5A623;
    box-shadow: 0 2px 10px rgba(10, 47, 90, .25);
}
.zn-topbar-inner {
    max-width: 1400px;
    margin: 0 auto;
    padding: 8px 16px;
    display: flex;
    align-items: center;
    gap: 16px;
    position: relative;
    flex-wrap: nowrap;
}

/* Wordmark on the dark topbar: force white so "ZAB" is visible.
   responsive.css base sets .zn-wordmark to #0A2F5A (invisible on navy bg).
   The .zn-hdr-c .zn-wordmark override only fires on pages with .zn-hdr-c,
   but sub-app pages use .zn-topbar without .zn-hdr-c, so "ZAB" was invisible. */
.zn-topbar .zn-wordmark { color: #ffffff; }

/* brand lockup: SZABIST crest + divider + ZABDESK wordmark */
.zn-lockup {
    display: flex;
    align-items: center;
    gap: 14px;
    flex: none;
}
/* The wordmark's own box must hold the whole word. The estate's legacy sheet
   declares `.Logo { width:10% }` (style.css) and the shared touch floor gives
   every <a> a 44px minimum, so the anchor rendered 44px wide while its text is
   111px - "DESK" painted outside its own link. !important because style.css
   loads after this sheet on the pages that carry it. */
.zn-lockup .Logo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: auto !important;
    margin-top: 0 !important;
    flex: 0 0 auto;
    padding: 0 6px;
    border-radius: 6px;
    text-decoration: none;
}
.zn-lockup-sep { width: 1px; height: 28px; background: rgba(255,255,255,.35); flex: none; }
.zn-lockup-univ {
    display: inline-flex;
    align-items: center;
    line-height: 0;
    background: #ffffff;
    border-radius: 8px;
    padding: 4px 8px;
}
.zn-lockup-univ img { height: 30px; width: auto; max-width: 160px; display: block; object-fit: contain; }
@media (min-width: 1600px) {
    .zn-lockup-univ img { height: 36px; max-width: 200px; }
}

/* hamburger toggle (mobile only) */
.zn-menu-btn {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 44px;
    height: 44px;
    padding: 10px;
    margin-left: auto;
    background: none;
    border: 1px solid rgba(255,255,255,.45);
    border-radius: 8px;
    cursor: pointer;
}
.zn-menu-btn:hover { border-color: #F5A623; }
.zn-menu-bar { display: block; width: 100%; height: 2px; background: #ffffff; border-radius: 2px; }

/* horizontal nav, right-aligned, 20px gaps, gold underline on hover */
.zn-topnav {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: flex-end;
    gap: 4px;
    margin-left: auto;
    min-width: 0;
}
.zn-topnav a {
    position: relative;
    padding: 6px 10px;
    color: #ffffff;
    text-decoration: none;
    font-size: 12.5px;
    font-weight: 700;
    white-space: nowrap;
    transition: color .15s ease;
}
.zn-topnav a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 3px;
    height: 2px;
    background: #F5A623;
    transform: scaleX(0);
    transform-origin: center;
    transition: transform .18s ease;
}
.zn-topnav a:hover,
.zn-topnav a:focus { color: #F5A623; }
.zn-topnav a:hover::after,
.zn-topnav a:focus::after { transform: scaleX(1); }

.zn-sysstatus {
    display: flex;
    align-items: center;
    gap: 7px;
    margin: 0;
    font-size: 11.5px;
    color: #E2E8F0;
    flex: none;
    white-space: nowrap;
}

/* signed-in cluster: avatar + user name + sign out (session-driven, no extra DB query)
   v20260913u: margin-left:auto pushes the whole cluster to the RIGHT on desktop,
   so it stays right-aligned regardless of whether the nav links (.zn-topnav) are
   present (they only render on Index.asp). Previously the cluster sat wherever
   the flexbox placed it, which was mid-bar on non-Index pages. */
.zn-user {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: none;
    white-space: nowrap;
    margin-left: auto;
}
.zn-user-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    overflow: hidden;
    background: #fff;
    border: 2px solid #F5A623;
    flex: none;
    box-shadow: 0 1px 3px rgba(0,0,0,.25);
}
.zn-user-avatar img { display: block; width: 100%; height: 100%; object-fit: cover; }
.zn-user-name {
    font-size: 13px;
    font-weight: 600;
    line-height: 1;
    color: #ffffff;
    max-width: 180px;
    overflow: hidden;
    text-overflow: ellipsis;
    align-self: center;
}
/* S371: the signed-in name is now a link to the portal home, like the wordmark.
   Scoped to a.zn-user-name on purpose - the Components sub-app header
   (inc_menu/zn_components_header.inc) reuses this class for a JS-filled <span>,
   and that span keeps its current box untouched.
   The link has to fill the estate's 44px anchor floor AND still ellipsise a long
   name, and those two pull apart: as a flex container the text becomes an
   anonymous flex item, which cannot carry text-overflow (measured: a 180px box
   that cut the name mid-word with no ellipsis). line-height on a block box does
   both - it centres the single line in the 44px target (box-sizing is border-box
   portal-wide) and keeps the ellipsis. */
a.zn-user-name {
    display: block;
    line-height: 44px;
    min-height: 44px;
    padding: 0 8px;
    border-radius: 6px;
    text-decoration: none;
    transition: color .15s ease;
}
/* S371b: the hover has to own its own INK.  The generic `a:hover` in
   zn_global.css sets color:var(--zn-color-primary, #0A2F5A) at specificity
   (0,1,1), which OUTRANKS the plain `.zn-user-name` class at (0,1,0); with no
   colour declared here the label took that navy on a lightened band - measured
   1.52:1 on TEST in the light scheme (dark and forced-colours survived only
   because that same token is itself themed).  This is the trap S87 logged for
   link-buttons.  (0,2,1) beats it.  No fill is declared: the estate already
   styles this element's hover at responsive.css:858
   (`.zn-hdr-c a.username-top:hover{color:#F5A623;background:none}`), gold on the
   bar's own navy measures 6.61:1 here, and a tinted band is what read as grey. */
a.zn-user-name:hover,
a.zn-user-name:focus {
    color: #F5A623;
    background: none;
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 3px;
}
.zn-signout {
    font-size: 13px;
    font-weight: 600;
    line-height: 1;
    color: #ffffff;
    background: rgba(245, 166, 35, .18);
    border: 1px solid rgba(245, 166, 35, .55);
    border-radius: 999px;
    padding: 6px 14px;
    text-decoration: none;
    align-self: center;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.zn-signout:hover,
.zn-signout:focus {
    background: #F5A623;
    border-color: #F5A623;
    color: #0A2F5A;
}

/* Component sub-app header (inc_menu/zn_components_header.inc) user cluster.
   Hidden by default; shown when the page marks the user as logged in by
   adding body.zn-tes-logged-in. Public nav + hamburger are hidden in that
   state so only the right-side user profile/name/sign-out remains. */
.zn-tes-user { display: none; }
body.zn-tes-logged-in .zn-tes-user { display: flex; }
body.zn-tes-logged-in .zn-topnav { display: none !important; }
body.zn-tes-logged-in .zn-menu-btn { display: none !important; }

/* legacy vertical / hamburger menus are replaced by .zn-topnav */
body.zn-has-topbar #menu,
body.zn-has-topbar #menu-res { display: none !important; }

.zn-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #9e9e9e;
    flex: none;
}
.zn-dot.ok       { background: #2e7d32; box-shadow: 0 0 0 3px rgba(46, 125, 50, .18); }
.zn-dot.err      { background: #c62828; box-shadow: 0 0 0 3px rgba(198, 40, 40, .15); }
.zn-dot.checking { background: #f9a825; }

/* header stacks on tablet/mobile; nav collapses into hamburger menu
   Breakpoint raised from 1024px to 1200px so the 8 nav items don't cramp
   on common laptop viewports (1100-1280px). */
@media (max-width: 1320px) {
    .zn-topbar-inner {
        flex-wrap: wrap;
        padding: 10px 12px;
        gap: 8px;
    }
    .zn-lockup { order: 1; }
    /* v20260913s: On narrow viewports the user cluster (.zn-user) goes to the
       RIGHT of the row, with the hamburger toggle next to it. The lockup
       (logo + ZABDESK wordmark) stays on the LEFT. */
    .zn-menu-btn { order: 3; display: flex; margin-left: 8px; }
    .zn-topbar .zn-user { order: 2; margin-left: auto; }
    .zn-topnav {
        order: 4;
        display: none;
        width: 100%;
        flex-direction: column;
        align-items: stretch;
        margin-left: 0;
        border-top: 1px solid #E2E8F0;
        padding-top: 6px;
    }
    .zn-topbar.zn-nav-open .zn-topnav { display: flex; }
    .zn-topnav a { padding: 12px 0; font-size: 14px; text-align: center; }
}

/* small screens: shrink lockup, dot-only status, compact user cluster */
@media (max-width: 480px) {
    .zn-wordmark { font-size: 18px; }
    .zn-lockup { gap: 8px; }
    .zn-lockup-univ { padding: 4px 8px; }
    .zn-lockup-univ img { height: 32px; max-width: 180px; }
    .zn-user-name, a.zn-user-name { display: none; }
}
@media (max-width: 380px) {
    .zn-lockup-sep { display: none; }
    .zn-topbar .zn-sysstatus #znDbText { display: none; }
}


/* Skip to main content link - hidden until focused */
.zn-skip-link {
    position: absolute;
    top: -100%;
    left: 50%;
    transform: translateX(-50%);
    background: #0A2F5A;
    color: #fff;
    padding: 12px 24px;
    border-radius: 4px;
    font-weight: 600;
    font-size: 14px;
    text-decoration: none;
    z-index: 10000;
    transition: top 0.2s ease;
}
.zn-skip-link:focus {
    top: 10px;
    outline: 2px solid #F5A623;
    outline-offset: 2px;
}

/* Focus visible for keyboard navigation */
.zn-topbar a:focus,
.zn-topbar button:focus,
.zn-topbar [tabindex]:focus {
    outline: 2px solid #F5A623;
    outline-offset: 2px;
}

/* Ensure focus visible for all interactive elements */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid #F5A623;
    outline-offset: 2px;
}

/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
    .zn-topbar a,
    .zn-topbar button,
    .zn-topbar .zn-menu-btn,
    .zn-topnav a,
    .zn-menu-btn .zn-menu-bar {
        transition: none !important;
        animation: none !important;
    }
}


/* v20260913e: Topbar is now visible on ALL pages that include zn_topbar.inc.
   The JS in zn_topbar.inc adds body.zn-has-topbar, which hides the legacy
   header bar and #menu. Previously the topbar itself was hidden via
   display:none and only shown on index.asp (zn-show-topbar class) — this
   left ALL logged-in pages (Student, Faculty, Coordinator, etc.) with NO
   top navigation at all, especially broken on mobile. Now the topbar is
   the single source of top navigation across the entire site. */
body.zn-has-topbar .zn-topbar,
body.zn-show-topbar .zn-topbar {
    display: block;
}

/* S241 (2026-10-02) - JavaScript-free duplicate-header guard.
   A legacy .header-top-bar that sits AFTER the shared .zn-topbar in the same
   container is always a duplicate: zn_topbar.inc already renders the logo,
   wordmark, avatar, user name and "Sign out". The rule at line 24 hides it, but
   only once JavaScript has added body.zn-has-topbar. This sibling rule needs no
   script at all, so the duplication cannot reappear if a partial re-adds the
   bar. It cannot hide a legitimate bar: it fires only when both elements are
   siblings AND the shared topbar comes first. */
.zn-topbar ~ .header-top-bar { display: none !important; }
/* Fallback: if the page includes the topbar HTML but JS hasn't run yet
   (slow connection, JS disabled), show the bar anyway — it's a critical
   navigation element, not optional decoration. */
.zn-topbar {
    display: block;
}
