/* SchoolCMS – Nav (template-parts/nav/)
   Burlington House School header bar, from `header` 11010:723 (home),
   `nav` 11010:1120 (inner) and the top of the mobile home mockup
   10001:2042. One fixed 105px bar (8px + the 87px logo + 10px), white
   ink and the round warm-grey menu disc: TRANSPARENT over the home
   banner, a solid PLUM BAND on every other page, and plum with a shadow
   once any page has scrolled 80px (`.scrolled`, menu.js) – brand/plum is
   the fill of `nav` 11010:1120 itself, not purple (corrected
   2026-09-14). Three regions:
   quick links (Top Links menu) left, the centred logo, utilities right.
   Below 992px only the logo and the disc show; the school switcher and
   the search trigger reappear in the open menu's top row (`.menu-open`),
   where the design draws them. The menu panel itself is the menu
   component (template-parts/menu/menu.css). */

/* The bar's height is intrinsic (8px + the 87px logo + 10px); this states
   it for the page shell, which has to start below the band on every page
   that wears one – default.css, banner.css. */
:root {
    --header-height: 105px;
}

.site-header {
    position:   fixed;
    top:        0;
    left:       0;
    right:      0;
    z-index:    100;
    color:      var(--color-white);
    background: transparent;
    transition: background var(--transition-base), box-shadow var(--transition-base);

    &.scrolled {
        background: var(--color-plum);
        box-shadow: var(--shadow-sm);
    }

    /* ── Retracts on scroll – the front page only, Rokeby's handoff ──
       nav.php marks the front page's bar `hideOnScroll`; menu.js adds
       `retracted` once the page has scrolled 80px – the same point
       `.scrolled` turns the inner bar plum, so this bar never shows plum
       for a moment before it goes – and takes it off only when the visitor
       is back within 80px of the top. Scrolling up does NOT bring it back:
       Rokeby's rule exactly (its nav.css, `.is-home.scrolled`), Charlie's
       call 2026-09-22 after two earlier cuts, one that slid the whole bar
       away and one that returned it on any upward scroll. Retracted, the
       band and everything in it go and the MENU DISC ALONE follows the
       visitor down: the quick links, the lockup, the school switcher and
       the magnifier fade out over --transition-base and are hidden at the
       fade's end, the plum ground and its shadow go with them, and the way
       back at the top is the same fade with the hide lifted first (each
       element's own `visibility 0s`) so there is a row to fade into. It
       stays on screen while the menu or the search strip is up, while the
       switcher is open or while anything in the bar has keyboard focus, and
       focus arriving in the bar brings it back. Inner pages keep the fixed
       band: the page shell starts below it there.

       NOTHING HERE TRANSLATES THE BAR: the full-screen menu panel is a fixed
       descendant of this header (menu.php sits inside it), and a translated
       ancestor would become its containing block – positioned against the
       bar's box, the panel would be 105px tall. The hidden pieces keep no
       pointer either (visibility does that), and the bar's box was already
       transparent to the pointer, so the page shows through the vanished
       band and takes the click. */
    &.retracted {
        background: transparent;
        box-shadow: none;

        .topLinks,
        .site-logo,
        .locationSwitch,
        .searchToggle {
            opacity:    0;
            visibility: hidden;
            transition: opacity var(--transition-base), visibility 0s var(--transition-base);
        }
    }

    /* The mobile search field takes the switcher's place in the row, so
       the pair it covers steps aside while it is up – `visibility`, so
       the row's layout does not move under it. Desktop's strip drops
       below the bar and covers nothing. */
    &.search-open {
        .locationSwitch,
        .searchToggle {
            visibility: hidden;

            @media (min-width: 992px) {
                visibility: visible;
            }
        }
    }

    /* Inner pages draw the bar as a solid plum BAND, not an overlay:
       `nav` 11010:1120 is a 105px plum frame at the very top of the
       inner template 10001:987 (0→105) with the banner photo behind it
       from y=80, so the photo shows from the band's bottom edge down.
       The home mockup 11010:723 gives its bar no ground – there it lies
       over the home banner's own plum. The 2026-09-08 build read the
       inner `header` frame 11010:1121 (which carries no fill) rather
       than its plum parent, recorded "no band" and made every page an
       overlay, which left white ink on a photograph where the file
       draws it on plum; corrected 2026-09-14. The banner still starts
       at y=0 and the band covers its first 105px – the photo one sees
       is the same 627px the file draws. */
    body:not(.home) & {
        background: var(--color-plum);
    }

    /* The open menu paints its own plum behind the bar. A scrolled bar
       keeps its plum – the same colour, so the panel slides in under it
       with no seam (Cathedral makes its bar a band of the panel for the
       same reason) – and only its shadow goes, for as long as the panel
       is on screen (`.menu-closing` spans the slide-out, menu.js). The
       bar, fixed edge to edge, also spans the strip the menu's scroll
       lock frees when the scrollbar goes – padding it back keeps the
       logo centred and the utilities where they were (--sbw, menu.js).
       That padding is open-state only: the scrollbar is back the moment
       the close starts. */
    .menu-open &,
    .menu-closing & {
        box-shadow: none;
    }

    .menu-open & {
        padding-right: var(--sbw, 0px);
    }

    /* ── The bar catches nothing but its own controls ──
       The bar is a fixed 105px box across the top of every page, and
       nothing in it is clickable except the three regions below – but
       the box itself was taking every pointer that landed in those
       105px. Two things sat underneath it: the home banner, and the
       open menu's Back row, which the design puts at 89px (menu.css),
       inside the bar's box. A tap on Back reached the bar instead of
       the button, so the mobile drill-down had no way back at all
       (reported 2026-09-15). The shell goes transparent to the pointer
       and the controls take it back; .siteMenu is listed because the
       whole panel hangs off this header and would inherit the none. */
    pointer-events: none;

    .topLinks,
    .site-logo,
    .locationSwitch,
    .searchToggle,
    .menuToggle,
    .headerSearch,
    .siteMenu {
        pointer-events: auto;
    }

    /* ── The bar – links | logo | utilities ──
       The menu overlay (template-parts/menu/, z-index 90) is a child of
       this header, so the bar and the search strip stack above it here */
    .headerBar {
        position:              relative;
        z-index:               91;
        display:               grid;
        grid-template-columns: 1fr auto 1fr;
        align-items:           start;
        /* 8px above the logo and 10px below it (`nav` 11010:1120's own
           padding) – without the 10px the plum band ends on the logo's
           last row of pixels and its wordmark reads as clipped */
        padding:               8px 15px 10px;

        @media (min-width: 992px) {
            padding: 8px 32px 10px;
        }
    }

    /* ── Quick links – "Arrange a visit | Contact us" (Top Links menu),
       desktop only; the menu panel repeats them at its foot ── */
    .topLinks {
        display:     none;
        grid-column: 1;
        padding-top: 34px;
        /* the retract's fade (above) – visibility 0s here so the links are
           there to fade back into; the state rule holds it for the fade out */
        transition:  opacity var(--transition-base), visibility 0s;

        @media (min-width: 992px) {
            display: block;
        }

        /* the design's 57px left margin against the bar's 32px – the
           logo stays on the page's centre line */
        @media (min-width: 1400px) {
            padding-left: 25px;
        }

        ul {
            display:     flex;
            align-items: center;
            gap:         36px;
            margin:      0;
            padding:     0;
            list-style:  none;
        }

        li {
            display:     flex;
            align-items: center;
            gap:         36px;
        }

        li + li::before {
            content: '|';
            font:    var(--text-12kx);
        }

        a {
            font:                      var(--text-12kx);
            text-transform:            uppercase;
            letter-spacing:            2.4px;
            color:                     var(--color-white);
            text-decoration:           underline;
            text-decoration-color:     transparent;
            transition:                text-decoration-color var(--transition-base);

            &:hover,
            &:focus-visible {
                text-decoration-color: currentColor;
            }
        }
    }

    /* ── Logo – the reversed stacked mark, 131×87 on every viewport ── */
    .site-logo {
        grid-column:     2;
        display:         block;
        text-decoration: none;
        opacity:         1;
        visibility:      visible;
        transition:      opacity var(--transition-slow), visibility 0s;

        .custom-logo {
            display:    block;
            width:      131px;
            height:     87px;
            object-fit: contain;
        }

        .site-title {
            font:  var(--text-20kl);
            color: var(--color-white);
        }

        /* The open mobile panel hides the logo (layer-3 is hidden in
           10001:645); the desktop overlay keeps it.

           It FADES back rather than snapping, and the hide hangs on
           `.menu-open` alone – not `.menu-closing`, which spans the
           slide-out – so the fade runs WITH the panel as it leaves and
           the logo is back by the time the panel has gone. Waiting for
           the panel first and appearing at the end is the snap that was
           reported (2026-09-15). Over the panel it is white ink on
           plum, which is exactly what the desktop state shows. Going
           the other way it leaves quickly, over --transition-base, with
           visibility held until the fade is done. */
        .menu-open & {
            opacity:    0;
            visibility: hidden;
            transition: opacity var(--transition-base), visibility 0s var(--transition-base);

            @media (min-width: 992px) {
                opacity:    1;
                visibility: visible;
                transition: none;
            }
        }
    }

    /* ── Utilities – school switcher, search, the menu disc ──
       Mobile: the row the open panel draws at its top (10001:645 –
       switcher at 21px, search at the right of it, disc 15px in), the
       disc alone while the menu is closed. Desktop: the bar's right
       group, 85px then 33px apart. */
    .headerUtils {
        position:    absolute;
        top:         15px;
        left:        21px;
        right:       15px;
        display:     flex;
        align-items: center;
        gap:         16px;

        @media (min-width: 992px) {
            position:     static;
            grid-column:  3;
            justify-self: end;
            gap:          33px;
            padding-top:  11px;
        }
    }

    /* Mobile: this pair belongs to the open PANEL's top row (10001:645),
       not to the closed bar, so it comes and goes with the panel rather
       than being switched on by `display` for the whole open state –
       which blinked it on over the banner before the panel had arrived
       and left it hanging over the logo coming back (2026-09-15).

       It FADES, on the panel's own clock: in over the last 200ms of the
       opening slide, so it lands with the panel, and straight out again
       when the close starts, well before the logo is back. Sliding it
       with the panel was the first attempt and read badly – the two
       items tracked across the bar and disappeared behind the menu disc
       (developer's call, 2026-09-15). `display: none` → `block` cannot
       transition, so the fade is a keyframe run, the dodge the drilled
       tiers use (menu.css); the delay is written as a plain time because
       --transition-* carries its easing. Desktop keeps the pair in the
       bar at all times and never animates it. */
    .locationSwitch,
    .searchToggle {
        display: none;

        .menu-open & {
            display:   block;
            animation: menuUtilsIn var(--transition-base) 0.2s both;

            @media (min-width: 992px) {
                animation: none;
            }
        }

        .menu-closing & {
            display:   block;
            animation: menuUtilsOut var(--transition-base) both;

            @media (min-width: 992px) {
                animation: none;
            }
        }

        @media (min-width: 992px) {
            display: block;
        }
    }

    .searchToggle {
        margin-left: auto;
        /* The open panel does not centre the magnifier on the disc: the
           file sets it at y=44 in a row that starts at 15 (10001:661),
           3px below the middle, where it lines up with the switcher's
           caps rather than with the disc. Desktop centres as before. */
        align-self:  flex-start;
        margin-top:  29px;

        @media (min-width: 992px) {
            margin-left: 0;
            align-self:  center;
            margin-top:  0;
        }
    }

    /* ── School switcher – "Choose a location" + chevron ── */
    .locationSwitch {
        /* the retract's fade (see .retracted above) – visibility 0s so the
           switcher is there to fade back into */
        transition: opacity var(--transition-base), visibility 0s;
        position: relative;

        @media (min-width: 992px) {
            margin-right: 52px;
        }
    }

    .locationToggle {
        display:        flex;
        align-items:    center;
        gap:            7px;
        padding:        0;
        border:         0;
        background:     none;
        font:           var(--text-12kx);
        text-transform: uppercase;
        letter-spacing: 2.2px;
        color:          var(--color-white);
        cursor:         pointer;
        white-space:    nowrap;

        @media (min-width: 992px) {
            letter-spacing: 2.4px;
        }

        /* The BOLD cut, because the file's own chevron is stroked: the
           vector in `group-127` 10001:658 (and its desktop twin) fills
           the mark in plum and strokes it white at 0.5, so what shows on
           the panel is the outline – about twice the ink of the hairline
           path the theme exported from it. The hairline read as a faint
           tick beside the caps; the bold cut lands on the drawn weight
           (corrected 2026-09-15 against the mobile tier 10001:645). */
        &::after {
            content:          '';
            flex-shrink:      0;
            /* 10 x 5.5, not the node's 9 x 5: the file's stroke sits ON
               the outline, so half of it falls outside that box and the
               mark reads about 9.5 wide. A mask has no overflow, so the
               box carries the whole mark. */
            width:            10px;
            height:           5.5px;
            background-color: currentColor;
            mask:             url(../../images/icons/chevron-down-bold.svg) center / contain no-repeat;
            -webkit-mask:     url(../../images/icons/chevron-down-bold.svg) center / contain no-repeat;
            transition:       transform var(--transition-base);
        }

        /* FLIPPED, not rotated – the house convention (CLAUDE.md § Reading
           the design). Both land on the same silhouette for a symmetrical
           chevron; the difference is the motion between them. */
        &[aria-expanded="true"]::after {
            transform: scaleY(-1);
        }
    }

    /* the dropdown – no open state is drawn: a plum panel hung off the
       label, the location names in body-2 white */
    .locationList {
        position:      absolute;
        top:           calc(100% + 12px);
        left:          0;
        z-index:       1;
        min-width:     100%;
        margin:        0;
        padding:       16px 20px;
        list-style:    none;
        background:    var(--color-plum);
        border-radius: var(--border-radius-sm);
        box-shadow:    var(--shadow-md);
        opacity:       0;
        visibility:    hidden;
        transform:     translateY(-8px);
        transition:    opacity var(--transition-base), transform var(--transition-base), visibility var(--transition-base);

        li + li {
            margin-top: 8px;
        }

        a {
            display:         block;
            font:            var(--text-16kl);
            color:           var(--color-white);
            text-decoration: none;
            white-space:     nowrap;
            transition:      color var(--transition-base);

            &:hover,
            &:focus-visible {
                color: var(--color-grey-600b);
            }
        }
    }

    .locationSwitch.open .locationList {
        opacity:    1;
        visibility: visible;
        transform:  none;
    }

    /* ── Search trigger – the 17×15 outline magnifier ── */
    .searchToggle {
        width:            17px;
        height:           15px;
        padding:          0;
        border:           0;
        background-color: var(--color-white);
        mask:             url(../../images/icons/search.svg) center / contain no-repeat;
        -webkit-mask:     url(../../images/icons/search.svg) center / contain no-repeat;
        cursor:           pointer;
        /* opacity for the hover below and for the retract's fade (the state
           rule above); visibility 0s so the way back from the retract is
           there to fade into */
        transition:       opacity var(--transition-base), visibility 0s;

        &:hover,
        &:focus-visible {
            opacity: 0.7;
        }
    }

    /* ── The menu disc – 66px warm-grey, frosted, burger → close ── */
    .menuToggle {
        display:         flex;
        align-items:     center;
        justify-content: center;
        flex-shrink:     0;
        margin-left:     auto;
        width:           66px;
        height:          66px;
        padding:         0;
        border:          0;
        border-radius:   50%;
        background:      var(--color-warm-grey);
        box-shadow:      var(--shadow-sm);
        backdrop-filter: blur(var(--blur-frosted));
        cursor:          pointer;
        transition:      background var(--transition-base);

        /* the open panel shows the search trigger beside the disc – one
           auto margin (the trigger's) then does the pushing */
        .menu-open &,
        .menu-closing & {
            margin-left: 0;
        }

        @media (min-width: 992px) {
            margin-left: 0;
        }

        /* No hover fill. The file draws this disc warm-grey in BOTH its
           states – `frame-21` in the bar and `group-126` 10001:676 in the
           open menu, both #c9c1c6 – and the white it took on hover was
           the 2026-09-08 build's own invention, which is what the open
           menu showed on a mouse: a white disc where the file draws a
           grey one (caught 2026-09-15). Keyboard focus still has to show,
           so that keeps a ring rather than a fill. */
        &:focus-visible {
            outline:        2px solid var(--color-white);
            outline-offset: 4px;
        }

        /* Three hairline bars rather than the burger.svg mask, because
           the close mark the file draws IS these bars: `group-126`
           10001:676 is a 14.14px X of two hairlines, which is exactly a
           pair of the burger's 20px lines turned 45°. So the button
           morphs instead of swapping one glyph for another: the outer
           pair turns ±45° while the middle one fades, one move over
           `--transition-base` with nothing staged behind it (it read as
           two steps at first – slide, then turn – and was halved to this
           on 2026-09-14). The 5px each outer bar closes up is what puts
           the arms on one centre line: a pair of 20px bars pivoting
           where they rest crosses off to one side, not in the middle,
           so the travel rides inside the turn rather than before it.
           Developer's call, 2026-09-14: the file draws the two states
           and never the move between them. burger.svg and close.svg stay
           for every other use. */
        .menuToggleIcon {
            display:  block;
            position: relative;
            width:    20px;
            height:   11px;
        }

        .menuToggleBar {
            position:   absolute;
            left:       0;
            width:      100%;
            height:     1px;
            background: var(--color-black);
            transition: top var(--transition-base),
                        rotate var(--transition-base),
                        opacity var(--transition-base);

            &:nth-child(1) {
                top: 0;
            }

            &:nth-child(2) {
                top: 5px;
            }

            &:nth-child(3) {
                top: 10px;
            }
        }

        .menu-open & .menuToggleBar {
            &:nth-child(1) {
                top:    5px;
                rotate: 45deg;
            }

            &:nth-child(2) {
                opacity: 0;
            }

            &:nth-child(3) {
                top:    5px;
                rotate: -45deg;
            }
        }
    }

    /* ── Search field (the design draws the trigger only) ──
       MOBILE: it takes the school switcher's place in the open panel's
       top row rather than dropping a band below the bar, which covered
       the menu's first items and read as clunky (developer's call,
       2026-09-15). It runs from the row's left edge to a 16px gap short
       of the disc, and its own magnifier lands near where the trigger
       was, so the trigger reads as having become the field. No ground of
       its own: the trigger only exists on mobile while the panel is up
       (see .locationSwitch / .searchToggle above), so the panel's plum
       is always behind it. DESKTOP: the strip drops from the bar's
       bottom edge as before, its own plum band across the page. */
    .headerSearch {
        position:   absolute;
        top:        15px;
        left:       21px;
        right:      97px;   /* the 66px disc + the bar's 15px + a 16px gap */
        height:     66px;
        z-index:    91;

        @media (min-width: 992px) {
            top:        100%;
            left:       0;
            right:      0;
            height:     auto;
            padding:    16px 32px;
            background: var(--color-plum);
            box-shadow: var(--shadow-sm);
        }

        .searchform {
            display:     flex;
            align-items: center;
            gap:         16px;
            height:      100%;
            max-width:   640px;
            margin:      0 auto;

            @media (min-width: 992px) {
                height: auto;
            }
        }

        .searchInput {
            flex:          1;
            min-width:     0;
            padding:       8px 0;
            border:        0;
            border-bottom: 1px solid var(--color-white-60);
            border-radius: 0;
            background:    none;
            font:          var(--text-18kl);
            color:         var(--color-white);
            outline:       none;

            &::placeholder {
                color: var(--color-white-60);
            }

            &:focus {
                border-bottom-color: var(--color-white);
            }
        }

        /* The SAME mark as the trigger, 17x15 of the file's own outline
           magnifier (10001:661) – the two sit in the same place on
           mobile, one replacing the other, and the form's Font Awesome
           glyph read as a second, heavier icon when the field opened
           (reported 2026-09-15). The glyph stays in the markup for the
           body search forms, which draw it inside a purple pill
           (content.css); here the mask carries the mark and the glyph is
           hidden. */
        .searchSubmit {
            width:            17px;
            height:           15px;
            padding:          0;
            border:           0;
            /* content.css rounds the body forms' pill (border-radius-sm,
               5px); on a 17×15 masked box that radius clips the corners
               of the paint and takes the magnifier's handle off with it
               (reported 2026-09-23). Square, like the trigger. */
            border-radius:    0;
            /* the trigger's own y on mobile (the file's 10001:661 at 44
               in a row starting at 15), so the two swap without the mark
               hopping 3px; desktop's strip centres it as before */
            align-self:       flex-start;
            margin-top:       29px;
            background-color: var(--color-white);
            mask:             url(../../images/icons/search.svg) center / contain no-repeat;
            -webkit-mask:     url(../../images/icons/search.svg) center / contain no-repeat;
            cursor:           pointer;
            transition:       opacity var(--transition-base);

            i {
                display: none;
            }

            &:hover,
            &:focus-visible {
                opacity: 0.7;
            }

            @media (min-width: 992px) {
                align-self: center;
                margin-top: 0;
            }
        }
    }
}

