/* =====================================================================
   FOW site chrome — the parts every page shares, paid or free.
   Lives in public/shared/ (ungated) per docs/fow_web/decisions/002-site-structure.md
   rule 1: the menu, the theme and the layout are not the product.

   Dark-first. The variables below ARE the dark theme; the
   :root[data-theme="light"] block overrides them, so any page that links
   this file adopts the site theme cookie without restyling.

   Contains ONLY chrome: colour tokens, reset, .wrap, header/nav, the auth
   widget, .card/.grid/.pill, buttons and the footer. Anything a single page
   needs stays in that page's own <style> block.
   ===================================================================== */

/* ── tokens ─────────────────────────────────────────────── */
:root{
  --bg:#0d0d0f; --panel:#17171a; --panel2:#1e1e22; --border:#2a2a2e;
  --text:#f2f2f4; --muted:#9a9aa0; --accent:#4ea1ff;
  --green:#26d07c; --red:#ff5b5b; --gold:#f5c842; --orange:#f2a93b;
  --shadow:0 10px 30px rgba(0,0,0,.35);
}
:root[data-theme="light"]{
  --bg:#f4f5f7; --panel:#ffffff; --panel2:#eef0f3; --border:#d8dbe0;
  --text:#1c2128; --muted:#6b7280; --accent:#1f6fe0;
  --green:#1a9f54; --red:#d83a3a; --gold:#b8860b; --orange:#f2a93b;
  --shadow:0 10px 24px rgba(0,0,0,.10);
}

/* ── reset + base ───────────────────────────────────────── */
*{box-sizing:border-box;margin:0;padding:0}
body{background:var(--bg);color:var(--text);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Helvetica,Arial,sans-serif;
  -webkit-font-smoothing:antialiased;line-height:1.5}
a{color:inherit;text-decoration:none}

/* ── TWO WIDTHS, EACH SET IN ONE PLACE ───────────────────────────────────────
   --page-app   dashboards and tools. Wide, because they are grids of numbers.
   --page-read  landing, editorial, sign-in, prose. Narrow, because they are
                sentences, and a sentence 1900px wide is ~200 characters a line.

   Change either here and the header, the second-level nav and page content move
   together. Before 6 Sep 2026 they did not: an app page's header sat at 1560px,
   the nav below it at 1900px and its content at 1120px — three edges stacked
   vertically, none aligned. Six pages then set their own max-width on top of
   that (1900, 1500, 1400, 1320, 1180, 900), inherited from the legacy
   stylesheets they were migrated from.

   1900px matches the home page, the reference the rest were asked to follow.

   .wrap KEEPS ITS 1120px. It is shared chrome: public/index.html, the Shastra
   articles, signin and upgrade all use it, and those are reading pages. An
   earlier draft of this change pointed .wrap at the app width and would have
   stretched the landing hero and every article to full width. An app page opts
   IN with .wrap-wide instead, which is the direction that cannot damage a page
   by forgetting about it. */
:root{
  --page-app:1900px;
  --page-read:1120px;
  /* The horizontal inset every wrapper uses. It has to be ONE value or the
     chrome cannot line up with the content: the bar was inset 16px by a
     legacy stylesheet while .homewrap used 14px, and the brand sat two
     pixels off the content on every page that links alpha.css. */
  --page-pad:16px;
}

/* The default is the READING width. Anything that does not ask is prose. */
.wrap{max-width:var(--page-read);margin:0 auto;padding:0 var(--page-pad)}
/* Dashboards and tools opt in. Every gated page carries this on both its header
   and its content wrapper, so the two share an edge. */
.wrap-wide{max-width:var(--page-app)}
.wrap-full{max-width:none;padding:0 var(--page-pad)}

