/* ===========================================================================
   GroundSpring Publishing — site styles.

   The palette is sampled from the logo itself: the near-black green it sits
   on, the two greens of the seedling, the two blues of the water, and the
   bronze rule under the wordmark. Nothing here is invented; the artwork is
   the brand and the page is built to match it rather than the other way
   round.

   System fonts only. Nothing is fetched from another origin — no font CDN,
   no analytics, no tag manager. A page about not being intermediated should
   not phone four companies to render.
   =========================================================================== */
:root {
  --ground:      #05100b;
  --ground-lift: #0a1a12;
  --panel:       #0f2418;
  --panel-lift:  #16311f;
  --rule:        rgba(155, 206, 170, .16);
  --rule-strong: rgba(185, 147, 63, .55);

  --ink:         #e8f2ea;
  --ink-mute:    #9db5a6;
  --ink-faint:   #6f8a79;

  --leaf:        #7cc242;
  --leaf-deep:   #4e8f2b;
  --leaf-light:  #a8e06d;
  --water:       #2aa3e8;
  --water-deep:  #1668a8;
  --water-light: #7fccf5;
  --gold:        #b9933f;
  --gold-light:  #e0c27a;

  --max:   72rem;
  --prose: 40rem;
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
  --sans:  ui-sans-serif, -apple-system, "Segoe UI", Inter, Helvetica, Arial, sans-serif;
  --mono:  ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: var(--leaf-light); text-underline-offset: .18em; }
a:hover { color: var(--gold-light); }

.wrap { max-width: var(--max); margin: 0 auto; padding-inline: 24px; }
/* The reading column. Left-aligned inside the page's own margin, so its edge
   agrees with the masthead and the headline above it rather than floating in
   the middle of the screen under them. */
.prose { max-width: var(--prose); }
.wrap > .prose { margin-inline: 0; }

h1, h2, h3 { font-family: var(--serif); font-weight: 600; line-height: 1.18; }
h1 { font-size: clamp(2rem, 5vw, 3.1rem); letter-spacing: -.015em; margin: 0 0 .4em; }
h2 { font-size: clamp(1.5rem, 3.2vw, 2.1rem); margin: 2.4em 0 .5em; }
h3 { font-size: 1.22rem; margin: 2em 0 .4em; }

.eyebrow {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--gold); margin: 0 0 .9em;
}
.standfirst { font-size: 1.24rem; line-height: 1.6; color: var(--ink); }
.sub { color: var(--ink-mute); }

/* ------------------------------------------------------------------ masthead */
.masthead {
  position: sticky; top: env(safe-area-inset-top, 0px); z-index: 30;
  background: color-mix(in srgb, var(--ground) 90%, transparent);
  backdrop-filter: saturate(160%) blur(12px);
  -webkit-backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid var(--rule);
}
.masthead .wrap { display: flex; align-items: center; gap: 16px; padding-block: 11px; }
.brand { display: flex; align-items: center; gap: 11px; text-decoration: none; color: var(--ink); }
.brand img { width: 38px; height: 38px; border-radius: 9px; }
.brand-text b { display: block; font-family: var(--serif); font-size: 1.12rem; font-weight: 600;
                letter-spacing: -.01em; line-height: 1.1; }
.brand-text > span { display: block; font-family: var(--mono); font-size: 9.5px; letter-spacing: .2em;
                     text-transform: uppercase; color: var(--gold); margin-top: 2px; }
.masthead nav { margin-left: auto; display: flex; gap: 22px; flex-wrap: wrap; }
.masthead nav a {
  color: var(--ink-mute); text-decoration: none;
  font-size: 14px; font-weight: 600; letter-spacing: .02em; white-space: nowrap;
  /* 44px of height, because that is the size of a fingertip. The link text is
     24px tall on its own and was being missed on a phone. */
  display: inline-flex; align-items: center; min-height: 44px;
}
.masthead nav a:hover, .masthead nav a[aria-current="page"] { color: var(--leaf-light); }

/* ---------------------------------------------------------------------- hero
   The artwork already carries the wordmark, the tagline and the not-for-profit
   line, so nothing underneath repeats any of them. It is shown whole at its
   own 3:2 proportion — any fixed height with object-fit:cover would cut the
   lockup out of the corner it was designed into.

   But whole is not the same as fitting. At 1440px the image was 960px tall in
   an 813px viewport (measured), so the landing zone of this site was the
   middle of a photograph: the wordmark was on screen, the bottom of the
   picture was not, and the headline that says what GroundSpring is began
   214px below the fold. The picture is now bounded by the room that is
   actually left under the masthead, so the whole artwork and the top of the
   argument arrive on the same screen.

   It is capped at the content measure too, so on a wide window the banner
   lines up with the column beneath it instead of floating at some third
   width of its own. */
