/* ── legal-kit ───────────────────────────────────────────────────────────────
   The shared document language for the four public policy pages: privacy,
   cookies, terms, compliance.

   One stylesheet rather than four inline copies, for the reason annotate.js is
   one file: these pages are near-identical in structure and differ only in
   prose, so two drifting copies of the layout is a bug nobody would look for.
   It is served from the landing page's public asset allowlist (routes/signup.ts)
   because these pages are reachable before anybody signs in.

   The palette and faces are the landing page's, restated here rather than
   imported: legal-kit is loaded by pages that do NOT load landing.html's inline
   <style>, so it has to stand on its own. If the brand moves, both move.

   Body copy is Newsreader, not Inter. A policy is a document someone reads at
   length and argues with, and the serif is what says so — the sans is kept for
   labels, tables and the chrome, where it is doing UI work rather than prose. */

:root {
  --paper: #fef8ef;
  --paper-deep: #f7eee2;
  --ink: #1e1e1b;
  --soft: #5c5a54;
  --line: rgba(30, 30, 27, .13);
  --rule: rgba(30, 30, 27, .28);
  /* The lattice ink, at the library's value. Deliberately far fainter than the
     landing page's .075: that grid is a structural device you are meant to
     notice, this one is stock you are meant to feel and not count. */
  --grid: rgba(30, 30, 27, .022);
  --yellow: #f4f56e;
  --blue: #3157c8;
  --red: #eb4b2d;
  --serif: "Newsreader", Georgia, serif;
  --sans: "Inter", Arial, sans-serif;
  --hand: "Caveat", cursive;
  /* The prose measure, and the margin the glosses hang in. Both are referenced
     from several rules, and the sidenote maths below only works while the two
     agree — keep them here rather than inline. */
  --measure: 34rem;
  --margin-col: 15rem;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.62;
}

/* The paper stock: graph paper, the same 13px lattice the library shelf is
   printed on. Those are the product's two long-form READING surfaces — a doc
   somebody scrolls and argues with — so they should be the same stock, and a
   policy that arrived on its own private texture would read as a page bolted
   on from outside.

   Painted on a fixed ::before rather than as a body background-image, which is
   the library's technique and is load-bearing: `background: var(--paper)` on
   body propagates to the canvas, so the pseudo-element at z-index -1 lands
   ABOVE the paper colour and below the text. Fixed, so the lattice holds still
   while the document scrolls over it — that is the difference between stock
   and a texture stuck to a div.

   13px, not the 60px the other shells use. These pages are read on phones as
   often as laptops, and at 60px the squares are six across on a handset and
   read as plaid rather than paper. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--grid) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid) 1px, transparent 1px);
  background-size: 13px 13px;
}

/* The brand's one flourish, borrowed from the landing page's hero, where the
   word "fits." sits on a yellow bar rotated a little off true. Same gesture
   here: the highlighter, not a hover colour. */
::selection { background: var(--yellow); color: var(--ink); }

.gutter {
  width: min(100% - 3rem, 74rem);
  margin-inline: auto;
}

/* ── chrome ──────────────────────────────────────────────────────────────── */

.site-nav {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: 74px;
  font-family: var(--sans);
}

.brandlock {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  color: inherit;
  text-decoration: none;
}

.emblem {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--ink);
  border-radius: 50%;
}

.emblem svg { width: 18px; height: 18px; fill: var(--ink); }

.wordmark {
  font-family: var(--hand);
  font-size: 27px;
  line-height: 1;
}

.nav-spacer { flex: 1; }

.nav-back {
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--soft);
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  padding-bottom: 2px;
  transition: color .18s ease, border-color .18s ease;
}

.nav-back:hover { color: var(--ink); border-color: var(--ink); }

/* ── masthead ────────────────────────────────────────────────────────────── */

.doc-head {
  padding: 3.5rem 0 2.25rem;
  border-bottom: 2px solid var(--ink);
}

.doc-kicker {
  margin: 0 0 1.5rem;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--soft);
}

.doc-head h1 {
  margin: 0;
  font-size: clamp(2.8rem, 8vw, 5.5rem);
  font-weight: 300;
  line-height: .94;
  letter-spacing: -.045em;
}

