/* layout.css -- Site header, nav, theme toggle, .page shell
   Part of the site stylesheet, split out of the former single
   site.css. Load order is significant and is fixed in
   src/view/layout.php -- theme first (tokens), then base, then
   layout, then components. Rules were moved verbatim, in their
   original order, so the cascade is unchanged. */

.site-header {
    flex-shrink: 0;
    position: sticky;
    top: 0;
    z-index: 100;
    /* No background color of its own -- body::before is the *only*
       fade layer (37signals' actual setup: their header has no
       separate background either). A second gradient here would force
       a plateau in body::before to avoid a seam, eating into its fade
       height for no reason. Sticky (not fixed) so it still reserves
       its own space in normal flow; nav text stays legible on its
       own z-index regardless of what's behind it. backdrop-filter is
       independent of background-color -- it still blurs whatever
       scrolls underneath even with no tint of its own. */
    background: none;
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}

.site-header::after {
    /* backdrop-filter on the header itself has a hard edge at the
       header's own bottom border -- content passing underneath jumps
       from fully blurred to fully sharp in one pixel row. This strip
       sits right below the header and re-blurs the same content with
       a mask-image fading from opaque (top, seamless with the header's
       own blur) to transparent (bottom, reveals sharp content), so the
       transition reads as a gradient instead of a line. */
    content: '';
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: 24px;
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    mask-image: linear-gradient(to bottom, black, transparent);
    -webkit-mask-image: linear-gradient(to bottom, black, transparent);
    pointer-events: none;
}

.site-header nav {
    /* Full width, not capped/centered at --container-xl -- the app
       shell reads as a real app bar spanning the whole window, not a
       marketing-page nav sitting in a centered content column. */
    padding: var(--spacing-6) 20px;
    display: flex;
    gap: var(--spacing-8);
    align-items: center;
}

/* Marketing pages: the header sits in the same column as the page below
   it, so the brand's left edge and the right-most control line up with the
   content edges (same max-width and side padding as .page). The brand
   takes the minor part of a golden-ratio split (38.2 %) and the links
   start exactly at that line: left-weighted, with the nav group landing
   near the optical centre. App pages keep the full-width bar above. */
body:not(.app-layout) .site-header nav {
    box-sizing: border-box;
    width: min(var(--container-xl), calc(100% - var(--page-offset)));
    margin: 0 0 0 var(--page-offset);
    padding-left: var(--spacing-5);
    padding-right: var(--spacing-5);
}

body:not(.app-layout) .site-header .brand {
    flex: 0 0 calc(38.2% - var(--spacing-8));
    white-space: nowrap;
}

.site-header .brand {
    font-family: var(--font-logo);
    font-size: 34px;
    font-weight: 600;
    letter-spacing: 1px;
    color: var(--fg-neutral-accent);
    text-decoration: none;
}

.site-header nav a:not(.brand) {
    font-family: var(--font-logo);
    font-size: 17px;
    font-weight: 500;
    letter-spacing: 1px;
}

.site-header nav a:not(.brand):not(.button) {
    color: var(--fg-neutral-body);
    text-decoration: none;
}

.site-header nav a:not(.brand):not(.button):hover {
    color: var(--fg-neutral-accent);
}

.site-header nav .nav-right {
    /* Lives on .theme-toggle (not Foundry -- Foundry stays left, near
       .brand, per the site-wide nav restructure). Pushes itself and
       everything after it in source order (Sign In, Sign up/My
       Account) to the right. */
    margin-left: auto;
}

.nav-cta {
    /* Muted/outline in the header specifically (unlike the filled
       .button default, or other .button-secondary uses elsewhere) --
       matches .theme-toggle's pill shape so the two sit together as a
       visually related pair. Resets both border-radius and
       corner-shape back to plain/round -- a pill (50%-of-height
       radius) can't be doubled the way .button's own squircle
       treatment needs, it would just go flat/square-ish instead. */
    border-radius: var(--rounded-full);
    --corner-shape: round;
    corner-shape: var(--corner-shape);
}

/* nav-burger: hidden entirely above 640px (nav-right/theme-toggle/
   nav-cta just show inline as normal) -- see the mobile override below
   for what it actually does. */

.nav-burger {
    display: none;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--fg-neutral-accent);
    cursor: pointer;
}

.nav-burger svg {
    width: 22px;
    height: 22px;
}

@media (max-width: 640px) {
    /* Below 640px: brand, theme-toggle, and the burger are the only
       things that stay in the top row (.nav-collapsible items --
       Foundry, Sign In, Sign up/My Account -- have no visible width
       here at all, so the row naturally closes up around them without
       any explicit reordering). .nav-right lives on theme-toggle now
       (it still needs pushing to the right on desktop), deliberately
       NOT included in this hide rule -- it must stay visible in the
       mobile top row same as before. Clicking the burger (src/view/
       layout.php) toggles .nav-open on <nav>, which reveals the
       collapsed items again as full-width rows wrapped onto a new line
       below -- order:10 keeps them there regardless of their actual
       position in the DOM. */
    .site-header nav {
        flex-wrap: wrap;
    }

    .nav-burger {
        display: inline-flex;
    }

    .site-header nav .nav-collapsible {
        display: none;
        order: 10;
        width: 100%;
        margin-left: 0;
    }

    .site-header nav.nav-open .nav-collapsible {
        display: block;
        margin-top: var(--spacing-3);
    }
}

