/* ============================================================
   StudyGPT — shared shell
   ============================================================
   Linked by every page in this folder: index.html, terms.html and
   privacy.html. Holds the design tokens, the base reset and the
   whole navbar + phone menu — i.e. exactly the things all three
   have in common and nothing else.

   ⚠️ This file exists because the navbar used to be inlined in
   index.html and copied again into legal.css, so a nav change had
   to be made twice and nothing would complain if it were made once.
   Extracted 2026-09-03. **Do not re-inline it.**

   ⚠️ index.html is therefore no longer a single standalone file.
   docs/08 §11 said it was, and that is now this stylesheet plus
   the document. Anything that copies the page elsewhere — the
   Artifact route in §11 — has to inline this too.

   Page-specific CSS stays with its page: the landing page keeps its
   own <style> for the hero, band, features and footer; the legal
   pages keep legal.css. Nothing that only one page uses belongs
   here.
   ============================================================ */

:root {
  /* Canvas ------------------------------------------------- */
  --canvas: #F7F7F7;
  --ink:    #101010;
  /* Muted type on the dark band. Kept a touch above mid-grey so it
     still reads as text rather than as a disabled state. */
  --dim:    #8C8C8C;

  /* The nav is painted in this, NOT in black. See .site-header. */
  --nav-ink: #EFEFEF;

  /* Type --------------------------------------------------- */
  --display: "Sofia Sans Condensed", "Arial Narrow", sans-serif;
  --mono:    "Spline Sans Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Layout ------------------------------------------------- */
  --gutter: 40px;
  --nav-h:  86px;

  /* Motion ------------------------------------------------- */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  /* The reference's own curve for the feature accordion. Kept separate
     from `--ease-out-expo` rather than folded into it: this one starts
     fast and coasts, which is what makes a panel feel like it is being
     pushed open rather than easing into place. */
  --ease-accordion: cubic-bezier(0.11, 0.82, 0.39, 0.92);
}

* { box-sizing: border-box; }

/* `currentColor` so this stays visible inside the differenced header
   as well as on the plain canvas. */
a:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 5px;
}

/* The header is fixed, so an anchor jump would otherwise drop the
   target's first line underneath it. Applied to any linkable section
   so this is handled once rather than per section. */
section[id] {
  scroll-margin-top: calc(var(--nav-h) + 8px);
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--display);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ============================================================
   NAVIGATION
   ============================================================
   The whole header is `mix-blend-mode: difference` over a
   transparent background — no fill, no backdrop blur.

   That is why its colour is #EFEFEF rather than black: differenced
   against the #F7F7F7 canvas it resolves to |247-239| = #080808,
   which reads as near-black. Over a dark section it resolves the
   other way to near-white. One nav, legible on both, with nothing
   to toggle when we add dark sections later.
   ============================================================ */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 10000;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  padding: 0 var(--gutter);
  background: transparent;
  mix-blend-mode: difference;
  color: var(--nav-ink);
}

.nav-inner {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(12px, 2.4vw, 32px);
}

/* --- Wordmark ------------------------------------------- */
/* ⚠️ The mark is a MASK filled with `currentColor`, not an <img>, and
   that is the whole point rather than a stylistic preference.

   The header is `mix-blend-mode: difference` and blends its *entire*
   layer against the backdrop — a child cannot opt out. So a normal
   image gets inverted: the logo's black circle over the #F7F7F7
   canvas resolves to |247-0| = white and its white bird to |247-255|
   = near-black, i.e. a negative of the mark across most of the page.

   Painted as a mask, the mark is one flat colour and the blend treats
   it exactly as it treats text — near-black on the canvas, near-white
   over the manifesto band. No rule of its own, no exception to §5,
   and it inverts with the links rather than against them.

   The mask carries the shape in its *alpha*: circle opaque, bird and
   book knocked out, everything outside transparent. It is generated
   from `assets/logo-source.png` — see docs/08 §9h for the command.

   ⚠️ It is INLINED as a data: URI, and that is not an optimisation.
   Chrome fetches CSS mask images with CORS, and every `file://`
   document is its own opaque origin — so a linked mask is blocked
   when the page is opened off disk, which is how this page is
   actually tested. **A blocked mask renders the element invisible and
   logs nothing**, so the wordmark simply vanished while every other
   relative asset on the page kept working. Inlining removes the fetch
   entirely, which also makes it survive the Artifact CSP (§11).
   128px grayscale+alpha, ~5 KB. **Do not turn this back into a
   url("assets/…") reference.**

   The text stays in the markup and is pushed out of the box rather
   than deleted, so the link keeps an accessible name and still reads
   as "StudyGPT" if the stylesheet never arrives. */
.wordmark {
  display: block;
  flex: none;
  width: 40px;
  height: 40px;
  background-color: currentColor;
  -webkit-mask-image: url("data:image/png;base64,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");
          mask-image: url("data:image/png;base64,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");
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;

  color: inherit;
  text-decoration: none;
  overflow: hidden;
  text-indent: 110%;
  white-space: nowrap;
}

/* --- Centre links --------------------------------------- */
/* Gap and size are fluid so the links survive a narrow window instead
   of being dropped. 72px is the reference spacing at full width. */
