
/* ---- tokens --------------------------------------------------------
   Three palettes ship, each light and dark: Evergreen (the default), Slate
   and Taupe, chosen in the Appearance panel (Sept 28, 2026). A palette
   overrides the surface and ink tokens below; the rest (confidence, warn,
   feature) are shared. A new color is checked in all six combinations.

   Every value here was measured against every surface it can land on. The
   two that are allowed under 4.5:1 are --display and --accent, which are
   display type and display italics and never small text. --accent on --tint
   is 3.89:1: do not set a caption in it.
------------------------------------------------------------------- */
:root{
  /* surfaces: Radix sand, steps 1-5 and 7.5 (Oct 23, 2026). They were a
     yellow cream (#faf7f1) with green-grey rules, which read muddy beside
     Slate's clean grey (Carl). */
  --paper:#f9f9f8; --raised:#fdfdfc; --tint:#e1e9e3; --tint-2:#f1f0ef;
  --rule:#e2e1de; --rule-strong:#c6c5c0;
  /* A card's surface: the raised one in light mode; a step off the page in
     dark mode, set per palette below. */
  --card:var(--raised);
  /* ink */
  /* Reading text is neutral: charcoal on cream, off-white on slate. Colour
     is for headings and labels. The prototype set body copy in green and it
     was adopted without the question being asked; Carl asked it. */
  --display:#516c5e; --ink:#1f2224; --ink-2:#3a3e41; --ink-3:#50555a;
  --heading:#3b5246;
  /* A card's hover surface. It used to be --tint, a cool mint that clashed
     with the forest green of the card headings beside it. */
  --lift:#f1f0ef;
  /* Card surfaces for the home mosaic, so the page is not one color. The
     feature card is the forest of the headings turned into a ground; stone
     is the page's own cream a shade deeper. */
  /* The tree card. In light mode a quiet card of the site's kind (Oct 1,
     2026): the raised white the family cards beside it use, a hairline
     edge, the palette's heading, text and accent, a lighter button. A dark
     slab outweighed the page, as the forest card had until Sept 26. Dark
     mode keeps the dark card (below). */
  --feature:var(--raised); --feature-ink:#3b5246; --feature-ink-2:#3a3e41;
  /* Stone: a darker shade of the page itself. Sand read too warm beside
     the forest card. */
  --feature-tag:var(--accent); --stone:#e9e8e6;
  /* the card's little pedigree, drawn in the card's ink: boxes, the first
     box, lines; then the same on hover. Its line markers get a thin edge,
     or the yellow one vanishes on a light card. */
  --tf-b:14%; --tf-b0:30%; --tf-ln:42%; --tf-bh:24%; --tf-b0h:45%; --tf-lnh:65%;
  --tf-go-bg:color-mix(in srgb, var(--feature-ink) 12%, var(--feature)); --tf-go-ink:var(--feature-ink);
  --tf-go-line:transparent; --tf-go-hover:color-mix(in srgb, var(--feature-ink) 20%, var(--feature));
  --tf-edge:var(--rule-strong); --tf-mark-edge:color-mix(in srgb, var(--feature-ink) 45%, transparent);
  /* the "Illustration" label over a photograph: light words, dark halo */
  --chip-ink:#f3efe6; --chip-halo:#2f4a3e; --stone-tag:#8f4f35;
  --deep:#42665b; --accent:#a75f43;
  /* confidence, rendered. These do not shift with the palette: "this is
     unverified" is not a decorative choice. */
  --warn:#85621f; --warn-tint:#fbf3df; --warn-rule:#c4956a;
  /* "You're signed in": green in every palette (Radix Colors green 9). */
  --ok:#30a46c;
  /* "Something new": the bell's dot, red in every palette, as a phone's
     badge is (Radix Colors red 9, the same in dark; Carl, Oct 27, 2026). */
  --new:#e5484d;
  --lost:#8b3a3a; --gone:#6b4a8b;
  /* Family lines on the charts: one colour per grandparent's line, as
     MyHeritage does, so a Norwegian patronymic still shows whose side it's
     on. Radix Colors step 9 (blue, grass, ruby, amber), which Radix keeps
     the same in its dark scales, so these don't change with the theme or
     the palette. Drawn as rims and stripes, never as text. */
  --line-1:#0090ff; --line-2:#46a758; --line-3:#e54666; --line-4:#ffc53d;

  /* ---- type -------------------------------------------------------
     Gelasio for display (since Sept 30, 2026): drawn to Georgia's
     proportions, so it sets the same and shows no jump while it loads,
     but looks alike on every device, where Georgia left Android to its
     own serif. Georgia stays as the fallback. It wants its sidebearings,
     so -0.015em is as far as it closes up. Geist variable
     for reading at 350 — a real point on the axis, not a synthesised
     light. 400 for anyone who has asked their device for more contrast.
     ---------------------------------------------------------------- */
  --serif:Gelasio,Georgia,"Times New Roman",serif;
  --body:Geist,system-ui,-apple-system,sans-serif;
  --track:-0.015em;
  --weight:350;

  /* The reader moves these two and nothing else. Headings are fixed, per
     the rule that big text does not need to grow — which only works
     because the scale below leaves room: at --size:24px the smallest
     heading is still 26px. Small text gains a little on the body text as
     size increases (80% at m, about 82% at l and xl), because somebody
     reaching for this control is telling you the small print is the
     problem. It gained much more until Oct 17, 2026 (86% and 92%), which
     made captions loom in Large (Carl). */
  --size:20px; --size-small:16px; --leading:1.62;

  --h1:52px; --h2:40px; --h3:32px; --h4:26px;

  /* The measure is expressed in the reader's own size, not in rem. In rem
     it tracked the root's 16px and stayed 608px whatever the reader chose,
     so picking XL dropped running prose from 57 characters a line to 48 —
     the size control quietly degrading the thing it exists to improve.
     36 x the body size holds ~66 characters at every step. 45-75 is the
     long-form range; 57 was inside it and still read as a ribbon on a
     27-inch display, which is the screen these pages are read on. */
  --measure:calc(var(--size) * 36);
  /* One gutter, used by the page column AND the masthead. They had
     different numbers — the masthead fell back to 16px while .wrap used
     32px — so the wordmark sat 16px outside the content it sits above. */
  --gutter:20px;
  /* How wide the page is, which is a different question from how wide a
     line of text is. Reading pages are one column and the two are the same.
     Index pages — the home page, the five section pages — are for choosing
     rather than reading, and they get the screen. */
  /* ONE site width. The masthead, every page's container and the lineage
     pages all use it, so the wordmark and the left edge of the content sit
     in the same place on every page. They used to be three numbers — the
     page's own width for the masthead, 74rem for index pages, the measure
     for reading pages, 68rem for the lineage pages — and the header landed
     in three different places depending on which page you were on. Reading
     pages keep a readable line by capping the prose, not the page. */
  --site:74rem;
  --step:1.5rem;
}

/* Four steps, spelled out. No calc() to decode in 2031. */
:root[data-size="s"]{ --size:18px; --size-small:15px }
:root[data-size="m"]{ --size:20px; --size-small:16px }
:root[data-size="l"]{ --size:22px; --size-small:18px }
:root[data-size="xl"]{ --size:24px; --size-small:20px }
:root[data-leading="roomy"]{ --leading:1.85 }

/* A reader who has switched on Increase Contrast gets the heavier weight
   and nobody else reads type they did not choose. */
@media (prefers-contrast:more){ :root{ --weight:400 } }
:root[data-weight="400"]{ --weight:400 }

/* Slate: blue on a faintly cool grey, with a brick-red accent.
   planetposts.me's default palette. The headline blue and the brick went
   one step deeper together on Oct 23, 2026 (from #3d6a80 and Carl's
   #a85852, chosen from a side-by-side): the brick keeps its balance with
   the darker headline and clears 4.5 : 1 on the hover surface. Its light
   page was Evergreen's cream until Oct 1, 2026, then a warm neutral
   (#f8f7f4) until Oct 23, when Carl chose a hair of cool from a
   side-by-side over it and a true grey: hue 220, matching the dark mode,
   and photos keep their warmth.
   Dark mode is a charcoal slate: Tailwind's slate scale blended halfway with
   its neutral zinc, darker and less blue than slate alone, with a clay
   accent. */
:root[data-palette="slate"]{
  --paper:#f7f8fa; --raised:#fefeff; --tint:#e1e9ec; --tint-2:#eef0f3;
  --rule:#dfe2e6; --rule-strong:#c6cad1;
  --display:#3a657f; --ink:#243e4c; --ink-2:#4c6270; --ink-3:#5a6b73;
  --heading:#243e4c; --lift:#eef0f3;
  --deep:#285c75; --accent:#a2544e;
  /* the tree card: raised white, the headings' blue, its brick accent */
  --feature:var(--raised); --feature-ink:#243e4c; --feature-ink-2:#4c6270; --feature-tag:var(--accent);
}
/* Taupe: Tailwind's warm-gray stone scale for surfaces and text, with a
   dusty blue accent, low in color and not teal (it replaced Walnut, whose
   brown and orange didn't work, Sept 28, 2026). */
:root[data-palette="taupe"]{
  --paper:#f5f5f4; --raised:#fafaf9; --tint:#e7e5e4; --tint-2:#f5f5f4;
  --rule:#e7e5e4; --rule-strong:#d6d3d1;
  --display:#57534e; --ink:#1c1917; --ink-2:#44403c; --ink-3:#57534e;
  --heading:#292524; --lift:#e7e5e4;
  --deep:#3d587b; --accent:#4c6b94;
  /* the tree card: raised white, its near-black heading and blue accent
     (in dark mode its dark stone, which Carl chose over a blue card) */
  --feature:var(--raised); --feature-ink:#292524; --feature-ink-2:#44403c; --feature-tag:var(--accent);
}

/* The tree card's green turned 10 degrees bluer in dark mode (156 to 166,
   Evergreen's dark tint) on Oct 1, 2026: the dark page is blue-teal and the
   card read yellow-green against it.
   Evergreen's dark surfaces came down one step on Sept 30, 2026 (paper
   #101d21 to #0c171a, and raised, lift and card with it): at night the old
   paper read grey-green, nearly twice as bright as a #121212 dark ground.
   Slate's paper and raised came down the same step, #141822 to #10141d. */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --paper:#0c171a; --raised:#172529; --tint:#2a403b; --tint-2:#20312c;
    --rule:#35494b; --rule-strong:#4a605d;
    --display:#c4d5c6; --ink:#efefed; --ink-2:#d3d5d3; --ink-3:#b4b8b6;
    --heading:#d2ded2; --lift:#1f3035;
    --feature:#2d4d46; --feature-ink:#f1eee6; --feature-ink-2:#cfd8d0;
    --tf-b:14%; --tf-b0:32%; --tf-ln:38%; --tf-bh:30%; --tf-b0h:55%; --tf-lnh:75%;
    --tf-go-bg:var(--feature-ink); --tf-go-ink:var(--feature); --tf-go-line:transparent;
    --tf-go-hover:color-mix(in srgb, var(--feature-ink) 65%, var(--feature-tag));
    --tf-edge:transparent; --tf-mark-edge:transparent;
    --feature-tag:#f0b99c; --stone:#2a2f2e; --stone-tag:#e8a888;
    --deep:#b3c9b8; --accent:#e39882; --card:#1a2a2f;
    --warn:#dab473; --warn-tint:#2e2a1c; --warn-rule:#7a6038;
    --ok:#33b074; --new:#e5484d;
    --lost:#e2a0a0; --gone:#c3abda;
  }
  :root:not([data-theme="light"])[data-palette="slate"]{
    --paper:#10141d; --raised:#1d222c; --tint:#2e3440; --tint-2:#222832;
    --rule:#39404e; --rule-strong:#4c5462;
    --display:#bcdcec; --ink:#f3f5f7; --ink-2:#d0d4dc; --ink-3:#9aa2b1;
    --heading:#f3f5f7; --lift:#39404e;
    --deep:#bfdbfe; --accent:#e0927b; --card:#2e3440;
    --feature:#2b4558; --feature-ink:#f3f5f7; --feature-ink-2:#d0d9e0; --feature-tag:#f0b0a3;
  }
  :root:not([data-theme="light"])[data-palette="taupe"]{
    --paper:#141210; --raised:#292524; --tint:#292524; --tint-2:#1c1917;
    --rule:#44403c; --rule-strong:#57534e;
    --display:#d6d3d1; --ink:#f5f5f4; --ink-2:#d6d3d1; --ink-3:#a8a29e;
    --heading:#e7e5e4; --lift:#44403c;
    --deep:#cbd5e1; --accent:#97b4d8; --card:#292524;
    --feature:#3f3a36; --feature-ink:#fafaf9; --feature-ink-2:#d6d3d1; --feature-tag:#b8cdea;
  }
}
:root[data-theme="dark"]{
  --paper:#0c171a; --raised:#172529; --tint:#2a403b; --tint-2:#20312c;
  --rule:#35494b; --rule-strong:#4a605d;
  --display:#c4d5c6; --ink:#efefed; --ink-2:#d3d5d3; --ink-3:#b4b8b6;
    --heading:#d2ded2; --lift:#1f3035;
    --feature:#2d4d46; --feature-ink:#f1eee6; --feature-ink-2:#cfd8d0;
    --tf-b:14%; --tf-b0:32%; --tf-ln:38%; --tf-bh:30%; --tf-b0h:55%; --tf-lnh:75%;
    --tf-go-bg:var(--feature-ink); --tf-go-ink:var(--feature); --tf-go-line:transparent;
    --tf-go-hover:color-mix(in srgb, var(--feature-ink) 65%, var(--feature-tag));
    --tf-edge:transparent; --tf-mark-edge:transparent;
    --feature-tag:#f0b99c; --stone:#2a2f2e; --stone-tag:#e8a888;
  --deep:#b3c9b8; --accent:#e39882; --card:#1a2a2f;
  --warn:#dab473; --warn-tint:#2e2a1c; --warn-rule:#7a6038;
  --ok:#33b074; --new:#e5484d;
  --lost:#e2a0a0; --gone:#c3abda;
}
:root[data-theme="dark"][data-palette="slate"]{
  --paper:#10141d; --raised:#1d222c; --tint:#2e3440; --tint-2:#222832;
  --rule:#39404e; --rule-strong:#4c5462;
  --display:#bcdcec; --ink:#f3f5f7; --ink-2:#d0d4dc; --ink-3:#9aa2b1;
  --heading:#f3f5f7; --lift:#39404e;
  --deep:#bfdbfe; --accent:#e0927b; --card:#2e3440;
  --feature:#2b4558; --feature-ink:#f3f5f7; --feature-ink-2:#d0d9e0; --feature-tag:#f0b0a3;
}
:root[data-theme="dark"][data-palette="taupe"]{
  --paper:#141210; --raised:#292524; --tint:#292524; --tint-2:#1c1917;
  --rule:#44403c; --rule-strong:#57534e;
  --display:#d6d3d1; --ink:#f5f5f4; --ink-2:#d6d3d1; --ink-3:#a8a29e;
  --heading:#e7e5e4; --lift:#44403c;
  --deep:#cbd5e1; --accent:#97b4d8; --card:#292524;
  --feature:#3f3a36; --feature-ink:#fafaf9; --feature-ink-2:#d6d3d1; --feature-tag:#b8cdea;
}
/* The Appearance panel's choices: a track, and the chosen one on it. In
   light mode a tint track and a white chip; in dark the page shows through
   as the track and the chip is a step lighter than the panel, as dark
   surfaces show lift. From each palette's own tokens: 1.20-1.22 : 1 in
   light, the chip 1.77-1.91 : 1 against its track in dark (Oct 2, 2026). */
/* On the page itself (Recipes' Courses · Categories · Saved) the dark track
   can't be the page: it is a step between the page and the chip, half of
   each, 1.28-1.33 : 1 against the page and the chip 1.38-1.44 : 1 against it
   (Nov 2, 2026). */
:root{--seg-track:var(--tint); --seg-on:var(--raised); --seg-track-page:var(--tint)}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){--seg-track:var(--paper); --seg-on:var(--rule);
    --seg-track-page:color-mix(in srgb, var(--rule) 50%, var(--paper))}
}
:root[data-theme="dark"]{--seg-track:var(--paper); --seg-on:var(--rule);
  --seg-track-page:color-mix(in srgb, var(--rule) 50%, var(--paper))}
/* The swatch dots in the Appearance panel: each palette's own display
   color, whatever palette is showing. */
:root{--sw-evergreen:#516c5e; --sw-slate:#3a657f; --sw-taupe:#78716c}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0; background:var(--paper); color:var(--ink);
  font:var(--weight) var(--size)/var(--leading) var(--body);
  font-feature-settings:"kern","liga";
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
}
.wrap{max-width:var(--site); margin:0 auto; padding:0 var(--gutter);
      container-type:inline-size}
/* Pictures past the text (DECISIONS, Oct 17, 2026). The text and the
   wordmark keep their shared left edge; pictures may reach right of the
   text into the frame's free band, to one outer edge: the text's right
   edge plus --hang (300px at most, less where the band is narrower, as on
   a page with a contents list, 120px). 100cqw is the frame's own width
   (.wrap is the container), so a scrollbar can't push a picture past it;
   a browser without container units hangs nothing. */
:root{--band:calc(100cqw - var(--measure)); --hang:clamp(0px, var(--band), 300px)}
/* A front door (Recipes, Stories: data-layout index) runs main across the
   whole frame already, so there is no band beside it. (As I Remember It is
   an index page too, but its main sits in the contents-list grid.) */
[data-layout="index"] .wrap > main{--hang:0px}
/* Reading pages: the page is site-wide, the prose is not. */
.wrap > main, .wrap > .foot{max-width:var(--measure)}
[data-layout="index"] .wrap > main{max-width:none}
@media (min-width:48rem){ :root{--gutter:32px} }

/* ---- index pages ----------------------------------------------------
   Set by shell(index=True). The page widens; the prose inside does not,
   which is the whole trick — a 5K display gets structure in the extra
   space rather than a longer line.
------------------------------------------------------------------- */

/* Capping main outright squeezed the home page's three cards into one
   column's worth of space. What needs the measure is the PROSE, not the
   grid — so the cap goes on the text children, at every width. (It used to
   live inside a 62rem media query, which left /teep running 910px lines on
   a laptop.) A railed page is different: there the whole column is prose,
   and .railed caps main itself. */
[data-layout="index"] .lede p,
[data-layout="index"] main > p,
[data-layout="index"] main > ul,
[data-layout="index"] main > ol,
[data-layout="index"] main > blockquote,
[data-layout="index"] main > .note,
[data-layout="index"] main > .readalso{max-width:var(--measure)}
.railed > main{max-width:var(--measure)}
@media (min-width:62rem){
  [data-layout="index"] .title{
    display:grid; grid-template-columns:1.25fr .85fr; gap:0 56px;
    align-items:start;
  }
  [data-layout="index"] .title .kicker,
  [data-layout="index"] .title h1,
  [data-layout="index"] .title .dates,
  [data-layout="index"] .title .standfirst,
  [data-layout="index"] .title .downloads,
  [data-layout="index"] .title .dl-help{grid-column:1}
  /* A banner in a two-column title (As I Remember It's) takes the whole row. */
  [data-layout="index"] .title > .pic.banner{grid-column:1 / -1}
  [data-layout="index"] .title > .origin{
    grid-column:2; grid-row:1 / span 5; margin:6px 0 0; align-self:start;
  }
  [data-layout="index"] .cards{grid-template-columns:repeat(6,1fr)}
  .cards .span2{grid-column:span 2} .cards .span3{grid-column:span 3}
  .cards .span4{grid-column:span 4}

  /* A long reading page in a wide wrap is a column with a desert beside it.
     The rail puts the contents in that space and keeps it in view, so the
     width does something down the whole page rather than only at the top. */
  .railed{display:grid; grid-template-columns:14rem minmax(0,1fr); gap:0 56px;
          --band:calc(100cqw - 14rem - 56px - var(--measure));
          /* restated: a custom property is worked out where it's declared,
             so the page-wide --hang would keep the page-wide --band */
          --hang:clamp(0px, var(--band), 300px)}
  .railed > .rail{grid-column:1; position:sticky; top:76px; align-self:start;
                  max-height:calc(100vh - 100px); overflow:auto}
  .railed > main{grid-column:2}
}
.rail{margin:0 0 calc(var(--step)*1.5)}
.rail-fold > summary{list-style:none; display:flex; align-items:baseline; gap:10px;
  cursor:pointer; margin:0 0 12px}
.rail-fold:not([open]) > summary{margin:0}
.rail-fold > summary::-webkit-details-marker{display:none}
.rail-fold > summary::marker{content:""}
.rail-n{font-size:var(--size-small); color:var(--ink-3)}
.rail-fold .chev{color:var(--ink-3); font-size:1.3rem; line-height:1; margin-left:auto}
.rail-fold[open] .chev{transform:rotate(90deg)}
/* Beside the story it is always open: no count, no arrow, nothing to press. */
@media (min-width:62rem){
  .railed > .rail .rail-n,.railed > .rail .chev{display:none}
  .railed > .rail summary{pointer-events:none; cursor:default}
}
.rail p,.rail-label{
  font:600 calc(var(--size) * .7)/1 var(--body); letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-3); margin:0 0 12px;
}
.rail ol{list-style:none; margin:0; padding:0; counter-reset:rail}
.rail li{counter-increment:rail; margin:0 0 2px}
.rail a{
  display:flex; gap:10px; text-decoration:none; color:var(--ink-2);
  font-size:.92em; line-height:1.35; padding:6px 8px; border-radius:7px;
  border-left:2px solid transparent;
  transition:background-color .18s, color .18s, border-color .18s;
}
.rail a::before{
  content:counter(rail); color:var(--ink-3); font-variant-numeric:tabular-nums;
  font-size:.82em; padding-top:.15em;
}
.rail a:hover{background:var(--tint); color:var(--ink); border-color:var(--accent)}
/* A section's own entries (a story's letters) sit under it, unnumbered. */
.rail ol ol{margin:2px 0 8px 22px; counter-reset:rail}
.rail ol ol a{font-size:.84em; padding:4px 8px}
.rail ol ol a::before{content:none}
/* Above the story on a phone, the letters would be half a screen of list
   before the first line; there it shows the sections only. */
