/* =====================================================================
   DATA PAGE TEMPLATE — canonical chrome for any module that lists data
   with filters (bookshelf, newsletters, future gameshelf/projects/...).

   This file IS the component. docs/design-system.md references it and
   deliberately does not duplicate the values: change it here, and every
   data page changes together.

   Required skeleton:

     <header class="site-header">
       <div class="masthead">
         <div class="masthead-text">
           <pre class="ascii-banner">...</pre>
           <p class="connect-line">...</p>
           <p class="menu-back"><a href="/petermarnef/">
             <span class="key-hint">[ESC]</span> back home</a></p>
           <p class="site-tagline">counts / subtitle</p>
         </div>
         <!-- optional right side: .controls with search/sort -->
       </div>
       <div class="toolbar"> tab-bars, selects, chips </div>
     </header>
     <main>...</main>

   Module CSS must still set:
     - :root { --page-max: ...; } (content width)
     - .ascii-banner { font-size: min(16px, calc((100vw - 2.5rem) / N)); }
       where N = banner char width * 0.6 (see design-system.md §1.5)
     - main padding (top spacing below the divider is module-specific)
   ===================================================================== */

/* ---------- Header ---------- */

.site-header {
  padding: 2.25rem 2rem 0.75rem;
  max-width: var(--page-max);
  margin: 0 auto;
}

.masthead {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem 2rem;
  margin-bottom: 1.5rem;
}

.masthead-text { position: relative; }

.ascii-banner {
  font-family: var(--mono);
  line-height: 1.15;
  margin: 0;
  color: var(--accent);
  text-shadow: 0 0 2px rgba(138, 176, 221, 0.55);
}

.connect-line {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--text-faint);
  margin: 0.4rem 0 0.1rem;
}

.menu-back { margin: 0.35rem 0 0; font-size: 0.78rem; font-family: var(--mono); }
.menu-back a { color: var(--text-faint); text-decoration: none; }
.menu-back a:hover { color: var(--accent); }
.menu-back .key-hint { color: var(--accent); font-weight: 700; }

.site-tagline {
  font-family: var(--mono);
  margin: 0.35rem 0 0;
  font-size: 0.78rem;
  color: var(--text-muted);
}

/* ---------- Toolbar: filters row, closed off by the header divider ----- */

.toolbar {
  display: flex;
  flex-wrap: wrap;
  /* Every control fills the row height (top AND bottom aligned):
     selects, inputs and tab bars all stretch to the tallest one. */
  align-items: stretch;
  gap: 0.75rem 1rem;
  padding-bottom: 0.85rem;
  border-bottom: 1px dashed var(--border);
}

/* Text-only toolbar items don't stretch — they center on the row. */
.toolbar-meta, .feed-note { align-self: center; }

.tab-bar {
  display: inline-flex;
  flex-wrap: wrap;
  /* longhand: the background shorthand would wipe the .crt-light lines */
  background-color: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 0.2rem;
  gap: 0.15rem;
}

.tab {
  font: inherit;
  font-size: 0.85rem;
  line-height: 1.5;
  border: none;
  background: transparent;
  color: var(--text-muted);
  padding: 0.35rem 0.9rem;
  border-radius: 5px;
  cursor: pointer;
  white-space: nowrap;
}

.tab:hover { color: var(--text); }

/* Keyboard focus = hover, plus an inset ring: the hover color change
   alone is too subtle to mark the roving stop (keynav.js) in a bar. */
.tab:focus-visible {
  color: var(--text);
  outline: 1px solid var(--accent);
  outline-offset: -1px;
}

.tab.active {
  background: var(--accent);
  color: var(--bg-elevated);
  font-weight: 600;
}

.tab-count {
  font-size: 0.72rem;
  opacity: 0.75;
  margin-left: 0.15rem;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

.search-input {
  font: inherit;
  font-size: 0.85rem;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 5px;
  background-color: var(--bg-elevated);
  color: var(--text);
  min-width: 13rem;
  max-width: 100%;
}

.search-input:focus {
  outline: none;
  border-color: var(--accent);
}

.sort-select {
  font: inherit;
  font-size: 0.85rem;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 5px;
  background-color: var(--bg-elevated);
  color: var(--text-muted);
  cursor: pointer;
}

/* <select> and <input> ignore flex stretch in some browsers.
   Explicit height = tab-bar's natural single-row height (border 2px +
   padding 2×0.2rem + button padding 2×0.35rem + font 0.85rem×1.5
   = 2.5rem). Tab-bars that wrap (category chips) grow taller. */
.toolbar .search-input,
.toolbar .sort-select {
  height: 2.5rem;
}

/* Toolbar surfaces carry .crt-light (theme.css): lifted above the
   page CRT (z-index 11) with their own lighter scanlines so the
   toolbar reads as an elevated panel, visibly distinct from the full-
   strength page background. Never use the background shorthand on
   these — it wipes background-image from .crt-light. */

/* Right-aligned meta line in the toolbar (bookshelf's SYNCED status,
   newsletters' edition date): one size, no letter-spacing, faint. */
.toolbar-meta {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--text-faint);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.5rem;
}
.toolbar-meta[hidden] { display: none; }

/* ---------- Shared states ---------- */

.loading, .empty-state {
  font-family: var(--mono);
  color: var(--text-faint);
  padding: 3rem 0;
  text-align: center;
}

/* Single reveal: while a module is fetching its data (body.pre-reveal,
   set in the HTML), the page is blank except the loading line — no
   half-empty toolbar chrome, no layout jump. The module JS removes the
   class after its first render (success OR error) so the whole page
   appears in one paint. visibility (not display) keeps the layout
   stable so the loading line doesn't move on reveal. */
.pre-reveal .site-header { visibility: hidden; }

/* Failed data load: filters, search, sort and counts are meaningless
   without data. The module JS sets body.data-failed next to its error
   empty-state; only the banner, connect line and [ESC] home remain. */
.data-failed .site-tagline,
.data-failed .controls,
.data-failed .toolbar { display: none; }

/* Terminal status lines: loading AND empty/error states share one look —
   accent "> " prompt, uppercase letter-spaced text. Deliberately no
   spinner/cursor suffix (dropped on feedback): the line is quiet, the
   single reveal does the work. */
.loading,
.empty-state {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.78rem;
}
.loading::before,
.empty-state::before {
  content: "> ";
  color: var(--accent);
  font-weight: 700;
}

@media (max-width: 640px) {
  .site-header { padding: 1.5rem 1.25rem 0.5rem; }
}
