/* App chrome: sidebar, mobile app bar, mobile tab bar, page scaffolding */

/* ===== Sidebar ===== */
aside {
    position: fixed;
    top: 0;
    left: 0;
    width: var(--sidebar-width);
    /* dvh tracks the shrinking viewport as a mobile browser's URL bar slides
       away, so the drawer never overshoots the visible area. vvh cannot. */
    height: 100vh;
    height: 100dvh;
    background: var(--bg-secondary);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    padding: 1.5rem 0;
    z-index: 500;
    overflow: hidden;
}

.sidebar-logo {
    padding: 0 1.25rem 1.5rem;
    border-bottom: 1px solid var(--border);
    margin-bottom: 0.5rem;
}

.sidebar-logo h2 {
    line-height: 0;
}

.brand-logo {
    display: block;
    width: min(100%, 9rem);
    height: auto;
}

/* The sidebar is a fixed-height flex column: logo, scrollable nav, theme
   toggle, account control. Only the nav is allowed to shrink, so on a very
   short viewport the three fixed rows together exceed 100dvh and the account
   control — the row that must never scroll away — is the one pushed off the
   bottom, where `overflow: hidden` silently clips it. Tighten the fixed rows
   as the viewport loses height so the account control stays reachable. */
@media (max-height: 300px) {
    aside {
        padding: 0.5rem 0;
    }

    .sidebar-logo {
        padding: 0 1.25rem 0.5rem;
        margin-bottom: 0.25rem;
    }

    .brand-logo {
        width: min(100%, 5rem);
    }

    .theme-toggle--sidebar {
        margin: 0.35rem 1.25rem;
    }
}

/* Below roughly one theme toggle plus the account control there is no height
   left for a wordmark. Dropping it keeps the sign-out reachable, which is the
   row that matters; the app bar still carries the logo on mobile. */
@media (max-height: 200px) {
    .sidebar-logo {
        display: none;
    }
}

.sidebar-nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 0 0.75rem;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.sidebar-nav::-webkit-scrollbar {
    display: none;
}

.sidebar-nav a {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.7rem 0.75rem;
    border-radius: var(--radius-sm);
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--text-secondary);
    transition: background-color var(--transition), color var(--transition);
}

.sidebar-nav a:hover {
    background: var(--bg-card);
    color: var(--text-primary);
}

/* Active page is signalled by background, weight AND aria-current (set in HTML) */
.sidebar-nav a.active {
    background: var(--accent-glow);
    color: var(--accent-light);
    font-weight: 600;
}

.sidebar-nav .nav-icon {
    font-size: 1.15rem;
    width: 1.5rem;
    text-align: center;
    flex-shrink: 0;
}

.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: 44px;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-card);
    color: var(--text-secondary);
    font-size: 0.82rem;
    font-weight: 600;
    transition: background-color var(--transition), color var(--transition),
        border-color var(--transition);
}

.theme-toggle:hover {
    background: var(--bg-card-hover);
    border-color: var(--border-strong);
    color: var(--text-primary);
}

.theme-toggle-icon {
    color: var(--accent-light);
    font-size: 1rem;
    line-height: 1;
}

.theme-toggle--sidebar {
    align-self: stretch;
    margin: 0.75rem 1.25rem 0.75rem;
}

.theme-toggle--mobile {
    display: none;
    flex: 0 0 auto;
    margin-left: auto;
}

/* ===== Mobile App Bar =====
   Sticky page identity. Replaces the old floating hamburger button and the
   4.5rem of main padding that existed only to leave room for it. Desktop
   hides it outright, because the sidebar already names the current page. */
.app-bar {
    display: none;
    position: sticky;
    top: 0;
    z-index: 200;
    align-items: center;
    gap: 0.6rem;
    min-height: var(--app-bar-height);
    /* The notch inset is added to the min-height, not baked into a padding
       that would double up on devices without one. */
    padding: var(--app-safe-top) 1.25rem 0;
    background: var(--bg-primary);
    border-bottom: 1px solid var(--border);
    /* This is a <header>, and the generic page-header rule adds 2rem of
       bottom margin meant for a page title. The app bar supplies its own
       separation via the border. */
    margin-bottom: 0;
}

