// =============================================================================
// Aumni AMS — application shell
//
// A narrow dark rail on the left, a short light topbar over the content, and a
// gray canvas the cards sit on. The rail carries the brand and the current
// location; the topbar carries search and identity; the canvas carries the work.
//
// The chrome is deliberately thin. Every pixel spent on a rail or a bar is a
// pixel a table does not get, and this is software people keep open all day.
// =============================================================================

// -----------------------------------------------------------------------------
// 1. Sidebar
//
// `offcanvas-lg` still does the responsive work — a drawer below lg, a fixed
// rail above it — so there is no custom JavaScript here.
//
// Bootstrap forces `background-color: transparent !important` on both
// `.offcanvas-lg` and `.offcanvas-body` at the breakpoint. Rather than fight
// that with a counter-!important, the dark surface is painted on an inner
// element, which is unaffected at every breakpoint.
// -----------------------------------------------------------------------------

.ams-sidebar {
    width: var(--ams-sidebar-width);
    display: flex;
    flex-direction: column;

    @include media-breakpoint-up(lg) {
        bottom: 0;
        flex: 0 0 var(--ams-sidebar-width);
        height: 100vh;
        left: 0;
        position: fixed;
        top: 0;
        z-index: $zindex-fixed;
    }

    // Bootstrap collapses the body to `flex-grow: 0` above the breakpoint; the
    // rail needs it to fill the full height so the footer can sit at the bottom.
    .offcanvas-body {
        display: flex;
        flex: 1 1 auto;
        max-height: calc(100vh - var(--bs-offcanvas-padding-y, 1rem) * 2);
        min-height: 0;
        padding: 0;
    }

    @include media-breakpoint-up(lg) {
        .offcanvas-body {
            max-height: 100vh;
        }
    }

    .offcanvas-header {
        background-color: $ams-sidebar-bg;
        border-bottom: 1px solid $ams-sidebar-border;
        color: $white;
        padding: 0.75rem 0.875rem;

        .btn-close {
            filter: invert(1) grayscale(1);
            opacity: 0.6;
        }
    }
}

.ams-sidebar__inner {
    background-color: $ams-sidebar-bg;
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    width: 100%;
}

// Brand lockup. Its height matches the topbar exactly, so the rail's dividing
// rule and the topbar's meet in a single unbroken line across the viewport —
// which is the detail that makes two panels read as one frame.
.ams-sidebar__brand {
    align-items: center;
    border-bottom: 1px solid $ams-sidebar-border;
    display: flex;
    flex-shrink: 0;
    gap: 0.625rem;
    height: var(--ams-topbar-height);
    padding: 0 0.875rem;
    text-decoration: none;

    &:hover {
        text-decoration: none;
    }
}

// Flat, not gradient. A gradient on a 26px mark is decoration nobody can
// resolve at that size, and it is the first thing that makes an interface look
// like a template.
.ams-sidebar__mark {
    align-items: center;
    background-color: $primary;
    border-radius: 0.375rem;
    color: $white;
    display: inline-flex;
    flex-shrink: 0;
    font-size: 0.8125rem;
    height: 1.625rem;
    justify-content: center;
    width: 1.625rem;
}

// An uploaded logo replaces the icon tile — own shape, own colours, so it
// gets a white plate under it rather than sitting on the teal fill meant
// for a single-colour glyph.
.ams-sidebar__mark--logo {
    background-color: $white;
    padding: 0.1875rem;

    img {
        height: 100%;
        object-fit: contain;
        width: 100%;
    }
}

.ams-sidebar__wordmark {
    color: $white;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.25;
}

.ams-sidebar__tagline {
    color: #6b7686;
    font-size: 0.6875rem;
    line-height: 1.3;
}

.ams-sidebar__nav {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    max-height: 100%;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 0.75rem 0.625rem 1.25rem;
}

// A quiet closing rule below the last group.
//
// Below Phase 3 the rail has only four or five items, which leaves most of its
// height as plain canvas before the footer. Rather than disguise that with
// fake content, this line gives the nav block a definite bottom edge — the
// space below it then reads as deliberate margin around a short list, not as
// a menu that stopped loading partway down.
.ams-nav__end {
    border-top: 1px solid $ams-sidebar-border;
    flex-shrink: 0;
    margin: 0.5rem 0.625rem 0;
}