/* The morph is motion: without it the bars sit in their end states.
   Both selectors are written out in full – a nested state rule carries
   every ancestor class with it, so a short selector here loses to the
   rule it means to switch off. */
@media (prefers-reduced-motion: reduce) {
    .site-header.retracted .topLinks,
    .site-header.retracted .site-logo,
    .site-header.retracted .locationSwitch,
    .site-header.retracted .searchToggle,
    .site-header .menuToggle .menuToggleBar,
    .menu-open .site-header .menuToggle .menuToggleBar,
    .site-header .site-logo,
    .menu-open .site-header .site-logo {
        transition: none;
    }

    .menu-open .site-header .locationSwitch,
    .menu-open .site-header .searchToggle,
    .menu-closing .site-header .locationSwitch,
    .menu-closing .site-header .searchToggle {
        animation: none;
    }
}

/* The switcher and the magnifier arriving and leaving with the panel
   (see .locationSwitch / .searchToggle above). */
@keyframes menuUtilsIn {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes menuUtilsOut {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;
    }
}

/* ── Admin bar offset for the fixed header ─────────────────
   .admin-bar is only on <body> when the bar renders; 601px and 783px are
   WordPress's own admin-bar breakpoints, not the layout grid.

   Below 601px the admin bar is `position: absolute` (wp-includes/css/
   admin-bar.css), so it SCROLLS AWAY with the page – a constant 46px
   offset there leaves the bar floating with a strip of scrolling
   content above it the moment the page moves (reported 2026-09-15).
   menu.js tracks what is left of the admin bar into --admin-bar-offset
   and the base rule follows it down to 0. From 601px the admin bar is
   fixed again and its own height is the offset. */
.admin-bar {
    .site-header {
        top: var(--admin-bar-offset, 46px);
    }

    @media (min-width: 601px) {
        .site-header {
            top: 46px;
        }
    }

    @media (min-width: 783px) {
        .site-header {
            top: 32px;
        }
    }
}
