/* =====================================================================
   layout.css — sidebar, topbar, page shell
   ===================================================================== */

.app {
    display: grid;
    grid-template-columns: var(--sidebar-w) 1fr;
    grid-template-rows: var(--topbar-h) 1fr;
    grid-template-areas:
        "sidebar topbar"
        "sidebar main";
    min-height: 100vh;
}

/* ─── Sidebar ─── */
.sidebar {
    grid-area: sidebar;
    background: var(--bg-panel);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}
.sidebar__brand {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-4);
    border-bottom: 1px solid var(--border);
    font-weight: 600;
    font-size: var(--fz-16);
    letter-spacing: -0.01em;
}
.sidebar__brand-mark {
    width: 28px; height: 28px;
    object-fit: contain;
    flex-shrink: 0;
}
.sidebar__nav {
    list-style: none;
    margin: 0;
    padding: var(--sp-3);
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.sidebar__nav a {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    color: var(--text-dim);
}
/* Unchecked-alert count (#188). Lives here, with the sidebar, NOT in a page
   stylesheet: .sidebar__pill is defined in pages/chat.css yet rendered in the
   sidebar on every page, so the Chat "beta" tag is unstyled everywhere except
   /chat — the same shape of bug as #177. Rose matches the alert FAB and the
   fired-row edge; white on #be185d is 6.04:1, and #be185d clears 3:1 against
   both sidebar surfaces (3.05 dark / 6.04 light) for 1.4.11. */
.sidebar__count {
    margin-left: auto;
    background: #be185d;
    color: #fff;
    font-size: var(--fz-12);
    font-weight: 700;
    line-height: 1;
    padding: 3px 7px;
    border-radius: 999px;
    min-width: 18px;
    text-align: center;
}
.sidebar__nav a:hover {
    background: var(--bg-elev);
    color: var(--text);
    text-decoration: none;
}
.sidebar__nav a.is-active {
    background: var(--nav-active-bg);
    color: var(--nav-active-fg);
}
.sidebar__nav .icon {
    width: 18px; height: 18px;
    flex-shrink: 0;
    color: currentColor;
}
.sidebar__section-label {
    padding: var(--sp-3) var(--sp-3) var(--sp-1);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-mute);
}

/* ─── Topbar ─── */
.topbar {
    grid-area: topbar;
    background: var(--bg-panel);
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: 0 var(--sp-4);
    position: sticky;
    top: 0;
    z-index: 10;
}
.topbar__hamburger {
    display: none;
    background: none;
    border: none;
    color: var(--text);
    padding: 6px;
    cursor: pointer;
}
.topbar__search {
    flex: 1;
    max-width: 600px;
    position: relative;
}
/* .topbar__search-box wraps the icon+input that used to sit directly in
   .topbar__search — desktop never notices the extra layer (it's just a
   flex pass-through), but it gives the mobile rules below something to
   show/hide as a unit, separate from .topbar__search-toggle. */
.topbar__search-box {
    display: flex;
    align-items: center;
    position: relative;
}
.topbar__search input {
    background: var(--bg-input);
    padding-left: 36px;
}
.topbar__search .icon {
    position: absolute;
    top: 50%;
    left: 10px;
    width: 18px; height: 18px;
    transform: translateY(-50%);
    color: var(--text-mute);
    pointer-events: none;
}
/* Mobile-only controls — desktop's search is always the input, never the
   button, and never shows a close button since there's nothing to close. */
.topbar__search-toggle,
.topbar__search-close {
    display: none;
    background: none;
    border: none;
    color: var(--text-dim);
    cursor: pointer;
}
.topbar__search-toggle:hover,
.topbar__search-close:hover { color: var(--text); }
.topbar__search-results {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-2);
    max-height: 60vh;
    overflow-y: auto;
    display: none;
}
.topbar__search-results.is-open { display: block; }
/* Empty-state line for the mobile overlay (app.js showSearchHint) — only
   ever rendered while the overlay is open. */
