/* ==========================================================================
   Site components — hero, navigation, cards, forms, footer
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. HERO
   Full-viewport photographic opening. The gold links sit at 25% from the top,
   in the dark upper third of the photograph, clear of the square & compasses.
   -------------------------------------------------------------------------- */

.hero p { max-width: none; }

.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  isolation: isolate;
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}
.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 62%;   /* keeps the emblem in frame on tall screens */
}

/* Scrim: darkens the top for legible gold text, and fades the base into the
   page ground so the hero and the next section read as one continuous space. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(180deg,
      rgb(3 5 9 / 0.86) 0%,
      rgb(3 5 9 / 0.62) 22%,
      rgb(3 5 9 / 0.18) 46%,
      rgb(3 5 9 / 0.30) 72%,
      var(--c-ink) 100%),
    radial-gradient(120% 70% at 50% 18%, rgb(3 5 9 / 0.45), transparent 70%);
}

/* The identity block is anchored by its BOTTOM edge to the 25% line, so it
   grows upward and the gold links always land exactly where the brief asks. */
.hero__identity {
  position: absolute;
  bottom: calc(100% - var(--hero-nav-top));
  left: 0;
  right: 0;
  padding-inline: var(--gutter);
  padding-bottom: clamp(var(--s-2), 1.5vh, var(--s-4));
  text-align: center;
}

/* --- Wordmark ------------------------------------------------------------- */

.hero__eyebrow {
  max-width: none;
  font-size: clamp(0.62rem, 1.1vw, 0.78rem);
  font-weight: 500;
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: rgb(201 162 39 / 0.85);
  margin: 0 0 var(--s-3);
}

.hero__title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(2.4rem, 7.4vw, 5.5rem);
  line-height: 0.98;
  letter-spacing: 0.01em;
  margin: 0;
  filter: drop-shadow(0 2px 18px rgb(0 0 0 / 0.85));
}
.hero__title .hero__no {
  display: block;
  font-size: clamp(1rem, 2.4vw, 1.6rem);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  font-family: var(--font-ui);
  font-weight: 400;
  margin-top: var(--s-3);
  color: var(--c-parchment);
  opacity: 0.82;
  filter: none;
}

/* --- Hero navigation: the gold links, at 25% from the top ----------------- */

/* Links and strapline travel together, so no amount of wrapping can make them
   collide. The block's top edge is the 25% line. */
.hero__links {
  position: absolute;
  top: var(--hero-nav-top);
  left: 0;
  right: 0;
  padding-inline: var(--gutter);
  text-align: center;
}

/* base.css gives list items a top margin for prose lists; navigation rows are
   flex and must not inherit it, or the first item sits proud of the rest. */
.hero__nav li,
.sitenav li,
.breadcrumb li,
.sitefooter li:first-child { margin-top: 0; }

.hero__nav ul {
  list-style: none;
  margin: 0 auto;
  padding: 0;
  max-width: var(--width-page);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(var(--s-2), 1.9vw, var(--s-6));
}

.hero__nav a {
  display: inline-block;
  padding: var(--s-2) var(--s-1);
  font-family: var(--font-ui);
  font-size: clamp(0.7rem, 1.25vw, 0.875rem);
  font-weight: 500;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  color: var(--c-gold-bright);
  text-shadow: 0 1px 14px rgb(0 0 0 / 0.9);
  position: relative;
  transition: color var(--dur) var(--ease);
}
.hero__nav a::after {
  content: "";
  position: absolute;
  left: var(--s-1);
  right: var(--s-1);
  bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: center;
  opacity: 0.7;
  transition: transform var(--dur) var(--ease);
}
.hero__nav a:hover,
.hero__nav a:focus-visible { color: #fbeec2; }
.hero__nav a:hover::after,
.hero__nav a:focus-visible::after { transform: scaleX(1); }

.hero__province {
  margin: var(--s-5) 0 0;
  max-width: none;
  font-size: var(--t-sm);
  letter-spacing: var(--tracking-wide);
  color: rgb(236 230 217 / 0.6);
  text-shadow: 0 1px 12px rgb(0 0 0 / 0.9);
}

/* --- 250th anniversary badge: deliberately unlike the plain nav links ----- */

.hero__anniversary {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-4);
  padding: var(--s-2) var(--s-4);
  border: 1px solid var(--border-gold);
  border-radius: 999px;
  background: rgb(5 7 11 / 0.35);
  backdrop-filter: blur(2px);
  font-family: var(--font-ui);
  font-size: clamp(0.7rem, 1.1vw, 0.8rem);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  color: var(--c-gold-bright);
  text-decoration: none;
  text-shadow: 0 1px 10px rgb(0 0 0 / 0.9);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.hero__anniversary:hover,
.hero__anniversary:focus-visible { border-color: var(--c-gold-bright); background: rgb(5 7 11 / 0.55); }

.hero__anniversary-dot {
  width: 8px;
  height: 8px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--c-gold);
  box-shadow: 0 0 0 0 var(--c-gold-glow);
}
@media (prefers-reduced-motion: no-preference) {
  .hero__anniversary-dot { animation: anniversary-pulse 2.2s ease-out infinite; }
}
@keyframes anniversary-pulse {
  0%   { box-shadow: 0 0 0 0 var(--c-gold-glow); }
  70%  { box-shadow: 0 0 0 8px rgb(201 162 39 / 0); }
  100% { box-shadow: 0 0 0 0 rgb(201 162 39 / 0); }
}