@media (max-width:61.99rem){ .rail ol ol{display:none} }
@media (max-width:61.99rem){
  .rail{border-left:2px solid var(--rule); padding-left:16px}
}
@media (min-width:48rem) and (max-width:61.99rem){
  [data-layout="index"] .cards{grid-template-columns:1fr 1fr}
}
/* The home page's headline is the introduction to the whole site. */
/* Two lines at every width, split where the sentence breathes ("Where family
   stories / meet—and last."): balanced wrapping picks that break itself. */
[data-page="home"] .title h1{font-size:clamp(1.95rem,9.2vw,4.25rem); line-height:1.04;
  max-width:10.5em; text-wrap:balance}
/* From 62rem the headline shares the row with the name box (1.25fr .85fr,
   a 56px gap, inside a 1184px site), so size it to its column instead of
   the screen: "Where family stories" is about 8.9em wide, and must fit. */
@media (min-width:62rem){
  [data-page="home"] .title h1{font-size:min(4.25rem, calc((min(100vw, 1184px) - 140px) * .065))}
}
/* The home headline reads itself in, word by word, on a fresh arrival
   (DECISIONS, "The headline reads itself in", Oct 1, 2026). Each word is
   uncovered left to right by a soft edge, at a reading voice's pace (the
   timings are build-home-page.py's HEADLINE); "meet" closes its letters
   up in the pause, "last." eases its apart.
   Only transform moves, so the browser can play it off the main thread
   while the page is still loading (rebuilt Oct 2, 2026): the soft edge is
   a page-coloured cover (.cv) sliding off each word, and the letters of
   "meet" and "last." are spans moved one by one, ending exactly where the
   line sets them. html[data-hl] means the motion is switched on
   (HOME_HEADLINE_MOTION); .hl-play, set before first paint, holds the
   covers in place; .hl-go, set once Gelasio has loaded, starts them. The
   page script drops both if the font is late or frames run slow. */
[data-page="home"] .title h1 .hw{display:inline-block}
/* The em-dash drawn lighter than Gelasio draws it at display size (3.4 px of
   3.75 beside 2.75 px crossbars), thinned on its own stroke's centre. */
[data-page="home"] .title h1 .hw.dash{transform:scaleY(.91); transform-origin:50% .531em}
html[data-hl] .title h1 em{letter-spacing:.04em}
html[data-hl] .title h1 .hl{display:inline-block}
.title h1 .cv{display:none}
/* Each cover is clipped to its word's box (all the ink is inside it, the
   "y" of "family" too), plus .12em on the right for the overhang of "y"
   and the italic. "meet"'s reaches .58em: its letters start .46em wider.
   The cover inside is 140% of that, its first .384 of the box a ramp from
   clear to the page's colour: the softness of the mask it replaces (a
   240% gradient, opaque 0-42%, clear 58-100%), travelling as far. */
html.hl-play .title h1{isolation:isolate}
/* Safari does not clip a cover that is waiting to start, and at the start
   a cover's soft edge reaches left of its word, by .76em for "last.": it
   faded the end of "and" until "last." began (Oct 2). So nothing relies on
   the clip: each word paints above every later word and its cover (--z
   counts down the sentence), and a cover is gone (opacity 0) the moment
   its sweep ends, rather than parked to the right of its word. */
html.hl-play .title h1 .hw{position:relative; z-index:var(--z)}
html.hl-play .title h1 .cv{display:block; position:absolute; top:0; bottom:0;
  left:0; right:-.12em; overflow:hidden; z-index:1; pointer-events:none}
html.hl-play .title h1 .cv span{position:absolute; top:0; bottom:0;
  left:-39.2%; width:140%;
  background:linear-gradient(90deg, transparent, var(--paper) 27.43%);
  /* both: a cover rests where it covers, so it must stay gone once off */
  animation:hw-read calc(var(--t) * 1ms) var(--e) calc(var(--d) * 1ms) both,
            hw-gone 1ms step-end calc((var(--d) + var(--t)) * 1ms) both}
/* "meet"'s spread letters reach over the dash, still covered; "meet" is
   the earlier word, so they paint above the dash's cover. */
html.hl-play .title h1 .meet .cv{right:-.58em}
html.hl-play .title h1 .meet .hl{
  animation:hw-meet 1500ms cubic-bezier(.45,0,.3,1) calc((var(--d) + 300) * 1ms) backwards}
html.hl-play .title h1 .last .hl{
  animation:hw-last 1900ms cubic-bezier(.3,.55,.2,1) calc((var(--d) + 150) * 1ms) backwards}
html.hl-play:not(.hl-go) .title h1 :is(.cv span,.hl){animation-play-state:paused}
@keyframes hw-read{from{transform:none} to{transform:translateX(100%)}}
@keyframes hw-gone{to{opacity:0}}
/* Letter i of "meet" starts i x (.10em - the line's tracking) to the right,
   as letter-spacing .10em set it, and closes up; "last." from -.07em to
   its resting +.04em. Anchored at the first letter, as letter-spacing is. */
@keyframes hw-meet{from{transform:translateX(calc(var(--i) * (.10em - var(--track))))} to{transform:none}}
@keyframes hw-last{from{transform:translateX(calc(var(--i) * -.11em))} to{transform:none}}

/* ---- masthead ------------------------------------------------------ */
.masthead{
  border-bottom:1px solid var(--rule); background:var(--raised);
  position:sticky; top:0; z-index:20;
  display:flex; align-items:center; gap:16px;
  /* Same gutter as .wrap, and the centred case adds it too, so the brand
     lines up with the page's left edge at every width. */
  padding:10px max(var(--gutter),
                   calc(50% - var(--site)/2 + var(--gutter)));
}
.masthead .home{
  font:600 .9rem/1 var(--body); color:var(--ink);
  text-decoration:none; letter-spacing:.02em;
}
.masthead .home span{color:var(--ink-3); font-weight:400}
.masthead .spacer{flex:1}
.masthead button{
  font:500 .78rem/1 var(--body); color:var(--ink-2);
  background:none; border:1px solid var(--rule); border-radius:999px;
  padding:6px 12px; cursor:pointer;
}
.masthead button:hover{color:var(--ink); border-color:var(--ink-3)}
.masthead a.mbtn{
  font:500 .78rem/1 var(--body); color:var(--ink-2); text-decoration:none;
  border:1px solid var(--rule); border-radius:999px; padding:6px 12px;
}
.masthead a.mbtn:hover{color:var(--ink); border-color:var(--ink-3)}
/* The chrome follows the reader's text size at half the body's rate
   (Carl, Oct 23, 2026): fixed, it read small beside 20px text, and at the
   full rate XL's header outgrew the page. The menu is 17px at M, these
   words 14px, a step under it; at XL 18.7 and 15.4. */
.masthead :is(#find-open,#appearance,#tier-chip),.masthead a.mbtn{
  font-size:calc(14px + (var(--size) - 20px) * .35); white-space:nowrap}

/* ---- home: the name, and the cards --------------------------------- */
.origin{
  border-left:2px solid var(--rule); padding:2px 0 2px 22px;
  /* Room above it when it stacks under the intro on a phone; beside the
     headline on a wide screen the grid rule resets the top margin. */
  margin:calc(var(--step)*1.6) 0 calc(var(--step)*2);
}
.origin-label{
  font:600 calc(var(--size) * .7)/1.2 var(--body); letter-spacing:.14em;
  text-transform:uppercase; color:var(--accent); margin:0 0 12px;
}
/* The four forms of the name, drawn as a fork rather than a chain: the
   Norwegian and American spellings are siblings, not steps. */
.forms{list-style:none; margin:0 0 16px; padding:0}
/* Each form on its own line with its gloss beneath: side by side, the
   glosses wrapped awkwardly in a column this narrow. */
.forms li{margin:0 0 12px}
.forms b{
  display:block; font:400 clamp(calc(var(--size) * 1.16),3vw,1.9rem)/1.1 var(--serif);
  color:var(--heading); letter-spacing:var(--track);
}
.forms span{display:block; font-size:calc(var(--size) * .78); color:var(--ink-3);
            margin-top:2px}
/* The two branches: indented, each hung off a copper elbow. */
.forms .fork{position:relative; padding-left:30px}
.forms .fork::before{
  content:""; position:absolute; left:8px; top:-6px; width:14px; height:1.05em;
  border-left:1.5px solid var(--accent); border-bottom:1.5px solid var(--accent);
  border-bottom-left-radius:5px;
}
.origin p{font-size:var(--size-small); color:var(--ink-2); margin:0 0 .7em}
.origin .src{font-size:calc(var(--size) * .76); color:var(--ink-3); margin:0}


.cards{
  display:grid; gap:16px; margin:calc(var(--step)*1.6) 0 calc(var(--step)*2.6);
}
@media (min-width:44rem){ .cards{grid-template-columns:1fr 1fr} }
/* The home page's groups: a small label, like the name's, then a row. The
   label sits close to its row and well clear of the row above. */
.cards-label{
  font:600 calc(var(--size) * .7)/1.2 var(--body); letter-spacing:.14em;
  text-transform:uppercase; color:var(--accent); margin:0;
}
.cards-label + .cards{margin-top:14px}
.cards:has(+ .cards-more){margin-bottom:0}
.cards-more{margin:14px 0 calc(var(--step)*2.6); font-size:var(--size-small)}
/* Two columns, an odd number of cards: the last one takes the row rather
   than leaving a hole beside it. Any labelled group (home, Stories,
   Recipes); the Journal's grids handle their own odd counts. */
@media (min-width:44rem) and (max-width:61.99rem){
  .cards-label + .cards > .card:last-child:nth-child(odd){grid-column:1 / -1}
}
.cards-more a{color:var(--ink-2)}
.cards-more a:hover{color:var(--ink)}
/* Where the grid has two columns, the first card only immediate family see
   leads across the row, so their three cards and the six public ones leave
   no gap. Hidden from everyone else, it takes no room at all. */
@media (min-width:44rem) and (max-width:61.99rem){
  .cards > .card[data-need]:first-child{grid-column:1 / -1}
}
/* A full-row card, at every width the grid has more than one column. */
.cards .span6{grid-column:1 / -1}
.card{
  display:flex; flex-direction:column; text-decoration:none; color:inherit;
  background:var(--raised); border:1px solid var(--rule); border-radius:16px;
  overflow:hidden; position:relative; min-height:15rem;
  transition:border-color .25s cubic-bezier(.2,.7,.2,1),
             transform .25s cubic-bezier(.2,.7,.2,1),
             box-shadow .25s cubic-bezier(.2,.7,.2,1),
             background-color .25s cubic-bezier(.2,.7,.2,1);
}
.card-body{display:flex; flex-direction:column; flex:1; padding:24px 26px 20px;
           position:relative}
/* A card stands off the page (Sept 28, 2026). Card and page were nearly the
   same color in every palette (1.03 to 1.19 : 1) and the hairline border
   barely darker, so in light mode a white card melted into the cream. Now
   the second border color, and in light mode a soft resting shadow, like
   paper on a table; in dark mode, where a shadow doesn't show, the card's
   surface (--card) sits a step off the page instead, and its words take the
   brightest ink. */
.card{border-color:var(--rule-strong);
  box-shadow:0 1px 2px color-mix(in srgb, var(--ink) 7%, transparent),
             0 6px 18px color-mix(in srgb, var(--ink) 6%, transparent)}
.card{background:var(--card)}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .card:not(:hover,:focus-visible){box-shadow:none}
  :root:not([data-theme="light"]) .card p{color:var(--ink)}
}
:root[data-theme="dark"] .card:not(:hover,:focus-visible){box-shadow:none}
:root[data-theme="dark"] .card p{color:var(--ink)}
/* Hover lifts the card on a shadow built from the ink (Oct 8, 2026): near
   black in light mode, so a soft shadow as before; near white in dark mode,
   so a faint glow, as the family tree's person card has. 12% for a card.
   Every card grows by about 9px, whatever its width: a third of the row by
   2.5%, half by 1.6%, two thirds by 1.2%, the whole row by 0.8%, as the
   family tree's card already did. One percentage for all made the wide
   cards on planetposts.me's Home and Trips grow 28px (Carl, Oct 19: amoth.us's
   is the look). The photo inside zooms the same way, 18px across. */
.card{--grow:1.025; --zoom:1.05}
.card.span3{--grow:1.016; --zoom:1.033}
.card.span4{--grow:1.012; --zoom:1.025}
.card.span6{--grow:1.008; --zoom:1.016}
.card:is(:hover,:focus-visible){
  transform:scale(var(--grow)); box-shadow:0 14px 34px color-mix(in srgb, var(--ink) 12%, transparent);
  border-color:var(--deep); z-index:1;
}
.card--plain:is(:hover,:focus-visible){background:var(--lift)}
/* A card that is not a link does not act like one. */
div.card:hover{transform:none; box-shadow:none; border-color:var(--rule);
               background:none}
/* ---- the Family page's lines ({lines}; family_lines()) --------------------
   A card per line, grouped by whose lines they are, every card the same
   fields; a line not yet researched is drawn dashed (Carl, Oct 8, 2026). */
.line-group{margin:1.8rem 0 2.2rem}
.line-group h3{margin:0}
.line-who{margin:.15rem 0 .9rem; color:var(--ink-3); font-size:var(--size-small)}
.line-grid{display:grid; grid-template-columns:repeat(auto-fill,minmax(270px,1fr)); gap:14px}
.line-card{display:flex; flex-direction:column; gap:.4rem; min-width:0;
  padding:14px 16px; border:1px solid var(--rule); border-radius:10px; background:var(--raised)}
.line-card header{display:flex; align-items:baseline; gap:.55rem; flex-wrap:wrap}
.line-card h4{margin:0; font:400 calc(var(--size) * 1.08)/1.2 var(--serif); color:var(--ink)}
.line-card .pic-tag{margin-left:0}
.line-card p{margin:0; font-size:var(--size-small); line-height:1.5}
.line-also{color:var(--ink-3); font-style:italic}
.line-where{color:var(--ink-2)}
.line-within{margin-top:.3rem; padding:.45rem .75rem; border-left:2px solid var(--rule-strong)}
.line-within h5{margin:0 0 .1rem; font:400 calc(var(--size) * .88)/1.3 var(--serif)}
.line-card footer{margin-top:auto; padding-top:.5rem; display:flex; justify-content:space-between;
  gap:.3rem .8rem; flex-wrap:wrap; font-size:var(--size-small)}
.line-reach{color:var(--ink-3)}
.line-card.soon{background:none; border-style:dashed}
.line-card.soon h4{color:var(--ink-2)}
.line-card .gallery{margin:.4rem 0 0}
.line-card .gallery .leaf img{height:112px}
.line-card .gallery-step{top:calc(112px / 2 - 16px)}
.line-card .gallery-open{display:none}

/* ---- the family tree, featured ({tree} in a page; tree_feature()) ------- */
.tree-feature{
  display:grid; grid-template-columns:minmax(0,1.15fr) minmax(0,1fr); align-items:center;
  gap:12px 28px; margin:calc(var(--step)*.4) 0 calc(var(--step)*1.4); padding:28px 30px;
  border-radius:16px; background:var(--feature); color:var(--feature-ink);
  border:1px solid var(--tf-edge); text-decoration:none; overflow:hidden;
  transition:transform .25s cubic-bezier(.2,.7,.2,1), box-shadow .25s cubic-bezier(.2,.7,.2,1),
             border-color .25s cubic-bezier(.2,.7,.2,1);
}
/* At rest in light mode, the family cards' own shadow (paper on a table),
   so the white card reads as white beside them; none in dark mode, as theirs. */
.tree-feature{box-shadow:0 1px 2px color-mix(in srgb, var(--ink) 7%, transparent),
                         0 6px 18px color-mix(in srgb, var(--ink) 6%, transparent)}
/* At rest only: these outrank the hover rule, which once left dark mode no
   hover shadow at all (found Oct 8, 2026). */
@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]) .tree-feature:not(:hover,:focus-visible){box-shadow:none} }
:root[data-theme="dark"] .tree-feature:not(:hover,:focus-visible){box-shadow:none}
/* Hover as the family cards have it, quieter for the panel's size: the
   ink's shadow at 8% (a glow in dark mode; Sept 30 it was a plain dark
   shadow, because at 18% over this much area the glow was a haze; Oct 8,
   Carl, back to the ink at 8%) and the smallest lift. The pedigree's
   ripple is the thing to see. */
.tree-feature:is(:hover,:focus-visible){transform:scale(1.008); box-shadow:0 14px 34px color-mix(in srgb, var(--ink) 8%, transparent);
  border-color:var(--deep)}   /* the edge darkens as the family cards' does */
.tree-feature .tf-tag{display:block; font:600 calc(var(--size) * .7)/1 var(--body);
  letter-spacing:.14em; text-transform:uppercase; color:var(--feature-tag); margin:0 0 12px}
.tree-feature h3{font:400 clamp(1.7rem,2.6vw,2.3rem)/1.1 var(--serif); color:var(--feature-ink);
  letter-spacing:var(--track); margin:0 0 .45em}
.tree-feature p{font-size:var(--size-small); color:var(--feature-ink-2); margin:0 0 20px; max-width:32rem}
.tree-feature .tf-go{display:inline-flex; align-items:center; gap:.5em; padding:.7em 1.2em;
  border-radius:999px; background:var(--tf-go-bg); color:var(--tf-go-ink);
  box-shadow:inset 0 0 0 1px var(--tf-go-line); font:600 calc(var(--size) * .8)/1 var(--body)}
.tree-feature .tf-go{transition:background-color .2s ease}
.tree-feature .tf-go span{transition:transform .2s}
.tree-feature:is(:hover,:focus-visible) .tf-go span{transform:translateX(3px)}
/* Pointed at directly, the button answers on its own (the whole panel is
   the link, but a reader aims for the button): it warms toward the panel's
   accent and the arrow steps further. */
.tree-feature .tf-go:hover{background:var(--tf-go-hover)}
.tree-feature .tf-go:hover span{transform:translateX(6px)}
.tf-ped{display:block; width:100%; height:auto; max-height:230px}
.tf-ped .b{fill:color-mix(in srgb, var(--feature-ink) var(--tf-b), transparent);
  transition:fill .3s ease}
.tf-ped .b.g0{fill:color-mix(in srgb, var(--feature-ink) var(--tf-b0), transparent)}
.tf-ped .ln{fill:none; stroke:color-mix(in srgb, var(--feature-ink) var(--tf-ln), transparent);
  stroke-width:1.4; transition:stroke .3s ease}
.tf-ped .q1{fill:var(--line-1)} .tf-ped .q2{fill:var(--line-2)}
.tf-ped .q3{fill:var(--line-3)} .tf-ped .q4{fill:var(--line-4)}
.tf-ped :is(.q1,.q2,.q3,.q4){stroke:var(--tf-mark-edge); stroke-width:.8}
/* On hover the branches light one generation after another, out from the
   person it starts with: a ripple, once, and still the rest of the time. */
.tree-feature:is(:hover,:focus-visible) .tf-ped .b{fill:color-mix(in srgb, var(--feature-ink) var(--tf-bh), transparent)}
.tree-feature:is(:hover,:focus-visible) .tf-ped .b.g0{fill:color-mix(in srgb, var(--feature-ink) var(--tf-b0h), transparent)}
.tree-feature:is(:hover,:focus-visible) .tf-ped .ln{stroke:color-mix(in srgb, var(--feature-ink) var(--tf-lnh), transparent)}
.tf-ped .g1{transition-delay:.07s} .tf-ped .g2{transition-delay:.14s} .tf-ped .g3{transition-delay:.21s}
@media (max-width:40rem){
  .tree-feature{grid-template-columns:1fr; padding:22px 20px}
  .tf-ped{order:-1; max-height:130px}
}
.card-tag{
  font:600 calc(var(--size) * .7)/1 var(--body); letter-spacing:.14em;
  text-transform:uppercase; color:var(--accent); margin-bottom:12px;
}
.card h3{
  font:400 clamp(calc(var(--size) * 1.28),2.4vw,2.1rem)/1.12 var(--serif); color:var(--heading);
  letter-spacing:var(--track); margin:0 0 .4em;
}
.card p{font-size:var(--size-small); color:var(--ink-2); margin:0 0 18px; flex:1}
.card-go{
  display:flex; align-items:center; gap:8px; margin-top:auto;
  font:500 calc(var(--size) * .72)/1 var(--body); color:var(--ink-3);
}
/* The arrow steps out and pivots to the north-east: "go there". */
.card-arrow{
  margin-left:auto; font-size:1.35rem; line-height:1; color:var(--accent);
  display:inline-block; transition:transform .25s cubic-bezier(.2,.7,.2,1);
}
.card:is(:hover,:focus-visible) .card-arrow{transform:translate(3px,-3px) rotate(-45deg)}
/* Once cards share a row: the arrow sits level with the tag, top right,
   rather than on a line of its own under the words (that line cost about
   40px on every card), and titles are smaller so fewer wrap. A phone, where
   one card has the width to itself, keeps the original layout. A "Coming
   soon" card keeps its note below. */
@media (min-width:44rem){
  .card:not(.card--later) .card-go{position:absolute; top:20px; right:22px; margin:0}
  .card:not(.card--later) .card-tag{padding-right:2rem}
  .card:not(.card--later) p{margin-bottom:2px}
  .card h3{font-size:calc(var(--size) * 1.2)}
}

/* The forest "feature" card retired Sept 26, 2026: one solid green slab
   outranked everything beside it, and in dark mode its green sat 40 degrees
   from the page's. Cards are stone, plain or photographs. */
/* Stone card: the page's own ground, a shade deeper. */
.card--stone{background:var(--stone); border-color:var(--stone)}
.card--stone p{color:var(--ink)}
.card--stone .card-tag,.card--stone .card-arrow{color:var(--stone-tag)}

