/* ==========================================================================
   TKAPP outreach pages — shared stylesheet.
   Type, colour and rhythm are Toby's (2026-09-11 design memos). Do not
   restyle without him. Machinery only below; no copy, no figures.
   ========================================================================== */

:root{
  --paper:#EFEEE7;
  --card:#FBFAF6;
  --card-alt:#F5F4ED;
  --ink:#17282C;
  --ink-soft:#556166;
  --ink-faint:#7C878B;
  --teal:#12626D;
  --teal-wash:#E2ECEC;
  --ochre:#9C5F24;
  --ochre-wash:#F2E7D8;
  --rule:#D6D4C8;
  --rule-soft:#E5E3D9;
  --stamp:#A33F2E;
  --shadow:rgba(23,40,44,.09);
  /* The haze under the hero words. A whole gradient rather than a colour,
     because the two themes need different GEOMETRY, not just different ink.
     Light: the words are dark on a bright photograph, so the haze only has to
     lift the left edge and can die at 60% — past that, dark-on-bright is
     already legible. Dark: the words are cream, so wherever the haze has
     faded they sit on a bright photo and disappear. The dark one therefore
     runs wider and deeper, out to 84%, past the end of the longest line.
     Same failure the tape and the tag call out, one step further on. */
  --hero-scrim:linear-gradient(90deg,rgba(255,255,255,.58) 0%,rgba(255,255,255,.42) 40%,rgba(255,255,255,0) 60%);
  /* The phone haze runs bottom-up, not left-right: at 375px there is no bright
     wall to hold. It only has to cover the HEADLINE, which is the bottom fifth
     of the frame, so it starts late and leaves the bag alone. It ends on the
     page's own ground so the photograph hands off with no visible edge. */
  --hero-scrim-phone:linear-gradient(180deg,rgba(255,255,255,0) 52%,rgba(255,255,255,.55) 68%,rgba(255,255,255,.90) 82%,var(--paper) 96%);
  /* the receipt tape has its own paper — a receipt is not printed on the
     same stock as the page it sits on */
  --tape:#F7F5EE;
  --tape-edge:#E6E2D4;
  --tape-ink:#2A2A28;
  --tape-faint:#8C8A80;
  --tape-fade:247,245,238;
  /* the gift tag has its own stock again — card, warmer than either. It
     needs its own INK for the same reason the tape does: the card stays a
     light card in dark mode, so text on it cannot ride --ink or it goes
     light-on-light and disappears. */
  --tag:#F6EFE2;
  --tag-edge:#DDD0B8;
  --tag-ink:#2C2A24;
  --tag-faint:#8A8271;

  /* THE DONATE FILL, added 2026-09-22 (launch review 1.10/2.8/3.6/5.3):
     Donate Now is filled forest green with white text and centred on every
     page. It is the only control on the site that does not ride --ochre or
     --teal, and that is the point -- it is the action, and it should not
     read as one more link in the same two colours as the navigation.

     UNLIKE --ochre, THIS DOES NOT FLIP LIGHT IN DARK MODE. It only goes a
     step lighter, so white on it stays white on it: 8.8:1 in light, 5.9:1
     in dark. That is why the rule below writes #fff and not var(--card) --
     var(--card) inverts to a near-black in dark mode and would vanish. */
  --forest:#1F5132;

  /* ---- TYPE SCALE -------------------------------------------------------
     Five steps, named, and nothing lands between them by accident. The step
     that did not exist before is --t-lead: the build had a 59px display and
     a 19px body with nothing in between, which is the same hole the old
     Squarespace page had (47.6px -> 17px). Standfirsts, door copy and
     section leads all sit on --t-lead now.

     It also fixes a quieter bug. Body was set to 19px but every prose block
     was sized in rem, and rem answers to the 16px ROOT, not to body — so
     copy that read as "19px" was actually rendering at 15.0-17.0px. Sizes
     below are stated against the 16px root on purpose; what you read here
     is what the browser computes. */
  --t-display: clamp(2.7rem,5.4vw,3.75rem); /* 43.2 -> 60px   h1 */
  --t-section: clamp(1.85rem,3vw,2.15rem);  /* 29.6 -> 34.4px h2 */
  --t-lead:    clamp(1.34rem,1.9vw,1.55rem);/* 21.4 -> 24.8px THE MISSING STEP */
  --t-body:    1.3125rem;                   /* 21px */
  --t-small:   1.1875rem;                   /* 19px — secondary prose floor */
  --t-mono:    .875rem;                     /* 14px */
  --t-mono-sm: .8125rem;                    /* 13px */

  /* Weights. Nothing that carries meaning is lighter than 400, and 300 is
     gone from this file entirely — it read as unfinished. */
  --w-body:400; --w-med:500; --w-head:600;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --paper:#131C1F; --card:#1B272B; --card-alt:#1F2D31;
    --ink:#E8E7DF; --ink-soft:#A6B2B5; --ink-faint:#7E8B8E;
    --teal:#6FC4CE; --teal-wash:#1E3438;
    --ochre:#D9A167; --ochre-wash:#2E2519;
    --rule:#314246; --rule-soft:#263539;
    --stamp:#D97A66; --shadow:rgba(0,0,0,.34);
    --tape:#E9E6DB; --tape-edge:#CFCABA; --tape-ink:#23231F; --tape-faint:#7A776C;
    --tape-fade:233,230,219;
    --hero-scrim-phone:linear-gradient(180deg,rgba(19,28,31,0) 52%,rgba(19,28,31,.55) 68%,rgba(19,28,31,.90) 82%,var(--paper) 96%);
    --hero-scrim:linear-gradient(90deg,rgba(19,28,31,.80) 0%,rgba(19,28,31,.70) 45%,rgba(19,28,31,.34) 68%,rgba(19,28,31,0) 84%);
    --tag:#E6DCC8; --tag-edge:#C3B69C;
    --tag-ink:#26241E; --tag-faint:#7B7464;
    --forest:#2C6A45;
  }
}
:root[data-theme="dark"]{
  --paper:#131C1F; --card:#1B272B; --card-alt:#1F2D31;
  --ink:#E8E7DF; --ink-soft:#A6B2B5; --ink-faint:#7E8B8E;
  --teal:#6FC4CE; --teal-wash:#1E3438;
  --ochre:#D9A167; --ochre-wash:#2E2519;
  --rule:#314246; --rule-soft:#263539;
  --stamp:#D97A66; --shadow:rgba(0,0,0,.34);
  --tape:#E9E6DB; --tape-edge:#CFCABA; --tape-ink:#23231F; --tape-faint:#7A776C;
  --tape-fade:233,230,219;
  --hero-scrim-phone:linear-gradient(180deg,rgba(19,28,31,0) 52%,rgba(19,28,31,.55) 68%,rgba(19,28,31,.90) 82%,var(--paper) 96%);
  --hero-scrim:linear-gradient(90deg,rgba(19,28,31,.80) 0%,rgba(19,28,31,.70) 45%,rgba(19,28,31,.34) 68%,rgba(19,28,31,0) 84%);
  --tag:#E6DCC8; --tag-edge:#C3B69C;
  --tag-ink:#26241E; --tag-faint:#7B7464;
  --forest:#2C6A45;
}

*{box-sizing:border-box}
/* Two blocks on the give and thank-you pages hid by attribute and showed
   anyway, because their own display:flex outranked the browser's default
   [hidden]{display:none}. Said once, for everything, with the weight to win. */
