/* THE WARD'S PAGE (Round 367).
   ==========================================================================
   The public page's own stylesheet, and the only one it loads. Warm ivory
   surfaces, forest green used as an accent rather than a fill, dark
   charcoal reading text, soft warm dividers, and one photograph per tab
   fading into the title area. Mobile first; a centred column with rounded
   corners on anything wider than a phone.

   EVERY RULE IS SCOPED UNDER .ward-app (or body:not(.admin) for the page
   ground) so the same file can be loaded by the leader app, where the LIVE
   PROGRAM replica renders this exact markup inside .wp-paper and must look
   identical to the page the ward reads. Class names were checked against
   styles.css for collisions before being chosen.

   LIGHT IS THE DEFAULT AND DARK IS EXPLICIT: the ward's page always sets
   data-theme on <html> (light unless the footer's switch chose dark), and the
   replica sets is-dark on its own root. There is deliberately no
   prefers-color-scheme block -- Round 233 settled that the page is light
   unless the reader chooses otherwise.

   The four header crops, zooms and washes live under [data-tab] near the
   top; a photograph can be re-framed there without touching any script.
   ========================================================================== */

@font-face {
  font-family: 'Ward Caslon';
  src: url('/caslon.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
/* THE PAGE'S READING FACE (Round 823): EB Garamond, the face Derek chose for
   the Welcome tab's scripture (Round 523) and the meeting agendas. Until now
   --serif named only faces a phone might have -- Iowan Old Style on an
   iPhone, Palatino on Windows -- and Android has neither, so on his phone the
   hymn titles, the theme, the date and the notes fell back to Android's own
   serif, a third look beside the Caslon. Garamond's small letters run small
   for their size (x-height 0.41 of the em against Iowan's and Palatino's
   0.46), so these faces draw it 115% as large: every size below, set for
   those faces, keeps its look and its line length. A family of its own, so
   the thought box's 'Ward Garamond' (sized for Garamond, below) is left as it
   is; the files are the same ones, fetched once. */
@font-face {
  font-family: 'Ward Garamond Text';
  src: url('/garamond.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  size-adjust: 115%;
}
@font-face {
  font-family: 'Ward Garamond Text';
  src: url('/garamond-italic.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
  size-adjust: 115%;
}
/* Its true semibold for the bold words (the masthead's small capitals, a
   bold line in a note), so no browser has to fake one. */
@font-face {
  font-family: 'Ward Garamond Text';
  src: url('/garamond-semibold.woff2') format('woff2');
  font-weight: 600 700;
  font-style: normal;
  font-display: swap;
  size-adjust: 115%;
}

[hidden] { display: none !important; }

/* ------------------------------------------------------------ the ground */

html.ward-html {
  background: #f4efe4;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
html.ward-html[data-theme='dark'] { background: #061711; }

body:not(.admin) {
  margin: 0;
  min-height: 100vh;
  background: radial-gradient(circle at 50% -10%, rgba(52, 115, 95, 0.09), transparent 32%), #f4efe4;
  color: #3f4441;
  font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
[data-theme='dark'] body:not(.admin) {
  background: radial-gradient(circle at 50% -10%, rgba(120, 180, 150, 0.10), transparent 32%), #061711;
  color: #e6dfd4;
}

/* ------------------------------------------------------------- the tokens */

.ward-app {
  --bg: #f4efe4;
  --surface: #faf7ef;
  --surface-2: #f2ece1;
  --card: #fcfaf3; /* the page's cards (the program, the group list, the history cards) */
  /* The box an opened item stands in: a fold card, an expanded announcement,
     an expanded group. Round 423 made it pure white at Derek's word; Round
     430 brought it to a slightly off-white (#fdfcf8) at his word; Round 433
     split the difference to #fefdfb; Round 434 pushed it "a little bit
     further towards pure white, but not actually pure white", all at his
     word. One notch under white on every channel now: as close as it can
     go while still being a colour of its own, and a step lighter than
     --card, so it reads as its own surface against the cream page. */
  --box: #fefefd;
  --ink: #31463f;
  --ink-strong: #1f2930;
  --title-ink: #1f2f4d; /* the announcement titles' navy (Round 502), the leader app's own (Round 501) */
  /* The notice's Button (Round 657, Derek's pick: Harbor, in the Glass style):
     a blue leaning toward the page's green, 5.7:1 under the cream words; the
     gloss along its top, and the frosted circle its glyph sits in. */
  --act: #2c6a86;
  --act-hi: rgba(255, 255, 255, 0.24);
  --act-chip: rgba(255, 255, 255, 0.17);
  --act-rim: rgba(255, 255, 255, 0.26);
  --body: #3f4441;
  --muted: #6b6a62;
  --forest: #124f3d;
  /* The calendar's three scope marks (Round 371): shapes AND colours. */
  --mk-ward: #1d6a4f;
  --mk-stake: #b8642f;
  --mk-church: #4c6f95;
  --accent: #367463;
  --accent-2: #568a78;
  --accent-soft: #e8efe9;
  --accent-soft-2: #d2e6da;
  /* The List / Calendar toggle's chosen side (Round 417, Derek: "more of
     a blue/green ... one that still flows with the overall design"): a
     teal tint between the forest accent and the slate --mk-church (a
     step bluer since Round 419, at his word), its
     ink a deep teal (5.5:1 on the tint) and its ring the mid teal. Dark
     below moves in step. */
  --seg-on-bg: #c3dfe6;
  --seg-on-ink: #1c5568;
  --seg-on-line: #4a8a9c;
  --line: #ded6c8;
  --line-strong: #cec2b1;
  --danger: #8c3b2e;
  --shadow: 0 8px 26px rgba(59, 48, 34, 0.07);
  --card-shadow: 0 5px 18px rgba(62, 51, 37, 0.055);
  --header-wash: rgba(250, 247, 239, 0.97);
  --nav-surface: rgba(252, 249, 244, 0.92);
  --display: 'Ward Caslon', 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia, serif;
  --serif: 'Ward Garamond Text', 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia, 'Times New Roman', serif;
  --sans: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --radius: 22px;
  --ds: 1;
  color-scheme: light;
  color: var(--body);
  background: var(--surface);
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.5;
}

[data-theme='dark'] .ward-app,
.ward-app.is-dark {
  --bg: #061711;
  --surface: #082419;
  --surface-2: #0c2b1f;
  --card: #0f2c21;
  --ink: #f3eee5;
  --ink-strong: #fffaf0;
  --title-ink: #cbd7ea;
  /* Harbor lifted to a pale version of itself, the words taking the dark
     ground, as the titles' navy does here. */
  --act: #94cadb;
  --act-hi: rgba(255, 255, 255, 0.42);
  --act-chip: rgba(6, 23, 17, 0.12);
  --act-rim: rgba(6, 23, 17, 0.18);
  --body: #e6dfd4;
  --muted: #b7b0a5;
  --forest: #7cc2a5;
  --mk-ward: #86cfae;
  --mk-stake: #e0956a;
  --mk-church: #9db8d6;
  --accent: #8ec1aa;
  --accent-2: #73ad94;
  --accent-soft: #153b2d;
  --accent-soft-2: #1a4a38;
  --seg-on-bg: #153b46;
  --seg-on-ink: #a3d4e0;
  --seg-on-line: #4c8c9e;
  --line: rgba(225, 236, 229, 0.13);
  --line-strong: rgba(225, 236, 229, 0.22);
  --danger: #e08a76;
  --shadow: 0 16px 38px rgba(0, 0, 0, 0.30);
  --card-shadow: 0 10px 24px rgba(0, 0, 0, 0.18);
  --header-wash: rgba(6, 27, 20, 0.96);
  --nav-surface: rgba(8, 30, 22, 0.91);
  color-scheme: dark;
}

.ward-app,
.ward-app * { box-sizing: border-box; }

.ward-app button,
.ward-app input,
.ward-app textarea { font: inherit; color: inherit; }

.ward-app a { color: var(--accent); }
.ward-app ::selection { background: var(--accent); color: #fff; }

.ward-app button:focus-visible,
.ward-app a:focus-visible,
.ward-app input:focus-visible,
.ward-app textarea:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

/* ------------------------------------------------------------- the column */

.ward-app {
  position: relative;
  width: min(100%, 40rem);
  margin: 0 auto;
  overflow: clip;
}

body:not(.admin) .ward-app {
  min-height: 100vh;
  box-shadow: 0 20px 60px rgba(54, 43, 29, 0.07);
}

/* A wider window gets the column as a card on the page ground rather than a
   phone layout stretched edge to edge. */
@media (min-width: 44rem) {
  body:not(.admin) { padding: 1.5rem 0; }
  body:not(.admin) .ward-app {
    border-radius: 30px;
    min-height: calc(100vh - 3rem);
  }
}

/* ------------------------------------------------------------- the header */

.ward-app .hero {
  position: relative;
  background: var(--surface);
  overflow: hidden;
}

.ward-app .hero-photo {
  position: relative;
  /* 24rem (16 on a phone) since Round 401: the meetinghouse photograph is
     a 4:3 landscape drawn at full width, so the box's HEIGHT is what
     decides how much of it shows -- with object-fit: cover the width sets
     the scale (the 640px column draws it 480px tall, a 390px phone 293px),
     and these two heights show rows 7-87% of it on a computer and 7.5-95%
     on a phone (Round 402; Round 401 showed 4-84 and 4-91.5): the cross
     just under the top edge, the whole facade, the steps, and the title
     block over the lawn. It was 13.75rem / 13rem for
     the old 335px snapshot, and 18.75 / 18 for the tall Instagram frame
     that stood here for an hour (the first cut of this round, never
     deployed). */
  height: 24rem;
  overflow: hidden;
}

.ward-app .hero-img {
  position: absolute;
  top: 0;
  left: 0;
  /* THE PHOTOGRAPH (Round 401): Derek's own 4:3 of the meetinghouse -- the
     spire and the entrance straight on, trees either side, a summer sky --
     supplied at 1448x1086 and encoded to 1280x960, which is the header's
     exact width on a retina screen. Nothing flipped, nothing cropped
     (Round 359's rule). It replaces the 335px autumn snapshot of Rounds
     390-400.

     FULL WIDTH, his ask ("Use the full width of this one"): the image is
     the box's width and height and object-fit: cover crops the HEIGHT
     only; object-position picks the rows. No plate and no side masks --
     Round 400's 88% band and the first cut's 16rem plate with feathered
     edges existed for pictures that could not fill the width, and this
     one can. The bottom still dissolves into the surface through
     .hero-fade and the title block's own ground. Two things that do NOT
     work here, from Round 400: a transform: scale() shows the same crop
     smaller, and width: auto on an absolutely positioned image takes its
     intrinsic ratio rather than stretching -- the width must be stated. */
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* 52% puts row 10% at the top of the 24rem box (Round 405 -- 36% and 58%
     in Round 402, the cross tip now 10px / 7px past the top edge) (the slack is 96px of a
     480px picture, so a point is under 1px here and the numbers run
     bigger than the old file ever needed); the phone block below sets
     its own, 84% for its 16rem box. Round 401 sat at 20% / 32% (row 4%
     at the top, 21px of sky over the cross on a computer and 12px on a
     phone); Round 402 panned down a little at his word: 15px on a
     computer and 10px on a phone, which leaves the cross tip 5px / 3px
     inside the top edge -- the same row of the photograph (about 70 of
     960) at the top on both screens. The crop of the old file walked
     33 -> 45 -> 40 -> 42 -> 44 -> 46 -> 48 -> 46% over Rounds 391-398
     and is history now. The filter is a step less muted than the old
     placeholders wore (Round 392). */
  object-position: center 52%;
  display: block;
  filter: saturate(0.86) contrast(0.96);
  opacity: 0;
  z-index: 1;
  transition: opacity 0.55s ease;
}
/* Fades in once loaded (is-loaded is set by ward.js; without script the
   no-JS block below shows it outright). */
.ward-app .hero-img.is-loaded { opacity: 1; }
/* The photograph carries a z-index, so its box is its own stacking context
   and it can never rise over the title. */
.ward-app .hero-photo { isolation: isolate; }

/* The per-tab framings (.hero-img[data-tab='...'], four rules) are gone:
   one photograph, one crop, on .hero-img above (Round 397). */

/* A wash over the photograph so the title reads, then a fade into the
   surface so the picture ends nowhere in particular rather than at an edge. */
.ward-app .hero-wash {
  position: absolute;
  inset: 0;
  z-index: 3;
  /* 12% (Round 842, from 24; Derek: dark mode's "less faded out version" is
     the one he likes). Round 392 took the meetinghouse's wash to 10% ('don't
     fade it out quite so much'); Round 400 brought it up a step ('fade the
     entire header image out just a little bit more'), then 16 (Round 406), 20
     and 24 (Round 419). The one wash now that one photograph serves every tab
     (Round 397). DARK NO LONGER MOVES IN STEP: a light veil lifts the
     picture's shadows toward the cream page, where a dark one only dims it
     against a darker page, so the same strength reads as more faded in light
     -- measured on the photograph, 24% light kept 72% of its contrast and
     28% dark 76%, and still light looked the paler of the two. At 12% the sky
     and the brick read as they do in dark; the title never sat on the wash
     (the fade below and the title block's own ground carry it). */
  background: rgba(255, 252, 245, 0.12);
}

.ward-app .hero-fade {
  position: absolute;
  z-index: 4;
  left: 0;
  right: 0;
  bottom: 0;
  /* Round 392: 72% and a 44% middle stop paled the whole lower half of the
     picture; the title block overlaps only the bottom 3.6rem of the box and
     brings its own ground, so the fade's job above that is tone. 66% and a
     26% stop let the facade through and still dissolve the bottom edge into
     the surface. Dark below moves in step. */
  height: 66%;
  background: linear-gradient(180deg, transparent 0%, rgba(250, 247, 239, 0.26) 36%, var(--header-wash) 86%, var(--surface) 100%);
}

[data-theme='dark'] .ward-app .hero-wash,
.ward-app.is-dark .hero-wash { background: rgba(3, 18, 13, 0.28); }
[data-theme='dark'] .ward-app .hero-fade,
.ward-app.is-dark .hero-fade {
  background: linear-gradient(180deg, transparent 0%, rgba(6, 26, 19, 0.28) 36%, var(--header-wash) 86%, var(--surface) 100%);
}

/* A header with no photograph behind it (the error page). */
.ward-app .hero-brand.is-bare { margin-top: 0; padding-top: 2.25rem; background: none; }

.ward-app .hero-brand {
  position: relative;
  z-index: 2;
  text-align: center;
  /* -3.225rem (Round 413, from -3.35; Round 408 from -3.6): the block
     overlaps the photograph by
     this much, so the overlap is the one number that moves THE HISTORIC
     and everything under it without moving the picture -- 4px down at his
     word ("just the tiniest bit"). */
  margin-top: -3.225rem;
  padding: 0 1.6rem 1.1rem;
  background: linear-gradient(180deg, transparent, var(--surface) 39%);
}

.ward-app .hero-kicker,
.ward-app .hero-est {
  margin: 0;
  font-family: var(--serif);
  font-weight: 700;
  text-transform: uppercase;
  color: var(--accent);
}
.ward-app .hero-kicker { font-size: calc(0.625rem * var(--ds)); letter-spacing: 0.28em; }
.ward-app .hero-est { font-size: calc(0.6875rem * var(--ds)); letter-spacing: 0.24em; color: var(--ink); }

.ward-app .hero-name {
  /* 0.4rem below and 0.4rem less 0.055em above (Round 407). The two
     margins were equal and the gaps did not read equal: the name has no
     descenders, so its bottom edge is a clean baseline, while its top edge
     is the capitals with the one ascender in Ward standing 2px higher at
     36px. Measured by cap height the gap above was 16.1px against 14.2
     below; the 0.055em (2px at this size, scaling with the name on a
     phone) is that ascender, so the two small-caps lines now stand the
     same distance off the letters the eye reads. */
  margin: calc(0.4rem - 0.055em) 0 0.4rem;
  font-family: var(--display);
  font-weight: 400;
  font-size: calc(2.5rem * var(--ds));
  line-height: 1;
  letter-spacing: -0.012em;
  color: var(--ink-strong);
}

.ward-app .hero-rule {
  width: 2.125rem;
  height: 1.5px;
  margin: 0.7rem auto 0.6rem;
  background: var(--accent);
  opacity: 0.75;
}

.ward-app .hero-date {
  margin: 0;
  font-family: var(--serif);
  font-style: italic;
  font-size: calc(1.0625rem * var(--ds));
  color: var(--accent);
}

/* ---------------------------------------------------------- the four tabs */

.ward-app .nav-wrap {
  position: sticky;
  top: 0;
  z-index: 30;
  /* The sides stay 10px when a phone's text is set larger (Round 887), so
     the room goes to the tabs; at the usual size 0.625rem is 10px. */
  padding: 0.5rem min(0.625rem, 10px) 0.375rem;
  background: linear-gradient(180deg, var(--surface) 70%, transparent);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}

.ward-app .primary-nav {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  background: var(--nav-surface);
  border: 1px solid var(--line);
  border-radius: 17px;
  box-shadow: 0 7px 22px rgba(46, 40, 31, 0.06);
  /* No clipping (Round 863): the chosen tab's glow in dark has to escape the
     bar, so the two end tabs round their own outer corners instead. */
  overflow: visible;
}

.ward-app .nav-btn {
  position: relative;
  min-height: 3.875rem;
  padding: 0.5rem 0.2rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
  border: 0;
  background: transparent;
  color: var(--forest);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 0.28s ease, color 0.28s ease;
}
.ward-app .nav-btn + .nav-btn { border-left: 1px solid var(--line); }
.ward-app .nav-btn .ico { width: 1.3125rem; height: 1.3125rem; opacity: 0.92; transition: opacity 0.28s ease; }
.ward-app .nav-label {
  font-family: var(--serif);
  font-size: 0.6875rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--forest);
}
.ward-app .nav-btn.is-active { background: rgba(210, 233, 219, 0.66); }
.ward-app .nav-btn.is-active .ico { opacity: 1; }
/* The mark under the open tab is always there, scaled to nothing until the
   tab is chosen, so a press grows it in from its centre (Round 379). */
.ward-app .nav-btn::after {
  content: '';
  position: absolute;
  left: 19%;
  right: 19%;
  bottom: 0;
  height: 2px;
  border-radius: 99px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 0.28s cubic-bezier(0.22, 0.75, 0.28, 1);
}
.ward-app .nav-btn.is-active::after { transform: scaleX(1); }
.ward-app .nav-btn:focus-visible { outline-offset: -3px; }
/* The end tabs keep the bar's corners now that it no longer clips (Round
   863): the bar's 17px less its 1px border. */
.ward-app .nav-btn:first-child { border-radius: 16px 0 0 16px; }
.ward-app .nav-btn:last-child { border-radius: 0 16px 16px 0; }
/* THE CHOSEN TAB GLOWS IN DARK (Round 863, Derek: "I love the green glow that
   you have in dark mode coming off the 'How well do you know the 1st Ward?'
   box. Can you implement that same glow ... for the selected category"): the
   quiz card's glow (Round 861) at the tab's scale -- the card's exact values
   all but vanish under a short edge, so the spread is wider. Light keeps its
   tint alone. A little less of it since Round 892 (Derek: "just a little bit
   less glowy"): the accent at 65% where it was whole, 16px of blur where it
   was 18, the same shape. */
[data-theme='dark'] .ward-app .nav-btn.is-active,
.ward-app.is-dark .nav-btn.is-active { background: rgba(114, 175, 148, 0.24); box-shadow: 0 6px 16px -6px color-mix(in srgb, var(--accent) 65%, transparent); }
[data-theme='dark'] .ward-app .nav-btn,
[data-theme='dark'] .ward-app .nav-label,
.ward-app.is-dark .nav-btn,
.ward-app.is-dark .nav-label { color: var(--ink); }

/* THE FOUR TABS FIT AT ANY TEXT SIZE (Round 887, from the Impeccable audit:
   with a phone's text set larger, History ran off the right edge from 1.25x
   and Groups from 2x, cut off by the column). The columns share the bar
   equally and never widen for their words (the minmax above), and a tab --
   its icon, its word, its height -- grows with the reader's text only until
   the word fills its quarter of the bar, then holds, as a phone's own tab
   bar does. --nav-u stands in for 1rem: "PROGRAM", the widest word, is 6.36
   times its 0.6875rem size, plus 0.2 of padding each side and the 1px rule,
   with a little to spare. At the usual size on a phone 340px wide or more it
   is exactly 1rem, so nothing moves; on a 320px phone the tabs come down a
   shade, where "PROGRAM" overran its quarter by two pixels. A browser without
   container units keeps the sizes above. */
@supports (width: 1cqi) {
  .ward-app .primary-nav { container-type: inline-size; }
  .ward-app .nav-btn {
    --nav-u: min(1rem, calc((25cqi - 1px) / 4.95));
    min-height: calc(3.875 * var(--nav-u));
    padding: calc(0.5 * var(--nav-u)) calc(0.2 * var(--nav-u));
    gap: calc(0.3 * var(--nav-u));
  }
  .ward-app .nav-btn .ico { width: calc(1.3125 * var(--nav-u)); height: calc(1.3125 * var(--nav-u)); }
  .ward-app .nav-label { font-size: calc(0.6875 * var(--nav-u)); }
}

/* Inside the leader app's card the page scrolls with the window, so the
   nav does not pin itself over the app's own tab bar. The phone-frame
   preview scrolls inside its own stage, where sticky behaves as on a phone. */
.acard .ward-app .nav-wrap { position: static; }

/* --------------------------------------------------------- the screens */

.ward-app .screens {
  padding: 0.375rem 0.75rem 2.25rem;
  scroll-margin-top: 5rem;
  /* The column is a container (Round 835): the History's width rules ask
     how wide the COLUMN is, not the window, so Leader Tools' phone preview
     (a phone's width on a computer) shows what a phone shows. 616px on a
     computer, about 366 on a phone. */
  container: wardcol / inline-size;
}

/* A tab press: the panel fades up on an ease-out (Round 379). The header
   photographs dissolve and the nav's mark grows in beside it. */
.ward-app .screen { animation: ward-fade 0.32s cubic-bezier(0.22, 0.61, 0.36, 1); }

@keyframes ward-fade {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

.ward-app .card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  padding: 1.125rem;
  margin-top: 0.625rem;
}

/* Round 383: .page-title has no emitter. It dressed the two display
   headings the tabs used to open with -- "Find Your People" on Groups and
   "One of Provo's Four Original Wards" on History -- both of which came off
   at Derek's word so that every tab opens straight onto its content. The
   chapter articles keep their own .article-title. */

/* No width cap: a cap left the right third of the card empty on a computer
   (Round 377). Alone in its card since Round 383. */
.ward-app .subtitle {
  margin: 0.5rem 0 0;
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--body);
}

.ward-app .mini-rule {
  width: 2.375rem;
  height: 1.5px;
  margin: 0.8rem 0;
  background: var(--accent);
}
.ward-app .mini-rule.is-centred { margin-left: auto; margin-right: auto; }

.ward-app .section-title {
  margin: 0;
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  white-space: nowrap;
}

.ward-app .section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  margin: 1.125rem 0.125rem 0.625rem;
}
/* .section-rule (the hairline beside a section title) went in Round 373
   with its one emitter, the Bulletin's UPCOMING EVENTS head; the Groups
   and History heads never carried one. */

.ward-app .empty-note {
  margin: 0.75rem 0;
  padding: 0.75rem 0.25rem;
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.9375rem;
  color: var(--muted);
}

.ward-app .draft-flag {
  display: inline-block;
  margin: 0.2rem 0 0;
  padding: 0.1rem 0.5rem;
  border: 1px dashed var(--accent-2);
  border-radius: 999px;
  font-size: 0.625rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}
.ward-app .is-draft { outline: 1px dashed var(--accent-2); outline-offset: 2px; }

.ward-app .chev { width: 1.1875rem; height: 1.1875rem; flex: none; transition: transform 0.2s ease; }

/* ----------------------------------------------------------- the program */

.ward-app .program-card { padding: 1.125rem 1.25rem 1.375rem; }
/* .program-title (the card's "Sacrament Meeting" heading) went in Round 378
   with its emitter. The card opens on the theme, which then sits at the
   card's own padding rather than a heading's distance below it. */
.ward-app .program-card > .prog-theme:first-child { margin-top: 0; }

.ward-app .stale-note {
  margin: 0.6rem 0 0;
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--muted);
}

/* text-wrap: balance on the program's centred words (Round 823): a line that
   has to break breaks near its middle, so a narrow phone reads ADMINISTRATION
   / OF THE SACRAMENT rather than stranding SACRAMENT on a line of its own. */
.ward-app .prog-theme { text-align: center; margin-top: 0.5rem; text-wrap: balance; }
/* The labels a step up from 10px at 800 to 11px at 700 (Round 823): the
   same colour and weight on the page, easier to read at arm's length. */
.ward-app .prog-theme-l {
  display: block;
  margin-bottom: 0.25rem;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
}
.ward-app .prog-theme em {
  font-family: var(--serif);
  font-size: 1.125rem;
  line-height: 1.35;
  color: var(--ink);
}
/* The theme's scripture, under its words (Round 823, themeParts in
   ward-page.js): Garamond's small capitals in the accent, an attribution
   rather than a second heading. */
.ward-app .prog-theme-ref {
  display: block;
  margin-top: 0.2rem;
  font-family: var(--serif);
  font-size: 0.9375rem;
  font-variant-caps: all-small-caps;
  letter-spacing: 0.07em;
  line-height: 1.35;
  color: var(--accent);
}

/* ---- The program as the ORDER OF SERVICE (Derek chose it from five
   mockups, Round 372): everything on the centre line -- a small label over
   each name, the hymn title in italic beneath its number, the officers as a
   credit block above a fleuron, the ceremonies set between rules. The
   sacrament, "the most important part of that whole meeting", is set a step
   up from Ward Business: its own rules above and below, the diamond, the
   deeper green, larger caps and more air -- a step, not a shout. ---- */
.ward-app .prog-list { margin-top: 1rem; text-align: center; }

.ward-app .prog-row { padding: 0.5rem 0 0.55rem; }

.ward-app .prog-label {
  display: block;
  margin-bottom: 0.15rem;
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}

/* The program's names -- speakers, hymn numbers, the officers -- in the
   display face like every other name on the page (Derek, Round 368; his
   Rounds 286 and 303 made the same call on the old page). */
.ward-app .prog-value {
  font-family: var(--display);
  font-size: 1.25rem;
  line-height: 1.2;
  color: var(--ink-strong);
  overflow-wrap: anywhere;
  text-wrap: balance;
}
.ward-app .prog-sub {
  display: block;
  margin-top: 0.15rem;
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.9375rem;
  line-height: 1.35;
  color: var(--muted);
  text-wrap: balance;
}

/* A hymn is a link to the Church's page for it (Round 455). It keeps the
   row's own inks -- the number in the strong ink, the title in the muted
   italic -- so the program still reads as a printed program; the one
   tell is a dotted rule under the title, going solid and accent under the
   pointer. The whole value is the target, which on a phone is the number
   and the title together. */
.ward-app .hymn-link { color: inherit; text-decoration: none; }
.ward-app .hymn-link .prog-sub {
  text-decoration: underline dotted;
  text-decoration-color: color-mix(in srgb, var(--accent) 55%, transparent);
  text-underline-offset: 0.18em;
}
.ward-app .hymn-link:focus-visible .prog-sub { text-decoration: underline solid; text-decoration-color: var(--accent); color: var(--accent); }
@media (hover: hover) {
  .ward-app .hymn-link:hover .prog-sub { text-decoration: underline solid; text-decoration-color: var(--accent); color: var(--accent); }
}
.ward-app .hymn-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

/* The officers are a credit block, and since Round 823 ONE block: a grid of
   two columns -- the labels, the names -- each as wide as its widest and
   left-aligned, the pair centred as one thing, each row on one baseline
   (Derek, Round 300: "all be in left alignment with each other"; the order
   of service had centred each row on its own, so every name began somewhere
   else). A row's two cells are the grid's own (display: contents), which
   holds only while every row carries both -- the renderer drops a label with
   no name. minmax(0, ...) lets a long name wrap in its column on a narrow
   phone rather than push past the card. */
.ward-app .prog-officers {
  display: grid;
  grid-template-columns: minmax(0, max-content) minmax(0, max-content);
  justify-content: center;
  align-items: baseline;
  column-gap: 0.75rem;
  row-gap: 0.4rem;
  text-align: left;
}
.ward-app .prog-row.is-officer { display: contents; }
.ward-app .prog-row.is-officer .prog-label { margin: 0; }
.ward-app .prog-row.is-officer .prog-value { font-size: 1.0625rem; }

/* The fleuron between the credits and the order of service. */
.ward-app .prog-sep {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0.7rem 0 0.55rem;
  color: var(--accent);
}
.ward-app .prog-sep::before,
.ward-app .prog-sep::after { content: ''; flex: 1; height: 1px; background: var(--line-strong); }
.ward-app .prog-sep i { display: block; width: 7px; height: 7px; background: currentColor; transform: rotate(45deg); }

/* A thing that HAPPENS -- Ward Business, a baby blessing -- is a line of
   small caps between two rules. */
.ward-app .prog-divider {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin: 0.35rem 0 0.5rem;
  padding: 0.3rem 0;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  text-align: center;
  text-wrap: balance;
  color: var(--forest);
}
.ward-app .prog-divider::before,
.ward-app .prog-divider::after { content: ''; flex: 1; height: 1px; background: var(--line-strong); }

/* The sacrament: its own rules, the diamond, the deeper green, a size up,
   more air. */
.ward-app .prog-divider.is-sacrament {
  display: block;
  margin: 0.9rem 0 0.95rem;
  padding: 0.85rem 0 0.9rem;
  border-top: 1px solid var(--line-strong);
  border-bottom: 1px solid var(--line-strong);
}
/* Neither of the ordinary divider's side rules: this block draws its own
   rules above and below the words. It carried a diamond above them from
   Round 372; Derek took it off in Round 375 -- the words carry the weight. */
.ward-app .prog-divider.is-sacrament::before,
.ward-app .prog-divider.is-sacrament::after { content: none; }
.ward-app .prog-divider.is-sacrament .prog-divider-t {
  font-size: 0.8125rem;
  font-weight: 800;
  letter-spacing: 0.2em;
  color: var(--forest);
}
/* SOMETHING ELSE ON THE PROGRAM -- a Primary program, a presentation -- typed
   on the conducting sheet. No side rules (Round 607, Derek: "there are these
   lines next to the title and I really don't like it"). A HEADING OF ITS OWN,
   A STEP UNDER THE SACRAMENT (Round 840, Derek: "a little more prominent ...
   Not quite as prominent as the administration of the sacrament"): at 12px in
   the labels' sans (Round 608) it read as a label whose name was missing. Now
   the page's heading voice -- Garamond's semibold capitals, the face of the
   tabs and the masthead -- at 16px in the forest ink, with air round it and
   no ornament; the sacrament keeps the weight, the width and the rules. True
   capitals at a set size, never small caps: the Garamond files carry no
   small-capital glyphs, so each browser would fake them its own way. A detail
   typed with it stands close beneath, a name under its heading. */
.ward-app .prog-divider.is-feature {
  display: block;
  margin: 1.4rem 0 0.95rem;
  padding: 0;
  font-family: var(--serif);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.125em;
  line-height: 1.3;
}
.ward-app .prog-divider.is-feature::before,
.ward-app .prog-divider.is-feature::after { content: none; }
.ward-app .prog-divider.is-feature + .prog-divider-d { margin: -0.8rem 0 0.95rem; line-height: 1.25; }
.ward-app .prog-divider-d {
  margin: -0.2rem 0 0.7rem;
  text-align: center;
  text-wrap: balance;
  font-family: var(--display);
  font-size: 1.125rem;
  color: var(--ink-strong);
}

.ward-app .after-card {
  margin-top: 1.125rem;
  padding-top: 0.95rem;
  border-top: 1px solid var(--line);
}
/* `.after-card strong` -- the AFTER SACRAMENT MEETING heading's small-caps
   rule -- stood here until Round 481. Written on the descendant it also
   dressed every bold run typed into the note (Round 478 gave that box the
   announcements' formatting), so "*Youth Sunday School:*" printed as a
   second green heading (Derek's screenshot); and then he took the heading
   off altogether ("just get rid of the title 'After sacrament meeting'
   completely"). ward-page.js emits no heading now, and a bold run inside
   the note is plain bold. */
/* A list typed into the note (Round 478 gave it the formatting bar) is set
   in the note's own type. The items were left on the page's sans at its
   own size, so a bullet read as a different font from the paragraph beside
   it (Round 531, Derek: "All the fonts should stay the same"). */
.ward-app .after-p,
.ward-app .after-card li {
  font-family: var(--serif);
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--body);
}
.ward-app .after-p { margin: 0 0 0.5rem; }
.ward-app .after-card > :last-child { margin-bottom: 0; }

.ward-app .nomeeting { text-align: center; padding: 0.75rem 0 0.25rem; }
.ward-app .nomeeting-title {
  margin: 0;
  font-family: var(--display);
  font-size: 1.5rem;
  color: var(--ink-strong);
}
.ward-app .nomeeting-sub {
  margin: 0.5rem auto 0;
  max-width: 22rem;
  font-family: var(--serif);
  font-size: 0.9375rem;
  color: var(--muted);
}
.ward-app .fleuron { color: var(--accent); margin: 1.1rem auto 0.9rem; }
.ward-app .fleuron svg { display: block; margin: 0 auto; }
.ward-app .nomeeting-thought { margin: 0 auto; max-width: 24rem; transition: opacity 0.17s ease; }
/* ANOTHER THOUGHT under the passage (Round 878, Derek): the day-thought box's
   control (.dt-again, below) and its fade; never in Leader Tools' replica,
   where ward.js's walk does not run. */
.ward-app .nomeeting-thought.is-swapping { opacity: 0; }
.ward-app .nm-again { margin-top: 1.1rem; }
body.leader .ward-app .nm-again { display: none; }
.ward-app .nomeeting-thought-text {
  margin: 0;
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.0625rem;
  line-height: 1.5;
  color: var(--ink);
}
.ward-app .nomeeting-thought-ref {
  margin: 0.5rem 0 0;
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

/* ---------------------------------------------------------- the bulletin */

.ward-app .bulletin { padding: 0.45rem 0.25rem 0; }

/* ONE LEFT EDGE (Round 825). The folds stood 4px inside the column, so their
   titles began 7px left of the cards' titles, their chevrons 7px right of the
   cards' chevrons, and the white cards they open 4px narrower than the
   notices' cards. Now the rules and the opened cards run the column's width,
   as the notices do, and the button's own sides are a card's: its 1px edge
   and its summary's padding (.event-summary), so a fold's title starts where
   Interviews starts and its chevron ends where every card's chevron ends. */
.ward-app .reminders {
  margin: 0.25rem 0 0;
  padding: 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
/* Two folds stacked read as one ruled list: the first's bottom rule is the
   divider. The folds carry no bottom margin, because the Announcements row
   (.ann-head, below) follows the last one as the third row of that list. */
.ward-app .reminders + .reminders { border-top: 0; }

/* THE HEIGHT OF A CARD (Round 752, Derek: the Birthdays and Missionaries
   rows "too tall" beside Interviews and Ward Survey): 2.8125rem, a closed
   card's 45px, the words centred by the padding; the type is unchanged. */
.ward-app .acc-btn {
  width: 100%;
  min-height: 2.8125rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.55rem calc(0.85rem + 1px) 0.55rem calc(0.75rem + 1px);
  box-sizing: border-box;
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
}
.ward-app .acc-title {
  font-family: var(--display);
  font-size: 1.3125rem;
  line-height: 1.1;
  color: var(--accent);
}
.ward-app .acc-btn .chev { color: var(--muted); }
/* How many the fold holds (Round 418, Derek): a quiet grey pill in the
   date badges' own face, hairline-edged, never a red dot -- nothing here
   is a notification (Round 18). margin-right: auto keeps it beside the
   title and leaves the chevron at the far edge. */
.ward-app .acc-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.55rem;
  height: 1.55rem;
  padding: 0 0.45rem;
  margin: 0 auto 0 -0.15rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-family: inherit;
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1;
  color: var(--muted);
  background: transparent;
}
/* Turns the way an event row's does (Round 376): right when shut, down
   when open. It was a down chevron flipping to up, the accordion idiom,
   which left the folds the odd ones out on a page whose announcements
   and groups all open in place under a right chevron. */
.ward-app .acc-btn[aria-expanded='true'] .chev-right { transform: rotate(90deg); }
.ward-app .acc-panel { padding: 0 0 0.75rem; }

/* Each item inside a fold is a card of its own (Round 418, Derek: "their
   own white box ... to differentiate it from the background color of the
   page"): the expanded event's own hairline and soft shadow on a white
   ground, small corners, and none of the event card's accent band. One
   card per Info notice, one for the week of birthdays, one per
   missionary. It was a ruled row (padding 0.85rem 0, a hairline above). */
.ward-app .rem-item {
  margin: 0.5rem 0 0;
  padding: 0.85rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--box); /* the opened-item off-white (Round 430; pure white in Round 423) */
  box-shadow: 0 7px 19px rgba(42, 38, 31, 0.035);
}
[data-theme='dark'] .ward-app .rem-item,
.ward-app.is-dark .rem-item { background: rgba(14, 39, 29, 0.8); box-shadow: none; }
/* A reminder's title is a notice title, so it is set like the event
   titles: the display face, regular weight (Round 368). */
.ward-app .rem-item > b {
  display: block;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.125rem;
  line-height: 1.2;
  color: var(--ink-strong);
}
/* .rem-h is gone (Round 412): it was the block heading inside the shared
   Birthdays & Missionaries fold (Rounds 368-369). Each block has a fold of
   its own now, whose title is the heading, so the blocks carry none and
   their first row sits at the panel's own padding. */
.ward-app .rem-birthdays > .rem-day:first-child { margin-top: 0; }
.ward-app .rem-missionaries > .rem-miss:first-child { margin-top: 0; }
/* .rem-empty is gone (Round 418): a fold with nothing in it is not drawn
   at all now, so the "Nothing posted here yet." line has no emitter. */
.ward-app .rem-scope {
  display: inline-block;
  margin: 0.25rem 0 0;
  padding: 0.05rem 0.5rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: 0.625rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.ward-app .rem-where {
  margin: 0.25rem 0 0;
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.875rem;
  color: var(--muted);
}
.ward-app .rem-text { margin-top: 0.25rem; }
/* A point up from 0.8125rem (Round 439, Derek's call, agreed): an expanded
   announcement's message is 0.9375rem, and these standing notices carry a
   link or a number to act on. One point keeps the fold a touch quieter
   than the list beneath it. */
.ward-app .rem-text p,
.ward-app .rem-text li { font-size: 0.875rem; line-height: 1.5; color: var(--muted); }
.ward-app .rem-text p { margin: 0 0 0.4rem; }
.ward-app .rem-text > :last-child { margin-bottom: 0; }
/* A web address in a standing notice is one unbreakable token (Round 416). */
.ward-app .rem-text a { overflow-wrap: anywhere; }

.ward-app .rem-day { margin: 0.4rem 0 0; font-size: 0.8125rem; line-height: 1.45; color: var(--body); }
/* 11px at 700, where it was 10px at 800 (Round 825): the program's labels'
   own step (Round 823). */
.ward-app .rem-when {
  display: block;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}
.ward-app .rem-when.is-today { color: var(--accent); }
/* The names take the display face like every other name on the page. */
/* Bold at Derek's word (Round 426): the display face has one cut, so this is
   the same synthesised 650 the card titles wear (Round 324). */
/* The announcement titles' own halfway bold (Round 514, Derek: "that same
   exact boldness"): weight 400 and a 0.35px stroke in the text's colour, in
   place of Round 426's synthesised 650. See .event-title for why a weight
   number cannot do it. */
.ward-app .rem-names { font-family: var(--display); font-weight: 400; -webkit-text-stroke: 0.35px currentColor; font-size: 1.125rem; color: var(--ink-strong); }
.ward-app .rem-name { display: inline-block; }
/* No mark on the person whose birthday is today (Derek, Round 370): the
   day label above them reads Today instead, and nothing else changes. */

/* rem-miss-*, not miss-*: the leader app still loads the old stylesheet,
   whose .miss-name carries a bold weight that was leaking into the replica.
   The weight is stated anyway. */
.ward-app .rem-miss { margin-top: 0.75rem; }
/* Bold at Derek's word (Round 426), and since Round 825 the birthday names'
   own halfway bold -- weight 400 and Round 514's 0.35px stroke -- where it was
   a synthesised 650: the Caslon has one weight, and the browser's made-up bold
   smeared the missionaries' names heavier than every other name on the tab. */
.ward-app .rem-miss-name {
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  -webkit-text-stroke: 0.35px currentColor;
  font-size: 1.125rem;
  line-height: 1.25;
  color: var(--ink-strong);
}
/* 14px, the notices' time and place (Round 825; 13px until then). */
.ward-app .rem-miss-mission,
.ward-app .rem-miss-email { margin: 0.1rem 0 0; font-size: 0.875rem; color: var(--muted); }
.ward-app .rem-miss-email a { color: var(--accent); overflow-wrap: anywhere; }
/* A MISSIONARY'S PLAQUE (Round 643, Derek): the whole plaque, never cropped,
   and a tap opens it full size (the lightbox, data-full). Since Round 890 it
   stands between the name and the email, at the left like the words, as
   wide as the card allows and at most 14rem tall -- a notice's lone
   picture's own limits (.ann-shots:not(.is-many)), and its 10px corner. It
   was a 4.5rem picture on the right, where on a phone it could only grow by
   breaking the address in two. A card without one is untouched. */
.ward-app .rem-miss-plaque { margin: 0.55rem 0 0.45rem; }
.ward-app .rem-miss-plaque:last-child { margin-bottom: 0; }
.ward-app .rem-miss-shot {
  display: block;
  max-width: 100%;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--card);
  overflow: hidden;
  line-height: 0;
  cursor: zoom-in;
}
.ward-app .rem-miss-shot img { display: block; width: auto; height: auto; max-width: 100%; max-height: 14rem; }
/* ITS ROOM IS HELD WHILE IT LOADS (Round 889's way, .hplate.is-sized): with
   its width and height known (ward.js sets --pw and --pr on the button), the
   frame is drawn at once at the size the loaded picture takes above -- its
   own width, the card's or 14rem of height, whichever is least, plus the 1px
   rim each side -- so the fold's glide measures the right height. */
.ward-app .rem-miss-shot.is-sized { width: min(100%, calc(var(--pw) + 2px), calc(14rem * var(--pr) + 2px)); }
.ward-app .rem-miss-shot.is-sized img { width: 100%; max-height: none; aspect-ratio: var(--pr); }

/* The third row: Announcements, the head of the events list (Round 373,
   Derek's pick). The folds' own voice -- the display face at the fold
   title's size, the same row height, the same inset -- but in ink rather
   than the accent, because this row is open rather than folded. The
   List / Calendar switch sits at its right as a small pill and the chips
   follow beneath, a size down. Both stand outside the two views, so
   switching to the calendar moves nothing above the grid. It replaced a
   full-width pair of underlined tabs, an ornament and a small-caps
   UPCOMING EVENTS label: five bands of chrome and no heading in them. */
.ward-app .ann-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 0.75rem;
  min-height: 3.6rem;
  padding: 0.7rem 0.25rem 0.65rem;
}
/* Without the word (Round 742) the row is the List / Calendar pill alone,
   at the right, with the chips beneath: no tall empty band where the
   heading stood. */
.ward-app .ann-head.no-title {
  min-height: 0;
  /* The room above the chips and the room below them SWAPPED (Round 745,
     Derek: first "as much space above them as exists below them", then
     "keep that same space above ... but reduce the space between the
     buttons and the lower line"): 27px from the folds' rule to the chips,
     6px from the chips to the first card (the list's head, below). Round 753
     brought the top down "a little bit", 27px to 18. */
  padding-top: 1.15rem;
  padding-bottom: 0;
  /* The chips and the switch share this one row whenever it fits (Round
     744, Derek), and the sizes below make sure it does on a 360px screen.
     When it does not -- a phone's text set larger, from about 1.05x on a
     360px phone, or a phone narrower than that -- the row WRAPS (Round 887,
     Derek: "yes, let the chips row wrap at large text"): the switch takes
     a line of its own at the left, and at the largest sizes the chips wrap
     among themselves too. Until then the row scrolled sideways and the
     switch slid off the screen. The lines stand far enough apart that no
     control's tap room (below) lies over the one above it. */
  flex-wrap: wrap;
  row-gap: max(0.5rem, calc(4px + max(0px, 44px - 2rem) / 2 + max(0px, 38px - 1.6rem) / 2));
  column-gap: 0.5rem;
  /* Level with the cards' edges at every width (Round 825), as a phone has
     had them since Round 744; a computer kept a 4px inset. */
  padding-left: 0;
  padding-right: 0;
}
/* A THUMB'S ROOM ON EVERY CONTROL IN THE ROW (Round 825): the chips are
   drawn 32px tall and List / Calendar 26, where 44 is a finger's size. Each
   answers a tap a little way above and below itself, half of what it lacks
   of 44px on each side, and nothing is drawn any larger; a chip grown to
   44px by a larger text size needs none. (Round 825 reached upward only,
   13 and 15px, because the row scrolled sideways and so clipped below it;
   Round 887's wrapping row clips nothing.) The chip's ::before is its
   check mark, so the reach is its ::after; the switch's reach starts at
   its pill's edge, 3px out. */
.ward-app .ann-head.no-title .filter,
.ward-app .ann-head.no-title .segmented button { position: relative; }
.ward-app .ann-head.no-title .filter::after { content: ''; position: absolute; inset: calc(-1px - max(0px, 44px - 2rem) / 2) -1px; }
.ward-app .ann-head.no-title .segmented button::before { content: ''; position: absolute; inset: calc(-3px - max(0px, 38px - 1.6rem) / 2) 0; }
/* The same room under the chips as between the cards (Round 747, Derek):
   the list's own gap. */
.ward-app .ann-head.no-title + .events-view .events { padding-top: 0.65rem; }
.ward-app .ann-head.no-title .filters {
  flex: 0 1 auto;
  flex-wrap: wrap;
  row-gap: max(0.4rem, calc(2px + max(0px, 44px - 2rem)));
  padding: 0;
}
.ward-app .ann-head.no-title .filter { white-space: nowrap; }
@media (max-width: 26rem) {
  .ward-app .ann-head.no-title { column-gap: 0.3rem; padding-left: 0; padding-right: 0; }
  .ward-app .ann-head.no-title .filters { column-gap: 0.25rem; }
  .ward-app .ann-head.no-title .filter { padding: 0.3rem 0.45rem; }
  .ward-app .ann-head.no-title .segmented { padding: 2px; }
  .ward-app .ann-head.no-title .segmented button { padding: 0.2rem 0.45rem; }
  .ward-app .ann-head.no-title .filters.is-cal .filter .mk { margin-right: 0.25rem; }
}
.ward-app .ann-title {
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.3125rem;
  line-height: 1.1;
  color: var(--ink-strong);
}

/* List / Calendar: a segmented pill the height of the chips beneath it,
   the chosen side filled from the same tokens the chips use, so the dark
   palette needs nothing of its own. Underlined tabs here read as a second
   navigation under the page's real tabs; a pill reads as a view switch. */
.ward-app .segmented {
  display: inline-flex;
  flex: none;
  padding: 3px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
}
.ward-app .segmented button {
  min-height: 1.6rem;
  padding: 0.2rem 0.7rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--muted);
  cursor: pointer;
}
.ward-app .segmented button.is-on {
  /* The chosen side in its own blue-green (Round 417, Derek), the three
     --seg-on-* tokens declared beside the palette in both themes: tint,
     ink and ring. Round 399 had it on --accent-soft-2 with the chips' own
     edge, so it read as on the way a chip does; he wanted it told apart
     from the chips. Text measured 5.5:1 on the tint in light, 7.4 in dark. */
  background: var(--seg-on-bg);
  color: var(--seg-on-ink);
  box-shadow: inset 0 0 0 1px var(--seg-on-line);
}

/* The scope chips, tucked under the heading they qualify: left-aligned
   with it and a size down (Round 373). A chip that is on keeps its check
   mark -- a filter should say what is included. */
.ward-app .filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  padding: 0 0.25rem 0.85rem;
}
.ward-app .filter {
  min-height: 2rem;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: transparent;
  font-size: 0.6875rem;
  font-weight: 700;
  color: var(--muted);
  cursor: pointer;
}
.ward-app .filter.is-on {
  background: var(--accent-soft);
  border-color: var(--accent-2);
  color: var(--accent);
}
.ward-app .filter.is-on::before { content: '\2713\00a0'; }
/* The chips wear the grid's own scope marks while the calendar is open
   (Round 446, Derek), in place of the legend that sat under the grid:
   the same three shapes, inline before the word, hidden in the list view
   where the rows carry no mark (Round 445). The check mark stays first. */