/* Photograph cards: the picture on top, whole and uncovered, and the words
   below it on the card's own ground. (Until Sept 27, 2026 the words sat on a
   dark wash over the picture, which hid most of it.) On hover the picture
   moves slightly closer inside its frame. */
/* The frame is 4:3 (3:2 until Nov 6, 2026: upright portraits lost their
   necks; DECISIONS, "Taller card frames").
   width:100% is for Safari: given only a shape and a height cap, it
   narrows the frame to keep the shape (352 x 1.5 = 528px at 3:2) and leaves the
   rest of a wide card blank (Carl's screenshot, Oct 19, 2026). With the
   width stated it keeps the card's width and the cap wins, as Chromium did
   all along; the photo inside is cropped to fit (object-fit:cover). */
.card-pic{display:block; position:relative; overflow:hidden; width:100%;
  aspect-ratio:4 / 3; max-height:22rem; background:var(--tint)}
.card--photo .card-pic img{
  display:block; width:100%; height:100%; object-fit:cover;
  transition:transform .6s cubic-bezier(.2,.7,.2,1);
}
.card--photo:is(:hover,:focus-visible) .card-pic img{transform:scale(var(--zoom))}
/* The label a generated picture wears on a card, when it could pass for a
   record: a plain word in the picture's lower corner, like a photo credit.
   It was a filled pill at the top, which drew the eye (Carl, Sept 28). */
.card-chip{
  position:absolute; right:10px; bottom:7px;
  font:500 calc(var(--size) * .58)/1 var(--body); letter-spacing:.04em;
  color:var(--chip-ink); opacity:.9;
  text-shadow:0 1px 3px color-mix(in srgb, var(--chip-halo) 90%, transparent),
              0 0 1px color-mix(in srgb, var(--chip-halo) 90%, transparent);
}

/* Not yet here. Visibly unfinished, and not dressed up. */
.card--later{background:none; border-style:dashed; min-height:12rem}
.card--later h3{color:var(--ink-2)}
.card-note{
  font:600 calc(var(--size) * .62)/1 var(--body); letter-spacing:.12em;
  text-transform:uppercase; color:var(--ink-3); border:1px solid var(--rule);
  border-radius:999px; padding:5px 9px;
}
}

.closing{
  border-top:1px solid var(--rule); padding-top:calc(var(--step)*1.2);
  color:var(--ink-2); max-width:var(--measure);
}

/* The same rule for an email address on its own line. "On its own line"
   is decided by the renderer (p.solo), not by :only-child, which ignores
   text and so also caught an address in the middle of a sentence. */
main p.solo > a[href^="mailto:"]{
  font:400 clamp(1.5rem,3.2vw,2rem)/1.2 var(--serif); letter-spacing:var(--track);
  color:var(--deep); text-decoration:none;
  border-bottom:2px solid var(--accent); padding-bottom:2px;
}
main p.solo > a[href^="mailto:"]:hover{color:var(--ink)}

/* A link to a PDF is content; that it looks like a button is presentation.
   Selecting on the extension means the markdown stays a plain link and an
   authoring tool never has to know this rule exists. */
main p.solo > a[href$=".pdf"]{
  display:inline-flex; align-items:center; gap:10px; text-decoration:none;
  background:var(--deep); color:var(--paper); border-radius:999px;
  padding:14px 24px; font:600 var(--size-small)/1 var(--body);
  margin:calc(var(--step)*.4) 0;
  transition:transform .2s cubic-bezier(.2,.7,.2,1), opacity .2s;
}
main p.solo > a[href$=".pdf"]::after{content:"↓"; font-size:1.1em}
main p.solo > a[href$=".pdf"]:hover{transform:scale(1.02); opacity:.93}

/* ---- appearance panel ---------------------------------------------- */
.masthead #appearance{display:inline-flex; align-items:center}
.masthead #appearance svg{display:block}
.masthead #appearance[aria-expanded="true"]{
  color:var(--ink); border-color:var(--ink-3); background:var(--tint);
}

.appearance{
  /* Inside .masthead, which is position:sticky and therefore the containing
     block. As a sibling of the header it resolved top:100% against the page
     and opened a screen and a half down. */
  position:absolute;
  right:max(var(--gutter),
            calc(50% - var(--site)/2 + var(--gutter)));
  top:calc(100% + 8px); z-index:30; width:min(24rem,calc(100vw - 32px));
  background:var(--raised); border:1px solid var(--rule); border-radius:14px;
  padding:18px 20px 16px; box-shadow:0 14px 40px rgba(0,0,0,.14);
  font:400 var(--size-small)/1.5 var(--body); color:var(--ink);
  /* Never taller than the screen below the masthead (79px on a phone):
     at XL on a phone it ran 834px down an 812px screen, Reset out of
     reach. Then it scrolls inside, and the page behind it stays put. */
  max-height:calc(100vh - 104px); max-height:calc(100dvh - 104px);
  overflow-y:auto; overscroll-behavior:contain;
}
.appearance[hidden]{display:none}
.ap-row{margin:0 0 16px}
.ap-label{
  font:600 calc(5.76px + var(--size) * 0.288)/1 var(--body); letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-3); margin:0 0 8px;
}
/* A way out on the panel itself, as Contents & search has: on a phone the
   only other one was tapping Appearance again, which nobody would guess. */
.ap-head{display:flex; align-items:center; justify-content:space-between; gap:12px; margin:0 0 8px}
.ap-head .ap-label{margin:0}

.ap-choices{display:flex; padding:3px; background:var(--seg-track); border-radius:999px}
.ap-choices button{
  flex:1 1 0; min-width:0; font:500 .86em/1 var(--body); color:var(--ink-2);
  background:none; border:0; border-radius:999px;
  padding:10px 6px; cursor:pointer; white-space:nowrap;
}
.ap-choices button:hover{color:var(--ink)}
.ap-choices .sw{display:inline-block; width:.72em; height:.72em; border-radius:50%;
  margin-right:.4em; vertical-align:-.04em; box-shadow:0 0 0 1px var(--rule-strong)}
.sw-evergreen{background:var(--sw-evergreen)} .sw-slate{background:var(--sw-slate)}
.sw-taupe{background:var(--sw-taupe)}
/* Each row one segmented control (Oct 2, 2026). Equal segments, except
   where the words differ in length ("Match device", the palette names):
   there each is as wide as its words, which fit at XL on a 375px phone. */
.ap-choices:is([aria-labelledby="ap-palette"],[aria-labelledby="ap-theme"]) button{flex:1 1 auto}
.ap-choices button[aria-checked="true"]{
  background:var(--seg-on); color:var(--heading); font-weight:600;
  box-shadow:0 1px 2px rgba(0,0,0,.12);
}
.ap-hint{color:var(--ink-3); font-size:.86em; margin:8px 0 0}
.appearance .ap-reset{
  width:100%; font:500 .92em/1 var(--body); color:var(--ink-2);
  background:none; border:1px solid var(--rule); border-radius:999px;
  padding:9px 12px; cursor:pointer; margin-top:2px;
}
.ap-reset:hover{border-color:var(--ink-3); color:var(--ink)}
.ap-foot{text-align:center; margin-top:10px}
.appearance{animation:apin .16s cubic-bezier(.2,.7,.2,1) both}
@keyframes apin{from{opacity:0; transform:translateY(-6px)} to{opacity:1; transform:none}}

/* Wordmark: Amot settles into Amoth. The ring is a positioned element, not a
   combining character, because transforms do not apply to inline boxes. It
   exists only during the animation, so a visitor never sees a misspelling.
   Plays once per session, and never with Motion off. */
.brand{
  font:400 1.7rem/1 var(--serif); color:var(--heading);
  text-decoration:none; letter-spacing:var(--track); white-space:nowrap;
}
.brand .dot{color:var(--accent); font-style:italic}
.brand .am{position:relative; display:inline-block}
.brand .ring{
  position:absolute; left:50%; top:-.13em; width:.30em; height:.30em;
  border:.072em solid currentColor; border-radius:50%;
  transform:translateX(-50%); opacity:0; pointer-events:none;
}
.brand{display:inline-block}
.brand .th{display:inline-block; overflow:hidden; vertical-align:bottom; max-width:2em}
body.logo-anim .brand .ring{animation:ringlift 1s cubic-bezier(.2,.7,.2,1) both}
body.logo-anim .brand .th{animation:thgrow .4s cubic-bezier(.2,.7,.2,1) .62s both}
/* The h grows in and pushes ".us" along, which is the effect. Growing it
   used to shrink the LINK too: for 1.6 seconds the wordmark was 98px wide,
   so a click aimed at ".us" landed on the masthead and did nothing — Carl
   had to click twice. Scaling the h instead kept the box but left a visible
   hole ("Åmot  .us") for a second on every page. So the script pins the
   link's finished width before the animation starts: the letters move, the
   hit target does not. */
@keyframes ringlift{
  0%{opacity:0; transform:translateX(-50%) translateY(-7px) scale(.6)}
  18%{opacity:1; transform:translateX(-50%) translateY(0) scale(1)}
  55%{opacity:1; transform:translateX(-50%) translateY(0) scale(1)}
  100%{opacity:0; transform:translateX(-50%) translateY(-13px) scale(.5)}}
@keyframes thgrow{from{max-width:0; opacity:0} to{max-width:2em; opacity:1}}
.masthead nav{display:flex; gap:18px; align-items:center}
.masthead nav a{
  font:500 calc(17px + (var(--size) - 20px) * .425)/1 var(--body); color:var(--heading);
  text-decoration:none; position:relative; padding-bottom:3px;
  white-space:nowrap;   /* "The family" was breaking across two lines */
}
.masthead nav a::after{
  content:""; position:absolute; left:0; bottom:0; height:1px; width:100%;
  background:var(--accent); transform:scaleX(0); transform-origin:left;
  transition:transform .2s cubic-bezier(.2,.7,.2,1);
}
.masthead nav a:hover{color:var(--ink)}
.masthead nav a:hover::after,.masthead nav a[aria-current]::after{transform:scaleX(1)}
.masthead nav a[aria-current]{color:var(--heading)}
/* A family sign-in that ran out (the page script adds it): one quiet line
   under the masthead, aligned with it, closed with the site's ×. */
.signin-lapsed{
  display:flex; align-items:center; gap:12px;
  border-bottom:1px solid var(--rule); background:var(--lift);
  padding:8px max(var(--gutter), calc(50% - var(--site)/2 + var(--gutter)));
  font-size:var(--size-small); color:var(--ink-2);
}
.signin-lapsed p{margin:0; flex:1}
.signin-lapsed a{color:var(--deep)}
.signin-lapsed button.cx{margin:-6px 0}   /* the site's close button, without making the line taller */
/* Below 54rem amoth.us's links take their own row. Wordmark, five links
   and the five tools as a group of circles need up to 856px, at XL
   (measured Oct 28, 2026, with nothing wrapping). This was 44rem, and from
   705px up the bar ran off the right edge; then 52rem, 54rem, and 57.5rem
   for a day, while the tools were wider pills. */
@media (max-width:54rem){
  .masthead:not(.pp){flex-wrap:wrap; row-gap:8px}
  .masthead:not(.pp) .spacer{display:none}
  .masthead:not(.pp) nav{order:3; width:100%; gap:14px; flex-wrap:wrap}
  /* 16px on phones, iOS's reading size; it was .86rem (13.8px), and Carl
     found the links small to read and to hit (Oct 23, 2026). */
  .masthead:not(.pp) nav a{font-size:1rem}
  .masthead:not(.pp) .brand{flex:1}
}
/* planetposts.me's bar is narrower (four links, two tools), so it keeps
   one row longer: its own width, not amoth.us's (Carl, Oct 28, 2026). It
   needs up to 688px at XL with the full logo, which shows from 44rem up,
   and 600px with the phone's smaller one; so below 38rem. */
@media (max-width:38rem){
  .masthead.pp{flex-wrap:wrap; row-gap:8px}
  .masthead.pp .spacer{display:none}
  .masthead.pp nav{order:3; width:100%; gap:14px; flex-wrap:wrap}
  .masthead.pp nav a{font-size:1rem}
  .masthead.pp .brand{flex:1}
}
/* Five links at 16px need about 365px, so a phone narrower than 408px
   (an iPhone 17 Pro, an SE) would push the last onto a second line; there
   they spread across the row instead. Left-aligned on the larger phones. */
@media (max-width:25.5rem){
  .masthead:not(.pp) nav,.masthead.pp nav{gap:0; justify-content:space-between}
}
/* On a touch screen, phone or tablet in either orientation, each link and
   round button gets a tap area about 44pt tall, Apple's minimum, without
   moving anything: an invisible layer reaching into the space around it,
   halfway to its neighbor. The links were 17pt tall, the buttons 31
   (Carl, Oct 23, 2026). A mouse keeps the visible size. */
@media (pointer:coarse){
  .masthead button,.masthead a.mbtn,.tn a{position:relative}
  .masthead nav a::before,.masthead button::before,
  .masthead a.mbtn::before,.tn a::before{content:""; position:absolute}
  .masthead nav a::before{inset:-12px -7px}
  .masthead button::before,.masthead a.mbtn::before{inset:-7px -5px}
  /* The tools are 6px apart: each reaches halfway, 44pt tall, 40 wide. */
  .masthead .mtools :is(button,a.mbtn)::before{inset:-5px -3px}
  .tn a::before{inset:-12px -8px}
}

/* ---- title page ---------------------------------------------------- */
/* The space around a page's introduction is set by the text, not the screen:
   it was 9vh above and 5vh below plus the rule's 44px, which on a phone left
   about a quarter of the first screen blank and on a tall monitor put 130px
   over the first word. Now 32px (phone) to 56px (desktop) above, and the
   rule after the introduction alone sets the space below it (Sept 28, 2026). */
.title{padding:clamp(2rem,4.4vw,3.5rem) 0 0; text-align:left}
/* The bookmark at the top right of a page's title (Carl, Oct 28, 2026):
   the masthead tools' circle, filling once saved; the script sets its top,
   level with the title's first line, and the line keeps room for it. Its
   name shows under it on hover and keyboard focus, as the tools' do, and a
   save is confirmed for a few seconds with a link to the list. */
.title.saveable{position:relative}
.title.saveable > :first-child{padding-right:48px}
.save-ic{position:absolute; right:0; top:0; width:34px; height:34px; padding:0; border-radius:50%;
  display:inline-flex; align-items:center; justify-content:center; cursor:pointer;
  background:none; color:var(--heading); border:1px solid var(--rule-strong)}
.save-ic[hidden]{display:none}
.save-ic:hover{color:var(--ink); border-color:var(--ink-3)}
.save-ic svg{display:block; fill:none; stroke:currentColor; stroke-width:1.7; stroke-linejoin:round}
.save-ic[aria-pressed="true"] svg{fill:currentColor}
.save-ic::after,.save-note{position:absolute; right:0; z-index:5; white-space:nowrap; padding:4px 8px;
  border-radius:6px; background:var(--raised); border:1px solid var(--rule); color:var(--ink-2);
  font:500 calc(12px + (var(--size) - 20px) * .3)/1.2 var(--body); box-shadow:0 4px 12px rgba(0,0,0,.08)}
.save-ic::after{content:attr(data-tip); top:calc(100% + 6px); opacity:0; transform:translateY(-3px);
  pointer-events:none; transition:opacity .12s ease, transform .12s ease}
@media (any-hover:hover){ .save-ic:hover::after{opacity:1; transform:none; transition-delay:.35s} }
.save-ic:focus-visible::after{opacity:1; transform:none}
.save-note{display:none}
.save-note.on{display:block}
.save-note a{color:var(--deep)}
.save-ic:has(+ .save-note.on)::after{display:none}
@media (pointer:coarse){ .save-ic::before{content:""; position:absolute; inset:-5px} }
/* The Saved page's lists. */
.saved-where{color:var(--ink-2)}
.saved-list{list-style:none; padding:0; margin:0 0 1.4em}
.saved-list li{display:flex; align-items:baseline; gap:12px; padding:10px 0; border-bottom:1px solid var(--rule)}
.saved-list li a{flex:1; min-width:0}
.saved-when{color:var(--ink-3); font-size:var(--size-small); white-space:nowrap}
.saved-x{font:500 var(--size-small)/1 var(--body); color:var(--ink-3); background:none; border:0;
  padding:6px 2px; cursor:pointer; text-decoration:underline; text-underline-offset:3px}
.saved-x:hover{color:var(--ink)}
.saved-photos{list-style:none; padding:0; margin:0 0 1.4em; display:grid; gap:12px;
  grid-template-columns:repeat(auto-fill, minmax(150px, 1fr))}
.saved-photos li{display:flex; flex-direction:column; align-items:flex-start; gap:4px}
.saved-pic{display:block; width:100%; padding:0; border:0; background:var(--lift); border-radius:8px;
  overflow:hidden; cursor:zoom-in; aspect-ratio:1}
.saved-pic img{display:block; width:100%; height:100%; object-fit:cover}
.title .kicker{
  font:600 calc(var(--size) * .78)/1 var(--body); letter-spacing:.16em;
  text-transform:uppercase; color:var(--accent); margin:0 0 24px;
}
/* A journal entry's trip, linked to its page: a faint underline that
   darkens on hover, the words and colour unchanged (Carl, Oct 24; no arrow,
   which would read as Older and Newer). */
.title .kicker a.kicker-trip{color:inherit; text-decoration:underline; text-decoration-thickness:1px;
  text-underline-offset:.5em; text-decoration-color:color-mix(in srgb,currentColor 35%,transparent)}
.title .kicker a.kicker-trip:hover{text-decoration-color:currentColor}
.title h1{
  font:400 clamp(2.4rem,8vw,var(--h1))/1.07 var(--serif);
  margin:0 0 6px; letter-spacing:var(--track); color:var(--display);
}
/* Two ways to lift a word in a headline, and they are not interchangeable.
   <em> is italic AND colored: a reader's inner voice puts stress on it,
   which is right for a word like "meet" and wrong for a pronoun — "all of
   US" reads as an argument with somebody. <b> is color only. It ties the
   word to the wordmark without asking for emphasis it has not earned. */
.title h1 em{font-style:italic; color:var(--accent)}
.title h1 b{font-weight:inherit; color:var(--accent)}
.title .dates{
  font:400 var(--size-small)/1.5 var(--body); color:var(--ink-3); margin:0 0 26px;
}
/* A person page's line for the signed-in reader, put there by the chart
   script: "Your great-grandfather" (Carl, Oct 27, 2026). Quiet, under the
   name, above the dates. */
.title .kin-line{
  font:italic 400 calc(var(--size) * .95)/1.4 var(--serif); color:var(--deep); margin:-.2em 0 .5em;
}
/* The byline under a headline: caption size on a phone, a step up from
   tablet width so it isn't caption-small under a large headline, and still
   well below the standfirst (18px against 24px at the default size). */
@media (min-width:48rem){ .title .dates{font-size:calc(var(--size) * .9)} }
/* The standfirst in the display serif, between the headline and the sans
   text, so it reads as the page's introduction and not a large first
   paragraph. Gelasio has no weight under 400; the open line spacing (37px
   at the default 24px) is what keeps it from looking heavy. 37.5rem keeps
   its lines near 60 characters. (Carl chose it on a test page, Sept 30.) */
.title .standfirst{
  font:400 calc(var(--size)*1.2)/1.54 var(--serif); color:var(--ink-2);
  max-width:37.5rem; margin:0;
}
/* The home standfirst's closing "About the site" link: the paragraph's own
   grey, smaller, with a faint underline, so it reads as a footnote to the
   statement and not part of it (Carl, Oct 23, 2026). */
[data-page="home"] .title .standfirst a{
  color:inherit; font-size:.8em; white-space:nowrap;
  text-decoration-color:var(--rule-strong);
}
[data-page="home"] .title .standfirst a:hover{text-decoration-color:currentColor}
/* Straight under the headline, with no byline between, the two serifs ran
   together at 6px; a third of the headline's size between them is the usual
   measure. A byline keeps its close 6px: it belongs to the headline. */
/* (One margin, on the headline: two would merge on an ordinary page and
   add up in an index page's grid.) */
.title h1:has(+ .standfirst){margin-bottom:var(--size)}
/* A banner straight under the headline (planetposts.me's home) sat 6px
   below it and 24px above the standfirst; the headline gets the
   standfirst's measure and the picture a little more room after it. */
.title h1:has(+ .pic.banner){margin-bottom:var(--size)}
.title > .pic.banner:has(+ .standfirst){margin-bottom:2rem}
/* On a phone 24px ran Langdon's to twelve lines before the story began. */
@media (max-width:47.99rem){ .title .standfirst{font-size:calc(var(--size)*1.05)} }
.rule{border:0; border-top:1px solid var(--rule); margin:44px 0}
/* The rule under the introduction: the same space on both sides, 28px
   (phone) to 40px (desktop), and the page's first element adds none. */
.title + .rule{margin:clamp(1.75rem,3.1vw,2.5rem) 0}
.title > :last-child{margin-bottom:0}
.title + .rule + main > :first-child,
.title + .rule + .railed > main > :first-child{margin-top:0}

/* ---- front matter -------------------------------------------------- */
.frontmatter{color:var(--ink-2); font-size:var(--size-small)}
.frontmatter p{margin:0 0 1.05em}
.frontmatter strong{color:var(--ink); font-weight:600}