.nav-links {
  display: flex;
  align-items: center;
  gap: clamp(10px, 3.6vw, 72px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav-link {
  font-family: var(--mono);
  font-weight: 300;
  font-size: clamp(9px, 1.2vw, 16px);
  /* `letter-spacing` covers the un-split fallback; `--track` is what
     the per-character boxes actually use. Keep the two in step. */
  --track: 0.04em;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: inherit;
  text-decoration: none;
  display: inline-flex;
  align-items: baseline;
  gap: 0.5ch;
  white-space: nowrap;
}

/* Each character is a 1-line window holding two stacked copies.
   On hover the stack slides up by exactly one line, so the label
   is replaced by itself letter by letter rather than all at once.

   ------------------------------------------------------------------
   Tracking has to be rebuilt by hand here, and the reason is not
   obvious. Splitting a line into per-character boxes breaks
   `letter-spacing` in two ways at once:

   1. It stops applying *between* the letters. Spacing is added after
      characters within a text run, and two adjacent inline-blocks are
      not one. Measured gaps across the wordline were 0,0,0,1,0,-1,1.
   2. It still applies *inside* each box, so every box came out exactly
      one tracking-step narrower than its glyph's advance — an 'S' with
      a 38px advance in a 31px box — and `overflow: hidden` then cut
      the right-hand side off every letter. That clipping, not the
      spacing, is why the strokes could not meet.

   So the tracking is cancelled inside the box, re-applied as a margin
   between boxes, and the clip area is padded out on both sides so no
   ink ever sits on the boundary.

   With padding P and tracking T, margin-left: -P puts the glyph back
   where it started, and the margin box then measures
   (-P + P + advance + P + margin-right). For consecutive glyphs to
   step by advance + T, that has to equal advance + T — so
   margin-right is T - P. Only the left padding is cancelled by the
   left margin; the right one still has to be paid for here.
   ------------------------------------------------------------------ */
.ch {
  display: inline-block;
  overflow: hidden;
  height: 1em;
  line-height: 1em;
  vertical-align: bottom;

  letter-spacing: normal;
  padding-left: 0.08em;
  padding-right: 0.08em;
  margin-left: -0.08em;
  margin-right: calc(var(--track, 0em) - 0.08em);
}

.ch > span {
  display: block;
  height: 1em;
  line-height: 1em;
  transition: transform 0.42s var(--ease-out-expo);
  transition-delay: var(--d, 0ms);
}

.nav-link:hover .ch > span { transform: translateY(-1em); }

/* Preserve the spaces between words once the label is split. No clip
   padding to compensate for here — there is no glyph to protect. */
.ch--space {
  width: 0.6ch;
  padding-left: 0;
  padding-right: 0;
  margin-left: 0;
  margin-right: var(--track, 0em);
}

/* --- Right-hand group ----------------------------------- */
.nav-end {
  display: flex;
  align-items: center;
  gap: clamp(12px, 2vw, 24px);
}

/* Text, not a hamburger — the whole page is typographic, and "MENU"
   costs less explanation than three lines do. Only appears once the
   inline links have been dropped. */
.nav-toggle {
  display: none;
  font-family: var(--mono);
  font-weight: 400;
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: inherit;
  background: none;
  border: 0;
  padding: 6px 0;
  cursor: pointer;
}

/* --- Log in --------------------------------------------- */
.nav-login {
  font-family: var(--mono);
  font-weight: 400;
  font-size: 16px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  display: inline-flex;
  align-items: center;
  gap: 0.4ch;
  white-space: nowrap;
}

.nav-login .arrow {
  display: inline-block;
  transition: transform 0.42s var(--ease-out-expo);
}

.nav-login:hover .arrow { transform: translate(2px, -2px); }

/* ============================================================
   MOBILE MENU
   ============================================================ */

.menu {
  position: fixed;
  inset: 0;
  /* Below the header's 10000 deliberately: the bar uses
     mix-blend-mode, so leaving it on top means it inverts against
     this panel and the toggle stays legible without a second rule. */
  z-index: 9000;
  background: var(--canvas);
  display: flex;
  align-items: center;
  padding: var(--nav-h) var(--gutter) var(--gutter);
}

.menu[hidden] { display: none; }

.menu__inner {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.menu__link {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(38px, 13vw, 76px);
  line-height: 1.04;
  letter-spacing: -0.06em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  padding: 6px 0;
}

/* ============================================================
   SHARED BREAKPOINTS
   ============================================================
   Only the two that belong to the shell. Each page keeps its own
   rules inside its own copy of these queries — the landing page
   collapses the hero grid at 900px, the legal pages have nothing
   to collapse.

   The links stay in the bar on a fluid gap and size rather than a
   hard breakpoint. Two earlier cut-offs — 900px, then 640px — both
   hid them in ordinary preview panes, which reads as a broken nav
   rather than as a responsive decision. Below 460px they are
   dropped, because four bracketed labels beside the wordmark and
   Log in cannot be set legibly in that width at any size.
   ============================================================ */

@media (max-width: 900px) {
  :root { --gutter: 24px; }
}

@media (max-width: 460px) {
  .nav-links { display: none; }
  .nav-toggle { display: block; }
}

/* Only the shell’s own motion. Each page adds its own. */
@media (prefers-reduced-motion: reduce) {
  .ch > span,
  .nav-login .arrow { transition-duration: 0.01ms !important; }
}