/* The one flash of colour on an otherwise ink-on-paper page, and it lands on
   the word that names the document rather than on decoration. */
.doc-head h1 em {
  font-style: italic;
  color: var(--blue);
}

.doc-standfirst {
  max-width: 40rem;
  margin: 1.5rem 0 0;
  font-size: 1.24rem;
  line-height: 1.5;
  color: var(--soft);
}

/* Effective date, version, controller — the stamp block on a printed notice.
   A definition list because that is what it is, laid out as rules rather than
   as a table so it reflows to one column without a horizontal scroller. */
.doc-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0 3rem;
  margin: 2.5rem 0 0;
  font-family: var(--sans);
}

.doc-meta > div {
  padding-top: .7rem;
  border-top: 1px solid var(--rule);
  min-width: 9rem;
}

.doc-meta dt {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--soft);
}

.doc-meta dd {
  margin: .35rem 0 0;
  font-size: .92rem;
}

.doc-meta a { color: var(--blue); }

/* ── the two-column body ─────────────────────────────────────────────────── */

.doc-body {
  display: grid;
  grid-template-columns: 13rem minmax(0, 1fr);
  gap: 0 4rem;
  padding: 3rem 0 5rem;
  align-items: start;
}

.doc-toc {
  position: sticky;
  top: 2rem;
  font-family: var(--sans);
}

.doc-toc p {
  margin: 0 0 1rem;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--soft);
}

.doc-toc ol {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: toc;
}

.doc-toc li { counter-increment: toc; }

.doc-toc a {
  display: grid;
  grid-template-columns: 1.9rem 1fr;
  gap: .4rem;
  padding: .42rem 0;
  font-size: .8rem;
  line-height: 1.35;
  color: var(--soft);
  text-decoration: none;
  border-top: 1px solid var(--line);
  transition: color .18s ease;
}

.doc-toc a::before {
  content: counter(toc, decimal-leading-zero);
  font-variant-numeric: tabular-nums;
  font-size: .68rem;
  padding-top: .13rem;
  color: rgba(30, 30, 27, .38);
}

.doc-toc a:hover { color: var(--ink); }

/* The prose column carries the sidenote margin as padding, so a floated gloss
   pulled into it with a negative margin sits inside the article's own box and
   never collides with the sticky rail on its left. */
.doc-prose {
  max-width: calc(var(--measure) + var(--margin-col));
  padding-right: var(--margin-col);
}

.doc-prose section {
  padding-top: 2.6rem;
  /* A sidenote belongs to its own section. Without this, a gloss near the end
     of one section is still floating when the next section's heading is laid
     out, and the heading gets pushed right — the section numeral leaves the
     margin it is supposed to hang in. Clearing at the section boundary is also
     what keeps the rule between sections a full-width rule. */
  clear: right;
  /* An anchor jump from the contents rail must not tuck the heading under the
     top of the viewport, and these pages have no fixed header to offset. */
  scroll-margin-top: 1.5rem;
}

.doc-prose section + section { border-top: 1px solid var(--line); }

/* The section numeral hangs in the LEFT margin on wide screens — the printed
   statute gesture, and the reason the h2 is a grid rather than a line of text.
   It collapses into the flow below the breakpoint, where there is no margin to
   hang anything in. */
.doc-prose h2 {
  display: grid;
  grid-template-columns: 3.4rem 1fr;
  align-items: baseline;
  gap: 0;
  margin: 0 0 1.1rem -3.4rem;
  font-size: 1.62rem;
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: -.03em;
}

.doc-prose h2 .sec-num {
  font-family: var(--sans);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .1em;
  color: var(--red);
  font-variant-numeric: tabular-nums;
}