.ward-app .filter .mk { display: none; }
.ward-app .filters.is-cal .filter .mk { display: inline-block; margin-right: 0.35rem; vertical-align: -1px; }
/* In the calendar view the mark stands in the check's place (Round 750,
   Derek: with both, the chips grew and the List / Calendar switch slid off
   a phone's screen): an off chip keeps its mark, faded. */
.ward-app .filters.is-cal .filter.is-on::before { content: none; }
.ward-app .filters.is-cal .filter:not(.is-on) .mk { opacity: 0.35; }

/* .bulletin-divider (the line-diamond-line ornament between the chips and
   the list) went in Round 373 with its one emitter: it carried no
   information, and the Announcements heading is the divider now. */

/* EVERY ANNOUNCEMENT IS A CARD (Round 510, Derek's reference): the opened-
   item white on a hairline with rounded corners and a soft lift, the cards
   stacked with a gap between them rather than ruled off one another. Dark
   mode keeps the ground Round 430 gave an opened box, below. */
/* One column that never widens for what is inside it (Round 887): an auto
   column took the width of the widest card's contents, so with a phone's
   text set larger, or a card opened, every card grew past the screen's
   edge and lost its right side to the column's clip. */
.ward-app .events { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.65rem; padding-top: 0.85rem; }
.ward-app .event {
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--box);
  box-shadow: 0 8px 18px -14px rgba(42, 38, 31, 0.22);
  transition: border-color 0.15s ease;
}