.topbar__search-hint {
    padding: 24px 12px;
    color: var(--text-mute);
    text-align: center;
}

/* ── Mobile search: a button that opens a full-screen overlay ──────────────
   Below 768px the input doesn't fit next to the hamburger/bell/avatar at any
   usable width, so it collapses to an icon button. Opening it (.is-open,
   toggled by app.js) turns .topbar__search itself into a fixed, full-screen
   panel — the input row up top, and the results panel filling the rest of
   the screen as a translucent, blurred overlay so the page is still visible
   (if dimmed) behind it, rather than a second opaque page. */
@media (max-width: 768px) {
    .topbar__search { flex: 0 0 auto; max-width: none; }
    .topbar__search-toggle {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 36px; height: 36px;
        border-radius: var(--radius-sm);
    }
    .topbar__search-toggle:hover { background: var(--bg-elev); }
    .topbar__search-toggle .icon { width: 18px; height: 18px; }
    .topbar__search-box { display: none; }
    .topbar__search.is-open {
        position: fixed;
        inset: 0;
        z-index: 200;
        max-width: none;
        display: flex;
        flex-direction: column;
        /* Deliberately NOT opaque: the whole point of the translucent results
           panel below is seeing the page behind it, and a background here
           would be what you saw through it instead. Only the input row is
           opaque; the rest of the screen is the results overlay. */
        background: none;
    }
    .topbar__search.is-open .topbar__search-toggle { display: none; }
    .topbar__search.is-open .topbar__search-box {
        display: flex;
        flex: none;
        height: var(--topbar-h);
        padding: 0 var(--sp-4);
        background: var(--bg-panel);
        border-bottom: 1px solid var(--border);
    }
    .topbar__search.is-open .topbar__search-box input { padding-right: 36px; }
    /* The magnifier and the close button are absolute against
       .topbar__search-box, but the open box carries var(--sp-4) of side
       padding that the input starts after — so both have to be pushed in by
       that padding or they straddle the input's border instead of sitting
       inside it (icon overhung the left edge by 6px, close sat 8px past the
       right one). */
    .topbar__search.is-open .topbar__search-box .icon { left: calc(var(--sp-4) + 10px); }
    /* A search input paints its own clear ✕ once it has a value, which landed
       right next to our close ✕ — two identical glyphs a few px apart doing
       different things (clear the query vs. dismiss the overlay). The overlay
       keeps its own, so drop the native one here. */
    .topbar__search.is-open .topbar__search-box input::-webkit-search-cancel-button {
        -webkit-appearance: none;
        appearance: none;
    }
    .topbar__search.is-open .topbar__search-close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        position: absolute;
        right: calc(var(--sp-4) + 8px); top: 50%;
        transform: translateY(-50%);
        width: 28px; height: 28px;
        font-size: 22px;
        line-height: 1;
        border-radius: 50%;
    }
    .topbar__search.is-open .topbar__search-close:hover { background: var(--bg-elev); }
    /* Forced open regardless of the results' own .is-open (which still
       tracks "does this query have results") — the overlay body should be
       there the instant you open search, showing a "type to search" state
       even before the first keystroke. */
    .topbar__search.is-open .topbar__search-results {
        display: block;
        position: static;
        flex: 1;
        min-height: 0;
        /* The desktop dropdown caps itself at 60vh; here the panel *is* the
           rest of the screen, and leaving the cap on left a dead opaque strip
           below it — flex:1 can grow the box but max-height still clamps it. */
        max-height: none;
        overflow-y: auto;
        border: none;
        border-radius: 0;
        box-shadow: none;
        background: color-mix(in srgb, var(--bg-base) 88%, transparent);
        backdrop-filter: blur(6px);
        -webkit-backdrop-filter: blur(6px);
    }
}