/* ---- parts and sections -------------------------------------------- */
.part{margin:calc(var(--step)*3.6) 0 calc(var(--step)*1.6); text-align:center}
.part span{
  display:inline-block; font:600 calc(var(--size) * .7)/1 var(--body);
  letter-spacing:.2em; text-transform:uppercase; color:var(--accent);
  padding:0 14px; background:var(--paper); position:relative; top:.62em;
}
.part hr{border:0; border-top:1px solid var(--rule); margin:0}
.part h2{
  font:400 var(--h2)/1.18 var(--serif); color:var(--heading);
  margin:30px 0 0; letter-spacing:var(--track);
}
h3{
  font:400 var(--h3)/1.22 var(--serif); color:var(--deep);
  margin:calc(var(--step)*2.2) 0 calc(var(--step)*.55); letter-spacing:var(--track);
}
h4{
  font:400 var(--h4)/1.3 var(--serif);
  margin:calc(var(--step)*1.6) 0 calc(var(--step)*.35); color:var(--heading);
  letter-spacing:var(--track);
}
p{margin:0 0 var(--step)}
h3 + p, h4 + p, .part + h3{margin-top:0}
em{font-style:italic}
strong{font-weight:600}
blockquote{
  margin:1.6em 0; padding:0 0 0 1.15em; border-left:2px solid var(--accent);
  color:var(--ink-2); font-style:italic;
}
ul{margin:0 0 1.15em; padding-left:1.15em}
ol{margin:0 0 1.15em; padding-left:1.5em}
/* The small label over a list: Ingredients, Directions. */
h5{
  font:600 calc(var(--size) * .7)/1.2 var(--body); letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-3);
  margin:calc(var(--step)*1.1) 0 calc(var(--step)*.5);
}
.pic{margin:calc(var(--step)*.4) 0 var(--step)}
.pic img{display:block; max-width:100%; max-height:var(--pic-h); width:auto;
         height:auto; border-radius:4px}
/* A picture whose shape the build knew takes its space before it loads:
   as wide as fits the column, its own width, or the height limit, and the
   height follows from the shape. See IMAGE_DIRS in amoth_page.py. */
.pic img[style]{
  width:min(100%, var(--w), calc(var(--pic-h) * var(--r)));
  aspect-ratio:var(--r); height:auto; max-height:none;
}
:root{--pic-h:26rem}
/* Upright, not italic (Oct 17, 2026): small, grey and italic together read
   poorly, and an upright caption can italicize a newspaper's title. */
.pic figcaption{font-size:var(--size-small); color:var(--ink-3);
                margin-top:.5em}
/* A stereograph's pair stays about 24rem wide, where the halves fuse when
   the eyes relax (place_photos, "stereo"). */
.pic.stereo img[style]{width:min(100%, 24rem)}
.pic.stereo figcaption{max-width:24rem}
/* Text flows around a floated portrait on screens wide enough; on a phone
   every photo takes the full width. Headings and full-width photos start
   below a float, never beside it. */
@media (min-width:44rem){
  /* clear: two floats on one side stack, never side by side, which left
     the text between them a word wide (As I Remember It, Oct 17, 2026) */
  .pic.wrap-right{float:right; clear:right; width:min(42%, 17rem);
                  margin:.3em 0 1em 1.6em}
  .pic.wrap-left{float:left; clear:left; width:min(42%, 17rem);
                 margin:.3em 1.6em 1em 0}
  .pic.wrap-right img[style],.pic.wrap-left img[style]{width:100%}
}
main h2,main h3,main h4,main hr,main .readalso,
.pic:not(.wrap-right):not(.wrap-left){clear:both}
/* A farm's map is a tall float beside a short opening, and a heading that
   waited for it left a blank strip (Hvammen, Oct 27, 2026). Headings may
   sit beside it; full-width photos and the timeline still start below. */
main .place-map ~ :is(h2,h3,h4){clear:none}
@media (min-width:48rem){
  /* a banner, and a picture across the column, reach the outer edge; a
     wide one grows, never taller than 30rem; its caption keeps the text's width */
  main .pic.banner:not(.pano),
  main .pic:not(.wrap-right):not(.wrap-left):not(.banner):not(.pair):not(.large):not(.jtext):not(.stereo){
    margin-right:calc(-1 * var(--hang))}
  main .pic:not(.wrap-right):not(.wrap-left):not(.banner):not(.pair):not(.large):not(.jtext):not(.stereo) img[style]{
    width:min(100%, var(--w), calc(30rem * var(--r)))}
  main .pic:not(.wrap-right):not(.wrap-left):not(.pair) > figcaption{max-width:var(--measure)}
  /* a tall picture with enough text after it (the build's .hang) hangs
     into the band, larger, the text beside it at about 60 characters */
  main .pic.wrap-right.hang{width:clamp(min(42%, 17rem), var(--hang) + 7rem, 25rem);
    margin-right:calc(-1 * var(--hang))}
  /* the wide route map, to the outer edge too; the tall farms map doesn't */
  main .route:not(.land):not(.wide-map){margin-right:calc(-1 * var(--hang))}
}
/* Any photo in the text opens larger (the lightbox, in the shell script). */
.pic img[data-lb],.fc-portrait img[data-lb]{cursor:zoom-in}
.pic img[data-lb]:focus-visible,.fc-portrait img[data-lb]:focus-visible{outline:2px solid var(--accent); outline-offset:3px}
/* The two small newspaper excerpts keep their original grayscale files.
   Sepia is a display tone, not a claim about the color of the source. */
:root{--clip-tone:brightness(.84) sepia(1) saturate(.3) hue-rotate(-6deg)}
/* Darkened before the sepia so the paper doesn't clip to yellow: it comes
   out a faint brown, #f1e8da, the ink still black (Carl's pick, Oct 17).
   The photo viewer wears the same tone (.lb img.newspaper). */
.pic.newspaper img,.lb img.newspaper{filter:var(--clip-tone)}
/* They show at their own width (about 385px), never shrunk to the usual
   height limit: they're tall, and a smaller scan is smaller type. */
.pic.newspaper img[style]{width:min(100%, var(--w))}
/* Focus handed back after a click or tap: no keyboard ring (amothReturnFocus). */
.no-ring:focus-visible{outline:none !important}
/* A pair: two portraits side by side at the same height, one caption. */
/* A full-width picture marked "large" in photos.json (a group portrait
   whose faces matter) grows past the height limit, up to the screen's. */
.pic.large img[style]{width:min(100%, var(--w), calc(85vh * var(--r)))}
.pic.pair{display:grid; grid-template-columns:1fr 1fr; gap:12px; align-items:end}
.pic.pair img[style]{width:100%; max-height:none}
.pic.pair figcaption{grid-column:1 / -1}

/* A word longer than the line (a web address written out, as in La
   Leona's www.hoteldecampolaleona.com.ar/home.html) breaks rather than
   push the page sideways on a phone. Ordinary words are untouched. */
main{overflow-wrap:break-word}

/* ---- a journal entry's pictures (DECISIONS, "A journal entry's pictures,
   callouts and corners", Oct 18, 2026; build-journal.py places them) ----
   A float is half the text width plus 30% of the band beside the text:
   450px at 1280, planetposts.me's size. A right float hangs its extra into
   the band; a left one has no band to hang into (the text keeps the
   wordmark's left edge), so it stays half the text width. On a phone every
   picture takes the full width. --fw scales a smaller float. */
:root{--jfloat:calc(var(--measure) / 2 + var(--hang) * .3);
      --jtall:min(80vh, 44rem)}
@media (min-width:44rem){
  main .pic.jfloat.wrap-right{width:calc(var(--jfloat) * var(--fw, 1));
    margin-right:calc(-1 * var(--hang) * .3)}
  main .pic.jfloat.wrap-left{width:calc(var(--measure) / 2 * var(--fw, 1))}
}
/* {full}: across the text to the outer edge, as tall as 80% of the window
   (44rem at most), so a 3:2 photo reaches past the text on a laptop. */
main .pic.jfull img[style]{width:min(100%, var(--w), calc(var(--jtall) * var(--r)))}
@media (min-width:48rem){ main .pic.jfull{margin-right:calc(-1 * var(--hang))} }
/* {text}, and a trip page whose opening picture its post marks {text}:
   across, but only as wide as the text (Carl, Oct 24). */
@media (min-width:48rem){ main .pic.jfull.jtext{margin-right:0} }
/* A gallery: rows of whole photos, each row filling the width at one
   height. The build chooses the rows (mosaic_rows: every row's height
   nearest a target, at most five across on a laptop, three on a phone;
   Oct 19, 2026) and marks where each layout breaks (.mbreak.w, .mbreak.n);
   between breaks each photo grows in proportion to its shape. No script.
   Captions are in the viewer. A person's photo row with five or more
   photos, and a journal gallery of STRIP_AT or more (.jstrip, Oct 20),
   opens as a row and is laid out the same way after "View all"
   (.gallery.hybrid.as-mosaic). */
.mosaic,.gallery.as-mosaic .gallery-strip{display:flex; flex-wrap:wrap; gap:0 6px}
.mosaic{clear:both; margin:calc(var(--step)*.4) 0 var(--step)}
.gallery.as-mosaic .gallery-strip{overflow:visible; scroll-snap-type:none; padding:4px 0; margin:0}
.gallery.as-mosaic .gallery-step{display:none}
@media (min-width:48rem){ main .mosaic:not(.in-col),main .gallery.jstrip{margin-right:calc(-1 * var(--hang))} }
.gallery.jstrip{clear:both}
/* The line under a page's first photo row or gallery that says a photo
   opens (Carl, Oct 20, 2026): "Tap" on a touchscreen. Built hidden; the
   viewer's script shows it, since without the script there's no caption. */
.photo-hint{margin:2px 0 0; font:400 var(--size-small)/1.4 var(--body); color:var(--ink-3)}
.photo-hint .by-touch{display:none}
@media (pointer:coarse){ .photo-hint .by-mouse{display:none} .photo-hint .by-touch{display:inline} }
.mosaic + .photo-hint{margin:calc(-1 * var(--step) + 2px) 0 var(--step)}
.gallery .photo-hint + .gallery-open{margin-top:10px}
@media print{ .photo-hint{display:none} }
.mosaic .leaf,.gallery.as-mosaic .leaf{flex:calc(var(--r) * 100) 1 calc(var(--r) * 1px);
  min-width:0; margin:0 0 6px}
.mbreak{display:none}
@media (min-width:44rem){
  .mosaic .mbreak.w,.gallery.as-mosaic .mbreak.w{display:block; flex-basis:100%; height:0} }
@media (max-width:43.99rem){
  .mosaic .mbreak.n,.gallery.as-mosaic .mbreak.n{display:block; flex-basis:100%; height:0}
  .mosaic,.gallery.as-mosaic .gallery-strip{gap:0 4px}
  .mosaic .leaf,.gallery.as-mosaic .leaf{margin-bottom:4px} }
/* Hover as the other photos do (the zoom cursor), plus a slight brighten,
   no frame (Carl, Oct 19, 2026). The ring is for the keyboard only. A
   photo row hovers the same way, no lift (Carl, Oct 20). */
.mosaic .leaf a,.gallery.as-mosaic .leaf a{border:0; border-radius:0; background:none; cursor:zoom-in}
.gallery .leaf a{cursor:zoom-in}
.mosaic .leaf a:hover,.gallery .leaf a:hover{transform:none}
.gallery .leaf a:is(:hover,:focus-visible){border-color:var(--rule)}
.mosaic .leaf a:focus-visible,.gallery .leaf a:focus-visible{transform:none;
  outline:2px solid var(--accent); outline-offset:2px}
.mosaic .leaf img,.gallery.as-mosaic .leaf img{aspect-ratio:var(--r); width:100%; height:auto;
  max-width:100%; object-fit:cover}
.mosaic .leaf img,.gallery .leaf img{transition:filter .18s ease}
.mosaic .leaf a:hover img,.gallery .leaf a:hover img{filter:brightness(1.07)}
.mosaic .leaf figcaption{position:absolute; width:1px; height:1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap}
/* A callout: a picture inside a quote ("Did You Know?"), drawn as a card
   in the card colour with a soft bar of the accent; its picture stays
   small beside the text at every width. */
.callout{clear:both; display:flow-root; background:var(--card);
  border:1px solid var(--rule);
  border-left:5px solid color-mix(in srgb, var(--accent) 45%, var(--card));
  border-radius:6px; padding:1.1em 1.3em;
  margin:calc(var(--step)*.6) 0 var(--step); font-size:calc(var(--size) * .9)}
.callout p{margin:0 0 .7em} .callout p:last-child{margin-bottom:0}
.callout .by{color:var(--ink-3)}
.callout figure{margin:.2em 0 .6em; width:min(36%, 13rem)}
.callout figure.at-left{float:left; margin-right:1.2em}
.callout figure.at-right{float:right; margin-left:1.2em}
.callout figure img{display:block; width:100%; height:auto; border-radius:4px}

/* Photos reveal as the page scrolls: a fade and a 10px rise, 0.35 s,
   once each (DECISIONS, Oct 19, 2026). Photos only, never words: a reader
   never waits for text. Only the script hides a photo (.rv), and only just
   before revealing it, so without it every photo simply shows; nothing
   moves when motion is off. Fades and shifts only: Safari draws them well
   on a moving layer. */
.rv{opacity:0; transform:translateY(10px);
  transition:opacity .35s ease-out, transform .35s cubic-bezier(.2,.7,.2,1)}
.rv.rv-in{opacity:1; transform:none}
@media print{ .rv{opacity:1 !important; transform:none !important} }
@media (max-width:47.99rem){ .pic.pair.newspaper{grid-template-columns:1fr} }
/* A page's banner: wide and short across the top, cropped to the part of
   the picture its entry names (--focus). Taller on a phone, so it isn't a
   sliver. */
.pic.banner{margin:0 0 var(--step)}
.pic.banner img{width:100%; max-height:none; aspect-ratio:16 / 9; object-fit:cover;
  object-position:var(--focus, 50% 50%)}
@media (min-width:48rem){ .pic.banner img{aspect-ratio:21 / 9} }
/* A banner shown whole, at its own shape, not cut to the strip:
   planetposts.me's home (Carl, Oct 19: "uncrop... use my original"). */
.pic.banner.whole img{aspect-ratio:var(--r); height:auto}
/* Its portrait crop on an upright screen (--rp, with a <source> matching
   this query): the room is kept at the right shape before it arrives. */
@media (orientation:portrait){ .pic.banner.whole img{aspect-ratio:var(--rp, var(--r))} }
/* A panorama ("panorama": true in its entry) runs the page's full width
   under the title, as the lineage pages' banners do, at its own proportions:
   it was made wide, so cropping it to 21:9 would only cut its ends. A phone
   still crops it to 16:9 around the focus. Its caption, kept short, runs
   the picture's width. */
@media (min-width:48rem){ .pic.banner.pano img{aspect-ratio:auto} }
.pic.banner.pano{margin:calc(var(--step)*.6) 0 var(--step)}
/* The route map (scripts/route_map.py): the column's width, and on a phone
   it keeps a readable size and scrolls sideways instead of shrinking. */
.route{margin:calc(var(--step)*.4) 0 var(--step)}
.route-scroll{overflow-x:auto; border-radius:4px}
.route-scroll svg{display:block; width:100%; min-width:720px; height:auto}
/* The close-up of the homesteads is portrait and legible at a phone's width. */
.route.land .route-scroll svg{min-width:0; max-width:100%; margin:0}
@media (max-width:560px){ .route.land .route-scroll svg{min-width:520px} }
.route.land .land-links{display:block; margin-top:.35em}
/* An aside under a land map's caption, closed until asked for. */
.land-more{margin-top:.35em}
.land-more > summary{
  cursor:pointer; width:max-content; list-style:none;
  color:var(--ink-2); font-weight:600;
}
.land-more > summary::-webkit-details-marker{display:none}
.land-more > summary::after{
  content:"\203A"; display:inline-block; margin-left:.35em; transition:transform .18s;
}
.land-more[open] > summary::after{transform:rotate(90deg)}
/* Every fold opens the same way: the label, then "›" on its right, turning
   a quarter when open. The farms' "Who lived here" list and the search
   tips had the browser's triangle on the left, which reads as a bullet
   (Carl, Oct 18, 2026). */
.place-fold > summary,.find-tips > summary{list-style:none}
.place-fold > summary::-webkit-details-marker,.find-tips > summary::-webkit-details-marker{display:none}
.place-fold > summary::marker,.find-tips > summary::marker{content:""}
.place-fold > summary::after,.find-tips > summary::after{
  content:"\203A"; display:inline-block; margin-left:.35em; transition:transform .18s;
}
.place-fold[open] > summary::after,.find-tips[open] > summary::after{transform:rotate(90deg)}
.land-more p{margin:.3em 0 0}
.route.land{clear:both}   /* never squeezed beside a floated photograph */
.route figcaption{font-size:var(--size-small); color:var(--ink-3); margin-top:.6em}
.route-hint{display:none}
@media (max-width:760px){ .route-hint{display:inline} }
@media print{ .route-scroll{overflow:visible} .route-scroll svg{min-width:0} .route-hint{display:none} }
/* The map full screen: the page's own ground, so the map looks as it does
   in the page; zoom buttons above, and the map scrolls and drags beneath. */
.route-scroll svg{cursor:zoom-in}
.mapview{position:fixed; inset:0; z-index:100; display:none; background:var(--paper)}
.mapview.on{display:block}
.mvbar{position:absolute; top:0; left:0; right:0; height:60px; z-index:1;
  display:flex; align-items:center; justify-content:center; gap:10px;
  background:var(--raised); border-bottom:1px solid var(--rule)}
.mvbar button{margin:0; min-width:44px; height:40px; justify-content:center}
.mvbar .mvclose{position:absolute; right:12px}
.mvscroll{position:absolute; inset:60px 0 0; overflow:auto; display:flex;
  padding:12px; touch-action:pan-x pan-y; cursor:grab}
.mvscroll.drag{cursor:grabbing}
.mvscroll svg{margin:auto; flex:none; display:block; height:auto}
/* a trip map's controls, under it (scripts/trip_map.py) */
.mvfoot{position:absolute; left:0; right:0; bottom:0; background:var(--raised);
  border-top:1px solid var(--rule); padding:10px 16px 14px}
.mvfoot .tm-bar{max-width:60rem; margin:0 auto}
@media print{ .route-open{display:none} }
/* Full screen on every map is a small chip in its top-right corner, over
   the map (Carl, Oct 27: a row for one pill button was too much, and an
   icon alone got lost in the map; words say what it does). A tap on the
   map opens it too. The figure's map is its first child, so the chip is
   placed against the figure. A map under 560px wide (a phone) has no room
   for it: the chip covered labels on the trip map's close-up and on the
   Langdon maps, which scroll sideways there. Then it sits beside the
   caption's first line, or at the end of the trip map's Play and Restart
   row, and the farm maps, which always fit, keep it on the map. */
.route,.trip-map{position:relative}
.route:not(.place-map),.trip-map{container:map / inline-size}
.mvfoot .route-open{display:none}   /* the viewer has its own controls */
.route .route-open,.trip-map .route-open{position:absolute; top:10px; right:10px; margin:0;
  padding:0 10px 0 7px; height:28px; gap:5px; font:500 12px/1 var(--body); white-space:nowrap;
  border:1px solid var(--rule); border-radius:8px;
  background:color-mix(in srgb,var(--raised) 82%,transparent); color:var(--ink-2)}
.route .route-open[hidden],.trip-map .route-open[hidden]{display:none}
.route .route-open:is(:hover,:focus-visible),.trip-map .route-open:is(:hover,:focus-visible){
  border-color:var(--accent); color:var(--ink)}
.route-open svg{width:15px; height:15px; pointer-events:none; fill:none; stroke:currentColor; stroke-width:1.6;
  stroke-linecap:round; stroke-linejoin:round}
/* after the rule above, which it overrides on a narrow map */
@container map (max-width:560px){
  .route .route-open{position:static; float:right; margin:.45em 0 .3em .8em}
  .trip-map .route-open{position:static; margin-left:auto}
  .trip-map .tm-btns{align-self:stretch}
}
/* The farm pages and Places (scripts/farm_page.py). Water is blue in every
   palette (Carl, Oct 9, 2026): Radix Colors blue, light steps 5/8/11, dark
   5/8/11. Fills stay pale so a name crossing them reads, and every name
   carries a halo of the map's own ground. */