.ward-app .event-summary {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.75rem 0.85rem 0.75rem 0.75rem;
  box-sizing: border-box;
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
/* .event-when (the day and date in their own column, Round 367; TODAY in
   it, Round 487) went in Round 502: the date is the first item of the
   green line under the title now, and Today there is bold. */
.ward-app .event-title {
  display: block;
  font-family: var(--display);
  /* One point up at Derek's word (Round 490): 1.25rem to 1.3125, and the
     phone override below 1.125 to 1.1875 with it. */
  font-size: 1.3125rem;
  /* HALFWAY BOLD (Round 514, Derek: "in between what it is now and what it
     was before"). Round 512 set 650; this cut has one weight, so the
     browser's synthesised bold is on or off, never graded -- measured in
     canvas ink at 19px, 400 and 525 are identical and 600 and 650 are both
     1.91x. So the weight stays 400 and a hairline stroke in the text's own
     colour thickens it: 0.35px gives 1.45x the ink, the midpoint to within
     half a percent. A stroke moves no advances and changes no layout, and
     currentColor follows the hover, the dark palette and print. */
  -webkit-text-stroke: 0.35px currentColor;
  line-height: 1.17;
  color: var(--title-ink);
  transition: color 0.15s ease;
  /* A title that needs two lines breaks near its middle (Round 825): at 360
     the Chili Cook-Off read "Annual Provo 1st Chili Cook-" over "Off". */
  text-wrap: balance;
}
/* Round 499: every hover shade on the ward's page sits inside
   @media (hover: hover). A phone treats a tap as a hover that stays until
   something else is tapped, so an opened announcement kept its green title
   (Derek). A mouse still gets the shade; keyboard focus keeps its own rules. */
@media (hover: hover) {
  .ward-app .event-summary:hover .event-title { color: var(--accent); }
}
/* THE LEADER APP'S ROW LINE (Round 502, Derek): calendar, clock and pin,
   each with its words, in the accent. The date and time never break inside
   themselves; a long place may wrap. */
/* THE HAIRLINE BETWEEN THE TIME AND THE PLACE (Round 510, the reference)
   never dangles at the start of a line. Every item carries the line at its
   left, the line of items is pulled 0.7rem left, and the wrapper clips at the
   column's edge -- so the first item on any line, including one that wrapped,
   has its hairline cut off. A divider drawn only BETWEEN items ended up alone
   at the head of the second line whenever a card's thumbnail made the time
   and place wrap. */
.ward-app .event-metawrap { display: block; overflow: hidden; margin-top: 0.35rem; }
.ward-app .event-meta {
  display: flex;
  flex-wrap: wrap;
  column-gap: 0.7rem;
  row-gap: 0.2rem;
  margin-left: -0.7rem;
  font-size: 0.875rem;
  line-height: 1.3;
  color: var(--body);
}
.ward-app .event-mi { display: inline-flex; align-items: center; gap: 0.35rem; white-space: nowrap; }
.ward-app .event-mi.is-place { white-space: normal; min-width: 0; }
.ward-app .event-mi .mi { width: 1.05rem; height: 1.05rem; flex: none; stroke-width: 1.7; color: var(--accent); }
/* The words in the ink and the icons in the accent (Round 510, the
   reference). .event-mi.is-today went with the date item: Today is in the
   date block now. */
.ward-app .event-mi { padding-left: 0.7rem; border-left: 1px solid var(--line-strong); }
.ward-app .event-summary .chev { flex: none; color: var(--accent); }

/* THE DATE BLOCK (Round 510): the month, the day in Caslon, the weekday --
   or TODAY on the day (Round 487's rule) -- on the mint tint, a picture of
   the date at the card's left. Absent on an undated notice. */
.ward-app .event-cal {
  flex: none;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 3.8rem;
  min-height: 4.5rem;
  padding: 0.45rem 0;
  box-sizing: border-box;
  border-radius: 12px;
  background: var(--accent-soft);
  text-align: center;
}
/* 11px, a step up from 10 (Round 825), as the program's labels went in
   Round 823: the smallest words on the Bulletin, read at arm's length. */
.ward-app .event-cal-m,
.ward-app .event-cal-w {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 1.2;
  text-transform: uppercase;
}
.ward-app .event-cal-m { color: var(--accent); }
.ward-app .event-cal-d {
  margin: 0.08rem 0 0.1rem;
  font-family: var(--display);
  font-size: 1.875rem;
  line-height: 1;
  color: var(--forest);
}
.ward-app .event-cal-w { color: var(--muted); }
.ward-app .event-cal.is-today .event-cal-w { font-weight: 800; color: var(--forest); }
.ward-app .event-copy { flex: 1 1 auto; min-width: 0; display: block; }
/* THE DATE GOES ABOVE THE TITLE AT A PHONE'S LARGEST TEXT (Round 887). Side
   by side, the block, the title and the arrow leave the words too little of
   the card once the column is under 14 times the text size (1.5x on a 360px
   phone): the title went a word to a line, and "10:00 AM", which never
   breaks, was cut off from about 1.6x and gone by 2x. Below that the block
   lies down as a band -- SEP 30 WED on one line, on its own mint -- with the
   arrow held at the band's right (a grid, so the arrow never drops to a line
   of its own; a band too wide for its room puts the weekday under the date),
   and the title, time and place take the card's whole width beneath. An
   undated notice has no block and keeps its row. */
@container wardcol (max-width: 14rem) {
  .ward-app .event:not(.is-undated) > .event-summary {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    row-gap: 0.55rem;
  }
  .ward-app .event:not(.is-undated) > .event-summary .event-cal {
    grid-area: 1 / 1;
    justify-self: start;
    align-self: center;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: 0.45rem;
    row-gap: 0;
    width: auto;
    max-width: 100%;
    min-height: 0;
    padding: 0.3rem 0.7rem;
  }
  .ward-app .event:not(.is-undated) > .event-summary .event-cal-d { margin: 0; font-size: 1.375rem; }
  .ward-app .event:not(.is-undated) > .event-summary .chev { grid-area: 1 / 2; }
  .ward-app .event:not(.is-undated) > .event-summary .event-copy { grid-area: 2 / 1 / 3 / 3; }
}
/* .event-sub stood here: Round 510's two-line preview of the words on a
   collapsed card. Gone (Round 513, Derek): a card shows none of its
   description until it is opened. */
/* .event-thumb stood here: Round 510's cover picture at the collapsed card's
   right, which Round 511 hid while the card was open. Gone (Round 516,
   Derek: "too visually busy"): the pictures show only in the opened card. */
.ward-app .event-summary[aria-expanded='true'] .chev-right { transform: rotate(90deg); }

/* THE OPEN CARD (Round 510). Round 448 made the opened row the white box,
   with a 5px accent band across its head; every card is that box now, so
   an open one only warms its edge toward the accent. The detail inside is
   transparent and edgeless, and the glide (Round 427) still animates its
   height. */
.ward-app .event.is-open { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.ward-app .event-detail {
  margin: 0;
  border: 0;
  background: transparent;
  /* Its fade-in is gone (Round 427): reveal() in ward.js glides the box
     open and shut, and a second fade on top of that read as a flicker. */
}
[data-theme='dark'] .ward-app .event,
.ward-app.is-dark .event { background: rgba(14, 39, 29, 0.8); box-shadow: none; }
.ward-app .event-accent { display: none; }
/* One column since Round 442: the box holds the description, the photos
   and the calendar links, and nothing the row above it already said. The
   date column, the repeated title, the long date, the time and the place
   went with the markup; their rules below have no emitter now. */
.ward-app .event-body {
  display: block;
  margin: 0 0.85rem;
  padding: 0.85rem 0 1rem;
  border-top: 1px solid var(--line);
}
/* In the words' own face since Round 825, as the list's empty line is. */
.ward-app .event-none { margin: 0; font-family: var(--serif); font-size: 0.9375rem; color: var(--muted); font-style: italic; }
/* `.event-meta .mk` stood here (Round 442): the month grid's shape after a
   row's time and place. Round 444 took the marks off the rows at Derek's
   word; the grid and its legend still wear .mk. */
.ward-app .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.ward-app .date-large { text-align: center; padding-top: 0.1rem; color: var(--ink-strong); }
.ward-app .date-large small {
  display: block;
  margin-bottom: 0.35rem;
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--accent);
}
.ward-app .date-large strong {
  display: block;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.9375rem;
  line-height: 0.95;
}
.ward-app .date-large span {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.625rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.ward-app .detail-title {
  margin: 0 0 0.4rem;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.5rem;
  line-height: 1.12;
  color: var(--ink-strong);
}
.ward-app .detail-date,
.ward-app .event-time,
.ward-app .event-place {
  margin: 0;
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.9375rem;
  line-height: 1.35;
  color: var(--ink-strong);
}
.ward-app .event-place { margin-top: 0.3rem; color: var(--muted); }
.ward-app .detail-rule { height: 1px; margin: 1.2rem 0 1.1rem; background: var(--line); }

/* A NOTICE'S WORDS IN THE PAGE'S READING FACE (Round 825): Garamond at the
   after-sacrament note's own size and ink (.after-p), where the prototype
   (Round 367) had set them in the system sans at 13.5px, the smallest reading
   text on the page. A notice now reads like the note under the program; its
   time and place, the labels and the buttons stay in the sans. `pretty`
   keeps a paragraph from ending on one short word where a browser can. */
.ward-app .event-description p,
.ward-app .event-description li {
  font-family: var(--serif);
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--body);
  text-wrap: pretty;
}
.ward-app .event-description p { margin: 0 0 0.6rem; }
.ward-app .event-description > :last-child { margin-bottom: 0; }
.ward-app .event-description a { overflow-wrap: anywhere; }
/* The page to read more on (Round 617): one short line under the words of an
   event the automatic check added. It is the page's link, not the notice's
   words, so it keeps the sans, at the time and place's 14px (Round 825). */
.ward-app .event-link { margin: 0.75rem 0 0; font-size: 0.875rem; line-height: 1.5; }
.ward-app .event-body > .event-link:first-child { margin-top: 0; }
.ward-app .event-link a { font-weight: 700; }

/* Lists typed into a notice (Round 210): a small indent, the marker quieter
   than the words, nested levels told apart by their marker. */
.ward-app .rem-text ul,
.ward-app .rem-text ol,
.ward-app .event-description ul,
.ward-app .event-description ol,
.ward-app .after-card ul,
.ward-app .after-card ol {
  margin: 0.3rem 0 0.6rem;
  padding-left: 1.35rem;
}
.ward-app .rem-text li,
.ward-app .event-description li,
.ward-app .after-card li { margin: 0 0 0.15rem; }
.ward-app .rem-text li::marker,
.ward-app .event-description li::marker,
.ward-app .after-card li::marker { color: var(--muted); font-size: 0.9em; }
.ward-app ul ul { list-style: circle; }
.ward-app ul ul ul { list-style: square; }
.ward-app ol ol { list-style: lower-alpha; }
.ward-app ol ol ol { list-style: lower-roman; }
.ward-app .ann-in1 { margin-left: 1.35rem; }
.ward-app .ann-in2 { margin-left: 2.7rem; }
.ward-app .ann-in3 { margin-left: 4.05rem; }
/* A line that introduces a list (Round 542, Derek: "the bullet points below it
   belong to that gospel doctrine text"). The renderer marks a paragraph with a
   list directly under it, no blank line between, as rt-lead; its gap goes and
   the list starts at the spacing its own items keep, so the heading and its
   bullets read as one thing, the way the Details box shows them. A blank line
   typed between the two still separates them, since that makes two blocks.
   Written after every paragraph and list rule above, at equal or higher
   specificity, so it wins in all three places notes are printed. */
.ward-app p.rt-lead { margin-bottom: 0; }
.ward-app p.rt-lead + ul,
.ward-app p.rt-lead + ol { margin-top: 0.15rem; }

/* THE ACTIONS ROW under an opened notice: Add to calendar (Round 672; I plan
   to attend stood first in it until Round 923, Derek: "Remove the 'I plan to
   attend' button for all announcements everywhere, always and forever"). */
.ward-app .event-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  margin-top: 1rem;
}
/* Add to calendar answers 44px of thumb, drawn at 36 (Round 825): 4px above
   and below the edge (5 from inside the 1px border, where an absolute box is
   measured). */
.ward-app .calbtn { position: relative; }
.ward-app .calbtn::before { content: ''; position: absolute; inset: -5px -1px; }

/* THE NOTICE'S BUTTON (Round 655, Derek: an action link "as a button pill",
   "classy and professional and engaging", blue -- "I don't want you to make
   it look really splotchy and overkill"). One per notice, under the words
   and above any pictures (Round 656). The words in the page's cream and
   its sans at the calendar button's weight, one small drawn glyph saying
   "opens a page" or "starts a text", a keyboard's focus a ring clear of
   the pill. Full width on a phone (below), its own width on a computer.
   Always an <a>: it navigates.
   HARBOR, IN GLASS (Round 657, Derek's pick of fifteen drawn for him: "Go
   with 13", and "make the button slightly smaller"). A glossy fill in --act
   -- a highlight along the top, a deeper shade at the foot, a shadow in its
   own blue -- with the glyph in a small frosted circle at the right end.
   Drawn at 40px rather than Round 655's 44, the words a point smaller; the
   tap target stays 44px tall through the ::before below, since a thumb is
   no smaller. */
.ward-app .event-act { margin: 1rem 0 0; }
/* A notice's Button alone at the top of the Bulletin, above the Birthdays
   fold (Round 741, Derek: the Tithing Declaration pill "right above the
   birthday row" and its card gone). The pill is the card's own; only the
   room around it is set here. */
/* The cards' own gap between the last pinned card and the Birthdays rule
   (Round 752); the folds' 0.25rem above collapses into it. */
.ward-app .bulletin-top { margin: 0.35rem 0 0.65rem; }
/* Centred up here (Round 744, Derek), whatever the pill does in a card. */
/* The block's OWN pills only (the > child rules, Round 748, Derek: left-align
   a pinned card's "Text ..." button "but keep the tithing declaration button
   centered"): a pill inside a pinned card keeps the card's look, at the
   left of its line. */
.ward-app .bulletin-top > .event-act { margin: 0.6rem 0 0; text-align: center; }
.ward-app .bulletin-top > .event-act > .event-action { margin-left: auto; margin-right: auto; }
.ward-app .bulletin-top > .event-act:first-child { margin-top: 0; }
/* The permanent notices under the buttons (Round 743), a little clear of a
   button above. */
.ward-app .bulletin-top .bulletin-pinned { padding-top: 0; }
.ward-app .bulletin-top > .event-act + .bulletin-pinned { margin-top: 0.9rem; }
/* THE PERMANENT NOTICES WEAR THE FOLDS' DRESS (Round 846, Derek: "make the
   interviews and ward survey tabs look more like the birthdays and
   missionary tabs, since they are permanent ... that would flow better").
   Interviews, the Ward Survey, Birthdays and Missionaries are one ruled list
   of standing things above the chips, and a card means one thing again: a
   notice in the list below. Each stays a notice underneath -- its markup,
   and ward.js opening it -- and changes only its dress: no box, the folds'
   hairlines (the last one the Birthdays fold's own, has-pinned), their 45px
   row and edges, the title in their green at their size, the chevron in
   their grey. Opened, its words stand in a white card under the row, as a
   fold's birthdays and missionaries do (.rem-item's own card). */
.ward-app .bulletin-top.has-pinned { margin-bottom: 0; }
.ward-app .bulletin-top.has-pinned + .reminders { margin-top: 0; border-top: 0; }
.ward-app .bulletin-top .bulletin-pinned { gap: 0; border-top: 1px solid var(--line); }
.ward-app .bulletin-pinned > .event,
[data-theme='dark'] .ward-app .bulletin-pinned > .event,
.ward-app.is-dark .bulletin-pinned > .event {
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.ward-app .bulletin-pinned > .event.is-open { border-color: var(--line); }
.ward-app .bulletin-pinned .event-summary {
  min-height: 2.8125rem;
  padding: 0.55rem calc(0.85rem + 1px) 0.55rem calc(0.75rem + 1px);
}
.ward-app .bulletin-pinned .event-title {
  font-size: 1.3125rem;
  line-height: 1.1;
  color: var(--accent);
  -webkit-text-stroke: 0;
}
.ward-app .bulletin-pinned .event-summary .chev { color: var(--muted); }
.ward-app .bulletin-pinned .event-body {
  margin: 0 0 0.75rem;
  padding: 0.85rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--box);
  box-shadow: 0 7px 19px rgba(42, 38, 31, 0.035);
}
[data-theme='dark'] .ward-app .bulletin-pinned .event-body,
.ward-app.is-dark .bulletin-pinned .event-body { background: rgba(14, 39, 29, 0.8); box-shadow: none; }
.ward-app .event-action {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.65rem;
  box-sizing: border-box;
  min-height: 2.5rem;
  min-width: 10rem;
  padding: 0.3rem 0.35rem 0.3rem 1.2rem;
  border: 0;
  border-radius: 999px;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--act) 90%, white) 0%,
    var(--act) 50%,
    color-mix(in srgb, var(--act) 84%, black) 100%);
  color: var(--card);
  box-shadow:
    inset 0 1px 0 var(--act-hi),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    0 8px 16px -9px color-mix(in srgb, var(--act) 75%, transparent);
  font-family: var(--sans);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.012em;
  line-height: 1.2;
  text-decoration: none;
  text-align: center;
  /* Android's grey tap flash would cover the press below. */
  -webkit-tap-highlight-color: transparent;
  transition: transform 160ms ease, box-shadow 200ms ease;
}
.ward-app .event-action::before { content: ''; position: absolute; inset: -2px 0; }
.ward-app .event-action-chip {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background: var(--act-chip);
  box-shadow: inset 0 0 0 1px var(--act-rim);
  transition: transform 220ms cubic-bezier(0.2, 0.7, 0.2, 1);
}
.ward-app .event-action .act-ico { width: 0.9rem; height: 0.9rem; flex: none; stroke-width: 2.1; }
/* A POINTER lifts it a hair, deepens its shadow, and tips the glyph. */
@media (hover: hover) {
  .ward-app .event-action:hover {
    transform: translateY(-1px);
    box-shadow:
      inset 0 1px 0 var(--act-hi),
      inset 0 -1px 0 rgba(0, 0, 0, 0.18),
      0 13px 22px -10px color-mix(in srgb, var(--act) 85%, transparent);
  }
  .ward-app .event-action:hover .event-action-chip { transform: translateX(2px) rotate(-8deg); }
}
/* A PRESS -- a finger, which has no hover, as well as a mouse -- sinks it a
   little and tips the glyph the same way (Derek: "when they press down on it,
   I would love for that button to suppress a little bit and for that little
   message icon to rotate a little bit"). Quick going in, so even a short tap
   shows it; it eases back at the ordinary pace. An iPhone shows :active only
   while the page has a touch listener, which ward.js adds. */
/* .is-pressed is the same look, held by ward.js for a moment before the
   link is followed (Round 754). */
.ward-app .event-action:active,
.ward-app .event-action.is-pressed {
  transform: translateY(1px) scale(0.97);
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.22);
  transition-duration: 70ms;
}
/* THE CIRCLE'S TURN IS MEANT TO BE SEEN (Round 666, Derek: "a little bit
   slower so they can actually see the little message icon to the right
   rotate. It just seems to go too fast"). A tap holds the button for a
   tenth of a second or so, so the turn still goes IN quickly -- a slow
   turn-in would never reach its angle under a quick finger -- but it turns
   further, to -22° and a shade larger, and under a finger (hover: none,
   below) it comes BACK over half a second with a small swing past upright:
   the motion the eye catches once the finger has lifted. A mouse keeps
   Round 657's pace. */
