/* 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;
}

[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;
  --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: '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;
  --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;
  /* 24% (Round 419, from 20; Round 406 from 16): 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'). The one wash now that one photograph
     serves every tab (Round 397); the old placeholders wore 20-30%. Dark
     below moves in step. */
  background: rgba(255, 252, 245, 0.24);
}

.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;
  padding: 0.5rem 0.625rem 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, 1fr);
  background: var(--nav-surface);
  border: 1px solid var(--line);
  border-radius: 17px;
  box-shadow: 0 7px 22px rgba(46, 40, 31, 0.06);
  overflow: hidden;
}

.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; }
[data-theme='dark'] .ward-app .nav-btn.is-active,
.ward-app.is-dark .nav-btn.is-active { background: rgba(114, 175, 148, 0.24); }
[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); }

/* 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;
}

/* 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);
}

.ward-app .prog-theme { text-align: center; margin-top: 0.5rem; }
.ward-app .prog-theme-l {
  display: block;
  margin-bottom: 0.25rem;
  font-size: 0.625rem;
  font-weight: 800;
  letter-spacing: 0.2em;
  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 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.625rem;
  font-weight: 800;
  line-height: 1.35;
  letter-spacing: 0.15em;
  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;
}
.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);
}

/* 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:hover .prog-sub,
.ward-app .hymn-link:focus-visible .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: label and name on one line, set tight. */
.ward-app .prog-row.is-officer { padding: 0.1rem 0; }
.ward-app .prog-row.is-officer .prog-label { display: inline-block; margin: 0 0.55rem 0 0; vertical-align: 0.12em; }
.ward-app .prog-row.is-officer .prog-value { display: inline; 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;
  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);
}
.ward-app .prog-divider-d {
  margin: -0.2rem 0 0.7rem;
  text-align: center;
  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. */
.ward-app .after-p {
  margin: 0 0 0.5rem;
  font-family: var(--serif);
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--body);
}
.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; }
.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; }

.ward-app .reminders {
  margin: 0.25rem 0 0;
  padding: 0 0.25rem;
  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; }

.ward-app .acc-btn {
  width: 100%;
  min-height: 3.6rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 1.05rem 0 1rem;
  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); }
.ward-app .rem-when {
  display: block;
  font-size: 0.625rem;
  font-weight: 800;
  letter-spacing: 0.13em;
  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). */
.ward-app .rem-names { font-family: var(--display); font-weight: 650; 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; }
.ward-app .rem-miss-name {
  margin: 0;
  font-family: var(--display);
  font-weight: 650; /* bold at Derek's word (Round 426); synthesised, as .rem-names */
  font-size: 1.125rem;
  line-height: 1.25;
  color: var(--ink-strong);
}
.ward-app .rem-miss-mission,
.ward-app .rem-miss-email { margin: 0.1rem 0 0; font-size: 0.8125rem; color: var(--muted); }
.ward-app .rem-miss-email a { color: var(--accent); overflow-wrap: anywhere; }

/* 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;
}
.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; }

/* .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. */

.ward-app .events { border-top: 1px solid var(--line); }
.ward-app .event { border-bottom: 1px solid var(--line); }

.ward-app .event-summary {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  display: grid;
  grid-template-columns: 4.25rem minmax(0, 1fr) 1.5rem;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem 0.125rem 0.95rem;
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ward-app .event-when {
  font-size: 0.6875rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--accent);
}
/* A row dated today reads TODAY (Round 487, Derek: 'slightly larger than
   typical'): the same accent small caps as the day beside the other rows,
   a step up, and heavier. It still fits the 4.25rem (4rem on a phone)
   when-column: five tracked capitals at this size run about 3.5rem. */
.ward-app .event-when.is-today {
  font-size: 0.8125rem;
  font-weight: 900;
  letter-spacing: 0.1em;
}
.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;
  line-height: 1.17;
  color: var(--ink-strong);
  transition: color 0.15s ease;
}
.ward-app .event-summary:hover .event-title { color: var(--accent); }
.ward-app .event-meta {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.75rem;
  line-height: 1.35;
  color: var(--muted);
}
.ward-app .event-summary .chev { justify-self: end; color: var(--accent); }
.ward-app .event-summary[aria-expanded='true'] .chev-right { transform: rotate(90deg); }