[hidden]{display:none !important}
html{ -webkit-text-size-adjust:100% }
body{
  margin:0;
  background:var(--paper); color:var(--ink);
  font-family:"Newsreader",Georgia,"Times New Roman",serif;
  font-size:var(--t-body); line-height:1.58;
  font-optical-sizing:auto; -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img{max-width:100%;height:auto}
.wrap{max-width:1020px;margin:0 auto;padding:0 28px}
.mono{font-family:"Courier Prime","Courier New",monospace}
a{color:var(--teal)}
a:focus-visible,button:focus-visible{outline:2px solid var(--ochre);outline-offset:3px}
.skip{position:absolute;left:-9999px}
.skip:focus{left:8px;top:8px;background:var(--card);padding:10px 14px;z-index:99}

/* --- review furniture. Tagged data-review so it lifts out in one pass. --- */
.reviewbar{
  background:var(--stamp);color:var(--card);
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;
  letter-spacing:.09em;text-transform:uppercase;
  padding:10px 28px;line-height:1.6;
}
.reviewbar b{font-weight:700}
.reviewbar a{color:var(--card)}
.note{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:12.5px;font-weight:700;letter-spacing:.05em;color:var(--stamp);
  margin:13px 0 0;text-transform:uppercase;line-height:1.6;
}
.hold{
  display:inline-block;border:1.5px dashed var(--stamp);color:var(--stamp);
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;
  padding:5px 10px;line-height:1.5;
}

/* --- masthead --- */
header.mast{padding:64px 0 0}

/* --- the photograph -------------------------------------------------------
   It is a portrait frame, 405x720 out of the camera, so it gets its own
   column beside the headline instead of being stretched across a wide band
   and cropped down to a letterbox that loses the bag. Under 860px the header
   stacks and the photo follows the words, capped so it never becomes the
   whole first screen on a phone. */
.hero{margin:34px 0 0;padding:0;max-width:420px}
/* Square, because the image on the page is square and a square frame crops it
   by exactly nothing. The two un-retouched photographs in assets/photos/ are
   portrait; if one of them is swapped in, nudge object-position to 50% 28%
   so the books and the bag both survive the crop. */
.heroimg{
  display:block;width:100%;
  aspect-ratio:1/1;object-fit:cover;object-position:50% 50%;
  border:1px solid var(--rule);background:var(--card-alt);
  box-shadow:0 1px 3px var(--shadow),0 6px 14px var(--shadow);
}
.hero .frame{aspect-ratio:1/1}
.hero .note{max-width:44ch}
.hero figcaption{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);line-height:1.65;color:var(--ink-faint);
  margin:11px 0 0;max-width:44ch;
}
.hero figcaption em{font-style:normal;color:var(--ink-soft)}
/* Only a masthead that actually carries the photograph becomes two columns.
   Scoped with a class rather than left on header.mast: the donor page has no
   hero and four direct children, so the bare rule dealt its eyebrow, headline
   and standfirst into the grid as three separate cells. */
/* --- HERO SIZE, DESKTOP. Mark, 2026-09-11: "the image of the tote with the
   bags just is not large enough. It doesn't pop. It's fine on the phone,
   actually, but on the laptop it's just underwhelming."

   He is right and the cause is structural, not a taste call. On a phone the
   header collapses to one column and the photo gets the full measure. On a
   laptop it was pinned to a FIXED 336px column inside a 964px page — 336x336,
   about 12% of the area above the fold, while the text column beside it ran
   528px tall. The photo was not competing with anything; it was a thumbnail
   with 117px of dead air under it.

   Fixed 336px is now two FRACTIONS, so the photo scales with the page instead
   of standing still while everything around it grows. 1.05fr / 1fr across the
   964px column with a 40px gutter gives the photo ~450px and the words ~473px,
   and the two columns now finish within a few pixels of each other. Fractions
   also fix the 861-1080px band, where a fixed 450 would have starved the
   headline. Nothing below 861px changes: the mobile rendering Mark says is
   already fine never enters this block. --- */
/* --- FULL-BLEED HERO, 2026-09-15. Mark's own comp: the photograph runs edge
   to edge, the words sit over the bright, out-of-focus left side, the bag
   holds the right. Below 601px the photo stacks above the words instead:
   type over a picture at 375px wide is unreadable, and Mark already likes the
   phone rendering. The scrim keeps the words legible on any frame, retouched
   or not. --- */
header.mast.bleed{
  position:relative;margin:18px 0 0;padding:0;
  width:100vw;margin-left:calc(50% - 50vw);
}
header.mast.bleed .hero{margin:0;max-width:none}
header.mast.bleed .heroimg{
  display:block;width:100%;aspect-ratio:4/3;object-fit:cover;
  object-position:50% 50%;border:0;box-shadow:none;background:var(--card-alt);
}
header.mast.bleed .masttext{padding:28px 20px 0}
/* --- PHONE: the headline sits ON the photograph, the rest below it -------
   Mark, 2026-09-21: "the words below the bag are not going to work." The
   whole text block will not fit on the picture without the haze swallowing
   the bag — seven lines need seven lines of cover. The headline alone is
   three, so only the headline goes on the frame and the credits fall past
   the photograph's foot onto the page. The frame fades to --paper at 96%,
   so there is no edge where one becomes the other. */
@media (max-width:600px){
  header.mast.bleed .hero{position:relative;margin:0}
  header.mast.bleed .heroimg{aspect-ratio:4/5;object-position:90% 26%}
  header.mast.bleed .hero::after{
    content:"";position:absolute;inset:0;pointer-events:none;
    background:var(--hero-scrim-phone);
  }
  /* Lifts the block so the headline lands in the hazed foot of the frame.
     Tied to viewport width, like the headline's own size, so the two move
     together instead of drifting apart between 320 and 600. */
  header.mast.bleed .masttext{position:relative;z-index:1;margin-top:-31vw;padding:0 20px 0}
  /* Same words as the bar directly above it, 40px apart. */
  header.mast.bleed .eyebrow{display:none}
  header.mast.bleed h1{font-size:clamp(30px,8.6vw,36px);line-height:1.08;margin:0 0 20px}
  header.mast.bleed .standfirst{font-size:16px;line-height:1.55;margin:0 0 12px}
  header.mast.bleed .standfirst:last-child{margin-bottom:0}
  header.mast.bleed .standfirst.promise-line{font-size:19px;line-height:1.45;margin:0 0 14px}
}
@media (min-width:601px){
  /* The hero's height used to come only from the copy, so the wider the
     window the flatter the frame and the harder `cover` cropped it. Past
     about 1400px that is what ate the table edge and the base of the bag.
     Height now grows with width until it stops at 900. */
  header.mast.bleed{min-height:clamp(480px,46vw,940px);overflow:hidden}
  header.mast.bleed .hero{position:absolute;inset:0}
  /* Past about 1200px the frame is width-bound and the crop is all vertical.
     Centred, it cut the table edge and the base of the bag, which left the
     bag looking like it was sliding out of the frame. Weighted low, the bag
     sits on the table and the blurred ceiling goes instead. */
  /* Weighted low, not centred: the crop is entirely vertical once the frame
     is width-bound, and what we want kept is the table edge and the base of
     the bag. What goes instead is blurred ceiling. 62% was not far enough —
     it still cut the base at every width past about 1400. */
  header.mast.bleed .heroimg{height:100%;aspect-ratio:auto;object-position:50% 80%}
  /* Same content column as .wrap (1020 minus 28px gutters), so the hero
     headline starts on the same vertical as the wordmark above it and the
     body copy below it. It used to be 964/24, which put the words 24px
     inboard of the rest of the page and read as a hero pushed right. */
  header.mast.bleed .masttext{
    position:relative;z-index:1;
    max-width:1020px;margin:0 auto;padding:64px 28px 56px;
    width:100%;box-sizing:border-box;
  }
  /* The bright wall in the photograph runs to about 47% of the frame, so the
     words can hold half of it without ever touching the bag. */
  header.mast.bleed .masttext > *{max-width:52%}
  header.mast.bleed h1{max-width:13ch;font-size:clamp(34px,4.6vw,64px);margin-bottom:20px}
  /* The standfirst is 17px on a photograph, so it gets a tighter cap than
     the headline: big display type survives sitting over the blurred books,
     body type does not. */
  header.mast.bleed .standfirst{font-size:clamp(17px,1.35vw,20px);max-width:42%}
  /* Past 1200 the centred page column strands the copy in the middle of the
     photograph: at 2000px it left about 490px of empty wall to its left.
     On a bleed hero the copy belongs near the picture's own left edge, so
     above this width it stops using the centred column and takes a margin
     that grows with the window instead. It no longer lines up with the
     wordmark in the bar above, which is on its own ground and its own strip.
     The caps move to vw for the same reason: they used to be a percentage of
     a column that no longer exists here. */
  @media (min-width:1201px){
    header.mast.bleed .masttext{
      max-width:none;margin:0;
      padding-left:clamp(28px,11vw,240px);padding-right:28px;
    }
    header.mast.bleed .masttext > *{max-width:min(560px,34vw)}
    header.mast.bleed .standfirst{max-width:min(460px,28vw)}
  }
  /* Between about 900 and 1200 the frame is height-bound, so the bag climbs
     further left in CSS pixels and the copy has to give ground with it. */
  @media (max-width:1200px){
    header.mast.bleed .masttext > *{max-width:46%}
    header.mast.bleed .standfirst{max-width:38%}
  }
  /* Narrow laptops and split panes: the words keep to the bright left third
     and the picture slides right so the bag never runs under the copy. */
  @media (max-width:900px){
    header.mast.bleed .masttext > *{max-width:44%}
    header.mast.bleed .standfirst{font-size:16px}
    header.mast.bleed .heroimg{object-position:72% 70%}
  }
  /* Scrim: the words need a quiet ground even on an un-retouched frame. */
  header.mast.bleed .hero::after{
    content:"";position:absolute;inset:0;
    background:var(--hero-scrim);
  }
}
}
/* The promise, standing alone since 2026-09-21. It carries full --ink where
   the provenance around it is --ink-soft, so it reads as the page talking
   rather than a caption, and it takes the lead step of the type scale. It is
   not bold: on a paragraph of its own, weight on top of colour and size is
   one signal too many. */