/* ── header ─────────────────────────────────────────────── */
/* SELECTED BY CLASS, and this is the third time a bare selector here has
   collided with page CSS — after .wrap (#531) and .bar (#539). This one ran the
   other way: the PAGE's bare `header{}` rule reaching the SITE chrome.

   Five migrated pages carry their own header rule, four saying `z-index:5`.
   Equal specificity, page style loads later, so the page won — and that rule
   landed on BOTH headers, the site chrome and the page's own title bar. Two
   sticky headers at the same z-index: the later one in the DOM paints on top,
   and the dropdown lives in the earlier one. On sector-heatmap the Themes panel
   was sliced in two, with a 48px band of title bar painted through the middle.
   The same rule also gave the chrome `display:flex;padding:10px 14px`, which is
   why it measured 116px instead of 62px there.

   `header.fow-hd` is (0,1,1) against a page's (0,0,1), which no load order can
   undo. display/margin/padding are re-asserted because they are the UA defaults
   a page's flex rule was overriding — on the other 39 pages they change nothing.

   Nothing lost by scoping: every page with a second <header> defines its own
   header{} rule, so none of them was relying on this one. Checked, not assumed. */
header.fow-hd{position:sticky;top:0;z-index:50;display:block;margin:0;padding:0;
  background:color-mix(in srgb,var(--bg) 88%,transparent);
  backdrop-filter:saturate(160%) blur(10px);border-bottom:1px solid var(--border)}
/* SCOPED TO .wrap.bar, and this is not cosmetic. `.bar` is a name a content
   element can reasonably want, and four migrated pages already use it for a
   thin measure bar: the heatmap's market-cap line, the two ops sparklines, and
   live.html's CE/PE strength bars. A bare `.bar` here reached all of them and
   inflated each to 62px — and `min-height` is a DIFFERENT PROPERTY from the
   `height` those pages set, so it could not be overridden by specificity or by
   load order. The heatmap's 3px line at the bottom of each tile became a pale
   slab up the left edge, which is how this was noticed (6 Sep 2026).
   Every header in the tree is `class="wrap ... bar"` — 43 of them, none
   otherwise — so scoping loses no header and reaches no page content. */
.wrap.bar{display:flex;align-items:center;flex-wrap:wrap;gap:10px 18px;
  min-height:62px}
/* TWO CLASSES ON PURPOSE. The header is `class="wrap wrap-wide bar"`, and
   alpha.css also styles .wrap — with `padding:0 16px 64px`, a bottom inset
   meant for a CONTENT wrapper. It loads after site.css, so a single-class
   .bar rule loses to it on source order and the header grew from 62px to 99px
   wearing content spacing. .wrap.bar outranks .wrap on specificity, which no
   load order can undo. */
.wrap.bar{padding-top:8px;padding-bottom:8px}
/* height was FIXED at 62px with nowrap. Once the top row grew — Home and
   Calendar were added on 24 Aug — its contents stopped fitting, and a flex row
   that does not wrap centres its overflow: the content spilled equally above
   and below the box. The header is pinned at top:0, so everything above the
   viewport edge was simply gone, and the header read as cut off at the top
   while the row below it looked fine.
   min-height + wrap lets it grow instead. Nothing can spill upward now. */
#auth{min-width:0}
.fow-who{min-width:0}
/* The email is the one unbounded string in the header — a long address would
   push Sign out off the edge on its own. */
.fow-email{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:22ch}

/* FULL-BLEED HEADER over a page that pads its own body.
   The migrated legacy pages carry body{padding:18px} from their own stylesheet,
   which inset the site header and the second-level row: their backgrounds
   stopped short of both edges and read as a header cut off rather than a band
   across the top.

   The bleed is applied by nav.js, not here, because it has to equal the body's
   padding EXACTLY and CSS cannot read that. The obvious pure-CSS version,
   margin-left:calc(50% - 50vw), is wrong: 50vw includes the scrollbar, so it
   overshoots by half a scrollbar on each side and manufactures horizontal
   overflow on any page that did not already have it. */
body > header[style]{max-width:none}
.brand{display:flex;align-items:center;gap:10px;font-weight:700;letter-spacing:-.3px;font-size:16.5px}
/* BETA badge, on the brand of every page — including any page migrated later,
   which is why it lives here rather than in each header's markup. There are
   eighteen of those and no way to be sure a nineteenth would remember.

   ::after content is not selectable and reads as decoration to most screen
   readers. That is the right call for a status label: it should not land in the
   middle of a copied page title, and it is not information anyone navigating by
   voice needs from the site's home link. Delete these three rules to end Beta. */