/* --- Scroll cue ----------------------------------------------------------- */

.hero__cue {
  position: absolute;
  left: 50%;
  bottom: clamp(var(--s-5), 4vh, var(--s-7));
  transform: translateX(-50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-xs);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: rgb(236 230 217 / 0.5);
  text-decoration: none;
}
.hero__cue:hover { color: var(--c-gold-bright); }
.hero__cue span[aria-hidden] {
  width: 1px;
  height: 2.5rem;
  background: linear-gradient(180deg, var(--c-gold), transparent);
  animation: cue 2.6s var(--ease) infinite;
}
@keyframes cue {
  0%, 100% { opacity: 0.25; transform: scaleY(0.6); transform-origin: top; }
  50%      { opacity: 1;    transform: scaleY(1);   transform-origin: top; }
}

/* --- Artefact gallery ("Where we meet"): tighter than the site-wide grid
   gap, since this section stacks six rows of photos back to back. */
.room-gallery .grid { gap: var(--s-3); }
.room-gallery .mt-6 { margin-top: var(--s-3); }

/* --------------------------------------------------------------------------
   2. STICKY SITE HEADER (appears once the hero is scrolled past)
   -------------------------------------------------------------------------- */

.siteheader {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: var(--z-nav);
  background: rgb(5 7 11 / 0.86);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--border);
  transform: translateY(-101%);
  transition: transform var(--dur) var(--ease);
}
.siteheader[data-visible="true"] { transform: translateY(0); }
.siteheader--static { position: sticky; transform: none; }

/* --- Admin-mode banner ---------------------------------------------------
   Injected by auth.js on every page when the signed-in visitor is an
   admin. In-flow (not sticky/fixed) — every sticky header on the site
   (every page except the homepage) needs no offset changes at all: it
   already renders below the banner naturally in document flow, and sticks
   to the true viewport top once the banner scrolls past.

   Height is capped and overflow hidden, not left to grow with content —
   the homepage's header is position: fixed (its hide-on-scroll hero
   overlay), removed from flow, so it alone needs an explicit offset to
   clear the banner above it (see below). That offset has to match a
   KNOWN height, so wrapped text on a narrow phone can never make the
   banner taller than expected and overlap the header — worst case it
   clips a touch, never overlaps. */
.admin-banner {
  height: 2.5rem;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.3rem;
  background: #87ceeb;
  color: #05070b;
  font: 600 0.8rem/1.2 inherit;
  text-align: center;
  padding: 0 1rem;
}
.admin-banner a {
  color: #05070b;
  text-decoration: underline;
  font-weight: 700;
  white-space: nowrap;
}

/* Must match .admin-banner's height above exactly. */
body.has-admin-banner .siteheader:not(.siteheader--static) {
  inset-block-start: 2.5rem;
}

.siteheader__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  min-height: 4rem;
}

.siteheader__brand {
  font-family: var(--font-display);
  font-size: 1.15rem;
  letter-spacing: 0.02em;
  text-decoration: none;
  white-space: nowrap;
}

.sitenav ul {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: var(--s-5);
}
.sitenav a {
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  text-decoration: none;
  color: var(--fg-muted);
  transition: color var(--dur-fast) var(--ease);
}
.sitenav a:hover,
.sitenav a[aria-current="page"] { color: var(--accent-bright); }

.sitenav__toggle {
  display: none;
  background: none; border: 1px solid var(--border-gold); color: var(--accent);
  padding: var(--s-2) var(--s-3); border-radius: var(--radius);
  font: inherit; font-size: var(--t-xs); letter-spacing: var(--tracking-wide);
  text-transform: uppercase; cursor: pointer;
}

@media (max-width: 52rem) {
  .sitenav__toggle { display: inline-block; }
  .sitenav ul {
    position: absolute; inset-inline: 0; top: 100%;
    flex-direction: column; gap: 0;
    background: rgb(5 7 11 / 0.97);
    border-bottom: 1px solid var(--border);
    padding: var(--s-4) var(--gutter) var(--s-5);
  }
  .sitenav[data-open="false"] ul { display: none; }
  .sitenav a { display: block; padding: var(--s-3) 0; font-size: var(--t-sm); }
}

/* --------------------------------------------------------------------------
   3. PAGE HEADER (inner pages)
   -------------------------------------------------------------------------- */

.pagehead {
  padding-block: clamp(7rem, 14vh, 11rem) var(--s-8);
  border-bottom: 1px solid var(--border);
  background:
    linear-gradient(180deg, var(--c-navy-deep), var(--c-ink)),
    var(--c-ink);
  position: relative;
}
.pagehead::after {
  content: "";
  position: absolute; inset-inline: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--border-gold) 30%,
              var(--border-gold) 70%, transparent);
}
.pagehead h1 { margin-bottom: var(--s-4); }