/* Scoped past `header.mast.bleed .standfirst`, which is more specific than a
   bare class and was overriding both the size and the colour. */
header.mast.bleed .standfirst.promise-line{
  color:var(--ink);font-size:var(--t-lead);line-height:1.4;
  margin:0 0 22px;max-width:26ch;
}
.eyebrow{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono);font-weight:700;
  letter-spacing:.16em;text-transform:uppercase;
  color:var(--teal);margin:0 0 22px;
}
h1{
  font-size:var(--t-display);
  font-weight:var(--w-head);line-height:1.08;letter-spacing:-.02em;
  margin:0 0 24px;text-wrap:balance;max-width:19ch;
}
.standfirst{
  font-size:var(--t-lead);color:var(--ink-soft);font-weight:var(--w-body);
  max-width:56ch;margin:0 0 10px;line-height:1.46;
}
.standfirst strong{color:var(--ink);font-weight:var(--w-head)}

/* --- the two doors --- */
/* Below the doors since 2026-09-21, so it needs air above it, not below. */
/* .landing-donate retired 2026-09-22 -- its one rule is now .donate-centre,
   which every page's Donate Now uses. */
.doors{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));
  gap:26px;margin:54px 0 0;
}
.door{
  background:var(--card);border:1px solid var(--rule);
  box-shadow:0 1px 2px var(--shadow);
  display:flex;flex-direction:column;position:relative;overflow:hidden;
}
.doorhead{padding:30px 30px 0}
.doortag{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;
  letter-spacing:.15em;text-transform:uppercase;
  color:var(--ink-faint);margin:0 0 14px;
}
.door h2{font-size:var(--t-section);font-weight:var(--w-head);letter-spacing:-.015em;margin:0 0 12px;line-height:1.14}
.door .promise{font-size:var(--t-body);font-weight:var(--w-med);color:var(--ink);margin:0 0 6px;max-width:34ch;line-height:1.46}
.door .sub{color:var(--ink-soft);font-weight:var(--w-body);font-size:var(--t-small);margin:10px 0 0;max-width:36ch;line-height:1.5}

/* each door shows its own paper — a sliver of its own artifact */
.peek{margin:26px 0 0;padding:0 30px;flex:1}
.peekcard{
  border:1px solid var(--rule);background:var(--card-alt);
  padding:15px 17px;position:relative;overflow:hidden;height:186px;
}
.peekcard:after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:78px;
  background:linear-gradient(to bottom,transparent,var(--card) 88%);
}
.peekline{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:12.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-faint);margin:0 0 9px;
}
.peekttl{font-size:var(--t-small);font-weight:var(--w-head);margin:0 0 3px;line-height:1.3}
.peekmeta{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;
  color:var(--teal);margin:0 0 13px;letter-spacing:.05em;
}
.peekbody{font-size:1.0625rem;color:var(--ink-soft);font-weight:var(--w-body);line-height:1.5;margin:0}
/* The donor door's peek — the gift tag, on its own card stock. It carries
   beat one and beat four at once (somebody in this town paid for this, and
   they may or may not have put their name on it), which the tape did not. */
/* Height to CONTENT, not the fixed 186px the schools card uses. That card is
   a sliver of a longer thing and is meant to run out of room; the tag is a
   whole small object, and on a phone the fixed box ate its last line. */
.peekcard.tagstock{
  background:var(--tag);border-color:var(--tag-edge);
  height:auto;min-height:186px;padding-bottom:22px;
}
.peekcard.tagstock:after{height:34px;background:linear-gradient(to bottom,transparent,var(--tag) 92%)}
.peekcard.tagstock .peekline{color:var(--tag-faint)}
.peekttl.tagcentre{text-align:center;margin-top:20px;font-weight:var(--w-body);color:var(--tag-ink)}
.peekcard .tagrule{border-bottom:1px solid var(--tag-faint);height:20px;margin:10px 14px 14px}
.peekbody.tagfoot{
  text-align:center;font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;letter-spacing:.09em;
  color:var(--tag-faint);line-height:1.7;
}

.doorfoot{padding:24px 30px 30px}
.btn{
  display:inline-block;font-family:"Courier Prime","Courier New",monospace;
  font-size:15.5px;letter-spacing:.06em;text-transform:uppercase;font-weight:700;
  /* --paper, not #fff: --ochre flips light in dark mode and white on it
     measured 2.27:1. --paper inverts with the theme. */
  background:var(--ochre);color:var(--card);border:0;padding:15px 24px;
  text-decoration:none;cursor:pointer;
}
.btn.ghost{background:transparent;color:var(--teal);border:1.5px solid var(--teal);padding:13.5px 22px}
/* DONATE NOW, launch review 1.10 / 2.8 / 3.6 / 5.3. Filled, not ghosted:
   on index and whats-the-story this button was outlined and sitting in a
   left-ranged paragraph, which made the one thing a donor is here to do the
   quietest control on the page. #fff is literal on purpose -- see --forest. */
.btn.donate{background:var(--forest);color:#fff;border:0;padding:15px 24px}
/* The centring half of the same three items. A wrapper, not text-align on the
   section, so nothing else inside it moves. */
.donate-centre{margin:34px 0 4px;text-align:center}
.cross{
  margin:16px 0 0;font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);letter-spacing:.05em;color:var(--ink-faint);
}
.cross a{color:var(--ink-faint);text-decoration-color:var(--rule)}

/* ==========================================================================
   THE SHELF — five covers in one flush row, under the doors and above the
   strip. Spec is Toby's rev 3 §5; the reasons for the odd-looking parts:

   repeat(5,1fr) and NOT auto-fit. The row must stay five across at every
   width, phone included. A 3-plus-2 wrap breaks the line and reads as a bug.
   At 375px that is about 60px a cover — too small to read a title, still
   plainly five books in a row of colour, which is the gesture Mark asked for.

   RAGGED TOPS WERE DELIBERATE UNTIL 2026-09-22, AND ARE NOW DELIBERATELY
   GONE. Toni's launch review, 1.11: "Equalize the size of the book cover
   images" -- Good to Go and A Little Something read as smaller books, not as
   books sitting on a shelf. Measured: those two are 0.782 wide-to-tall, the
   other three 0.751, so at equal track widths the pair rendered about 9px
   short.

   The fix is a fixed box at the MEAN ratio with object-fit:contain, so every
   cover gets an identical frame and NOTHING IS CROPPED. The cost is a band of
   card colour inside the border -- under 3px at desktop width, on one axis
   for the wide pair and the other axis for the tall three. Cropping would
   have cost 2% off the top and bottom of two covers instead, which is not a
   trade to make on somebody's artwork.

   This overrides the old note here, which said FEET ALIGN AND TOPS ARE RAGGED
   ON PURPOSE, DO NOT NORMALIZE. It was true and it was Mark's; the review
   changed it, and it is recorded rather than quietly dropped. Mark confirmed
   the reversal on 2026-09-23 after seeing it on the preview. Do not restore
   the ragged tops as a fix.

   Nothing below it. The strip's own 44px margin and 1.5px ink rule do that
   work, and doubling the gap would float the fine print mid-page.
   ========================================================================== */
