/* Return Authorship — the whole visual system, one file, every page.
   Reasons live in projects/spirituality/return-authorship-genesis-plan.md and the
   style session of 2026-07-25. Nothing here is a default; each value was compared
   against alternatives and chosen.

   Dark only, deliberately. The light variant was built, rendered side by side, and
   dropped. There is no theme switch because there is no second theme. */

:root {
  /* Cool, not black. Ink is deliberately NOT #fff — maximum contrast on a dark ground
     causes halation: the letterforms bleed and long prose gets tiring. This is 12.5:1,
     which is plenty, and easier to read for four hundred words than 15.8:1 would be. */
  --ground: #14181b;
  --ink:    #d4d9db;
  --muted:  #8b9497;  /* 5.8:1 — carries the small-caps metadata, so it must clear AA */
  --rule:   #272d31;

  /* Sea. 8.6:1. The warm ember this started as was dropped for reading too close to
     Claude's own product accent — a site arguing for human authorship should not wear
     the machine's colour. One accent, doing real work: the mark, small caps, links,
     the end-of-piece dot. Nothing else is coloured. */
  --accent: hsl(168 48% 60%);

  /* Georgia first, honestly. Iowan Old Style is macOS-only and Charter is not reliably
     installed on Windows, so a book-serif-first stack silently resolves to Georgia for
     most visitors anyway. Naming it renders identically and lies less. */
  --serif: Georgia, "Times New Roman", serif;

  /* ~69 characters at 20px Georgia — measured, not estimated.
     In rem, NOT em, and that distinction is load-bearing: `em` resolves against each
     element's own font-size, so a 31em cap on the 40px h1 came out at 1240px and capped
     nothing at all. rem pins it to one width for every element it is applied to. */
  --measure: 39rem;
  --rail:    22rem;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--ground);
  color: var(--ink);
  font: 400 20px/1.75 var(--serif);
  /* No -webkit-font-smoothing:antialiased. It THINS type on dark grounds and the serif
     goes spindly; the default is correct here. */
}

a { color: inherit; }

/* Keyboard users have to be able to see where they are. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* ── shared marks ─────────────────────────────────────────────── */

.mark {
  width: .55rem; height: .55rem; border-radius: 50%; flex: none;
  background: var(--accent);
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent) 14%, transparent);
}
.wordmark { font-size: 1.05rem; letter-spacing: .16em; text-transform: uppercase; }
.label    { color: var(--accent); font-size: .72rem; letter-spacing: .2em; text-transform: uppercase; }
.meta     { color: var(--muted);  font-size: .8rem;  letter-spacing: .12em; text-transform: uppercase; }

/* ── The Rail ─────────────────────────────────────────────────────
   A standing place. The rail persists across every page, and one practice is
   always present on it, unasked for. The affordance is: move around a body of
   work — not: read this one essay. */

.page { display: grid; grid-template-columns: var(--rail) 1fr; min-height: 100vh; }

.rail {
  display: flex; flex-direction: column;
  border-right: 1px solid var(--rule);
  padding: 3.5rem 2.25rem 12rem;
  position: sticky; top: 0; align-self: start; height: 100vh; overflow: auto;
}
.rail .head { display: flex; align-items: baseline; gap: .75rem; margin-bottom: 3.5rem;
              text-decoration: none; }
.rail nav { display: flex; flex-direction: column; gap: .9rem; font-size: .95rem; }
.rail nav a { text-decoration: none; color: var(--muted); transition: color .18s; }
.rail nav a:hover, .rail nav a[aria-current] { color: var(--ink); }
.rail nav a[aria-current] { position: relative; }
.rail nav a[aria-current]::before {
  content: ""; position: absolute; left: -1.1rem; top: .62em;
  width: .32rem; height: .32rem; border-radius: 50%; background: var(--accent);
}
/* Pages that do not exist yet. Rendering them as inert text rather than dead links is
   the honest option — a nav item that 404s is worse than one that waits. */
.rail nav span { color: color-mix(in srgb, var(--muted) 55%, transparent); cursor: default; }

.pinned { margin-top: auto; padding-top: 3rem; border-top: 1px solid var(--rule); }
.pinned .label { display: block; margin-bottom: 1rem; }
.pinned a { display: block; text-decoration: none; }
.pinned b { display: block; font-weight: 400; font-style: italic; font-size: 1.05rem;
            margin-bottom: .4rem; transition: color .18s; }
.pinned a:hover b { color: var(--accent); }
.pinned p { font-size: .92rem; line-height: 1.65; color: var(--muted); }

/* ── the reading column ───────────────────────────────────────── */

.body { padding: 5.5rem 3.5rem 12rem; }
.body > * { max-width: var(--measure); }
.body h1 { font-size: 2.5rem; font-weight: 400; line-height: 1.14; margin-bottom: .5rem; }
.body > .meta { margin-bottom: 3.5rem; }
.body p { margin-bottom: 1.5rem; }

/* Prose links, which only exist inside a piece. Accent plus the browser's own underline,
   dimmed: an underline at full accent competes with the sentence it sits in. */
.body p a { color: var(--accent); text-underline-offset: .25em;
            text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent); }
.body p a:hover { text-decoration-color: var(--accent); }

/* The end of a piece. A dot rather than a rule: the writing stops, it is not cut off. */
.end { width: .32rem; height: .32rem; border-radius: 50%; background: var(--accent);
       margin-top: 3.5rem; }