/* Full-header hero photo of a degree's working tools (EA/FC/MM), one of
   three, fixed per page and cycled across the page list rather than
   chosen at random on each visit — same treatment as the admin pages'
   Secretary's-desk background just below: the photo covers the whole
   .pagehead and fades into the page's own background via the same scrim
   gradient, so the breadcrumb/title/lede stay legible over it. */
.pagehead--ea-tools {
  background-size: cover;
  background-position: center 40%;
  background-repeat: no-repeat;
  background-image:
    linear-gradient(180deg, rgb(5 7 11 / 0.80) 0%, rgb(5 7 11 / 0.55) 55%, var(--c-ink) 100%),
    url('/assets/img/pagehead-hero-ea-tools-1600.webp');
}
.pagehead--fc-tools {
  background-size: cover;
  background-position: center 40%;
  background-repeat: no-repeat;
  background-image:
    linear-gradient(180deg, rgb(5 7 11 / 0.80) 0%, rgb(5 7 11 / 0.55) 55%, var(--c-ink) 100%),
    url('/assets/img/pagehead-hero-fc-tools-1600.webp');
}
.pagehead--mm-tools {
  background-size: cover;
  background-position: center 40%;
  background-repeat: no-repeat;
  background-image:
    linear-gradient(180deg, rgb(5 7 11 / 0.80) 0%, rgb(5 7 11 / 0.55) 55%, var(--c-ink) 100%),
    url('/assets/img/pagehead-hero-mm-tools-1600.webp');
}

/* --- 404 page: a full-viewport background photo -----------------------------
   Unlike .pagehead's photos (a fixed-height banner that fades into the page
   below it), .page-centre fills the whole viewport with its content
   vertically centred — so a top-to-bottom fade would leave the text sitting
   somewhere in the middle of an uneven gradient. A flat, even scrim over the
   whole photo keeps the gold heading legible wherever it lands instead. */
.errorpage {
  background-size: cover;
  background-position: center 45%;
  background-repeat: no-repeat;
  background-image:
    linear-gradient(rgb(5 7 11 / 0.78), rgb(5 7 11 / 0.78)),
    url('/assets/img/404-bg-1600.webp');
}

/* --- Admin pages: a Secretary's-desk background photo -----------------------
   Same treatment as the degree-specific background further down (account
   page): the photo covers the full .pagehead — from the site header down to
   the gold divider rule (.pagehead::after) — and fades into the page's own
   background by the bottom edge, via the same scrim gradient, so the
   breadcrumb/title/lede stay legible over it. Every admin page's data-page
   value starts with "admin" (admin, admin-hub, admin-summons, ...), so one
   attribute selector covers all of them without listing each by name. */
body[data-page^="admin"] .pagehead {
  background-size: cover;
  background-position: center 35%;
  background-repeat: no-repeat;
  background-image:
    linear-gradient(180deg, rgb(5 7 11 / 0.80) 0%, rgb(5 7 11 / 0.55) 55%, var(--c-ink) 100%),
    url('/assets/img/admin-secretary-1600.webp');
}

.breadcrumb { font-size: var(--t-xs); letter-spacing: var(--tracking-wide);
              color: var(--fg-faint); margin-bottom: var(--s-5); }
.breadcrumb ol { list-style: none; margin: 0; padding: 0; display: flex;
                 flex-wrap: wrap; gap: var(--s-2); }
.breadcrumb li + li::before { content: "/"; margin-right: var(--s-2);
                              color: var(--border-gold); }
.breadcrumb a { color: var(--fg-muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--accent-bright); }

/* --------------------------------------------------------------------------
   4. RULES & ORNAMENT
   -------------------------------------------------------------------------- */

.rule-gold {
  width: 4rem; height: 1px; margin: var(--s-5) 0;
  background: linear-gradient(90deg, var(--c-gold), transparent);
  border: 0;
}
.rule-gold--center { margin-inline: auto;
  background: linear-gradient(90deg, transparent, var(--c-gold), transparent);
  width: 8rem; }

/* --------------------------------------------------------------------------
   5. CARDS
   -------------------------------------------------------------------------- */

.card {
  background: linear-gradient(160deg, var(--c-ink-raised), var(--c-ink));
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s-6);
  position: relative;
  transition: border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.card h3 { margin-bottom: var(--s-3); }
.card p { color: var(--fg-muted); font-size: var(--t-sm); }

a.card, .card--link { display: block; text-decoration: none; color: inherit; }
a.card:hover, .card--link:hover {
  border-color: var(--border-gold);
  transform: translateY(-2px);
  box-shadow: var(--shadow-lift);
}
a.card:hover h3 { color: var(--accent-bright); }

/* News card thumbnail — pulled out to the card's edges (the card's own
   padding would otherwise letterbox the photo) and cropped to a fixed
   ratio so a row of cards lines up regardless of each source photo's own
   proportions. */
.card__thumb {
  margin: calc(-1 * var(--s-6)) calc(-1 * var(--s-6)) var(--s-4);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  overflow: hidden;
}
.card__thumb img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block; }

.card__meta {
  font-size: var(--t-xs); letter-spacing: var(--tracking-wide);
  text-transform: uppercase; color: var(--accent); margin-bottom: var(--s-3);
}