.bookrow{
  display:grid;grid-template-columns:repeat(5,1fr);
  gap:18px;align-items:end;margin:42px 0 0;
}
.bookrow img{
  display:block;width:100%;height:auto;
  /* 0.766 is the mean of the two cover ratios in the set (0.782 / 0.751).
     Sizing to either end would push the whole band onto one group. */
  aspect-ratio:0.766;object-fit:contain;
  border:1px solid var(--rule);background:var(--card);
  box-shadow:0 1px 3px var(--shadow),0 6px 14px var(--shadow);
}

.groundrule{
  margin:44px 0 0;padding:22px 0 0;border-top:1.5px solid var(--ink);
  display:grid;grid-template-columns:repeat(auto-fit,minmax(215px,1fr));gap:22px;
}
.groundrule div{font-size:var(--t-small);color:var(--ink-soft);font-weight:var(--w-body);line-height:1.5}
.groundrule b{
  display:block;font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-faint);margin:0 0 7px;font-weight:700;
}

/* --- sections --- */
.sec{padding:68px 0 0}
h2.sechead,h3.sechead{
  font-size:var(--t-section);font-weight:var(--w-head);letter-spacing:-.012em;
  margin:0 0 14px;line-height:1.2;text-wrap:balance;
}
.lede{font-size:var(--t-lead);color:var(--ink-soft);max-width:58ch;margin:0 0 30px;font-weight:var(--w-body);line-height:1.46}
.lede strong{color:var(--ink);font-weight:var(--w-head)}

/* ==========================================================================
   DONOR PAGE — rev 2, four beats. Structure and copy are Toby's re-cut of
   2026-09-11; sizes and weights are this build's scale, so nothing here
   reaches for a rem against the 16px root or a 300 weight.
   ========================================================================== */
.beat{padding:54px 0 0;border-top:1px solid var(--rule-soft)}
.beat:first-of-type{border-top:0;padding-top:34px}
.beatno{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;
  letter-spacing:.16em;text-transform:uppercase;
  color:var(--teal);margin:0 0 14px;
}
.beat .sechead{max-width:22ch}
.body p{max-width:58ch;color:var(--ink-soft);font-weight:var(--w-body);margin:0 0 16px;line-height:1.54}
.body p:last-child{margin-bottom:0}
.body p strong{color:var(--ink);font-weight:var(--w-head)}
.body p em{font-style:italic;color:var(--ink)}

.twocol{display:grid;grid-template-columns:1fr minmax(280px,380px);gap:54px;align-items:start}
@media (max-width:880px){.twocol{grid-template-columns:1fr;gap:32px}}

/* --- beat one: the place field ---------------------------------------------
   Deliberately not an <input>. Nothing on this page submits anywhere yet, and
   a box that accepts typing and then drops it on the floor is worse than one
   that plainly does not take it. The caret is the whole device: asking is a
   different act from describing. */
.placebox{
  background:var(--card);border:1px solid var(--rule);
  box-shadow:0 1px 2px var(--shadow);padding:26px 28px 28px;
}
.placelbl{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-faint);margin:0 0 12px;
}
.placefield{
  border:1.5px solid var(--ink);background:var(--card-alt);
  padding:14px 16px;font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono);color:var(--ink-faint);letter-spacing:.02em;
  display:flex;align-items:center;gap:2px;
}
.caret{
  display:inline-block;width:1.5px;height:1.25em;background:var(--ochre);
  animation:blink 1.15s step-end infinite;flex-shrink:0;
}
@keyframes blink{50%{opacity:0}}
.chips{display:flex;flex-wrap:wrap;gap:7px;margin:14px 0 0}
.chips .chip{color:var(--teal);background:var(--card-alt)}
.placehelp{margin:16px 0 0;font-size:var(--t-small);color:var(--ink-soft);font-weight:var(--w-body);line-height:1.55}
.placehelp strong{color:var(--ink);font-weight:var(--w-head)}

/* --- beat two: the three numbers --- */
.tiers{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  gap:1px;background:var(--rule);border:1px solid var(--rule);margin:8px 0 26px;
}
.tier{background:var(--card);padding:24px 22px}
.tier .amt{
  font-size:2.25rem;font-weight:var(--w-head);letter-spacing:-.02em;line-height:1;
  margin:0 0 10px;color:var(--ink);
}
.tier .amt small{font-size:var(--t-small);font-weight:var(--w-body);color:var(--ink-faint);letter-spacing:0}
.tier p{margin:0;font-size:var(--t-small);color:var(--ink-soft);font-weight:var(--w-body);line-height:1.5}
.tier p strong{color:var(--ink);font-weight:var(--w-head)}
.storylink{
  font-family:"Courier Prime","Courier New",monospace;font-size:var(--t-mono);
  letter-spacing:.05em;margin:22px 0 0;
}

/* --- beat three: the Septembers rail --- */
.rail{margin:10px 0 0;border-left:1.5px solid var(--rule)}
.rung{position:relative;padding:0 0 26px 30px}
.rung:before{
  content:"";position:absolute;left:-5.5px;top:.55em;width:9px;height:9px;
  background:var(--teal);border-radius:50%;
}
.rung:last-child{padding-bottom:4px}
.rung .when{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;
  letter-spacing:.13em;text-transform:uppercase;
  color:var(--teal);margin:0 0 5px;
}
.rung p{margin:0;color:var(--ink-soft);font-weight:var(--w-body);max-width:46ch;line-height:1.52}
.rung p strong{color:var(--ink);font-weight:var(--w-head)}

.layerbox{background:var(--card);border:1px solid var(--rule);padding:24px 26px;margin:28px 0 0}
.layerbox.nogap{margin-top:0}
.layerbox h4{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);letter-spacing:.14em;text-transform:uppercase;
  color:var(--teal);margin:0 0 12px;font-weight:700;
}
.layerbox p{margin:0 0 13px;font-size:var(--t-small);color:var(--ink-soft);font-weight:var(--w-body);line-height:1.56}
.layerbox p:last-child{margin-bottom:0}
.layerbox strong{color:var(--ink);font-weight:var(--w-head)}

/* --- beat four: the gift tag --- */
.tagwrap{display:flex;justify-content:center;padding:6px 0 0}
.gifttag{
  background:var(--tag);border:1px solid var(--tag-edge);
  width:100%;max-width:362px;padding:30px 26px 26px;position:relative;
  box-shadow:0 4px 14px var(--shadow);transform:rotate(-1.3deg);
}
.gifttag:before{
  content:"";position:absolute;top:13px;left:50%;transform:translateX(-50%);
  width:13px;height:13px;border-radius:50%;
  background:var(--paper);border:1px solid var(--tag-edge);
}
.tagline1{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;letter-spacing:.18em;text-transform:uppercase;
  color:var(--tag-faint);text-align:center;margin:16px 0 20px;
}
.tagbig{font-size:var(--t-body);font-weight:var(--w-body);color:var(--tag-ink);text-align:center;margin:0 0 6px;line-height:1.4}
.tagrule{border-bottom:1px solid var(--tag-faint);height:26px;margin:8px 14px 12px}
.tagfoot{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;letter-spacing:.13em;text-transform:uppercase;
  color:var(--tag-faint);text-align:center;margin:0;line-height:1.7;
}

/* --- and the money: the fragment ------------------------------------------
   It is 32 monospace characters wide in a column that can be narrower than
   32 characters want to be. Sized off the container rather than in fixed px,
   because a fixed size is exactly how the peek card clipped its own amounts
   column: 32 chars x 0.6em advance needs font-size <= (box - padding) / 19.2,
   and 19.8 leaves slack. min() stops it growing past the mono scale. */