.ward-app .event-action:active .event-action-chip,
.ward-app .event-action.is-pressed .event-action-chip { transform: rotate(-22deg) scale(1.08); transition-duration: 90ms; }
@media (hover: none) {
  .ward-app .event-action { transition: transform 260ms ease, box-shadow 260ms ease; }
  .ward-app .event-action-chip { transition: transform 520ms cubic-bezier(0.3, 1.35, 0.5, 1); }
}
.ward-app .event-action:focus-visible { outline: 3px solid var(--act); outline-offset: 3px; }
/* Dark mode: --act is pale there, so the words take the page's dark ground. */
[data-theme='dark'] .ward-app .event-action,
.ward-app.is-dark .event-action { color: var(--bg); }
/* Without motion, a press still answers -- the shadow sinks -- but nothing
   moves or turns. */
@media (prefers-reduced-motion: reduce) {
  .ward-app .event-action,
  .ward-app .event-action-chip { transition: none; }
  .ward-app .event-action:hover,
  .ward-app .event-action:active,
  .ward-app .event-action.is-pressed,
  .ward-app .event-action:hover .event-action-chip,
  .ward-app .event-action:active .event-action-chip,
  .ward-app .event-action.is-pressed .event-action-chip { transform: none; }
}

/* Flyers on a notice: a row that scrolls sideways and never wraps. */
.ward-app .ann-shots {
  display: flex;
  gap: 0.5rem;
  margin: 0.9rem 0 0;
  overflow-x: auto;
  scrollbar-width: thin;
}
.ward-app .ann-shot {
  flex: none;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--card);
  overflow: hidden;
  cursor: zoom-in;
}
.ward-app .ann-shot img { display: block; width: 6.25rem; height: 6.25rem; object-fit: cover; }
/* A LONE PICTURE FITS THE CARD WHOLE (Round 640, Derek: a wide one scrolled
   sideways under a bar -- "that's silly. You should just resize the picture to
   fully fit"). The tile is a flex item that never shrinks, so its picture's
   max-width: 100% was measured against a tile as wide as the picture itself;
   capping the TILE at the row's width is what makes the picture scale down to
   the card. Tapping it still opens the full picture in the lightbox. */
.ward-app .ann-shots:not(.is-many) .ann-shot { max-width: 100%; min-width: 0; }
.ward-app .ann-shots:not(.is-many) .ann-shot img { width: auto; max-width: 100%; height: auto; max-height: 14rem; }
/* A PDF in the strip (Round 488): the same tile, drawn as a link that opens
   the file, with a small mark in the corner so a reader knows the tap
   leaves the page for a document rather than opening a picture. */
.ward-app .ann-shot.is-pdf { position: relative; display: block; cursor: pointer; text-decoration: none; }
.ward-app .ann-pdf-tag {
  position: absolute;
  right: 0.35rem;
  bottom: 0.35rem;
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--card);
  font-family: var(--body);
  font-size: 0.625rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  line-height: 1.4;
}

/* The two calendar links as they ship, and the one button calendar.js
   folds them into. */
.ward-app .ann-cal {
  margin: 0;
  font-size: 0.75rem;
  color: var(--muted);
}
.ward-app .ann-cal a { font-weight: 700; }
.ward-app .ann-cal-sep { margin: 0 0.4rem; }
.ward-app .ann-cal.is-folded,
.ward-app .wardcal-links.is-folded { position: relative; }

.ward-app .calbtn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 2.25rem;
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--accent);
  font-size: 0.78125rem; /* 12.5px (Round 825) */
  font-weight: 700;
  letter-spacing: 0.01em;
  cursor: pointer;
}
@media (hover: hover) { .ward-app .calbtn:hover { background: var(--accent-soft); } }
.ward-app .calbtn-words { text-decoration: none; }
.ward-app .calbtn::after { content: '\25BE'; font-size: 0.8em; transition: transform 120ms ease; }
.ward-app .calbtn[aria-expanded='true']::after { transform: rotate(180deg); }

.ward-app .calmenu {
  display: block;
  margin-top: 0.5rem;
  padding: 0.25rem;
  max-width: 15rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow);
  text-align: left;
}
.ward-app .calmenu .calmenu-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.5rem 0.55rem;
  border: 0;
  border-radius: 8px;
  background: none;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink-strong);
  text-decoration: none;
  cursor: pointer;
}
.ward-app .calmenu .calmenu-item:focus-visible { background: var(--accent-soft); }
@media (hover: hover) { .ward-app .calmenu .calmenu-item:hover { background: var(--accent-soft); } }
.ward-app .calicon { width: 1.15em; height: 1.15em; flex: none; }
/* The line that asks for a second tap after Google's app opened from closed (calendar.js, Round 635). */
.ward-app .calmenu-note { display: block; margin-bottom: 0.25rem; padding: 0.3rem 0.5rem 0.5rem; border-bottom: 1px solid var(--line); font-size: 0.8125rem; line-height: 1.4; color: var(--muted); }
.ward-app .calmenu-copy { display: block; margin-top: 0.25rem; padding-top: 0.25rem; border-top: 1px solid var(--line); }
.ward-app .calmenu-address { display: block; padding: 0.25rem 0.5rem; font-size: 0.75rem; color: var(--muted); word-break: break-all; }
.ward-app .wardcal-links .calmenu { margin-inline: auto; }

/* The month grid. */
.ward-app .calendar-view { padding-top: 0.6rem; border-top: 1px solid var(--line); }
.ward-app .cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.7rem;
  padding: 0.2rem 0.125rem 0.3rem;
}
.ward-app .cal-step {
  position: relative;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: transparent;
  color: var(--accent);
  font-size: 1.35rem;
  line-height: 1;
  cursor: pointer;
}
/* 44px to a thumb, the 36px circle drawn as before (Round 825). */
.ward-app .cal-step::before { content: ''; position: absolute; inset: -5px; border-radius: 50%; }
.ward-app .cal-head strong {
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.5rem;
  color: var(--ink-strong);
}
/* Seven columns that never widen for a day (Round 887): with a phone's text
   set larger, 1fr columns grew to the day's number and its circle, and the
   week ran off the right edge from 1.25x -- Saturday first, Friday by 2x. A
   day drops the button's own side padding and its circle shrinks to the
   column, below. */
.ward-app .cal-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 4px;
  text-align: center;
}
.ward-app .cal-grid .dow {
  padding: 0.3rem 0;
  font-size: 0.625rem;
  font-weight: 700;
  color: var(--muted);
}
.ward-app .day {
  position: relative;
  height: 2.75rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.15rem;
  border: 0;
  padding-inline: 0;
  border-radius: 13px;
  background: transparent;
  font-size: 0.8125rem;
  color: var(--ink-strong);
  cursor: pointer;
}
.ward-app .day.is-dim { opacity: 0.35; cursor: default; }
/* Today wears a filled disc behind its number, the mark every phone
   calendar uses for the current date (Round 431, Derek: "it needs to be
   more obvious what the current date is"). It was bold green digits alone,
   which is the same voice an event-marked day speaks in. The number is the
   card colour on the accent: cream on forest in light, the dark ground on
   the pale accent in dark, one rule for both. The tapped day keeps its
   ring, so today-and-tapped is the disc inside the ring. */
.ward-app .day .num {
  display: flex;
  align-items: center;
  justify-content: center;
  /* 1.6rem, or the column's width when that is less (Round 887). */
  width: min(1.6rem, 100%);
  height: 1.6rem;
  border-radius: 50%;
}
@supports (aspect-ratio: 1) {
  .ward-app .day .num { height: auto; aspect-ratio: 1; }
}
.ward-app .day.is-today .num { background: var(--accent); color: var(--card); font-weight: 800; }
.ward-app .day.is-selected { outline: 2px solid var(--accent); outline-offset: -2px; }
/* `.daycount` stood here (Round 442): an accent pill with the tapped
   day's total. Round 445 took it off at Derek's word ("that's terrible");
   a scope with more than one event that day says so beside its own mark
   instead -- see .mkn below. */
@media (hover: hover) { .ward-app .day:hover:not(.is-dim) { background: var(--accent-soft); } }
/* The scope marks under a day: three shapes in three colours, big enough
   to tell apart at a glance (Derek, Round 371). The legend reuses the same
   classes, so it cannot drift from the grid. */
.ward-app .day .marks { display: flex; gap: 4px; height: 9px; }
/* A scope's count beside its mark (Round 445): a small superscript to the
   upper right of the dot when that scope has two or more that day, in the
   ink so it reads against any of the three colours. Above the dot it runs
   into the day's number (measured 4.6px of overlap), so it sits beside.
   A wrap with a count keeps 6px more room, or the digit lands on the next
   scope's mark. */
.ward-app .mkwrap { position: relative; display: block; width: 9px; height: 9px; }
.ward-app .mkwrap.has-n { margin-right: 6px; }
.ward-app .mkn { position: absolute; top: -3px; left: 10px; font-size: 0.5rem; font-weight: 800; line-height: 1; color: var(--ink-strong); }
.ward-app .mk { display: block; width: 9px; height: 9px; }
.ward-app .mk-ward { border-radius: 50%; background: var(--mk-ward); }
.ward-app .mk-stake { background: var(--mk-stake); transform: rotate(45deg) scale(0.82); }
.ward-app .mk-church { background: var(--mk-church); border-radius: 1.5px; }
/* `.cal-legend` stood here: the three shapes named under the grid. Round
   446 took it off at Derek's word; the chips above the grid carry the
   marks instead (see .filters.is-cal). */
.ward-app .selected-date { margin-top: 0.9rem; padding: 0.9rem 0.125rem 0; border-top: 1px solid var(--line); }
.ward-app .selected-date h4 {
  margin: 0 0 0.5rem;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.5rem;
  color: var(--ink-strong);
}
/* The day list's own line in the list's empty voice (Round 825): the serif
   italic of .empty-note, set at the left under the day. */
.ward-app .sel-empty { margin: 0; font-family: var(--serif); font-style: italic; font-size: 0.9375rem; color: var(--muted); }
/* A day with nothing on it lends the next day's rows under that line
   (Round 825, ward.js paintSelected): the list's gap above the first. */
.ward-app .sel-empty + .event { margin-top: 0.65rem; }
/* The day list holds the real event rows (Round 371), so they take the
   list's own rules; only the rule above the first one is needed here. The
   old .sel-ev button rows are gone with their builder. */
.ward-app .sel-list .event + .event { margin-top: 0.65rem; }

.ward-app .wardcal {
  margin: 2rem 0 0;
  padding: 1.25rem 0.5rem 0;
  border-top: 1px solid var(--line);
  text-align: center;
}
.ward-app .wardcal p { margin: 0 auto; max-width: 28rem; }
.ward-app .wardcal-ask { font-size: 0.875rem; font-weight: 500; color: var(--ink); }
.ward-app .wardcal-note {
  margin-top: 0.4rem;
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.75rem;
  color: var(--muted);
}
.ward-app .wardcal-links { margin-top: 0.7rem; font-size: 0.8125rem; color: var(--muted); }
.ward-app .wardcal-links a { font-weight: 700; }
.ward-app .wardcal-sep { margin: 0 0.4rem; }

/* ------------------------------------------------------------ the groups */

/* Round 383: the paragraph alone -- the "Find Your People" heading and its
   rule came off at Derek's word -- so the card is the standard card and the
   paragraph carries no margin of its own. Round 374's centring went with
   the heading it centred. */
.ward-app .intro-card .subtitle { margin: 0; }
.ward-app .group-list { padding: 0 0.875rem; }
.ward-app .group { border-bottom: 1px solid var(--line); }
.ward-app .group:last-child { border-bottom: 0; }

.ward-app .group-row {
  width: 100%;
  min-height: 3.25rem;
  display: grid;
  /* minmax(0, ...) so a long time and place shortens itself with an
     ellipsis rather than push the chevron off the card. */
  grid-template-columns: minmax(0, 1fr) 1.25rem;
  /* The chevron keeps to the name's line (below), so an opened group's
     longer words run on under the name with the chevron still beside it. */
  align-items: start;
  gap: 0.75rem;
  padding: 0.875rem 0.25rem;
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ward-app .group-copy { display: block; min-width: 0; }
.ward-app .group-name { display: block; font-family: var(--display); font-size: 1.125rem; line-height: 1.25; color: var(--ink-strong); }
/* WHEN AND WHERE, UNDER THE NAME (Round 833): a notice's time-and-place line
   -- the sans, a size down, the body ink -- at most two lines while the row
   is shut, finished with an ellipsis when it is longer, and whole once
   opened. */
.ward-app .group-meets {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  margin-top: 0.2rem;
  font-size: 0.875rem;
  line-height: 1.4;
  color: var(--body);
  /* No last word alone on the second line ("room"), where it can be helped. */
  text-wrap: pretty;
}
.ward-app .group-row[aria-expanded='true'] .group-meets { display: block; -webkit-line-clamp: none; line-clamp: none; overflow: visible; }
/* 0.075rem down centres it on the name's first line (measured to half a
   pixel at 375 and 1024). */
.ward-app .group-row .chev { margin-top: 0.075rem; color: var(--accent); }
.ward-app .group-row[aria-expanded='true'] .chev-right { transform: rotate(90deg); }

/* An opened group stands in the same box as an opened announcement or a
   fold card (Round 430, Derek: "apply the same white box around the
   expanded groups tabs"): the same hairline, corners, off-white and soft
   shadow. It was bare text under the row (padding 0 0.25rem 1rem). The
   margin below keeps it clear of the group's own bottom rule. */
.ward-app .group-detail {
  margin: 0 0 0.9rem;
  padding: 0.85rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--box);
  box-shadow: 0 7px 19px rgba(42, 38, 31, 0.035);
}
[data-theme='dark'] .ward-app .group-detail,
.ward-app.is-dark .group-detail { background: rgba(14, 39, 29, 0.8); box-shadow: none; }
/* Who to text (Round 833): the notices' own Button (.event-action, Harbor
   blue, the bubble in its frosted circle), with the number under it in
   plain words -- on a computer a text link goes nowhere, and the number is
   what they need -- set in from the pill's edge to its words. Under it on
   every group, however long the name, so no two differ. */
.ward-app .group-act {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  margin: 0;
}
.ward-app .group-num {
  padding-left: 1.2rem;
  font-size: 0.875rem;
  color: var(--muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* A phone or tablet texts from the button itself, so the number under it
   only repeated it (Round 834, Derek: "if you already have the text ...
   button, what's the point in showing his number below the button?"), as
   the Bulletin's own Text buttons show none. A computer keeps
   it: a text link there opens nothing, or a box asking for an app. Asked
   of the pointer, not the width, so a narrow window on a computer keeps it. */
@media (hover: none) and (pointer: coarse) {
  .ward-app .group-num { display: none; }
}
.ward-app .group-led { margin: 0; font-size: 0.875rem; line-height: 1.45; color: var(--body); }
.ward-app .group-none { margin: 0; font-family: var(--serif); font-style: italic; font-size: 0.9375rem; color: var(--muted); }

.ward-app .gstart { margin-top: 0.875rem; }
/* "Create a Group" is a centred outlined pill sized to its words (Round 457,
   Derek): drawn as a full-width row it read as a sixth group. It is the
   Add-to-calendar pill's own recipe a size up -- the sans, the strong
   hairline, the accent -- outlined rather than filled so it does not shout
   over the groups themselves. .join-note is the invitation beneath it, when
   the bishopric writes one (empty since Round 454). */
.ward-app .join-btn {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  width: fit-content;
  margin: 1rem auto 0;
  min-height: 2.75rem;
  padding: 0.6rem 1.35rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--accent);
  font-size: 0.8125rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
}
@media (hover: hover) { .ward-app .join-btn:hover { background: var(--accent-soft); } }
.ward-app .join-plus { font-size: 1.25em; line-height: 1; font-weight: 600; }
.ward-app .join-note { margin: 0.6rem auto 0; max-width: 24rem; text-align: center; font-size: 0.875rem; line-height: 1.55; color: var(--muted); }

.ward-app .gform {
  margin-top: 0.75rem;
  padding: 1rem 1.125rem 1.125rem;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--card);
}
/* The form's name at its head (Round 833), in the thank-you's own dress. */
.ward-app .gform-title { margin: 0; font-family: var(--display); font-size: 1.25rem; font-weight: 400; line-height: 1.2; color: var(--ink-strong); }
.ward-app .gform-lead { margin: 0.3rem 0 0.5rem; font-size: 0.8125rem; line-height: 1.5; color: var(--muted); }
.ward-app .form-field { display: block; margin: 0.75rem 0; }
.ward-app .form-field span {
  display: block;
  margin-bottom: 0.35rem;
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
.ward-app .form-field em { font-style: normal; text-transform: none; letter-spacing: 0; font-weight: 500; opacity: 0.8; }
.ward-app .form-field input,
.ward-app .form-field textarea {
  width: 100%;
  padding: 0.75rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--ink-strong);
  font-size: 1rem;
  outline: none;
}
.ward-app .form-field input:focus { border-color: var(--accent-2); }
/* The pair's boxes keep the form's one gap (Round 833). A grid's items never
   share their margins with each other or with the box above, so each field's
   0.75rem was being added to the grid's own gap: the space above Who runs it
   was twice the form's and above Number to text three times, on a phone. */
.ward-app .form-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0.75rem; margin: 0.75rem 0; }
.ward-app .form-row .form-field { margin: 0; }
.ward-app .gform-err { margin: 0.25rem 0 0; font-size: 0.8125rem; color: var(--danger); }
.ward-app .gform-err:empty { display: none; }
.ward-app .gform-acts,
.ward-app .gconfirm-acts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.5rem; margin-top: 0.75rem; }
.ward-app .btn-primary {
  min-height: 2.75rem;
  padding: 0.7rem 1.1rem;
  border: 0;
  border-radius: 13px;
  background: var(--accent);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 800;
  cursor: pointer;
}
.ward-app .btn-primary:disabled { opacity: 0.6; cursor: default; }
.ward-app.is-dark .btn-primary,
[data-theme='dark'] .ward-app .btn-primary { color: #071610; }
.ward-app .btn-quiet {
  min-height: 2.75rem;
  padding: 0.7rem 1rem;
  border: 1px solid var(--line-strong);
  border-radius: 13px;
  background: transparent;
  color: var(--muted);
  font-size: 0.875rem;
  font-weight: 700;
  cursor: pointer;
}
.ward-app .gconfirm { margin-top: 0.9rem; padding-top: 0.9rem; border-top: 1px solid var(--line); }
.ward-app .gconfirm-q { margin: 0; font-family: var(--serif); font-size: 1.0625rem; color: var(--ink-strong); }
.ward-app .gconfirm-p { margin: 0.3rem 0 0; font-size: 0.8125rem; color: var(--muted); }
.ward-app .gthanks { margin-top: 0.75rem; padding: 1rem 1.125rem; text-align: center; }
.ward-app .gthanks-h { margin: 0.5rem 0 0; font-family: var(--display); font-size: 1.25rem; color: var(--ink-strong); }
.ward-app .gthanks-p { margin: 0.4rem 0 0; font-size: 0.8125rem; color: var(--muted); }
/* The thanks takes the focus once a group is sent, with no ring on words
   that are not a control; Send it without them dims while it sends (Round 942). */
.ward-app .gthanks:focus { outline: none; }
.ward-app .gconfirm-acts .btn-quiet:disabled { opacity: 0.6; cursor: default; }

/* ----------------------------------------------------------- the history */

/* ONE INK (Round 293's grey-sepia over every photograph, so an 1852
   painting and a 2025 snapshot read as one archive), written once since
   Round 835: the carousel cards had drifted to a lighter mix than the
   chapter plates, so a painting was greener on its card than inside. The
   bishops' portraits keep their own full grey, on purpose. */
.ward-app { --h-ink: grayscale(0.8) sepia(0.12); }

/* Round 383: the History tab opens on the chapters. The heading card
   ("One of Provo's Four Original Wards" over the founding paragraph) came
   off at Derek's word; .history-intro survives only as the card around the
   gathering note on a ward with no chapters yet. */
.ward-app .history-intro { text-align: center; padding: 1.125rem 1.125rem 1rem; }
/* The editor's "opening words", when there are any: a quiet lead above the
   cards -- no heading, no card -- set left at the column's edge, its first
   line standing the same 1.375rem off the tab row that the section head
   does (0.875rem here plus the paragraph's own 0.5rem). */
.ward-app .history-lead { text-align: left; margin-top: 0.875rem; }
/* A list among the opening words is set in their type (Round 531). */
.ward-app .history-lead p,
.ward-app .history-lead li {
  font-family: var(--serif);
  font-size: 0.9375rem;
  line-height: 1.52;
  color: var(--body);
}
.ward-app .history-lead p { margin: 0.5rem 0 0; }
.ward-app .history-lead ul,
.ward-app .history-lead ol { margin: 0.5rem 0 0; padding-left: 1.35rem; }

.ward-app .history-explore-head { margin-top: 1.375rem; margin-bottom: 0.625rem; }
/* THE CAROUSEL, BACK AND DONE PROPERLY (Round 443, Derek). Round 438 had
   made the chapters a vertical list, which fixed the old carousel's
   faults (a near-square crop, one card in view, nothing saying there were
   five) and lost the page-turning feel he liked. Now: cards centred on a
   snapping track with both neighbours peeking in from the edges, a 16:10
   band, a "1 of 5" and dots beneath, arrows where there is no swipe, and
   a contents list under it all so nothing is hidden from a reader who
   never swipes. */
.ward-app .history-explore-head .carousel-pos {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}
.ward-app .history-carousel { position: relative; }
.ward-app .history-thumbs {
  display: flex;
  gap: 0.75rem;
  /* The inset on both sides is what lets the first and last cards sit
     centred too, and what the neighbours peek through. A card is 100% of
     the CONTENT box (the width less both insets), so centring one leaves
     exactly one inset each side: the gap plus 28px of the neighbour. The
     first cut subtracted the inset from the card as well and the outer
     two cards could never reach the centre. */
  /* Top and bottom room for the focus ring and the card's shadow, which the
     scrolling track clips (Round 835: the 0.75rem under the card cut its
     20px shadow into a hard pale shelf); the negative margin gives the
     extra back so the dots sit where they did. */
  padding: 0.375rem 2.5rem 1.75rem;
  margin-bottom: -1rem;
  scroll-padding-inline: 2.5rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-inline: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.ward-app .history-thumbs::-webkit-scrollbar { display: none; }
/* Two circles at the height of the picture, for a pointer; a touch
   screen swipes and never sees them. */
.ward-app .car-arrow {
  position: absolute;
  top: 5.2rem;
  width: 2.25rem;
  height: 2.25rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: var(--card);
  color: var(--accent);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--card-shadow);
  z-index: 2;
}
.ward-app .car-prev { left: 0.2rem; }
.ward-app .car-next { right: 0.2rem; }
.ward-app .car-arrow:disabled { opacity: 0.3; cursor: default; }
@media (hover: none) { .ward-app .car-arrow { display: none; } }
/* On a phone the track reaches the screen's edges (Round 835), so the
   neighbouring cards peek in from the edge of the glass rather than
   stopping 12px short of it; the card itself is the same width as before. */
@container wardcol (max-width: 33.99rem) {
  .ward-app .history-carousel { margin-inline: -0.75rem; }
  .ward-app .history-thumbs { padding-inline: 3.25rem; scroll-padding-inline: 3.25rem; }
}
/* Above the track, whose shadow room reaches down into this row (a click
   on a dot landed on the track until it was lifted). */
.ward-app .carousel-dots {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: center;
  margin: -0.125rem 0 0.75rem;
}
/* Each dot is a button (Round 835): a 6px mark in a 24px by 28px press.
   Out of the Tab order (tabindex -1): the cards and their arrow keys are
   the keyboard's way along, and the dots would repeat every card. Drawn
   in the second green, 3.7:1 on the page, now that they are controls; the
   current one wider, in the accent. */
.ward-app .carousel-dots button {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5rem;
  height: 1.75rem;
  padding: 0 2px;
  border: 0;
  border-radius: 999px;
  background: none;
  cursor: pointer;
}
.ward-app .carousel-dots i {
  display: block;
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--accent-2);
  transition: width 0.25s ease, background-color 0.25s ease;
}
.ward-app .carousel-dots i.is-on { width: 1.1rem; background: var(--accent); }
@media (hover: hover) {
  .ward-app .carousel-dots button:hover i:not(.is-on) { background: var(--accent); }
}
/* .history-contents / .hc-link / .hc-num / .hc-title stood here: the list
   of chapter titles under the carousel (Round 443). Round 450 removed it at
   Derek's word; the carousel and its dots are the History tab's home. */