/* --------------------------------------------------------------------------
   6. BUTTONS
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-6);
  font-family: var(--font-ui); font-size: var(--t-sm); font-weight: 500;
  letter-spacing: var(--tracking-wide); text-transform: uppercase;
  text-decoration: none; cursor: pointer;
  border-radius: var(--radius);
  border: 1px solid var(--border-gold);
  background: transparent; color: var(--accent-bright);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.btn:hover { background: rgb(201 162 39 / 0.12); border-color: var(--c-gold);
             color: #fbeec2; }

.btn--solid {
  background: linear-gradient(180deg, var(--c-gold-bright), var(--c-gold));
  color: var(--c-ink); border-color: transparent; font-weight: 600;
}
.btn--solid:hover { background: linear-gradient(180deg, #f6e5b4, var(--c-gold-bright));
                    color: var(--c-ink); }

.btn--quiet { border-color: var(--border); color: var(--fg-muted); }
.btn--quiet:hover { color: var(--fg); border-color: var(--border-gold);
                    background: transparent; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--s-4); align-items: center; }
.btn-row--center { justify-content: center; }

/* --------------------------------------------------------------------------
   7. FIGURES
   -------------------------------------------------------------------------- */

.figure {
  margin: 0; border-radius: var(--radius-lg); overflow: hidden;
  border: 1px solid var(--border); box-shadow: var(--shadow-soft);
}
.figure img { width: 100%; }
/* A small line-art emblem (white background), not a full-bleed photograph —
   constrained and centered rather than stretched to the wrap's full width. */
.figure--emblem { max-width: 320px; margin-inline: auto; margin-block-end: var(--s-6); background: #fff; }
.figure figcaption {
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-xs); letter-spacing: var(--tracking-wide);
  color: var(--fg-faint); background: var(--c-ink-raised);
  border-top: 1px solid var(--border);
}

/* Magazine-style article figures: full width and stacked in reading order
   on narrow screens (a float that never gets room to wrap looks broken,
   not stylish); floated left/right with text wrapping around it once
   there's enough width for a paragraph to comfortably wrap beside a
   16rem-wide image without squeezing into an unreadable sliver. */
.figure--float { margin-bottom: var(--s-6); }
@media (min-width: 40rem) {
  .figure--float { width: 16rem; margin-bottom: var(--s-2); }
  .figure--float.figure--left { float: left; margin: 0 var(--s-6) var(--s-5) 0; }
  .figure--float.figure--right { float: right; margin: 0 0 var(--s-5) var(--s-6); }
}
/* Clears the floats so the wrap--narrow container (and whatever follows
   the article, e.g. the "Back to" buttons) doesn't collapse around them. */
.article-body::after { content: ""; display: table; clear: both; }

/* --------------------------------------------------------------------------
   8. PLACEHOLDER NOTICE (used on the stub pages)
   -------------------------------------------------------------------------- */

.notice {
  border: 1px dashed var(--border-gold);
  border-radius: var(--radius-lg);
  padding: var(--s-6);
  background: rgb(201 162 39 / 0.04);
}
.notice__label {
  font-size: var(--t-xs); font-weight: 600;
  letter-spacing: var(--tracking-widest); text-transform: uppercase;
  color: var(--accent); margin-bottom: var(--s-3);
}
.notice p { color: var(--fg-muted); }

/* A verbatim inscription (e.g. an honours board's own heading), set apart
   from ordinary body copy in the display serif. */
.board-heading {
  font-family: var(--font-display); font-style: italic;
  font-size: var(--t-lg); color: var(--accent-bright);
  margin-top: var(--s-6);
}

/* --------------------------------------------------------------------------
   9. FORMS
   -------------------------------------------------------------------------- */

.field { display: block; margin-bottom: var(--s-5); }
.field > span {
  display: block; margin-bottom: var(--s-2);
  font-size: var(--t-sm); font-weight: 500; color: var(--fg);
}
.field .hint { font-size: var(--t-xs); color: var(--fg-faint); font-weight: 400; }

/* Honeypot: off-screen for everyone but a bot filling in every field it
   finds. Not .visually-hidden — that pattern stays in the accessibility
   tree on purpose, which would have a screen reader announce it. This one
   must be invisible to every real visitor, sighted or not. */
.field--trap {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden; margin: 0;
}

/* Two-factor setup: the QR code needs a light background to scan reliably
   against this site's dark theme. */
.mfa-qr-row { display: flex; align-items: center; gap: var(--s-5); flex-wrap: wrap; }
.mfa-qr-row img {
  background: #fff; padding: var(--s-3); border-radius: var(--radius);
  width: 200px; height: 200px;
}
.mfa-secret { word-break: break-all; max-width: 28rem; }

/* Matches .field > span's weight, for a read-only value that isn't inside an
   actual form field (degree / lodge offices — admin-only, nothing to label an
   <input> for). */
.field-label {
  margin: 0 0 var(--s-2);
  font-size: var(--t-sm); font-weight: 500; color: var(--fg);
}