/* THE OPEN ROW IS ONE WHITE BOX (Round 448, Derek: "the title should just
   also be included in that white box"). Until this round the box was
   drawn round .event-detail alone, so an opened announcement read as its
   title on the page's ground with its details in a card beneath -- two
   boxes for one thing. Now the ROW (.event.is-open, set by ward.js beside
   the button's aria-expanded) is the box: the opened-item off-white
   (Round 430; pure white in Round 423), the hairline, the soft shadow and
   the 5px accent band across its head, with the title inside it and the
   details below on the same ground. The detail box itself is transparent
   and edgeless inside it; the accent bar that sat at the top of the
   details is gone, since the band is the box's own top edge now. The
   glide (Round 427) still animates the detail's height inside the box. */
.ward-app .event.is-open {
  margin: 0.4rem 0 0.75rem;
  border: 1px solid var(--line);
  border-top: 5px solid var(--accent);
  background: var(--box);
  box-shadow: 0 7px 19px rgba(42, 38, 31, 0.035);
}
.ward-app .event.is-open .event-summary { padding-inline: 1.25rem 1rem; }
.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.is-open,
.ward-app.is-dark .event.is-open { 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;
  padding: 1.1rem 1.25rem 1.2rem;
}
.ward-app .event-none { margin: 0; font-size: 0.8125rem; 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); }

.ward-app .event-description p,
.ward-app .event-description li {
  font-size: 0.84375rem;
  line-height: 1.58;
  color: var(--body);
}
.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; }

/* 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 { margin: 0 0 0.15rem; }
.ward-app .rem-text li::marker,
.ward-app .event-description 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; }

.ward-app .event-actions { margin-top: 1rem; }

/* 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; }
.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.71875rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  cursor: pointer;
}
.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:hover,
.ward-app .calmenu .calmenu-item:focus-visible { background: var(--accent-soft); }
.ward-app .calicon { width: 1.15em; height: 1.15em; flex: none; }
.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 {
  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;
}
.ward-app .cal-head strong {
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.5rem;
  color: var(--ink-strong);
}
.ward-app .cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 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;
  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;
  min-width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
}
.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. */
.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);
}
.ward-app .sel-empty { margin: 0; font-size: 0.8125rem; color: var(--muted); }
/* 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:first-child { border-top: 1px solid var(--line); }

.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;
  grid-template-columns: 1fr 1.25rem;
  align-items: center;
  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-name { font-family: var(--display); font-size: 1.125rem; color: var(--ink-strong); }
.ward-app .group-row .chev { 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; }
.ward-app .group-meets {
  margin: 0 0 0.6rem;
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.9375rem;
  line-height: 1.4;
  color: var(--accent);
}
.ward-app .group-meets.is-muted { color: var(--muted); }
.ward-app .group-contact {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.75rem;
  margin: 0;
  color: var(--muted);
}
.ward-app .group-contact-l {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.ward-app .group-tel {
  display: inline-flex;
  align-items: center;
  min-height: 2.4rem;
  padding: 0.3rem 0.85rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-family: var(--serif);
  font-size: 1rem;
  color: var(--ink-strong);
  text-decoration: none;
}
.ward-app a.group-tel:hover { background: var(--accent-soft); border-color: var(--accent-2); }

.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;
}
.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);
}
.ward-app .gform-lead { margin: 0 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); }
.ward-app .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
.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 history */

/* 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; }
.ward-app .history-lead p {
  margin: 0.5rem 0 0;
  font-family: var(--serif);
  font-size: 0.9375rem;
  line-height: 1.52;
  color: var(--body);
}

.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. */
  padding: 0.125rem 2.5rem 0.75rem;
  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; } }