.brand::after{content:"Beta";font-size:9.5px;font-weight:700;letter-spacing:.9px;
  text-transform:uppercase;color:var(--red);border:1px solid var(--red);
  border-radius:999px;padding:2px 6px;line-height:1;
  /* the brand is flex with gap:10px, which would double-space this */
  margin-left:-2px;align-self:center;white-space:nowrap}
@media(max-width:560px){.brand::after{display:none}}
.mark{width:30px;height:30px;display:block;flex:0 0 30px}
nav{display:flex;align-items:center;gap:4px;margin-left:12px}
nav a{padding:7px 11px;border-radius:7px;font-size:13.5px;color:var(--muted);white-space:nowrap}
nav a:hover{background:var(--panel2);color:var(--text)}
nav a .lock{font-size:10px;opacity:.65;margin-left:5px}
nav a[data-locked="true"]{color:var(--muted)}
nav a[aria-current="page"]{color:var(--text);background:var(--panel2)}
.spacer{flex:1}

/* ── auth widget ───────────────────────────────────────── */
#auth{display:flex;align-items:center;gap:9px;position:relative}
.fow-btn{display:inline-flex;align-items:center;gap:8px;padding:8px 15px;border-radius:8px;
  background:var(--accent);color:#06121f;font-size:13.5px;font-weight:650;
  border:1px solid transparent;cursor:pointer;white-space:nowrap}
.fow-btn:hover{filter:brightness(1.08)}
.fow-btn-quiet{background:transparent;color:var(--muted);border-color:var(--border);font-weight:550}
.fow-btn-quiet:hover{color:var(--text);border-color:var(--muted);filter:none}
.fow-btn-soon{background:var(--panel2);color:var(--text);border-color:var(--border)}
.fow-btn-skeleton{background:var(--panel2);border-color:var(--border);width:96px;height:35px;
  opacity:.5;animation:pulse 1.4s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:.35}50%{opacity:.6}}
.fow-g{width:17px;height:17px;border-radius:50%;background:#fff;color:#4285F4;
  display:grid;place-items:center;font-size:11.5px;font-weight:800;font-family:Arial,sans-serif}
.fow-avatar{width:28px;height:28px;border-radius:50%;background:var(--accent);color:#06121f;
  display:grid;place-items:center;font-size:12.5px;font-weight:700}
.fow-who{display:flex;flex-direction:column;line-height:1.25}
.fow-email{font-size:12.5px}
.fow-tier{font-size:10.5px;color:var(--muted);text-transform:uppercase;letter-spacing:.7px}
.fow-note{position:absolute;top:44px;right:0;background:var(--panel);border:1px solid var(--border);
  border-radius:8px;padding:8px 12px;font-size:12.5px;color:var(--muted);box-shadow:var(--shadow);
  opacity:0;transform:translateY(-4px);pointer-events:none;transition:.18s;white-space:nowrap}
.fow-note.on{opacity:1;transform:none}

/* ── cards ─────────────────────────────────────────────── */
.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(250px,1fr))}
.card{display:block;background:var(--panel);border:1px solid var(--border);border-radius:12px;
  padding:20px;transition:.16s;position:relative;overflow:hidden}
.card:hover{border-color:var(--muted);transform:translateY(-2px);box-shadow:var(--shadow)}
.card h3{font-size:15.5px;font-weight:650;margin-bottom:7px;display:flex;align-items:center;gap:8px}
.card p{font-size:13.2px;color:var(--muted);line-height:1.55}
.card .glyph{font-size:19px;line-height:1}
.pill{font-size:10px;font-weight:700;letter-spacing:.8px;text-transform:uppercase;
  padding:3px 8px;border-radius:20px;margin-left:auto}