.doc-prose h3 {
  margin: 2rem 0 .6rem;
  font-family: var(--sans);
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.doc-prose p { margin: 0 0 1.05rem; max-width: var(--measure); }

.doc-prose ul { margin: 0 0 1.05rem; padding-left: 1.1rem; max-width: var(--measure); }

.doc-prose li { margin-bottom: .5rem; }

.doc-prose li::marker { color: var(--red); }

.doc-prose a { color: var(--blue); text-underline-offset: 3px; }

.doc-prose strong { font-weight: 600; }

/* ── the plain-English gloss ─────────────────────────────────────────────────
   The thing that makes these pages ours rather than a template. Every dense
   clause gets a handwritten note in the margin saying what it means, because
   the people this product is for are not engineers and a policy they cannot
   read is not transparency.

   Floated rather than absolutely positioned. A float flows with the paragraph
   it follows and pushes the next one down if it is tall; an absolutely
   positioned sidenote of unknown height silently overlaps the one below it.
   `clear: right` stops two consecutive glosses stacking on top of each other. */
.gloss {
  float: right;
  clear: right;
  width: calc(var(--margin-col) - 2.5rem);
  margin: .3rem calc(-1 * var(--margin-col)) 1.2rem 0;
  font-family: var(--hand);
  font-size: 1.06rem;
  line-height: 1.34;
  color: var(--soft);
  padding-left: .85rem;
  border-left: 1px solid var(--rule);
}

.gloss b { font-weight: 600; color: var(--ink); }

/* ── ledger tables ───────────────────────────────────────────────────────── */

/* Cookie inventory and the subprocessor list. Ruled like a ledger — horizontal
   rules only, no boxes — and allowed to scroll inside its own container so the
   page body never scrolls sideways on a phone. */
/* `clear: right` is load-bearing, not tidiness. This is a block formatting
   context (overflow-x does that), and a BFC does not flow AROUND a float — it
   SHRINKS to avoid one. A gloss floated beside a table therefore narrowed the
   scroller and silently clipped a whole column off the right-hand side, which
   is how the lawful-basis table first shipped. Clearing means a table always
   gets the full measure, whatever is floated above it.

   The same applies to .callout below, which is a BFC for the same reason. */
.ledger-wrap {
  overflow-x: auto;
  clear: right;
  margin: 0 0 1.4rem;
  max-width: var(--measure);
}

.ledger {
  width: 100%;
  min-width: 30rem;
  border-collapse: collapse;
  font-family: var(--sans);
  font-size: .81rem;
  text-align: left;
}

.ledger th {
  padding: 0 .9rem .55rem 0;
  border-bottom: 1px solid var(--ink);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--soft);
  vertical-align: bottom;
}

.ledger td {
  padding: .7rem .9rem .7rem 0;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
  line-height: 1.45;
}

.ledger td:first-child { font-weight: 600; }

.ledger code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: .92em;
  background: var(--paper-deep);
  padding: .1em .35em;
  border: 1px solid var(--line);
}

/* ── callout ─────────────────────────────────────────────────────────────── */

/* Used sparingly, for the two or three statements on these pages that a reader
   would be worse off for skimming past. */
.callout {
  max-width: var(--measure);
  clear: right;
  margin: 0 0 1.4rem;
  padding: 1.15rem 1.35rem;
  background: var(--paper-deep);
  border: 1px solid var(--ink);
  box-shadow: 4px 4px 0 rgba(30, 30, 27, .1);
}

.callout p { margin: 0; }
.callout p + p { margin-top: .7rem; }

.callout .callout-label {
  display: block;
  margin-bottom: .5rem;
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--red);
}

/* An honest-gap callout: something we are telling you we have NOT done. Yellow
   rather than red, because it is a disclosure and not an alarm. */
.callout--gap { background: var(--yellow); border-color: var(--ink); }
.callout--gap .callout-label { color: var(--ink); }

/* ── footer ──────────────────────────────────────────────────────────────── */

.doc-foot {
  border-top: 2px solid var(--ink);
  padding: 2rem 0 3rem;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  align-items: center;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--soft);
}

.doc-foot nav { display: flex; flex-wrap: wrap; gap: .35rem 1.5rem; }

/* ── the highlighter ─────────────────────────────────────────────────────────
   Four legal links are the easiest thing on a page to leave as blue text and
   forget. These get the one gesture this brand actually owns: the yellow
   marker bar from the landing page's hero, where "fits." sits on a rectangle
   rotated -.6deg off true — a stroke laid down by hand rather than a box drawn
   by a machine.

   Hovering wipes it across left to right. `scaleX` from a left origin is the
   whole effect, and it composites on the GPU, so four of these cost nothing.

   The rotation is carried in BOTH transform values. `transform` is one
   property: writing `scaleX(1)` alone in the hover rule would silently discard
   the rotation and the bar would snap square at the moment it is most visible.

   The current page is painted permanently rather than being given a different
   treatment — "you are here" and "you could go here" in one visual language,
   which is the whole reason to have a language. */
