/* freedomshope.org --- the whole design, one stylesheet.
   Typefaces come from assets/fonts.css (self-hosted, see tools/fetch_fonts.py).

   Decisions, so nobody has to guess later:
   - The 2014 logo, the #256ea5 accent and the 2014 background texture stay.
     Everything else is rebuilt. The texture (fhmbg1.jpg, a vignetted paper
     wash: teal at the top, cream through the middle, dusty rose at the foot)
     is what made the old site feel warm, and it is what gives the frosted
     panels something to sit against -- glass over flat white is just white.
   - Prose sits in a single column at a reading measure. The archive sidebar
     appears only in News, not on all 462 pages.
   - Galleries break out wider than the text. 276 of 462 pages are a report
     followed by a photo grid; that shape gets the attention.
   - Mobile is the default; the desktop layout is the enhancement. */

/* ---------------------------------------------------------------- tokens */

:root {
  --accent:        #256ea5;   /* the 2015 brand blue, kept --- 5.5:1 on white */
  --accent-deep:   #1a527b;   /* hover, and text on tinted panels --- 8.3:1 */
  --accent-wash:   #eef4f9;

  /* Measured, not estimated. The second number is against --paper-soft, which
     is the footer and the table headers; every pair clears WCAG AA for body
     text (4.5:1). --ink-faint was #6b7885 and came to 4.24 on --paper-soft,
     which is where the footer's copyright line sits. */
  --ink:           #16202a;   /* body text      16.5:1 / 15.5:1 */
  --ink-soft:      #4d5a67;   /* meta, captions  7.1:1 /  6.6:1 */
  --ink-faint:     #63707c;   /* least loud      5.1:1 /  4.8:1 */

  --paper:         #ffffff;
  --paper-soft:    #f6f8fa;
  --rule:          #e2e8ee;
  --rule-strong:   #cbd5de;

  /* Glass. The alphas are solved, not chosen. The texture's darkest corner is
     rgb(79 51 82) --- a deep plum, far darker than the cream middle suggests
     --- and the panels have to stay AA over *that*, because on a phone the
     panel is full width and the corners are under it. Measured:
        scrim 0.18 + glass 0.93  -> rgb(244 243 245), worst pair 4.6:1
        scrim 0.18 + thin  0.86  -> rgb(235 232 235), --ink 13.6:1
     Thinner looks better and fails, which is why the numbers are written down.
     Anything nested inside a panel (panel-wide, callout, chips, table heads)
     sits on the composited panel rather than the texture, so it can be far
     thinner and still clear 4.8:1. */
  --ground:        #eff1bf;                    /* the old body colour, kept */
  --glass:         rgb(255 255 255 / 0.93);
  --glass-thin:    rgb(255 255 255 / 0.86);
  --glass-line:    rgb(255 255 255 / 0.75);
  --glass-tint:    rgb(37 110 165 / 0.07);
  --blur:          saturate(170%) blur(16px);

  --shadow:        0 1px 2px rgb(30 40 30 / 0.06), 0 10px 30px rgb(30 40 30 / 0.10);
  --shadow-sm:     0 1px 2px rgb(30 40 30 / 0.06), 0 4px 12px rgb(30 40 30 / 0.07);

  --sans: 'Source Sans 3', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --serif: 'Source Serif 4', Georgia, 'Times New Roman', serif;

  --measure: 68ch;
  --shell: 1180px;

  --step-0: 1.0625rem;
  --step-1: 1.25rem;
  --step-2: 1.5rem;
  --step-3: 1.875rem;
  --step-4: 2.25rem;

  --space: 1.5rem;
  --radius: 6px;
  --focus: 3px solid var(--accent);
}

@media (min-width: 40rem) {
  :root { --step-0: 1.125rem; --step-3: 2.125rem; --step-4: 2.875rem; }
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font: var(--step-0)/1.7 var(--serif);
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
}