/* The only call to action on the site. Same small caps as .label so it belongs to the
   system rather than reading as a button bolted onto it — there is no button anywhere
   else here, and one would be the loudest object on the page. */
.begin {
  display: inline-block; margin-top: 3rem; text-decoration: none;
  color: var(--accent); font-size: .78rem; letter-spacing: .2em; text-transform: uppercase;
}
.begin:hover { text-decoration: underline; text-underline-offset: .45em; }

/* ── the practices index ──────────────────────────────────────────
   Seven groups of three. Numbering runs continuously across groups, not 1-2-3
   inside each: the page is one catalogue that happens to be grouped, and
   restarting the count at every heading would say otherwise. */

.group { margin-bottom: 4.5rem; }   /* .body > * already caps the measure */
.group > .label { display: block; margin-bottom: .3rem; }
.group > .lede  { color: var(--muted); font-style: italic; font-size: 1rem;
                  margin-bottom: 1.75rem; }

.index { list-style: none; counter-reset: none; }
.index li {
  display: grid; grid-template-columns: 3rem 1fr;
  padding: 1.5rem 0; border-bottom: 1px solid var(--rule);
  scroll-margin-top: 2rem;   /* deep links land clear of the top edge */
}
.index li::before { content: attr(data-n); color: var(--accent); font-size: .85rem; padding-top: .5rem; }
.index b { display: block; font-weight: 400; font-style: italic; }
/* 1.05rem, not the .95 this started at: at .95 the line ran to 83 characters inside the
   column, past the 78 ceiling, because the measure is capped on the 20px group while the
   text inside it is smaller. Larger text, same column, shorter line. */
.index p { margin: 0; color: var(--muted); font-size: 1.05rem; line-height: 1.65; }
/* A deep-linked practice stays marked after you arrive, or the link did nothing visible.
   The negative margin equals the padding, so the rule hangs outside the column and the
   row's own content does not shift when it becomes the target. */
.index li:target { border-left: 2px solid var(--accent);
                   padding-left: 1.25rem; margin-left: -1.25rem; }

/* ── the writing index ────────────────────────────────────────────
   Flat rows, title left, month right, newest first. No numbering and no excerpts: the
   practices page is one catalogue and counts itself, this is a list of separate pieces
   and would be lying if it did the same. */

.posts { list-style: none; }
.posts a {
  display: flex; align-items: baseline; justify-content: space-between; gap: 2rem;
  padding: 1.5rem 0; border-bottom: 1px solid var(--rule); text-decoration: none;
}
.posts b { font-weight: 400; font-style: italic; font-size: 1.05rem; transition: color .18s; }
.posts a:hover b { color: var(--accent); }
.posts .meta { flex: none; }

/* ── phone: the rail becomes a drawer ─────────────────────────────
   900, not the 760 this started at. The two-column layout stops working well above
   phone width: a 22rem rail plus a 31em measure needs ~970px, so the prose column
   measured 65 characters at 880 once the drawer engaged and 32 before it did.
   The trigger is horizontal room, not device class — a narrow desktop window gets
   the drawer too, and that is correct rather than a side effect. */

.topbar, .menu, .scrim { display: none; }
html.locked, html.locked body { overflow: hidden; }

@media (max-width: 900px) {
  .page { grid-template-columns: 1fr; }
  .body { padding: 4.75rem 1.5rem 6rem; }
  .body h1 { font-size: 2rem; }
  /* clear the fixed topbar, or a deep link lands underneath it */
  .index li { grid-template-columns: 2.25rem 1fr; scroll-margin-top: 5.5rem; }

  .topbar {
    display: flex; align-items: center; gap: .7rem;
    position: fixed; inset: 0 0 auto 0; z-index: 10;
    background: var(--ground); border-bottom: 1px solid var(--rule);
    padding: .9rem 1.25rem; text-decoration: none;
  }
  .topbar .wordmark { font-size: .82rem; }

  .menu {
    display: block; position: fixed; top: .5rem; right: .75rem; z-index: 13;
    background: none; border: 0; color: var(--ink);
    font-size: 1.4rem; line-height: 1; padding: .5rem .6rem; cursor: pointer;
  }

  /* Tapping anywhere off the drawer closes it — the expected gesture, and the one
     whose absence makes a drawer feel broken. */
  .scrim {
    display: block; position: fixed; inset: 0; z-index: 11;
    background: rgba(0,0,0,.55); opacity: 0; pointer-events: none; transition: opacity .22s;
  }
  .open .scrim { opacity: 1; pointer-events: auto; }

  /* height must be explicit: an auto-height fixed box ignores `bottom` and shrink-wraps.
     Without this the drawer came out 416px tall on a 760px screen — a floating card
     with the scrim showing under it. dvh, not vh, so a mobile URL bar leaves no gap. */
  .rail {
    position: fixed; inset: 0 auto 0 0; height: 100dvh; z-index: 12;
    width: min(20rem, 82vw);
    background: var(--ground); border-right: 1px solid var(--rule);
    padding: 2.5rem 1.75rem;
    transform: translateX(-100%); transition: transform .22s ease;
  }
  .open .rail { transform: none; }
  /* Title and month stop fitting on one line: at phone width the 2rem gap plus the
     small-caps date leaves the title about 160px, so it wraps to two and the row reads
     as two columns that lost an argument. Stacked, it reads as one entry. */
  .posts a { flex-direction: column; align-items: start; gap: .25rem; }

  .rail .head { margin-bottom: 2.5rem; }
  .rail .pinned { margin-top: auto; }
}