.doc-foot nav a {
  position: relative;
  z-index: 0;
  display: inline-block;
  padding: .12em .18em .16em;
  color: var(--soft);
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  transition: color .2s ease, border-color .2s ease;
}

.doc-foot nav a::before {
  content: "";
  position: absolute;
  z-index: -1;
  /* Overhanging the text a touch on each side: a real highlighter overshoots,
     and a bar that stops exactly at the glyphs reads as a table cell. */
  left: -.2em;
  right: -.26em;
  top: .02em;
  bottom: -.04em;
  background: var(--yellow);
  transform: rotate(-.6deg) scaleX(0);
  transform-origin: left center;
  transition: transform .28s cubic-bezier(.2, .8, .2, 1);
}

.doc-foot nav a:hover,
.doc-foot nav a:focus-visible,
.doc-foot nav a[aria-current="page"] { color: var(--ink); border-color: var(--ink); }

.doc-foot nav a:hover::before,
.doc-foot nav a:focus-visible::before,
.doc-foot nav a[aria-current="page"]::before { transform: rotate(-.6deg) scaleX(1); }

/* Focus must not rely on the wipe alone — it is a hover affordance, and a
   keyboard user needs an outline the yellow cannot swallow. */
.doc-foot nav a:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  .doc-foot nav a::before { transition: none; }
}

.doc-foot .foot-spacer { flex: 1; }

/* ── narrow ──────────────────────────────────────────────────────────────── */

@media (max-width: 62rem) {
  .doc-body { grid-template-columns: minmax(0, 1fr); gap: 0; }
  /* The rail becomes a plain block at the top of the document rather than
     disappearing: on a phone it is the only way to see how long this is. */
  .doc-toc { position: static; margin-bottom: 2.5rem; }
  .doc-toc ol { columns: 2; column-gap: 1.5rem; }
  .doc-prose { max-width: none; padding-right: 0; }
  .doc-prose h2 { grid-template-columns: 2.6rem 1fr; margin-left: 0; }
  /* No margin to hang in, so the gloss stops being a sidenote and becomes an
     indented aside in the flow, immediately after the clause it explains. */
  .gloss {
    float: none;
    width: auto;
    max-width: var(--measure);
    margin: -.2rem 0 1.2rem;
  }
}

@media (max-width: 30rem) {
  .doc-toc ol { columns: 1; }
  .gutter { width: min(100% - 2rem, 74rem); }
}

/* ── motion ──────────────────────────────────────────────────────────────── */

/* One orchestrated arrival, not scattered micro-interactions: the masthead
   settles, then the document under it. Anything more on a page of legal prose
   is decoration getting in the way of reading. */
@media (prefers-reduced-motion: no-preference) {
  .doc-kicker, .doc-head h1, .doc-standfirst, .doc-meta, .doc-body {
    animation: docRise .62s cubic-bezier(.2, .8, .2, 1) both;
  }
  .doc-head h1 { animation-delay: .05s; }
  .doc-standfirst { animation-delay: .11s; }
  .doc-meta { animation-delay: .17s; }
  .doc-body { animation-delay: .23s; }
}

@keyframes docRise {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* ── print ───────────────────────────────────────────────────────────────── */

/* A policy is a document people save. Printed, the rail and the chrome are
   noise, and the glosses belong under the clause they explain. */
@media print {
  body { background: #fff; font-size: 11pt; }
  .site-nav, .doc-toc, .cookie-notice { display: none; }
  .doc-body { display: block; padding-top: 1rem; }
  .doc-prose { max-width: none; padding-right: 0; }
  .doc-prose h2 { margin-left: 0; }
  .doc-prose section { page-break-inside: avoid; }
  .gloss { float: none; width: auto; margin: 0 0 1rem; }
  .callout { box-shadow: none; }
}