.ward-app .thumb {
  flex: 0 0 100%;
  scroll-snap-align: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--card);
  box-shadow: 0 7px 20px rgba(48, 42, 33, 0.07);
  overflow: hidden;
  text-align: left;
  cursor: pointer;
  transition: transform 0.18s ease;
}
.ward-app .thumb:active { transform: scale(0.985); }
.ward-app .thumb img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  filter: var(--h-ink);
}
/* A portrait's card sits on the face (Round 835). */
.ward-app .thumb img.is-portrait { object-position: 50% 12%; }
.ward-app .thumb-body {
  display: block;
  padding: 0.85rem 1rem 0.95rem;
}
/* ROOM FOR THE QUIZ TO PEEK IN ON A PHONE (Round 864, Derek: "make the
   thumbnail photos ... just a little bit smaller so that you can at least
   barely see that there is something below it for the user to scroll down
   to"): the hero, the tab bar and one tall card filled a phone's first
   screen to the last pixel, and the quiz card's top sat just under the fold,
   so nothing said there was more. The pictures go to the cinema's 1.85:1
   (16:9 left the peek too slight on a wider phone, 2:1 cropped the old
   meetinghouse's cupola), held a little high so a cupola or a roofline
   survives the crop, and the card's foot, the dots and the quiz's label
   give up a few pixels each. Measured on an 844px phone: the green card's
   top and its emblem stand above the fold. A computer keeps 16:10. */
/* MORE OF IT (Round 872, Derek, with the page's top on his phone: the label
   cut off at the bottom, "it looks bad like it did before"): Round 864 was
   measured on an 844px screen and his is about 820, where the card's top
   sat 7px under the fold. Fifty pixels more come out here -- the pictures
   at 2:1, held high (30%) so the old meetinghouse keeps its cupola; the
   heading's and the label's margins, the card's foot, the shadow room under
   the track and the dots' margins each a little tighter -- so the green
   card's top stands about 60px above the fold at 399x820 and the whole
   invitation's head at 844. */
@container wardcol (max-width: 33.99rem) {
  .ward-app .history-home .section-head { margin-top: 0.5rem; margin-bottom: 0.4rem; }
  .ward-app .history-thumbs { padding-bottom: 1.25rem; margin-bottom: -0.75rem; }
  .ward-app .thumb img { aspect-ratio: 2 / 1; object-position: 50% 30%; }
  .ward-app .thumb img.is-portrait { object-position: 50% 12%; }
  .ward-app .thumb-body { padding: 0.55rem 1rem 0.6rem; }
  .ward-app .thumb-read { margin-top: 0.35rem; }
  .ward-app .carousel-dots { margin: -0.5rem 0 0.25rem; }
  /* A little of that air back above the quiz (Round 874, Derek: "You brought
     the ward history quiz up just a little bit too much. Push it down a
     bit."): the label fully in view and the card's top edge, its emblem just
     under the fold. Only the label's own margin moves it: the dots' margins
     collapse into the track's and the label's. */
  .ward-app .history-home .hquiz-head { margin-top: 1.375rem; }
}
/* The title in the page's own headline voice; "Read" in the section-label
   voice, in the accent, so the card says it opens (Round 438). */
.ward-app .thumb-title {
  display: block;
  font-family: var(--display);
  font-size: 1.25rem;
  line-height: 1.2;
  color: var(--ink-strong);
}
/* .thumb-teaser -- the one-line description under the title -- is gone
   (Round 453, Derek: no descriptions on the chapter cards). */
.ward-app .thumb-read {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  margin-top: 0.6rem;
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}
.ward-app .thumb-read .chev { width: 1rem; height: 1rem; }
[data-theme='dark'] .ward-app .thumb,
.ward-app.is-dark .thumb { box-shadow: 0 10px 24px rgba(0, 0, 0, 0.18); }

.ward-app .article-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 0.25rem 0 0.625rem;
}
.ward-app .back-btn {
  min-height: 2.25rem;
  padding: 0.45rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--card);
  color: var(--accent);
  font-size: 0.75rem;
  font-weight: 800;
  cursor: pointer;
}
/* .chapter-pos ("Chapter III of V" in the toolbar) went in Round 835: the
   card's own label says it now, once. */
/* 5.75rem (Round 835): a chapter opened by a link landed its "← History"
   2px under the sticky tab bar; now it has 12px of air, and the pill is
   44px tall to a thumb. */
.ward-app .article { scroll-margin-top: 5.75rem; }
.ward-app .article .back-btn { min-height: 2.75rem; padding: 0.5rem 0.95rem; }
.ward-app .article-card { padding: 1.25rem 1.125rem; }
.ward-app .chapter-label {
  margin: 0;
  text-align: center;
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
}
.ward-app .article-title {
  margin: 0.375rem 0 0.5rem;
  text-align: center;
  font-family: var(--display);
  font-weight: 400;
  font-size: calc(2rem * var(--ds));
  line-height: 1.06;
  color: var(--ink-strong);
}
/* A list in a chapter's lede is set in the lede's type and sits in the
   paragraph's centred column, its items set left so the markers line up
   (Round 531). */
.ward-app .article-lede p,
.ward-app .article-lede li {
  font-family: var(--serif);
  font-size: 1.0625rem;
  line-height: 1.55;
  color: var(--muted);
}
.ward-app .article-lede p { margin: 0 auto 1.125rem; max-width: 22.5rem; text-align: center; }
.ward-app .article-lede ul,
.ward-app .article-lede ol { margin: 0 auto 1.125rem; max-width: 22.5rem; padding-left: 1.35rem; text-align: left; }
.ward-app .hentry-h {
  margin: 1.375rem 0 0.5rem;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.4375rem;
  line-height: 1.15;
  color: var(--ink-strong);
}
.ward-app .hentry p,
.ward-app .hentry li {
  font-family: var(--serif);
  font-size: 1rem;
  line-height: 1.65;
  color: var(--body);
}
.ward-app .hentry p { margin: 0 0 0.875rem; }
.ward-app .hentry ul,
.ward-app .hentry ol { margin: 0 0 0.875rem; padding-left: 1.35rem; }

/* A CHAPTER'S STORIES READ AS STORIES (Round 835). The gap before a new
   entry's heading was 8px more than the gap between two paragraphs, and the
   heading was nearly the chapter title's size, so a seven-entry chapter ran
   together as one text. Now each entry after the first stands under a short
   centred rule (the chapter head's mini-rule, quieter) with 2rem of air, and
   the headings are a step down from the title. Written on .article, so the
   privacy page, which borrows .hentry, keeps its own look. */
.ward-app .article .hentry + .hentry { margin-top: 2rem; }
.ward-app .article .hentry + .hentry::before {
  content: '';
  display: block;
  width: 2.5rem;
  height: 1px;
  margin: 0 auto 1.5rem;
  background: var(--line-strong);
}
.ward-app .article .hentry + .hentry .hentry-h { margin-top: 0; }
.ward-app .article .hentry-h { font-size: 1.3125rem; line-height: 1.2; text-wrap: balance; }
/* No word left alone on a line: the centred lede balanced, the body set
   with the browser's own care for the last line. */
.ward-app .article-lede p { text-wrap: balance; }
.ward-app .article .hentry p,
.ward-app .article .hentry li,
.ward-app .article .timeline-text p { text-wrap: pretty; }
/* A computer's column is 40rem: at 16px that was about 81 letters a line.
   18px brings it near 72, and the lede's column widens to match. A phone,
   and the phone preview in Leader Tools, are untouched. */
@container wardcol (min-width: 34rem) {
  .ward-app .article .hentry p,
  .ward-app .article .hentry li { font-size: 1.125rem; line-height: 1.6; }
  .ward-app .article .timeline-text p,
  .ward-app .article .timeline-text li { font-size: 1.0625rem; }
  .ward-app .article-lede p,
  .ward-app .article-lede ul,
  .ward-app .article-lede ol { max-width: 30rem; }
}

.ward-app .hshots {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5625rem;
  margin: 0.875rem 0 1.125rem;
}
.ward-app .hshots:not(.is-many) { grid-template-columns: minmax(0, 1fr); }
/* A quiet line under a chapter's photographs (Round 386): a caption, set a
   size down, italic, in the lede's own muted ink, pulled up close to the
   pictures it describes -- it belongs to them, not to the entry beneath. */
.ward-app .hcap {
  margin: -0.5rem 0 1.125rem;
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--muted);
}
.ward-app .hplate {
  display: block;
  width: 100%;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--card);
  overflow: hidden;
  cursor: zoom-in;
}
/* THE PHOTOGRAPHS SHOWN, NOT CROPPED TO A BAND (Round 835). Two-up tiles had
   a fixed 9rem height whatever their width, so a computer showed 38 to 68%
   of a picture and a single scan lost its top and bottom (the 1939 program
   cover lost "DEDICATION" and its date). Now a tile is 4:3, which keeps
   94 to 99% of most of these photographs; an odd last tile spans the row
   as a wide closer (The Chapel's 2025 view, The Painted Rotunda's third);
   and a picture alone is shown whole, as large as the column allows up to
   30rem tall. The bishops' 4:4.8 portraits set their own shape below. */
.ward-app .hplate img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  filter: var(--h-ink);
}
/* A tall picture's subject sits high (a face, a chandelier under a vault), so
   a tile keeps the top of it rather than the middle: 15% down. A landscape
   photograph near 4:3 barely moves. The wide closer below stays centred. */
.ward-app .hshots.is-many .hplate img { object-position: 50% 15%; }
.ward-app .hshots.is-many > .hplate:last-child:nth-child(odd) { grid-column: 1 / -1; }
.ward-app .hshots.is-many > .hplate:last-child:nth-child(odd) img { aspect-ratio: 16 / 9; object-position: 50% 50%; }
.ward-app .hshots:not(.is-many) { justify-items: center; }
.ward-app .hshots:not(.is-many) .hplate { width: auto; max-width: 100%; }
.ward-app .hshots:not(.is-many) .hplate img {
  width: auto;
  max-width: 100%;
  max-height: 30rem;
  aspect-ratio: auto;
  object-fit: contain;
}
/* A PICTURE ALONE KEEPS ITS ROOM WHILE IT LOADS (Round 889). With its width
   and height known (ward.js sets them on the plate as --pw and --pr), the
   plate is drawn at once at the size the loaded picture takes above -- its
   own width, the column's or 30rem of height, whichever is least, plus the
   plate's 1px rim each side -- and the picture fills it when it lands; until
   then the plate's own card ground holds the place. */
.ward-app .hshots:not(.is-many) .hplate.is-sized { width: min(100%, calc(var(--pw) + 2px), calc(30rem * var(--pr) + 2px)); }
.ward-app .hshots:not(.is-many) .hplate.is-sized img { width: 100%; aspect-ratio: var(--pr); }
.ward-app .hplate.is-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 4 / 4.8;
  color: var(--accent);
  background: var(--surface-2);
  cursor: default;
}

.ward-app .bishop-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.625rem;
  margin: 0.5rem 0 0;
  padding: 0;
  list-style: none;
}
.ward-app .bishop {
  border: 1px solid var(--line);
  border-radius: 15px;
  background: var(--card);
  overflow: hidden;
}
.ward-app .bishop .hplate { border: 0; border-radius: 0; }
.ward-app .bishop .hplate img {
  height: auto;
  aspect-ratio: 4 / 4.8;
  filter: grayscale(1) sepia(0.08);
}
.ward-app .bishop-cap { padding: 0.5625rem 0.5rem 0.7rem; text-align: center; }
/* A bishop's name in the page's name face (Round 835, after Round 823's
   rule: names and numbers in Ward Caslon), balanced so a long one breaks
   evenly. */
.ward-app .bishop-cap > strong {
  display: block;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.0625rem;
  line-height: 1.2;
  color: var(--ink-strong);
  text-wrap: balance;
}
/* Three across once there is room (Round 835: two across made the gallery
   6,000px tall on a computer; 27 is nine rows of three). On a phone, two
   across, and the last portrait, alone on its row, stands in the middle. */
@container wardcol (min-width: 34rem) {
  .ward-app .bishop-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@container wardcol (max-width: 33.99rem) {
  .ward-app .bishop-grid > .bishop:last-child:nth-child(odd) {
    grid-column: 1 / -1;
    justify-self: center;
    width: calc(50% - 0.3125rem);
  }
}
/* The focus ring on the card, not on the photograph, whose card clips it
   (Round 835); a browser without :has keeps the plate's own ring. */
@supports selector(:has(*)) {
  .ward-app .bishop:has(.hplate:focus-visible) { outline: 3px solid var(--accent); outline-offset: 2px; }
  .ward-app .bishop .hplate:focus-visible { outline: none; }
}
.ward-app .bishop-cap > span {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  color: var(--accent);
}
/* The two rules above are written on the caption's own children (Round
   531): on every descendant they turned a bold run inside a note into a
   second name, set in another face and size. A list in a note takes the
   note's type. */
.ward-app .bishop-note,
.ward-app .bishop-cap li { font-size: 0.75rem; line-height: 1.4; color: var(--muted); }
.ward-app .bishop-note { margin: 0.35rem 0 0; }
.ward-app .bishop-cap ul,
.ward-app .bishop-cap ol { margin: 0.35rem 0 0; padding-left: 1rem; text-align: left; }

/* A TIMELINE THAT READS AS ONE (Round 835): the years were a column of
   separate 12px pills. Now each year is set in the page's number face at
   the right of its column, and the lines hang from one thread -- each
   line's left rule, the rows touching so the rules join -- with a dot on
   the thread at every year. */
.ward-app .timeline { display: grid; gap: 0; margin-top: 0.75rem; }
.ward-app .timeline-row { display: grid; grid-template-columns: 3.25rem 1fr; gap: 0 1rem; align-items: start; }
.ward-app .timeline-year {
  padding: 0;
  font-family: var(--display);
  font-size: 1.125rem;
  line-height: 1.25;
  color: var(--accent);
  text-align: right;
  font-variant-numeric: lining-nums;
}
.ward-app .timeline-text {
  position: relative;
  padding: 0 0 1.1rem 1.1rem;
  border-left: 1px solid var(--line-strong);
}
.ward-app .timeline-row:last-child .timeline-text { padding-bottom: 0.2rem; }
.ward-app .timeline-text::before {
  content: '';
  position: absolute;
  left: -4px;
  top: 0.45rem;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--card);
}
/* A list in a timeline line is set in the line's type (Round 531). */
.ward-app .timeline-text p,
.ward-app .timeline-text li {
  font-family: var(--serif);
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--body);
}
.ward-app .timeline-text p { margin: 0; }
.ward-app .timeline-text ul,
.ward-app .timeline-text ol { margin: 0.2rem 0 0; padding-left: 1.35rem; }
.ward-app .timeline-text > :first-child { margin-top: 0; }

/* A PROGRAM'S ORDER OF SERVICE (Round 835): a block of lines that each open
   with a bold part (the 1939 dedication's, the 2025 rededication's), drawn by
   historyText in ward-page.js the way the Program tab draws its own: the part
   in small capitals in the accent over what or who in the display face, on
   the centre line, on the opened-item white, so it reads as the printed
   program it was. No rule between the rows. */
.ward-app .h-order {
  margin: 0.125rem 0 1rem;
  padding: 0.8rem 0.9rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--box);
  box-shadow: 0 7px 19px rgba(42, 38, 31, 0.035);
  text-align: center;
}
[data-theme='dark'] .ward-app .h-order,
.ward-app.is-dark .h-order { background: rgba(14, 39, 29, 0.8); box-shadow: none; }
.ward-app .h-order-row { padding: 0.4rem 0 0.45rem; }
.ward-app .h-order dt {
  margin: 0 0 0.15rem;
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}
.ward-app .h-order dd {
  margin: 0;
  font-family: var(--display);
  font-size: 1.0625rem;
  line-height: 1.3;
  color: var(--ink-strong);
  text-wrap: balance;
  overflow-wrap: anywhere;
}
/* An item's second line (an arranger, an accompanist, a hymn's number):
   the Program tab's .prog-sub, italic and muted under the name. */
.ward-app .h-order-sub {
  display: block;
  margin-top: 0.15rem;
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.9375rem;
  line-height: 1.35;
  color: var(--muted);
  text-wrap: balance;
}
/* A hymn in it links to the Church's page for it, with the Program tab's one
   tell (Round 455): a dotted rule, solid in the accent under the pointer. */
.ward-app .h-order dd a {
  color: inherit;
  text-decoration: underline dotted;
  text-decoration-color: color-mix(in srgb, var(--accent) 55%, transparent);
  text-underline-offset: 0.18em;
}
.ward-app .h-order dd a:focus-visible { color: var(--accent); text-decoration: underline solid; }
@media (hover: hover) {
  .ward-app .h-order dd a:hover { color: var(--accent); text-decoration: underline solid; text-decoration-color: var(--accent); }
}

/* THE WARD HISTORY QUIZ (Round 835): a card under the carousel, filled by
   setupHistoryQuiz in ward.js. The page's own pieces throughout -- the
   section head, the display face for the question, the carousel's dots for
   the progress (each turning the accent or the danger ink as it is
   answered), the Groups form's primary button -- and the opened-item white
   for the choices, so the game looks like the page it lives on. */
.ward-app .hquiz-head { margin-top: 1.5rem; }
.ward-app .hquiz { margin-top: 0; padding: 1.125rem 1.125rem 1.2rem; scroll-margin-top: 5rem; }
.ward-app .hq-intro { text-align: center; }
.ward-app .hq-title {
  margin: 0.1rem 0 0.4rem;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.4375rem;
  line-height: 1.15;
  color: var(--ink-strong);
  text-wrap: balance;
}
.ward-app .hq-lede {
  margin: 0 auto 1rem;
  max-width: 20rem;
  font-family: var(--serif);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--muted);
  text-wrap: balance;
}
/* THE INVITATION (Round 861, Derek: "a little bit more obvious and engaging
   ... we don't want to overdo it"; his pick of two drawn on the live page):
   until the game starts the card wears the page's soft green with the accent
   rim -- the sign-up sheet's "notice this one" card (.su-mine) -- with the
   History tab's book in the accent disc over the headline, one line ending
   in the quiz's top rank, and the button a touch taller with a small arrow.
   THE WHOLE GAME WEARS IT (Round 869, Derek: "you didn't make the rest of the
   cards that way. Will you go ahead and do that?"): the questions and the
   end card too, so a right answer's fill steps one shade deeper
   (--accent-soft-2, below) to read against it. Both themes from the tokens
   alone. */
.ward-app .hquiz { border-color: var(--accent); background: var(--accent-soft); box-shadow: 0 8px 20px -14px var(--accent); }
.ward-app .hq-emblem {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  margin: 0.15rem auto 0.7rem;
  border-radius: 50%;
  background: var(--accent);
  color: var(--card);
}
.ward-app .hq-emblem svg { width: 1.5rem; height: 1.5rem; }
[data-theme='dark'] .ward-app .hq-emblem,
.ward-app.is-dark .hq-emblem { color: var(--bg); }
.ward-app .hq-go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.2rem;
  min-width: 12rem;
  min-height: 3rem;
  padding-right: 0.9rem;
  font-size: 0.9375rem;
  white-space: nowrap;
}
.ward-app .hq-go-chev { flex: none; width: 1.05rem; height: 1.05rem; }
.ward-app .hq-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.7rem;
}
.ward-app .hq-count {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}
.ward-app .hq-pips { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.3rem; }
.ward-app .hq-pips i {
  display: block;
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--line-strong);
  transition: width 0.25s ease, background-color 0.25s ease;
}
.ward-app .hq-pips i.is-on { width: 1.1rem; background: var(--accent); }
.ward-app .hq-pips i.is-right { background: var(--accent); }
/* A miss is a ring as well as another colour, so the record reads without
   telling red from green. */
.ward-app .hq-pips i.is-wrong { background: transparent; box-shadow: inset 0 0 0 1.5px var(--danger); }
.ward-app .hq-q {
  margin: 0 0 0.85rem;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.25rem;
  line-height: 1.25;
  color: var(--ink-strong);
  text-wrap: pretty;
}
/* The question and the title at the end take the focus so a screen reader
   starts there; neither is a control, so neither draws a ring. */
.ward-app .hq-q:focus,
.ward-app .hq-rank:focus { outline: none; }
.ward-app .hq-choices { display: grid; gap: 0.5rem; }
.ward-app .hq-choice {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  min-height: 3rem;
  padding: 0.6rem 0.75rem 0.6rem 0.6rem;
  border: 1px solid var(--line-strong);
  border-radius: 14px;
  background: var(--box);
  color: var(--ink-strong);
  font-family: var(--serif);
  font-size: 1.0625rem;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.2s ease, opacity 0.2s ease, transform 0.12s ease;
}
[data-theme='dark'] .ward-app .hq-choice,
.ward-app.is-dark .hq-choice { background: rgba(14, 39, 29, 0.8); }
.ward-app .hq-choice:active { transform: scale(0.985); }
@media (hover: hover) {
  .ward-app .hq-choice:not(:disabled):hover { border-color: var(--accent); }
}
.ward-app .hq-letter {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 800;
}
.ward-app .hq-text { flex: 1; min-width: 0; }
.ward-app .hq-mark {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ward-app .hq-choice:disabled { cursor: default; }
.ward-app .hq-choice.is-right { border-color: var(--accent); background: var(--accent-soft-2); }
.ward-app .hq-choice.is-wrong { border-color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, transparent); }
.ward-app .hq-choice.is-right .hq-letter { background: var(--accent); color: var(--card); }
.ward-app .hq-choice.is-wrong .hq-letter { background: var(--danger); color: var(--card); }
.ward-app .hq-choice.is-right .hq-mark { color: var(--accent); }
.ward-app .hq-choice.is-wrong .hq-mark { color: var(--danger); }
/* The choices not taken step back in their ink and badge, not by fading the
   whole button, so the words stay readable (5.4:1) for a reader checking
   the answer. */