/* The texture is painted by a fixed pseudo-element rather than
   `background-attachment: fixed`, which repaints the whole layer on every
   scroll frame in mobile Safari --- noticeable on a report with 136 photos. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(0deg, rgb(255 255 255 / 0.18), rgb(255 255 255 / 0.18)),
    url('/assets/background.jpg') center / cover no-repeat,
    var(--ground);
}

h1, h2, h3, h4, h5, h6, nav, .ui { font-family: var(--sans); }

h1, h2, h3, h4 {
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: -0.012em;
  margin: 2.2em 0 0.6em;
  text-wrap: balance;
}
h1 { font-size: var(--step-4); margin-top: 0; }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }

p, ul, ol, blockquote, table, figure { margin: 0 0 1.25em; }
/* Prose only. Left unscoped this lands on every UI list too: the nav bar and
   the footer lay their items out in a flex row, so a top margin on items 2..n
   drops them all and leaves the first one looking misaligned. The grid of
   page links and the news card list picked up stray offsets from it as well.
   Every UI list below sets its own spacing. */
.prose li + li { margin-top: 0.35em; }

a { color: var(--accent); text-underline-offset: 0.16em; text-decoration-thickness: 1px; }
a:hover { color: var(--accent-deep); }

:focus-visible { outline: var(--focus); outline-offset: 2px; border-radius: 2px; }

img { max-width: 100%; height: auto; }

hr { border: 0; border-top: 1px solid var(--rule); margin: 2.5em 0; }

blockquote {
  margin-inline: 0;
  padding: 0.2em 0 0.2em 1.25em;
  border-left: 3px solid var(--accent);
  color: var(--ink-soft);
  font-style: italic;
}
blockquote cite { display: block; margin-top: 0.6em; font: 600 0.9em var(--sans); font-style: normal; color: var(--ink-faint); }

table { border-collapse: collapse; width: 100%; font-size: 0.95em; }
th, td { border: 1px solid var(--rule); padding: 0.5em 0.7em; text-align: left; }
th { background: rgb(255 255 255 / 0.6); font-family: var(--sans); }

.table-scroll { overflow-x: auto; }

/* ----------------------------------------------------------- skip / shell */

.skip {
  position: absolute; left: -9999px;
  background: var(--accent); color: #fff;
  padding: 0.7em 1.1em; border-radius: 0 0 var(--radius) 0;
  font: 600 0.95rem var(--sans); z-index: 20;
}
.skip:focus { left: 0; top: 0; }

.shell {
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: clamp(1rem, 4vw, 2rem);
}

/* --------------------------------------------------------------- masthead */
/*
 *  One row wherever the menu fits beside the wordmark, a Menu button when it
 *  does not. The eight labels come to roughly 620px of nav at the compact
 *  size; with a 260px wordmark and the shell's gutters that needs about
 *  1050px, so 66rem is where the row gives out. Below it, flex-wrap drops the
 *  nav onto its own full-width line and the button controls it.
 */

.masthead {
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur);
  backdrop-filter: var(--blur);
  border-bottom: 1px solid var(--glass-line);
  box-shadow: var(--shadow-sm);
  position: relative;
  z-index: 20;
}

.masthead__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem var(--space);
  padding-block: 0.8rem;
}

/* The 2014 mark is a 1460x217 black wordmark carrying the full name, so the
   brand is the image alone --- repeating the name in text beside it would read
   as a mistake. The name lives in alt text for anyone not seeing the image. */
.brand { display: block; text-decoration: none; color: inherit; }
.brand img { display: block; width: min(250px, 56vw); height: auto; }
.brand__tagline {
  display: block; margin-top: 0.25rem;
  font: 400 0.78rem/1.3 var(--sans); color: var(--ink-faint);
  letter-spacing: 0.01em;
}

/* ------------------------------------------------------------------ navbar */