.ward-app .carousel-dots {
  display: flex;
  justify-content: center;
  gap: 0.4rem;
  margin: 0 0 1rem;
}
.ward-app .carousel-dots 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 .carousel-dots i.is-on { width: 1.1rem; 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: grayscale(0.72) sepia(0.1);
}
.ward-app .thumb-body {
  display: block;
  padding: 0.85rem 1rem 0.95rem;
}
/* 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;
}
.ward-app .chapter-pos {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.ward-app .article { scroll-margin-top: 5rem; }
.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);
}
.ward-app .article-lede p {
  margin: 0 auto 1.125rem;
  max-width: 22.5rem;
  text-align: center;
  font-family: var(--serif);
  font-size: 1.0625rem;
  line-height: 1.55;
  color: var(--muted);
}
.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; }

.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: 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;
}
.ward-app .hplate img {
  display: block;
  width: 100%;
  height: 9rem;
  object-fit: cover;
  filter: grayscale(0.8) sepia(0.12);
}
.ward-app .hshots:not(.is-many) .hplate img { height: auto; max-height: 24rem; }
.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; }
.ward-app .bishop-cap strong {
  display: block;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 0.9375rem;
  line-height: 1.25;
  color: var(--ink-strong);
}
.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);
}
.ward-app .bishop-note { margin: 0.35rem 0 0; font-size: 0.75rem; line-height: 1.4; color: var(--muted); }

.ward-app .timeline { display: grid; gap: 0.75rem; margin-top: 0.625rem; }
.ward-app .timeline-row { display: grid; grid-template-columns: 4rem 1fr; gap: 0.75rem; align-items: start; }
.ward-app .timeline-year {
  padding: 0.45rem 0.3rem;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-align: center;
}
.ward-app .timeline-text p {
  margin: 0;
  font-family: var(--serif);
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--body);
}

.ward-app .chapter-nav { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5625rem; margin-top: 1.25rem; }
.ward-app .chapter-nav button {
  min-height: 2.75rem;
  padding: 0.65rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--card);
  color: var(--accent);
  font-size: 0.75rem;
  font-weight: 800;
  line-height: 1.25;
  cursor: pointer;
}
.ward-app .chapter-nav button:disabled { opacity: 0.35; cursor: default; }
.ward-app .article-foot { margin: 0.9rem 0 0; text-align: center; }
.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; }
.ward-app .disclaimer {
  margin: 0;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--muted);
  text-wrap: balance;
}
.ward-app .updated { margin: 0.35rem 0 0; font-size: 0.6875rem; color: var(--muted); opacity: 0.8; }
.ward-app .themepick {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin: 1.25rem 0 0;
  font-size: 0.75rem;
  color: var(--muted);
}
.ward-app .themepick-label { margin-right: 0.2rem; }
.ward-app .themepick button {
  min-height: 2rem;
  padding: 0.3rem 0.75rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 700;
  cursor: pointer;
}
.ward-app .themepick button[aria-pressed='true'] {
  background: var(--accent-soft);
  border-color: var(--accent-2);
  color: var(--accent);
}

/* ----------------------------------------------------------- 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; }

.lb-close,
.lb-step {
  position: absolute;
  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); }
.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 { grid-template-columns: 4rem minmax(0, 1fr) 1.375rem; gap: 0.55rem; }
  .ward-app .event-title { font-size: 1.1875rem; }
  .ward-app .event-body { grid-template-columns: 3.6rem minmax(0, 1fr); gap: 0.8rem; padding: 1.2rem 0.95rem 1.05rem; }
  .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 .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 .themepick,
html:not(.js) .ward-app .article-toolbar,
html:not(.js) .ward-app .chapter-nav,
html:not(.js) .ward-app .article-foot { display: none !important; }

/* ------------------------------------------------------------------ print */

@media print {
  html.ward-html, body:not(.admin) { background: #fff; padding: 0; }
  .ward-app,
  .ward-app.is-dark {
    --surface: #fff; --card: #fff; --box: #fff; --bg: #fff; --ink-strong: #111; --ink: #222; --body: #222;
    --muted: #555; --accent: #2f5d3e; --line: #ccc; --line-strong: #bbb; --accent-soft: #eee;
    color-scheme: light;
    width: 100%;
    box-shadow: none;
    border-radius: 0;
    min-height: 0;
  }
  .ward-app .hero-photo,
  .ward-app .nav-wrap,
  .ward-app .themepick,
  .ward-app .segmented,
  .ward-app .filters,
  .ward-app .calendar-view,
  .ward-app .event-actions,
  .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.is-open,
  .ward-app .group-detail { box-shadow: 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. */
.ward-app .event.is-open[data-date=""] .event-summary { grid-template-columns: minmax(0, 1fr) 1.5rem; }
.ward-app .event.is-open[data-date=""] .event-when.is-undated { display: none; }
@media (max-width: 30rem) {
  .ward-app .event.is-open[data-date=""] .event-summary { grid-template-columns: minmax(0, 1fr) 1.375rem; }
}