input[type="text"], input[type="email"], input[type="tel"], input[type="date"],
input[type="number"], select, textarea {
  width: 100%;
  padding: var(--s-3) var(--s-4);
  font: inherit; font-size: var(--t-sm);
  color: var(--fg);
  background: var(--c-ink-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  transition: border-color var(--dur-fast) var(--ease);
}
input:hover, select:hover, textarea:hover { border-color: #232b3a; }
input:focus, select:focus, textarea:focus { border-color: var(--c-gold); outline: none;
  box-shadow: 0 0 0 3px rgb(201 162 39 / 0.15); }
textarea { min-height: 8rem; resize: vertical; }
::placeholder { color: var(--fg-faint); }

/* Browsers paint autofilled fields white regardless of page styling, which
   breaks on a dark form. The address fields below make autofill common, so
   this is a correctness fix, not decoration. An inset shadow is the only
   reliable override. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
  -webkit-text-fill-color: var(--fg);
  -webkit-box-shadow: 0 0 0 1000px var(--c-ink-raised) inset;
  box-shadow: 0 0 0 1000px var(--c-ink-raised) inset;
  caret-color: var(--fg);
  transition: background-color 100000s ease-in-out 0s;
}

/* Browsers paint autofilled fields white, which looks broken on a dark form.
   An inset shadow is the only reliable way to override it. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
  -webkit-text-fill-color: var(--fg);
  -webkit-box-shadow: 0 0 0 1000px var(--c-ink-raised) inset;
  box-shadow: 0 0 0 1000px var(--c-ink-raised) inset;
  caret-color: var(--fg);
  transition: background-color 100000s ease-in-out 0s;
}

fieldset { border: 1px solid var(--border); border-radius: var(--radius-lg);
           padding: var(--s-5); margin: 0 0 var(--s-6); }
legend { padding-inline: var(--s-3); font-size: var(--t-sm); font-weight: 600;
         letter-spacing: var(--tracking-wide); color: var(--accent); }

/* --------------------------------------------------------------------------
   10. TABLES
   -------------------------------------------------------------------------- */

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch;
                border: 1px solid var(--border); border-radius: var(--radius-lg); }
table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
th, td { padding: var(--s-3) var(--s-4); text-align: left;
         border-bottom: 1px solid var(--border); }
th { font-size: var(--t-xs); letter-spacing: var(--tracking-wide);
     text-transform: uppercase; color: var(--accent); font-weight: 600;
     background: var(--c-ink-raised); white-space: nowrap; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover td { background: rgb(201 162 39 / 0.03); }

/* Past Masters roll: its third column is a full sentence, not a short
   value — left at the browser's default auto column width it wraps into
   a narrow, many-line strip on mobile. A minimum width lets it read as a
   normal short paragraph instead, at the cost of more horizontal scroll. */
.roll-table td:last-child, .roll-table th:last-child { min-width: 20rem; }

/* --------------------------------------------------------------------------
   11. FOOTER
   -------------------------------------------------------------------------- */

.sitefooter {
  border-top: 1px solid var(--border);
  background: var(--c-navy-deep);
  padding-block: var(--s-8) var(--s-6);
  font-size: var(--t-sm);
}
.sitefooter__grid { display: grid; gap: var(--s-7); }
@media (min-width: 48rem) {
  .sitefooter__grid { grid-template-columns: 1.4fr 1fr 1fr; }
}
.sitefooter h2 {
  font-family: var(--font-ui); font-size: var(--t-xs); font-weight: 600;
  letter-spacing: var(--tracking-widest); text-transform: uppercase;
  color: var(--accent); margin-bottom: var(--s-4);
}
.sitefooter ul { list-style: none; margin: 0; padding: 0; }
.sitefooter li + li { margin-top: var(--s-3); }
.sitefooter a { color: var(--fg-muted); text-decoration: none; }
.sitefooter a:hover { color: var(--accent-bright); }
.sitefooter__brand {
  font-family: var(--font-display); font-size: var(--t-xl);
  margin-bottom: var(--s-3);
}
.sitefooter__legal {
  margin-top: var(--s-7); padding-top: var(--s-5);
  border-top: 1px solid var(--border);
  display: flex; flex-wrap: wrap; gap: var(--s-4);
  justify-content: space-between;
  color: var(--fg-faint); font-size: var(--t-xs);
}

/* --------------------------------------------------------------------------
   12. REVEAL ON SCROLL (progressive enhancement — content is visible if JS
       never runs, because .is-ready is only added by the script)
   -------------------------------------------------------------------------- */

.is-ready [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--dur-slow) var(--ease),
              transform var(--dur-slow) var(--ease);
}
.is-ready [data-reveal].is-visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .is-ready [data-reveal] { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   13. PRINT (summonses and forms are printed often in a Lodge)
   -------------------------------------------------------------------------- */

@media print {
  :root { --bg: #fff; --fg: #000; }
  body { background: #fff; color: #000; }
  .hero, .siteheader, .hero__cue, .sitefooter__grid, .skip-link { display: none !important; }
  a { color: #000; text-decoration: underline; }
  .card, .notice, .figure { border: 1px solid #999; break-inside: avoid; }
}

/* ==========================================================================
   14. MEMBERS AREA
   ========================================================================== */

.authpanel {
  max-width: 30rem;
  margin-inline: auto;
  background: linear-gradient(160deg, var(--c-ink-raised), var(--c-ink));
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: clamp(var(--s-5), 4vw, var(--s-7));
  box-shadow: var(--shadow-soft);
}
.authpanel h2 { margin-bottom: var(--s-2); }
.authpanel__intro { color: var(--fg-muted); font-size: var(--t-sm);
                    margin-bottom: var(--s-6); }
.authpanel--wide { max-width: 44rem; }

.authfoot {
  margin-top: var(--s-6); padding-top: var(--s-5);
  border-top: 1px solid var(--border);
  font-size: var(--t-sm); color: var(--fg-muted);
}
.authfoot a { text-decoration: none; }
.authfoot p + p { margin-top: var(--s-2); }

/* --- Form status messages ------------------------------------------------- */

.formstatus {
  margin: 0 0 var(--s-5);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--radius);
  font-size: var(--t-sm);
  border: 1px solid;
  max-width: none;
}
.formstatus--error   { border-color: rgb(190 70 70 / 0.5);
                       background: rgb(190 70 70 / 0.10); color: #f0b8b8; }
.formstatus--success { border-color: rgb(110 170 110 / 0.45);
                       background: rgb(110 170 110 / 0.10); color: #bfe3bf; }
.formstatus--info    { border-color: var(--border-gold);
                       background: rgb(201 162 39 / 0.08); color: var(--c-gold-bright); }

/* --- Verification code input ---------------------------------------------- */

.codefield input {
  font-family: var(--font-ui);
  font-size: clamp(1.5rem, 6vw, 2rem);
  font-weight: 500;
  letter-spacing: 0.5em;
  text-indent: 0.5em;      /* balances the trailing letter-space */
  text-align: center;
  padding-block: var(--s-4);
}

/* --- Password field with a reveal toggle ---------------------------------- */

.pw { position: relative; }
.pw input { padding-right: 4.5rem; }
.pw__toggle {
  position: absolute; right: var(--s-2); top: 50%; transform: translateY(-50%);
  background: none; border: 0; cursor: pointer;
  color: var(--fg-muted); font: inherit; font-size: var(--t-xs);
  letter-spacing: var(--tracking-wide); text-transform: uppercase;
  padding: var(--s-2) var(--s-3); border-radius: var(--radius);
}
.pw__toggle:hover { color: var(--accent-bright); }

/* --- Password strength meter ---------------------------------------------- */

.pwmeter { margin-top: var(--s-2); }
.pwmeter__track {
  height: 3px; border-radius: 2px; background: var(--border); overflow: hidden;
}
.pwmeter__bar {
  height: 100%; width: 0; border-radius: 2px;
  background: var(--c-gold);
  transition: width var(--dur) var(--ease), background var(--dur) var(--ease);
}
.pwmeter__bar[data-level="1"] { width: 25%;  background: #b4534e; }
.pwmeter__bar[data-level="2"] { width: 50%;  background: #b4884e; }
.pwmeter__bar[data-level="3"] { width: 75%;  background: var(--c-gold); }
.pwmeter__bar[data-level="4"] { width: 100%; background: #7fae76; }
.pwmeter__label { font-size: var(--t-xs); color: var(--fg-faint);
                  margin-top: var(--s-2); }

/* --- Member status chip ---------------------------------------------------- */

.chip {
  display: inline-block;
  padding: 0.2em 0.7em;
  border-radius: 999px;
  font-size: var(--t-xs); font-weight: 600;
  letter-spacing: var(--tracking-wide); text-transform: uppercase;
  border: 1px solid;
}
.chip--active    { color: #bfe3bf; border-color: rgb(110 170 110 / 0.5);
                   background: rgb(110 170 110 / 0.10); }
.chip--pending   { color: var(--c-gold-bright); border-color: var(--border-gold);
                   background: rgb(201 162 39 / 0.08); }
.chip--invited   { color: #cbd8f0; border-color: rgb(120 150 200 / 0.4);
                   background: rgb(120 150 200 / 0.08); }
.chip--suspended { color: #f0b8b8; border-color: rgb(190 70 70 / 0.5);
                   background: rgb(190 70 70 / 0.10); }
.chip--admin     { color: #cbd8f0; border-color: rgb(120 150 200 / 0.5);
                   background: rgb(120 150 200 / 0.10); }
.chip--caterer   { color: #b8e0c0; border-color: rgb(90 170 110 / 0.5);
                   background: rgb(90 170 110 / 0.10); }
.chip--paid      { color: #bfe3bf; border-color: rgb(110 170 110 / 0.5);
                   background: rgb(110 170 110 / 0.10); }

.admin-badge { display: inline-block; vertical-align: middle; }

/* --- Members dashboard ----------------------------------------------------- */

.memberbar {
  display: flex; flex-wrap: wrap; gap: var(--s-4);
  align-items: center; justify-content: space-between;
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--c-ink-raised);
  margin-bottom: var(--s-7);
}
.memberbar__who { font-size: var(--t-sm); }
.memberbar__who strong { color: var(--fg); font-weight: 600; }

.tile-grid { display: grid; gap: var(--s-5); }
@media (min-width: 40rem) { .tile-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem) { .tile-grid { grid-template-columns: repeat(3, 1fr); } }

/* --- Dashboard stat tiles ---------------------------------------------------- */

.stat { text-align: center; }
/* Scoped under .stat, not just the bare class — .card p (site.css's generic
   card-body-text rule) has higher specificity than a single class alone and
   was silently winning here, flattening all three of these to plain card
   text. Found by actually checking computed styles, not just a screenshot:
   the numbers were rendering at 14px this whole time, never the intended
   large gold clamp() size. */
.stat .stat__value {
  font-family: var(--font-display); font-weight: 300;
  font-size: clamp(3.5rem, 8vw, 5.5rem); line-height: 1;
  color: var(--c-gold-bright); margin: 0 0 var(--s-2);
}
.stat .stat__value--sm { font-size: clamp(1.15rem, 2.4vw, 1.5rem); line-height: 1.3; }
.stat .stat__label {
  font-size: var(--t-xs); letter-spacing: var(--tracking-wide);
  text-transform: uppercase; color: var(--fg-muted); margin: 0;
}
.stat .stat__sub { font-size: var(--t-xs); color: var(--fg-faint); margin: var(--s-2) 0 0; }

.activity-list { list-style: none; margin: 0; padding: 0; }
.activity-list li {
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4);
  padding: var(--s-3) 0; border-bottom: 1px solid var(--border);
  font-size: var(--t-sm);
}
.activity-list li:last-child { border-bottom: 0; }
.activity-list .activity-when { color: var(--fg-faint); font-size: var(--t-xs); flex-basis: 100%; }
.activity-list .activity-who { color: var(--c-gold-bright); }

.attendance-list { list-style: none; margin: 0; padding: 0; }
.attendance-list li {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) 0; border-bottom: 1px solid var(--border);
}
.attendance-list li:last-child { border-bottom: 0; }
.attendance-list label {
  display: flex; align-items: center; gap: var(--s-3); cursor: pointer; flex: 1;
}
.attendance-list input[type="checkbox"] {
  accent-color: var(--c-gold); cursor: pointer; width: 1.1rem; height: 1.1rem; flex-shrink: 0;
}
.attendance-list input[type="checkbox"]:disabled { cursor: not-allowed; opacity: 0.6; }
.attendance-list .attendance-date { color: var(--fg-faint); font-size: var(--t-xs); white-space: nowrap; }

/* --- Admin table ----------------------------------------------------------- */

.admin-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.btn--tiny {
  padding: var(--s-1) var(--s-3); font-size: var(--t-xs);
  letter-spacing: var(--tracking-wide);
}

.status-toggle {
  display: inline-flex; align-items: center; gap: var(--s-2);
  margin-top: var(--s-2); cursor: pointer;
}
.status-toggle input[type="checkbox"] {
  accent-color: var(--c-gold); cursor: pointer;
  width: 1.1rem; height: 1.1rem;
}
.status-toggle input[type="checkbox"]:disabled { cursor: not-allowed; opacity: 0.6; }
.status-toggle span { font-size: var(--t-xs); color: var(--fg-muted); }

.emptystate {
  padding: var(--s-7); text-align: center;
  color: var(--fg-muted); font-size: var(--t-sm);
}

/* A spinner-free loading line — quieter, and no motion to suppress. */
.loading { color: var(--fg-faint); font-size: var(--t-sm); padding: var(--s-5) 0; }

/* --- Required-field marker -------------------------------------------------- */
.req { color: var(--accent); }

/* --- Collapsible sections (long repeater lists on the summons generator) --- */

.details-section summary {
  cursor: pointer;
  list-style: none;
}
.details-section summary::-webkit-details-marker { display: none; }
.details-section summary h3 {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  margin: 0;
}
.details-section summary h3::before {
  content: '▸';
  color: var(--c-gold);
  display: inline-block;
  transition: transform var(--dur) var(--ease);
}
.details-section[open] summary h3::before { transform: rotate(90deg); }
.details-section > :not(summary) { margin-top: var(--s-4); }

/* --- Checkbox groups (dietary requirements, allergies) ---------------------- */

.checkbox-group {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: var(--s-3) var(--s-5);
  margin: var(--s-3) 0 0;
}
.checkbox-group label {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-sm);
  color: var(--fg);
  cursor: pointer;
}
.checkbox-group input[type="checkbox"] {
  width: 1.05rem;
  height: 1.05rem;
  flex-shrink: 0;
  accent-color: var(--c-gold);
  cursor: pointer;
}
.checkbox-group label:has(input:disabled) {
  color: var(--fg-faint);
  cursor: not-allowed;
}
.checkbox-group--divider {
  margin-top: var(--s-5);
  padding-top: var(--s-5);
  border-top: 1px solid var(--border);
}

/* --- File upload (lodge certificate) ---------------------------------------- */

input[type="file"] {
  display: block;
  width: 100%;
  padding: var(--s-3);
  font: inherit;
  font-size: var(--t-sm);
  color: var(--fg-muted);
  background: var(--c-ink-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
input[type="file"]::file-selector-button {
  margin-right: var(--s-3);
  padding: var(--s-2) var(--s-4);
  border: 1px solid var(--border-gold);
  border-radius: var(--radius);
  background: transparent;
  color: var(--accent-bright);
  font: inherit;
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease);
}
input[type="file"]::file-selector-button:hover {
  background: rgb(201 162 39 / 0.12);
}

.filecard {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-4);
  margin-bottom: var(--s-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--c-ink-raised);
}
.filecard__name {
  color: var(--fg);
  font-size: var(--t-sm);
  font-weight: 500;
  word-break: break-word;
}
.filecard__meta {
  margin-top: var(--s-1);
}
.filecard__thumb {
  width: 3.5rem; height: 3.5rem; flex-shrink: 0;
  object-fit: cover; border-radius: var(--radius);
}
.filecard__grow { flex: 1; }

/* --- Degree-specific background (account page only) -------------------------
   Set by JS as a plain data attribute on <body> once the member's own profile
   loads — never as an inline style, since that would violate the site's CSP
   (style-src has no 'unsafe-inline'). The scrim mirrors .hero__scrim so the
   page title stays legible over the photograph. */

/* .pagehead already sets position: relative in its base rule (needed for the
   gold divider in .pagehead::after); only size/position/repeat need adding
   here. */
body[data-page="account"][data-degree] .pagehead {
  background-size: cover;
  background-position: center 38%;
  background-repeat: no-repeat;
}

body[data-page="account"][data-degree="entered_apprentice"] .pagehead {
  background-image:
    linear-gradient(180deg, rgb(5 7 11 / 0.80) 0%, rgb(5 7 11 / 0.55) 55%, var(--c-ink) 100%),
    url('/assets/img/degree-ea-1600.webp');
}
body[data-page="account"][data-degree="fellow_craft"] .pagehead {
  background-image:
    linear-gradient(180deg, rgb(5 7 11 / 0.80) 0%, rgb(5 7 11 / 0.55) 55%, var(--c-ink) 100%),
    url('/assets/img/degree-fc-1600.webp');
}
body[data-page="account"][data-degree="master_mason"] .pagehead {
  background-image:
    linear-gradient(180deg, rgb(5 7 11 / 0.80) 0%, rgb(5 7 11 / 0.55) 55%, var(--c-ink) 100%),
    url('/assets/img/degree-mm-1600.webp');
}

/* --- Degree / lodge-office chips (read-only display) ------------------------ */

.chip--gold {
  color: var(--c-ink);
  border-color: transparent;
  background: linear-gradient(180deg, var(--c-gold-bright), var(--c-gold));
  font-weight: 700;
}
.chip-row {
  display: flex; flex-wrap: wrap; gap: var(--s-2);
  margin-top: var(--s-2);
}

/* --- Lodge office badges (collar-jewel photographs) ------------------------- */

.badge-row {
  display: flex; flex-wrap: wrap; gap: var(--s-5);
  margin-top: var(--s-2);
}
.badge-row figure {
  margin: 0; text-align: center; width: 38px;
}
.badge-row img {
  width: 38px; height: 38px; border-radius: var(--radius);
  background: var(--c-ink-raised); border: 1px solid var(--border);
}
.badge-row figcaption {
  margin-top: var(--s-2); font-size: var(--t-xs);
  color: var(--fg-muted);
}

/* The Officers-of-the-Lodge table: a larger badge beside the office name. */
.office-row {
  display: flex; align-items: center; gap: var(--s-4);
}
.office-row img {
  width: 63px; height: 63px; border-radius: var(--radius);
  background: var(--c-ink-raised); border: 1px solid var(--border);
  flex-shrink: 0;
}

/* --- Consent checkbox (privacy acceptance, cookie banner) ------------------- */

.consent-check {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  cursor: pointer;
}
.consent-check input[type="checkbox"] {
  flex-shrink: 0;
  margin-top: 0.2em;
  width: 1.1rem;
  height: 1.1rem;
  accent-color: var(--c-gold);
  cursor: pointer;
}
.consent-check span {
  font-size: var(--t-sm);
  color: var(--fg-muted);
  line-height: var(--leading-snug);
}

/* --- Cookie banner ----------------------------------------------------------
   Sits at the bottom of the viewport on first visit, on every public page.
   Never blocks content — a slim bar, not a modal, matching the site's tone. */

.cookie-banner {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: var(--z-overlay);
  background: rgb(5 7 11 / 0.97);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  border-top: 1px solid var(--border-gold);
  padding: var(--s-5) var(--gutter);
  box-shadow: 0 -8px 30px rgb(0 0 0 / 0.4);
}
.cookie-banner__inner {
  width: min(100% - 0px, var(--width-page));
  margin-inline: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
}
.cookie-banner p {
  margin: 0;
  font-size: var(--t-sm);
  color: var(--fg-muted);
  max-width: 56ch;
}
.cookie-banner a { color: var(--accent-bright); }
.cookie-banner .btn-row { flex-shrink: 0; }

@media (prefers-reduced-motion: no-preference) {
  .cookie-banner {
    animation: cookie-rise var(--dur-slow) var(--ease);
  }
}
@keyframes cookie-rise {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}