:root { --masthead-h: 67px; --hero-peek: 52px; }
.hero {
  border-bottom: 1px solid var(--rule); background: var(--ground-lift);
  display: flex; justify-content: center;
}
.hero img {
  width: auto; height: auto;
  max-width: min(100%, var(--max));
  max-height: calc(100svh - var(--masthead-h) - var(--hero-peek));
  aspect-ratio: 1536 / 1024;
}
/* A short, wide window is the case this is for. On a phone the picture is
   nowhere near the height of the screen and the cap never binds, so it is
   left alone rather than given a second set of numbers to disagree with. */
@media (max-width: 900px) { .hero img { width: 100%; max-height: none; } }

/* The opening of every page. It used to be a single left column, which left
   the right 55% of a 1440px screen empty on every page on the site — the
   headline sat in a corner and the page read as unfinished. It is now two
   columns, and each page puts something worth reading in the second one. */
.lede { padding: clamp(40px, 7vw, 76px) 0 clamp(28px, 5vw, 56px); }
@media (min-width: 900px) {
  .lede--split {
    display: grid; grid-template-columns: 1.1fr .9fr; gap: clamp(32px, 5vw, 64px);
    align-items: start;
  }
  .lede--split .lede__main > :first-child { margin-top: 0; }
}
.lede__aside {
  background: var(--ground-lift); border: 1px solid var(--rule);
  border-radius: 14px; padding: 24px 22px; font-size: 15.5px;
}
.lede__aside h2 { font-family: var(--sans); font-size: 12px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--gold); margin: 0 0 14px; }
.lede__aside p:last-child, .lede__aside ol:last-child, .lede__aside ul:last-child { margin-bottom: 0; }
.lede__aside ol, .lede__aside ul { padding-left: 1.15em; margin: 0; }
.lede__aside li { margin-bottom: .55em; }
.lede__aside li:last-child { margin-bottom: 0; }
@media (max-width: 899px) { .lede__aside { margin-top: 26px; } }
.lede h1 { max-width: 20ch; }
/* Every paragraph in the opening, not just the standfirst. The .sub under it
   had no cap and ran to 136 characters a line. */
.lede p { max-width: 52ch; }
.lede .standfirst { max-width: 46ch; }

/* ---------------------------------------------------------------- components */
.band { padding: clamp(44px, 7vw, 84px) 0; border-top: 1px solid var(--rule); }
.band--lift { background: var(--ground-lift); }
.band--panel { background: var(--panel); }

.grid { display: grid; gap: 22px; }
/* 300px, not 255: at desk width 255 gave five columns and a 25-character
   measure inside each card, which is a column of single words. */
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(310px, 1fr)); }

.card {
  background: var(--ground-lift); border: 1px solid var(--rule);
  border-radius: 14px; padding: 24px 22px;
}
.card h3 { margin-top: 0; }
/* Nothing reads past about 70 characters a line. Card and band copy had no
   cap and ran to 136. */
.card p, .card li { max-width: 62ch; }
.band > .wrap > p, .band > .wrap > h2 { max-width: 40rem; }
.card p:last-child { margin-bottom: 0; }
.card--accent { border-color: var(--rule-strong); background: var(--panel); }

.num {
  font-family: var(--serif); font-size: clamp(2rem, 4.4vw, 2.9rem);
  line-height: 1; color: var(--leaf-light); display: block; margin-bottom: .25em;
}
.num--water { color: var(--water-light); }
.num--gold { color: var(--gold-light); }
.stat p { margin: 0; color: var(--ink-mute); font-size: 15px; }
.stat cite { display: block; font-style: normal; font-size: 12.5px; color: var(--ink-faint); margin-top: 8px; }

.btn {
  display: inline-block; text-decoration: none; font-weight: 700; font-size: 15px;
  padding: 13px 24px; border-radius: 999px; letter-spacing: .01em;
  background: linear-gradient(180deg, var(--leaf) 0%, var(--leaf-deep) 100%);
  color: #06210c; border: 0; cursor: pointer;
}
.btn:hover { filter: brightness(1.08); color: #06210c; }
.btn--ghost {
  background: transparent; color: var(--ink);
  border: 1px solid var(--rule-strong);
}
.btn--ghost:hover { color: var(--gold-light); border-color: var(--gold); }
.btn[disabled] { opacity: .5; cursor: not-allowed; filter: none; }
.actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 28px; }