.costrow{display:grid;grid-template-columns:1fr minmax(250px,300px);gap:44px;align-items:start}
@media (max-width:880px){.costrow{grid-template-columns:1fr;gap:28px}}
.tapewrap{position:relative;filter:drop-shadow(0 4px 12px var(--shadow));container-type:inline-size}
/* Height in em, not px, so the window keeps showing the SAME rows when the
   font sizes itself down in a narrow column. 26.9em is 15.1 rows at the 1.78
   line, which — starting 0.79 of a row up — ends the sheet part-way through
   the list of book titles rather than at a section head. */
.tapecrop{
  background:var(--tape);height:26.9em;overflow:hidden;position:relative;
  font-size:min(var(--t-mono-sm),calc((100cqw - 36px) / 19.8));
}
.tapefrag{
  font-size:inherit;
  line-height:1.78;color:var(--tape-ink);
  padding:0 18px;white-space:pre;letter-spacing:.005em;
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum";
  /* the sheet starts mid-row: a cut BETWEEN two lines reads as a design
     decision, a cut THROUGH a row reads as a sheet that continues */
  margin:-1.4em 0 0;
}
.fadetop,.fadebot{position:absolute;left:0;right:0;height:44px;pointer-events:none;z-index:2}
.fadetop{top:0;background:linear-gradient(to bottom,var(--tape) 6%,rgba(var(--tape-fade),0) 100%)}
.fadebot{bottom:0;background:linear-gradient(to top,var(--tape) 6%,rgba(var(--tape-fade),0) 100%)}
.tapecap{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);letter-spacing:.05em;color:var(--ink-faint);
  margin:14px 2px 0;line-height:1.65;
}

.ctarow{display:flex;flex-wrap:wrap;gap:14px;align-items:center;margin:30px 0 0}
.ctanote{
  font-family:"Courier Prime","Courier New",monospace;font-size:var(--t-mono-sm);
  color:var(--ink-faint);letter-spacing:.04em;
}

/* --- a bracketed blocker, on the page and visible. Same family as .hold and
   .note: tagged data-review so the whole lot lifts out in one pass. --- */
.gate{
  border:2px dashed var(--stamp);padding:16px 18px;margin:26px 0 0;
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);line-height:1.7;color:var(--ink-soft);
}
.gate em{
  color:var(--stamp);font-style:normal;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;display:block;margin-bottom:8px;
}
.gate b{color:var(--ink);font-weight:700}
.gate code{background:var(--ochre-wash);color:var(--ochre);padding:1px 5px;font-weight:700}

/* --- facts rail --- */
.facts{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(185px,1fr));
  gap:0;margin:48px 0 0;border-top:1.5px solid var(--ink);border-bottom:1px solid var(--rule);
}
.fact{padding:20px 22px 22px 0;border-right:1px solid var(--rule-soft)}
.fact:last-child{border-right:0}
.fact dt{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;
  letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-faint);margin:0 0 7px;
}
.fact dd{margin:0;font-size:var(--t-small);font-weight:var(--w-med);line-height:1.42}

/* --- catalog cards --- */
.shelf{display:flex;flex-direction:column;gap:22px}
.bk{
  display:grid;grid-template-columns:212px 1fr;gap:0;
  background:var(--card);border:1px solid var(--rule);box-shadow:0 1px 2px var(--shadow);
}
.bk:nth-child(even){background:var(--card-alt)}
.plate{border-right:1px solid var(--rule);padding:22px;display:flex;align-items:flex-start;justify-content:center}
.frame{
  width:100%;aspect-ratio:5/6.4;border:1.5px dashed var(--ink-faint);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:7px;padding:14px;text-align:center;color:var(--ink-faint);background:transparent;
}
.frame span{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:12px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;line-height:1.5;
}
.frame .glyph{font-size:22px;line-height:1;opacity:.55}
/* A real cover. Books are 8.75x11.25 trim; the image carries its own ratio,
   so nothing is cropped and nothing is stretched. The board edge is a 1px
   rule plus a small drop, which is as close to "a book on a shelf" as this
   wants to get. */
.plate .cover{
  display:block;width:100%;height:auto;
  border:1px solid var(--rule);
  box-shadow:0 1px 3px var(--shadow),0 6px 14px var(--shadow);
  background:var(--card);
}
.bkbody{padding:24px 26px 26px}
.bk h3{font-size:1.8rem;font-weight:var(--w-head);letter-spacing:-.015em;margin:0 0 3px;line-height:1.16}
.byline{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;color:var(--ink-faint);margin:0 0 16px;letter-spacing:.02em;
}
.card-meta{
  display:flex;flex-wrap:wrap;gap:6px 8px;align-items:center;
  padding:0 0 15px;margin:0 0 16px;border-bottom:1px solid var(--rule-soft);
}
.chip{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:12.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  padding:4px 10px;border:1px solid var(--rule);color:var(--ink-soft);white-space:nowrap;
}
.chip.grade{border-color:var(--ochre);color:var(--ochre);background:var(--ochre-wash);font-weight:700}
.chip.place{border-color:var(--teal);color:var(--teal);background:var(--teal-wash)}
.about{margin:0 0 15px;max-width:60ch}
.pull{
  margin:0 0 15px;padding:0 0 0 15px;border-left:2.5px solid var(--teal);
  font-size:var(--t-lead);font-weight:var(--w-body);font-style:italic;
  color:var(--ink);max-width:52ch;line-height:1.44;
}
.pull cite{
  display:block;font-style:normal;font-family:"Courier Prime","Courier New",monospace;
  font-size:12.5px;font-weight:700;letter-spacing:.06em;color:var(--ink-faint);margin-top:7px;text-transform:uppercase;
}
.asks{display:flex;gap:10px;align-items:baseline;padding-top:14px;border-top:1px solid var(--rule-soft);max-width:60ch;margin:0}
.asks dt{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:12.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-faint);white-space:nowrap;flex-shrink:0;
}
.asks dd{margin:0;font-size:var(--t-small);font-weight:var(--w-med);line-height:1.45}

/* --- how it works --- */
.how{
  margin-top:20px;border-top:1.5px solid var(--ink);
  display:grid;grid-template-columns:repeat(auto-fit,minmax(235px,1fr));gap:0;
}
.how div{padding:22px 24px 26px 0;border-right:1px solid var(--rule-soft)}
.how div:last-child{border-right:0}
.how h3{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);letter-spacing:.13em;text-transform:uppercase;
  color:var(--teal);margin:0 0 9px;font-weight:700;
}
.how p{margin:0;font-size:var(--t-small);color:var(--ink-soft);line-height:1.5}

.close{margin:60px 0 0;padding:34px 0 0;border-top:1px solid var(--rule)}
.close p{max-width:58ch;color:var(--ink-soft);margin:0 0 20px}
/* .close p caps its paragraphs at 58ch, and the Donate Now wrapper IS one of
   them, so text-align:center was centring the button inside a 673px column
   inside a 964px section -- 145px left of where it looked centred. Same
   specificity as .close p, declared after it, so this wins on source order.
   Anything that later moves .donate-centre above this line breaks it again. */
p.donate-centre{max-width:none}
a.out{
  display:inline-block;color:var(--teal);text-decoration:none;
  border-bottom:1.5px solid var(--teal);padding-bottom:2px;font-size:var(--t-body);font-weight:var(--w-med);
}
a.out:hover{color:var(--ink);border-color:var(--ink)}

/* --- header / footer --- */
.minihead{
  border-bottom:1px solid var(--rule);padding:16px 0;
  display:flex;justify-content:space-between;align-items:baseline;gap:16px;flex-wrap:wrap;
}
.minihead .brand{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--ink);text-decoration:none;
}
/* Lives in the footer since 2026-09-21, not the head bar. Given --teal and a
   little air, because down there it is the only link on the strip and has to
   read as one; in the head bar it was the opposite problem. */
.sitefoot .back{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;letter-spacing:.05em;
  color:var(--teal);text-decoration:none;display:inline-block;margin:0 0 12px;
}
footer.sitefoot{
  margin:78px 0 0;padding:26px 0 62px;border-top:1px solid var(--rule);
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);letter-spacing:.05em;color:var(--ink-faint);line-height:1.9;
}

