/* site/public/lib/header.css: THE site header (2026-09-27), one stylesheet for every page with the header: the render.js
   templates (head() links it) and every static page (a <link> after tokens.css). The rules were copies in stocks.css and
   in each static page; site/test/header.test.mjs holds every page to this file and fails if a page grows its own header
   rule. Page-specific additions stay in the page, after this link: the home page's live read (.header-status) and
   /verify's larger tap targets. Colours are tokens.css variables only. */
/* ── The header's place (2026-09-27, feat/sticky-header). <header class="site-header"> is a direct child of <body>,
   before <main>: the page's banner landmark, full width, above the grid texture. Its row, .page-header, sits in the page
   column exactly where it sat inside <main>: the column is --col-max (main's max-width; the 760px pages set it on
   .site-header, their one header addition) and --col-pad-* (main's padding at each width; site/test/header.test.mjs holds every page's main to them). <body> is a
   column of the two, so <main> still fills the screen under the header on a short page. The same with the switch off:
   the switch (below) only makes the header stick and compact. ── */
.site-header { --col-max: 920px; --col-pad-top: 28px; --col-pad-l: max(32px, env(safe-area-inset-left)); --col-pad-r: max(32px, env(safe-area-inset-right)); }
@media (max-width: 600px) { .site-header { --col-pad-top: 20px; --col-pad-l: max(20px, env(safe-area-inset-left)); --col-pad-r: max(20px, env(safe-area-inset-right)); } }
html > body { display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; }
.site-header { position: relative; z-index: 2; padding-top: var(--col-pad-top); }
.site-header > .page-header {
  width: calc(min(100%, var(--col-max)) - var(--col-pad-l) - var(--col-pad-r));
  margin-left: calc((100% - min(100%, var(--col-max))) / 2 + var(--col-pad-l));
}
.site-header + main { padding-top: 0; min-height: 0; flex: 1 0 auto; width: 100%; }
/* ── Top bar ── */
.page-header {
  display: flex; justify-content: space-between; align-items: center;
  padding-bottom: 16px; border-bottom: 1px solid var(--border);
  font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--text3); letter-spacing: 0.14em;
}
.brand-logo { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; }
.brand-logo img { height: 20px; width: auto; display: block; }
.brand-wordmark { font-family: 'JetBrains Mono', monospace; font-weight: 700; font-size: 13px; letter-spacing: 0.14em; word-spacing: -0.3em; text-transform: uppercase; color: var(--text); }
.brand-logo:focus-visible { outline: 1px solid var(--border2); outline-offset: 3px; border-radius: 3px; }
.topbar-back, .topbar-link { color: var(--text2); text-decoration: none; letter-spacing: 0.12em; transition: color 0.2s; }
.topbar-back:hover, .topbar-back:focus-visible, .topbar-link:hover, .topbar-link:focus-visible { color: var(--text); }
.topbar-back:focus-visible, .topbar-link:focus-visible { outline: 1px solid var(--border2); outline-offset: 3px; }
/* The top bar's site nav (render.js head): the page's back link, then Stocks and Crypto (topbarSections). Nothing in the
   header shrinks ("header rows" below), so the stock pages' ticker box keeps its width. Lockstep: the same rules in every
   static page with the header. */
.topbar-nav { display: flex; align-items: center; gap: 20px; }
.topbar-nav > * { flex: 0 0 auto; }
.topbar-link[aria-current="page"] { color: var(--text); }
@media (max-width: 600px) { .topbar-nav { gap: 14px; } }
/* ── header rows: start (site/test/header.test.mjs) ──
   Desktop: one row; the brand on the left, then the page's own element and the site nav. Phones: row 1 is the brand,
   never wrapped or shrunk, and the page's own element (the live read, or the ticker box); the site nav (the back link,
   Stocks, Crypto) is a slim second row under it, full width, left-aligned, with a hairline above. */
.page-header { flex-wrap: wrap; column-gap: 20px; }
.page-header > * { flex: 0 0 auto; }
.brand-logo { margin-right: auto; }
.brand-wordmark { white-space: nowrap; }
@media (max-width: 600px) {
  .page-header { padding-bottom: 0; column-gap: 14px; }
  .page-header > .topbar-nav { order: 3; flex: 0 0 100%; height: 30px; margin-top: 16px; border-top: 1px solid var(--border); }
}
/* Above the phones, a header with a back link (the brand, the search box, the back link, Stocks, Crypto) needs about
   680px of viewport for one row (scripts/check-header.mjs, 2026-09-27: every header has the box); below 720px it takes
   the phones' two rows. A header without a back link (the stock and coin pages, the indexes, home) keeps one row. */