/* --------------------------------------------------------------- placards
   A book on the shelf. The markup comes from build.py's shelf(), which reads
   books.json — so a placard's copy is the publisher's copy and cannot drift
   from it.

   Two covers of very different shapes have to sit beside each other and still
   read as one collection, so the art is boxed at a fixed 2:3 and cropped to
   it. That is a decision, not a default: `object-fit: contain` would letterbox
   a landscape cover into a portrait box and the shelf would look broken.

   The actions are one filled button and then quiet links. Three equal pills
   in a 300px column wrap onto three lines and make the reader choose between
   things that are not equal — reading the book is the point; the PDF is a
   convenience. */
.shelf {
  display: grid; gap: 26px; margin-top: 32px;
  /* 33rem, and the number is derived rather than chosen. A placard spends
     52px on padding, 158px on the cover and 24px on the gap, so a card needs
     to be 528px before its text column reaches 280px — about 38 characters,
     which is the narrowest a blurb can be set and still read as prose. At
     25rem two cards sat side by side in a 900px window with 188px of text
     each, four words to the line. Below 33rem the shelf goes one-up instead. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 33rem), 1fr));
}
.placard {
  display: grid; grid-template-columns: minmax(0, 158px) minmax(0, 1fr);
  gap: clamp(18px, 2.4vw, 28px); align-items: stretch;
  background: var(--ground-lift); border: 1px solid var(--rule);
  border-radius: 16px; padding: clamp(20px, 2.4vw, 26px);
  transition: border-color .14s ease, transform .14s ease;
}
.placard:hover { border-color: var(--rule-strong); transform: translateY(-2px); }
/* Below this the cover goes above the text rather than beside it: measured,
   a 158px cover leaves 218px of text column at 500px wide, and that is not a
   column, it is a gutter. */
@media (max-width: 34rem) {
  .placard { grid-template-columns: minmax(0, 1fr); }
  .placard__art { max-width: 200px; }
}
.placard__art {
  display: block; align-self: start; border-radius: 10px; overflow: hidden;
  border: 1px solid var(--rule);
  box-shadow: 0 16px 34px rgba(0, 0, 0, .45);
}
.placard__art img { width: 100%; height: auto; aspect-ratio: 2 / 3; object-fit: cover; }
.placard__body { display: flex; flex-direction: column; min-width: 0; }
.placard h3 { margin: 0 0 6px; font-size: clamp(1.18rem, 2vw, 1.4rem); text-wrap: balance; }
.placard h3 a { color: var(--ink); text-decoration: none; }
.placard h3 a:hover { color: var(--leaf-light); }
.placard__by { margin: 0 0 12px; font-size: 14px; font-weight: 600; color: var(--gold-light); }
.placard__blurb { margin: 0 0 14px; font-size: 15px; line-height: 1.6; color: var(--ink-mute); max-width: 52ch; }
.placard__meta { margin: 0 0 18px; font-size: 13px; color: var(--ink-faint); }
/* Stacked, not in a row. Measured: a placard on a two-up shelf at 1440px gives
   its body column about 300px, and the button plus both secondary links need
   430px, so left to wrap on their own the three took three ragged lines. The
   button now has its own row and the two links share the one beneath it —
   which is also why the cover is 158px and not 175px, and the links 13px and
   not 13.5px: that is what it takes for "Listen to the audiobook · Download
   the PDF" to stay on one line here.

   margin-top:auto pins the block to the bottom, so two books with blurbs of
   different lengths still line their buttons up across the shelf. */
.placard__acts {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 12px; margin-top: auto;
}
.placard__acts .btn { font-size: 14.5px; padding: 11px 20px; }
.placard__more { display: flex; flex-wrap: wrap; align-items: center; gap: 7px 16px; }
.placard__more a {
  font-size: 13px; font-weight: 600; text-decoration: none; color: var(--water-light);
  border-bottom: 1px solid rgba(127, 204, 245, .4); padding-bottom: 1px;
}
.placard__more a:hover { color: var(--gold-light); border-bottom-color: var(--gold); }

.rule { height: 1px; background: var(--rule-strong); border: 0; margin: 0; opacity: .6; }

/* ------------------------------------------------------------------- reading */
.reading { font-size: 18px; }
.reading p { margin: 0 0 1.15em; }
.reading h2 { scroll-margin-top: 90px; }
.reading h3 { scroll-margin-top: 90px; color: var(--leaf-light); }
.reading > p, .reading > ul, .reading > ol { max-width: var(--prose); }
.reading blockquote {
  margin: 1.8em 0; padding: 2px 0 2px 22px; border-left: 2px solid var(--gold);
  font-family: var(--serif); font-size: 1.12rem; color: var(--ink);
}
.reading blockquote cite { display: block; font-family: var(--sans); font-style: normal;
  font-size: 13.5px; color: var(--ink-faint); margin-top: .7em; }
.reading ul, .reading ol { padding-left: 1.3em; }
.reading li { margin-bottom: .5em; }

/* Endnote markers. A citation you cannot click is a citation you cannot check. */
a.note {
  font-size: .72em; vertical-align: super; line-height: 0; text-decoration: none;
  font-family: var(--mono); font-weight: 700; color: var(--gold-light);
  padding: 0 .15em; scroll-margin-top: 90px;
}
a.note:hover { color: var(--leaf-light); text-decoration: underline; }
a.note::before { content: "["; }
a.note::after  { content: "]"; }

ol.endnotes { font-size: 15px; color: var(--ink-mute); padding-left: 1.6em; }
ol.endnotes li { margin-bottom: .95em; scroll-margin-top: 90px; }
ol.endnotes li:target { background: rgba(185,147,63,.12); outline: 1px solid var(--rule-strong);
                        border-radius: 5px; padding: 6px 8px; margin-left: -8px; }
ol.endnotes a.back { font-family: var(--mono); font-size: 12px; text-decoration: none; }

.bib { font-size: 15px; color: var(--ink-mute); }
.bib li { margin-bottom: .8em; }

.toc { font-size: 15px; }
.toc ol { list-style: none; padding: 0; margin: 0; counter-reset: toc; }
.toc li { counter-increment: toc; margin-bottom: .5em; }
.toc a { text-decoration: none; }
.toc a::before { content: counter(toc, upper-roman) ". "; color: var(--gold); font-family: var(--mono); font-size: 12px; }

/* --------------------------------------------------------------------- forms */
.form { display: grid; gap: 16px; max-width: 34rem; }
.field { display: grid; gap: 6px; }
.field label { font-size: 13.5px; font-weight: 700; letter-spacing: .01em; color: var(--ink); }
.field .hint { font-size: 12.5px; color: var(--ink-faint); }
.field input, .field select, .field textarea {
  font: inherit; font-size: 16px; color: var(--ink);
  background: var(--ground); border: 1px solid var(--rule); border-radius: 9px;
  padding: 11px 13px; width: 100%;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: 2px solid var(--leaf-deep); outline-offset: 1px; border-color: var(--leaf-deep);
}
.field textarea { min-height: 128px; resize: vertical; }
.field--bad input { border-color: #c4553f; }
.field .err { font-size: 12.5px; color: #f0a08e; }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-note { font-size: 13px; color: var(--ink-faint); }
.form-status { font-size: 15px; border-radius: 10px; padding: 14px 16px; border: 1px solid var(--rule); }
.form-status--ok   { border-color: var(--leaf-deep); background: rgba(124,194,66,.10); }
.form-status--bad  { border-color: #8d4433; background: rgba(196,85,63,.12); }
.form-status--work { color: var(--ink-mute); }

/* -------------------------------------------------------------------- footer */
.footer {
  border-top: 1px solid var(--rule); background: var(--ground-lift);
  padding: 46px 0 calc(40px + env(safe-area-inset-bottom, 0px));
  font-size: 14.5px; color: var(--ink-mute);
}
.footer .cols { display: grid; gap: 28px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.footer h4 { font-family: var(--sans); font-size: 12px; letter-spacing: .14em; text-transform: uppercase;
             color: var(--gold); margin: 0 0 .8em; }
.footer a { color: var(--ink-mute); text-decoration: none; }
.footer a:hover { color: var(--leaf-light); }
.footer ul { list-style: none; padding: 0; margin: 0; }
.footer li { margin-bottom: .45em; }
.footer .legal { margin-top: 34px; padding-top: 22px; border-top: 1px solid var(--rule);
                 font-size: 13px; color: var(--ink-faint); }
.footer .legal a { text-decoration: underline; }

/* ------------------------------------------------------------------- phone */
@media (max-width: 760px) {
  body { font-size: 16px; }
  .reading { font-size: 17px; }
  .masthead .wrap { flex-wrap: wrap; gap: 10px; padding-block: 10px; }
  .masthead nav { margin-left: 0; width: 100%; gap: 16px; overflow-x: auto; padding-bottom: 2px; }
  .brand-text > span { display: none; }
}