/* theme-toggle: ui-theme-toggle (modules/ui) cycles system -> light ->
   dark. Only its look is set here, through its custom properties. */

ui-theme-toggle {
    --ui-theme-toggle-size: 1.9rem;
    --ui-theme-toggle-icon-size: 1rem;
    --ui-theme-toggle-radius: var(--rounded-full);
    --ui-theme-toggle-border-color: transparent;
    --ui-theme-toggle-background: var(--bg-neutral-section);
    --ui-theme-toggle-color: var(--fg-neutral-subtle);
    --ui-theme-toggle-hover-color: var(--fg-neutral-accent);
}

/* On app-layout pages, body itself is --bg-neutral-section -- the
   toggle's fill of that same color would blend into it under the
   header's blur. Use --bg-raised so it still reads as a distinct
   control there. */
ui-theme-toggle > button {
    corner-shape: var(--corner-shape);
}

body.app-layout ui-theme-toggle {
    --ui-theme-toggle-background: var(--bg-raised);
}

:root {
    /* Left-anchored like Google's results page. Its grid has a flexible
       gutter on both sides, so up to a certain width the content is centred;
       the left gutter stops growing at 260 px and every pixel beyond that goes
       to the right. Same here: the content (1240 px wide, 20 px of it the
       box's own padding) is centred while the free space per side is below
       260 px, then it stays 260 px from the left edge. The 20 px come off
       because the box carries its own side padding. */
    --page-offset: clamp(0px, (100vw - 1240px) / 2 - 20px, 240px);
    /* Imperavi-style step: the header sits on the column edge, everything the
       page says starts a little further in (left side only). */
    --content-indent: clamp(0px, 7.5vw - 12px, 96px);
}

@media (max-width: 1000px) {
    :root {
        --content-indent: 24px;
    }
}

@media (max-width: 720px) {
    :root {
        --content-indent: 0px;
    }
}

.page-content {
    padding-left: var(--content-indent);
}

.page {
    flex: 1;
    display: flex;
    flex-direction: column;
    /* flex: 1 alone only grants .page whatever's left after the
       header/footer's own height. This min-height guarantees the
       full viewport-minus-header allocation regardless, so the
       golden-ratio split below actually has real space to distribute.
       --header-height is a measured constant, not computed -- there's
       no JS on this site and no pure-CSS way to read a sibling's
       rendered (content-driven) height, so this needs re-measuring by
       hand if .site-header's own content/size ever changes. */
    min-height: calc(100dvh - var(--header-height));
    width: min(var(--container-xl), calc(100% - var(--page-offset)));
    margin: 0 0 0 var(--page-offset);
    /* No top padding -- every page's content now either starts with
       .page-section (which owns its own top spacing) or is a stub
       page (which sets its own top padding directly, see stub.php's
       .stub-content). A shared top padding here just meant every
       .page-section had to cancel it back out with a negative margin. */
    padding: 0 var(--spacing-5) var(--spacing-20);
    box-sizing: border-box;
}

/* app-page/sheet: logged-in account pages (layout.php's app_layout
   branch skips the marketing footer/wordmark entirely for these).
   Full-width muted canvas with the actual content sitting in a
   raised, width-capped "sheet" panel -- the same shape Basecamp's own
   dashboard uses (confirmed via modules/php/one's licensed Ciborius
   theme, cb_sheet class), rebuilt here with this site's own tokens
   instead of reusing that theme's CSS. Overrides several .page
   properties that only make sense for the marketing golden-ratio
   layout (width cap, no-top/big-bottom padding, column flex). */
/* Language switch in the header, shown on pages that have a translation. */
.lang-switch {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-1);
    font-size: var(--text-size-label);
    color: var(--fg-neutral-muted);
}

.lang-switch a {
    padding: 2px var(--spacing-1);
    color: var(--fg-neutral-body);
    text-decoration: none;
}

.lang-switch a:hover {
    color: var(--fg-neutral-accent);
}

.lang-switch a[aria-current="true"] {
    color: var(--fg-neutral-accent);
    font-weight: var(--weight-bold);
    text-decoration: underline;
    text-underline-offset: 4px;
}

/* The header button is an outlined button, which has no fill of its own; on
   pages whose hero draws a dot grid behind the header the dots would show
   through it. A solid page-coloured fill keeps it a button. */
.site-header .nav-cta.button-secondary {
    background: var(--bg-base);
}

.site-header .nav-cta.button-secondary:hover {
    background: var(--bg-neutral-section);
}

/* Safety net against sideways scrolling on a phone: every normal page has a
   dot host, and wide things (a long word, a full-bleed layer, the dot grid)
   must never widen the page. */
html:has(.dot-host) {
    overflow-x: hidden;
}

html:has(.dot-host) body {
    overflow-x: clip;
}