.ward-app .hq-choice.is-dim { color: var(--muted); border-color: var(--line); }
.ward-app .hq-choice.is-dim .hq-letter { opacity: 0.55; }
.ward-app .hq-after { margin-top: 0.95rem; padding-top: 0.9rem; border-top: 1px solid var(--line); }
.ward-app .hq-verdict { margin: 0 0 0.3rem; font-family: var(--display); font-size: 1.1875rem; line-height: 1.2; }
.ward-app .hq-verdict.is-right { color: var(--accent); }
.ward-app .hq-verdict.is-wrong { color: var(--danger); }
.ward-app .hq-why { margin: 0; font-family: var(--serif); font-size: 1rem; line-height: 1.55; color: var(--body); }
.ward-app .hq-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin-top: 0.85rem;
}
.ward-app .hq-actions.is-end { justify-content: center; }
/* The way into the chapter: the carousel cards' "Read" voice, 44px tall. */
.ward-app .hq-read {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  min-height: 2.75rem;
  padding: 0.25rem 0;
  border: 0;
  background: none;
  color: var(--accent);
  font-size: 0.8125rem;
  font-weight: 800;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
}
.ward-app .hq-read .chev { flex: none; width: 1rem; height: 1rem; }
.ward-app .hq-next { margin-left: auto; }
.ward-app .hq-done { text-align: center; }
.ward-app .hq-done .hq-top { flex-direction: column; justify-content: center; gap: 0.45rem; }
.ward-app .hq-score { margin: 0.35rem 0 0; font-family: var(--display); font-size: 1.25rem; line-height: 1.1; color: var(--muted); }
.ward-app .hq-score strong { margin-right: 0.08em; font-weight: 400; font-size: 3rem; color: var(--ink-strong); }
.ward-app .hq-rank { margin: 0.5rem 0 0.25rem; font-family: var(--display); font-weight: 400; font-size: 1.4375rem; line-height: 1.15; color: var(--accent); }
.ward-app .hq-rankline { margin: 0 auto; max-width: 21rem; font-family: var(--serif); font-size: 1rem; line-height: 1.5; color: var(--body); text-wrap: balance; }
@media (prefers-reduced-motion: reduce) {
  .ward-app .hq-choice,
  .ward-app .hq-pips i { transition: none; }
  .ward-app .hq-choice:active { transform: none; }
}

.ward-app .chapter-nav { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5625rem; margin-top: 1.5rem; }
/* THE PAGE-TURN (Round 835): which way and which chapter in small
   capitals, over the chapter's title in the display face; the left one set
   left, the right one right, like a book's running feet. */
.ward-app .chapter-nav button {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 0.2rem;
  min-height: 3.75rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--card);
  color: var(--accent);
  text-align: left;
  cursor: pointer;
}
.ward-app .chapter-nav .cn-next { align-items: flex-end; text-align: right; }
.ward-app .chapter-nav .cn-k {
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}
.ward-app .chapter-nav .cn-t {
  font-family: var(--display);
  font-size: 1.0625rem;
  line-height: 1.2;
  color: var(--ink-strong);
  text-wrap: balance;
}
@media (hover: hover) {
  .ward-app .chapter-nav button:hover { border-color: var(--accent-2); }
}
.ward-app .article-foot { margin: 0.9rem 0 0; text-align: center; }
.ward-app .article .article-foot .text-btn { display: inline-flex; align-items: center; min-height: 2.75rem; padding: 0 0.75rem; }
.ward-app .text-btn {
  padding: 0.35rem 0;
  border: 0;
  background: none;
  color: var(--accent);
  font-size: 0.75rem;
  font-weight: 800;
  cursor: pointer;
}

/* ------------------------------------------------------------ the footer */

.ward-app .colophon { padding: 1.5rem 1.25rem 3.25rem; text-align: center; }
/* The "not an official website" line stood first in the colophon until Round
   877 (Derek: "too annoying and cluttered"); it is on the privacy page now,
   .policy-disclaimer below. */
/* The privacy policy's link, first in the colophon since Round 877 (Round 566),
   at the small size and the fade of the Updated line that stood under it
   (Round 878, Derek: "the same smaller size", both faded "a bit"; the Updated
   line itself went in Round 880). Fainter again in Round 883 (Derek: "even
   more"): half strength, about 2:1 on the page in light and 3:1 in dark (it
   was 2.7 and 4.8), and whole again under a pointer or the keyboard's focus,
   so whoever goes looking for it still finds it plainly. */
.ward-app .privacy-link { margin: 0.35rem 0 0; font-size: 0.6875rem; opacity: 0.5; transition: opacity 0.15s ease; }
.ward-app .privacy-link a { color: var(--muted); text-underline-offset: 2px; }
.ward-app .privacy-link:focus-within { opacity: 1; }
@media (hover: hover) {
  .ward-app .privacy-link:hover { opacity: 1; }
}
/* THE PRIVACY PAGE (Round 566): /privacy, in a History chapter's article
   card and type (.article-title, .hentry). A line length a person can read
   on a computer; a phone is narrower than the cap anyway. */
.ward-app .policy { max-width: 42rem; margin-left: auto; margin-right: auto; }
.ward-app .policy-date { margin: 0 0 0.45rem; text-align: center; font-size: 0.75rem; color: var(--muted); }
/* The one place the "not an official website" sentence stands (Round 877,
   Derek): under the date, the Church's name bound with no-break spaces so it
   never splits (Round 330), so a phone reads it as two whole lines. */
.ward-app .policy-disclaimer { margin: 0 0 1.35rem; text-align: center; font-size: 0.8125rem; line-height: 1.5; color: var(--muted); text-wrap: balance; }
/* The way back (Round 877): the sign-up pages' own arrow-and-word line
   (.su-leave-a, below) above the card, at the card's width. */
.ward-app .pv-back { max-width: 42rem; margin: -0.35rem auto 0.6rem; }
/* LIGHT OR DARK (Round 826, Derek: the sun-and-moon toggle "at the bottom
   instead", and "eliminate the text 'Appearance' completely"; it was the word
   and a Light and a Dark button). Leader Tools' own switch (Round 815), the
   page's tokens in place of the app's. AT FULL STRENGTH (Round 827, Derek:
   "not quite so faded out" -- the quiet dress was for Leader Tools' top bar,
   a prominent place; this is the last thing at the foot of the page): the
   app's Account-page dress, the pill drawn, the knob amber under the sun by
   day and grey under the moon by night, the other glyph in the soft ink.
   26px drawn, 44 to a thumb (::before). Centred where the row stood. */
.ward-app .theme-foot {
  display: flex;
  justify-content: center;
  margin: 1.25rem 0 0;
}
.ward-app .themesw {
  position: relative;
  display: inline-flex;
  align-items: center;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background-color: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ward-app .themesw::before { content: ''; position: absolute; inset: -0.55rem -0.3rem; }
.ward-app .themesw:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.ward-app .themesw-track {
  position: relative;
  display: block;
  box-sizing: border-box;
  width: 3.2rem;
  height: 1.6rem;
  border-radius: 999px;
  background-color: color-mix(in srgb, var(--ink) 8%, var(--card));
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.18);
}
.ward-app .themesw-knob {
  position: absolute;
  top: 0.2rem;
  left: 0.2rem;
  width: 1.2rem;
  height: 1.2rem;
  border-radius: 50%;
  background-color: #eb9d33;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
  transition: transform 0.15s ease, background-color 0.15s;
}
/* The amber, a layer of its own so it can fade out under the moon rather
   than switch. */
.ward-app .themesw-knob::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background-image: linear-gradient(180deg, #f5b650 0%, #e3892a 100%);
  transition: opacity 0.15s;
}
.ward-app .themesw[aria-checked='true'] .themesw-knob {
  transform: translateX(1.6rem);
  background-color: color-mix(in srgb, var(--muted) 55%, var(--card));
}
.ward-app .themesw[aria-checked='true'] .themesw-knob::after { opacity: 0; }
.ward-app .themesw-ico {
  position: absolute;
  top: 0.35rem;
  width: 0.9rem;
  height: 0.9rem;
  color: var(--muted);
  transition: color 0.15s;
}
.ward-app .themesw-sun { left: 0.35rem; }
.ward-app .themesw-moon { right: 0.35rem; }
.ward-app .themesw[aria-checked='false'] .themesw-sun { color: #fff; }
.ward-app .themesw[aria-checked='true'] .themesw-moon { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
  .ward-app .themesw-track,
  .ward-app .themesw-knob,
  .ward-app .themesw-knob::after,
  .ward-app .themesw-ico { transition: none; }
}

/* ----------------------------------------------------------- the lightbox */

/* Hidden by attribute; the class rule setting display must not win. */
.lightbox[hidden] { display: none !important; }
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(20, 16, 10, 0.88);
  touch-action: pan-y pinch-zoom;
  opacity: 0;
  transition: opacity 0.24s ease;
}
.lightbox.is-open { opacity: 1; }
.lightbox.is-closing { opacity: 0; transition-duration: 0.2s; }
body.lb-open { overflow: hidden; }

/* THE PDF VIEWER (Round 491): a flyer's pages drawn inside the page under the
   lightbox's own close button, so a PDF is put away the way a picture is.
   Built by ward.js on <body>, like the lightbox, so it is unscoped. */
.pdfview {
  position: fixed;
  inset: 0;
  z-index: 90;
  overflow-y: auto;
  overflow-x: hidden;
  background: rgba(20, 16, 10, 0.92);
  touch-action: pan-y pinch-zoom;
  -webkit-overflow-scrolling: touch;
  opacity: 0;
  transition: opacity 0.24s ease;
  font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}
.pdfview.is-open { opacity: 1; }
body.pdf-open { overflow: hidden; }
/* The close stays put while the pages scroll under it, and ABOVE them:
   Round 491's title bar carried a z-index of its own and painted over the
   button, so a tap on the ✕ landed on the bar and nothing closed (Derek,
   Round 493). The bar is gone; the button keeps a z-index anyway, so
   nothing added later can cover it. */
.pdfview .lb-close { position: fixed; z-index: 3; }
.pdfview-pages {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  /* Room at the top for the fixed close. */
  padding: 4.4rem 1rem 3rem;
}
.pdfview-pages canvas {
  display: block;
  max-width: 100%;
  height: auto;
  background: #fff;
  border-radius: 3px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
}
.pdfview-status {
  margin: 1rem;
  text-align: center;
  color: #faf6ee;
  font-size: 0.875rem;
  opacity: 0.85;
}
.pdfview-status[hidden] { display: none; }
@media print { .pdfview { display: none !important; } }

/* HOW IT MOVES (Round 379). The frame is a real box in both states (a
   flyer's simply has no moulding), so it can be moved: it rises out of the
   thumbnail it was tapped on -- ward.js sets its starting transform from
   that thumbnail's rectangle -- and settles on an ease-out; closing runs
   the road back. is-shown is added once the picture is decoded, so the
   frame never appears empty. */
.lightbox .lb-frame {
  display: block;
  box-sizing: border-box;
  max-width: 100%;
  max-height: 100%;
  opacity: 0;
  transform: translateY(12px) scale(0.94);
  transition: opacity 0.3s ease, transform 0.34s cubic-bezier(0.22, 0.75, 0.28, 1);
  will-change: transform, opacity;
}
.lightbox.is-shown .lb-frame { opacity: 1; transform: none; }
.lightbox.is-closing .lb-frame {
  opacity: 0;
  transform: translateY(6px) scale(0.96);
  transition-duration: 0.2s, 0.2s;
}
.lightbox .lb-mat { display: block; position: relative; }

/* The picture box is sized in pixels by ward.js to the decoded picture, so
   the next picture's proportions are glided to rather than jumped to. Two
   layers: the incoming picture fades in over the outgoing; at rest the box
   has the picture's own proportions, so cover and contain agree. */
.lb-pic {
  position: relative;
  transition: width 0.3s cubic-bezier(0.22, 0.75, 0.28, 1), height 0.3s cubic-bezier(0.22, 0.75, 0.28, 1);
}
.lb-pic.no-anim { transition: none; }
.lb-img { display: block; max-width: 100%; max-height: calc(88vh - 3rem); object-fit: contain; transition: opacity 0.34s ease-out; }
/* The step between two pictures (Round 440): out over 0.28s, easing in to
   nothing; back over 0.34s, easing out to full. The nameplate below
   carries the identical pair, so the two move as one. */
.lightbox.is-fading .lb-img { opacity: 0; transition-duration: 0.28s; transition-timing-function: ease-in; }
.lb-pic:not(.is-sized) .lb-img-in { display: none; }
.lb-pic.is-sized { overflow: hidden; }
.lb-pic.is-sized .lb-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: cover;
}
/* The second image layer is idle since Round 440 (the step no longer
   cross-fades); it stays in the markup, hidden. */
.lb-img-in { opacity: 0; pointer-events: none; }
.lightbox:not(.is-framed) .lb-pic { border-radius: 4px; }

/* ABOVE THE FRAME, WHICHEVER SIDE (Round 670, Derek: on a phone "the left
   arrow is hidden behind the bishop frame"). The frame carries a transform,
   which makes it a painting layer of its own, and the buttons had no z-index,
   so they painted in markup order: the previous arrow, written before the
   frame, went under it once a phone-wide frame reached its spot, while the
   next arrow, written after, stayed on top. A flyer's frame is as wide, so
   the pictures under a notice had the same hole. */
.lb-close,
.lb-step {
  position: absolute;
  z-index: 2;
  font: inherit;
  color: #faf6ee;
  background: rgba(20, 16, 10, 0.55);
  border: 1px solid rgba(250, 246, 238, 0.35);
  border-radius: 50%;
  cursor: pointer;
  line-height: 1;
  transition: background-color 0.2s ease;
}
.lb-close { top: 1rem; right: 1rem; width: 2.6rem; height: 2.6rem; font-size: 1.5rem; }
.lb-step { top: 50%; transform: translateY(-50%); width: 3rem; height: 3rem; font-size: 1.75rem; }
.lb-prev { left: 0.75rem; }
.lb-next { right: 0.75rem; }
.lb-close:hover,
.lb-step:hover { background: rgba(20, 16, 10, 0.8); }
/* THE FOOT UNDER THE FRAME (Round 709): the swipe hand above the count, one
   column centred at the bottom of the scrim. The count kept its own absolute
   place until this round, in this file and in styles.css both, so the rules
   here are written long enough to win in Leader Tools as well. */
.lb-foot {
  position: absolute;
  bottom: 1rem;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
}
.lb-foot .lb-count { position: static; bottom: auto; left: auto; transform: none; }
/* Drawn only on a touch screen, and only while the lightbox says to (ward.js
   adds is-hinting when a gallery of more than one opens, and takes it off
   after a few seconds or at the first swipe). A fade, never a movement. */
.lb-hint {
  display: none;
  margin: 0;
  color: #faf6ee;
  opacity: 0;
  transition: opacity 0.5s ease;
}
.lb-hint .lb-swipe { display: block; width: 2.3rem; height: 2.3rem; }

/* NO ARROWS WHERE A FINGER CAN SWIPE (Round 708, Derek, with a bishop's
   portrait open on his phone and both arrows circled: "they're just too
   visually distracting. Take them off ... But keep the usability"). A touch
   screen already walks the gallery with a swipe (Round 350) and the count
   under the frame still says where you are, so the two buttons are drawn
   only where there is a pointer that cannot swipe -- a computer, where they
   are the one visible way between the 27 portraits (his own choice when
   asked). They keep their places in the markup and their keyboard and
   screen-reader labels; a hidden button is simply not painted. */
@media (hover: none) {
  .lb-step { display: none; }
  .lb-hint { display: block; }
  .lightbox.is-hinting .lb-hint { opacity: 0.9; }
}
.lb-count {
  position: absolute;
  bottom: 1rem;
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  color: #faf6ee;
  font-size: 0.875rem;
  letter-spacing: 0.06em;
}

/* A portrait opens in a frame (Round 339); a bishop's carries the engraved
   plate (Round 353). Redrawn in Round 379 as a mitred moulding lit from the
   upper left; Round 380 made it black lacquer with a little gloss and gave
   the nameplate its black ground and silver lettering; Round 381 took the
   silver fillet off the sight edge so the photograph meets the moulding,
   made the plate's rim a real 3px silver border, and set the lettering in
   a bright silver gradient a size up (all Derek). Round 389 redrew the
   moulding to a frame Derek photographed: a broad satin-black body with
   square corners, a raised bead near the picture over a stepped inner lip,
   and no gloss. The colours are literal on purpose: a depicted object is
   not page chrome, and it is always seen against the same dark scrim. */
.lightbox .lb-plate { display: none; }
.lightbox.is-framed .lb-frame {
  max-width: min(92vw, 32rem);
  max-height: 88vh;
  padding: 0; /* the photograph meets the moulding (Round 381) */
  /* 1.75rem of moulding (1.2rem on a phone): the frame in Derek's
     photograph is broad. ward.js's lbFit reserves the SAME widths; move
     one and the other must follow. */
  border: 1.75rem solid;
  /* Four tints on one moulding, mitred at the corners by the browser: the
     satin black beneath shows through each side's own tint, the top and
     left lit, the right and bottom in shade. Halved in Round 432 (they
     were 0.10 / 0.32 / 0.5 / 0.03): at the old strength the diagonal seam
     at each corner read as a jagged join rather than a mitre. */
  border-color: rgba(255, 255, 255, 0.06) rgba(0, 0, 0, 0.16) rgba(0, 0, 0, 0.26) rgba(255, 255, 255, 0.02);
  border-radius: 0;
  /* Satin, not lacquer: a soft top-to-bottom shading and no sheen (Round
     389). The body reads slightly convex -- lighter at the top, darkest
     just below the middle, lifting again toward the foot. */
  background: linear-gradient(180deg, #232323 0%, #161616 28%, #0b0b0b 66%, #171717 100%);
  background-clip: border-box;
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.12),
    0 1.6rem 3.4rem rgba(0, 0, 0, 0.62),
    0 0.35rem 0.9rem rgba(0, 0, 0, 0.5);
}
/* The profile (Round 389), drawn as rings around the picture: a child's
   box-shadow paints ABOVE its parent's border, so these lie over the
   moulding, and being translucent they keep its lit-from-above tints. From
   the picture outward: the rabbet's shadow line; a flat inner step; the
   shadow under the bead; the bead's lower flank, its lit crown and its
   upper flank; the groove behind it; then the broad body of the moulding
   runs out to the lit outer edge. Widths in px on purpose -- they are the
   moulding's own carving and scale with its width below, not with type.
   Round 432 (Derek: "really jagged changes of color ... smooth it out"):
   the seven hard-edged rings became five, each BLURRED by a few pixels so
   one band flows into the next and the profile reads as turned wood
   rather than as stripes; only the rabbet line at the picture's edge
   stays crisp. The steps between them are gentler too (the old rings ran
   0.92 / 0.055 / 0.55 / 0.05 / 0.17 / 0.06 / 0.5). A blurred ring never
   spills onto the picture: a box-shadow is clipped to outside its own
   box. */
.lightbox.is-framed .lb-mat {
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.85),
    0 0 2px 4px rgba(255, 255, 255, 0.04),
    0 0 3px 7px rgba(0, 0, 0, 0.35),
    0 0 3px 11px rgba(255, 255, 255, 0.13),
    0 0 4px 15px rgba(0, 0, 0, 0.32);
}
.lightbox.is-framed .lb-pic { border-radius: 0; }
.lightbox.is-framed .lb-img { border-radius: 0; box-shadow: none; }

/* The plate: black, brushed, in a real silver border -- a 3px rim carrying
   a polished gradient (Round 381; it was a 1px box-shadow ring) -- with the
   name in a bright silver gradient clipped to the glyphs, set bold, and a
   faint lit edge beneath each letter, which is what reads as engraved on a
   dark plate. The engraving is a drop-shadow FILTER, not a text-shadow: a
   text-shadow paints over a background clipped to the text and would hide
   the gradient. Round 382 set the name bold and took the two mounting
   screws off (Derek). The bold is SYNTHESISED -- caslon.woff2 is one weight
   -- which is the call Round 324 made for the card titles after looking at
   it: the thickened outline still reads as Caslon, and the letters gain the
   width a nameplate wants. */