.pill-free{background:#15803d;color:#fff}
.pill-lock{background:rgba(154,154,160,.14);color:var(--muted)}
.card[data-locked="true"]{opacity:.82}
.card[data-locked="true"]:hover{opacity:1}

/* ── buttons ───────────────────────────────────────────── */
.cta{display:flex;gap:12px;margin-top:30px;flex-wrap:wrap}
.cta a{padding:12px 20px;border-radius:9px;font-size:14.5px;font-weight:600}
.cta .primary{background:var(--text);color:var(--bg)}
.cta .ghost{border:1px solid var(--border);color:var(--text)}
.cta .ghost:hover{border-color:var(--muted)}

/* ── "members area opens shortly" toast, raised by FOWAuth.guard ── */
#fow-soon-banner{position:fixed;left:50%;bottom:28px;transform:translate(-50%,10px);
  background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:12px 18px;
  font-size:13.5px;color:var(--text);box-shadow:var(--shadow);opacity:0;pointer-events:none;
  transition:.2s;z-index:80}
#fow-soon-banner.on{opacity:1;transform:translate(-50%,0)}

/* ── footer ────────────────────────────────────────────── */
footer{border-top:1px solid var(--border);margin-top:40px;padding:28px 0 44px;
  color:var(--muted);font-size:12.5px;display:flex;gap:20px;flex-wrap:wrap;align-items:center}
footer a:hover{color:var(--text)}
footer .sep{flex:1}

@media (max-width:760px){
  nav{display:none}
  .fow-who{display:none}
}

@media print{
  header,footer,#fow-soon-banner{display:none}
}


/* ── navigation menus (nav.js) ───────────────────────────
   Replaces the old menu.js dropdowns. Panels are absolutely positioned so a
   long category list never pushes the header around. */
/* Icon links: the svg takes currentColor, so it hovers with the text. */
.fow-ico{display:inline-flex;align-items:center;gap:6px}
.fow-ico svg{display:block;flex:none}

.fow-menu{position:relative;display:inline-block}
.fow-menu-btn{background:none;border:0;color:inherit;font:inherit;cursor:pointer;
  padding:6px 2px;opacity:.85}
.fow-menu-btn:hover,.fow-menu.open .fow-menu-btn{opacity:1;color:var(--accent)}
.fow-menu-btn::after{content:"\25be";margin-left:5px;font-size:10px;opacity:.7}
.fow-menu-panel{display:none;position:absolute;top:100%;left:0;z-index:60;
  min-width:210px;background:var(--panel);border:1px solid var(--border);
  border-radius:9px;box-shadow:var(--shadow);padding:7px;margin-top:6px}
.fow-menu.open .fow-menu-panel{display:block}
.fow-menu-panel>a{display:block;padding:7px 10px;border-radius:6px;font-size:13.5px;
  white-space:nowrap;color:var(--text)}
.fow-menu-panel>a:hover{background:var(--panel2);color:var(--accent)}
.fow-menu-panel>a[aria-current]{color:var(--accent)}

/* THE ONE ROW. Until 6 Sep 2026 the menu lived on a second bar below the
   header, centred, at a different width from both the header above it and the
   content below. Now it sits inside #nav in the single header row.

   The row is CENTRED as a block at the content width, and its contents are
   LEFT-ALIGNED within it — brand hard left, menu straight after it, identity
   pushed right by .spacer. So the brand shares a left edge with the page's
   content, which is the alignment that was missing. */
#nav{display:flex;flex-wrap:wrap;align-items:center;gap:2px 4px;
  min-width:0;
  /* A half-height rule between the brand and the menu. They are different
     things — one is the product, the other is where you go in it — and with
     nothing between them the first menu item read as part of the wordmark.
     Drawn as a border on #nav rather than an extra element, so no page markup
     changes and it cannot end up on a wrapped second line by itself. */
  border-left:1px solid var(--border);
  margin-left:16px;padding-left:16px;
  align-self:center;min-height:26px}
#nav .fow-menu-btn{padding:8px 8px;font-size:12.8px}
/* Plain links among dropdown buttons: without matching padding, Home and
   Calendar sit tight against each other while the buttons breathe. */
#nav > a{padding:8px 8px;font-size:12.8px;border-radius:8px;color:var(--muted)}
#nav > a:hover{background:var(--panel2);color:var(--accent)}
#nav > a[aria-current="page"]{color:var(--text);background:var(--panel2)}
/* The boundary marker between the built-in links and the generated sections.
   It is a real node so the async insert needs no index arithmetic; it must take
   no space. */