@media (max-width:700px){
  /* Override the scale, not body alone — everything sized in var(--t-*)
     follows. Body stays a full step above where it was (18px -> 20px). */
  :root{--t-body:1.25rem;--t-small:1.125rem}
  .wrap{padding:0 20px}
  header.mast{padding:40px 0 0}
  .bk{grid-template-columns:1fr}
  .plate{border-right:0;border-bottom:1px solid var(--rule);padding:20px 20px 0}
  .frame{aspect-ratio:5/3;max-width:220px;margin:0 auto}
  .plate .cover{max-width:180px;margin:0 auto 20px}
  .bkbody{padding:20px}
  /* The shelf stays five across and shrinks. Gutters down to 7px because 18
     is a quarter of a cover at this width, and the shadow comes off: a 6px
     drop under a 60px cover is a smudge, not a board edge. */
  .bookrow{gap:7px;margin-top:34px}
  .bookrow img{box-shadow:none}
  .fact,.how div{border-right:0;border-bottom:1px solid var(--rule-soft);padding-right:0}
  .fact:last-child,.how div:last-child{border-bottom:0}
  .asks{flex-direction:column;gap:4px}
  /* The fragment gets the full column width once .costrow stacks, so it
     sizes itself up and keeps the same window on the sheet — no override.
     A shorter one here stopped the crop before the book titles. */
  .beat{padding-top:40px}
  .placebox,.layerbox{padding:20px 20px 22px}
}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* Joslin proof photograph, closing beat one */
.proof{margin:34px 0 0;padding:0}
.proof img{width:100%;height:auto;display:block;border-radius:2px}
.proof figcaption{
  margin-top:10px;font-family:var(--mono,ui-monospace,monospace);
  font-size:var(--t-fine);letter-spacing:.04em;color:var(--ink-soft);text-transform:uppercase
}

/* ==========================================================================
   DONOR PAGE REV 3 — 2026-09-17, carried from the design canvas.
   Mark's headline runs two lines; the lede's last beat is the accent; the
   ring is everything that arrives in the classroom, laid out on a square
   whose children are placed in percentages so it scales to a phone.
   ========================================================================== */
header.mast.donor h1{max-width:24ch;font-size:clamp(2.1rem,4.2vw,2.9rem);line-height:1.12}
.standfirst.donorlede{font-size:clamp(1.5rem,3vw,2.3rem);font-weight:var(--w-head);color:var(--ink);line-height:1.15;letter-spacing:-.015em;max-width:30ch;margin-top:6px}
.standfirst.donorlede .accent{color:var(--teal);font-weight:var(--w-head)}

.ringsec{padding-top:34px;display:flex;justify-content:center}
/* 920px, up from 840 (launch review 3.7): Mark wanted the ring to extend
   further and sit "more in proportion with the text below it". The covers
   grow inside it as well, and every ring child is placed in percentages, so
   this one number scales the whole composition. */
.ring{position:relative;width:min(920px,100%);aspect-ratio:1/1}
.ring > *{position:absolute;transform:translate(-50%,-50%)}
.ring-centre{left:50%;top:47%;width:32%;display:flex;flex-direction:column;align-items:center;gap:.4em;text-align:center}
.ring-head{margin:0;font-size:clamp(1rem,4.3vw,2.25rem);font-weight:var(--w-head);line-height:1.1;letter-spacing:-.015em}
.ring-sub{margin:0;font-size:clamp(.72rem,2.1vw,1.125rem);line-height:1.4;color:var(--ink-soft)}
.ring-bag{left:50%;top:16.7%;width:28.3%;height:auto;object-fit:contain;filter:drop-shadow(0 8px 14px rgba(23,40,44,.18))}
.ring-cover{width:20%;height:auto;border:1px solid var(--rule);background:var(--card);box-shadow:0 1px 3px var(--shadow),0 8px 18px rgba(23,40,44,.12)}
.ring-cover.c1{left:77.6%;top:27.7%}
.ring-cover.c2{left:84.5%;top:57.7%}
.ring-cover.c3{left:65.4%;top:81.5%}
.ring-cover.c4{left:34.6%;top:81.5%}
.ring-cover.c5{left:15.5%;top:57.7%}
/* 3.8: THE TILT IS GONE. The tag was the only object in the ring at an
   angle and the five covers around it are square to the page; Zane offered
   to tilt everything instead, Mark chose all straight.
   3.9: and the stock is now --tag / --tag-edge, the tokens the identical
   gift tag on index.html already uses. It was hardcoded #E7C9A9, which is
   a good deal warmer -- Mark read it as too red on a screen -- and being
   hardcoded it also never followed dark mode. Both fixed by the same line. */
.ring-tag{left:22.4%;top:27.7%;width:20%;box-sizing:border-box;transform:translate(-50%,-50%);
  border:1px solid var(--tag-edge);background:var(--tag);padding:1.1em .9em 1.2em;display:flex;flex-direction:column;gap:.3em;
  box-shadow:0 1px 3px var(--shadow),0 8px 18px rgba(23,40,44,.12);font-size:clamp(.42rem,1.1vw,.62rem)}
.ring-tag p{margin:0}
.tag-brand{font-family:"Courier Prime","Courier New",monospace;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--tag-faint)}
.tag-big{margin-top:.4em!important;text-align:center;font-size:1.45em;line-height:1.3;color:var(--tag-ink)}
.tag-rule{border-bottom:1px solid var(--tag-faint);height:1.1em;margin:0 .7em .5em}
.tag-foot{text-align:center;font-family:"Courier Prime","Courier New",monospace;font-weight:700;letter-spacing:.09em;line-height:1.6;color:var(--tag-faint)}

.donorgrid{columns:2;column-gap:56px;padding-top:56px}
.dsec{break-inside:avoid;margin:0 0 40px}
@media (max-width:700px){.donorgrid{columns:1}}
.dsec .sechead{margin-bottom:12px}
.dsec .body p{max-width:none}

/* align-items:center, launch review 3.6. The give block was left-ranged under
   a two-column grid, so on a wide screen the button sat under the left
   column with the right column's last paragraph beside it. */
.give{padding-top:52px;display:flex;flex-direction:column;gap:18px;align-items:center}
.btn.big{font-size:clamp(1rem,2.2vw,1.35rem);background:var(--teal);color:var(--card);border-radius:6px;padding:16px 26px}
/* .btn.big sets its own fill and comes later in this file than .btn.donate,
   so the two-class selector is what makes the forest green stick on the big
   buttons. Same reason #fff is literal here -- see --forest. */