@media (min-width: 601px) and (max-width: 720px) {
  .page-header:has(.topbar-back) { padding-bottom: 0; column-gap: 14px; }
  .page-header:has(.topbar-back) > .topbar-nav { order: 3; flex: 0 0 100%; height: 30px; margin-top: 16px; border-top: 1px solid var(--border); gap: 14px; }
}
/* ── header rows: end ── */
/* The header's search box (render.js quickFindForm; the same markup in every static page's header since 2026-09-27): a small box and an arrow button in the header's right
   slot, sized so the header stays one line at 390px beside the brand and the title does not move noticeably.
   124px on desktop: "stock or coin" (88.7px at 11px) + Chrome's datalist indicator (14.7px, a flex item inside the
   box, in the layout even while transparent) + 16px padding + 2px border (scripts/check-search-boxes.mjs). */
.quick-find { display: flex; align-items: stretch; gap: 4px; }
.quick-input { width: 124px; padding: 5px 8px; border: 1px solid var(--border2); border-radius: 4px; background: var(--bg2); color: var(--text); font-family: 'JetBrains Mono', monospace; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; -webkit-appearance: none; appearance: none; transition: border-color 0.2s; }
.quick-input::placeholder { color: var(--text3); text-transform: none; letter-spacing: 0.02em; }
.quick-input:focus { outline: none; border-color: var(--text3); }
.quick-input:focus-visible { outline: 1px solid var(--border2); outline-offset: 2px; }
.quick-btn { padding: 0 9px; border: 1px solid var(--border2); border-radius: 4px; background: var(--bg3); color: var(--text2); font-family: 'JetBrains Mono', monospace; font-size: 12px; line-height: 1; cursor: pointer; -webkit-appearance: none; appearance: none; transition: color 0.2s, border-color 0.2s; }
.quick-btn:hover, .quick-btn:focus-visible { color: var(--text); border-color: var(--text3); }
.quick-btn:focus-visible { outline: 1px solid var(--border2); outline-offset: 2px; }
@media (max-width: 600px) { .quick-input { width: 96px; font-size: 16px; padding: 3px 7px; letter-spacing: 0.04em; } .quick-input::placeholder { font-size: 10px; letter-spacing: 0; } .quick-input::-webkit-calendar-picker-indicator { display: none !important; } .quick-btn { font-size: 13px; } } /* 16px: no iOS zoom on focus; 96px: sized when the Crypto link shared this row at 360px (since the second header row, 2026-09-27, row 1 has 58px spare at 360px, scripts/check-header.mjs, so the box could now grow and show the indicator); the placeholder ("stock or coin", copy.js SEARCH.placeholderShort) at 10px so all of it shows in that width (78px of 80px); Chrome's datalist indicator hidden here only, because at 16px it takes 21.4px of the 80px (the list still opens on tap and typing; scripts/check-search-boxes.mjs); !important because Chrome's own sheet sets its display !important */
/* The home page's box (quickFindForm compactOnly): only in the compact header, so the full header keeps the live read. */
.quick-find[data-compact-only] { display: none; }

/* ── The sticky header (feat/sticky-header, 2026-09-27). Everything below applies only under <html data-header="sticky">,
   which the workers set from ONE value, the STICKY_HEADER var (site/header.js): off, the header is exactly as before.
   Without JavaScript the header sticks at full size. /lib/header.js adds html.hdr-compact once the page has scrolled
   past the full header, and takes it off when the full header is back in view: one slim 44px row at every width (the
   mark, on a stock or coin page the symbol and today's regime, the search box, Stocks, Crypto). The full header's
   height stays reserved in the flow (--hdr-reserve, a bottom margin measured by the script), so nothing below it moves.
   --hdr-offset: the height a page's own sticky parts sit under (the ranking table's header row, the sector jump
   list) and anchor jumps clear: the full header's without JavaScript, 44px when compact, 0 with the switch off. ── */
html[data-header="sticky"] { --hdr-offset: 55px; scroll-padding-top: calc(var(--hdr-offset) + 8px); }
/* Every static page sets body { overflow-x: hidden }, which makes <body> a scroll container, and a sticky header inside
   one never sticks. clip stops sideways scroll the same way without that (stocks.css has used it since the sticky sector
   list). A browser without clip (Safari before 16) keeps hidden: the header just does not stick there. */
html[data-header="sticky"] body { overflow-x: clip; }
html[data-header="sticky"].hdr-compact { --hdr-offset: 44px; }
/* The bar sticks with its row 12px under the top edge; its own top padding goes out of view first. Until it pins, only
   the row has a background (the column, as always); pinned (html.hdr-pinned, the script), the bar's background and its
   bottom rule run edge to edge, so nothing scrolls past on either side. */