.nav-btn {
  display: inline-flex; align-items: center; gap: 0.6rem;
  padding: 0.6rem 0.9rem;
  font: 600 0.95rem var(--sans); color: var(--ink);
  background: rgb(255 255 255 / 0.6);
  border: 1px solid var(--rule-strong); border-radius: var(--radius);
  cursor: pointer;
}
.nav-btn:hover { background: #fff; border-color: var(--accent); color: var(--accent-deep); }
.nav-btn__bars,
.nav-btn__bars::before,
.nav-btn__bars::after {
  display: block; width: 18px; height: 2px; border-radius: 2px;
  background: currentColor; content: '';
}
.nav-btn__bars { position: relative; }
.nav-btn__bars::before { position: absolute; top: -6px; }
.nav-btn__bars::after { position: absolute; top: 6px; }

.nav__list, .nav__sub { list-style: none; margin: 0; padding: 0; }
.navbar a {
  display: block; text-decoration: none; color: var(--ink);
  font: 600 0.95rem var(--sans);
}
.navbar a:hover, .navbar a[aria-current='page'] { color: var(--accent-deep); }

.nav-sub-btn {
  border: 0; background: none; cursor: pointer;
  color: var(--ink-soft); font: 600 1.15rem/1 var(--sans);
  padding: 0.4rem 0.7rem;
}

/* ---- narrow: the nav wraps to its own row and collapses ---- */
@media (max-width: 65.999rem) {
  /* Collapsed here rather than in the markup, so a visitor without JavaScript
     keeps the whole menu (see the <noscript> rule in layout.ts). */
  .navbar { display: none; flex-basis: 100%; }
  .navbar.is-open { display: block; }
  .navbar { padding-bottom: 0.5rem; }

  .nav__list > li { border-top: 1px solid var(--rule); }
  .navbar li { position: relative; }
  .navbar a { padding: 0.8rem 0.2rem; }

  .nav-sub-btn { position: absolute; top: 0.25rem; right: 0; }
  .nav-sub-btn[aria-expanded='true'] span { font-size: 0; }
  .nav-sub-btn[aria-expanded='true'] span::before { content: '\2212'; font-size: 1.15rem; }

  /* Closed by the script; open by default when the script never ran. */
  .nav__sub { padding-left: 1rem; }
  .nav-sub-btn ~ .nav__sub { display: none; }
  .nav-sub-btn[aria-expanded='true'] ~ .nav__sub,
  .nav__sub.is-open { display: block; }
  .nav__sub a { font-weight: 400; font-size: 0.95rem; color: var(--ink-soft); }
}

/* ---- wide: one row, with flyouts ---- */
@media (min-width: 66rem) {
  .masthead { position: sticky; top: 0; }
  .nav-btn, .nav-sub-btn { display: none; }
  .masthead__inner { flex-wrap: nowrap; padding-block: 0.6rem; }

  .nav__list { display: flex; align-items: stretch; }
  .nav__list > li { position: relative; display: flex; }
  .nav__list > li > a {
    display: flex; align-items: center; white-space: nowrap;
    padding: 0.7rem 0.6rem;
    border-bottom: 3px solid transparent;
  }
  .nav__list > li > a:hover,
  .nav__list > li > a[aria-current='page'] {
    border-bottom-color: var(--accent);
    background: var(--glass-tint);
  }

  /* Anchored to the right edge of its tab, because the nav sits flush against
     the shell's right gutter and a panel that grew rightwards ran off screen.
     It did that even while closed: visibility:hidden still takes part in
     layout, so the third-level list was adding 137px to the document's scroll
     width and showing a band of bare texture down the right of every page
     from 66rem to about 1330px. Growing leftwards has room at every width. */
  .nav__sub {
    position: absolute; top: 100%; right: 0; z-index: 30;
    min-width: 13.5rem; padding: 0.35rem;
    background: rgb(255 255 255 / 0.96);
    -webkit-backdrop-filter: var(--blur);
    backdrop-filter: var(--blur);
    border: 1px solid var(--glass-line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    visibility: hidden; opacity: 0;
    transition: opacity 0.14s ease, visibility 0.14s;
  }
  li:hover > .nav__sub,
  li:focus-within > .nav__sub { visibility: visible; opacity: 1; }

  /* Third level (Projects > Africa > Ghana) flies out sideways, or it would
     land on top of the level above it. Its containing block is the panel
     above, not the tab, so `right: 100%` parks it against that panel's left
     edge. */
  .nav__sub .nav__sub { top: -0.35rem; right: 100%; }
  .nav__sub a {
    padding: 0.5rem 0.7rem 0.5rem 1.3rem;
    border-radius: 4px; font-weight: 500;
  }
  .nav__sub a:hover { background: var(--accent-wash); }
  /* The chevron points the way the panel actually opens. It sits in the left
     gutter every row already reserves, so one item having a submenu does not
     push its label out of line with its siblings. */
  .nav__sub .has-sub > a { position: relative; }
  .nav__sub .has-sub > a::before {
    content: '\2039'; position: absolute; left: 0.6rem; color: var(--ink-faint);
  }
}

/* Past 80rem there is room to breathe: a larger wordmark and looser tabs. */
@media (min-width: 80rem) {
  .brand img { width: 310px; }
  .nav__list > li > a { padding-inline: 0.85rem; font-size: 0.98rem; }
}

/* ------------------------------------------------------------------- page */

main { display: block; padding-block: clamp(1.5rem, 4vw, 3rem) 4rem; }

/* The content sits on a frosted panel over the texture --- the same boxed
   layout the old site had, but letting the ground show through instead of
   covering it with opaque white. `main >` keeps this off the masthead and
   footer shells. */
main > .shell {
  padding: clamp(1.4rem, 4vw, 3rem);
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur);
  backdrop-filter: var(--blur);
  border: 1px solid var(--glass-line);
  border-radius: 16px;
  box-shadow: var(--shadow);
}

/* Edge to edge on a phone: a 16px gutter of texture either side of a panel is
   fussy, and the reading measure needs every pixel. */
@media (max-width: 40rem) {
  main > .shell { border-radius: 0; border-inline: 0; padding-inline: 1.1rem; }
}

/* News puts the article and the archive on two panels, not one wide one. */
main > .shell.with-sidebar {
  padding: 0; background: none; border: 0; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  padding-inline: clamp(1rem, 4vw, 2rem);
}
.with-sidebar > div,
.with-sidebar > .sidebar {
  padding: clamp(1.4rem, 3vw, 2.25rem);
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur);
  backdrop-filter: var(--blur);
  border: 1px solid var(--glass-line);
  border-radius: 16px;
  box-shadow: var(--shadow);
}
@media (max-width: 40rem) {
  main > .shell.with-sidebar { padding-inline: 0; }
  .with-sidebar > div,
  .with-sidebar > .sidebar { border-radius: 0; border-inline: 0; padding-inline: 1.1rem; }
}

