/* Layered on top of Bootstrap 5.
   Base type is deliberately larger than Bootstrap's default with generous
   line-height: the Society's members are largely OCS alumni, who skew older,
   and readability matters more here than density. Page background stays white. */

:root {
  --ink: #1a1a1a;
  --muted: #5a5a5a;
  --rule: #ddd8cf;
  --accent: #14532d;       /* deep green */
  --accent-dark: #0e3a20;
  --gold: #b08d3f;
  --measure: 40rem;
}

body {
  background: #fff;
  color: var(--ink);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.0625rem;
  line-height: 1.7;
}

h1, h2, h3, h4 { color: var(--accent); line-height: 1.25; }
a { color: var(--accent); }
a:hover { color: var(--accent-dark); }
:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }

.skip-link { position: absolute; left: -9999px; }
.skip-link:focus {
  position: fixed; left: 1rem; top: 1rem; z-index: 2000;
  background: #fff; padding: .5rem 1rem; border: 2px solid var(--accent);
}

/* ---- Navbar ---------------------------------------------------------- */

.site-nav { box-shadow: 0 1px 3px rgba(0,0,0,.05); }
.navbar-brand { display: flex; align-items: center; gap: .75rem; font-weight: 700; padding-block: .25rem; }
/* Height-constrained so the crest sets the navbar height predictably; width
   follows its own aspect ratio. The crest carries its own "ARMY / HERITAGE
   SOCIETY" lettering, but at this size that lettering is not readable, so the
   wordmark beside it is doing the actual work of naming the Society. */
.brand-logo { height: 76px; width: auto; display: block; }
.brand-text { color: #000; font-size: 1.5rem; line-height: 1.2; letter-spacing: -.005em; }

@media (max-width: 575.98px) {
  .brand-logo { height: 54px; }
  .brand-text { font-size: 1.15rem; }
}
/* Two-row bar from lg up: the brand keeps the first line, the links get the
   second. The container is allowed to wrap and the collapse is forced to a full
   line, which is what pushes it below the brand -- Bootstrap otherwise lays the
   collapse out beside it and the two fight over the width.

   Why this rather than the alternatives: see the comment in templates/base.html.
   Short version -- dropdowns hide sections, a smaller font undoes a deliberate
   sizing decision, and an earlier hamburger hides everything. */
@media (min-width: 992px) {
  .site-nav > .container-fluid { flex-wrap: wrap; }
  .site-nav .navbar-collapse {
    flex: 0 0 100%;
    /* The links sit under the brand, so the row needs a hairline above it and a
       little breathing room -- without it the two rows read as one crowded block. */
    border-top: 1px solid #efece4;
    margin-top: .35rem;
    padding-top: .1rem;
  }
  /* Both lists share the row: sections from the left, actions pushed right. */
  .site-nav .navbar-collapse { display: flex; align-items: center; flex-wrap: wrap; }
  .site-nav .nav-sections { flex: 0 1 auto; flex-wrap: wrap; row-gap: .15rem; }
  /* Wrapping is deliberate. Just above the lg breakpoint the ten items and the
     Donate button are a close fit, and the width depends on the visitor's font.
     Allowed to wrap, a tight window gets a second line of links; forbidden, it
     gets a horizontal scrollbar or items pushed off the edge. */

  /* The bar is sticky, so two rows must not eat the viewport. The brand row
     carries the height, and its padding comes down to pay for the second. */
  .site-nav .navbar-brand { padding-block: .1rem; }
  .site-nav { padding-block: .25rem; }
}

.site-nav .nav-link {
  color: var(--ink); font-family: system-ui, -apple-system, sans-serif;
  font-size: 1.15rem; padding-inline: .5rem;
  border-bottom: 2px solid transparent;
}
/* Align the first section with the crest above it rather than sitting .5rem in. */
@media (min-width: 992px) {
  .site-nav .nav-sections > .nav-item:first-child .nav-link { padding-inline-start: 0; }
}
.site-nav .nav-link:hover, .site-nav .nav-link:focus {
  color: var(--accent); border-bottom-color: var(--accent);
}
/* Donate reads as a button, not a nav link: it is the one action on the bar
   and needs to look different from navigation. Gold picks up the hero's call
   to action so the two read as the same kind of thing. */
.nav-donate-item { margin-left: .4rem; }
.nav-donate {
  display: inline-block;
  background: var(--gold);
  color: #1a1a1a;
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: .02em;
  padding: .42rem 1.05rem;
  border-radius: 3px;
  text-decoration: none;
  white-space: nowrap;
}
.nav-donate:hover, .nav-donate:focus { background: #c79c46; color: #1a1a1a; }

/* In the collapsed menu it sits on its own row, so give it breathing room
   rather than letting it hug the links above it. */
@media (max-width: 1199.98px) {
  .nav-donate-item { margin: .5rem 0 .25rem; }
  .nav-donate { display: block; text-align: center; }
}

/* ---- Hero ------------------------------------------------------------ */

.hero {
  position: relative;
  background-image: linear-gradient(rgba(12,17,12,.58), rgba(12,17,12,.78)), var(--hero-img);
  background-size: cover;
  background-position: center;
  color: #fff;
  padding: clamp(3.5rem, 11vw, 8rem) 0;
}
/* Home hero: a photograph under a green-tinted scrim, set as light as the
   contrast budget allows so the collage still reads.

   Measured properly — by compositing the scrim over the image in Pillow rather
   than sampling the rendered page, which only picks up the anti-aliased halo
   around the white glyphs and reports nonsense. Worst-case contrast against
   white across the whole photograph at this strength is 7.4:1, clearing WCAG
   AAA, not merely AA. The tint keeps it in the site's palette rather than
   going flat grey. */
.hero-photo {
  background-image:
    linear-gradient(rgba(22,30,19,.74), rgba(16,23,14,.80)),
    var(--hero-img);
  background-size: cover;
  background-position: center;
}

/* No max-width of its own: the Bootstrap .container it also carries sets the
   width, so the lockup spans the full section rather than a narrower column. */
.hero-inner { max-width: none; }

/* Home hero: a crest at each edge with the wordmark centred between them.
   space-between pushes the marks to the outside and lets the text block take
   the middle, so the three fill the section's width. */
.hero-brand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1rem, 3vw, 2.5rem);
  /* Inset each edge by 15% of the section width, so the marks sit inboard of
     the container edges rather than hard against them. space-between then
     distributes within the inset box. Removed below md, where the row wraps
     and the inset would only squeeze the wordmark. */
  padding-inline: 15%;
}
.hero-logo {
  height: clamp(158px, 20.2vw, 274px);
  width: auto;
  flex: none;
  filter: drop-shadow(0 4px 18px rgba(0,0,0,.5));
}
.hero-brand-text {
  flex: 1 1 auto;
  max-width: 40rem;
  text-align: center;
  margin-inline: auto;
}
.hero-roundel {
  height: clamp(138px, 15.8vw, 245px);
  width: auto;
  flex: none;
  filter: drop-shadow(0 4px 18px rgba(0,0,0,.5));
}