.ams-sidebar__footer {
    border-top: 1px solid $ams-sidebar-border;
    flex-shrink: 0;
    padding: 0.75rem 0.875rem;
}

.ams-sidebar__meta {
    color: #5b6472;
    font-size: 0.6875rem;
    line-height: 1.5;

    strong {
        color: #8b95a5;
        display: block;
        font-weight: 500;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}

// -----------------------------------------------------------------------------
// 2. Rail navigation
//
// The active item is a solid accent pill rather than a border or a tint: at a
// glance across a narrow rail, fill is the only treatment that survives
// peripheral vision.
// -----------------------------------------------------------------------------

.ams-nav {
    &__section {
        color: #5b6472;
        font-size: 0.6875rem;
        font-weight: 600;
        letter-spacing: 0.05em;
        padding: 1rem 0.75rem 0.4375rem;
        text-transform: uppercase;

        &:first-child {
            padding-top: 0.375rem;
        }
    }

    &__link {
        align-items: center;
        border-radius: 0.375rem;
        color: #a6afbd;
        display: flex;
        font-size: 0.8125rem;
        font-weight: 500;
        gap: 0.625rem;
        margin-bottom: 0.125rem;
        padding: 0.5625rem 0.75rem;
        text-decoration: none;
        transition:
            background-color 0.12s ease,
            color 0.12s ease;

        i {
            flex-shrink: 0;
            font-size: 0.9375rem;
            width: 1.125rem;
        }

        span {
            min-width: 0;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        &:hover {
            background-color: #1b2431;
            color: $white;
            text-decoration: none;
        }

        &:focus-visible {
            outline: 2px solid $teal-400;
            outline-offset: -2px;
        }

        &.is-active {
            background-color: $primary;
            color: $white;
            font-weight: 500;

            &:hover {
                background-color: $teal-500;
            }
        }
    }

    &__empty {
        color: #5b6472;
        font-size: 0.75rem;
        line-height: 1.6;
        padding: 0.75rem 0.625rem;
    }
}

// -----------------------------------------------------------------------------
// 3. Content column
// -----------------------------------------------------------------------------

.ams-shell {
    display: flex;
    flex-direction: column;
    min-height: 100vh;

    @include media-breakpoint-up(lg) {
        padding-left: var(--ams-sidebar-width);
    }
}

.ams-topbar {
    align-items: center;
    background-color: $white;
    border-bottom: 1px solid $gray-200;
    display: flex;
    flex-shrink: 0;
    gap: 0.5rem;
    height: var(--ams-topbar-height);
    padding: 0 0.75rem;
    position: sticky;
    top: 0;
    z-index: $zindex-sticky;

    @include media-breakpoint-up(lg) {
        padding: 0 1.25rem;
    }
}

.ams-main {
    flex: 1 1 auto;
    min-width: 0;
}

.ams-container {
    margin: 0 auto;
    max-width: var(--ams-content-max-width);
    padding: 1rem 0.875rem 2.5rem;
    width: 100%;

    @include media-breakpoint-up(md) {
        padding: 1.125rem 1.25rem 3rem;
    }
}

// Forms and detail screens cap out well short of a listing.
//
// A table earns every pixel of a 1680px canvas; a "Full Name" field does not —
// stretched to 900px it stops looking like a form and starts looking like a
// layout bug. Listings go wide, forms stay readable. Pages opt in with
// `@section('container-class', 'ams-container--narrow')`.
.ams-container--narrow {
    max-width: 1140px;
}

// The hamburger and any other bare icon control on the topbar.
.ams-icon-btn {
    align-items: center;
    background-color: transparent;
    border: 1px solid transparent;
    border-radius: 0.375rem;
    color: $gray-500;
    display: inline-flex;
    flex-shrink: 0;
    height: 2rem;
    justify-content: center;
    padding: 0;
    transition:
        background-color 0.12s ease,
        color 0.12s ease;
    width: 2rem;

    &:hover {
        background-color: $gray-100;
        color: $gray-900;
    }

    &:active {
        background-color: $gray-200;
    }

    &:focus-visible {
        box-shadow: var(--ams-focus-ring);
        outline: none;
    }
}

// -----------------------------------------------------------------------------
// 4. Identity
// -----------------------------------------------------------------------------

.ams-avatar {
    align-items: center;
    background-color: $teal-700;
    border-radius: 0.375rem;
    color: $white;
    display: inline-flex;
    flex-shrink: 0;
    font-size: 0.6875rem;
    font-weight: 600;
    height: 1.625rem;
    justify-content: center;
    letter-spacing: 0.01em;
    width: 1.625rem;
}

.ams-avatar--lg {
    border-radius: 0.5rem;
    font-size: 0.8125rem;
    height: 2.25rem;
    width: 2.25rem;
}

// The topbar account control: avatar + name + chevron, with no button chrome
// until it is hovered.
.ams-user-btn {
    align-items: center;
    background-color: transparent;
    border: 1px solid transparent;
    border-radius: 0.375rem;
    color: $gray-700;
    display: inline-flex;
    font-size: 0.8125rem;
    font-weight: 500;
    gap: 0.4375rem;
    padding: 0.1875rem 0.375rem;
    transition: background-color 0.12s ease;

    &:hover,
    &.show {
        background-color: $gray-100;
        color: $gray-900;
    }

    &:focus-visible {
        box-shadow: var(--ams-focus-ring);
        outline: none;
    }

    &::after {
        border: 0;
        color: $gray-400;
        content: "\f282"; // bi-chevron-down
        font-family: bootstrap-icons, sans-serif;
        font-size: 0.5625rem;
        margin: 0;
        vertical-align: 0;
    }
}

// The location label. Weighted to sit *below* the page title in the hierarchy —
// it is orientation, not a heading, and repeating the title at heading weight
// two inches above the real one would read as a mistake.
.ams-topbar__context {
    color: $gray-500;
    font-size: 0.75rem;
    font-weight: $font-weight-medium;
    letter-spacing: 0;
    max-width: 22rem;
}

// A hairline separating groups of topbar controls, so the bar reads as regions
// rather than as a row of floating objects.
.ams-topbar__divider {
    align-self: center;
    background-color: $gray-200;
    flex-shrink: 0;
    height: 1.25rem;
    width: 1px;
}

// -----------------------------------------------------------------------------
// 5. Page header
//
// Title, subtitle and actions on one baseline. The actions sit on the title
// row — not on a row of their own — so the header reads as a single object and
// costs one line instead of two.
// -----------------------------------------------------------------------------

.ams-page-header {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 0.625rem 1rem;
    justify-content: space-between;
    margin-bottom: 1rem;

    h1 {
        font-size: 1.25rem;
        letter-spacing: -0.018em;
        line-height: 1.25;
        margin: 0;
    }

    p {
        color: $gray-500;
        font-size: 0.8125rem;
        line-height: 1.4;
        margin: 0.1875rem 0 0;
    }
}

.ams-page-header__actions {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    // Buttons set `white-space: nowrap`, so a shrinking actions group pushes
    // them off the right edge instead of wrapping. It never shrinks; below sm
    // the whole header stacks instead.
    flex-shrink: 0;
}

// Breadcrumbs sit tight above the title and belong to it.
.ams-page-header__crumbs {
    margin-bottom: 0.375rem;
}

// On a phone the title and its action cannot share a row without one of them
// losing. They stack, and the action goes full width — which is also the
// easiest thing to hit with a thumb.
@include media-breakpoint-down(sm) {
    .ams-page-header {
        align-items: stretch;
        flex-direction: column;
    }

    .ams-page-header__actions .btn {
        flex: 1 1 auto;
    }
}

// -----------------------------------------------------------------------------
// 6. Print
// -----------------------------------------------------------------------------

@media print {
    .ams-sidebar,
    .ams-topbar,
    .ams-no-print {
        display: none !important;
    }

    .ams-shell {
        min-height: auto;
        padding-left: 0;
    }

    .ams-container {
        max-width: none;
        padding: 0;
    }

    .card {
        border: 0;
        box-shadow: none;
    }
}
