#blazor-error-ui { color-scheme: light only; background: lightyellow; bottom: 0; box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); box-sizing: border-box; display: none; left: 0; padding: 0.6rem 1.25rem 0.7rem 1.25rem; position: fixed; width: 100%; z-index: 1000; } #blazor-error-ui .dismiss { cursor: pointer; position: absolute; right: 0.75rem; top: 0.5rem; } /* Header: pinned to the top while the page scrolls, so the brand and (on mobile) the hamburger button are always reachable. It is a plain block child of (NOT a flex item) -- a stretched flex child fills its cell and never sticks. z-index keeps it above the content; the opaque background stops content showing through as it scrolls underneath. */ .site-header { /* Brand-blue bar with a warm accent underline -- the strongest, most visible cue that carries the friendly tone across every page. Uses its own header token so it stays deep blue in dark mode too (see app.css). */ background: var(--color-header); border-bottom: 3px solid var(--color-accent); box-shadow: var(--shadow); position: sticky; top: 0; z-index: 20; } .header-inner { max-width: var(--content-width); margin: 0 auto; padding: var(--space-3) 1.25rem; display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2) var(--space-4); } .brand { font-size: 1.35rem; font-weight: 700; color: #fff; text-decoration: none; white-space: nowrap; } .main-nav { display: flex; flex-wrap: wrap; gap: 0.25rem 1.25rem; } /* The hamburger button, its state checkbox, and the mobile-only home link are hidden on wide screens; the media query below turns them on for narrow ones. (On wide screens the brand is the home link, so a "Start" entry is redundant.) */ .nav-toggle, .nav-toggle-label, .nav-home-mobile { display: none; } /* The link colours/states for .main-nav a live in the GLOBAL app.css, not here. Reason: NavLink renders plain elements that carry no scoped-CSS attribute (b-xxxxx), so a scoped rule ".main-nav a" would not match them. See app.css. */ /* Content: at least tall enough that the footer sits at the bottom of the viewport on short pages. 100dvh - 4rem leaves room for the header (which sits above in normal flow); dvh follows the mobile browser's shrinking toolbar. On long pages the content simply grows past this and pushes the footer down naturally. */ .content { min-height: calc(100dvh - 4rem); box-sizing: border-box; width: 100%; max-width: var(--content-width); margin: 0 auto; padding: var(--space-4) 1.25rem var(--space-6); } /* Footer */ .site-footer { border-top: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-text-soft); font-size: 0.9rem; } .footer-inner { max-width: var(--content-width); margin: 0 auto; padding: var(--space-3) 1.25rem; display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-2) var(--space-4); } .footer-nav { display: flex; gap: var(--space-4); } .footer-nav a { color: var(--color-text-soft); text-decoration: none; } .footer-nav a:hover { color: var(--color-brand); text-decoration: underline; } /* Mobile: on narrow screens the nav collapses behind a hamburger button. This is pure CSS -- the #nav-toggle checkbox holds the open/closed state and its :checked state reveals the nav. No JavaScript, so it works under static SSR. */ @media (max-width: 40rem) { /* The brand stays on the left, the hamburger goes to the right, and the nav occupies its own full-width row below both. */ .header-inner { flex-wrap: wrap; align-items: center; justify-content: space-between; } /* Show the hamburger button. */ .nav-toggle-label { display: block; cursor: pointer; padding: 0.5rem; margin: -0.5rem; /* keep the tap target large without shifting layout */ } /* The three-bar icon, drawn with one element plus its ::before/::after. */ .nav-toggle-bar, .nav-toggle-bar::before, .nav-toggle-bar::after { display: block; width: 1.5rem; height: 2px; background: #fff; /* on the blue header bar */ content: ""; } .nav-toggle-bar::before { transform: translateY(-6px); } .nav-toggle-bar::after { transform: translateY(4px); /* 6px minus the bar's own 2px height */ } /* The nav takes its own row and is hidden until the checkbox is checked. */ .main-nav { flex-basis: 100%; flex-direction: column; gap: 0; max-height: 0; overflow: hidden; transition: max-height 0.2s ease; } /* Checked state: reveal the stacked links. The max-height caps the open menu to the space below the sticky header; a longer list scrolls inside it instead of running off the screen. */ .nav-toggle:checked ~ .main-nav { max-height: 70vh; overflow-y: auto; margin-top: 0.5rem; } /* The mobile-only home link reappears as the first entry in the menu. */ .nav-home-mobile { display: block; } /* Mobile per-link spacing/separators for .main-nav a are in the global app.css too, for the same scoped-attribute reason as above. */ }