:root{--water:#c2e5ff; --water-line:#5eb1ef; --water-ink:#0d74ce}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){--water:#004074; --water-line:#2870bd; --water-ink:#70b8ff} }
:root[data-theme="dark"]{--water:#004074; --water-line:#2870bd; --water-ink:#70b8ff}
.place-facts{display:flex; flex-wrap:wrap; gap:.3rem 1.2rem; margin:0 0 1.4rem; padding:.7rem 0;
  border-block:1px solid var(--rule); font-size:var(--size-small); color:var(--ink-2)}
.place-facts b{font-weight:600; color:var(--ink-3); font-size:.78em; letter-spacing:.06em;
  text-transform:uppercase; margin-right:.35em}
.place-note{font-size:var(--size-small)}
.place-map{float:right; width:280px; margin:.3rem 0 1rem 1.6rem; text-align:center}
/* The valley map on the farms page is tall, so it stays in the column at
   the text's left edge, like a tall picture (Oct 18, 2026: centred in a box
   reaching the outer edge, it sat 400px in, the page bare beside it). */
.place-map.wide-map{float:none; width:auto; max-width:560px; margin:calc(var(--step)*.4) 0 var(--step)}
@media (max-width:44rem){ .place-map{float:none; margin:0 auto 1.2rem} }
.farm-map{display:block; width:100%; height:auto; background:var(--raised);
  border:1px solid var(--rule); border-radius:10px}
.place-map svg{cursor:zoom-in}
.fm-lake{fill:var(--water); stroke:var(--water-line); stroke-width:.5}
.fm-river{fill:none; stroke:var(--water-line); stroke-width:1.6; stroke-linejoin:round; stroke-linecap:round}
.fm-road{fill:none; stroke:color-mix(in srgb,var(--ink-3) 55%,var(--raised)); stroke-width:1.1}
.fm-dot{fill:var(--ink-3)} .fm-dot.prob{fill:var(--raised); stroke:var(--ink-3); stroke-width:1.4}
.fm-dot.me{fill:var(--accent); stroke:var(--raised); stroke-width:2}
.farm-map a:is(:hover,:focus-visible) .fm-dot{fill:var(--accent)}
.farm-map a:is(:hover,:focus-visible) .fm-lab{fill:var(--accent)}
.fm-lab{font:500 11px/1 var(--body); fill:var(--ink-2)} .fm-lab.me{font-size:12px; font-weight:700; fill:var(--ink)}
.fm-area,.fm-village{font:600 9px/1 var(--body); letter-spacing:.12em; fill:var(--ink-3)}
.fm-sm{font:400 10px/1 var(--body); fill:var(--ink-3)} .fm-scale{stroke:var(--ink-3); stroke-width:2}
.fm-lab,.fm-area,.fm-sm,.fm-village,.fm-tiny{paint-order:stroke; stroke:var(--raised);
  stroke-width:3px; stroke-linejoin:round}
.fm-inset{fill:var(--raised); stroke:var(--rule-strong); stroke-width:1}
.fm-land{fill:color-mix(in srgb,var(--ink) 6%,var(--raised)); stroke:color-mix(in srgb,var(--ink) 25%,var(--raised)); stroke-width:.5}
.fm-land.no{fill:color-mix(in srgb,var(--ink) 14%,var(--raised))}
.fm-box{fill:none; stroke:var(--accent); stroke-width:1.6}
.fm-city{fill:var(--ink-2)} .fm-tiny{font:500 7.5px/1 var(--body); letter-spacing:.06em; fill:var(--ink-2)}
.route.place-map figcaption{margin-top:3px}
.fm-credit{display:block; margin-bottom:.45em; text-align:right; font-size:.68rem; line-height:1.4}
.fm-credit a{color:inherit; text-decoration:none}
.fm-credit a:hover{text-decoration:underline}
.map-links{text-align:center}
.place-who{clear:both}
.tl-wrap{overflow-x:auto; overscroll-behavior-x:contain; scrollbar-width:thin}
.tl{display:block; min-width:600px; margin:.6rem 0 .2rem; overflow:visible}
.tl-grid{stroke:var(--rule); stroke-width:1} .tl-yr{font:400 11px/1 var(--body); fill:var(--ink-3)}
.tl-name{font:400 13px/1 var(--serif); fill:var(--ink)} a:is(:hover,:focus-visible) .tl-name{fill:var(--accent)}
.tl-bar{fill:var(--line-2); opacity:.75} .tl-bar.approx{opacity:.4} .tl-bar.open{opacity:.35}
.tl-here{fill:var(--accent); stroke:var(--raised); stroke-width:2}
.tl-dates{font:400 11px/1 var(--body); fill:var(--ink-3)}
.tl-key{font-size:var(--size-small); color:var(--ink-3); margin:0 0 1rem}
.tl-key i{display:inline-block; width:10px; height:10px; border-radius:50%; background:var(--accent);
  vertical-align:-1px; margin:0 .3em 0 0}
.place-fold > summary{cursor:pointer; font-size:var(--size-small); color:var(--ink-2); font-weight:600;
  width:max-content; max-width:100%}
.place-list,.place-index{list-style:none; padding:0; margin:.4rem 0 1.4rem; font-size:var(--size-small)}
.place-list li,.place-index li{padding:.35rem 0; border-bottom:1px solid var(--rule)}
.place-index li{font-size:calc(var(--size) * .8)}
.place-index .dim,.place-list .dim{color:var(--ink-3); font-size:var(--size-small)}
.place-parish{margin-top:calc(var(--step)*.8)}
@media print{ .place-map{float:none} .tl{min-width:0} }
/* An altered photograph says so (SPECS: altered images are labelled):
   "Colorized", "Restored". A small quiet chip after the caption, so the
   reader is told without the label competing with the words. */
/* A caption's chips (Oct 17, 2026): small boxes with softened corners on a
   faint wash of the ink colour. A label (Illustration, Colorized) is in
   small capitals behind a lighter outline; a control (Credit, the Restored
   switch) is in ordinary type behind a firmer one, and Credit carries an
   arrow, so a phone shows which of them opens something. */
:root{--chip-bg:color-mix(in srgb, var(--ink) 6%, transparent)}
.pic-tag{display:inline-block; margin-left:.45em; padding:2px 7px 3px;
         border:1px solid var(--rule-strong); border-radius:4px;
         background:var(--chip-bg);
         font:500 .8em/1.2 var(--body); font-style:normal;
         letter-spacing:.03em; color:var(--ink-3); vertical-align:middle;
         white-space:nowrap}
span.pic-tag:not(.pic-orig){
  border-color:color-mix(in srgb, var(--rule-strong) 60%, transparent);
  text-transform:uppercase; letter-spacing:.09em; font-size:.68em; font-weight:600;
  /* the same height as a control: .8em × 1.2 = .68em × 1.41 */
  line-height:1.41}
/* When the original scan is on file the chip reaches it: a link without
   script, a switch with it that swaps the scan into the same frame
   (letterboxed if its shape differs) and back. The hit area reaches past
   the small chip for fingers. */
a.pic-tag,.pic-tag a{color:inherit; text-underline-offset:2px;
                     text-decoration-color:var(--rule-strong)}
button.pic-tag{position:relative; background:var(--chip-bg); cursor:pointer;
               color:var(--ink-2)}
button.pic-tag::after{content:""; position:absolute; inset:-9px -4px}
button.pic-tag:hover{border-color:var(--accent); color:var(--ink)}
button.pic-tag:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
button.pic-orig{display:inline-grid; justify-items:center}
button.pic-orig > span{grid-area:1 / 1}
button.pic-orig[data-on="true"] > span:first-child,
button.pic-orig:not([data-on="true"]) > span:last-child{visibility:hidden}
/* The credit chip: the credit on a small card above the caption, opened
   by a tap (a <details>, no script) or, with a mouse, by hovering. The card
   sits on the caption's left edge so it never runs off a phone's screen.
   Printed, the credit is simply part of the caption. */
figcaption:has(> .pic-credit),.lb .lbcap{position:relative}
.pic-credit{display:inline; font-style:normal}
.pic-credit > summary{display:inline-block; list-style:none; cursor:pointer;
                      color:var(--ink-2)}
.pic-credit > summary::-webkit-details-marker{display:none}
.pic-credit > summary:hover{border-color:var(--accent); color:var(--ink)}
.pic-credit > summary:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
.pic-credit > summary{position:relative}
.pic-credit > summary::after,.pic-credit > button.pic-tag::after{content:""; display:inline-block;
  position:static; inset:auto; width:.38em; height:.38em;
  margin-left:.5em; border-right:1.5px solid currentColor; border-bottom:1.5px solid currentColor;
  transform:translateY(-.18em) rotate(45deg); transition:transform .2s ease}
.pic-credit[open] > summary::after,.pic-credit.on > button.pic-tag::after{transform:translateY(.06em) rotate(-135deg)}
/* A thumb-sized target (about 46px tall), without a bigger chip. */
.pic-credit > summary::before,.pic-credit > button.pic-tag::before{content:""; position:absolute; inset:-12px -10px}
.pic-credit > span{position:absolute; left:0; bottom:calc(100% + 6px); z-index:2;
  width:max-content; max-width:min(400px,100%); box-sizing:border-box;
  padding:7px 10px; background:var(--raised); border:1px solid var(--rule-strong);
  border-radius:8px; box-shadow:0 4px 14px color-mix(in srgb,var(--ink) 12%,transparent);
  font:400 1em/1.45 var(--body); font-style:normal; color:var(--ink-2);
  text-align:left; white-space:normal}
.pic-credit:not([open]) > span{display:none}
/* With the script running (html.credit-js) the <details> is swapped for a
   plain button and the card is shown by a class, .on. Safari on iPhone
   fought the <details> both ways: it toggled it itself as well as the
   script, then drew nothing inside a closed one (Carl, Oct 17, 2026).
   Only a click or tap opens it, never hover: a card that comes and goes
   as the pointer passes isn't something you chose to open (Carl, Oct 17). */
html.credit-js .pic-credit > span{display:none}
html.credit-js .pic-credit.on > span{display:block}
@media print{ .pic-credit > summary,.pic-credit > button{display:none}
  .pic-credit > span,html.credit-js .pic-credit > span{display:inline; position:static; padding:0; border:0;
                     background:none; box-shadow:none; font:inherit} }
.pic img[data-orig],.lb img{object-fit:contain; transition:opacity .2s ease}
.pic img.swapping,.lb img.swapping{opacity:0}
/* A folded passage ([data-fold], the shell script) fades out at its foot. */
[data-fold].folded{max-height:var(--fold); overflow:hidden;
  -webkit-mask-image:linear-gradient(#000 calc(100% - 3.5em), transparent);
          mask-image:linear-gradient(#000 calc(100% - 3.5em), transparent)}
.fold-btn{font:500 var(--size-small)/1.4 var(--body); color:var(--deep); background:none; border:0;
  padding:8px 0; cursor:pointer; text-decoration:underline; text-decoration-color:var(--rule-strong);
  text-underline-offset:3px}
.fold-btn:hover{text-decoration-color:currentColor}
@media print{ [data-fold].folded{max-height:none; -webkit-mask-image:none; mask-image:none} .fold-btn{display:none} }
/* Words most visitors won't know (data/glossary.json, add-glossary.py): a
   quiet dotted underline on the first use, and a small card beside it when
   tapped. The card is a native popover; without support it never shows
   inline, and the word stays an ordinary link to /glossary. */
/* [href] for weight: the McGregor page styles its own links and would
   otherwise win. */
a.gloss[href]{color:inherit; text-decoration:underline dotted 1px;
        text-decoration-color:var(--ink-3); text-underline-offset:3px;
        cursor:help; font-weight:inherit; border:0; background:none}
a.gloss[href]:hover,a.gloss[aria-expanded="true"]{text-decoration-color:var(--ink)}
.gloss-pop{display:none}
.gloss-pop:popover-open{
  display:block; position:fixed; inset:auto; margin:0;
  width:max-content; max-width:min(22rem, calc(100vw - 24px));
  padding:12px 14px; border:1px solid var(--rule); border-radius:12px;
  background:var(--raised); color:var(--ink);
  box-shadow:0 14px 40px rgba(0,0,0,.14);
  font:400 var(--size-small)/1.5 var(--body); font-style:normal;
  text-align:left; letter-spacing:normal; text-transform:none;
}
.gloss-pop b{font-weight:600; color:var(--heading)}
.gloss-pop b span{font-weight:400; color:var(--ink-3)}
.gloss-pop a{display:block; margin-top:6px; color:var(--ink-3);
             font-size:.92em}
.glossary dt{margin:1.3em 0 .2em; font-weight:600; color:var(--heading)}
.glossary dd{margin:0}
/* Download links under a page's introduction. */
.title .downloads,.title .also{font-size:var(--size-small); color:var(--ink-3);
                  margin:calc(var(--step)*.8) 0 0; max-width:var(--measure)}
/* "What's an e-book?" under them: one quiet line that opens in place. */
.title .dl-help{font-size:var(--size-small); color:var(--ink-3); margin:.3em 0 0; max-width:var(--measure)}
.title .dl-help > summary{cursor:pointer; width:max-content; list-style:none}
.title .dl-help > summary::-webkit-details-marker{display:none}
.title .dl-help > summary::after{content:"\203A"; display:inline-block; margin-left:.35em;
  transition:transform .18s}
.title .dl-help[open] > summary::after{transform:rotate(90deg)}
.title .dl-help > summary:hover{color:var(--ink-2)}
.title .dl-help p{margin:.4em 0 0}
/* ---- recipes: serving control, check-off, timers -------------------
   From MyBaseCamp, in this site's tokens. scripts/recipes.js adds the
   controls; without it the recipe reads as plain text.
------------------------------------------------------------------- */
.rcp-base{font-size:var(--size-small); color:var(--ink-3)}
.rcp-controls{display:flex; align-items:center; gap:18px; flex-wrap:wrap;
              margin:4px 0 20px}
.rcp-servings{display:flex; align-items:center; gap:10px; flex-wrap:wrap}
.rcp-step-btn{
  width:36px; height:36px; border-radius:50%; border:1px solid var(--rule-strong);
  background:var(--raised); color:var(--ink-2); font-size:20px; line-height:1;
  cursor:pointer; display:flex; align-items:center; justify-content:center;
  padding:0; -webkit-tap-highlight-color:transparent;
}
.rcp-step-btn:hover{border-color:var(--accent); color:var(--accent)}
.rcp-step-btn:active{background:var(--lift)}
.rcp-serving-value{font:400 var(--size)/1.2 var(--serif); color:var(--ink);
                   min-width:6.5em; text-align:center; font-variant-numeric:tabular-nums}
.rcp-reset{background:none; border:0; color:var(--ink-3); cursor:pointer;
           font:600 calc(var(--size) * .62)/1 var(--body); letter-spacing:.1em;
           text-transform:uppercase; padding:6px 4px}
.rcp-reset:hover{color:var(--accent)}
.rcp-reset[hidden]{display:none}
/* An amount that answers the serving control, quietly marked as such. */
.rcp-amt{color:var(--accent); font-weight:600; font-variant-numeric:tabular-nums;
         white-space:nowrap}
.recipe-ingredients li.rcp-ing{cursor:pointer; -webkit-tap-highlight-color:transparent}
.recipe-ingredients li.rcp-ing.is-done{color:var(--ink-3); text-decoration:line-through;
                                       text-decoration-color:var(--rule-strong)}
.recipe-ingredients li.rcp-ing.is-done .rcp-amt{color:inherit}
.recipe-ingredients li.rcp-ing:focus-visible{outline:2px solid var(--accent);
                                             outline-offset:2px; border-radius:3px}
/* Steps are numbered straight through a recipe, its directions' parts
   included (Carl, Nov 2, 2026): the count is the recipe's, not each list's. */
.recipe{counter-reset:rcp}
ol.rcp-steps{list-style:none; margin:0 0 1.15em; padding:0}
ol.rcp-steps > li{
  counter-increment:rcp; position:relative; padding:10px 12px 10px 52px;
  margin:0; border-radius:8px; cursor:pointer; outline:none;
  -webkit-tap-highlight-color:transparent;
}
ol.rcp-steps > li::before{
  content:counter(rcp); position:absolute; left:12px; top:10px;
  width:28px; height:28px; border-radius:50%; border:1.5px solid var(--rule-strong);
  color:var(--ink-3); font:600 14px/1 var(--body);
  display:flex; align-items:center; justify-content:center;
}
ol.rcp-steps > li:hover{background:var(--lift)}
ol.rcp-steps > li:focus-visible{box-shadow:0 0 0 2px var(--accent)}
ol.rcp-steps > li.is-done{color:var(--ink-3); opacity:.7}
ol.rcp-steps > li.is-done::before{content:"\2713"; background:var(--deep);
                                  border-color:var(--deep); color:var(--paper)}
.rcp-timer{
  display:inline-flex; align-items:center; gap:6px; margin-left:4px;
  padding:3px 12px; border-radius:999px; border:1px solid var(--rule-strong);
  background:var(--raised); color:var(--ink-2);
  font:500 var(--size-small)/1.4 var(--body); font-variant-numeric:tabular-nums;
  cursor:pointer; vertical-align:baseline; -webkit-tap-highlight-color:transparent;
}
.rcp-timer::before{content:""; border-style:solid; border-width:5px 0 5px 8px;
                   border-color:transparent transparent transparent currentColor}
.rcp-timer:hover{border-color:var(--accent); color:var(--accent)}
.rcp-timer.is-running{border-color:var(--accent); color:var(--accent); background:var(--lift)}
.rcp-timer.is-running::before{width:12px; height:12px; border-radius:50%;
  border:1.5px solid currentColor; border-top-color:transparent;
  animation:rcp-spin 1.4s linear infinite}
.rcp-timer.is-done{border-color:var(--deep); color:var(--deep)}
.rcp-timer.is-done::before{content:"\2713"; border:0; font-weight:700}
.rcp-timer.is-alarming{border-color:var(--accent); background:var(--accent);
                       color:var(--paper); animation:rcp-pulse .9s ease-in-out infinite}
.rcp-timer.is-alarming::before{content:"\25A0"; border:0; font-size:11px}
@keyframes rcp-spin{to{transform:rotate(360deg)}}
@keyframes rcp-pulse{50%{opacity:.6}}
/* Running timers, pinned to the bottom so they stay in view. */
.rcp-tray{
  position:fixed; left:0; right:0; bottom:0; z-index:35;
  background:var(--raised); border-top:1px solid var(--rule);
  box-shadow:0 -4px 16px rgba(0,0,0,.1); transform:translateY(100%);
  transition:transform .28s cubic-bezier(.32,.72,.28,1);
  padding-bottom:env(safe-area-inset-bottom, 0px);
}
.rcp-tray.open{transform:none}
.rcp-tray-list{max-width:var(--site); margin:0 auto; padding:8px var(--gutter);
               display:flex; flex-direction:column; gap:6px}
.rcp-tray-row{display:flex; align-items:center; gap:12px}
/* The name and time open the timer's step (on the cook board, its recipe). */
.rcp-tray-go{flex:1; min-width:0; display:flex; align-items:center; gap:12px; padding:4px 0;
             background:none; border:0; font:inherit; color:inherit; text-align:left; cursor:pointer}
.rcp-tray-name{flex:1; min-width:0; font-size:var(--size-small); color:var(--ink-2);
               white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.rcp-tray-time{font-weight:600; color:var(--accent); font-variant-numeric:tabular-nums;
               min-width:3.5em; text-align:right}
.rcp-tray-stop{width:32px; height:32px; border-radius:50%; flex-shrink:0; padding:0;
               border:1px solid var(--rule-strong); background:var(--paper); cursor:pointer;
               display:flex; align-items:center; justify-content:center}
.rcp-tray-stop-icon{width:10px; height:10px; background:var(--accent); border-radius:2px}
/* The tools float above the tray when it is open. */
body:has(.rcp-tray.open) .tools{bottom:calc(20px + 4.2rem)}
/* Keep screen on, at the foot of the Contents & search panel. */
.find-foot{border-top:1px solid var(--rule); padding:10px 12px}
.keepawake{
  display:flex; align-items:center; gap:10px; width:100%; cursor:pointer;
  font:500 var(--size-small)/1 var(--body); color:var(--ink-2);
  background:none; border:1px solid var(--rule); border-radius:999px; padding:10px 14px;
}
.keepawake-dot{width:10px; height:10px; border-radius:50%;
               border:1.5px solid var(--ink-3)}
.keepawake[aria-pressed="true"]{color:var(--ink); border-color:var(--deep)}
.keepawake[aria-pressed="true"] .keepawake-dot{background:var(--deep); border-color:var(--deep)}
@media print{
  .rcp-controls,.rcp-timer,.rcp-tray{display:none!important}
  ol.rcp-steps > li.is-done,.recipe-ingredients li.rcp-ing.is-done{
    opacity:1; color:inherit; text-decoration:none}
}
/* The two buttons under a recipe page's introduction, as in MyBaseCamp. */
.recipe-top{display:flex; flex-wrap:wrap; gap:10px; margin:calc(var(--step)*1.1) 0 0}
.pill{
  display:inline-flex; align-items:center; gap:8px; cursor:pointer;
  font:600 calc(var(--size) * .66)/1 var(--body); letter-spacing:.14em;
  text-transform:uppercase; color:var(--accent); background:transparent;
  border:1px solid var(--rule-strong); border-radius:999px; padding:10px 18px;
}
.pill:hover{border-color:var(--accent); background:var(--lift)}
@media (max-width:44rem){ .pill{padding:9px 13px; letter-spacing:.08em} .recipe-top{gap:8px} }
.pill svg{width:13px; height:13px; fill:none; stroke:currentColor; stroke-width:1.8}
/* Cook: the cook board with this recipe on it (cook-board.js). */
a.pill.cook-go{text-decoration:none; background:var(--deep); border-color:var(--deep); color:var(--paper)}
a.pill.cook-go:hover{background:color-mix(in srgb, var(--deep) 85%, var(--ink))}
.fav-count{
  min-width:1.5em; padding:3px 6px; border-radius:999px; text-align:center;
  background:var(--accent); color:var(--paper); letter-spacing:0; font-size:.95em;
}
.fav-count[hidden]{display:none}
/* A recipe's title row: the heart, and the jigger for drinks. */
.recipe-head{display:flex; align-items:flex-start; gap:12px}
.recipe-head > .recipe-title{flex:1; min-width:0}
.recipe-actions{display:flex; gap:8px; flex-shrink:0;
                margin-top:calc(var(--step)*1.6)}
h3.recipe-title + .recipe-actions{margin-top:calc(var(--step)*2.2)}
.recipe-jigger-btn,.recipe-fav-btn{
  width:36px; height:32px; padding:0; cursor:pointer; color:var(--accent);
  display:inline-flex; align-items:center; justify-content:center;
  background:transparent; border:1px solid var(--rule-strong); border-radius:8px;
}
.recipe-jigger-btn:hover,.recipe-fav-btn:hover{border-color:var(--accent); background:var(--lift)}
.recipe-jigger-btn svg,.recipe-fav-btn svg{width:16px; height:16px; fill:none; stroke-linejoin:round;
  stroke:currentColor; stroke-width:1.7; stroke-linejoin:round; stroke-linecap:round}
.recipe-copy-btn{
  height:32px; padding:0 10px; cursor:pointer; color:var(--accent);
  display:inline-flex; align-items:center; gap:6px;
  background:transparent; border:1px solid var(--rule-strong); border-radius:8px;
  font:600 calc(var(--size) * .6)/1 var(--body); letter-spacing:.1em; text-transform:uppercase;
}
.recipe-copy-btn:hover{border-color:var(--accent); background:var(--lift)}
.recipe-copy-btn svg{width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:1.8}
.recipe-copy-btn.copied{background:var(--deep); border-color:var(--deep); color:var(--paper)}
@media (max-width:44rem){ .recipe-copy-btn .rc-text{display:none} .recipe-copy-btn{width:36px; padding:0; justify-content:center} }
.recipe-fav-btn.is-fav{border-color:var(--accent)}
.recipe-fav-btn.is-fav svg{fill:var(--accent)}
.jigger-overlay{
  position:fixed; inset:0; z-index:60; display:flex; align-items:center;
  justify-content:center; background:rgba(0,0,0,.88);
  opacity:0; pointer-events:none; transition:opacity .2s;
}
.jigger-overlay.open{opacity:1; pointer-events:auto}
.jigger-overlay img{max-width:92vw; max-height:88vh; border-radius:8px}
.jigger-close{position:absolute; top:16px; right:16px}
/* Favorites: a sheet from the right, as MyBaseCamp had it. */
.fav-panel{position:fixed; inset:0; z-index:60; pointer-events:none}
.fav-scrim{position:absolute; inset:0; background:rgba(0,0,0,.35);
           opacity:0; transition:opacity .2s}
.fav-sheet{
  position:absolute; top:0; right:0; bottom:0; width:min(24rem, 92vw);
  background:var(--raised); border-left:1px solid var(--rule);
  box-shadow:-12px 0 40px rgba(0,0,0,.18); overflow:auto;
  transform:translateX(100%); transition:transform .25s cubic-bezier(.2,.7,.2,1);
  font:400 var(--size-small)/1.4 var(--body); color:var(--ink);
}
.fav-panel.open{pointer-events:auto}
.fav-panel.open .fav-scrim{opacity:1}
.fav-panel.open .fav-sheet{transform:none}
.fav-sheet-head{display:flex; align-items:center; justify-content:space-between;
                padding:18px 18px 10px; border-bottom:1px solid var(--rule)}
.fav-sheet-head h2{font:400 calc(var(--size) * 1.2)/1.2 var(--serif); color:var(--heading); margin:0}
.fav-rm{
  width:34px; height:34px; border-radius:50%; flex-shrink:0; cursor:pointer;
  border:1px solid var(--rule); background:none; color:var(--ink-2);
  font-size:20px; line-height:1;
}
.fav-list{list-style:none; margin:0; padding:8px}
.fav-list li{display:flex; align-items:center; gap:8px; margin:0}
.fav-go{
  flex:1; min-width:0; display:flex; align-items:center; gap:12px; text-align:left;
  background:none; border:0; border-radius:10px; padding:8px; cursor:pointer;
  font:inherit; color:inherit;
}
.fav-go:hover{background:var(--lift)}
.fav-thumb{width:48px; height:48px; object-fit:cover; border-radius:8px; flex-shrink:0}
.fav-words{min-width:0}
.fav-name{display:block; font-weight:600; color:var(--heading)}
.fav-sec{display:block; color:var(--ink-3); font-size:.9em}
.fav-empty{color:var(--ink-3); padding:14px 10px}
/* The way from a notebook's saved recipes to everything saved (Oct 28, 2026). */
.fav-all{margin:10px 10px 4px; font-size:var(--size-small)}
.fav-all a{color:var(--deep)}
@media print{ .recipe-top,.recipe-actions{display:none} }
/* ---- the recipe library, Nov 2, 2026 (recipe_book.py) ---------------
   A recipe as a card: its photo or Base Camp's "Photo coming soon" glass,
   its title, a line. The cards are a list, so without styles the library
   reads as one, grouped by course. */
.rcards{list-style:none; padding:0; margin:14px 0 calc(var(--step)*2);
  display:grid; gap:12px; grid-template-columns:repeat(2,minmax(0,1fr))}
@media (min-width:44rem){ .rcards{grid-template-columns:repeat(auto-fill,minmax(12.5rem,1fr)); gap:18px} }
.rcard{position:relative; margin:0; padding:0}
.rcard > a{display:flex; flex-direction:column; height:100%; text-decoration:none; color:inherit;
  background:var(--card); border:1px solid var(--rule-strong); border-radius:14px; overflow:hidden;
  box-shadow:0 1px 2px color-mix(in srgb, var(--ink) 7%, transparent);
  transition:transform .25s cubic-bezier(.2,.7,.2,1), box-shadow .25s cubic-bezier(.2,.7,.2,1),
             border-color .25s cubic-bezier(.2,.7,.2,1)}
.rcard > a:is(:hover,:focus-visible){transform:translateY(-2px); border-color:var(--deep);
  box-shadow:0 12px 28px color-mix(in srgb, var(--ink) 12%, transparent)}
.rcard-pic{position:relative; display:block; aspect-ratio:4 / 5; background:var(--tint); overflow:hidden}
.rcard-pic img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; display:block;
  transition:transform .6s cubic-bezier(.2,.7,.2,1)}
.rcard > a:is(:hover,:focus-visible) .rcard-pic img{transform:scale(1.04)}
.rcard-ph{position:absolute; inset:0; width:100%; height:100%; color:var(--ink-3); opacity:.75}
.rcard-ph-t{font-family:var(--serif)}
.rcard-status{position:absolute; left:10px; bottom:9px;
  font:600 calc(var(--size) * .56)/1 var(--body); letter-spacing:.1em; text-transform:uppercase;
  color:var(--ink-2); background:var(--card); border-radius:999px; padding:5px 8px}
.rcard-body{display:flex; flex-direction:column; gap:4px; padding:12px 14px 14px}
main .rcard-title{margin:0; font:400 calc(var(--size) * 1.02)/1.22 var(--serif); color:var(--ink);
  letter-spacing:0; text-transform:none}
.rcard-meta{font-size:var(--size-small); color:var(--ink-3); line-height:1.35}
.rcard-save{position:absolute; top:8px; right:8px; width:34px; height:34px; border-radius:50%;
  display:flex; align-items:center; justify-content:center; padding:0; cursor:pointer;
  background:color-mix(in srgb, var(--card) 88%, transparent); border:1px solid var(--rule-strong);
  color:var(--accent)}
.rcard-save svg{width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linejoin:round}
.rcard-save.is-fav svg{fill:currentColor}
.rcard-save:hover{border-color:var(--accent)}
/* Search first (Nov 2): the search box and menus, then the two notebooks
   as small cards, their photos filling the card's whole height. */
.rlib-find .rlib-bar{margin-top:0}
.rlib-notebooks[hidden]{display:none}
.nb-mini.cards{grid-template-columns:1fr 1fr; gap:10px; margin:10px 0 calc(var(--step)*1.4)}
.nb-mini .card{flex-direction:row; min-height:76px; border-radius:14px; --grow:1.02; --zoom:1.04;
  grid-column:auto}   /* not the front door's six-column spans */
.nb-mini .card-pic{width:clamp(72px, 30%, 168px); aspect-ratio:auto; max-height:none; align-self:stretch; flex:none}
.nb-mini .card-pic img{position:absolute; inset:0}
.nb-mini .card-body{padding:12px 14px; justify-content:center}
main .nb-mini h3{font-size:calc(var(--size) * .95); line-height:1.2; margin:0}
.nb-mini .card-tag,.nb-mini .card-go,.nb-mini .card-body p{display:none}
@media (min-width:44rem){
  .nb-mini .card{min-height:112px}
  .nb-mini .card-tag{display:block; margin-bottom:6px}
  .nb-mini .card-body p{display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
    margin:.4em 0 0; font-size:var(--size-small)}
}
.rlib-course{margin-top:calc(var(--step)*1.2)}
.rlib-course h3{margin-bottom:0}
.rlib-bar{display:flex; flex-direction:column; gap:12px; margin:14px 0 calc(var(--step)*.6)}
.rlib-searchbox{position:relative; max-width:30rem}
.rlib-searchbox svg{position:absolute; left:14px; top:50%; transform:translateY(-50%); width:17px; height:17px;
  fill:none; stroke:var(--ink-3); stroke-width:2; pointer-events:none}
.rlib-search{font:400 var(--size)/1.3 var(--body); color:var(--ink); background:var(--raised); box-sizing:border-box;
  border:1px solid var(--rule-strong); border-radius:999px; padding:11px 18px 11px 40px; width:100%}
.rlib-search:focus{outline:2px solid var(--accent); outline-offset:1px}
.rlib-count{margin:0; font-size:var(--size-small); color:var(--ink-3); display:flex; gap:14px; align-items:center}
/* Browse (Nov 2, 2026; DECISIONS, "Recipe tiles"): Courses, Categories or
   Saved in the Appearance panel's segmented control, then picture tiles with
   a name and a count, as RecipeKeeper shows them. A grid on a computer or an
   iPad; one sliding row of smaller tiles on a phone, where the grid would
   push the first recipe a screen down. Drawn by recipes.js. */
:root{--tile-ink:#ffffff; --tile-scrim:rgba(0,0,0,.72)}
.rlib-browse{display:flex; flex-direction:column; gap:10px}
.rlib-browse[hidden]{display:none}
.rlib-browse-head{display:flex; flex-wrap:wrap; align-items:center; gap:10px 16px}
.rlib-seg{width:min(100%, 24rem); background:var(--seg-track-page)}
.rlib-browse-back{display:flex; align-items:baseline; gap:12px}
.rlib-browse-back button{background:none; border:0; padding:4px 0; cursor:pointer; color:var(--deep);
  font:inherit; font-size:var(--size-small); text-decoration:underline; text-underline-offset:3px}
.rlib-browse-back h3{margin:0; font:400 1.35rem/1.2 var(--serif); color:var(--heading)}
.rlib-tiles{display:grid; grid-template-columns:repeat(auto-fill, minmax(8.75rem, 1fr)); gap:8px}
.rtile{position:relative; display:block; aspect-ratio:1; overflow:hidden; border:0; padding:0;
  border-radius:10px; cursor:pointer; background:var(--lift); color:var(--ink); font:inherit; text-align:left}
.rtile img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover}
.rtile .rcard-ph{inset:6% 14% 26%; width:72%; height:68%}
.rtile .rcard-ph-t{display:none}
.rtile-l{position:absolute; left:0; right:0; bottom:0; display:flex; justify-content:space-between;
  align-items:flex-end; gap:6px; padding:22px 9px 7px; font-size:.92rem; line-height:1.2;
  color:var(--tile-ink); background:linear-gradient(transparent, var(--tile-scrim))}
.rtile.no-pic .rtile-l{color:var(--ink); background:none}
.rtile-n{font-variant-numeric:tabular-nums; opacity:.9}
.rtile[aria-pressed="true"]{box-shadow:0 0 0 3px var(--accent)}
.rtile:focus-visible{outline:3px solid var(--accent); outline-offset:2px}
@media (hover:hover){ .rtile:hover img{transform:scale(1.03)} .rtile img{transition:transform .25s} }
[data-motion="off"] .rtile img{transition:none; transform:none}
.rlib-saved-note{margin:2px 0 0; color:var(--ink-2)}
@media (max-width:600px){
  .rlib-tiles{display:flex; overflow-x:auto; scroll-snap-type:x proximity; padding-bottom:6px;
    margin-right:calc(var(--gutter, 20px) * -1); padding-right:var(--gutter, 20px)}
  .rtile{flex:0 0 6.5rem; scroll-snap-align:start}
  .rtile-l{font-size:.78rem; padding:16px 7px 5px}
}
.rlib-course[hidden],.rcard[hidden]{display:none}
.rlib-more{color:var(--ink-3); font-size:var(--size-small)}
/* A recipe's own page: the page title is the recipe's, so the recipe's own
   heading is there for Copy and screen readers only, and its row holds the
   buttons. */
[data-page="recipe"] .recipe-title{position:absolute; width:1px; height:1px; margin:0;
  overflow:hidden; clip-path:inset(50%); white-space:nowrap}
/* A recipe's labels (Ingredients, Directions, Notes…) in the colour of the
   palette's section headings (h3, --deep), to pick them out (Bev, Nov 2,
   2026): Slate's light blue in dark mode, its deep blue in light. */
.recipe h5{color:var(--deep)}
[data-page="recipe"] .recipe-head{justify-content:flex-end; margin-bottom:6px}
[data-page="recipe"] .recipe-head .recipe-actions{margin-top:0}
.rfrom{margin-top:calc(var(--step)*1.6); color:var(--ink-2); font-size:var(--size-small)}
/* Recipes side by side (Carl and Bev, Nov 2, 2026; DECISIONS, "Recipes side
   by side"). Where the screen is wide and tall enough, a recipe is two
   columns, each scrolling by itself, with a faint line between: the photo,
   name, servings and ingredients, and beside them the directions, notes and
   nutrition. A phone, or an iPad held upright, keeps one column, in the same
   order as ever. build-recipes.py writes the columns (.rs); recipes.js sizes
   them to the screen (--rs-h) and moves the introduction across. The same
   query is SPLIT in recipes.js, and the cook board's is in cook-board.css. */
@media (min-width:900px) and (min-height:600px){
  .rs{display:grid; grid-template-columns:minmax(18rem, 2fr) 3fr;
      height:calc(100vh - 10rem); height:var(--rs-h, calc(100dvh - 10rem)); min-height:24rem}
  .rs-col{min-height:0; overflow-y:auto; overscroll-behavior:contain;
          padding-bottom:calc(var(--step)*2)}
  .rs-left{padding-right:clamp(1.2rem, 2.4vw, 2.2rem)}
  .rs-right{border-left:1px solid var(--rule); padding-left:clamp(1.2rem, 2.4vw, 2.2rem)}
  .rs-right > :first-child{margin-top:0}
  /* The photo beside the name, small, so the ingredients start high up. */
  .rs-head{margin-bottom:calc(var(--step)*.4)}
  .rs-head:has(> .pic, > [data-need]){display:grid; grid-template-columns:9rem minmax(0, 1fr);
           column-gap:1rem; align-items:start}
  .rs-head:has(> .pic, > [data-need]) > *{grid-column:2}
  .rs-head > .pic, .rs-head > [data-need]{grid-column:1; grid-row:1 / span 8; margin:0}
  .rs-head .pic img{width:9rem !important; height:9rem; aspect-ratio:auto; max-height:none;
                    object-fit:cover; border-radius:10px}
  /* The name across the column, Copy (and the jigger) under it. */
  .rs-head .recipe-head{flex-direction:column; align-items:flex-start; gap:6px; margin-bottom:6px}
  /* The recipe's own heading is the name on show here; the page's title
     keeps the course line and the buttons, and its heading is there for
     screen readers. */
  .rs .recipe-title{position:static; width:auto; height:auto; overflow:visible; clip-path:none;
                    white-space:normal; margin:0; font:400 clamp(1.45rem, 2.2vw, 2rem)/1.14 var(--serif);
                    color:var(--heading); letter-spacing:0}
  [data-page="recipe"] .wrap:has(.rs){max-width:min(96vw, 84rem)}
  [data-page="recipe"] .wrap:has(.rs) main{max-width:none}
  [data-page="recipe"] .wrap:has(.rs) .title{display:flex; flex-wrap:wrap; align-items:center;
    justify-content:space-between; gap:.4rem 1rem; padding-top:clamp(1rem, 2vw, 1.6rem);
    padding-right:44px; margin-bottom:clamp(.8rem, 1.6vw, 1.2rem)}
  [data-page="recipe"] .wrap:has(.rs) .title > .kicker,
  [data-page="recipe"] .wrap:has(.rs) .title > h1{position:absolute; width:1px; height:1px; margin:0;
    overflow:hidden; clip-path:inset(50%); white-space:nowrap}
  [data-page="recipe"] .wrap:has(.rs) .title .dates,
  [data-page="recipe"] .wrap:has(.rs) .title .recipe-top{margin:0}
  [data-page="recipe"] .wrap:has(.rs) .title + .rule{display:none}
}
@media print{ .rcard-save,.rlib-bar{display:none} }
/* The Journal's archive: a bar of years, then a compact list under each. */
.years{display:flex; flex-wrap:wrap; gap:8px; margin:0 0 calc(var(--step)*1.2)}
.years a{
  font:600 var(--size-small)/1 var(--body); color:var(--heading);
  text-decoration:none; border:1px solid var(--rule-strong);
  border-radius:999px; padding:8px 14px; font-variant-numeric:tabular-nums;
}
.years a:hover{background:var(--lift); border-color:var(--ink-3)}
.archive h4{margin:calc(var(--step)*.9) 0 .1em; font-size:calc(var(--size) * 1.105)}
.archive h4 + p{margin-bottom:0; color:var(--ink-3); font-size:var(--size-small)}
/* The year list, folded once it is long (build-journal.py, FOLD_AT): the
   year and its count are the fold's label, opening as every fold does.
   The year is the size of an entry's heading, not a section's (32px was
   half again the titles it heads), and each year sits with its own
   entries: 16px around a folded year, 24px after an open year's last
   entry, 10px down to its first (Carl chose B from mockups/yearfold-options,
   Oct 19). */
.yearfold{border-bottom:1px solid var(--rule)}
.yearfold > summary{cursor:pointer; padding:16px 0; display:flex; align-items:baseline; gap:.6em}
.yearfold > summary h3{margin:0; display:inline; font-size:var(--h4); line-height:1.2}
.yearfold > summary span{color:var(--ink-3); font-size:var(--size-small)}
.yearfold[open]{padding-bottom:24px}
.yearfold[open] > summary{padding-bottom:2px}
.yearfold > summary + h4{margin-top:10px}
.yearall{display:inline-flex; gap:4px; margin-left:auto}
.yearall[hidden]{display:none}
.yearall button{font:500 var(--size-small)/1 var(--body); color:var(--ink-2); background:none; border:0;
  padding:12px 8px; cursor:pointer; text-decoration:underline; text-underline-offset:3px}   /* 40px tall, for a thumb */
.yearall button:hover{color:var(--ink)}
/* Travel photographs are the point of the page; let them be big. */
[data-page="journal"]{--pic-h:80vh}
li{margin:0 0 .35em}
table{border-collapse:collapse; width:100%; margin:1.5em 0; font-size:calc(var(--size) * 0.76)}
th,td{text-align:left; padding:.42em .6em; border-bottom:1px solid var(--rule)}
th{font-weight:600; color:var(--ink-2)}
/* Links keep an underline (their colour alone sits too close in brightness
   to the text around them to be the only cue), but a light one: 1px, well
   clear of the letters, at half strength until hovered. */
a{color:var(--deep); text-decoration-thickness:1px; text-underline-offset:.22em;
  text-decoration-color:color-mix(in srgb,currentColor 50%,transparent)}
a:hover{text-decoration-color:currentColor}

/* An editorial note is not his voice, and must never look like it. */
.note{
  margin:1.7em 0; padding:.95em 1.1em; background:var(--tint);
  border-radius:8px; font-size:var(--size-small); line-height:1.6; color:var(--ink-2);
}
[data-voice="his"] .note::before{
  content:"Editor's note"; display:block;
  font:600 calc(var(--size) * .66)/1 var(--body); letter-spacing:.14em;
  text-transform:uppercase; color:var(--accent); margin-bottom:.5em;
}
.note em{font-style:normal}

/* Reference material folds away. The story should start near the top. */
.fold{
  margin:calc(var(--step)*1.1) 0; border:1px solid var(--rule);
  border-radius:12px; background:var(--raised); overflow:hidden;
}
.fold > summary{
  list-style:none; cursor:pointer; padding:15px 18px;
  display:flex; align-items:center; gap:12px;
  font:600 var(--size-small)/1.35 var(--body);
}
.fold > summary::-webkit-details-marker{display:none}
.fold > summary::marker{content:""}
.fold > summary > span:first-child{flex:1}
.fold .chev{color:var(--ink-3); font-size:1.3rem; transition:transform .18s}
.fold[open] .chev{transform:rotate(90deg)}
.fold .body{
  padding:4px 18px 18px; border-top:1px solid var(--rule);
  font-size:calc(var(--size) * 0.85); color:var(--ink-2);
}
/* Long runs of italic are tiring. The panel already marks this as editorial
   voice, so the text inside it sits upright. */
.fold .body em{font-style:normal; color:var(--ink)}
.fold .body h3{font-size:calc(var(--size) * 0.912); margin:calc(var(--step)*1.1) 0 .3em}
.fold .body h4{font-size:calc(var(--size) * 0.8)}
/* A story's Who's who (fold_cast): its heading is the summary's title, the
   names under it in grey, the list itself at the story's own size. */
main .fold.cast h3{font:600 var(--size)/1.3 var(--body); margin:0; color:var(--ink)}
.fold.cast .cast-names{display:block; font-weight:400; color:var(--ink-3); margin-top:3px}
.fold.cast .body{font-size:calc(var(--size) * .92)}
.fold.cast .body ul{margin:12px 0 0}

.readalso{
  margin:calc(var(--step)*1.6) 0; padding:16px 18px; border-radius:12px;
  background:var(--tint); font-size:calc(var(--size) * 0.85);
}
.readalso b{display:block; font-size:calc(var(--size) * 0.864); margin-bottom:6px}
.readalso a{font-weight:600}

/* Older and Newer at the foot of a journal entry (build-journal.py,
   older_newer; Carl, Oct 22–23, 2026): under a plain rule, Older's title at
   the left and Newer's at the right, each with its date and trip, in small
   type so the entry above stays the thing to read; under them the entry's
   trip and the way back. No bars or dots (Oct 23). */
.jn{margin:0 0 calc(var(--step)*.6); font-family:var(--body)}
/* As wide as the site's footer below it, the rule over it too: past the
   text into the frame's free band (--band), to its right edge. Held to the
   text it looked cut short beside the photos and the footer (Carl, Oct 22). */
main .jn, main hr:has(+ .jn){margin-right:calc(-1 * max(0px, var(--band)))}
.jn-row{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:28px}
.jn-row a{text-decoration:none; color:inherit}
.jn-st{min-width:0; overflow-wrap:break-word}
.jn-next{text-align:right}
.jn-k{display:block; font:600 calc(var(--size) * .5)/1 var(--body); letter-spacing:.12em; text-transform:uppercase; color:var(--ink-3)}
.jn-t{font:400 calc(var(--size)*.84)/1.3 var(--serif); color:var(--heading); margin:4px 0 2px; text-wrap:balance;
  display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden}
.jn-m{display:block; font-size:calc(var(--size)*.72); color:var(--ink-2)}
.jn-row a:hover .jn-t{text-decoration:underline; text-decoration-color:var(--accent); text-underline-offset:3px}
.jn-row a:focus-visible{outline:2px solid var(--accent); outline-offset:3px; border-radius:6px}
/* The entry's trip, its place in it, and the way back: as quiet as the rest. */
.jn-more{margin:calc(var(--step)*.9) 0 0; font-size:calc(var(--size)*.82); color:var(--ink-2)}
/* Older and Newer again at the top, under the header rule (build-journal.py,
   top_line; Carl, Oct 23): "← Older" and "Newer →" alone, in the third ink.
   Close under the rule and with room after, so it belongs to the header
   and the story starts clear of it. On a wide screen with a pointer,
   hovering one opens its title beside it; a phone, a tablet by touch and
   the footer's titles do without. */
hr.rule:has(+ .tn){margin-bottom:10px}
.tn{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:20px; margin:0 0 calc(var(--step)*1.4);
  font:400 calc(var(--size)*.74)/1.4 var(--body)}
.tn a{display:inline-flex; align-items:baseline; gap:.3em; max-width:100%; min-width:0; justify-self:start;
  color:var(--ink-3); text-decoration:none}
.tn .tn-next{justify-self:end}
/* The underline is the word's, never the arrow's. */
.tn a:is(:hover,:focus-visible) .tn-w{color:var(--ink-2); text-decoration:underline;
  text-decoration-color:var(--accent); text-underline-offset:3px}
.tn a:focus-visible{outline:2px solid var(--accent); outline-offset:3px; border-radius:4px}
.tn-in{display:inline-block; max-width:0; opacity:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;
  vertical-align:bottom; transition:max-width .3s cubic-bezier(.2,.7,.2,1), opacity .2s}
@media (hover:hover) and (min-width:64rem){
  .tn a:is(:hover,:focus-visible) .tn-in{max-width:min(28rem, 34vw); opacity:1}
}
/* The arrows, top and foot, slide 3px the way they point, in the home
   cards' quarter second and ease; still for Reduce Motion. */
.tn-ar,.jn-ar{display:inline-block; transition:transform .25s cubic-bezier(.2,.7,.2,1)}
:is(.tn-prev,.jn-prev):is(:hover,:focus-visible) :is(.tn-ar,.jn-ar){transform:translateX(-3px)}
:is(.tn-next,.jn-next):is(:hover,:focus-visible) :is(.tn-ar,.jn-ar){transform:translateX(3px)}
:root[data-motion="off"] :is(.tn-ar,.jn-ar){transform:none!important}

/* A lifted story needs a little air around it, and an editor's setup line
   must not be mistaken for his voice. */
/* scroll-margin, or the sticky masthead covers the heading you jumped to. */
.story,h2,h3,h4,[id]{scroll-margin-top:76px}
.story{margin:0 0 calc(var(--step)*2.4)}
html{scroll-behavior:smooth}
.story + .story{
  padding-top:calc(var(--step)*1.6); border-top:1px solid var(--rule);
}
.story h3{margin-top:0}
.setup{
  font:400 var(--size-small)/1.6 var(--body); color:var(--ink-3);
  border-left:2px solid var(--rule); padding-left:.9em;
  margin:0 0 calc(var(--step)*.9);
}

/* ---- home page doors -------------------------------------------------- */
.doors{display:grid; gap:14px; margin:calc(var(--step)*1.8) 0}
@media (min-width:44rem){ .doors{grid-template-columns:1fr 1fr; gap:16px} }
.door{
  display:block; position:relative; text-decoration:none; color:inherit;
  padding:22px 22px 24px; border:1px solid var(--rule); border-radius:14px;
  background:var(--raised);
  transition:border-color .2s, transform .2s cubic-bezier(.2,.7,.2,1);
}
.door:hover,.door:focus-visible{border-color:var(--accent); transform:translateY(-2px)}
.door .tag{
  font:600 calc(var(--size) * .66)/1 var(--body); letter-spacing:.14em;
  text-transform:uppercase; color:var(--accent);
}
.door h3{
  font:400 1.6rem/1.2 var(--serif); letter-spacing:var(--track);
  margin:9px 0 .4em; color:var(--heading);
}
.door p{font-size:calc(var(--size) * 0.8); color:var(--ink-2); margin:0 2.2rem 0 0}
.door .go{
  position:absolute; right:20px; bottom:20px; color:var(--ink-3);
  font-size:calc(var(--size) * 0.96); transition:transform .2s cubic-bezier(.2,.7,.2,1), color .2s;
}
.door:hover .go{color:var(--accent); transform:translateX(4px)}

/* A journal photo reached by its address from search (its file's name,
   build-journal.py photo_ids): clear of the sticky header, and ringed for
   a moment so the eye finds it (Carl, Oct 23, 2026). */
figure[id]{scroll-margin-top:96px}
@keyframes arrive{from{outline-color:var(--accent)} to{outline-color:transparent}}
figure:target img{outline:3px solid transparent; outline-offset:3px; animation:arrive 2.6s ease-in .4s backwards}
:root[data-motion="off"] figure:target img{animation:none}

/* ---- lightbox --------------------------------------------------------- */
.lb{
  position:fixed; inset:0; z-index:100; display:none;
  /* Opaque: at 94% the page's text showed through behind the caption and
     the arrows (Carl, Oct 22, 2026). The photo gets the whole screen. */
  background:rgb(12,20,24);
}
.lb[open],.lb.on{display:flex; flex-direction:column}
.lb img{
  flex:1; min-height:0; object-fit:contain; width:100%;
  padding:56px 12px 8px;
}
/* A photo grows to fit the screen, but to no more than twice its own size
   (the script sets its box's limit as each loads): the journal's old
   544px photos were postage stamps on a large screen, and twice is soft
   but fine where three times shows the JPEG blocks (Carl chose it on a
   mock-up, Oct 23, 2026). Until then a photo stopped at its own size (Oct
   20). A clipping still grows to fill, to be read. */
.lb img:not(.newspaper){margin:auto; align-self:center}
/* The caption always gets the same column, so the arrows stay put from
   photo to photo instead of hugging each caption (Carl, Oct 22, 2026). The
   bar keeps room for four lines, the caption centred in it and the arrows
   pinned to its middle, so a caption of one line or four sits centred
   between them and they never move (Carl, Oct 23: four lines hold 96% of
   the journal's captions with their post's title on a phone, 99.6% on a
   laptop). A longer caption grows the bar upward past the arrows. Until
   Oct 23 the arrows sat level with the caption's last line. */
.lb .lbbar{
  display:grid; grid-template-columns:44px minmax(0,34rem) 44px;
  grid-template-rows:minmax(calc(1.4em * 4), auto);
  align-items:center; gap:14px; justify-content:center;
  padding:10px 12px 18px; color:#e6efeb;
  font:400 .92rem/1.4 var(--body);
}
.lb .lbbar > button{font:inherit; align-self:end; margin-bottom:calc((1.4em * 4 - 44px) / 2)}
.lb .lbcap{text-align:center}
.lb .lbcap b{color:#e3a080; margin-right:.4em}
.lb .pic-tag{color:#cfd8d0; border-color:rgba(255,255,255,.35)}
.lb span.pic-tag:not(.pic-orig){border-color:rgba(255,255,255,.2)}
.lb .lbbar.solo .lbprev,.lb .lbbar.solo .lbnext{visibility:hidden}
.lb button{
  background:rgba(255,255,255,.09); border:1px solid rgba(255,255,255,.22);
  color:#e6efeb; border-radius:999px; width:44px; height:44px; flex:none;
  font-size:1.2rem; cursor:pointer; line-height:1;
}
.lb button:hover{background:rgba(255,255,255,.18)}
.lb:focus{outline:none}
/* The arrows wear the Close button's soft square: its wash, its corners
   scaled up, no edge. Drawn chevrons at the x's weight, not the ‹ ›
   characters, which sat small and low; a little dimmed until hover
   (Carl, Oct 22, 2026). */
.lb .lbprev,.lb .lbnext{display:grid; place-items:center; padding:0; border:0;
  border-radius:10px; background:var(--cx-scrim); transition:background-color .2s}
.lb .lbprev:is(:hover,:focus-visible),.lb .lbnext:is(:hover,:focus-visible){background:var(--cx-scrim-on)}
.lb .lbprev:focus-visible,.lb .lbnext:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
.lb .lbprev svg,.lb .lbnext svg{width:24px; height:24px; fill:none; stroke:currentColor;
  stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; opacity:.72; transition:opacity .2s}
.lb .lbprev:is(:hover,:focus-visible) svg,.lb .lbnext:is(:hover,:focus-visible) svg{opacity:1}
/* The caption's original switch is a chip, not one of the round buttons. */
.lb button.pic-tag{width:auto; height:auto; background:none; border-radius:4px;
                   font:500 .8em/1.2 var(--body)}
/* color: the page's hover ink is dark in light mode, on this dark scrim. */
.lb button.pic-tag:hover,.lb .pic-credit > summary:hover{border-color:currentColor; color:inherit}
.lb .pic-credit > summary,.lb .pic-credit > button{color:inherit}
/* A photo for sale on Fine Art America: a chip after its caption, in a new
   tab (photo's `prints:` in the journal; Carl, Oct 22, 2026). */
.lb a.lbprints{text-decoration:none; font:500 .8em/1.2 var(--body)}
.lb a.lbprints:is(:hover,:focus-visible){color:var(--cx-scrim-ink); border-color:currentColor}
.lb .lbclose{position:absolute; top:12px; right:12px}
/* The photo count, top left, opposite Close and level with it: the
   caption's size, one quiet ink, digits of one width so it doesn't shift
   as you step. Off the caption line, where it crowded the words (Carl,
   Oct 22, 2026). A screen reader hears "Photo 3 of 12". */
.lb .lbcount{position:absolute; top:12px; left:16px; height:36px; display:flex; align-items:center;
  font:400 .92rem/1 var(--body); font-variant-numeric:tabular-nums; color:var(--cx-scrim-dim)}
.lb .lbcount .vh{position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap}
/* Clear view (Carl, Oct 23, 2026): a button beside Close, or a tap on the
   photo, hides the caption, the arrows and the count and gives the photo
   the room. The button and Close stay, faded: one brings the rest back,
   the other still closes. Its icon: corners out, then corners in. */
.lb .lbbare{position:absolute; top:12px; right:56px}
.lb .lbbare .g{fill:none; stroke:currentColor; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round}
.lb .lbbare .in,.lb.bare .lbbare .out{display:none}
.lb.bare .lbbare .in{display:inline}
.lb.bare :is(.lbbar,.lbcount,.lbtip){display:none}
.lb.bare img{padding:0}
.lb.bare :is(.lbsave,.lbplay,.lbbare,.lbclose){opacity:.45; transition:opacity .2s}
.lb.bare :is(.lbsave,.lbplay,.lbbare,.lbclose):is(:hover,:focus-visible){opacity:1}
/* Save, left of Play (Carl, Oct 28, 2026): the bookmark fills once saved. */
.lb .lbsave{position:absolute; top:12px; right:144px}
.lb .lbsave[hidden]{display:none}
.lb .lbsave .g{fill:none; stroke:currentColor; stroke-width:1.7; stroke-linejoin:round}
.lb .lbsave[aria-pressed="true"] .g{fill:currentColor}
/* The slideshow (Carl, Oct 28, 2026): Play beside Clear view, Pause while
   it plays, faded with the others in a clear view. Each photo fades into
   the next: the one leaving is a copy laid over the same box, under the
   arriving photo (z-index -1 inside the viewer), and both fade at once. */
.lb .lbplay{position:absolute; top:12px; right:100px}
.lb .lbplay[hidden]{display:none}
.lb .lbplay .g{fill:none; stroke:currentColor; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round}
.lb .lbplay .pause,.lb.playing .lbplay .play{display:none}
.lb.playing .lbplay .pause{display:inline}
.lb img.lbghost{position:fixed; z-index:-1; margin:0; pointer-events:none}
/* The first time a visitor opens the viewer, a tip under the button says
   what it does, until they use it or close (localStorage amoth-viewer-tip). */
.lb .lbtip{position:absolute; top:58px; right:12px; padding:8px 12px; border-radius:8px;
  background:var(--cx-scrim); color:var(--cx-scrim-ink); white-space:nowrap;
  font:400 calc(var(--size) * .62)/1.2 var(--body)}
.lb .lbtip::before{content:""; position:absolute; top:-6px; right:56px; border:6px solid transparent;
  border-top:0; border-bottom-color:var(--cx-scrim)}
.lb .lbtip .by-touch{display:none}
@media (pointer:coarse){ .lb .lbtip .by-mouse{display:none} .lb .lbtip .by-touch{display:inline} }
/* Search's viewer: under each caption, its entry's title, which opens the
   entry at that photo. */
.lb .lbpost{display:inline-block; margin-top:4px; color:#e3a080; text-decoration:none; font-size:.9em}
.lb .lbpost:is(:hover,:focus-visible){text-decoration:underline}
@media (max-width:34rem){
  .lb .lbbar{grid-template-columns:44px minmax(0,1fr) 44px; gap:8px}
  .lb .lbcap,.lb .lbcount{font-size:calc(var(--size) * 0.672)}
}

.pagemark{
  margin:calc(var(--step)*1.6) 0 calc(var(--step)*1.1); text-align:center;
  border-top:1px solid var(--rule); line-height:0;
}
.pagemark span{
  display:inline-block; background:var(--paper); padding:0 12px;
  font:600 calc(var(--size) * .66)/1 var(--body); letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-3);
}

/* ---- facsimile leaves ------------------------------------------------ */
.lede{font-size:calc(var(--size) * 0.872)}
.leaves{
  display:grid; gap:22px; margin:calc(var(--step)*2) 0;
  grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
}
@media (min-width:40rem){
  .leaves{grid-template-columns:repeat(auto-fill,minmax(180px,1fr))}
}
.leaf{margin:0}
.leaf a{
  display:block; border:1px solid var(--rule); border-radius:4px;
  overflow:hidden; background:var(--raised);
  transition:border-color .18s, transform .18s cubic-bezier(.2,.7,.2,1);
}
.leaf a:hover,.leaf a:focus-visible{
  border-color:var(--accent); transform:translateY(-3px);
}
.leaf img{display:block; width:100%; height:auto}
.leaf figcaption{
  font:400 var(--size-small)/1.45 var(--body); color:var(--ink-3);
  margin-top:7px;
}
.leaf figcaption b{color:var(--accent); font-weight:600; margin-right:.35em}
/* A run of pictures: one scrolling row, every photo uncropped at one
   height, swiped on a phone or stepped with the arrows the script adds
   where there's a mouse; any of them opens the viewer, which has the
   captions (Carl, Oct 8, 2026: "B", on person pages and in stories). */
.gallery{position:relative; margin:calc(var(--step)*.4) 0 var(--step)}
.gallery-strip{display:flex; gap:12px; overflow-x:auto; overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory; scroll-padding-inline:4px;
  padding:4px 4px 10px; margin:0 -4px; scrollbar-width:thin}
/* position: the hidden caption below is placed against its own leaf, inside
   the scrolling row, so the row clips it. Placed against .gallery, the last
   leaves' captions sat past the row's end and widened the whole page
   (Carl's page was 2416px wide on a 1024px screen until Oct 17, 2026). */
.gallery .leaf{flex:none; scroll-snap-align:start; position:relative}
.gallery .leaf img{height:clamp(180px,32vw,260px); width:auto; max-width:none;
  aspect-ratio:var(--r); object-fit:cover}
.gallery .leaf figcaption{position:absolute; width:1px; height:1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap}
.gallery-step{position:absolute; top:calc(clamp(180px,32vw,260px) / 2 - 16px); z-index:2;
  width:40px; height:40px; border-radius:999px; border:1px solid var(--rule-strong);
  background:var(--raised); color:var(--ink-2); cursor:pointer;
  font:400 1.4rem/1 var(--body); box-shadow:0 2px 8px color-mix(in srgb,var(--ink) 12%,transparent);
  transition:border-color .18s, color .18s, opacity .18s}
.gallery-step:hover,.gallery-step:focus-visible{border-color:var(--accent); color:var(--ink)}
.gallery-step.prev{left:-10px} .gallery-step.next{right:-10px}
.gallery-step[disabled]{opacity:0; pointer-events:none}
@media (hover:none){ .gallery-step{display:none} }
@media print{ .gallery-step{display:none} .gallery-strip{flex-wrap:wrap; overflow:visible} }
.gallery-open,.route-open,.mvbar button,.fc-fs,.fc-pr{
  margin-top:14px; display:inline-flex; align-items:center; gap:.5em;
  padding:.6em 1.15em; border:1px solid var(--rule-strong); border-radius:999px;
  background:var(--raised); color:var(--ink-2); cursor:pointer;
  font:500 var(--size-small)/1 var(--body);
  transition:border-color .18s, color .18s;
}
.gallery-open:is(:hover,:focus-visible),.route-open:is(:hover,:focus-visible),
.mvbar button:is(:hover,:focus-visible),.fc-fs:is(:hover,:focus-visible),
.fc-pr:is(:hover,:focus-visible){border-color:var(--accent); color:var(--ink)}
.gallery-open span,.route-open span,.fc-fs span,.fc-pr span{color:var(--accent)}
@media print{ .fc-fs,.fc-pr{display:none} }
/* ---- the close button: one design everywhere (Sept 30, 2026) ---------
   A drawn x on a soft square with 8px corners, the chart tabs' and frame's
   (a circle echoed the pill buttons it sat beside), a see-through wash of the text ink so it sits
   right on any ground (about 1.4-1.6x off a panel in every palette, the x
   4.7:1 or better). Hover deepens the disc and turns the x a quarter.
   On a dark scrim (the photo viewers) a light wash; over a photograph a
   frosted dark one. Classes: cx, cx-scrim, cx-photo. */
:root{
  --cx-bg:color-mix(in srgb,var(--ink) 20%,transparent);
  --cx-bg-on:color-mix(in srgb,var(--ink) 30%,transparent);
  --cx-scrim:rgba(255,255,255,.12); --cx-scrim-on:rgba(255,255,255,.22); --cx-scrim-ink:#e6efeb;
  --cx-scrim-dim:rgba(230,239,235,.6);   /* the viewer's photo count */
  --cx-photo:rgba(20,20,20,.36); --cx-photo-on:rgba(20,20,20,.55);
  --cx-photo-edge:rgba(255,255,255,.18); --cx-photo-ink:#ffffff;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --cx-bg:color-mix(in srgb,var(--ink) 15%,transparent);
    --cx-bg-on:color-mix(in srgb,var(--ink) 24%,transparent);
  }
}
:root[data-theme="dark"]{
  --cx-bg:color-mix(in srgb,var(--ink) 15%,transparent);
  --cx-bg-on:color-mix(in srgb,var(--ink) 24%,transparent);
}
button.cx{
  display:inline-flex; align-items:center; justify-content:center; flex:none;
  width:36px; height:36px; min-width:0; min-height:0; margin:0; padding:0;
  border:0; border-radius:8px; background:none; color:var(--ink-2);
  font:inherit; line-height:0; cursor:pointer;
}
button.cx svg{width:36px; height:36px; display:block; overflow:visible}
button.cx .o{fill:var(--cx-bg); transition:fill .2s}
button.cx .x{fill:none; stroke:currentColor; stroke-width:1.7; stroke-linecap:round;
  transform-box:view-box; transform-origin:18px 18px;
  transition:transform .28s cubic-bezier(.3,.7,.2,1)}
button.cx:is(:hover,:focus-visible){color:var(--ink); background:none}
button.cx:is(:hover,:focus-visible) .o{fill:var(--cx-bg-on)}
button.cx:is(:hover,:focus-visible) .x{transform:rotate(90deg)}
button.cx:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
button.cx.cx-scrim{color:var(--cx-scrim-ink)}
button.cx.cx-scrim .o{fill:var(--cx-scrim)}
button.cx.cx-scrim:is(:hover,:focus-visible){color:var(--cx-scrim-ink)}
button.cx.cx-scrim:is(:hover,:focus-visible) .o{fill:var(--cx-scrim-on)}
button.cx.cx-photo{color:var(--cx-photo-ink); -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px)}
button.cx.cx-photo .o{fill:var(--cx-photo); stroke:var(--cx-photo-edge); stroke-width:1}
button.cx.cx-photo:is(:hover,:focus-visible){color:var(--cx-photo-ink)}
button.cx.cx-photo:is(:hover,:focus-visible) .o{fill:var(--cx-photo-on)}


.marginalia{
  margin:calc(var(--step)*2) 0; padding:20px; border-radius:12px;
  background:var(--tint); font-size:calc(var(--size) * 0.8);
}
.marginalia h4{margin-top:0}
.marginalia ul{margin-bottom:0}
.marginalia li{margin-bottom:.5em}

.foot{
  margin:88px 0 40px; padding-top:20px; border-top:1px solid var(--rule);
  font-size:calc(var(--size) * 0.688); color:var(--ink-3);
}
/* A site's own footer under the page's credit line: planetposts.me's
   copyright, who designed it, and the RSS feed (build-journal.py, Oct 21). */
/* One line, the rule across the page. Room below it, so the back-to-top
   button (bottom right, 46px) never sits on the words (Carl, Oct 21). */
.sitefoot{margin:88px 0 96px; padding-top:18px; border-top:1px solid var(--rule); display:flex; flex-wrap:wrap;
  justify-content:space-between; gap:4px 20px; font-size:calc(var(--size) * 0.688); color:var(--ink-3)}
.sitefoot a{color:var(--ink-2)}
/* amoth.us's footer (site_footer): the page's credit over the copyright.
   Low on the page, level with the round buttons at the window's bottom right
   (Contents and search, Back to top: 46px each, 16px from the edge, 20px
   from the bottom), and stopping short of them (Carl, Oct 22): the room it
   leaves is what the buttons take from the frame's margin, none on a wide
   window, where they sit outside the footer. */
.amothfoot{margin-bottom:20px; align-items:flex-end;
  padding-right:max(0px, calc(78px - (100vw - min(100vw, var(--site))) / 2 - var(--gutter)))}
.amothfoot .foot-left{display:flex; flex-direction:column; gap:4px}
.amothfoot .foot-credit{color:var(--ink-2)}
/* ---- family views -------------------------------------------------
   One public page, two more audiences. The page's own source holds only
   the family LINKS; what they point at sits behind the family sign-in. The
   script asks a file inside each gate whether this browser is signed in and
   sets data-tier on the root, and these rules do the rest. No JavaScript,
   no tier: a reader without it sees the public page, which is correct.
------------------------------------------------------------------- */
:root:not([data-tier]) [data-need],
:root[data-tier="family"] [data-need="inner"]{display:none!important}
/* Two half-row cards where only immediate family see the second (Knute
   Stenerson and the Wild Fiddler): for everyone else the first takes the
   whole row rather than sit beside a gap. */
:root:not([data-tier="inner"]) .cards .span3:has(+ .span3[data-need="inner"]){grid-column:1 / -1}
:root[data-tier] .signin{display:none!important}
/* The person icon is on every page (Oct 27, 2026). Signed out it is a link
   to Family sign-in; signed in, the chip with its green dot and menu. */
:root:not([data-tier]) #tier-chip,:root:not([data-tier]) .tier-menu,
:root[data-tier] .tier-out{display:none}
.masthead a.tier-out{display:inline-flex; align-items:center; color:var(--heading); border-color:var(--rule-strong)}
:root:not([data-tier="inner"]) .tier-inner,
:root[data-tier="inner"] .tier-family{display:none}

/* Unused since Sept 26: family material appears without a label. */
.for-tier{
  font:600 calc(var(--size) * .62)/1 var(--body); letter-spacing:.14em;
  text-transform:uppercase; color:var(--accent); margin:1.6em 0 -.9em;
}
.card .for-tier{margin:0 0 10px}
.card--stone .for-tier{color:var(--stone-tag)}

/* Family sign-in is a convenience, not a setting: last, under a rule. */
.ap-row.signin{margin:16px 0 0; padding-top:14px; border-top:1px solid var(--rule)}
.ap-signin{
  display:block; text-align:center; color:var(--ink-2); text-decoration:none;
  border:1px solid var(--rule); border-radius:999px; padding:9px 12px;
  font:500 .92em/1 var(--body);
}
.ap-signin:hover{border-color:var(--ink-3); color:var(--ink)}

.tier{display:flex}
.masthead #tier-chip{display:inline-flex; align-items:center;
                     color:var(--heading); border-color:var(--rule-strong)}
.masthead #tier-chip[aria-expanded="true"]{background:var(--tint);
                                           border-color:var(--ink-3)}
.tier-icon{position:relative; display:block}
.tier-icon svg{display:block}
/* The dot sits on the figure's shoulder, ringed in the masthead's color so
   it reads as a badge and not part of the drawing. */
.tier-dot{position:absolute; right:-3px; top:-2px; width:8px; height:8px;
           /* green: signed in (Carl, Oct 27, 2026; was the accent) */
          border-radius:50%; background:var(--ok);
          box-shadow:0 0 0 2px var(--raised)}
#tier-chip[aria-expanded="true"] .tier-dot{box-shadow:0 0 0 2px var(--tint)}
/* What's new's bell, drawn like the person icon. Its dot is red (--new),
   not the sign-in's green: something new since you last looked. It was the
   accent, which is blue in Taupe and a pale salmon in dark mode. */
.masthead a.news{display:inline-flex; align-items:center; color:var(--heading); border-color:var(--rule-strong)}
.news-dot{display:none; position:absolute; right:-3px; top:-2px; width:8px; height:8px;
          border-radius:50%; background:var(--new); box-shadow:0 0 0 2px var(--raised)}
.masthead a.news.on .news-dot{display:block}
.tier-name{position:absolute; width:1px; height:1px; overflow:hidden;
           clip:rect(0 0 0 0); white-space:nowrap}
.tier-who{margin:0; padding:8px 12px 10px; color:var(--ink-3)}
/* The menu hangs under the chip, right edges aligned. On a phone the chip
   is too far from the right for that, so the menu takes the page's edge. */
.tier{position:relative}
@media (max-width:44rem){
  .tier{position:static}
  .tier-menu{right:var(--gutter)}
}
.tier-menu{
  position:absolute; right:0;
  top:calc(100% + 8px); z-index:30; width:min(17rem,calc(100vw - 32px));
  background:var(--raised); border:1px solid var(--rule); border-radius:14px;
  padding:8px; box-shadow:0 14px 40px rgba(0,0,0,.14);
  font:400 var(--size-small)/1.4 var(--body);
}
.tier-menu[hidden]{display:none}
.tier-menu a{display:block; padding:9px 12px; border-radius:9px;
             color:var(--ink); text-decoration:none}
.tier-menu a:hover{background:var(--lift)}
.tier-menu a[hidden]{display:none}
.tier-menu .signout{color:var(--ink); border-top:1px solid var(--rule);
                    border-radius:0 0 9px 9px; margin-top:4px}
.tier-menu{animation:apin .16s cubic-bezier(.2,.7,.2,1) both}

/* ---- What's new (/whats-new) ----------------------------------------
   The list build-whats-new.py writes: a choice of time, then each day's
   additions under a small-capital date, kind on the left. The choice is
   Appearance's segmented control; it shows only with script, which is what
   makes it work.
------------------------------------------------------------------- */
.wn-when{display:flex; flex-wrap:wrap; gap:12px 18px; align-items:center; margin:0 0 18px}
.wn-when[hidden],.wn-dates[hidden],.wn-seg button[hidden]{display:none}
.wn-seg{display:inline-flex; flex-wrap:wrap; gap:2px; padding:3px; background:var(--seg-track); border-radius:22px}
.wn-seg button{font:500 var(--size-small)/1 var(--body); color:var(--ink-2); background:none; border:0;
  padding:10px 15px; border-radius:999px; cursor:pointer; white-space:nowrap}
.wn-seg button:hover{color:var(--ink)}
.wn-seg button[aria-checked="true"]{background:var(--seg-on); color:var(--heading); font-weight:600;
  box-shadow:0 1px 2px color-mix(in srgb,var(--ink) 14%,transparent)}
.wn-seg button:focus-visible{outline:2px solid var(--deep); outline-offset:1px}
.wn-dates{display:flex; flex-wrap:wrap; gap:10px 16px; font-size:var(--size-small); color:var(--ink-3)}
.wn-dates input{font:400 var(--size-small)/1.3 var(--body); color:var(--ink); background:var(--paper);
  border:1px solid var(--rule-strong); border-radius:10px; padding:7px 10px; margin-left:6px}
.wn-sum{color:var(--ink-2); margin:0 0 6px}
.wn-sum:empty{display:none}
.wn .wn-day{font:600 calc(5.76px + var(--size) * .288)/1.2 var(--body); letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-3); margin:30px 0 4px; padding:0 0 8px; border-bottom:1px solid var(--rule)}
.wn-items{list-style:none; margin:0; padding:0}
.wn-items li{display:grid; grid-template-columns:6.2rem minmax(0,1fr); gap:4px 16px; padding:14px 0;
  border-bottom:1px solid var(--rule); margin:0}
.wn-kind{font:600 calc(var(--size) * .58)/1 var(--body); letter-spacing:.12em; text-transform:uppercase;
  color:var(--deep); padding-top:.45em}
.wn-kind.rev{color:var(--accent)}
.wn-t{font:400 calc(var(--size) * 1.12)/1.3 var(--serif); color:var(--heading); text-decoration:none}
a.wn-t:hover{text-decoration:underline; text-underline-offset:3px}
.wn-d{display:block; color:var(--ink-2); font-size:var(--size-small); margin-top:3px}
.wn-d a{color:var(--deep)}
.wn-foot{margin-top:30px; font-size:var(--size-small); color:var(--ink-3)}
.wn-none{color:var(--ink-3); margin-top:20px}
@media (max-width:36rem){
  .wn-items li{grid-template-columns:1fr}
  .wn-kind{padding:0}
}

/* ---- find: contents and search, and back to top ----------------------
   The panel lists this page's sections and entries and searches the whole
   public site. It opens from the masthead, or from the round button that
   appears once you scroll, beside the one that takes you back to the top.
   Without JavaScript none of it shows; the page is the same page.
------------------------------------------------------------------- */
.masthead :is(#find-open,a.help){display:inline-flex; align-items:center}
.masthead :is(#find-open,a.help) svg{display:block}
/* The tools, icons only: 34px circles 6px apart, so they read as one set,
   apart from the menu's words, all in one outline; the dots carry the news
   (Carl chose it from five side by side, Oct 28, 2026). Each icon's name is
   its tooltip and what a screen reader hears. Display stays with each
   control's own rule, so the hidden ones (the person icon's two states)
   stay hidden. */
.mtools{display:flex; align-items:center; gap:6px}
.masthead .mtools :is(button,a.mbtn){justify-content:center; width:34px; height:34px; padding:0;
  color:var(--heading); border-color:var(--rule-strong)}
.masthead .mtools :is(button,a.mbtn):hover{color:var(--ink); border-color:var(--ink-3)}
/* Each tool's name in a small label under it (data-tip), on hover where
   there's a mouse or trackpad and on keyboard focus; a tap alone never
   shows one (Carl, Oct 28, 2026). It waits a moment, so a pointer passing
   across the group doesn't flash five, and it replaces the browser's own
   tooltip, which came a second late and beside the pointer. The person
   icon's is right-aligned, to stay on the screen. None while that tool's
   menu or panel is open. */
.masthead .mtools [data-tip]{position:relative}
.masthead .mtools [data-tip]::after{
  content:attr(data-tip); position:absolute; top:calc(100% + 6px); left:50%; z-index:31;
  transform:translate(-50%,-3px); opacity:0; pointer-events:none; white-space:nowrap;
  padding:4px 8px; border-radius:6px; background:var(--raised); border:1px solid var(--rule);
  color:var(--ink-2); font:500 calc(12px + (var(--size) - 20px) * .3)/1.2 var(--body);
  box-shadow:0 4px 12px rgba(0,0,0,.08); transition:opacity .12s ease, transform .12s ease}
.masthead .mtools .tier [data-tip]::after{left:auto; right:0; transform:translateY(-3px)}
@media (any-hover:hover){
  .masthead .mtools [data-tip]:hover::after{opacity:1; transform:translate(-50%,0); transition-delay:.35s}
  .masthead .mtools .tier [data-tip]:hover::after{transform:none}
}
.masthead .mtools [data-tip]:focus-visible::after{opacity:1; transform:translate(-50%,0)}
.masthead .mtools .tier [data-tip]:focus-visible::after{transform:none}
.masthead .mtools [aria-expanded="true"]::after{display:none}
@media (max-width:44rem){
  .masthead{gap:10px}
  .masthead button,.masthead a.mbtn{padding:6px 9px}
}
.tools{
  position:fixed; right:max(16px, env(safe-area-inset-right)); bottom:20px;
  z-index:25; display:flex; flex-direction:column; gap:10px;
  opacity:0; transform:translateY(8px); pointer-events:none;
  transition:opacity .2s, transform .2s;
}
.tools.on{opacity:1; transform:none; pointer-events:auto}
.tools button{
  width:46px; height:46px; border-radius:50%; cursor:pointer;
  display:grid; place-items:center; color:var(--heading);
  background:var(--raised); border:1px solid var(--rule-strong);
  box-shadow:0 6px 18px rgba(0,0,0,.14);
  /* Frosted (Carl, Oct 23): the card colour at 78%, what's behind blurred a
     little, so a photo or a line of text under it isn't blotted out. At
     worst, a white or black patch behind, the icon keeps 4.9:1; 60% fell
     under 3:1. A browser without color-mix keeps the solid card colour. */
  background:color-mix(in srgb, var(--raised) 78%, transparent);
  -webkit-backdrop-filter:blur(8px) saturate(1.2); backdrop-filter:blur(8px) saturate(1.2);
}
.tools button:hover{color:var(--ink); border-color:var(--ink-3)}
.find{
  position:fixed; z-index:40; top:64px; bottom:84px;
  right:max(16px, calc(50% - var(--site)/2 + var(--gutter)));
  width:min(26rem, calc(100vw - 32px));
  display:flex; flex-direction:column;
  background:var(--raised); border:1px solid var(--rule); border-radius:14px;
  box-shadow:0 18px 50px rgba(0,0,0,.18); overflow:hidden;
  font:400 var(--size-small)/1.45 var(--body); color:var(--ink);
}
.find[hidden]{display:none}
.find-head{display:flex; align-items:center; gap:8px; padding:12px; border-bottom:1px solid var(--rule)}
/* The box: chips (the Journal's by:, year:, place:, trip:, has:) and the
   words typed after them, wrapping onto a second line when they need it. */
.find-field{
  flex:1; min-width:0; display:flex; flex-wrap:wrap; align-items:center; gap:5px;
  background:var(--paper); border:1px solid var(--rule-strong);
  border-radius:20px; padding:4px 6px 4px 12px;
}
.find-field:focus-within{outline:2px solid var(--accent); outline-offset:1px}
.find-chips{display:contents}
.find input{
  flex:1; min-width:8rem; font:inherit; color:var(--ink); background:none;
  border:0; outline:0; padding:5px 2px;
}
.find-chip{
  display:inline-flex; align-items:center; gap:2px; max-width:100%;
  font:500 calc(6.40px + var(--size) * 0.320)/1.2 var(--body); color:var(--ink); white-space:nowrap;
  background:var(--lift); border:1px solid var(--accent); border-radius:999px;
  padding:3px 3px 3px 10px;
}
.find-chip button{
  font:inherit; font-size:calc(8px + var(--size) * 0.400); line-height:1; color:var(--ink-3); cursor:pointer;
  background:none; border:0; border-radius:999px; padding:1px 6px 3px;
}
.find-chip button:hover{color:var(--ink); background:var(--rule)}

.find-body{overflow:auto; padding:6px 8px 12px}
.find-label{
  font:600 calc(5.76px + var(--size) * 0.288)/1 var(--body); letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-3); margin:14px 8px 6px;
}
.find a{display:block; padding:7px 8px; border-radius:8px; color:var(--ink);
        text-decoration:none}
.find a:hover,.find a:focus-visible{background:var(--lift)}
.find .lvl4{padding-left:22px; color:var(--ink-2)}
.find .hit b{display:block; font-weight:600; color:var(--heading)}
.find .hit span{display:block; color:var(--ink-3); font-size:.92em}
.find .hit .for{display:block; font:600 calc(5.44px + var(--size) * 0.272)/1.4 var(--body); font-style:normal;
                letter-spacing:.12em; text-transform:uppercase; color:var(--accent)}
.find mark{background:var(--warn-tint); color:inherit; border-radius:2px}
.find .none{color:var(--ink-3); margin:10px 8px}
/* Words, not a button: it leaves the panel for the Journal's own search */
.find a.find-deeper{display:inline-block; margin:0 8px 10px; padding:6px 0; border-radius:0;
  font:500 calc(6.88px + var(--size) * 0.344)/1.3 var(--body); color:var(--ink); background:none; text-decoration:underline;
  text-decoration-color:var(--accent); text-decoration-thickness:1.5px; text-underline-offset:3px}
.find a.find-deeper:hover{background:none; text-decoration-thickness:2.5px}
/* A journal entry among the results: its first photo, its title, when,
   which trip, where and who, then the words that matched. */
.find .hit.entry{display:grid; grid-template-columns:56px minmax(0,1fr); gap:10px; align-items:start}
.find .hit.entry.bare{display:block}
.find .hit.entry > img{width:56px; height:56px; object-fit:cover; border-radius:6px; background:var(--lift)}
.find .hit small{display:block; font-size:.86em; color:var(--ink-2); margin:1px 0 2px}
.find-filters{display:flex; flex-wrap:wrap; gap:6px; padding:2px 8px 10px}
.find-filters button{display:inline-flex; align-items:center; gap:5px; min-height:34px; padding:0 10px;
  font:500 calc(6.56px + var(--size) * 0.328)/1 var(--body); border-radius:8px; border:1px solid var(--rule-strong);
  background:none; color:var(--ink-2); cursor:pointer}
/* Filters, not buttons: square corners, and a check on the one chosen (Carl, Oct 21) */
.find-filters button[aria-pressed="true"]{border-color:var(--accent); color:var(--ink);
  background:var(--tint); padding-left:8px}
.find-filters .ck{display:none; width:14px; height:14px; flex:none; fill:none; stroke:currentColor;
  stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round}
.find-filters [aria-pressed="true"] .ck{display:block}
/* A person the search names: their picture, name and years, above the rest */
.find-people{margin:0 0 6px}
.find a.hit.person{display:grid; grid-template-columns:44px minmax(0,1fr); gap:12px; align-items:center;
  margin:0 0 6px; padding:8px; border:1px solid var(--rule); border-radius:10px}
.find a.hit.person img,.find .person .nopic{width:44px; height:44px; border-radius:50%; object-fit:cover;
  object-position:50% 20%; background:var(--lift); display:block}
.find .person small{display:block; margin:1px 0 0; color:var(--ink-2)}
.find .people-more{display:block; margin:0 0 8px; padding:6px 8px; border:0; background:none; cursor:pointer;
  font:500 calc(6.56px + var(--size) * 0.328)/1.3 var(--body); color:var(--ink-2); text-decoration:underline; text-underline-offset:3px}
.find .people-more:hover{color:var(--ink)}
.find-photos{display:grid; grid-template-columns:repeat(auto-fill,minmax(104px,1fr));
  gap:8px; padding:2px 8px 10px}
.find a.ph{padding:0; border-radius:8px}
.find a.ph img{display:block; width:100%; aspect-ratio:1; object-fit:cover; border-radius:6px}
.find a.ph span{display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  overflow:hidden; font-size:calc(6.24px + var(--size) * 0.312); line-height:1.3; color:var(--ink-3); margin:4px 2px 2px}
.find-tips{padding:6px 16px 0; font-size:calc(6.40px + var(--size) * 0.320); color:var(--ink-3)}
.find-tips summary{cursor:pointer; width:max-content}
.find-tips ul{margin:6px 0 4px; padding-left:1.1em; line-height:1.55}
.find-tips b{color:var(--ink-2); font-weight:600}
.find{animation:apin .16s cubic-bezier(.2,.7,.2,1) both}

@media print{
  .masthead,.gated,.tools,.find{display:none}
  body{background:#fff; color:#000}
}

/* Motion off: the Appearance panel's switch, which starts from the device's
   Reduce Motion (the head script sets data-motion="off" before paint). One
   rule for the whole site, so nothing added later can forget it. Durations
   go to almost nothing rather than "none", so an animation that starts a
   thing hidden (the old Kjemhus page faded its generations in) still ends
   with it shown. The hover lifts and zooms are not animations but moves,
   so they go too; colour changes on hover stay, instantly. */
:root[data-motion="off"],:root[data-motion="off"] *,
:root[data-motion="off"] *::before,:root[data-motion="off"] *::after{
  animation-duration:.01ms!important; animation-delay:0s!important;
  animation-iteration-count:1!important;
  transition-duration:.01ms!important; transition-delay:0s!important;
  scroll-behavior:auto!important}
:root[data-motion="off"] :is(.card,.tree-feature,.door,.leaf a,.person-card,
  main p.solo > a[href$=".pdf"]):is(:hover,:focus-visible),
:root[data-motion="off"] :is(.card,.tree-feature,.door):is(:hover,:focus-visible)
  :is(.card-arrow,.card-pic img,.tf-go span,.go),
:root[data-motion="off"] button.cx:is(:hover,:focus-visible) .x{transform:none}


/* ---- wide pages (mcgregor; kjemhus was one until Oct 10, 2026) ----- */
.wide main{max-width:var(--site); margin:0 auto; padding:0 var(--gutter)}
/* The lineage banner: a picture inside the page width under the title,
   rather than a full-bleed hero with its own type. */
.lineage-banner{margin:0 0 calc(var(--step)*1.5)}
.lineage-banner img{display:block; width:100%; height:clamp(14rem,32vw,24rem);
                    object-fit:cover; border-radius:16px}
.lineage-banner figcaption{
  font:400 calc(var(--size) * .76)/1.45 var(--body); color:var(--ink-3);
  margin-top:10px; max-width:var(--measure);
}
/* The lineage pages follow the title with their own section spacing. */
.wide .wrap + main.mcgregor-saga{padding-top:8px}
/* The McGregor narrative ran 107-114 characters a line across the full site
   width (98 before, at 68rem) — well past the 75 a line of prose can take.
   Cap the prose at the same measure as every other page; the gallery, the
   timeline and the two-column blocks keep the width, because they are laid
   out for it. */
.wide .mcgregor-saga > :is(p, h2, h3, h4, ul, ol, blockquote,
                            .section-intro, .pull, .mcgregor-byline){
  max-width:var(--measure);
}

.wide .mcgregor-saga{padding:40px 0 56px}
/* That rule also matches <main>, and at higher specificity than .wide main,
   so it zeroed main's side padding: both lineage pages started their
   content 32px left of the wordmark. Put the gutter back on main only — the
   nested .mcgregor-saga divs inside it must not add a second one. */
.wide main.mcgregor-saga{
  padding-left:var(--gutter); padding-right:var(--gutter);
}
/* A lineage page with its contents beside the story (McGregor), laid out
   like As I Remember It: the frame carries the gutter, the story is one
   reading column, and the width that was empty beside it holds the list. */
.wide .lineage-railed{max-width:var(--site); margin:0 auto; padding:0 var(--gutter)}
.wide .lineage-railed > main.mcgregor-saga{
  max-width:var(--measure); margin:0; padding:0 0 56px;
}
.wide .lineage-railed > main > .mcgregor-saga{padding-top:0}
.wide .mcgregor-saga img{max-width:100%; height:auto}
/* ...except a photo row's pictures, which keep the row's height (a card's
   photographs on the Kjemhus page, Oct 9, 2026) */
.wide .gallery .leaf img{height:clamp(180px,32vw,260px); max-width:none}
.wide a{color:inherit}
.wide :focus-visible{outline:2px solid var(--accent); outline-offset:3px}