.lightbox .lb-plate { transition: opacity 0.34s ease-out; }
.lightbox.is-fading .lb-plate { opacity: 0; transition-duration: 0.28s; transition-timing-function: ease-in; }
.lightbox.is-plated .lb-plate {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 1.1rem;
  width: fit-content;
  margin-inline: auto;
  margin-block: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.14rem;
  max-width: calc(100% - 1.6rem);
  padding: 0.5rem 1.45rem 0.55rem;
  border: 3px solid transparent;
  text-align: center;
  border-radius: 3px;
  /* The brushed black stops at the padding edge; the silver runs under the
     transparent border, so the rim IS the border. */
  background:
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.035) 0 1px, rgba(0, 0, 0, 0) 1px 3px) padding-box,
    linear-gradient(172deg, #303030 0%, #181818 38%, #0a0a0a 55%, #1e1e1e 80%, #0d0d0d 100%) padding-box,
    linear-gradient(135deg, #ffffff 0%, #d9d9d9 14%, #8a8a8a 30%, #f5f5f5 46%, #9e9e9e 62%, #e8e8e8 78%, #a6a6a6 100%) border-box;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 -1px 0 rgba(0, 0, 0, 0.8),
    inset 1px 0 0 rgba(255, 255, 255, 0.06),
    inset -1px 0 0 rgba(0, 0, 0, 0.5),
    0 0 0 1px #0a0a0a,
    0 2px 7px rgba(0, 0, 0, 0.55);
}
/* Round 382: the two silver mounting screws that sat either side of the
   name (the plate's ::before and ::after, 6px radial-gradient discs at
   0.42rem in) are gone at Derek's word. */
.lightbox.is-plated .lb-plate-n {
  font-family: 'Ward Caslon', 'Iowan Old Style', Palatino, Georgia, serif;
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #f2f2f2;
  filter: drop-shadow(0 1px 0 rgba(255, 255, 255, 0.24)) drop-shadow(0 -1px 0 rgba(0, 0, 0, 0.75));
}
.lightbox.is-plated .lb-plate-y {
  font-size: 0.78rem;
  /* A step lighter than the plate's name (Round 388, Derek: "just a little
     thinner"). The date line is the system sans, which has real light cuts
     on every platform -- Semilight where one exists, Light where that is
     the nearest -- so this thins the strokes rather than faking it. */
  font-weight: 350;
  line-height: 1.3;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #d6d6d6;
  filter: drop-shadow(0 1px 0 rgba(255, 255, 255, 0.18)) drop-shadow(0 -1px 0 rgba(0, 0, 0, 0.7));
}
/* The shine: a silver gradient clipped to the glyphs. The flat silver above
   is the fallback where a browser cannot clip a background to text. */
@supports (-webkit-background-clip: text) or (background-clip: text) {
  .lightbox.is-plated .lb-plate-n,
  .lightbox.is-plated .lb-plate-y {
    background-image: linear-gradient(180deg, #ffffff 0%, #f8f8f8 36%, #cdcdcd 50%, #f2f2f2 60%, #bebebe 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
  }
  .lightbox.is-plated .lb-plate-y {
    background-image: linear-gradient(180deg, #f4f4f4 0%, #e6e6e6 36%, #b8b8b8 50%, #dedede 60%, #a9a9a9 100%);
  }
}
@media (max-width: 30rem) {
  .lightbox.is-framed .lb-frame { border-width: 1.2rem; max-width: 94vw; }
  /* The carving scaled to the narrower moulding (19.2px against 28), the
     same five soft bands as above (Round 432). */
  .lightbox.is-framed .lb-mat {
    box-shadow:
      0 0 0 1px rgba(0, 0, 0, 0.85),
      0 0 1.5px 3px rgba(255, 255, 255, 0.04),
      0 0 2px 5px rgba(0, 0, 0, 0.35),
      0 0 2px 8px rgba(255, 255, 255, 0.13),
      0 0 3px 10px rgba(0, 0, 0, 0.32);
  }
  .lightbox.is-plated .lb-plate { bottom: 0.8rem; padding: 0.4rem 1.15rem 0.44rem; }
  .lightbox.is-plated .lb-plate-n { font-size: 0.94rem; letter-spacing: 0.1em; }
}

/* ------------------------------------------------- the replica, and the phone frame */

/* Inside the leader app the paper IS the app column: no gutters of its own,
   and it ends where its content ends rather than filling a window. */
.wp-paper.ward-app { padding-inline: 0; min-height: 0; }
.phoneview-stage .ward-app { --ds: 0.88; }
.phoneview-stage .ward-app .nav-wrap { position: sticky; top: 0; }

/* -------------------------------------------------------------- the phone */

@media (max-width: 30rem) {
  .ward-app { --ds: 0.9; }
  /* 16rem and 84%: rows 10.5-98% of the photograph on a 390px phone, the
     cross tip 7px past the top edge (58% in Round 402) and the title block over the lawn (32%
     until Round 402; the numbers are explained on .hero-photo and
     .hero-img above). */
  .ward-app .hero-photo { height: 16rem; }
  .ward-app .hero-img { object-position: center 84%; }
  /* The Groups lead on a phone: 0.84375rem (13.5px) against 0.875rem
     elsewhere -- a point down in Round 409, half a point back up in Round
     410, both at his word; the Bulletin and History leads are not
     .subtitle and are untouched. */
  .ward-app .intro-card .subtitle,
  .ward-app .join-note { font-size: 0.84375rem; }
  .ward-app .event-summary { gap: 0.65rem; padding: 0.65rem 0.65rem 0.65rem 0.6rem; }
  /* The folds keep to the cards' edges here too (Round 825), and so do the
     permanent notices in their dress (Round 846). */
  .ward-app .acc-btn { padding-left: calc(0.6rem + 1px); padding-right: calc(0.65rem + 1px); }
  .ward-app .bulletin-pinned .event-summary { padding-left: calc(0.6rem + 1px); padding-right: calc(0.65rem + 1px); }
  .ward-app .bulletin-pinned .event-body { padding: 0.8rem 0.85rem 0.95rem; }
  .ward-app .event-cal { width: 3.5rem; min-height: 4.25rem; }
  .ward-app .event-cal-d { font-size: 1.75rem; }
  .ward-app .event-title { font-size: 1.1875rem; }
  .ward-app .event-body { margin: 0 0.7rem; padding: 0.8rem 0 0.95rem; }
  /* The notice's button on a phone is ITS OWN WIDTH, at the left of its line
     (Round 666, Derek: "far too wide ... wide enough to comfortably fit all
     the text within it and then ... left-aligned"). It was full width from
     Round 655 to Round 665, the words centred ahead of the circle. The base
     rule above -- an inline-flex pill at least 10rem wide, the circle at its
     right end -- already does what he asked, so the phone adds nothing now. */
  .ward-app .date-large strong { font-size: 1.75rem; }
  .ward-app .detail-title { font-size: 1.3125rem; }
  .ward-app .form-row { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------ no JavaScript */

/* The tabs cannot switch anything, so every screen shows in turn and every
   fold stands open. */
html:not(.js) .ward-app .nav-wrap { display: none; }
html:not(.js) .ward-app .screen,
html:not(.js) .ward-app .event-detail,
html:not(.js) .ward-app .group-detail,
html:not(.js) .ward-app .acc-panel,
html:not(.js) .ward-app .article,
html:not(.js) .ward-app .hero-img { display: block !important; }
html:not(.js) .ward-app .hero-img { opacity: 1; }
html:not(.js) .ward-app .group-meets { display: block; -webkit-line-clamp: none; line-clamp: none; overflow: visible; }
html:not(.js) .ward-app .screen + .screen { margin-top: 2rem; border-top: 1px solid var(--line); padding-top: 1rem; }
html:not(.js) .ward-app .calendar-view,
html:not(.js) .ward-app .segmented,
html:not(.js) .ward-app .filters,
html:not(.js) .ward-app .theme-foot,
html:not(.js) .ward-app .article-toolbar,
html:not(.js) .ward-app .chapter-nav,
html:not(.js) .ward-app .carousel-dots,
html:not(.js) .ward-app .car-arrow,
html:not(.js) .ward-app .article-foot { display: none !important; }

/* ------------------------------------------------------------ the survey */

/* THE WARD SURVEY PAGE (Round 664, Derek's pick of six phone treatments: "I
   love #1"): one question at a time. survey.js prints every question as a
   section; survey-steps.js shows one at a time under a progress bar, with
   Back, Next and Skip in a foot pinned to the bottom, and big stacked
   answers a thumb can press. Without the script (html without .sv-js) the
   sections stand in a column with a rule between and the one Save posts
   them all. The thank-you keeps the privacy page's shell. */
.ward-app.sv-app { min-height: 100dvh; display: flex; flex-direction: column; }
.ward-app .sv-form { display: flex; flex-direction: column; flex: 1 1 auto; width: min(100%, 30rem); margin: 0 auto; }
.ward-app .sv-top { padding: calc(env(safe-area-inset-top, 0px) + 1.1rem) 1.25rem 0.9rem; }
/* THE TOP ROW (Round 668, Derek: "The back button should be in the top left
   of the screen not in the bottom left next to the next button"): Back at
   the left, the brand words in the middle, Skip at the right -- three
   columns, the outer two equal, so the words stay centred whichever of the
   two buttons is hidden. Back is only here since Round 682 ("I only want
   one back arrow, and it should be in the top left of the screen"), and the
   brand words then take a line of their own above Back and Skip, since on a
   phone Back ran into them; on the first question, with both buttons
   hidden, that second line is not drawn at all. */
/* The top row holds Back alone since Round 871: Skip went down to the foot,
   beside Next (Derek: "the skip button should be close to the next button
   not on a completely different part of the screen"). */
.ward-app .sv-nav { display: flex; align-items: center; margin: 0 0 0.6rem; }
/* THE WAY OUT (Round 721, Derek: "There should be some way to exit the survey
   if you get sick of it... Maybe an 'x' in the top right?"): the brand words
   centred with the × at the right of that same line, so it is nowhere near
   Next. Without the script there is nothing to leave -- the plain form has
   saved nothing yet -- so it is not drawn. */
.ward-app .sv-brandline { position: relative; display: flex; align-items: center; justify-content: center; margin: 0 0 0.6rem; min-height: 1.75rem; }
.ward-app .sv-brandline .sv-brand { margin: 0; text-align: center; }
.ward-app .sv-x {
  position: absolute;
  right: -0.35rem;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
}
.ward-app .sv-x:focus-visible { outline: 3px solid var(--accent); outline-offset: 0; }
html:not(.sv-js) .ward-app .sv-x { display: none; }
/* The question it asks before it lets go. */
.ward-app .sv-leaveask { position: fixed; inset: 0; z-index: 50; display: grid; place-items: center; padding: 1.25rem; background: rgba(15, 26, 22, 0.55); }
.ward-app .sv-leaveask-box { width: min(22rem, 100%); box-sizing: border-box; padding: 1.25rem; border-radius: var(--radius); background: var(--card); box-shadow: 0 24px 48px -20px rgba(0, 0, 0, 0.5); }
.ward-app .sv-leaveask-h { margin: 0 0 0.4rem; font-family: var(--display); font-size: 1.3125rem; color: var(--title-ink); }
.ward-app .sv-leaveask-p { margin: 0 0 1.1rem; font-size: 0.9375rem; line-height: 1.5; color: var(--body); }
.ward-app .sv-leaveask-acts { display: flex; flex-direction: column; gap: 0.5rem; }
.ward-app .sv-leaveask-acts button { width: 100%; box-sizing: border-box; min-height: 3rem; }
.ward-app .sv-foot[hidden],
.ward-app .sv-next[hidden] { display: none; }
.ward-app .sv-brand { margin: 0 0 0.6rem; font-size: 0.66rem; font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase; color: var(--accent); }
.ward-app .sv-prog { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; font-size: 0.8125rem; font-weight: 600; color: var(--muted); }
/* Skip, the quiet way on beside the strong one (Round 871): the foot's own
   grey at 600, a thumb's height, at the left of Next; on a question that
   moves on by itself it stands in the foot alone. */
.ward-app .sv-skip { appearance: none; flex: none; border: 0; background: none; min-height: 2.75rem; padding: 0.5rem 0.9rem 0.5rem 0.25rem; font: inherit; font-size: 0.9375rem; font-weight: 600; color: var(--muted); cursor: pointer; white-space: nowrap; }
.ward-app .sv-skip:focus-visible { outline: 3px solid var(--accent); outline-offset: 0; border-radius: 8px; }
/* THE BAR (Round 682, Derek: "just a completion bar that moved forward as the
   user progressed", in place of Round 669's bubbles): it fills a step at a
   time under "Question N of 18". Without the script there is nothing to
   page through, so no bar. */
.ward-app .sv-bar { height: 6px; margin-top: 0.5rem; border-radius: 999px; background: var(--line); overflow: hidden; }
.ward-app .sv-bar i { display: block; width: 0; height: 100%; border-radius: 999px; background: var(--accent); transition: width 240ms ease; }
html:not(.sv-js) .ward-app .sv-bar { display: none; }
/* The one Back (Round 682: "in the top left of the screen"), in the top
   row's left column. */
.ward-app .sv-nav .sv-back { margin-left: -0.25rem; white-space: nowrap; }
.ward-app .sv-steps { flex: 1 1 auto; padding: 1.5rem 1.25rem 1rem; }
html:not(.sv-js) .ward-app .st + .st { margin-top: 1.75rem; padding-top: 1.5rem; border-top: 1px solid var(--line); }
.ward-app .st-q { margin: 0 0 0.5rem; font-family: var(--display); font-weight: 400; font-size: 1.75rem; line-height: 1.2; color: var(--title-ink); text-wrap: balance; }
.ward-app .st-hint { margin: 0 0 1.4rem; font-size: 0.95rem; line-height: 1.5; color: var(--muted); }
.ward-app .st-sub { margin: 1.25rem 0 0.6rem; font-size: 0.95rem; font-weight: 600; color: var(--ink-strong); }
.ward-app .st-fields { display: flex; flex-direction: column; gap: 0.9rem; }
.ward-app .sv-form .form-field { display: block; }
.ward-app .sv-form .form-field input { min-height: 3.25rem; font-size: 1.05rem; }
.ward-app .sv-form .form-field select {
  width: 100%;
  box-sizing: border-box;
  min-height: 3.25rem;
  padding: 0 0.75rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background-color: var(--surface-2);
  color: var(--ink-strong);
  font: inherit;
  font-size: 1.05rem;
}
.ward-app .st-area {
  width: 100%;
  box-sizing: border-box;
  min-height: 7rem;
  padding: 0.75rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--ink-strong);
  font: inherit;
  font-size: 1.05rem;
  line-height: 1.45;
  resize: vertical;
  outline: none;
}
.ward-app .st-area:focus,
.ward-app .sv-form .form-field select:focus { outline: none; border-color: var(--accent-2); }
.ward-app .row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
.ward-app .st-choices { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.ward-app .st-choices.is-big { flex-direction: column; flex-wrap: nowrap; gap: 0.75rem; }
.ward-app .st-choice { position: relative; display: block; flex: 1 1 auto; }
.ward-app .st-choice input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.ward-app .st-choice span {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  min-height: 3.25rem;
  padding: 0.7rem 1.1rem;
  border: 1.5px solid var(--line-strong);
  border-radius: 14px;
  background: var(--box);
  color: var(--ink-strong);
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.25;
}
.ward-app .is-big .st-choice span { min-height: 4rem; padding-left: 1.25rem; font-size: 1.15rem; }
.ward-app .st-choice span::before { content: ''; flex: none; width: 1.25rem; height: 1.25rem; box-sizing: border-box; border-radius: 50%; border: 2px solid var(--line-strong); background: var(--box); }
.ward-app .st-choice input:checked + span { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--box)); }
.ward-app .st-choice input:checked + span::before { border-color: var(--accent); background: var(--accent); box-shadow: inset 0 0 0 3px var(--box); }
.ward-app .st-choice input:focus-visible + span { outline: 3px solid var(--accent); outline-offset: 2px; }
.ward-app .st-err { margin: 0.6rem 0 0; font-size: 0.875rem; font-weight: 600; color: var(--danger); }
/* UNDER A PHONE'S KEYBOARD (Round 667, Derek: "When the user clicks the first
   name, it should auto scroll up so that the first name and the last name
   box are towards the top, and the submit button should be visible at the
   bottom"). The survey's viewport tag asks the keyboard to SHRINK the page
   (interactive-widget=resizes-content, survey.js), so on Android the page's
   100dvh and this sticky foot end where the keyboard begins and Next stands
   on it; an iPhone keeps the page its full height under the keyboard, so
   survey-steps.js measures the keyboard from the visual viewport and lifts
   the foot by it (--sv-kb). While a box is being typed in, the steps get
   room below (is-typing), so the boxes can be scrolled to the top of what
   is left of the screen with the heading above them out of the way. */
.ward-app.sv-app.is-typing .sv-steps { padding-bottom: 60dvh; }
.ward-app .sv-foot {
  position: sticky;
  bottom: var(--sv-kb, 0px);
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.9rem 1.25rem calc(env(safe-area-inset-bottom, 0px) + 1.1rem);
  border-top: 1px solid var(--line);
  background: var(--surface);
}
.ward-app .sv-back { appearance: none; flex: none; border: 0; background: none; padding: 0.5rem 0.25rem; font: inherit; font-weight: 600; color: var(--muted); cursor: pointer; }
.ward-app .sv-next { flex: 1 1 auto; min-height: 3.25rem; font-size: 1rem; }
.ward-app .sv-hp { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }
.ward-app .sv-error { margin: 0 1.25rem; padding: 0.6rem 0.8rem; border-radius: 10px; background: color-mix(in srgb, var(--danger) 12%, var(--card)); color: var(--danger); font-size: 0.875rem; font-weight: 600; }

/* THE THANK-YOU (Round 851, Derek: Round 693's candy coupon was "a little
   overboard and extra"; his pick of three drawn for him): the survey's brand
   line, then one white card in the page's own dress, centred in the viewport
   -- the tick in the accent disc (the sign-up sheet's, .su-mine-tick), "Thank
   you, Jane." in Caslon, the two lines in Garamond, each on a row of its own,
   and Back to the bulletin in the survey's own green button. Nothing here is
   fixed paper: the card and its words follow the theme. */
.ward-app.sv-thanks-app { display: flex; flex-direction: column; min-height: 100dvh; }
.ward-app .sv-thanks-top { padding: calc(env(safe-area-inset-top, 0px) + 1.1rem) 1.25rem 0; text-align: center; }
.ward-app .sv-thanks-top .sv-brand { margin: 0; }
.ward-app .sv-thanks {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: min(100%, 26rem);
  margin: 0 auto;
  padding: 1.5rem 1.5rem 2rem;
  box-sizing: border-box;
  text-align: center;
}
.ward-app .sv-thanks-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  padding: 2rem 1.5rem 1.6rem;
  box-sizing: border-box;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--box);
  box-shadow: 0 10px 26px rgba(42, 38, 31, 0.05);
}
.ward-app .sv-thanks-tick {
  display: grid;
  place-items: center;
  width: 3.5rem;
  height: 3.5rem;
  margin: 0 0 1.25rem;
  border-radius: 50%;
  background: var(--accent);
  color: var(--card);
}
.ward-app .sv-thanks-tick svg { width: 1.9rem; height: 1.9rem; }
.ward-app .sv-thanks-title { margin: 0 0 0.55rem; font-family: var(--display); font-weight: 400; font-size: 2.125rem; line-height: 1.12; color: var(--title-ink); text-wrap: balance; overflow-wrap: anywhere; }
.ward-app .sv-thanks-line { margin: 0; font-family: var(--serif); font-size: 1.2rem; line-height: 1.4; color: var(--ink-strong); }
.ward-app .sv-thanks-line + .sv-thanks-line { margin-top: 0.15rem; }
.ward-app .sv-thanks-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 3.25rem;
  margin-top: 1.9rem;
  box-sizing: border-box;
  font-size: 1rem;
  text-decoration: none;
}
[data-theme='dark'] .ward-app .sv-thanks-card,
.ward-app.is-dark .sv-thanks-card { background: rgba(14, 39, 29, 0.8); box-shadow: none; }
[data-theme='dark'] .ward-app .sv-thanks-tick,
.ward-app.is-dark .sv-thanks-tick { color: var(--bg); }

.ward-app .sv-foot-links { padding: 1.5rem 1rem 2.25rem; text-align: center; font-size: 0.8125rem; line-height: 1.6; color: var(--muted); }
.ward-app .sv-foot-links p { margin: 0.2rem 0; }
.ward-app .sv-foot-links a { color: var(--accent); }

/* ------------------------------------------------------------------ print */