.fow-nav-mark{display:none}
/* IDENTITY STAYS RIGHT, ON THE FIRST LINE.
   The header markup carries <span class="spacer"> with flex:1 between the nav
   and #auth. On a row that wraps, that spacer grows to fill the whole first
   line and pushes #auth onto a second one — where it lands hard LEFT, under the
   brand, which is the opposite of what it is for. Seen immediately in the
   harness; it is not visible from reading the rule.
   margin-left:auto does the same job without claiming space of its own, so the
   nav can wrap to a second line while identity stays where it belongs. The
   spacer is neutralised here rather than deleted from 31 pages' markup. */
.wrap.bar > .spacer{display:none}
.wrap.bar > #auth{margin-left:auto}
/* When nav.js has drawn the theme switch (gated plane), it moves #auth into one
   .fow-right group with the switch, so a header that wraps on a laptop keeps both
   controls together on the right instead of stranding the switch at the end of the
   menu row and Sign in on a row of its own (13 Sep 2026). Two flex items cannot be
   kept together by CSS alone once the row wraps; a wrapper can. */
.wrap.bar > .fow-right{margin-left:auto;display:flex;align-items:center;gap:10px}
/* Panels hang off a row that can wrap to two lines on a laptop, so cap them and
   let the last few open leftwards rather than off the right edge. */
#nav .fow-menu-panel{max-height:70vh;overflow-y:auto}
#nav .fow-menu:nth-last-child(-n+3) .fow-menu-panel{left:auto;right:0}
.fow-menu-head{font-size:10.5px;letter-spacing:.8px;text-transform:uppercase;
  color:var(--muted);padding:8px 10px 4px}
.fow-menu-sep{height:1px;background:var(--border);margin:5px 8px}
/* Sign out is icon-only — square, so it does not read as a truncated button. */
.fow-signout{padding:8px;line-height:0}
/* Same square, icon-only shape as sign out — they sit next to each other and
   a different size would read as a different KIND of control. */
.fow-theme{padding:8px;line-height:0}
/* STOCK SEARCH (nav.js, 16 Sep 2026). Sits in .fow-right ahead of the theme
   switch, so it travels with the account controls when the header wraps. The
   list is absolutely positioned under the box and opens to the LEFT edge of
   the box's right side — the box is near the right of the viewport, so a
   left-anchored panel wider than the box would run off the page. */
.fow-search{position:relative;flex:0 1 200px;min-width:120px}
.fow-search-in{width:100%;box-sizing:border-box;background:var(--panel2);color:var(--text);
  border:1px solid var(--border);border-radius:8px;padding:6px 10px;font:inherit;font-size:12.8px;
  outline:none;-webkit-appearance:none;appearance:none}
.fow-search-in::placeholder{color:var(--muted)}
.fow-search-in:focus{border-color:var(--accent)}
.fow-search-in::-webkit-search-cancel-button{-webkit-appearance:none}
.fow-search-list{display:none;position:absolute;top:100%;right:0;z-index:61;min-width:280px;
  max-height:60vh;overflow-y:auto;margin-top:6px;padding:6px;background:var(--panel);
  border:1px solid var(--border);border-radius:9px;box-shadow:var(--shadow)}
.fow-search-list.open{display:block}
.fow-search-row{display:flex;justify-content:space-between;align-items:baseline;gap:14px;
  padding:7px 10px;border-radius:6px;cursor:pointer;font-size:13px;color:var(--text)}
.fow-search-row:hover,.fow-search-row.sel{background:var(--panel2);color:var(--accent)}
.fow-search-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fow-search-code{flex:none;font-size:11px;color:var(--muted);letter-spacing:.3px}
@media(max-width:700px){
  .fow-search{flex-basis:140px}
}
@media(max-width:700px){
  #nav{margin-left:8px;gap:2px}
  #nav .fow-menu-btn,#nav > a{padding:7px 8px;font-size:12.5px}
}
@media (max-width:760px){
  .fow-menu-panel{min-width:180px}
}