.topbar__bell {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-sm);
    color: var(--text-mute);
    transition: color 0.15s, background 0.15s;
    flex-shrink: 0;
}
.topbar__bell:hover { color: var(--text); background: var(--bg-elev); }
.topbar__bell-badge {
    position: absolute;
    top: 4px;
    right: 4px;
    background: var(--accent);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 8px;
    min-width: 16px;
    text-align: center;
    pointer-events: none;
}

.topbar__user {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    position: relative;
}
.topbar__avatar {
    display: grid; place-items: center;
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
}
.topbar__menu {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-2);
    padding: var(--sp-2);
    min-width: 200px;
    display: none;
    z-index: 20;
}
.topbar__menu.is-open { display: block; }
.topbar__menu a, .topbar__menu button {
    display: block;
    width: 100%;
    text-align: left;
    padding: 8px 10px;
    border: none;
    background: none;
    color: var(--text);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.topbar__menu a:hover, .topbar__menu button:hover { background: var(--bg-elev); text-decoration: none; }

/* ─── Main ─── */
.main {
    grid-area: main;
    padding: var(--sp-5);
    max-width: 1400px;
    width: 100%;
    /* Grid items default to min-width:auto, which refuses to shrink below
       content's intrinsic width — on the board page that meant the whole
       page (header included) stretched/scrolled horizontally instead of
       .board's own overflow-x:auto containing the scroll. */
    min-width: 0;
}
.page-header {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin-bottom: var(--sp-5);
}
.page-title { font-size: var(--fz-24); margin: 0; }
.page-title--toggle {
    color: var(--text);
    text-decoration: none;
    border-bottom: 2px dashed var(--border-strong);
    cursor: pointer;
}
.page-title--toggle:hover {
    color: var(--accent-hi);
    border-bottom-color: var(--accent-hi);
}
.page-actions { margin-left: auto; display: flex; gap: var(--sp-2); }

/* Flash */
.flash {
    padding: var(--sp-3) var(--sp-4);
    border-radius: var(--radius-sm);
    margin-bottom: var(--sp-4);
    border: 1px solid var(--border);
    background: var(--bg-panel);
}
.flash--success { border-color: #14532d; background: #052e16; color: #bbf7d0; }
.flash--error   { border-color: #7f1d1d; background: #2a0a0a; color: #fecaca; }
.flash--info    { border-color: var(--accent-dim); background: #0f1a33; color: #bfdbfe; }

/* ─── Minimal layout (login, install) ─── */
.minimal {
    display: grid;
    place-items: center;
    min-height: 100vh;
    padding: var(--sp-5);
    background:
        radial-gradient(1200px 600px at 50% -10%, rgba(59,130,246,0.15), transparent),
        var(--bg-base);
}
.minimal__card {
    width: 100%;
    max-width: 420px;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: var(--sp-6);
    box-shadow: var(--shadow-2);
}
.minimal__brand {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin-bottom: var(--sp-5);
}
.minimal__brand-mark {
    width: 36px; height: 36px;
    object-fit: contain;
    flex-shrink: 0;
}

/* ─── Mobile ─── */
@media (max-width: 768px) {
    .app {
        grid-template-columns: 1fr;
        grid-template-areas: "topbar" "main";
        grid-template-rows: var(--topbar-h) 1fr;
    }
    .sidebar {
        position: fixed;
        left: 0; top: 0; bottom: 0;
        width: 280px;
        transform: translateX(-100%);
        transition: transform 200ms ease;
        z-index: 30;
        box-shadow: var(--shadow-2);
    }
    .sidebar.is-open { transform: translateX(0); }
    .topbar__hamburger { display: inline-flex; }
    /* Room at the bottom for the floating + button (56px plus its offset), which
       is fixed and was sitting on top of the last row of whatever list you were
       reading. Desktop has enough width that it lands clear of content. */
    .main { padding: var(--sp-4); padding-bottom: 104px; }
    .sidebar-backdrop {
        position: fixed; inset: 0;
        background: rgba(0,0,0,0.5);
        z-index: 25;
        display: none;
    }
    .sidebar-backdrop.is-open { display: block; }
}