.btn.big.donate{background:var(--forest);color:#fff}
.give .fine{margin:0;max-width:62ch;font-family:"Courier Prime","Courier New",monospace;font-size:var(--t-mono);line-height:1.75;color:var(--ink-soft)}
.give .fine strong{color:var(--ink)}
.give .fine a{color:var(--teal)}
@media (max-width:600px){
  /* THE RING STOPS BEING A RING ON A PHONE, because at ~335px across it
     cannot be one. The geometry, measured on production 2026-09-20: the
     centre copy runs to 70% of the ring's width and cover c1 starts at
     67.3%, so the two overlap by about 9px and the heading lost a letter
     behind Good to Go. Narrowing the centre does not save it -- clearing
     the covers needs it under 34.6% (~116px), and the heading at its 16px
     floor then wraps to six-plus lines and meets the covers underneath
     instead. A five-cover ring plus centred copy needs room this width
     does not have.

     So below 600px the same five covers, the bag and the copy unwind into
     a stack: bag, then the copy, then the covers in one row of five. The
     children are absolutely positioned for the ring, so they are put back
     into normal flow here and laid out on a five-column grid; their c1-c5
     left/top percentages simply stop applying. Nothing above 600px moves. */
  .ring{
    position:static;aspect-ratio:auto;width:100%;
    display:grid;grid-template-columns:repeat(5,1fr);
    gap:14px 8px;align-items:end;justify-items:center;
  }
  .ring > *{position:static;transform:none}
  /* THE BUNDLE, Mark 2026-09-23: "the tote looks weird separated from the
     other products that come in it", and then "a frame around it so it
     looks like a bundle". So the question comes FIRST, and the tote, the
     five books and the tag card sit together below it inside one frame.
     The tag is back on phones too -- it had been hidden here since 9/20.

     The frame is .ring::before, a grid item spanning rows 2-4 behind the
     others. Every child is placed on an explicit row and column, because a
     pseudo-element that covers cells pushes auto-placed items out into new
     implicit columns -- the first render of this put the five covers in a
     sixth column and squeezed the rest into the first. */
  .ring{row-gap:0}
  .ring-centre{grid-row:1;grid-column:1/-1;width:100%;margin-bottom:22px}
  .ring-bag{grid-row:2;grid-column:1/-1;width:58%;margin:20px 0 10px}
  .ring-cover{grid-row:3;width:100%}
  .ring-cover.c1{grid-column:1} .ring-cover.c2{grid-column:2}
  .ring-cover.c3{grid-column:3} .ring-cover.c4{grid-column:4}
  .ring-cover.c5{grid-column:5}
  .ring-tag{grid-row:4;grid-column:1/-1;width:66%;margin:22px 0 20px}
  .ring-bag,.ring-cover,.ring-tag{z-index:1}
  .ring::before{
    content:"";grid-row:2/5;grid-column:1/-1;align-self:stretch;justify-self:stretch;
    margin:0 -12px;z-index:0;
    background:var(--card);border:1.5px solid var(--rule);border-radius:6px;
  }
  /* Freed from the ring, the copy can take the width it actually wants. */
  .ring-head{font-size:clamp(1.25rem,6vw,1.75rem)}
  .ring-sub{font-size:1rem}
}

/* Mark, 2026-09-17: centre the masthead with the page. The ring below it is
   centred, so a left-ranged masthead read as two different pages stacked.
   The eyebrow is uppercase and letter-spaced, which leaves a trailing gap on
   the right and makes it sit a hair left of centre; the padding pays it back. */
header.mast.donor{text-align:center}
header.mast.donor .eyebrow{padding-left:.16em}
header.mast.donor h1,
header.mast.donor .donorlede{margin-left:auto;margin-right:auto}

/* Custom-amount CTA under Need some help? on donors.html — same spacing
   the old finder button used. .findernote kept for any leftover markup. */
.findercta{margin:20px 0 0}
.findernote{margin:12px 0 0;font-size:var(--t-small);color:var(--ink-faint);line-height:1.5;max-width:44ch}

/* ==========================================================================
   GIVE.HTML — the choice block above Stripe's embedded form. Radios and a
   stepper sized for a thumb (44px minimum targets), in the finder's control
   vocabulary so the two pages read as one site. Stripe styles what is inside
   #checkout; nothing here reaches into it.
   ========================================================================== */
.choice{display:flex;flex-direction:column;gap:22px;align-items:flex-start;padding-top:44px}
.choice-school{
  margin:0;font-size:var(--t-lead);line-height:1.3;color:var(--ink);font-weight:var(--w-med);max-width:34ch;
}
.choice-pick{margin:-10px 0 0;font-family:"Courier Prime","Courier New",monospace;font-size:var(--t-mono);}
.choice-pick a{color:var(--teal)}
.modes{display:flex;flex-wrap:wrap;gap:12px 14px;margin:0;padding:0;border:0;min-width:0}
.mode{
  display:inline-flex;align-items:center;gap:12px;min-height:48px;padding:0 18px 0 14px;
  border:1.5px solid var(--ink);background:var(--card-alt);cursor:pointer;
  font-family:"Courier Prime","Courier New",monospace;font-size:var(--t-mono);letter-spacing:.03em;color:var(--ink);
}
.mode input{width:20px;height:20px;margin:0;accent-color:var(--teal)}
.mode:has(input:checked){border-color:var(--teal);background:var(--teal-wash)}
.mode:has(input:disabled){opacity:.45;cursor:not-allowed}
.mode:has(input:focus-visible){outline:2px solid var(--ochre);outline-offset:1px}
.qty{display:flex;flex-direction:column;gap:10px}
/* Mirrors .qty/.stepper -- the amount field, added 2026-09-18. */
.amount{display:flex;flex-direction:column;gap:10px}
.amount-field{display:inline-flex;align-items:stretch;border:1.5px solid var(--ink);background:var(--card-alt);width:fit-content}
.amt-prefix{
  display:flex;align-items:center;padding:0 4px 0 14px;color:var(--ink-faint);
  font-family:"Courier Prime","Courier New",monospace;font-size:1.5rem;
}
.amount-field input{
  width:120px;min-height:48px;border:0;background:transparent;color:var(--ink);
  font-family:"Courier Prime","Courier New",monospace;font-size:1.5rem;
  padding:0 14px 0 2px;
}
.amount-field input:focus{outline:2px solid var(--teal);outline-offset:-2px}
.amount-error{color:var(--stamp)}
.qty-label{margin:0}
.stepper{display:inline-flex;align-items:stretch;border:1.5px solid var(--ink);background:var(--card-alt)}
.stepper .step{
  width:52px;min-height:48px;border:0;background:transparent;color:var(--teal);cursor:pointer;
  font-family:"Courier Prime","Courier New",monospace;font-size:1.5rem;font-weight:700;line-height:1;
}
.stepper .step:disabled{color:var(--ink-faint);cursor:not-allowed}
.stepper .step:focus-visible{outline:2px solid var(--ochre);outline-offset:-2px}
.stepper .count{
  min-width:3.5ch;display:inline-flex;align-items:center;justify-content:center;
  border-left:1.5px solid var(--ink);border-right:1.5px solid var(--ink);
  font-family:"Courier Prime","Courier New",monospace;font-size:1.25rem;font-weight:700;color:var(--ink);
}
.qty-total{margin:0;font-family:"Courier Prime","Courier New",monospace;font-size:var(--t-mono);color:var(--ink-soft)}
.pay{padding-top:40px;display:flex;flex-direction:column;gap:14px}
.pay .cardnote{margin:0;font-family:"Courier Prime","Courier New",monospace;font-size:var(--t-mono);color:var(--ink-faint)}
#checkout{width:100%;min-height:120px}
.fallback{display:flex;flex-direction:column;gap:16px;align-items:flex-start}
.fallback .note{margin:0}

/* ==========================================================================
   FOR REVIEWERS — PARKED 2026-09-19, THE PAGE IT STYLES IS NOT ON THE SITE.
   Mark pulled for-reviewers.html the day it shipped: "not approved by team."
   These rules are left in place rather than deleted so restoring the page is
   a revert of one commit and not a re-typesetting job. If you are reading
   this because you found selectors with no markup, that is why — do not
   "clean it up" without checking whether the page is coming back.
   Original note follows.

   FOR REVIEWERS — the text-only reading page. Built 2026-09-18.

   This is the page a school or district reviewer opens to answer a policy
   form: every word of every book, no download, no login, no account, and it
   prints straight into a committee packet.

   TYPE IS SET LARGER AND HEAVIER HERE THAN ANYWHERE ELSE ON THE SITE, AND
   THAT IS DELIBERATE. Every other page is skimmed. This one is read end to
   end by somebody who has to certify what is in it, possibly on a school
   laptop, possibly on paper. Story copy rides --ink, not --ink-soft, for
   the same reason: secondary-prose grey is right for a caption beside a
   photograph and wrong for two thousand words of a book.
   ========================================================================== */
.readintro{max-width:60ch;margin:0 0 10px}

.bookblock{padding:64px 0 0;border-top:1px solid var(--rule);margin:64px 0 0}
.bookblock:first-of-type{border-top:0;margin-top:0;padding-top:34px}
.bookno{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;
  letter-spacing:.16em;text-transform:uppercase;
  color:var(--teal);margin:0 0 12px;
}
.bookttl{
  font-size:var(--t-section);font-weight:var(--w-head);letter-spacing:-.012em;
  margin:0 0 8px;line-height:1.2;
}
.bookline{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono);color:var(--ink-faint);
  margin:0 0 30px;line-height:1.6;letter-spacing:.03em;
}

/* The policy block. A reviewer answers most of the form from this and never
   scrolls into the story — so it comes FIRST, and "contains no" is a row of
   its own rather than a sentence buried in a paragraph. */