/* Below md the two marks sit side by side on one row with the wordmark on its
   own row beneath, all centred. Stacking all three in a single column would
   push the text most of a screen down, and setting them side by side with the
   text would leave the title in a column a few words wide. */
@media (max-width: 767.98px) {
  .hero-brand { flex-wrap: wrap; text-align: center; gap: 1.25rem; padding-inline: 0; }
  .hero-logo { order: 1; height: 150px; }
  .hero-roundel { order: 2; height: 138px; }
  .hero-brand-text { order: 3; flex: 0 0 100%; max-width: none; }
  .hero-lede { margin-inline: auto; }

  /* A banner is not the home page. Those heights are the opening statement of
     the site; on a phone, in a page banner, two marks that size push the heading
     most of a screen down before a word is read. */
  .hero-brand-compact { gap: .9rem; }
  .hero-brand-compact .hero-logo { height: 92px; }
  .hero-brand-compact .hero-roundel { height: 84px; }
}
.hero-eyebrow {
  font-family: system-ui, sans-serif; text-transform: uppercase;
  letter-spacing: .16em; font-size: .8rem; color: #e8e2d4; margin-bottom: 1rem;
}
.hero-title { color: #fff; font-size: clamp(1.9rem, 4.2vw, 3.1rem); margin-bottom: 1rem; }
.hero-lede { font-size: clamp(1.05rem, 1.7vw, 1.3rem); color: #f1ece1; max-width: 36rem; margin: 0 auto 1.75rem; }
/* The single most arresting fact the Society has, given the room it deserves
   instead of sitting in body copy below the fold. */
.hero-stat {
  margin: 0 auto 1.75rem;
  max-width: 40rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .15rem;
}
.hero-stat-figure {
  font-size: clamp(2.2rem, 5vw, 3.4rem);
  font-weight: 700;
  line-height: 1;
  color: var(--gold);
  letter-spacing: -.01em;
  text-shadow: 0 2px 14px rgba(0,0,0,.45);
}
.hero-stat-label {
  /* balance stops the last word orphaning onto a line of its own when the
     label does wrap at narrower widths. */
  text-wrap: balance;
  font-family: system-ui, -apple-system, sans-serif;
  font-size: clamp(.72rem, 1.05vw, .82rem);
  text-transform: uppercase;
  letter-spacing: .14em;
  color: #e8e2d4;
  line-height: 1.5;
}

.btn-hero {
  background: var(--gold); color: #1a1a1a; border: none; font-weight: 700;
  font-family: system-ui, sans-serif; letter-spacing: .04em; padding: .85rem 2rem;
}
.btn-hero:hover, .btn-hero:focus { background: #c79c46; color: #1a1a1a; }

/* Interior pages get a shorter banner than the home hero: it announces the
   page without pushing the content below the fold. */
.hero-compact { padding: clamp(2.25rem, 6vw, 4.25rem) 0; }

/* Smoke: charcoal to near-black with two soft hazes, for a banner that carries
   the Society's marks instead of a photograph. No image, so nothing to load and
   nothing to go stale.

   MEASURED, not guessed -- the same discipline as the photo scrim above, and the
   same trap to avoid (sampling a screenshot inside a text block reads the
   anti-aliased halo around the glyphs and reports nonsense). Composited in
   Python instead: worst case is both haze layers stacked on the lightest stop of
   the base gradient, giving #434645. Against that:

       white #fff        9.54:1
       .hero-lede        8.10:1
       .hero-eyebrow     7.39:1   <- the binding constraint

   All three clear WCAG AAA (7:1). The eyebrow is the one that binds, which is
   why the base is this dark: at #3c3f3d, an obvious first choice, the eyebrow
   came out at 5.06:1 -- fine for AA, below the standard the rest of this site
   holds. Lighten the base or strengthen the hazes and that figure is what breaks
   first, so re-measure rather than eyeball it. */
.hero-smoke {
  background-color: #0b0c0d;
  background-image:
    radial-gradient(120% 85% at 18% 18%, rgba(255,255,255,.07), rgba(255,255,255,0) 60%),
    radial-gradient(95% 70% at 84% 88%, rgba(255,255,255,.05), rgba(255,255,255,0) 55%),
    linear-gradient(160deg, #2a2d2c 0%, #1b1e1f 45%, #0b0c0d 100%);
}

/* The home hero's lockup at banner scale. The marks are roughly half the height
   they are on the home page: there they ARE the page's opening, here they flank
   one line of heading on a band a third the depth, and at home-page size they
   would dwarf the wording they are meant to frame.

   The shield stays the larger of the two, in the same proportion as the home
   hero -- they are not the same shape and matching their heights makes the
   roundel look oversized. */
.hero-brand-compact {
  /* Far less inset than the home hero's 15%: this band is shorter, so the marks
     sit nearer the text rather than stranded at the container edges. */
  padding-inline: clamp(0rem, 4vw, 3rem);
  gap: clamp(1rem, 4vw, 3rem);
}
.hero-brand-compact .hero-logo { height: clamp(84px, 11vw, 150px); }
.hero-brand-compact .hero-roundel { height: clamp(76px, 9.8vw, 134px); }
/* The lede is centred between two marks here, not running the full width. */
.hero-brand-compact .hero-brand-text { max-width: 44rem; }
.hero-compact .hero-title { font-size: clamp(1.7rem, 3.4vw, 2.6rem); margin-bottom: .75rem; }
.hero-compact .hero-lede { margin: 0 auto; font-size: clamp(1rem, 1.5vw, 1.15rem); }

/* A page with a hero already has its title; its prose starts with an h2, so it
   does not need the large top margin an h1-less page would want. */
.hero + main .prose > h2:first-child { margin-top: 0; }

/* ---- Alternating image / text bands ---------------------------------- */

.band { display: grid; grid-template-columns: 1fr; }
.band-media {
  /* --band-bg fills the letterbox when a band uses --band-size: contain. Set it
     to the image's own ground colour and the fit is invisible. */
  background-color: var(--band-bg, transparent);
  background-image: var(--band-img);
  /* --band-size lets a band zoom past `cover`. Needed when the subject occupies
     one corner of a photograph: at `cover` the crop is whatever the aspect
     mismatch happens to leave, which may not be the part worth showing. */
  background-size: var(--band-size, cover);
  background-position: var(--band-pos, center);
  background-repeat: no-repeat;
  min-height: 15rem;
}
.band-body { background: #fff; display: flex; align-items: center; }
.band-copy { padding: clamp(2rem, 5vw, 4rem); max-width: 34rem; }
.band-eyebrow {
  font-family: system-ui, sans-serif; text-transform: uppercase;
  letter-spacing: .14em; font-size: .75rem; color: var(--gold); margin-bottom: .5rem;
}
.band-copy h2 { font-size: clamp(1.5rem, 2.6vw, 2.1rem); margin-bottom: .75rem; }
.band + .band { border-top: 1px solid var(--rule); }

@media (min-width: 992px) {
  .band { grid-template-columns: 1fr 1fr; min-height: 26rem; }
  .band-media { min-height: 100%; }
  /* Flip only on wide screens. On phones the image always comes first so the
     reading order stays image-then-text throughout. */
  .band-reverse .band-media { grid-column: 2; grid-row: 1; }
  .band-reverse .band-body { grid-column: 1; grid-row: 1; justify-content: flex-end; }
}

/* A band whose TEXT half goes dark instead of white. Keeps the half-width
   image layout while giving the section the contrast a full-bleed photographic
   band had. Used sparingly — one or two per page, or it stops being emphasis
   and the page simply becomes dark. */

.band-dark .band-body { background: #141a14; }
.band-dark .band-copy h2 {
  color: #fff;
  font-weight: 700;
  text-shadow: 0 2px 10px rgba(0,0,0,.35);
}
.band-dark .band-copy p { color: #e9e4d8; font-weight: 600; }
.band-dark .band-eyebrow { color: #d8bf80; }
.band-dark .btn-accent { background: var(--gold); color: #16200f; }
.band-dark .btn-accent:hover, .band-dark .btn-accent:focus { background: #c79c46; color: #16200f; }

.btn-accent {
  background: var(--accent); color: #fff; border: none; font-weight: 600;
  font-family: system-ui, sans-serif; padding: .6rem 1.4rem;
}
.btn-accent:hover, .btn-accent:focus { background: var(--accent-dark); color: #fff; }

/* ---- Prose ----------------------------------------------------------- */

.prose { max-width: var(--measure); }
.prose.mx-auto { margin-inline: auto; }
.prose h1 { font-size: clamp(1.8rem, 3.4vw, 2.4rem); margin-bottom: 1rem; }
.prose h2 { font-size: 1.5rem; margin-top: 2.25rem; margin-bottom: .6rem; }
.prose ul { padding-left: 1.2rem; }
.prose li { margin-bottom: .4rem; }
.lede, .lead-statement { font-size: 1.2rem; color: var(--muted); }
.lead-statement { color: var(--ink); }
.note { color: var(--muted); font-size: .95rem; }

/* ---- Explore cards --------------------------------------------------- */

/* Warm paper fill rather than white-on-white, with the border warmed to match.
   A gold rule under each heading ties them to the site's accent without adding
   another box. Kept flat and quiet: six cards with heavy shadows or gradients
   would look like a marketing page, which is not the register of this site. */
.explore-card {
  display: block;
  height: 100%;
  padding: 1.15rem 1.3rem 1.25rem;
  background: #faf8f3;
  border: 1px solid #e2dccf;
  border-radius: 4px;
  text-decoration: none;
  color: var(--ink);
  transition: background .15s ease, border-color .15s ease,
              box-shadow .15s ease, transform .15s ease;
}
.explore-card:hover, .explore-card:focus {
  background: #fff;
  border-color: var(--accent);
  box-shadow: 0 4px 14px rgba(20, 83, 45, .10);
  transform: translateY(-2px);
  color: var(--ink);
}
.explore-card strong {
  display: block;
  color: var(--accent);
  margin-bottom: .45rem;
  padding-bottom: .4rem;
  border-bottom: 2px solid var(--gold);
}
.explore-card span {
  font-size: .95rem;
  color: var(--muted);
  /* The contact card holds an email address — one unbroken string with no
     natural break opportunity, which ran past the card's edge. */
  overflow-wrap: anywhere;
}

/* The lift is decorative; honour a reduced-motion preference. */
@media (prefers-reduced-motion: reduce) {
  .explore-card { transition: none; }
  .explore-card:hover, .explore-card:focus { transform: none; }
}

/* ---- Inline figures -------------------------------------------------- */

.inline-figure { margin: 1.75rem 0; max-width: 100%; }
.inline-figure img {
  display: block;
  width: 100%;
  max-width: 28rem;   /* never scaled past its own 445px, so it stays sharp */
  height: auto;
  border-radius: 3px;
  /* Centred in the text column: capped well below the measure, it would
     otherwise sit hard against the left margin. */
  margin-inline: auto;
}
.inline-figure figcaption {
  margin-top: .5rem;
  font-size: .92rem;
  color: var(--muted);
  text-align: center;
}

/* ---- Branch school list ---------------------------------------------- */

.branch-list { list-style: none; padding: 0; margin: 0 0 1.5rem; }
.branch-list li {
  padding: .3rem 0;
  border-bottom: 1px solid #ece8e0;
  display: flex;
  gap: .75rem;
  align-items: baseline;
}
.branch-code {
  flex: none;
  min-width: 4.2rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .82rem;
  color: var(--muted);
  letter-spacing: .03em;
}

/* ---- Events ---------------------------------------------------------- */

.event-list { list-style: none; padding: 0; }
.event-list li { border-bottom: 1px solid var(--rule); padding: 1rem 0; }
.event-list .event-when { display: block; color: var(--muted); font-size: .95rem; }
.event-list.past a { color: var(--muted); }
/* Label/value pairs. Named twice because events had it first and the member
   portal needs the same thing: one rule, not two that drift apart. */
.event-detail dt, .detail-list dt { font-weight: 700; margin-top: .75rem; color: var(--accent); }
.event-detail dd, .detail-list dd { margin: 0; }

/* Quiet callout -- paper fill, gold rule down the left. Same reasoning: the
   "this event has passed" notice and the "your alumni status is unconfirmed"
   notice are the same object, so they share one definition. */
.event-past-notice, .callout {
  background: #f6f3ec; border-left: 4px solid var(--gold);
  padding: .75rem 1rem; margin-bottom: 1rem;
}
.button { /* legacy hook kept for event templates */
  display: inline-block; background: var(--accent); color: #fff;
  padding: .6rem 1.3rem; border-radius: 3px; text-decoration: none;
  font-family: system-ui, sans-serif; font-weight: 600;
}
.button:hover, .button:focus { background: var(--accent-dark); color: #fff; }

/* ---- Footer ---------------------------------------------------------- */

.site-footer { background: #fbfaf7; color: var(--muted); font-size: .95rem; text-align: center; }
.site-footer strong { color: var(--ink); }
/* Cap the 501(c)(3) line to a readable measure so it wraps rather than running
   the full width of a wide screen, then centre the block. */
.site-footer p { max-width: 46rem; margin-inline: auto; }

/* ─────────────────────────────────────────────────────────────────────────
   Sign-in page (templates/account/login.html)

   Two panels: the flag on the left, the form on the right. Below 48rem the
   aside collapses to a short band above the form rather than disappearing —
   on a phone it is the only thing identifying whose sign-in page this is.
   ───────────────────────────────────────────────────────────────────────── */
.auth-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: calc(100vh - 12rem);
}
.auth-aside {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3rem 2rem;
  /* Lifted off near-black, exactly as the home hero was: with the flag
     deliberately faint there is nothing else carrying light in this panel, and
     a darker ground read as a flat slab. */
  background-image: linear-gradient(160deg, #35432f 0%, #263120 55%, #2e3a28 100%);
}
.auth-aside-inner { position: relative; z-index: 1; text-align: center; max-width: 26rem; }
.auth-mark { width: 148px; height: auto; margin-bottom: 1.25rem; }
.auth-eyebrow {
  color: #d8d2c4; font-size: .82rem; letter-spacing: .14em;
  text-transform: uppercase; margin: 0;
}
.auth-motto { color: #fff; font-size: 1.75rem; line-height: 1.2; margin: .25rem 0 1rem; }
.auth-blurb { color: #cfd6c6; font-size: .98rem; line-height: 1.65; margin: 0; }

/* The flag. Inherited wholesale from the home hero it was built for — the
   blend is the part that took the work, so it is reproduced rather than
   re-derived. Desaturated and blended INTO the ground, not laid over it:
   soft-light lets its light areas lift the green and its dark areas deepen it,
   so it reads as tonal relief instead of a picture sitting on top. Opacity
   alone only ever produces a faded flag. */
/* The class is still .hero-flag: the partial was built for the home hero and
   the sign-in page is now its only caller. Renamed nothing, so the commit
   history for this artwork stays findable under one name. */
.hero-flag {
  position: absolute; inset: 0; width: 100%; height: 100%;
  filter: grayscale(1) contrast(.45);
  mix-blend-mode: soft-light;
  opacity: .22;
  pointer-events: none;
  user-select: none;
  z-index: 0;
}
/* The wave is an SVG filter, so the cloth ripples rather than sliding. DO NOT
   swap the inline <svg> for an <img>: a browser renders an <img>-loaded SVG as
   a static image and never starts its SMIL animation. That was verified — two
   frames six seconds apart were pixel-identical via <img>, and differ inline. */
.hero-flag .cloth { filter: url(#wave); }
/* Under prefers-reduced-motion the animated filter is swapped for an identical
   static one: it still reads as cloth, but nothing moves. Continuous
   background motion is a vestibular trigger and this membership skews older.
   Do not remove this media query. */
@media (prefers-reduced-motion: reduce) {
  .hero-flag .cloth { filter: url(#wave-still); }
}

.auth-panel { display: flex; align-items: center; justify-content: center; padding: 3rem 1.5rem; }
.auth-card { width: 100%; max-width: 24rem; }
.auth-title { margin: 0 0 .35rem; font-size: 1.9rem; }
.auth-sub { color: var(--muted); margin: 0 0 1.5rem; font-size: .98rem; }

.auth-field { margin-bottom: 1rem; }
.auth-field label { display: block; font-size: .9rem; color: var(--muted); margin-bottom: .3rem; }
.auth-field input {
  width: 100%; padding: .6rem .7rem;
  border: 1px solid var(--rule); border-radius: 4px;
  font-family: inherit; font-size: 1rem; background: #fff; color: var(--ink);
}
.auth-field input:focus {
  outline: 3px solid rgba(20, 83, 45, .35);
  outline-offset: 1px;
  border-color: var(--accent);
}
.auth-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin: .25rem 0 1.25rem;
}
.auth-check { display: flex; align-items: center; gap: .45rem; font-size: .92rem; color: var(--muted); margin: 0; }
.auth-check input { width: auto; }
.auth-link, .auth-foot a { color: var(--accent); }
.auth-submit {
  width: 100%; padding: .7rem 1rem;
  background: var(--accent); color: #fff;
  border: 1px solid var(--accent-dark); border-radius: 4px;
  font-family: inherit; font-size: 1rem; cursor: pointer;
}
.auth-submit:hover { background: var(--accent-dark); }
.auth-submit:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }
.auth-foot { margin: 1.25rem 0 0; font-size: .95rem; color: var(--muted); }
/* ---- allauth's own markup, inside our card ---------------------------
   templates/allauth/layouts/base.html puts every allauth page in .auth-card, but
   the pages themselves ship plain markup: a bare <h1>, labels wrapped in <p>, an
   unstyled <button>. Rather than write a leaf template for each one just to add
   classes, these rules make that markup inherit the same look as the hand-written
   auth screens.

   This is the SAFETY NET, and the reason it exists rather than only leaf
   overrides: allauth has pages this project has never thought about --
   reauthenticate, email confirmation, sign-up-closed variants, anything a future
   upgrade adds -- and every one of them lands here looking like the site instead
   of like a bug report. Leaf templates are for pages whose WORDING matters; this
   is for the rest.

   Scoped to .auth-card-allauth so it cannot reach the hand-written screens, whose
   markup already carries the real classes. */
.auth-card-allauth h1 { margin: 0 0 .35rem; font-size: 1.9rem; }
.auth-card-allauth h2 { font-size: 1.25rem; margin: 1.75rem 0 .5rem; }
.auth-card-allauth > p { color: var(--muted); margin: 0 0 1.25rem; font-size: .98rem; }
.auth-card-allauth form p { margin-bottom: 1rem; }
.auth-card-allauth label { display: block; font-size: .9rem; color: var(--muted); margin-bottom: .3rem; }
.auth-card-allauth input[type="text"],
.auth-card-allauth input[type="email"],
.auth-card-allauth input[type="password"] {
  width: 100%; padding: .6rem .7rem;
  border: 1px solid var(--rule); border-radius: 4px;
  font-family: inherit; font-size: 1rem; background: #fff; color: var(--ink);
}
.auth-card-allauth input:focus {
  outline: 3px solid rgba(20, 83, 45, .35);
  outline-offset: 1px;
  border-color: var(--accent);
}
/* A checkbox must not stretch to the full width of the card. */
.auth-card-allauth input[type="checkbox"],
.auth-card-allauth input[type="radio"] { width: auto; }
.auth-card-allauth button,
.auth-card-allauth input[type="submit"] {
  width: 100%; padding: .7rem 1rem; margin-top: .25rem;
  background: var(--accent); color: #fff;
  border: 1px solid var(--accent-dark); border-radius: 4px;
  font-family: inherit; font-size: 1rem; cursor: pointer;
}
.auth-card-allauth button:hover,
.auth-card-allauth input[type="submit"]:hover { background: var(--accent-dark); }
.auth-card-allauth button:focus-visible,
.auth-card-allauth input[type="submit"]:focus-visible {
  outline: 3px solid var(--gold); outline-offset: 2px;
}
/* Secondary buttons -- allauth marks destructive or lesser actions this way. */
.auth-card-allauth button[type="submit"][name^="action_remove"],
.auth-card-allauth button.secondaryAction {
  background: #fff; color: var(--accent); border-color: var(--rule);
}
.auth-card-allauth a { color: var(--accent); }
/* Field errors, which allauth renders as a bare <ul class="errorlist">. */
.auth-card-allauth .errorlist {
  list-style: none; padding: .6rem .8rem; margin: 0 0 1rem;
  border-left: 4px solid #8a1c1c; background: #fdf3f3;
  color: #6b1414; font-size: .95rem;
}
/* Email-management lists the addresses on the account. */
.auth-card-allauth form ul:not(.errorlist) { list-style: none; padding: 0; }
.auth-card-allauth form ul:not(.errorlist) > li { margin-bottom: .5rem; }
/* The card is wider here than the hand-written screens: some of these pages carry
   two forms and a list of addresses, which 24rem crushes. */
.auth-card-allauth { max-width: 30rem; }

/* Cloudflare's widget is a fixed-size box of its own; it only needs room around
   it, and to be allowed to shrink on a narrow phone rather than overflow the card. */
.turnstile-field { margin: 0 0 1rem; max-width: 100%; overflow: hidden; }

.auth-alert {
  border: 1px solid #b44; border-left-width: 4px;
  background: #fdf5f5; color: #7a2020;
  padding: .7rem .8rem; border-radius: 4px; margin-bottom: 1.25rem; font-size: .95rem;
}

@media (max-width: 48rem) {
  .auth-split { grid-template-columns: 1fr; min-height: 0; }
  .auth-aside { padding: 2rem 1.5rem; min-height: 13rem; }
  .auth-mark { width: 96px; margin-bottom: .75rem; }
  .auth-motto { font-size: 1.4rem; }
  .auth-blurb { display: none; }   /* the mark and the name are what matter here */
  .auth-panel { padding: 2rem 1.25rem 3rem; }
}

/* ---- Member portal --------------------------------------------------- */

/* The portal is a short page: a notice, some details, and what to do next. It
   needs spacing rules, not a look of its own -- it uses .callout, .detail-list
   and .button like the rest of the site.

   The actions sit in a flex row with a wrap, so two buttons sit side by side on
   a desktop and stack on a phone without either stretching to full width. */
.member-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .75rem 1.25rem;
  margin-top: 2rem;
  padding-top: 1.25rem;
  border-top: 1px solid #e7e2d6;
}
/* Sign out is deliberately a link, not a second button: it is the one action on
   this page nobody comes here to do, and two buttons of equal weight would make
   leaving look as inviting as searching the record. */
.member-actions .signout { font-family: system-ui, sans-serif; font-size: .95rem; }

/* Empty-state line, for an account with no OCS details recorded yet. Muted and
   in prose, because three rows reading "--" look like a page that failed to
   load rather than a profile nobody has filled in. */
.member-empty { color: var(--muted); }