html[data-header="sticky"] .site-header { position: sticky; top: calc(12px - var(--col-pad-top)); z-index: 20; padding-top: calc(var(--col-pad-top) - 12px); }
html[data-header="sticky"] .page-header { background: var(--bg); padding-top: 12px; }
html[data-header="sticky"].hdr-pinned .site-header { background: var(--bg); box-shadow: inset 0 -1px 0 var(--border); }
.hdr-here, .hdr-search-btn, .quick-close { display: none; }
html[data-header="sticky"].hdr-swap .page-header > * { visibility: hidden; } /* one frame while the layout changes (/lib/header.js) */
/* compact: only the row changes (44px); the bar keeps its padding and its sticky offset, so the row keeps its place in the
   bar and nothing counts as moved (a layout shift is judged on layout positions, not on screen) */
html[data-header="sticky"].hdr-compact .site-header { margin-bottom: var(--hdr-reserve, 0px); }
html[data-header="sticky"].hdr-compact .page-header { height: 44px; padding-top: 0; padding-bottom: 0; flex-wrap: nowrap; column-gap: 16px; }
html[data-header="sticky"].hdr-compact .brand-wordmark,
html[data-header="sticky"].hdr-compact .topbar-back,
html[data-header="sticky"].hdr-compact .header-status { display: none; }
html[data-header="sticky"].hdr-compact .quick-find[data-compact-only] { display: flex; }
html[data-header="sticky"].hdr-compact .page-header > .topbar-nav { order: 0; flex: 0 0 auto; height: auto; margin-top: 0; border-top: 0; }
/* a stock or coin page: "NVDA · Mildly Off" beside the mark (render.js head here), the regime word in its AA colour */
html[data-header="sticky"].hdr-compact .hdr-here {
  display: inline-flex; align-items: baseline; gap: 7px; margin-right: auto; min-width: 0; white-space: nowrap;
  font-family: 'JetBrains Mono', monospace; font-size: 11px; letter-spacing: 0.08em; color: var(--text3);
}
html[data-header="sticky"].hdr-compact .hdr-regime { display: inline-flex; align-items: baseline; gap: 7px; }
html[data-header="sticky"].hdr-compact .hdr-here strong { color: var(--text); font-weight: 700; }
html[data-header="sticky"].hdr-compact .page-header:has(.hdr-here) .brand-logo { margin-right: 0; }
/* The magnifier and the close button: the stroke icons of the home card (share, email), a 44px square to tap. */
.hdr-search-btn, .quick-close {
  align-items: center; justify-content: center; flex: 0 0 auto; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 4px;
  background: none; color: var(--text2); cursor: pointer; -webkit-appearance: none; appearance: none; transition: color 0.2s;
}
.hdr-search-btn:hover, .hdr-search-btn:focus-visible, .quick-close:hover, .quick-close:focus-visible { color: var(--text); }
.hdr-search-btn:focus-visible, .quick-close:focus-visible { outline: 1px solid var(--border2); outline-offset: -6px; }
@media (max-width: 600px) {
  html[data-header="sticky"] { --hdr-offset: 88px; }
  html[data-header="sticky"].hdr-compact { --hdr-offset: 44px; }
  html[data-header="sticky"].hdr-compact .page-header { column-gap: 12px; }
  /* the compact box: its whole placeholder, with room to spare for a wider rendering (Safari drew "stock or co:" at 96px) */
  html[data-header="sticky"].hdr-compact .quick-input { width: 112px; }
  /* a stock or coin page: the symbol and regime take the box's place, and the magnifier opens the box over the row
     (the mark stays): focused, with its close button; Escape, the close button or a search closes it (/lib/header.js) */
  html[data-header="sticky"].hdr-compact .page-header:has(.hdr-here) > .quick-find { display: none; }
  html[data-header="sticky"].hdr-compact .hdr-search-btn { display: inline-flex; margin: 0 -10px; }
  html[data-header="sticky"].hdr-compact.hdr-search-open .page-header:has(.hdr-here) > .quick-find { display: flex; flex: 1 1 auto; min-width: 0; align-items: center; }
  html[data-header="sticky"].hdr-compact.hdr-search-open .page-header:has(.hdr-here) :is(.quick-input, .quick-btn) { height: 32px; } /* the close button keeps its 44px to tap */
  html[data-header="sticky"].hdr-compact.hdr-search-open .page-header:has(.hdr-here) .quick-input { flex: 1 1 auto; width: auto; min-width: 0; }
  html[data-header="sticky"].hdr-compact.hdr-search-open .quick-close { display: inline-flex; margin-right: -10px; }
  html[data-header="sticky"].hdr-compact.hdr-search-open .hdr-here,
  html[data-header="sticky"].hdr-compact.hdr-search-open .hdr-search-btn,
  html[data-header="sticky"].hdr-compact.hdr-search-open .page-header:has(.hdr-here) > .topbar-nav { display: none; }
}
/* the narrowest phones: the symbol alone, never clipped (the row: mark, symbol, magnifier, Stocks, Crypto) */
@media (max-width: 380px) { html[data-header="sticky"].hdr-compact .hdr-regime { display: none; } }