.policy{
  display:grid;grid-template-columns:minmax(150px,200px) 1fr;
  gap:0;margin:0 0 40px;
  background:var(--card);border:1px solid var(--rule);border-radius:3px;
  overflow:hidden;
}
.policy dt{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--teal);
  padding:16px 20px;border-top:1px solid var(--rule-soft);
  background:var(--card-alt);
}
.policy dd{
  margin:0;padding:16px 22px;font-size:var(--t-small);
  color:var(--ink);font-weight:var(--w-body);line-height:1.5;
  border-top:1px solid var(--rule-soft);
}
.policy dt:first-of-type,.policy dd:first-of-type{border-top:0}
.policy dd strong{font-weight:var(--w-head)}
.policy dd.flagged{color:var(--ochre);font-weight:var(--w-med)}
@media (max-width:620px){
  .policy{grid-template-columns:1fr}
  .policy dd{padding-top:0;border-top:0}
  .policy dt{border-top:1px solid var(--rule-soft)}
}

.storyhead{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;
  letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink-faint);margin:0 0 20px;
  padding-bottom:10px;border-bottom:1px solid var(--rule-soft);
}
.story p{
  font-size:var(--t-body);color:var(--ink);font-weight:var(--w-body);
  line-height:1.64;max-width:62ch;margin:0 0 24px;
}
.story p:last-child{margin-bottom:0}
.story p em{font-style:italic}
/* The book's own publication details, set smaller than the story so a reader
   can tell at a glance where the story starts. The class goes on the WRAPPER,
   not the paragraph: model.js builds the <p> elements itself from a list in
   the EDIT BLOCK, so nothing can put a class on them from the markup side. */
.story .matterwrap p{
  font-size:var(--t-small);color:var(--ink-soft);max-width:60ch;font-style:italic;
}

@media print{
  .reviewbar,.minihead,.sec.give,.readnav{display:none}
  .bookblock{break-before:page;border-top:0}
  .bookblock:first-of-type{break-before:auto}
  .policy{break-inside:avoid}
  .story p{font-size:11.5pt;line-height:1.5;color:#000;max-width:none}
}

/* The "how a school gets picked" note on the donor page. Added 2026-09-19.
   It sits between the give button and the legal strip, set quieter than a
   section and louder than footer small print, because it answers a question
   a donor is entitled to ask and should not have to hunt for. */
.sec.pickrule{padding:54px 0 0;border-top:1px solid var(--rule-soft);margin:54px 0 0}
.sec.pickrule .sechead{font-size:var(--t-lead);margin-bottom:10px}
.sec.pickrule .body p{font-size:var(--t-small);color:var(--ink-soft);max-width:62ch}
.sec.pickrule .body p strong{color:var(--ink)}

/* ---- donate.html, the 2026-09-20 donate-flow MOCKUP. Delete with the
   page when that proposal is settled either way. Everything else it uses
   (.help-*, .mode, .stepper, .amount, .btn) is the real thing. ---- */
/* --- MOCKUP MASTHEAD, 2026-09-20. Mark, on donate.html: "i'd like a
   image of the bundle (not the loop) to the right of the donate text at top
   just to color things up."

   Two columns above 720px, words left and the photograph right. Below that
   the header stacks, words first: at 375px a side-by-side squeezes "Donate."
   and its standfirst into a four-word measure, which is the same mistake the
   ring made before it was unwound. Nothing else on the site uses .nx-, so
   this block dies with the mockup. --- */
.nx-mast{padding-top:44px}
.nx-mast .masttext > :first-child{margin-top:0}
.nx-masthero{margin:26px auto 0;max-width:420px}
@media (min-width:721px){
  .nx-mast{
    display:grid;grid-template-columns:1fr minmax(250px,350px);
    gap:38px;align-items:center;
  }
  .nx-masthero{margin:0;max-width:none}
}
/* A PHOTOGRAPH AGAIN AS OF 2026-09-22, SO THE FRAME IS BACK ON.
   Until today this carried tote-bundle-cutout.webp, cut out on transparency,
   and the rule here stripped the border, the ground and the shadow, because
   a cutout inside a box is a box. Launch review 4.5 replaced it with
   tote-desk-library.webp -- an opaque photograph of the tote on a wooden
   table -- and an opaque photograph with no frame is just an unfinished
   cutout. So this now inherits .heroimg whole and only sets object-fit.

   ⚠ THE BOX IS THE PHOTOGRAPH'S OWN RATIO, NOT .heroimg's SQUARE, AND THAT
   IS THE WHOLE POINT OF 4.5. Cropped square the file loses about 12% of its
   height, and the two things it loses are the handles off the top and the
   WOODEN TABLE off the bottom -- the hard surface Mark asked for in the
   first place. Rendered and looked at before and after, not assumed. At the
   source ratio nothing is cropped, and the column's 350px cap makes it 395px
   tall, which the masthead grid absorbs because it centres its two columns.

   ⚠ If COPY.heroImg is ever swapped, CHECK THIS NUMBER. It is that file's
   ratio, and a differently shaped photograph will letterbox against it.
   If a transparent cutout goes back in, this whole block reverts to
   border:0/background:none/box-shadow:none/object-fit:contain. */
.nx-masthero .heroimg{
  aspect-ratio:1002/1132;
  object-fit:cover;object-position:50% 50%;
}

/* --- THE INTRO, for a reader who arrived by QR code and has never seen the
   landing page. Set at the standfirst step rather than body: it is the only
   thing between the headline and a form, and at body size it reads as small
   print a stranger skips. --- */
.nx-intro{padding-top:30px}
.nx-intro .body > p{font-size:var(--t-lead);line-height:1.5;max-width:60ch}
.nx-intro .body > p + p{margin-top:16px}

/* --- HOW A SCHOOL IS CHOSEN, and the asterisked line that jumps to it. The
   line is quiet on purpose: it answers a question for the donor who has one
   and stays out of the way of the donor who does not. --- */
/* .fine is scoped to .give in this stylesheet, so on the mockup every line
   wearing it -- the table note, the quantity total, the Stripe placeholder's
   explanation, the source line -- was rendering at full body size. Restated
   for the mockup's own containers rather than unscoped, because unscoping it
   would reach pages that are live and taking money. */
.nx-step .fine,.nx-chosen .fine{
  margin:0;max-width:62ch;
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono);line-height:1.75;color:var(--ink-soft);
}

.nx-chosenlink{margin:16px 0 0}
.nx-chosenlink a{
  font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono);color:var(--ink-soft);
  text-decoration:underline;text-underline-offset:3px;
}
.nx-chosenlink a:hover{color:var(--teal)}
.nx-chosen{
  padding:34px 28px;margin-top:34px;
  background:var(--card);border:1px solid var(--rule-soft);
}
.nx-chosen .sechead{margin-top:0}
.nx-chosen .body > p{max-width:64ch}
.nx-chosentable{margin:22px 0 0}
.nx-chosensource{margin:14px 0 0;max-width:64ch}
/* :target is what the asterisk lands on; say so for a second rather than
   dropping the reader into a wall of grey with no idea what moved. */
.nx-chosen:target{border-color:var(--ochre)}
@media (max-width:600px){
  .nx-chosen{padding:26px 20px;margin-left:-6px;margin-right:-6px}
}

.nx-step{padding-top:44px;border-top:1px solid var(--rule-soft);margin-top:34px}
.nx-step:first-of-type{border-top:0;margin-top:0}
.nx-stepno{
  margin:0 0 6px;font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono-sm);font-weight:700;letter-spacing:.16em;
  text-transform:uppercase;color:var(--teal);
}
.nx-table{margin:18px 0 4px}
.nx-tablenote{margin:0;max-width:52ch}
.nx-going{
  margin:0 0 18px;font-size:var(--t-lead);font-weight:var(--w-head);
  color:var(--ink);line-height:1.3;
}
.nx-amounts{margin-bottom:20px}
.nx-paymock{
  margin:14px 0 18px;padding:30px 22px;text-align:center;
  border:1.5px dashed var(--rule);background:var(--card);
}
.nx-paymock-label{
  margin:0 0 10px;font-family:"Courier Prime","Courier New",monospace;
  font-size:var(--t-mono);font-weight:700;letter-spacing:.1em;color:var(--ink-faint);
}
.nx-paymock-why{margin:0 auto;max-width:46ch}