.app-bar-logo {
    display: block;
    width: 5.75rem;
    height: auto;
    flex-shrink: 0;
}

.app-bar-title {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-primary);
    /* Long page names must not push the row wide on a 320px screen. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ===== Mobile Tab Bar =====
   Five destinations at thumb height. Progress and Goals are deliberately not
   tabs: six at 390px is ~65px each, which truncates every label. They live
   behind the More button, which opens the existing drawer. */
.tab-bar {
    display: none;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 340;
    background: var(--bg-secondary);
    border-top: 1px solid var(--border);
    /* Keeps the row clear of the home indicator on notched phones. */
    padding-bottom: var(--app-safe-bottom);
}

.tab {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.1rem;
    /* 56px clears the 44px minimum with room either side of the label. */
    min-height: var(--tab-bar-height);
    padding: 0.35rem 0.15rem 0.4rem;
    color: var(--text-secondary);
    transition: color var(--transition);
}

.tab-icon {
    font-size: 1.1rem;
    line-height: 1.1;
}

.tab-label {
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

/* The active tab is marked by a rule above the icon rather than a filled
   pill, so the bar reads as one surface instead of five buttons. */
.tab::before {
    content: '';
    display: block;
    width: 1.25rem;
    height: 2px;
    margin-bottom: 0.1rem;
    border-radius: 999px;
    background: transparent;
    transition: background-color var(--transition);
}

.tab.is-active {
    color: var(--accent-light);
}

.tab.is-active::before {
    background: var(--accent-light);
}

.tab-more {
    font-family: inherit;
    border: none;
    background: none;
    cursor: pointer;
}

.nav-scrim {
    display: none;
    position: fixed;
    inset: 0;
    /* Above the app bar (200) and tab bar (340) so opening the drawer dims
       the whole page rather than leaving a lit strip at either end. */
    z-index: 450;
    background: rgba(0, 0, 0, 0.6);
    border: none;
    cursor: pointer;
}

/* ===== Main Content ===== */
main {
    /* Auto inline margins centre the column once flex-grow hits max-width */
    margin-inline: auto;
    flex: 1;
    /* A flex item defaults to min-width:auto, which refuses to shrink below its
       content and pushes the page wide. The calendar's 1fr tracks need this. */
    min-width: 0;
    padding: 2rem 2.5rem;
    max-width: 1200px;
}

/* ===== Page Load Reveal =====
   Moving between pages is a full document load, so there is no router to
   animate. The page assembles itself on arrival instead.

   Scoped away from .toast/.modal on purpose: calendar.html places both inside
   <main>, and fill-mode:both would hold opacity:1 at the end of the animation
   and leave the toast permanently on screen. No position:fixed element lives
   inside <main>, so the transient transform breaks no containing blocks. */
@keyframes slideUp {
    from {
        opacity: 0;
        transform: translateY(12px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

main > *:not(.toast):not(.modal) {
    animation: slideUp 0.25s ease-out both;
}

/* Staggered increments; n+6 clamps so a long page cannot stretch the reveal
   past 0.25s + 0.25s. Under the 300ms ceiling for a single element. */
main > *:not(.toast):not(.modal):nth-child(1) { animation-delay: 0s; }
main > *:not(.toast):not(.modal):nth-child(2) { animation-delay: 0.05s; }
main > *:not(.toast):not(.modal):nth-child(3) { animation-delay: 0.1s; }
main > *:not(.toast):not(.modal):nth-child(4) { animation-delay: 0.15s; }
main > *:not(.toast):not(.modal):nth-child(5) { animation-delay: 0.2s; }
main > *:not(.toast):not(.modal):nth-child(n+6) { animation-delay: 0.25s; }

/* Reduced motion needs no rule of its own: base.css already forces
   animation-duration to 0.01ms under prefers-reduced-motion: reduce. */

/* ===== Page Header ===== */
header {
    margin-bottom: 2rem;
}

header h1 {
    font-size: 1.75rem;
    font-weight: 700;
    margin-bottom: 0.25rem;
}

header p {
    color: var(--text-secondary);
    font-size: 0.95rem;
}

/* ===== Section ===== */
section {
    margin-bottom: 2rem;
}

section > h2 {
    font-size: 1.15rem;
    font-weight: 600;
    margin-bottom: 1rem;
    color: var(--text-primary);
}

.section-header {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 1rem;
}

.section-header--stacked {
    flex-direction: column;
    align-items: flex-start;
}

.section-header h2 {
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 0;
    line-height: 1.3;
}

.section-link {
    font-size: 0.85rem;
    color: var(--accent-light);
    font-weight: 500;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    transition: color var(--transition);
    white-space: nowrap;
    flex-shrink: 0;
}

.section-link:hover {
    color: var(--accent-light);
    text-decoration: underline;
}

/* The Quick Notes "View all" link moved below the note list when the composer
   became a disclosure, so the header holds only the Add button. Without a
   stacked header the button would sit right-aligned next to the heading, which
   leaves a long empty gap at narrow widths. */
.section-link-wrap {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.75rem;
}

/* ===== Card (generic) ===== */
.card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1.5rem;
}

.two-col > section {
    display: flex;
    flex-direction: column;
}

.two-col .card {
    flex: 1;
}

/* ===== Two-Column Layout ===== */
.two-col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem;
}

/* ===== Responsive ===== */
@media (max-width: 768px) {
    .app-bar {
        display: flex;
    }

    .theme-toggle--sidebar {
        display: none;
    }

    .theme-toggle--mobile {
        display: inline-flex;
    }

    .tab-bar {
        display: flex;
    }

    /* Standalone links that measured 22px tall at 320-390px. A target in its
       own right rather than a link inside a sentence, so the inline-target
       exemption does not apply. Given height rather than extra padding, which
       would have pulled it out of line with its heading. */
    .section-link {
        min-height: 44px;
    }

    /* The scrim covers the whole viewport, so it is always mounted here and
       toggled by opacity/visibility rather than display. */
    .nav-scrim {
        display: block;
        opacity: 0;
        visibility: hidden;
        transition: opacity var(--transition), visibility var(--transition);
    }

    body.nav-open .nav-scrim {
        opacity: 1;
        visibility: visible;
    }

    aside {
        transform: translateX(-100%);
        transition: transform 0.3s ease;
        /* The account control is the drawer's last row, and the tab bar is fixed
           across the bottom of the viewport. Without this the row sits under the
           tab bar and is clipped: 21px of overlap on a plain viewport, and 55px
           once env(safe-area-inset-bottom) is non-zero on a notched phone, which
           left barely a sliver of the avatar and Sign out visible. The drawer
           ends at 100dvh, so the clearance has to be padding, not margin. */
        padding-bottom: calc(var(--tab-bar-total) + 0.75rem);
    }

    .sidebar-logo {
        order: 0;
    }

    .sidebar-nav {
        order: 2;
    }

    body.nav-open aside {
        transform: translateX(0);
    }

    /* Sidebar is off-canvas here, so it no longer occupies body space */
    body {
        padding-left: 0;
        /* body is display:flex in a row so main can centre itself in the space
           left by the fixed sidebar. With the sidebar out of flow that row
           would place the app bar BESIDE main instead of above it, squeezing
           main to roughly half the viewport. Stacking restores the intended
           order. Both .app-bar and main are direct children of body. */
        flex-direction: column;
    }

    main {
        /* The app bar is in flow and supplies its own height, so the old 4.5rem
           of top padding is gone. The bottom padding reserves the tab bar plus
           the home-indicator inset, so the last card is never trapped under it. */
        width: 100%;
        padding: 1rem 1.25rem calc(var(--tab-bar-total) + 1.5rem);
    }

    .section-header {
        flex-direction: column;
        align-items: flex-start;
    }

    .two-col {
        grid-template-columns: 1fr;
    }
}
