/* ========================
   APP SHELL — shared two-column layout
   Sidebar (assets/components/sidebar/) + a right-hand content column
   (#app-main) that the desktop router (assets/js/app-router.js) swaps
   between Home / Play / About / Notes. Used by index.html, about.html,
   play.html, and the Notes list page.

   Below 1140px the grid collapses to a single stacked column and the
   router never activates — every page renders/navigates as a normal
   standalone page at that width, unchanged from before this shell existed.
======================== */

.app-shell {
    width: 100%;
    padding: 96px max(80px, calc((100% - 1178px) / 2)) 0 max(131px, calc((100% - 1178px) / 2));
    display: grid;
    grid-template-columns: 340px 1fr;
    gap: 64px;
    align-items: start;
    box-sizing: border-box;
}

/* The sidebar's sticky-until-row-ends behavior depends on the sticky
   element (.home-sidebar) being the direct grid item of .app-shell — a
   grid item's sticky containing block spans the full row height even with
   align-items: start, which is what lets it stay pinned until the right
   column runs out. #sidebar-placeholder is empty until sidebar-loader.js's
   async fetch injects the template into it, so without `display: contents`
   it would sit as an ordinary wrapper box (auto-height := its own content),
   demoting .home-sidebar to a non-grid-item descendant and collapsing its
   sticky range down to just its own height. */
#sidebar-placeholder {
    display: contents;
}

.app-shell__main {
    display: flex;
    flex-direction: column;
    max-width: 880px;
    min-width: 0;
}

/* Flex items default to min-width: auto — they won't shrink below their
   own content's intrinsic width even when the flex container is narrower.
   Most sections here happen to set their own `width: 100%` which masks
   this, but anything that doesn't (e.g. About's brand-logo ticker in its
   non-wrapping "static" mode) can silently force the whole column wider
   than 880px instead of being clipped/wrapped to fit it. This is a
   blanket safeguard so future content doesn't hit the same bug. */
.app-shell__main > * {
    min-width: 0;
}

/* Footer's "Let's connect" block is redundant on every shell page — the
   sidebar already surfaces the same CTA/email/LinkedIn/Resume. Lives here
   (rather than duplicated per-page-CSS-file) since app-shell.css is loaded
   only by the four shell pages; case-study pages don't load this file, so
   their footer keeps the block as their only on-page contact CTA. */
.site-footer .footer-top {
    display: none;
}

/* ========================
   RESPONSIVE — LARGE TABLET
======================== */
@media (max-width: 1140px) {
    .app-shell {
        grid-template-columns: 1fr;
        padding: 96px 40px 0 60px;
        gap: 48px;
    }
    .app-shell__main { max-width: none; }
}

/* ========================
   RESPONSIVE — MOBILE
======================== */
@media (max-width: 768px) {
    .app-shell { padding: 112px 24px 0; gap: 40px; }
}

/* ========================
   GO TO TOP — mobile only, shown past 50% scroll (sidebar-loader.js).
   Same visual language as .cs-to-top in case-study.css, without the
   hover tooltip (no hover on touch devices).
======================== */
.shell-to-top {
    display: none;
    position: fixed;
    bottom: 24px;
    right: 24px;
    width: 40px;
    height: 40px;
    align-items: center;
    justify-content: center;
    background: #ffffff;
    border: none;
    border-radius: 4px;
    box-shadow: 0 2px 10px rgba(10, 24, 51, 0.16);
    cursor: pointer;
    z-index: 90;
    padding: 0;
    color: #0a1833;
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px);
    transition: opacity 0.25s ease, transform 0.25s ease, visibility 0.25s ease;
}

.shell-to-top svg {
    width: 20px;
    height: 20px;
    display: block;
}

.shell-to-top:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}

@media (max-width: 768px) {
    .shell-to-top { display: flex; }
    .shell-to-top.is-visible {
        opacity: 1;
        visibility: visible;
        transform: translateY(0);
    }
}

[data-theme="dark"] .shell-to-top { background: #1f2430; color: #ffffff; }
