/* The Sanctuary — brand surfaces (thesanctuary.dev, legal., provision.)
 *
 * SELF-HOSTED, deliberately. A <link> to fonts.googleapis.com hands every
 * visitor's IP to Google on page load. These sites exist downstream of an audit
 * whose whole point was removing that kind of thing; loading the type from a
 * third party would undo it on the one page carrying the company's name.
 * Two variable files, latin subset, 52 KB total.
 *
 * Geist / Geist Mono — SIL Open Font License 1.1, Vercel with Basement Studio.
 *
 * PALETTE. Warm neutrals rather than pure black: #232322 not #0a0a0a, cream not
 * white. docs/DESIGN.md governs the OPS surfaces and keeps its own darker
 * ground; this is the brand register and is intentionally softer. The acid
 * accent is shared across both — it is the existing brand colour and the mark
 * is drawn in it.
 *
 * Contrast measured against each scheme's own background, per docs/DESIGN.md:
 *   token   dark      light     carries
 *   ink     13.91     15.82     body text
 *   dim      6.08      5.23     labels, furniture
 *   acid    13.69      4.67     accent, links
 *   rule     1.38      1.23     hairlines only, never text
 * Every token that carries text clears 4.5:1 in BOTH schemes. --acid is a
 * DIFFERENT value per scheme for exactly this reason: #d8ff36 measures 1.60 on
 * cream and would fail; #5f7a00 is its light-scheme counterpart.
 */

@font-face {
  font-family: "Geist";
  src: url("/fonts/geist-latin.woff2") format("woff2");
  font-weight: 100 900;           /* one variable file covers the range */
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/fonts/geist-mono-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light dark;
  --bg:#232322; --surface:#2C2C2A; --ink:#F2F1EC; --dim:#A3A199;
  --rule:#3A3A37; --acid:#D8FF36;
  --sans:"Geist", ui-sans-serif, -apple-system, "Segoe UI", system-ui, sans-serif;
  --mono:"Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}
@media (prefers-color-scheme: light) {
  :root {
    --bg:#FAF9F5; --surface:#F2F0E9; --ink:#1F1E1B; --dim:#6B6960;
    --rule:#E5E2D9; --acid:#5F7A00;
  }
}

* { box-sizing: border-box }
body {
  margin:0; background:var(--bg); color:var(--ink);
  font-family:var(--sans); font-size:16px; line-height:1.65;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  font-feature-settings:"cv11";   /* Geist: disambiguated single-storey shapes */
}
code, pre, .mono { font-family:var(--mono); font-variant-numeric:tabular-nums; }
a { color:inherit; text-decoration-color:var(--acid); text-underline-offset:3px; }
a:focus-visible { outline:2px solid var(--acid); outline-offset:3px; border-radius:2px; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration:.01ms !important; transition-duration:.01ms !important; }
}

/* ---------------------------------------------------------------------------
 * LAYOUT — mobile first, and it uses the screen.
 *
 * What was here before: a fixed 38rem column, 16px type, zero media queries.
 * On a phone that meant a cramped measure inside fixed 1.5rem padding; on a
 * wide display it meant a narrow ribbon of text with most of the viewport
 * empty. One layout that suited neither end.
 *
 * Base styles below are the PHONE. Everything grows from there via clamp(),
 * so there is no breakpoint where the design snaps — and one min-width query
 * at 64rem introduces the second column, because that is the width at which a
 * single column genuinely starts wasting space rather than the width some
 * device happens to be.
 * ------------------------------------------------------------------------- */
:root{
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --measure: 66ch;                 /* ceiling on line length, not on the page */
  --s--1: clamp(.82rem, .79rem + .15vw, .93rem);
  --s-0 : clamp(1rem,   .96rem + .24vw, 1.18rem);
  --s-1 : clamp(1.15rem, 1.05rem + .5vw, 1.5rem);
  --s-2 : clamp(1.35rem, 1.15rem + 1vw,  2.1rem);
  --s-3 : clamp(1.8rem,  1.3rem + 2.4vw, 3.4rem);
}
body { font-size: var(--s-0); }

main {
  width: 100%;
  padding: clamp(2rem,7vh,5rem) var(--gutter) clamp(3rem,10vh,7rem);
  max-width: none;                 /* overrides the old fixed 38rem */
  margin-inline: auto;
}
/* Only a page BUILT as rail+flow becomes a grid. Applying this to every <main>
   turned the apex — three loose children — into grid items and scattered them:
   mark left, wordmark far right, link orphaned below. A layout rule that
   assumes a structure has to say so in its selector. */
main.split {
  display: grid;
  /* minmax(0,1fr), NOT the implicit `auto`. A grid track defaults to max-content
     and a grid item defaults to min-width:auto, so children capped at 66ch sized
     the single mobile column to ~600px and pushed the page off a 390px screen.
     This is the whole mobile bug: it was never the type or the padding. */
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3rem);
}
/* Grid and flex children need this explicitly or they refuse to shrink below
   their content's intrinsic width. */
main.split > .rail, main.split > .flow { min-width: 0; }
main > .flow > * + * { margin-top: 1.1em; }
.rail h1 { font-size: var(--s-3); line-height: 1.04; letter-spacing: -.02em;
           text-wrap: balance; margin: 0 0 .4em; }
.rail .sub { font-size: var(--s-1); color: var(--dim); margin: 0; max-width: min(34ch, 100%); }
.flow h2 { font-size: var(--s-1); margin: 2em 0 .5em; letter-spacing: -.01em; }
.flow p, .flow li, .flow dd { max-width: min(var(--measure), 100%); }

@media (min-width: 64rem) {
  main.split {
    grid-template-columns: minmax(16rem, 24rem) minmax(0, var(--measure));
    gap: clamp(3rem, 7vw, 8rem);
    max-width: 108rem;
    align-items: start;
  }
  /* The rail holds the page's identity, so it stays put while the body scrolls.
     align-self:start is required — a stretched grid item cannot stick. */
  .rail { position: sticky; top: clamp(2rem,7vh,5rem); align-self: start; }
}

/* Checksums, DNS records and URLs are long unbroken strings; without this they
   set the minimum width of their container and reopen the same overflow. */
.flow pre, .flow code { overflow-x: auto; max-width: 100%; }
.flow a { overflow-wrap: anywhere; }