@media print {
  /* Paper has no dark mode (Round 43). The footer's Dark switch puts
     data-theme on <html>, and its rules outranked these, so a page printed in
     dark came out in pale ink on white. Round 942 names each dark selector
     here and sets every token dark changes on something paper shows: from
     --forest on, the light palette's values, copied from the top of the file. */
  html.ward-html, body:not(.admin),
  html.ward-html[data-theme='dark'], [data-theme='dark'] body:not(.admin) { background: #fff; padding: 0; }
  [data-theme='dark'] body:not(.admin) { color: #3f4441; }
  .ward-app,
  [data-theme='dark'] .ward-app,
  .ward-app.is-dark {
    --surface: #fff; --card: #fff; --box: #fff; --bg: #fff; --ink-strong: #111; --title-ink: #111; --ink: #222; --body: #222;
    --muted: #555; --accent: #2f5d3e; --line: #ccc; --line-strong: #bbb; --accent-soft: #eee;
    --forest: #124f3d; --accent-2: #568a78; --accent-soft-2: #d2e6da; --surface-2: #f2ece1; --danger: #8c3b2e;
    --shadow: 0 8px 26px rgba(59, 48, 34, 0.07); --card-shadow: 0 5px 18px rgba(62, 51, 37, 0.055);
    color-scheme: light;
    width: 100%;
    box-shadow: none;
    border-radius: 0;
    min-height: 0;
  }
  /* Dark's card fill and button ink name no token (Round 942 review), so with
     Background graphics ticked the light ink above printed on dark green.
     Their light values under the dark rules' own selectors, later, so these
     win; the quiz's answer tints keep theirs. */
  [data-theme='dark'] .ward-app .event, .ward-app.is-dark .event,
  [data-theme='dark'] .ward-app .rem-item, .ward-app.is-dark .rem-item,
  [data-theme='dark'] .ward-app .bulletin-pinned .event-body, .ward-app.is-dark .bulletin-pinned .event-body,
  [data-theme='dark'] .ward-app .group-detail, .ward-app.is-dark .group-detail,
  [data-theme='dark'] .ward-app .h-order, .ward-app.is-dark .h-order,
  [data-theme='dark'] .ward-app .hq-choice:not(.is-right):not(.is-wrong), .ward-app.is-dark .hq-choice:not(.is-right):not(.is-wrong),
  [data-theme='dark'] .ward-app .sv-thanks-card, .ward-app.is-dark .sv-thanks-card { background-color: var(--box); }
  [data-theme='dark'] .ward-app .btn-primary, .ward-app.is-dark .btn-primary { color: #fff; }
  .ward-app .hero-photo,
  .ward-app .nav-wrap,
  .ward-app .theme-foot,
  .ward-app .segmented,
  .ward-app .filters,
  .ward-app .calendar-view,
  .ward-app .event-actions,
  .ward-app .event-act,
  .ward-app .wardcal,
  .ward-app .article-toolbar,
  .ward-app .chapter-nav,
  .ward-app .article-foot,
  .ward-app .gstart,
  .ward-app .chev,
  .lightbox { display: none !important; }
  .ward-app .hero-brand { margin-top: 0; background: none; }
  .ward-app .screen[hidden] { display: none !important; }
  .ward-app .event-detail,
  .ward-app .group-detail,
  .ward-app .acc-panel { display: block !important; }
  .ward-app .card { box-shadow: none; }
  .ward-app .event,
  .ward-app .group-detail { box-shadow: none; }
  .ward-app .group-meets { display: block; -webkit-line-clamp: none; line-clamp: none; overflow: visible; }
  /* A group's Text button prints as its words, with the number under them
     (the notices' Buttons do not print at all). */
  .ward-app .event-act.group-act { display: flex !important; }
  .ward-app .group-act .event-action { min-width: 0; padding: 0; background: none; box-shadow: none; color: var(--ink-strong); }
  .ward-app .group-act .event-action-chip { display: none; }
}

/* --------------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
  .ward-app *,
  .ward-app *::before,
  .ward-app *::after {
    animation: none !important;
    transition: none !important;
  }
  .lightbox,
  .lightbox *,
  .lightbox *::before,
  .lightbox *::after { animation: none !important; transition: none !important; }
}

/* Paper gets no hint that a hymn is a link (Round 455): the dotted rule is a
   screen affordance and prints as a stray underline. */
@media print {
  .ward-app .hymn-link .prog-sub { text-decoration: none; }
}

/* THE HOME-SCREEN OFFER (Round 459). A quiet centred line at the head of
   the footer -- somebody wants this AFTER the page has proved useful
   (Round 41) -- opening to numbered steps for the reader's own phone.
   install.js decides whether it shows; this only dresses it. The text
   link is the page's quiet-action rank: the accent, an underline at
   --ul-offset. */
.ward-app .install { margin: 0 0 1.25rem; text-align: center; }
.ward-app .install-link {
  font: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--accent);
  background: none;
  border: 0;
  padding: 0.5rem 0.25rem;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent);
  text-underline-offset: 0.2em;
}
.ward-app .install-why { margin: 0.1rem 0 0; font-size: 0.8125rem; color: var(--muted); }
.ward-app .install-panel { display: inline-block; max-width: 22rem; margin-top: 0.7rem; text-align: left; }
.ward-app .install-steps { margin: 0; padding-left: 1.3rem; font-size: 0.875rem; line-height: 1.5; }
.ward-app .install-steps li { margin-bottom: 0.4rem; }
.ward-app .install-caveat { margin: 0.5rem 0 0; font-size: 0.8125rem; font-style: italic; color: var(--muted); }
/* The iPhone's own "Already added it" line (Round 467) -- a quiet underlined
   sentence under the steps, in the muted ink. There is no 'No thanks' any
   more; the offer stands until the icon exists. */
.ward-app .install-done {
  font: inherit;
  font-size: 0.8125rem;
  color: var(--muted);
  background: none;
  border: 0;
  padding: 0.5rem 0 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
@media print { .ward-app .install { display: none !important; } }

/* AN OPENED NOTICE WITH NO DATE TAKES THE DATE COLUMN'S ROOM (Round 482,
   Derek: "If there is not a date associated with an announcement, then you
   can move the title of the announcement over to the left more when the
   user opens that card"). In the list an undated row keeps its empty date
   column so its title lines up with the dated rows beneath it (Round 469);
   once the card is open that alignment has nothing to serve, so the empty
   column goes and the title starts at the card's own edge. The row's
   data-date="" is the tell; .is-open is what ward.js sets on the row. The
   chevron keeps the width the collapsed row gives it at each breakpoint. */
/* Its three rules went in Round 502: no row has a date column any more, so
   an undated title already starts at the edge, open or shut. */

/* ---------------------------------------------------- the thought for the day
   Round 537 (Derek): a small box with a scripture that greets somebody the
   first time they open the page each day; ward.js decides when. It wears the
   Leader Tools Welcome tab's look (Round 523): the small-caps greeting, the
   fleuron, the passage in EB Garamond and its reference in italic, with a
   big x in the corner. The two Garamond faces are declared here as well as
   in styles.css; a browser fetches a face only when text is drawn in it, so
   a day the box does not show costs the page nothing. Above the page and
   under the picture viewer (90). */
@font-face {
  font-family: 'Ward Garamond';
  src: url('/garamond.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Ward Garamond';
  src: url('/garamond-italic.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

html.dt-open { overflow: hidden; }

.ward-app .daythought {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
}
.ward-app .daythought[hidden] { display: none; }
.ward-app .dt-scrim {
  position: absolute;
  inset: 0;
  background: rgba(20, 16, 10, 0.45);
  opacity: 0;
  transition: opacity 0.24s ease;
}
.ward-app .dt-card {
  position: relative;
  box-sizing: border-box;
  width: 100%;
  max-width: 24rem;
  padding: 2.9rem 1.6rem 2.1rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 24px 60px rgba(20, 16, 10, 0.28);
  text-align: center;
  opacity: 0;
  transform: translateY(0.75rem) scale(0.98);
  transition: opacity 0.24s ease, transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.ward-app .daythought.is-open .dt-scrim { opacity: 1; }
.ward-app .daythought.is-open .dt-card { opacity: 1; transform: none; }
.ward-app .dt-card:focus { outline: none; }

/* The big x Derek asked for: a 3rem target with a 2.4rem glyph. */
.ward-app .dt-close {
  position: absolute;
  top: 0.35rem;
  right: 0.35rem;
  width: 3rem;
  height: 3rem;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 0 0.2rem;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-strong);
  font: inherit;
  font-size: 2.4rem;
  font-weight: 300;
  line-height: 1;
  cursor: pointer;
}
@media (hover: hover) {
  .ward-app .dt-close:hover { background: var(--accent-soft); }
}
.ward-app .dt-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.ward-app .dt-hello {
  margin: 0;
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.ward-app .dt-fleuron { margin: 0.85rem auto 1.15rem; }
.ward-app .dt-quote { margin: 0; }
.ward-app .dt-text {
  margin: 0;
  color: var(--ink-strong);
  font-family: 'Ward Garamond', 'EB Garamond', Garamond, var(--serif);
  font-weight: 400;
  font-size: 1.42rem;
  line-height: 1.45;
  text-wrap: balance;
}
.ward-app .dt-ref {
  margin: 0.85rem 0 0;
  color: var(--accent);
  font-family: 'Ward Garamond', 'EB Garamond', Garamond, var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: 1.1rem;
}
/* ANOTHER THOUGHT (Round 539): the Leader Tools Welcome tab's control
   (.thought-again in styles.css) set on the ward's page -- small capitals in
   the accent over a hairline, a turning arrow before the words. Each press
   turns the arrow half a turn (--turns, set by ward.js) while the passage
   fades out and back. */
.ward-app .dt-quote { transition: opacity 0.17s ease; }
.ward-app .dt-quote.is-swapping { opacity: 0; }
.ward-app .dt-again {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 1.6rem;
  padding: 0.35rem 0.15rem 0.25rem;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 34%, transparent);
  border-radius: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: 0.75rem;
  font-weight: 650;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ward-app .dt-again::before {
  content: '\21bb';
  display: inline-block;
  font-size: 0.82rem;
  letter-spacing: 0;
  line-height: 1;
  transform: rotate(calc(var(--turns, 0) * -180deg));
  transition: transform 0.4s ease;
}
/* A thumb-sized target without moving the hairline (Round 24's idiom). */
.ward-app .dt-again::after { content: ''; position: absolute; inset: -0.75rem -0.6rem; }
@media (hover: hover) {
  .ward-app .dt-again:hover { color: var(--ink-strong); border-bottom-color: var(--ink-strong); }
}
.ward-app .dt-again:active { transform: translateY(1px); }
.ward-app .dt-again:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
@media (max-width: 30rem) {
  .ward-app .dt-text { font-size: 1.3rem; }
}
@media (prefers-reduced-motion: reduce) {
  .ward-app .dt-scrim,
  .ward-app .dt-card,
  .ward-app .dt-quote,
  .ward-app .dt-again::before { transition: none; }
}
@media print {
  .ward-app .daythought { display: none !important; }
  html.dt-open { overflow: visible; }
}

/* ------------------------------------------------------ the sign-up sheet */

/* A SIGN-UP SHEET ON A NOTICE (Round 679, src/signup.js): the privacy and
   survey pages' shell, then cards down one phone-width column -- the
   notice's own facts with the bulletin's date block, the tally against the
   goals, and the form. The bringing boxes are the survey's big choices as
   tick-boxes (.su-check squares the ring); a kind's questions stand in a
   ruled fieldset that signup.js shows only once the kind is ticked. The
   goal bars are <progress> elements: the page's policy allows no inline
   style, so no width is written on them. */
.ward-app.su-app { min-height: 100dvh; display: flex; flex-direction: column; }
/* 1.25rem of air above the first card since the masthead went (Round 700). */
.ward-app .su-main { width: min(100%, 34rem); margin: 0 auto; padding: 1.25rem 1rem 1.5rem; box-sizing: border-box; flex: 1 0 auto; }
/* The way back to the Bulletin tab (Round 712), above the first card on every
   sign-up page: a thumb-sized line, the page's own green, the arrow its own
   span so it never wraps away from the words. */
.ward-app .su-leave { margin: -0.35rem 0 0.6rem; }
.ward-app .su-leave-a,
.ward-app .pv-back-a {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 2.75rem;
  padding: 0.25rem 0.5rem 0.25rem 0;
  color: var(--accent);
  font-size: 0.9375rem;
  font-weight: 700;
  text-decoration: none;
}
.ward-app .su-leave-a:focus-visible,
.ward-app .pv-back-a:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: 10px; }
.ward-app .su-leave-x,
.ward-app .pv-back-x { font-size: 1.05rem; line-height: 1; }
.ward-app .su-main .card { margin: 0 0 0.85rem; }
.ward-app .su-event-row { display: flex; align-items: flex-start; gap: 0.9rem; }
.ward-app .su-event-copy { flex: 1 1 auto; min-width: 0; }
.ward-app .su-kicker { margin: 0 0 0.2rem; font-size: 0.66rem; font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase; color: var(--accent); }
.ward-app .su-title { margin: 0 0 0.35rem; font-family: var(--display); font-weight: 400; font-size: 1.6rem; line-height: 1.15; color: var(--title-ink); text-wrap: balance; overflow-wrap: anywhere; }
.ward-app .su-when,
.ward-app .su-where { margin: 0.15rem 0 0; font-size: 0.95rem; line-height: 1.4; color: var(--body); }
.ward-app .su-mi { display: inline-flex; align-items: center; gap: 0.3rem; }
.ward-app .su-mi .mi { width: 1em; height: 1em; flex: none; color: var(--muted); }
/* (.su-more, the card's link to the ward's page, went in Round 702.) */
.ward-app .su-h { margin: 0 0 0.7rem; font-family: var(--display); font-weight: 400; font-size: 1.3rem; line-height: 1.2; color: var(--title-ink); }
/* THE BOARD, PLAIN (Round 692, Derek's sketch): a block per kind under
   "What we still need" -- the kind's name, a dotted leader, the count --
   then the names of who has signed up as one line of text. */
.ward-app .su-cat { margin: 0.9rem 0 0; }
.ward-app .su-cat-head { display: flex; align-items: baseline; gap: 0.5rem; margin: 0; font-size: 1rem; font-weight: 700; line-height: 1.3; color: var(--ink-strong); }
.ward-app .su-cat-name { flex: none; }
.ward-app .su-cat-lead { flex: 1 1 auto; min-width: 1.5rem; border-bottom: 2px dotted var(--line-strong); transform: translateY(-0.3em); }
.ward-app .su-cat-count { flex: none; font-weight: 700; color: var(--muted); }
.ward-app .su-cat.is-met .su-cat-count { color: var(--accent); }
.ward-app .su-goal-line { display: block; margin: 0.3rem 0 0; font-size: 0.9rem; font-weight: 600; color: var(--accent); }
.ward-app .su-names { margin: 0.3rem 0 0; font-size: 0.95rem; line-height: 1.55; color: var(--body); overflow-wrap: anywhere; }
.ward-app .su-none { color: var(--muted); font-style: italic; }
.ward-app .su-bar { display: block; width: 100%; height: 0.5rem; margin-top: 0.3rem; border: 0; border-radius: 999px; background: var(--accent-soft); overflow: hidden; -webkit-appearance: none; appearance: none; }
.ward-app .su-bar::-webkit-progress-bar { background: var(--accent-soft); border-radius: 999px; }
.ward-app .su-bar::-webkit-progress-value { background: var(--accent); border-radius: 999px; }
.ward-app .su-bar::-moz-progress-bar { background: var(--accent); border-radius: 999px; }
.ward-app .su-full { display: block; margin-top: 0.3rem; font-size: 0.875rem; font-weight: 600; color: var(--danger); }
/* (.su-closes, the "Sign-ups close at" line over the form, went in Round 701.) */
.ward-app .su-closed p { margin: 0; font-weight: 600; color: var(--ink-strong); }
.ward-app .su-error { margin: 0 0 0.9rem; padding: 0.6rem 0.8rem; border-radius: 10px; background: color-mix(in srgb, var(--danger) 12%, var(--card)); color: var(--danger); font-size: 0.875rem; font-weight: 600; }
.ward-app .su-form fieldset { margin: 1.1rem 0 0; padding: 0; border: 0; min-width: 0; }
.ward-app .su-form .su-kind,
.ward-app .su-form .su-allergens { padding: 0.85rem 0.9rem 0.2rem; border: 1px solid var(--line); border-radius: 14px; background: var(--surface-2, var(--box)); }
.ward-app .su-legend { display: block; margin: 0 0 0.5rem; padding: 0; font-size: 0.8rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.ward-app .su-legend em { font-style: normal; text-transform: none; letter-spacing: 0; font-weight: 500; opacity: 0.8; }
.ward-app .su-kind .su-legend,
.ward-app .su-allergens .su-legend { float: left; margin-bottom: 0.6rem; }
.ward-app .su-kind .form-field,
.ward-app .su-kind .su-sub,
.ward-app .su-allergens .st-choices { clear: both; }
.ward-app .su-form .form-field { margin: 0.6rem 0 0.75rem; }
.ward-app .su-form .form-field:first-child { margin-top: 0; }
.ward-app .su-sub { margin: 0.9rem 0 0.45rem; font-size: 0.95rem; font-weight: 600; color: var(--ink-strong); }
.ward-app .su-opts .st-choice { flex: 1 1 8rem; }
.ward-app .su-opts .st-choice span { min-height: 2.9rem; padding: 0.55rem 0.9rem; font-size: 1rem; }
/* The kinds stack, one box each the same width, the tick and the word
   centred in it (Round 691, Derek: "the same size ... centered and just
   stacked on top of each other"). The allergen boxes keep their row. */
.ward-app .su-bring .su-opts { flex-direction: column; flex-wrap: nowrap; gap: 0.6rem; }
.ward-app .su-bring .su-opts .st-choice { flex: none; width: 100%; }
/* THE BOXES IN ONE COLUMN (Round 704, Derek: "make sure these check boxes ...
   are actually in vertical alignment with each other"): the words start at
   the left, after the box, so every box stands at the same distance from the
   pill's edge; a centred row put each box where its own words' width did.
   Round 705 tabbed them in to 2.75rem at Derek's word and Round 706 put them
   back at his ("Go back to what you had before. Just make them all left
   aligned in the left side of the row"). */
.ward-app .su-bring .su-opts .st-choice span { justify-content: flex-start; padding-left: 1.25rem; min-height: 3.1rem; }
.ward-app .su-check span::before { border-radius: 6px; }
.ward-app .su-check input:checked + span::before { box-shadow: inset 0 0 0 2.5px var(--box); }
.ward-app .st-choice.is-off span { opacity: 0.55; }
.ward-app .st-choice.is-off input { cursor: default; }
.ward-app .su-fulltag { margin-left: 0.35rem; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--danger); }
.ward-app .su-or { margin: 0.6rem 0; text-align: center; font-size: 0.8rem; font-weight: 700; letter-spacing: 0.15em; text-transform: uppercase; color: var(--muted); }
.ward-app .su-optw { display: flex; flex-direction: column; gap: 0.1rem; font-style: normal; min-width: 0; }
.ward-app .su-optl { font-weight: 600; }
.ward-app .su-opts-sub { font-size: 0.78rem; font-weight: 400; line-height: 1.3; color: var(--muted); }
/* The foot stacks: Sign me up alone on a new sign-up; on the Change page Save
   changes over "Keep it as it is" (Round 723), the quiet button at the
   primary's size and width, so a change of heart has somewhere to go. */
.ward-app .su-foot { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 1.25rem; }
.ward-app .su-submit { width: 100%; box-sizing: border-box; min-height: 3.1rem; font-size: 1rem; }
.ward-app .su-nevermind { display: inline-flex; align-items: center; justify-content: center; width: 100%; box-sizing: border-box; min-height: 3.1rem; font-size: 1rem; text-decoration: none; }
.ward-app .su-lead { margin: 0.25rem 0 1rem; font-size: 0.95rem; line-height: 1.5; color: var(--body); }
.ward-app .su-sum { margin: 0.5rem 0 0; display: flex; flex-direction: column; gap: 0.55rem; }
.ward-app .su-sum div { display: grid; grid-template-columns: 5.5rem minmax(0, 1fr); gap: 0.5rem; align-items: baseline; }
.ward-app .su-sum dt { margin: 0; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.ward-app .su-sum dd { margin: 0; font-size: 1rem; line-height: 1.45; color: var(--ink-strong); overflow-wrap: anywhere; }
.ward-app .su-sum-x { color: var(--muted); }
.ward-app .su-remind { margin: 1rem 0 0; padding: 0.8rem 0.9rem; border-radius: 12px; background: var(--accent-soft); color: var(--ink-strong); font-weight: 700; font-size: 1.05rem; line-height: 1.35; }
.ward-app .su-closedword { margin: 1rem 0 0; font-size: 0.9rem; color: var(--muted); }
.ward-app .su-acts { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1.1rem; }
.ward-app .su-acts .btn-primary,
.ward-app .su-acts .btn-quiet { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; box-sizing: border-box; }
.ward-app .su-inline { display: contents; }
.ward-app .su-danger { background: var(--danger); }
/* The printed "Your private link" block went in Round 711 (.su-link and its
   four parts with it): the confirmation page is that link. In its place, the
   sheet greets whoever this device already signed up (signup.js). */
/* Round 715 (Derek: "it needs to be much more obvious. I glanced right over
   the first couple times"): the page's green, a tick in a disc, the whole
   card a link with a chevron at its end. It is the one coloured card on a
   page of cream ones, so a returning signer cannot miss it. */
.ward-app a.su-mine {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: 0 6px 16px -12px var(--accent);
  color: var(--ink-strong);
  text-decoration: none;
}
.ward-app a.su-mine:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.ward-app .su-mine-tick {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background: var(--accent);
  color: var(--card);
}
.ward-app .su-mine-tick svg { width: 1.35rem; height: 1.35rem; }
.ward-app .su-mine-words { display: flex; flex-direction: column; gap: 0.3rem; min-width: 0; flex: 1 1 auto; }
.ward-app .su-mine-h { font-family: var(--display); font-size: 1.3125rem; line-height: 1.2; color: var(--title-ink); text-wrap: pretty; }
/* "Change or cancel" with the arrow at its shoulder (Round 716, Derek), not
   away at the card's edge. */
.ward-app .su-mine-sub { display: inline-flex; align-items: center; gap: 0.2rem; font-size: 0.9375rem; font-weight: 700; color: var(--accent); }
.ward-app .su-mine-x { flex: none; width: 1.1rem; height: 1.1rem; }
@media (hover: hover) {
  .ward-app a.su-mine:hover { border-color: var(--accent); background: var(--accent-soft-2); }
}
[data-theme='dark'] .ward-app .su-mine-tick,
.ward-app.is-dark .su-mine-tick { color: var(--bg); }
.ward-app .su-back { margin: 1rem 0 0; font-size: 0.875rem; }
.ward-app .su-back a { color: var(--accent); }
.ward-app .su-done.is-cancelled .su-sum { opacity: 0.7; }

/* THE CHILI COOK-OFF BALLOT (Round 903, src/vote.js, public/vote.js), in the
   sign-up sheet's dress: the heading and one line, then a card per prize --
   its name, a word on what it is voted from, and the dishes as rows, each
   its number in a disc and the dish's name beside it. A pressed row fills
   green with a tick at its end; the number's disc turns solid. Submit stands
   on the foot of the screen while the ballot scrolls. Once this phone has
   voted the ballot gives way to "Your vote is in" with the picks and Change
   my vote. */
.ward-app .vt-head { padding: 0.35rem 0.125rem 0.9rem; }
.ward-app .vt-title { margin: 0 0 0.35rem; font-family: var(--display); font-weight: 400; font-size: 2.125rem; line-height: 1.08; color: var(--title-ink); text-wrap: balance; }
.ward-app .vt-lead { margin: 0; font-family: var(--serif); font-size: 1.125rem; line-height: 1.4; color: var(--body); text-wrap: pretty; }
.ward-app .vt-cat { padding: 1rem 1rem 1.05rem; }
.ward-app .vt-cat-h { margin: 0; font-family: var(--display); font-weight: 400; font-size: 1.4rem; line-height: 1.2; color: var(--title-ink); }
.ward-app .vt-cat-hint { margin: 0.15rem 0 0; font-size: 0.875rem; line-height: 1.35; color: var(--muted); }
.ward-app .vt-rows { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.8rem; }
.ward-app .vt-row { position: relative; display: block; }
.ward-app .vt-row input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.ward-app .vt-row-in {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  min-height: 3.25rem;
  padding: 0.45rem 0.7rem 0.45rem 0.5rem;
  box-sizing: border-box;
  border: 1.5px solid var(--line-strong);
  border-radius: 14px;
  background: var(--box);
  color: var(--ink-strong);
  transition: background-color 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease, transform 0.12s ease;
}
.ward-app .vt-n {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.35rem;
  line-height: 1;
  font-variant-numeric: lining-nums tabular-nums;
  transition: background-color 0.12s ease, color 0.12s ease;
}
.ward-app .vt-dish { flex: 1 1 auto; min-width: 0; font-size: 1.05rem; font-weight: 600; line-height: 1.25; overflow-wrap: anywhere; }
.ward-app .vt-dish.is-unnamed { font-weight: 500; color: var(--body); }
.ward-app .vt-row-tick { flex: none; width: 1.5rem; height: 1.5rem; color: var(--accent); opacity: 0; transform: scale(0.6); transition: opacity 0.12s ease, transform 0.12s ease; }
.ward-app .vt-row-tick svg { width: 100%; height: 100%; }
.ward-app .vt-row input:checked + .vt-row-in { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--box)); box-shadow: 0 6px 16px -12px var(--accent); }
.ward-app .vt-row input:checked + .vt-row-in .vt-n { background: var(--accent); color: var(--card); }
.ward-app .vt-row input:checked + .vt-row-in .vt-row-tick { opacity: 1; transform: none; }
.ward-app .vt-row input:focus-visible + .vt-row-in { outline: 3px solid var(--accent); outline-offset: 2px; }
.ward-app .vt-row input:active + .vt-row-in { transform: scale(0.985); }
@media (hover: hover) {
  .ward-app .vt-row input:not(:checked):hover + .vt-row-in { border-color: var(--accent); }
}
.ward-app .vt-none { margin: 0.6rem 0 0; font-style: italic; color: var(--muted); }
.ward-app .vt-error { margin: 0.85rem 0 0; padding: 0.6rem 0.8rem; border-radius: 10px; background: color-mix(in srgb, var(--danger) 12%, var(--card)); color: var(--danger); font-size: 0.9rem; font-weight: 600; }
.ward-app .vt-foot {
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin: 0.85rem -1rem 0;
  padding: 0.75rem 1rem calc(0.85rem + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: var(--bg);
}
.ward-app .vt-submit { width: 100%; box-sizing: border-box; min-height: 3.25rem; font-size: 1.05rem; }
.ward-app .vt-note { margin: 0.5rem 0 0; text-align: center; font-size: 0.8125rem; line-height: 1.4; color: var(--muted); }
.ward-app .vt-done { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 1.75rem 1.25rem 1.4rem; }
.ward-app .vt-done-tick { display: grid; place-items: center; width: 3.25rem; height: 3.25rem; margin: 0 0 1rem; border-radius: 50%; background: var(--accent); color: var(--card); }
.ward-app .vt-done-tick svg { width: 1.75rem; height: 1.75rem; }
.ward-app .vt-done-h { margin: 0 0 0.9rem; font-family: var(--display); font-weight: 400; font-size: 1.9rem; line-height: 1.12; color: var(--title-ink); }
.ward-app .vt-picks { width: 100%; margin: 0 0 1rem; display: flex; flex-direction: column; text-align: left; }
.ward-app .vt-picks div { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 0.6rem; align-items: baseline; padding: 0.5rem 0; border-top: 1px solid var(--line); }
.ward-app .vt-picks div:last-child { border-bottom: 1px solid var(--line); }
.ward-app .vt-picks dt { margin: 0; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.ward-app .vt-picks dd { margin: 0; font-size: 1rem; font-weight: 600; line-height: 1.3; color: var(--ink-strong); text-align: right; overflow-wrap: anywhere; }
.ward-app .vt-pick-n { display: inline-grid; place-items: center; min-width: 1.6rem; height: 1.6rem; padding: 0 0.3rem; margin-right: 0.2rem; border-radius: 999px; background: var(--accent); color: var(--card); font-family: var(--display); font-weight: 400; font-size: 0.95rem; line-height: 1; vertical-align: 0.1em; }
.ward-app .vt-done-sub { margin: 0; font-family: var(--serif); font-size: 1.1rem; color: var(--body); }
.ward-app .vt-change { margin-top: 1.1rem; width: 100%; box-sizing: border-box; min-height: 3rem; font-size: 1rem; }
.ward-app .vt-closed { text-align: center; padding: 1.75rem 1.25rem 1.4rem; }
.ward-app .vt-closed-h { margin: 0 0 0.5rem; font-family: var(--display); font-weight: 400; font-size: 1.75rem; line-height: 1.12; color: var(--title-ink); text-wrap: balance; }
.ward-app .vt-closed-p { margin: 0; font-family: var(--serif); font-size: 1.1rem; line-height: 1.4; color: var(--body); }
[data-theme='dark'] .ward-app .vt-done-tick,
.ward-app.is-dark .vt-done-tick,
[data-theme='dark'] .ward-app .vt-pick-n,
.ward-app.is-dark .vt-pick-n,
[data-theme='dark'] .ward-app .vt-row input:checked + .vt-row-in .vt-n,
.ward-app.is-dark .vt-row input:checked + .vt-row-in .vt-n { color: var(--bg); }