.page-head { margin-bottom: 2rem; }
.page-head .eyebrow {
  font: 600 0.8rem/1 var(--sans); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--accent); margin: 0 0 0.75rem;
}
.page-head time { font: 400 0.95rem var(--sans); color: var(--ink-faint); }

/* Prose is a grid so a gallery can break out wider than the text without
   being lifted out of the body HTML the converter produced. */
.prose {
  display: grid;
  grid-template-columns:
    [full-start] minmax(0, 1fr)
    [wide-start] minmax(0, 6rem)
    [text-start] min(var(--measure), 100%) [text-end]
    minmax(0, 6rem) [wide-end]
    minmax(0, 1fr) [full-end];
}
.prose > * { grid-column: text; min-width: 0; }
.prose > .gallery,
.prose > .table-scroll,
.prose > video { grid-column: wide; }

.prose > h2 { border-top: 1px solid var(--rule); padding-top: 1.6rem; }
.prose > h2:first-child { border-top: 0; padding-top: 0; }

/* ---------------------------------------------------------------- gallery */

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 0.6rem;
  margin: 2rem 0 2.5rem;
}
@media (min-width: 40rem) {
  .gallery { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 0.85rem; }
}
.gallery figure { margin: 0; }
.gallery.cols-1 { grid-template-columns: minmax(0, 1fr); max-width: 40rem; }
.gallery.cols-1 img { aspect-ratio: auto; object-fit: contain; }
.gallery.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 40rem) { .gallery.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.gallery a {
  display: block; border-radius: 8px; overflow: hidden;
  background: var(--paper-soft);
  box-shadow: var(--shadow-sm);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.gallery a:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
.gallery img {
  display: block; width: 100%; aspect-ratio: 1; object-fit: cover;
  transition: transform 0.25s ease, opacity 0.25s ease;
}
.gallery a:hover img { transform: scale(1.03); opacity: 0.94; }
.gallery figcaption {
  font: 400 0.85rem/1.45 var(--sans); color: var(--ink-soft);
  margin-top: 0.4rem;
}

/* A single captioned image inside prose, from the old [caption] shortcode. */
figure.wp-caption { margin: 2rem 0; }
figure.wp-caption img { border-radius: 8px; box-shadow: var(--shadow-sm); }
figure.wp-caption figcaption {
  font: 400 0.9rem/1.5 var(--sans); color: var(--ink-soft); margin-top: 0.5rem;
}

video { width: 100%; height: auto; border-radius: var(--radius); background: #000; }

/* --------------------------------------------------------------- lightbox */

dialog.lightbox {
  border: 0; padding: 0; max-width: 100vw; max-height: 100vh;
  width: 100%; height: 100%; background: rgb(10 14 18 / 0.94);
}
dialog.lightbox::backdrop { background: rgb(10 14 18 / 0.94); }
.lightbox__frame {
  display: grid; grid-template-rows: 1fr auto; gap: 0.75rem;
  width: 100%; height: 100%; padding: clamp(0.75rem, 3vw, 2rem);
}
.lightbox__frame img {
  grid-row: 1; justify-self: center; align-self: center;
  max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 4px;
}
.lightbox__bar {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  color: #e8edf2; font: 400 0.95rem var(--sans);
}
.lightbox__bar button {
  font: 600 1rem var(--sans); color: #fff; background: rgb(255 255 255 / 0.12);
  border: 1px solid rgb(255 255 255 / 0.25); border-radius: var(--radius);
  padding: 0.5rem 0.9rem; cursor: pointer; min-width: 3rem;
}
.lightbox__bar button:hover { background: rgb(255 255 255 / 0.22); }

/* ------------------------------------------------------------ news layout */

.with-sidebar { display: grid; gap: clamp(2rem, 5vw, 3.5rem); }
@media (min-width: 62rem) {
  .with-sidebar { grid-template-columns: minmax(0, 1fr) 17rem; align-items: start; }
}
.sidebar { font-family: var(--sans); font-size: 0.95rem; }
.sidebar h2 { font-size: 1.05rem; margin: 0 0 0.7rem; }
.sidebar section + section { margin-top: 2rem; }
.sidebar ul { list-style: none; margin: 0; padding: 0; }
.sidebar li { margin: 0 0 0.45em; }
.sidebar a { color: var(--ink); text-decoration: none; }
.sidebar a:hover { color: var(--accent); text-decoration: underline; }
.sidebar .count { color: var(--ink-faint); font-size: 0.9em; }
.sidebar ul ul { margin: 0.3rem 0 0.8rem 0.9rem; }
.sidebar strong { font-weight: 600; }

.card-list { list-style: none; margin: 0; padding: 0; }
.card-list > li { padding-block: 1.6rem; border-top: 1px solid var(--rule); }
.card-list > li:first-child { border-top: 0; padding-top: 0; }
.card-list h2 { margin: 0 0 0.35rem; font-size: var(--step-2); }
.card-list h2 a { text-decoration: none; }
.card-list h2 a:hover { text-decoration: underline; }
.card-list .meta { font: 400 0.9rem var(--sans); color: var(--ink-faint); margin: 0 0 0.6rem; }
.card-list p { margin: 0; color: var(--ink-soft); }

/* The featured image on a card. aria-hidden, so it is decoration beside the
   heading link rather than a second tab stop to the same place. */
.card-list .card-img {
  display: block; margin-bottom: 0.9rem;
  border-radius: 10px; overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.card-list .card-img img {
  display: block; width: 100%; aspect-ratio: 21 / 9;
  object-fit: cover; background: var(--accent-wash);
  transition: opacity 0.15s ease;
}
.card-list .card-img:hover img { opacity: 0.92; }

/* ------------------------------------------------------------- slideshow */
/*
 *  The 2014 Revolution Slider, rebuilt. A horizontal scroll-snap strip, so it
 *  swipes and scrolls with no JavaScript at all; /assets/slider.js adds the
 *  bullets and the autoplay on top. The old one was a 250px letterbox band,
 *  which cut these photos to a sliver --- this is taller and scales with the
 *  viewport instead.
 */
.slideshow {
  position: relative;
  max-width: var(--shell);
  margin: 0 auto 2.5rem;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  background: var(--accent-wash);
}
.slideshow__track {
  display: flex; list-style: none; margin: 0; padding: 0;
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.slideshow__track::-webkit-scrollbar { display: none; }
.slide {
  position: relative; flex: 0 0 100%; scroll-snap-align: start;
  height: clamp(320px, 38vw, 460px);
}
.slide img {
  display: block; width: 100%; height: 100%;
  object-fit: cover; background: var(--accent-wash);
}
/* The scrim is solved, not eyeballed: at its lightest the text sits on 0.68
   black, so even over a pure white photo the composite is rgb(82 82 82) and
   white text clears AA at 7.8:1. design.test.ts holds it there. */
.slide__text {
  position: absolute; inset: auto 0 0 0;
  padding: 1.4rem clamp(1.1rem, 4vw, 2.2rem) clamp(1.1rem, 3vw, 1.8rem);
  background: linear-gradient(to top, rgb(0 0 0 / 0.88), rgb(0 0 0 / 0.68));
  color: #fff;
}
/* The fade lives above the text box rather than inside it, so the scrim under
   the words is never lighter than its 0.68 stop no matter how tall the text
   runs. That is what makes the contrast provable instead of positional. */
.slide__text::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 100%;
  height: 3.5rem;
  background: linear-gradient(to top, rgb(0 0 0 / 0.68), rgb(0 0 0 / 0));
}
.slide__text h2 { margin: 0 0 0.4rem; font-size: var(--step-2); line-height: 1.15; }
.slide__text h2 a { color: #fff; text-decoration: none; }
.slide__text h2 a:hover { text-decoration: underline; }
/* One link, whole slide clickable: the overlay is on the heading's anchor, so
   there is exactly one tab stop and it carries the slide's name. */
.slide__text h2 a::after { content: ''; position: absolute; inset: 0; }
.slide__text p {
  margin: 0; max-width: 60ch; color: rgb(255 255 255 / 0.92);
  font-size: 0.95rem; line-height: 1.5;
}
@media (max-width: 40rem) {
  .slide__text p { display: none; }     /* the headline carries it on a phone */
}

.slideshow__nav {
  position: absolute; left: 0; right: 0; bottom: 0.7rem;
  display: flex; justify-content: center; gap: 0.5rem; z-index: 2;
}
.slideshow__dot {
  width: 10px; height: 10px; padding: 0; border-radius: 50%;
  border: 1px solid rgb(255 255 255 / 0.85); background: rgb(0 0 0 / 0.35);
  cursor: pointer; transition: background 0.15s ease, transform 0.15s ease;
}
.slideshow__dot.is-current { background: #fff; transform: scale(1.25); }
.slideshow__dot:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* WordPress's featured image, above the title. The old theme cropped every
   cover to 881x229 (3.84:1); these originals run from 0.75 to 3.84 and from
   385px to 1936px wide, so something has to give. 21:9 keeps about twice as
   much of a 4:3 photo as the old crop did while still reading as a banner.
   The wash underneath means a short or slow image never shows the texture. */
.cover {
  margin: 0 0 1.6rem; border-radius: var(--radius); overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.cover img {
  display: block; width: 100%; aspect-ratio: 21 / 9;
  object-fit: cover; background: var(--accent-wash);
}

/* Auto page listings, from [sibling-pages] / [child-pages]. */
.page-links { list-style: none; margin: 1.5rem 0 2rem; padding: 0; display: grid; gap: 0.6rem; }
@media (min-width: 40rem) { .page-links { grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); } }
.page-links a {
  display: block; padding: 0.85rem 1rem;
  border: 1px solid var(--glass-line); border-radius: 10px;
  font: 600 1rem var(--sans); text-decoration: none; color: var(--ink);
  background: rgb(255 255 255 / 0.6);
  box-shadow: var(--shadow-sm);
  transition: transform 0.15s ease, border-color 0.15s ease;
}
.page-links a:hover {
  border-color: var(--accent); color: var(--accent);
  background: #fff; transform: translateY(-1px);
}
.page-links .is-current > a {
  border-color: var(--accent); background: var(--accent-wash);
  color: var(--accent-deep);
}
.page-links .nav__sub,
.page-links ul { list-style: none; margin: 0.6rem 0 0 1rem; padding: 0; display: grid; gap: 0.5rem; }

/* --------------------------------------------------------------- unlock */

/* Unlock and 404 are a short card, not a full-width sheet. :has is the whole
   support story here --- an old browser just gets the wide panel. */
main > .shell:has(> .panel) { max-width: 46rem; }
.panel { max-width: 34rem; margin-inline: auto; }
.panel__note {
  margin-top: 1.75rem; padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
  font: 400 0.92rem/1.6 var(--sans); color: var(--ink-faint);
}
.contact-form, .unlock-form { margin-top: 1.5rem; }
.cf-turnstile { margin-bottom: 1.25rem; }
.panel h1 { font-size: var(--step-3); }
.panel p { color: var(--ink-soft); }

.field { display: block; margin-bottom: 1.1rem; font-family: var(--sans); }
.field > span { display: block; font-weight: 600; margin-bottom: 0.35rem; font-size: 0.95rem; }
.field input, .field textarea {
  width: 100%; padding: 0.7rem 0.8rem;
  border: 1px solid var(--rule-strong); border-radius: var(--radius);
  font: var(--step-0) var(--sans); color: var(--ink);
  background: rgb(255 255 255 / 0.85);
}
.field input:focus, .field textarea:focus { outline: var(--focus); outline-offset: 1px; border-color: var(--accent); }
.field textarea { min-height: 9rem; resize: vertical; }

.btn {
  display: inline-block; border: 0; border-radius: var(--radius);
  background: var(--accent); color: #fff;
  font: 600 1rem var(--sans); padding: 0.75rem 1.4rem; cursor: pointer;
  text-decoration: none;
}
.btn:hover { background: var(--accent-deep); color: #fff; }

.notice { padding: 0.9rem 1.1rem; border-radius: var(--radius); font-family: var(--sans); font-size: 0.95rem; }
.notice--error { background: #fdf0ef; border: 1px solid #f0c8c4; color: #8a2b22; }
.notice--ok { background: var(--accent-wash); border: 1px solid #c3d9ea; color: var(--accent-deep); }

/* ------------------------------------------------- odds the templates use */

.pager {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin-top: 2.5rem; padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  font: 600 0.95rem var(--sans);
}
.pager span { color: var(--ink-faint); font-weight: 400; }
.pager a { text-decoration: none; }
.pager a:hover { text-decoration: underline; }

.page-tail { margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid var(--rule); }
.page-tail a { font: 600 0.95rem var(--sans); text-decoration: none; }
.page-tail a:hover { text-decoration: underline; }

/* Two blocks the homepage's old page-builder shortcodes become. */
.panel-wide {
  margin: 2.5rem 0; padding: clamp(1.25rem, 3vw, 2rem);
  background: rgb(255 255 255 / 0.55);
  border: 1px solid var(--glass-line);
  border-radius: 12px;
  box-shadow: var(--shadow-sm);
}
.panel-wide h2 { margin-top: 0; font-size: var(--step-2); }
.panel-wide p:last-child { margin-bottom: 0; }

.callout {
  margin: 3rem 0 1rem; padding: clamp(1.5rem, 4vw, 2.5rem);
  background: linear-gradient(140deg, rgb(37 110 165 / 0.10), rgb(255 255 255 / 0.55));
  border: 1px solid var(--glass-line);
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
  text-align: center;
}
.callout h2 { margin-top: 0; color: var(--accent-deep); }
.callout p:last-child { margin-bottom: 0; }

.cta { margin: 1.5rem 0; }
.center { text-align: center; }
.icon { vertical-align: -0.2em; color: var(--accent); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.prose.home > .panel-wide,
.prose.home > .callout { grid-column: wide; }

/* --------------------------------------------------------------- search */

.search-form { display: flex; gap: 0.6rem; margin-bottom: 2rem; }
.search-form input { flex: 1; }
#search-results mark { background: #fdf3cf; color: inherit; padding: 0 0.1em; }

/* --------------------------------------------------------------- footer */

.sitefoot {
  border-top: 1px solid var(--glass-line);
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur);
  backdrop-filter: var(--blur);
  padding-block: 2.5rem 3rem; margin-top: 4rem;
  font-family: var(--sans); font-size: 0.95rem; color: var(--ink-soft);
}
.sitefoot ul { list-style: none; margin: 0 0 1.5rem; padding: 0; display: flex; flex-wrap: wrap; gap: 0.4rem 1.5rem; }
.sitefoot a { color: var(--ink); text-decoration: none; }
.sitefoot a:hover { color: var(--accent); text-decoration: underline; }
.sitefoot small { color: var(--ink-faint); }

@media print {
  .masthead, .sitefoot, .navbar, .nav-btn, .skip, .pager { display: none; }
  body { font-size: 11pt; background: #fff; }
  body::before { display: none; }
  main > .shell,
  .with-sidebar > div,
  .with-sidebar > .sidebar {
    padding: 0; background: none; border: 0; box-shadow: none;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .prose > * { grid-column: 1 / -1; }
}

/* Backdrop blur is a per-frame GPU cost. Anyone who has asked for less motion
   has usually asked for less of this too, and the layout does not depend on
   it --- the panels just become solid. */
@media (prefers-reduced-transparency: reduce) {
  .masthead__bar, .navbar, .sitefoot, .nav__sub,
  main > .shell, .with-sidebar > div, .with-sidebar > .sidebar {
    background: var(--paper);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0.01ms !important; }
  .gallery a:hover, .page-links a:hover { transform: none; }
}
