/* ===========================================================================
   Kappa Delta Chi — collegiate design system (navy + gold)
   Placeholder-driven; swap content per README.
   =========================================================================== */

:root {
  --navy:        #0A1F44;   --navy-rgb: 10,31,68;       /* keep every *-rgb triplet in sync with its hex */
  --navy-2:      #12305F;   --navy-2-rgb: 18,48,95;
  --navy-deep:   #071634;
  --gold:        #C8A24B;   --gold-rgb: 200,162,75;
  --gold-bright: #E8C766;   --gold-bright-rgb: 232,199,102;
  --gold-deep:   #7d5f1e;   /* darkened from #9A7628 → clears WCAG AA 4.5:1 as small text on cream/parchment */
  --cream:       #F7F5EF;
  --cream-2:     #EFEADC;
  --ink:         #12151C;
  --muted:       #5B6270;
  /* "white" is warm paper sitewide — true #fff stays only on the crest badge */
  --white:       #FBF8F1;   --white-rgb: 251,248,241;
  --paper:       #FDFBF6;

  --serif: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --display: 'Playfair Display', Georgia, serif;
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  --wrap: 1160px;
  --shadow: 0 18px 50px rgba(var(--navy-rgb), 0.16);
  --shadow-sm: 0 6px 18px rgba(var(--navy-rgb), 0.10);
  --shadow-md: 0 12px 32px rgba(var(--navy-rgb), 0.13);
  /* One red for text/borders, one for solid fills that carry white text. */
  --danger:    #b4342b;
  --danger-bg: #b4342b;
  --radius: 14px;
  /* Tell the browser which way the page leans, so date pickers, checkboxes,
     select popups and UA scrollbars stop rendering light on the dark theme. */
  color-scheme: light;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: 84px; }

/* ---- Global themed scrollbar (applies to the page + every scroll container,
   current and future — modals, the tree viewport, dropdowns, etc.) ---------- */
/* A transparent track lets the browser's DEFAULT (white, clunky) channel show
   through in light mode — so give the track an explicit, subtle tint instead. */
* { scrollbar-width: thin; scrollbar-color: var(--gold) var(--scroll-track); }   /* Firefox */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--scroll-track); }
::-webkit-scrollbar-corner { background: var(--scroll-track); }
::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, var(--gold-bright), var(--gold));
  border-radius: 999px;
  border: 2px solid transparent;        /* transparent inset -> slim floating pill */
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(180deg, var(--gold-bright), var(--gold-deep));
  background-clip: padding-box;
}

/* ---- Kill the browser's autofill paint job ---------------------------------
   When Chrome/Safari autofills a field it slaps its own pale blue/yellow
   background and near-black text over the input, which looked white-on-dark and
   broke the theme. There's no `background` override for it — the supported route
   is a giant inset box-shadow (which paints on top) plus -webkit-text-fill-color.
   The absurd transition delay keeps it from flashing back on focus. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active,
textarea:-webkit-autofill,
select:-webkit-autofill {
  -webkit-text-fill-color: var(--text);
  -webkit-box-shadow: 0 0 0 1000px var(--bg) inset;
          box-shadow: 0 0 0 1000px var(--bg) inset;
  caret-color: var(--text);
  border: 1.5px solid var(--hairline);
  transition: background-color 600000s 0s, color 600000s 0s;
}
/* autofilled passwords keep the gold dots */
input[type="password"]:-webkit-autofill { -webkit-text-fill-color: var(--gold); }

/* the modal's ✕ sits at the card's top-right — keep the tab row out from under it */
.pmodal .portal-tabs { padding-right: 2rem; }

/* ---- Password fields: GOLD masking dots + 🐓 hold-to-peek ------------------
   The dots take the input's own `color`, so this genuinely recolors them (the
   mask *character* itself is browser-drawn and can't be swapped for a glyph). */
input[type="password"] {
  color: var(--gold);
  letter-spacing: .2em;
  font-weight: 700;
}
input[type="password"]::placeholder { color: var(--muted); letter-spacing: normal; font-weight: 400; }

.pw-wrap { position: relative; display: block; }
.pw-wrap > input { width: 100%; padding-right: 3rem !important; }
.pw-peek {
  position: absolute; right: .45rem; top: 50%; transform: translateY(-50%);
  width: 34px; height: 34px; padding: 0; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--hairline); background: var(--tint);
  color: var(--gold);                 /* the SVG rooster is fill=currentColor -> GOLD */
  line-height: 1; display: grid; place-items: center;
  user-select: none; -webkit-user-select: none; touch-action: none;
  transition: background .12s, transform .12s, border-color .12s, color .12s;
}
.pw-peek svg { width: 20px; height: 20px; display: block; }
.pw-peek:hover { background: rgba(var(--gold-rgb),.22); border-color: var(--gold); color: var(--gold-bright); }
/* while held: button fills gold, so flip the bird to navy or it would vanish */
.pw-peek.on { background: var(--gold); border-color: var(--gold-deep); color: var(--navy-deep); transform: translateY(-50%) scale(1.08); }

/* ---- Chapter-title request (profile) ---- */
.title-req {
  margin-top: .5rem; padding: .6rem .75rem; border-radius: 10px;
  font-size: .88rem; border: 1px solid var(--hairline); background: var(--tint); color: var(--heading);
}
.title-req span { display: block; margin-top: .2rem; color: var(--muted); font-size: .8rem; }
.title-req--wait { border-color: rgba(var(--gold-rgb),.5); }
.title-req--no { border-color: rgba(180,52,43,.4); background: rgba(180,52,43,.07); color: var(--danger); }
.title-req-open { margin-top: .5rem; }
.title-req-open > summary {
  cursor: pointer; font-weight: 600; font-size: .88rem; color: var(--gold-deep);
  padding: .5rem .75rem; border: 1px dashed var(--gold); border-radius: 10px; background: var(--tint);
  list-style: none;
}
.title-req-open > summary::-webkit-details-marker { display: none; }
.title-req-open > summary:hover { background: rgba(var(--gold-rgb),.18); }
.title-req-open[open] > summary { border-style: solid; margin-bottom: .7rem; }
.title-req-form { padding: .2rem .1rem; }

/* ---- Account: sign-in email + two-step destructive confirm ---- */
.acct-email {
  margin: 0 0 .9rem; font-family: var(--sans); font-weight: 600; color: var(--heading);
  background: var(--tint); border: 1px solid var(--hairline); border-radius: 10px;
  padding: .65rem .8rem; word-break: break-all;
}
/* Cloudflare Turnstile widget holder on the auth forms. Collapses to nothing
   when empty (widget disabled or not yet mounted) so there's no phantom gap. */
.ts-holder { margin: .2rem 0 .9rem; }
.ts-holder:empty { margin: 0; }
/* Two-factor (2FA) enrollment UI */
.mfa-qr { margin: .6rem 0; }
.mfa-qr img { width: 180px; height: 180px; max-width: 100%; background: #fff; padding: 8px; border-radius: 10px; border: 1px solid var(--hairline); }
.mfa-secret { margin: .2rem 0 .6rem; font-size: .85rem; }
.mfa-secret code { background: var(--tint); border: 1px solid var(--hairline); border-radius: 6px; padding: .15rem .4rem; word-break: break-all; letter-spacing: .05em; }
.mfa-on { margin: 0 0 .8rem; color: var(--heading); font-weight: 600; }
.danger-confirm {
  margin-top: 1rem; padding: 1rem 1.1rem; border-radius: 12px;
  background: rgba(180,52,43,.08); border: 1px solid rgba(180,52,43,.35);
}
.danger-confirm p { margin: 0 0 .5rem; color: var(--danger); }
.danger-confirm ul { margin: 0 0 .9rem; padding-left: 1.1rem; color: var(--text); font-size: .9rem; line-height: 1.7; }
.danger-confirm .field { margin-bottom: .8rem; }
.danger-actions { display: flex; flex-wrap: wrap; gap: .6rem; }
.btn--danger { background: var(--danger-bg); color: #fff; }
.btn--danger:hover:not(:disabled) { background: #9a2b23; transform: translateY(-2px); }
.btn--danger:disabled { opacity: .45; cursor: not-allowed; }

/* ---- Global file-input styling: turn the generic "Choose File" button into a
   gold pill site-wide (applies to every current/future <input type=file>) ---- */
input[type="file"] { font-family: var(--sans); font-size: .88rem; color: var(--muted); cursor: pointer; }
input[type="file"]::file-selector-button,
input[type="file"]::-webkit-file-upload-button {
  font-family: var(--sans); font-weight: 600; font-size: .85rem; letter-spacing: .01em;
  color: var(--navy-deep); background: linear-gradient(180deg, var(--gold-bright), var(--gold));
  border: 0; border-radius: 999px; padding: .5rem 1.15rem; margin-right: .9rem; cursor: pointer;
  transition: box-shadow .15s, transform .15s, filter .15s;
}
input[type="file"]::file-selector-button:hover,
input[type="file"]::-webkit-file-upload-button:hover {
  box-shadow: 0 6px 16px rgba(var(--gold-rgb),.4); transform: translateY(-1px); filter: brightness(1.04);
}
body {
  margin: 0;
  font-family: var(--sans);
  color: var(--text);
  background: var(--bg);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
/* Keyboard skip link (injected by a11y.js) — off-screen until focused. */
.skip-link { position: fixed; left: .5rem; top: -3rem; z-index: 3000; background: var(--gold); color: var(--navy-deep); padding: .65rem 1.1rem; border-radius: 0 0 10px 10px; font-weight: 700; font-size: .9rem; transition: top .15s; }
.skip-link:focus { top: 0; outline: 2px solid var(--navy-deep); outline-offset: 2px; }

h1, h2, h3 { font-family: var(--display); font-weight: 700; line-height: 1.12; margin: 0 0 .4em; }
.section-title { font-size: clamp(2rem, 4vw, 3rem); color: var(--heading); }
p { margin: 0 0 1em; }

.wrap { width: min(var(--wrap), 92vw); margin-inline: auto; }
.section { padding: clamp(4rem, 9vw, 7rem) 0; }
.section--navy { background: var(--navy); color: var(--on-navy); }
.section--navy .section-title { color: var(--gold-bright); }
.section--cream2 { background: var(--bg-2); }
.center { text-align: center; }

/* Eyebrow + gold rule */
.eyebrow {
  font-family: var(--sans);
  font-size: .78rem; font-weight: 700; letter-spacing: .28em;
  text-transform: uppercase; color: var(--gold-deep); margin-bottom: .8rem;
}
.section--navy .eyebrow { color: var(--gold-bright); }
.rule { width: 74px; height: 3px; background: var(--gold); border: 0; margin: 1.1rem 0; }
.center .rule { margin-inline: auto; }
.lede { font-size: 1.18rem; color: var(--muted); max-width: 60ch; }
.section--navy .lede { color: var(--on-dark); }
.center .lede { margin-inline: auto; }

/* Buttons */
.btn {
  display: inline-block; font-weight: 600; font-size: .98rem;
  padding: .85rem 1.7rem; border-radius: 999px; cursor: pointer;
  border: 2px solid transparent; transition: transform .15s, box-shadow .2s, background .2s, color .2s;
}
.btn:active { transform: translateY(1px); }
.btn--gold { background: linear-gradient(180deg, var(--gold-bright), var(--gold)); color: var(--navy-deep); box-shadow: 0 10px 24px rgba(var(--gold-rgb),.35); }
.btn--gold:hover { box-shadow: 0 14px 30px rgba(var(--gold-rgb),.5); transform: translateY(-2px); }
/* Soft gold fill so the secondary button reads as a solid pill, not a washed
   outline; hover still fills solid gold. */
.btn--ghost { border-color: var(--gold); color: var(--gold-deep); background: rgba(var(--gold-rgb),.12); }
.btn--ghost:hover { background: var(--gold); color: var(--navy-deep); }
/* Most ghost buttons live on CREAM cards — modals, the notifications page, the
   gallery manager — where the bright gold read at 1.38:1. The base is therefore
   the deep gold (5.0:1 on cream); the bright gold is restored below for the
   handful of places the pill genuinely sits on navy. */
.hero .btn--ghost,
.section--navy .btn--ghost,
.navy-body .btn--ghost,
.admin-body .btn--ghost { color: var(--gold-bright); }
.btn--navy { background: var(--navy); color: var(--on-navy); }
.btn--navy:hover { background: var(--navy-2); transform: translateY(-2px); }

/* Brand-gold focus ring for everything without a bespoke one. :where() has zero
   specificity, so the hand-tuned rings further down still win. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
/* Windows High Contrast throws away box-shadow, and several controls here use a
   shadow ring as their only focus cue — re-assert a real outline for those. */
@media (forced-colors: active) {
  :where(a, button, input, select, textarea, [tabindex]):focus-visible,
  .field input:focus, .field select:focus, .field textarea:focus,
  .admin-search:focus, .ask-input:focus, .zselect:focus, .oc-card:focus-visible {
    outline: 2px solid Highlight;
    outline-offset: 2px;
  }
}
/* One disabled treatment: opacity ran .4-.75 with the cursor alternating. */
.btn:disabled, .btn[disabled],
button:disabled, select:disabled, input:disabled, textarea:disabled {
  opacity: .5;
  cursor: not-allowed;
}

/* ---------- Header / nav ---------- */
.nav {
  position: fixed; inset: 0 0 auto 0; z-index: 100;
  background: rgba(var(--chrome), 0.92); backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(var(--gold-rgb),.28);
}
.nav__inner { display: flex; align-items: center; justify-content: space-between; height: 72px; }
.brand { display: flex; align-items: center; gap: .7rem; color: var(--on-navy); }
.brand img { height: 42px; width: auto; }
.brand__txt { font-family: var(--display); font-size: 1.15rem; font-weight: 700; letter-spacing: .04em; }
.brand__txt small { display: block; font-family: var(--sans); font-size: .6rem; letter-spacing: .25em; color: var(--gold-bright); font-weight: 600; }
.nav__links { display: flex; align-items: center; gap: 1.6rem; }
.nav__links a { color: var(--on-navy-2); font-size: .92rem; font-weight: 500; letter-spacing: .02em; transition: color .15s; }
.nav__links a:hover { color: var(--gold-bright); }
.nav__cta { padding: .55rem 1.2rem; font-size: .88rem; }
/* ---------- "Brothers" nav group ----------
   Find a Mentor and Worldwide Map were reachable from exactly ONE place on the
   whole site (the collapsed account submenu) — no nav, no footer, no perks grid.
   They could not simply be added to the top row: measured at 1024px the row had
   4px of headroom. Folding the six members-only pages behind one item frees
   ~360px and surfaces both.

   Opens on hover AND focus-within, so it costs no click handler, no
   outside-click listener, and no JS — and a keyboard user gets it by tabbing to
   the button, which is what makes the panel's links focusable in the first
   place. aria-expanded is deliberately absent rather than hardcoded to a value
   nothing updates; aria-haspopup states what's true. */
/* display:flex, not the default block: as a block the inline-flex button below
   sat on a TEXT BASELINE inside this wrapper's line box, which pushed "Brothers"
   ~1.7px below every other item in the row. */
.nav__group { position: relative; display: flex; align-items: center; }
.nav__group-btn {
  display: inline-flex; align-items: center; gap: .3rem;
  background: none; border: 0; padding: 0 0 4px; cursor: pointer;
  font-family: inherit; font-size: .92rem; font-weight: 500; letter-spacing: .02em;
  /* A <button> does not inherit line-height, so this computed to `normal` (21.6px
     tall) while the sibling links inherit 24.288px. 1.65 IS that 24.288px at
     .92rem — same line box, same text top, same 28.29px outer height. */
  line-height: 1.65;
  color: var(--on-navy-2); transition: color .15s;
}
.nav__group-btn:hover, .nav__group:focus-within .nav__group-btn { color: var(--gold-bright); }
.nav__group--on .nav__group-btn { color: var(--gold-bright); font-weight: 700; }
.nav__group-btn .nav__caret { font-style: normal; font-size: .7rem; }
.nav__group-menu {
  position: absolute; top: calc(100% + 10px); left: 50%; transform: translateX(-50%);
  min-width: 190px; padding: .4rem 0; border-radius: var(--radius);
  background: var(--surface); box-shadow: 0 18px 50px rgba(var(--chrome),.35);
  display: none; z-index: 120;
}
/* Invisible bridge across the 10px gap. Without it the pointer leaves the group
   on the way down and the panel shuts before you reach it. */
.nav__group-menu::before { content: ''; position: absolute; left: 0; right: 0; top: -12px; height: 12px; }
.nav__group:hover .nav__group-menu, .nav__group:focus-within .nav__group-menu,
.nav__group-btn[aria-expanded="true"] + .nav__group-menu { display: block; }
.nav__group-menu a { display: block; padding: .55rem 1.1rem; font-size: .86rem; color: var(--text); }
.nav__group-menu a:hover { background: var(--bg); color: var(--gold-deep); }
.nav__group-menu a.on { color: var(--gold-deep); font-weight: 700; }
.nav__group-menu a::after { display: none; }   /* the underline sweep is for the top row only */

.nav__toggle { display: none; background: none; border: 0; cursor: pointer; padding: 8px; }
.nav__toggle span { display: block; width: 26px; height: 2px; background: var(--gold-bright); margin: 5px 0; transition: .25s; }

/* Account indicator (top-right) */
.nav__account { display: flex; align-items: center; position: relative; }
.nav__chip {
  display: flex; align-items: center; gap: .55rem; cursor: pointer;
  background: rgba(var(--gold-rgb),.10); border: 1.5px solid rgba(var(--gold-rgb),.5);
  color: var(--on-navy); border-radius: 999px; padding: .32rem .7rem .32rem .35rem;
  font-family: var(--sans); font-size: .9rem; transition: background .15s, border-color .15s;
}
.nav__chip:hover { background: rgba(var(--gold-rgb),.2); border-color: var(--gold); }
.nav__avatar {
  position: relative; width: 30px; height: 30px; flex: none; border-radius: 50%;
  background: linear-gradient(180deg, var(--gold-bright), var(--gold)); color: var(--navy-deep);
  display: grid; place-items: center; font-family: var(--display); font-weight: 700; font-size: .95rem;
}
.nav__chip-name { max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.nav__caret { color: var(--gold-bright); font-size: .7rem; }
.admin-badge {
  background: linear-gradient(180deg, var(--gold-bright), var(--gold)); color: var(--navy-deep);
  font-size: .6rem; font-weight: 800; letter-spacing: .1em; padding: .12rem .4rem; border-radius: 5px;
}
.nav__menu {
  position: absolute; top: calc(100% + 10px); right: 0; width: 232px;
  background: #0c2350; border: 1px solid rgba(var(--gold-rgb),.35); border-radius: 12px;
  padding: .5rem; z-index: 120; box-shadow: 0 18px 44px rgba(0,0,0,.5);
  display: none;
}
.nav__menu.open { display: block; }
.nav__menu-head { padding: .5rem .6rem .7rem; border-bottom: 1px solid rgba(255,255,255,.08); margin-bottom: .4rem; }
.nav__menu-head b { display: block; color: var(--on-navy); font-family: var(--display); font-size: 1rem; }
.nav__menu-head span { display: block; color: var(--on-dark); font-size: .74rem; overflow: hidden; text-overflow: ellipsis; }
.nav__menu-head .admin-badge { display: inline-block; margin-top: .45rem; }
.nav__menu a, .nav__menu button {
  display: block; width: 100%; text-align: left; background: none; border: 0; cursor: pointer;
  color: var(--on-navy-2); font-family: var(--sans); font-size: .9rem; padding: .6rem .6rem; border-radius: 8px; transition: background .12s, color .12s;
}
.nav__menu a:hover, .nav__menu button:hover { background: rgba(var(--gold-rgb),.12); color: var(--gold-bright); }
.nav__menu-admin { color: var(--gold-bright) !important; font-weight: 600; }
.nav__menu-divider { height: 1px; background: rgba(255,255,255,.08); margin: .4rem 0; }
.nav__menu-signout:hover { background: rgba(180,52,43,.18) !important; color: #ff9c93 !important; }

/* "Brothers Only" — expands in place to the members-only surfaces */
.nav__sub-toggle {
  display: flex; align-items: center; gap: .65rem; width: calc(100% - .9rem);
  margin: 0 .45rem; padding: .6rem .55rem; border: 0; border-radius: 8px; cursor: pointer;
  background: none; color: var(--gold-bright); font-family: var(--sans); font-size: .9rem; font-weight: 600;
  text-align: left; transition: background .12s;
}
.nav__sub-toggle i { font-style: normal; flex: none; width: 22px; text-align: center; }
.nav__sub-toggle:hover { background: rgba(var(--gold-rgb),.12); }
.nav__sub-caret { font-style: normal; margin-left: auto; font-size: .7rem; transition: transform .2s; }
.nav__sub-toggle[aria-expanded="true"] .nav__sub-caret { transform: rotate(180deg); }
.nav__sub { display: none; margin: .1rem .45rem .2rem; padding-left: .6rem; border-left: 2px solid rgba(var(--gold-rgb),.3); }
.nav__sub.open { display: block; }
.nav__sub a { font-size: .86rem; padding: .45rem .5rem; }

/* Log in / Sign up CTA + its dropdown */
.nav__login-btn { display: inline-flex; align-items: center; gap: .4rem; }
.nav__login-btn .nav__caret { color: var(--navy-deep); font-size: .62rem; transition: transform .2s; }
.nav__login-btn[aria-expanded="true"] .nav__caret { transform: rotate(180deg); }
.nav__menu--login { width: 262px; padding: .4rem; }
.nav__menu--login a {
  display: flex; align-items: center; gap: .7rem;
  padding: .55rem .6rem; margin: .12rem 0; border-radius: 11px; line-height: 1.2;
}
.nav__login-ic {
  flex: none; width: 36px; height: 36px; border-radius: 50%;
  display: grid; place-items: center; font-size: 1.05rem;
  background: rgba(var(--gold-rgb),.14); border: 1px solid rgba(var(--gold-rgb),.32);
  transition: background .12s, border-color .12s;
}
.nav__login-txt { display: flex; flex-direction: column; min-width: 0; gap: .1rem; }
.nav__login-txt b { font-family: var(--display); font-weight: 600; font-size: 1rem; color: var(--on-navy); letter-spacing: .01em; }
.nav__login-txt small { font-size: .74rem; color: var(--on-dark); opacity: .72; white-space: nowrap; }
.nav__menu--login a:hover .nav__login-ic { background: rgba(var(--gold-rgb),.28); border-color: var(--gold); }
.nav__menu--login a:hover .nav__login-txt small { opacity: .95; }

/* ---------- Hero ---------- */
.hero {
  position: relative; min-height: 100svh; display: flex; align-items: center;
  color: var(--on-navy); padding-top: 72px; overflow: hidden;
}
/* Smooth navy field with warm gold accent glows on both sides. */
.hero__bg {
  position: absolute; inset: 0; z-index: 0;
  background:
    radial-gradient(80% 70% at 26% 42%, rgba(var(--gold-rgb),.30), rgba(var(--gold-rgb),0) 60%),
    radial-gradient(90% 80% at 96% 8%, rgba(var(--gold-bright-rgb),.16), rgba(var(--gold-bright-rgb),0) 55%),
    radial-gradient(140% 120% at 50% 120%, var(--navy-2), rgba(var(--navy-2-rgb),0) 60%),
    linear-gradient(180deg, var(--navy-deep) 0%, var(--navy) 55%, var(--navy-deep) 100%);
}
/* Two columns: crest on the left, text on the right — no overlap. */
.hero__inner {
  position: relative; z-index: 2; width: min(var(--wrap), 92vw); margin-inline: auto;
  display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(1.5rem, 4vw, 4rem); align-items: center;
}
.hero__crest-col { display: flex; flex-direction: column; align-items: center; justify-content: center; }
/* "est. 1996" was baked into the crest art, inline with the bead arc — black on
   navy, so it vanished once the white background came off. It's painted out of
   the PNG (arc closed with matching beads) and set as real text here instead. */
.hero__est {
  /* Same box as the crest image, so the two centres coincide exactly. */
  display: block; width: 100%; max-width: 460px;
  margin: -.4rem auto 0; text-align: center;
  font-family: var(--display); font-weight: 700;
  color: var(--gold-bright); font-size: 1.05rem;
  /* letter-spacing also trails the LAST glyph, which drags centred text left by
     half a space; an equal text-indent restores true optical centring. */
  letter-spacing: .42em; text-indent: .42em;
  text-shadow: 0 2px 12px rgba(0,0,0,.6);
  animation: heroCrestIn 1s cubic-bezier(.2,.7,.2,1) both;
}
@media (max-width: 820px) { .hero__est { font-size: .9rem; letter-spacing: .34em; text-indent: .34em; } }
/* crest-hero.webp has its white background cut out, so the crest floats straight
   on the navy hero — no plate, no rectangle. */
.hero__crest-img {
  width: 100%; max-width: 460px; height: auto; display: block; margin-inline: auto;
  filter: drop-shadow(0 18px 46px rgba(0,0,0,.5));
  animation: heroCrestIn 1s cubic-bezier(.2,.7,.2,1) both;
}
@keyframes heroCrestIn { from { opacity: 0; transform: translateY(14px) scale(.97); } to { opacity: 1; transform: none; } }
/* The .fx class is only on <html> when the visitor has NOT asked for less motion. */
html:not(.fx) .hero__crest-img, html:not(.fx) .hero__crest { animation: none !important; }
html:not(.fx) .tree-node--pulse { animation: none !important; }
html:not(.fx) .nav__menu, html:not(.fx) .acct__menu { animation: none !important; }
.hero__text { text-align: left; }
.hero__kicker { font-size: .82rem; letter-spacing: .32em; text-transform: uppercase; color: var(--gold-bright); font-weight: 700; text-shadow: 0 2px 10px rgba(0,0,0,.6); margin: 0 0 .4rem; }
.hero h1 { font-size: clamp(2.6rem, 6vw, 5rem); line-height: 1.02; margin: .2rem 0 0; text-shadow: 0 4px 24px rgba(0,0,0,.6), 0 1px 3px rgba(0,0,0,.85); }
.hero h1 .amp { color: var(--gold-bright); font-style: italic; }
/* Stronger gold accent under the headline. */
.hero__rule { border: 0; height: 3px; width: 96px; margin: 1.2rem 0 1.3rem;
  background: linear-gradient(90deg, var(--gold-bright), var(--gold-deep));
  border-radius: 3px; box-shadow: 0 0 18px rgba(var(--gold-bright-rgb),.45); }
.hero__tag { font-size: clamp(1.02rem, 1.7vw, 1.3rem); max-width: 46ch; margin: 0 0 2rem; color: var(--on-navy-2); text-shadow: 0 2px 14px rgba(0,0,0,.7); }
.hero__cta { display: flex; gap: 1rem; flex-wrap: wrap; }

/* Stack on narrower screens: crest on top, text centered below. */
@media (max-width: 820px) {
  .hero__inner { grid-template-columns: 1fr; gap: 1.2rem; text-align: center; }
  .hero__crest-img { max-width: 300px; }
  .hero__text { text-align: center; }
  .hero__rule { margin-left: auto; margin-right: auto; }
  .hero__cta { justify-content: center; }
  /* Breathing room so the CTA doesn't crowd the cream section below. */
  .hero { padding-bottom: clamp(2.75rem, 7vh, 4.5rem); }
  /* Mobile Safari rasterises `filter: drop-shadow()` to the element's BOX rather
     than to the PNG's alpha, which drew a faint rectangular edge under the crest
     (invisible on desktop). The crest reads fine on navy unaided — drop the
     filter on phones in BOTH themes so no box can be painted. */
  .hero__crest-img,
  :root[data-theme="dark"] .hero__crest-img { filter: none; }
}

/* ---------- About / values ---------- */
.split { display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
.founding-note { background: var(--navy); color: var(--on-navy); border-radius: var(--radius); padding: 2rem 2.2rem; box-shadow: var(--shadow); border: 1px solid rgba(var(--gold-rgb),.3); }
.founding-note h3 { color: var(--gold-bright); font-size: 1.5rem; }
.stat-row { display: flex; gap: 2.5rem; flex-wrap: wrap; margin-top: 1.4rem; }
.stat { }
.stat b { display: block; font-family: var(--display); font-size: 2.4rem; color: var(--gold-bright); line-height: 1; }
.stat span { font-size: .82rem; letter-spacing: .06em; color: var(--on-dark); }

.values { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.4rem; margin-top: 3rem; }
.value { background: var(--surface); border-radius: var(--radius); padding: 1.8rem; box-shadow: var(--shadow-sm); border-top: 4px solid var(--gold); }
.value h3 { color: var(--heading); font-size: 1.35rem; }
.value p { color: var(--muted); margin: 0; font-size: .98rem; }

/* Badges */
.badges { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.2rem; margin-top: 2.6rem; }
.badge { text-align: center; }
.badge__seal {
  width: 92px; height: 92px; margin: 0 auto .8rem; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--gold-bright), var(--gold-deep));
  display: grid; place-items: center; color: var(--navy-deep); font-size: 2rem;
  box-shadow: inset 0 0 0 4px rgba(255,255,255,.25), 0 8px 20px rgba(0,0,0,.3); border: 3px solid var(--gold-bright);
}
.badge b { display: block; color: var(--gold-bright); font-family: var(--display); font-size: 1rem; }
.badge span { font-size: .74rem; color: var(--on-dark); letter-spacing: .05em; }

/* ---------- Brotherhood / flip cards ---------- */
.grid-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem; margin-top: 2.6rem; }
.flip { perspective: 1200px; aspect-ratio: 4/5; }
.flip__inner { position: relative; width: 100%; height: 100%; transition: transform .6s cubic-bezier(.4,.2,.2,1); transform-style: preserve-3d; }
.flip:hover .flip__inner, .flip:focus-within .flip__inner, .flip.is-flipped .flip__inner { transform: rotateY(180deg); }
.flip__face { position: absolute; inset: 0; backface-visibility: hidden; border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); }
.flip__front { background: var(--navy-2); }
.flip__front img { width: 100%; height: 100%; object-fit: cover; }
.flip__name { position: absolute; left: 0; right: 0; bottom: 0; padding: .9rem 1rem; background: linear-gradient(transparent, rgba(var(--chrome),.92)); color: var(--on-navy); }
.flip__name b { font-family: var(--display); font-size: 1.1rem; display: block; }
.flip__name span { font-size: .78rem; color: var(--gold-bright); letter-spacing: .04em; }
.flip__back { background: var(--navy); color: var(--on-navy); transform: rotateY(180deg); display: flex; flex-direction: column; justify-content: center; padding: 1.4rem; border: 2px solid var(--gold); }
.flip__back .role { color: var(--gold-bright); font-weight: 700; letter-spacing: .05em; text-transform: uppercase; font-size: .74rem; }
.flip__back .quote { font-family: var(--serif); font-size: 1.15rem; line-height: 1.4; margin-top: .5rem; }
.flip__back .meta { margin-top: auto; font-size: .82rem; color: var(--on-dark); }
.eboard-label { margin-top: 2.4rem; }

/* ---------- Rush ---------- */
.rush-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem,5vw,4rem); align-items: start; }
.steps { list-style: none; padding: 0; margin: 1.4rem 0 0; counter-reset: s; }
.steps li { position: relative; padding: 0 0 1.4rem 3.2rem; counter-increment: s; }
.steps li::before { content: counter(s); position: absolute; left: 0; top: -2px; width: 2.2rem; height: 2.2rem; border-radius: 50%; background: var(--gold); color: var(--navy-deep); font-weight: 700; display: grid; place-items: center; font-family: var(--display); }
.steps li b { display: block; color: var(--heading); font-family: var(--display); font-size: 1.15rem; }
.section--navy .steps li b { color: var(--gold-bright); }
.steps li p { margin: .15rem 0 0; color: var(--muted); font-size: .95rem; }
.section--navy .steps li p { color: var(--on-dark); }

/* ---------- Forms ---------- */
.card-form { background: var(--surface); border-radius: var(--radius); padding: 2rem; box-shadow: var(--shadow); border-top: 5px solid var(--gold); }
.section--navy .card-form { color: var(--text); }
.field { margin-bottom: 1.1rem; }
.field label { display: block; font-size: .82rem; font-weight: 600; letter-spacing: .04em; color: var(--heading); margin-bottom: .35rem; }
.field input, .field select, .field textarea {
  width: 100%; padding: .8rem .9rem; border: 1.5px solid var(--hairline); border-radius: 10px;
  font-family: var(--sans); font-size: .98rem; background: var(--bg); transition: border .15s, box-shadow .15s;
}
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px rgba(var(--gold-rgb),.25); }
.field textarea { min-height: 120px; resize: vertical; }
.form-row { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 1rem; }
.form-note { font-size: .8rem; color: var(--muted); margin-top: .4rem; }
.form-status { margin-top: 1rem; font-weight: 600; display: none; }
.form-status.ok { display: block; color: #1c7a41; }
.form-status.err { display: block; color: var(--danger); }
.btn[disabled] { opacity: .6; cursor: default; }

/* ---------- Alumni ---------- */
.alumni-cta { display: grid; grid-template-columns: 1.1fr .9fr; gap: 3rem; align-items: center; }
.give-card { background: linear-gradient(160deg, var(--navy-2), var(--navy-deep)); border: 1px solid rgba(var(--gold-rgb),.4); border-radius: var(--radius); padding: 2.4rem; box-shadow: var(--shadow); }
.give-card h3 { color: var(--gold-bright); font-size: 1.7rem; }

/* ---------- Events ---------- */
.events { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.6rem; margin-top: 2.6rem; }
.event { background: var(--surface); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); transition: transform .2s, box-shadow .2s; }
.event:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.event img { aspect-ratio: 4/3; object-fit: cover; width: 100%; }
.event__body { padding: 1.3rem 1.4rem 1.6rem; }
.event__tag { font-size: .72rem; letter-spacing: .12em; text-transform: uppercase; color: var(--gold-deep); font-weight: 700; }
.event h3 { color: var(--heading); font-size: 1.3rem; margin: .3rem 0 .4rem; }
.event p { color: var(--muted); font-size: .95rem; margin: 0; }

/* ---------- Gallery ---------- */
.gallery { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-top: 2.6rem; }
.gallery button { padding: 0; border: 0; cursor: pointer; background: none; border-radius: 12px; overflow: hidden; box-shadow: var(--shadow-sm); }
.gallery img { aspect-ratio: 1; object-fit: cover; width: 100%; transition: transform .35s; }
.gallery button:hover img { transform: scale(1.06); }

.lightbox { position: fixed; inset: 0; z-index: 200; background: rgba(var(--chrome),.94); display: none; align-items: center; justify-content: center; padding: 4vw; }
.lightbox.open { display: flex; }
.lightbox img { max-width: 92vw; max-height: 88vh; border-radius: 10px; border: 3px solid var(--gold); box-shadow: 0 20px 60px rgba(0,0,0,.6); }
.lightbox__close, .lightbox__nav { position: absolute; background: rgba(var(--gold-rgb),.15); color: var(--gold-bright); border: 1.5px solid var(--gold); border-radius: 999px; cursor: pointer; font-size: 1.4rem; width: 52px; height: 52px; display: grid; place-items: center; transition: background .15s; }
.lightbox__close:hover, .lightbox__nav:hover { background: var(--gold); color: var(--navy-deep); }
.lightbox__close { top: 22px; right: 22px; }
.lightbox__nav { top: 50%; transform: translateY(-50%); }
.lightbox__nav.prev { left: 20px; } .lightbox__nav.next { right: 20px; }

/* ---------- Contact ---------- */
.contact-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem,5vw,4rem); }
.socials { display: flex; flex-direction: column; gap: .9rem; margin-top: 1.4rem; }
.social { display: flex; align-items: center; gap: .8rem; color: var(--on-navy); padding: .8rem 1rem; border: 1px solid rgba(var(--gold-rgb),.35); border-radius: 12px; transition: background .15s, border .15s; }
.social:hover { background: rgba(var(--gold-rgb),.12); border-color: var(--gold); }
.social .ic { width: 34px; height: 34px; display: grid; place-items: center; background: var(--gold); color: var(--navy-deep); border-radius: 8px; font-weight: 700; flex: none; }
/* two-character marks ("in", "ig") need to shrink to fit the 34px square */
.social .ic--sm { font-size: .78rem; letter-spacing: -.02em; }
.social b { display: block; } .social span { font-size: .82rem; color: var(--on-dark); }

/* ---------- Footer ---------- */
.footer { background: var(--navy-deep); color: var(--on-dark); padding: 3rem 0 2rem; text-align: center; }
.footer img { height: 74px; margin: 0 auto 1rem; }
.footer__nav { display: flex; gap: 1.4rem; justify-content: center; flex-wrap: wrap; margin: 1.2rem 0; }
.footer__nav a { color: var(--on-dark); font-size: .9rem; }
.footer__nav a:hover { color: var(--gold-bright); }
.footer small { display: block; margin-top: 1rem; color: var(--on-navy-3); font-size: .8rem; }
.footer .motto { font-family: var(--serif); font-size: 1.3rem; color: var(--gold-bright); }

/* ---------- Admin: tabs, search, edit modal ---------- */
/* (.btn--danger consolidated at the top button block — the duplicate here had an
   unguarded :hover that lifted/darkened even disabled buttons.) */

.admin-tabs { display: flex; gap: .5rem; margin-bottom: 1rem; flex-wrap: wrap; }
.admin-tabs button {
  background: var(--surface); border: 1.5px solid var(--hairline); color: var(--muted);
  border-radius: 999px; padding: .5rem 1.1rem; font-weight: 600; font-size: .9rem; cursor: pointer; transition: background .15s, color .15s, border-color .15s;
}
.admin-tabs button.on { background: var(--navy); color: var(--on-navy); border-color: var(--heading); }
.tab-count { display: inline-block; min-width: 1.4em; text-align: center; font-size: .75rem; background: rgba(var(--gold-rgb),.25); color: inherit; border-radius: 999px; padding: 0 .35em; margin-left: .2em; }
.admin-tabs button.on .tab-count { background: rgba(255,255,255,.2); }
.admin-search {
  width: 100%; padding: .75rem 1rem; border: 1.5px solid var(--hairline); border-radius: 12px;
  font-family: var(--sans); font-size: .95rem; background: var(--surface); margin-bottom: 1.2rem;
}
.admin-search:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px rgba(var(--gold-rgb),.22); }

.admin-modal { position: fixed; inset: 0; z-index: 220; background: rgba(var(--chrome),.85); display: flex; align-items: flex-start; justify-content: center; padding: 5vh 4vw; overflow-y: auto; }
.admin-modal.open { display: flex; }
.admin-modal__card { background: var(--bg); color: var(--text); border-radius: 16px; width: min(560px, 96vw); padding: 2rem; position: relative; border-top: 6px solid var(--gold); box-shadow: 0 30px 80px rgba(0,0,0,.5); }
.admin-modal__card h3 { color: var(--heading); margin-top: 0; }
/* Import preview: the default 560px card puts Apply off-screen behind 300+ rows,
   and the backdrop is the scroller, so the list needs its own.
   Navy, not the default cream: the preview's body copy (.admin-hint, .cls-sum) is
   --on-dark text designed for the navy console and disappears on a light card.
   Same committed navy+gold in both themes as the rest of the console. */
.admin-modal__card--wide {
  width: min(860px, 96vw);
  background: linear-gradient(180deg, var(--navy), var(--navy-deep));
  color: var(--on-navy);
  border: 1px solid rgba(var(--gold-rgb),.28);
}
.admin-modal__card--wide h3 { color: var(--gold-bright); }
.admin-modal__card--wide .admin-modal__close { color: var(--on-navy); }
/* The one-line-of-text ask modal (ask-modal.js): a narrow navy card. */
.admin-modal__card--ask {
  width: min(460px, 96vw);
  background: linear-gradient(180deg, var(--navy), var(--navy-deep));
  color: var(--on-navy);
  border: 1px solid rgba(var(--gold-rgb),.28);
}
.admin-modal__card--ask h3 { color: var(--gold-bright); }
.admin-modal__card--ask .admin-modal__close { color: var(--on-navy); }
.ask-rows { margin: 0 0 1rem; font-size: .9rem; }
.ask-rows div { display: flex; gap: .6rem; }
.ask-rows span { min-width: 7.5em; color: var(--on-dark); }
.ask-rows b { color: var(--on-navy); font-weight: 600; }
.ask-input { width: 100%; background: rgba(255,255,255,.07); border: 1px solid rgba(var(--gold-rgb),.4); border-radius: 10px; padding: .65rem .8rem; color: var(--on-navy); font: inherit; }
.ask-input:focus { outline: none; border-color: var(--gold-bright); box-shadow: 0 0 0 3px rgba(var(--gold-rgb),.22); }
.ask-warn { margin: .7rem 0 0; font-size: .85rem; color: var(--gold-bright); }
.ask-body { margin: 0 0 1.1rem; font-size: .95rem; line-height: 1.5; color: var(--on-navy); }
.ask-body b, .ask-body strong { color: var(--gold-bright); font-weight: 600; }
.ask-actions { display: flex; justify-content: flex-end; gap: .6rem; margin-top: 1.2rem; }

.imp-list { max-height: 46vh; overflow-y: auto; margin: .5rem 0 1rem; }
/* A decided conflict quiets down so the undecided ones stand out. */
.admin-row--decided { opacity: .6; }
.admin-row--decided .admin-row__info span b { color: var(--gold-bright); }
.admin-modal__close { position: absolute; top: 14px; right: 14px; background: none; border: 0; font-size: 1.3rem; color: var(--muted); cursor: pointer; }
.admin-modal__card .field label { color: var(--heading); }

/* ---------- Privacy "locked" states ---------- */
.flip__locked { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; gap: .5rem; text-align: center; padding: 1rem; color: var(--on-dark); }
.flip__lock-ic { font-size: 1.6rem; }
.bm__locked { margin-top: 1rem; padding: 1.1rem; background: rgba(var(--navy-rgb),.05); border: 1px dashed rgba(var(--navy-rgb),.25); border-radius: 12px; text-align: center; }
.bm__locked b { display: block; color: var(--heading); font-family: var(--display); font-size: 1.1rem; margin: .2rem 0; }
.bm__locked span { display: block; color: var(--muted); font-size: .9rem; margin-bottom: .8rem; }
.bm__locked .btn { padding: .5rem 1.2rem; font-size: .9rem; }

/* Homepage members-only teasers (Find a Mentor / Worldwide Map): a count and a
   button. Never a row, a name, a city or a pin — see main.js for the reasoning. */
.home-stats { display: flex; justify-content: center; gap: 3rem; flex-wrap: wrap; margin-top: 2.2rem; }
.home-stat { text-align: center; }
.home-stat b { display: block; font-family: var(--display); font-size: 2.7rem; line-height: 1; color: var(--gold-deep); }
.home-stat span { display: block; margin-top: .45rem; color: var(--muted); font-size: .84rem; letter-spacing: .04em; }
@media (max-width: 480px) {
  .home-stats { gap: 1.8rem; }
  .home-stat b { font-size: 2.1rem; }
}
.bm__loading { color: var(--muted); text-align: center; padding: 1rem; }
.bm__bio { color: var(--text); font-size: .95rem; margin-top: 1rem; }

/* ---------- Brotherhood directory cards (homepage) ---------- */
.dir-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 1.6rem; margin-top: 2.6rem; }
.dir-card {
  display: block; background: var(--surface); border-radius: var(--radius); padding: 2.2rem;
  box-shadow: var(--shadow-sm); border-top: 5px solid var(--gold); transition: transform .18s, box-shadow .2s;
}
.dir-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.dir-card__ic { font-size: 2rem; display: block; margin-bottom: .6rem; }
.dir-card b { font-family: var(--display); font-size: 1.5rem; color: var(--heading); display: block; }
.dir-card__count { display: inline-block; min-height: 1.2em; color: var(--gold-deep); font-weight: 700; font-size: .9rem; margin: .2rem 0 .5rem; }
.dir-card p { color: var(--muted); font-size: .95rem; margin: 0 0 1rem; }
.dir-card__go { color: var(--gold-deep); font-weight: 600; font-size: .92rem; }

/* ---------- Subpages (active/alumni) ---------- */
.page-body { background: var(--bg); }
.page-main { padding-top: 72px; }
.page-hero { background: var(--navy); color: var(--on-navy); padding: clamp(3rem, 7vw, 5rem) 0; }
.page-hero .lede { color: var(--on-dark); }
#pageCount { color: var(--gold-bright); font-weight: 600; }

/* ---------- Legal pages (privacy, terms) — readable long-form prose ---------- */
.legal { max-width: 820px; margin: 0 auto; }
.legal h2 { font-family: var(--display); color: var(--heading); font-size: clamp(1.4rem, 3vw, 1.8rem); margin: 2.6rem 0 .9rem; }
.legal h2:first-of-type { margin-top: 0; }
.legal h3 { font-family: var(--sans); color: var(--heading); font-size: 1.05rem; font-weight: 700; margin: 1.7rem 0 .5rem; }
.legal p, .legal li { color: var(--text); line-height: 1.75; font-size: 1.02rem; }
.legal p { margin: 0 0 1.05rem; }
.legal ul { margin: .3rem 0 1.2rem; padding-left: 1.25rem; }
.legal li { margin: 0 0 .55rem; }
.legal strong { color: var(--heading); font-weight: 700; }
.legal a { color: var(--gold-deep); text-decoration: underline; text-underline-offset: 2px; }
:root[data-theme="dark"] .legal a { color: var(--gold-bright); }
/* Data-request CTA — beats the .legal a link styling in both themes (fixed gold button, dark text) */
.legal a.legal-cta,
:root[data-theme="dark"] .legal a.legal-cta {
  display: inline-block; text-decoration: none; color: var(--navy-deep);
  background: linear-gradient(180deg, var(--gold-bright), var(--gold));
  font-weight: 700; padding: .7rem 1.15rem; border-radius: 10px;
  box-shadow: 0 10px 24px rgba(var(--gold-rgb),.35);
}
.legal a.legal-cta:hover { box-shadow: 0 14px 30px rgba(var(--gold-rgb),.5); transform: translateY(-1px); }
.legal-updated { color: var(--muted); font-size: .95rem; margin: -.4rem 0 2.2rem; }
.legal-note { background: var(--bg-2); border-left: 3px solid var(--gold); padding: 1rem 1.2rem; border-radius: 8px; margin: 0 0 2rem; }
.legal-note p:last-child { margin-bottom: 0; }
.footer__disclaimer { display: block; max-width: 640px; margin: .7rem auto 0; font-size: .72rem; line-height: 1.55; opacity: .7; }
.footer__legal { display: block; margin-top: .55rem; font-size: .82rem; }
.footer__legal a { color: var(--gold-bright); text-decoration: none; margin: 0 .3rem; }
.footer__legal a:hover { text-decoration: underline; }
.nav__links a.on { color: var(--gold-bright); font-weight: 700; }
.page-empty { color: var(--muted); padding: 1.4rem 0; }

/* minmax(0,1fr), not bare 1fr: a plain 1fr track keeps its min-content floor,
   so one card with a long unbreakable line (name · title · company) silently
   widens its whole column — the "some cards are wider" bug. */
.eb-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1.2rem; margin-top: 1rem; }
.eb-card {
  background: var(--surface); border: 0; border-radius: var(--radius); padding: 1.6rem 1rem; text-align: center;
  box-shadow: var(--shadow-sm); border-top: 4px solid var(--gold); cursor: pointer; transition: transform .15s, box-shadow .2s;
  font-family: var(--sans);
}
.eb-card:hover { transform: translateY(-3px); box-shadow: var(--shadow); }
.eb-card__av { position: relative; overflow: hidden; width: 64px; height: 64px; margin: 0 auto .7rem; border-radius: 50%; background: var(--navy); color: var(--gold-bright); display: grid; place-items: center; font-family: var(--display); font-weight: 700; font-size: 1.3rem; }
.eb-card b { display: block; font-family: var(--display); color: var(--heading); font-size: 1.1rem; }
.eb-card__role { display: block; color: var(--gold-deep); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; font-size: .72rem; margin: .25rem 0; }
.eb-card small { color: var(--muted); font-size: .78rem; }

/* A chair is the same card at lower weight, never a second design: thinner top
   rule, smaller portrait, muted role. That contrast IS the hierarchy the board
   page is asking for — the four officers read as the board, chairs read as the
   men who served beside them, without a word of explanation. */
.eb-grid--chairs { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: .9rem; }
.eb-card--chair { padding: 1.15rem .75rem; border-top-width: 2px; border-top-color: var(--gold-deep); }
.eb-card--chair .eb-card__av { width: 48px; height: 48px; font-size: 1rem; margin-bottom: .55rem; }
.eb-card--chair b { font-size: .95rem; }
.eb-card--chair .eb-card__role { color: var(--muted); letter-spacing: .06em; }

.bro-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .9rem; margin-top: 1rem; }
.bro-card {
  display: flex; align-items: center; gap: .8rem; text-align: left; cursor: pointer;
  background: var(--surface); border: 1.5px solid var(--hairline); border-radius: 12px; padding: .8rem .9rem;
  font-family: var(--sans); transition: border-color .15s, box-shadow .15s, transform .12s;
}
.bro-card:hover { border-color: var(--gold); box-shadow: var(--shadow-sm); transform: translateY(-2px); }
/* No overflow:hidden here — the __dot badge overhangs the circle by design;
   the absolutely-pinned img (below) is what keeps the photo a true circle. */
.bro-card__av { position: relative; width: 44px; height: 44px; flex: none; border-radius: 50%; background: var(--navy-2); color: var(--on-dark); display: grid; place-items: center; font-family: var(--display); font-weight: 700; font-size: .95rem; }
.bro-card--live .bro-card__av { background: var(--navy); color: var(--gold-bright); }
.bro-card__dot { position: absolute; right: -2px; bottom: -2px; width: 12px; height: 12px; border-radius: 50%; background: var(--gold-bright); border: 2px solid var(--surface); }
.bro-card__meta { min-width: 0; }
.bro-card__meta b { display: block; color: var(--heading); font-family: var(--display); font-size: 1.02rem; line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bro-card__meta small { color: var(--muted); font-size: .76rem; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bro-card__tag { font-style: normal; font-size: .68rem; font-weight: 700; color: var(--gold-deep); }
.bro-card__tag--off { color: var(--muted); font-weight: 500; }
.bro-card--live { border-color: rgba(var(--gold-rgb),.55); }

/* ---------- Tree: legend, toggles, registration colors ---------- */
.tree-legend { display: flex; gap: 1.6rem; justify-content: center; flex-wrap: wrap; margin-top: 1.6rem; color: var(--muted); font-size: .85rem; }
.tree-legend .dot { display: inline-block; width: 11px; height: 11px; border-radius: 50%; margin-right: .35rem; vertical-align: -1px; }
.tree-legend .dot--reg { background: var(--gold); box-shadow: 0 0 0 2px rgba(var(--gold-rgb),.3); }
.tree-legend .dot--unreg { background: var(--navy-2); }
.tree-legend .dot--chev { width: auto; height: auto; border-radius: 6px; background: var(--surface); border: 1px solid var(--hairline); padding: 0 .4rem; font-size: .75rem; color: var(--gold-deep); font-weight: 700; }
.tree-toggle {
  position: absolute; left: 50%; bottom: -14px; transform: translateX(-50%);
  background: var(--gold); color: var(--navy-deep); border-radius: 999px; padding: .1rem .55rem;
  font-size: .72rem; font-weight: 800; box-shadow: var(--shadow-sm); white-space: nowrap; z-index: 3;
}
.tree-toggle:hover { background: var(--gold-bright); }
.tree-node--reg { border-color: var(--gold); box-shadow: 0 0 0 3px rgba(var(--gold-rgb),.25), var(--shadow-sm); }
.tree-node--reg .tree-node__av { background: linear-gradient(180deg, var(--gold-bright), var(--gold)); color: var(--navy-deep); }

/* ---------- Portal: claim chooser ---------- */
.portal-choose h3, .portal-claim h3 { color: var(--heading); font-family: var(--display); text-align: center; }
.portal-choice {
  display: block; width: 100%; text-align: left; background: var(--bg); border: 1.5px solid var(--hairline);
  border-radius: 12px; padding: 1rem 1.2rem; margin-bottom: .8rem; cursor: pointer; font-family: var(--sans);
  transition: border-color .15s, background .15s;
}
.portal-choice:hover { border-color: var(--gold); background: var(--tint); }
.portal-choice b { display: block; color: var(--heading); font-size: 1rem; }
.portal-choice span { color: var(--muted); font-size: .85rem; }
.claim-list { max-height: 300px; overflow-y: auto; }
.claim-row {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem; width: 100%;
  background: var(--bg); border: 1.5px solid var(--hairline); border-radius: 10px; padding: .7rem .9rem;
  margin-bottom: .5rem; cursor: pointer; font-family: var(--sans); text-align: left;
}
.claim-row:hover { border-color: var(--gold); }
.claim-row b { color: var(--heading); }
.claim-row span { color: var(--muted); font-size: .8rem; flex: none; }

/* ---------- Real crest badge (white-background art framed on navy) ---------- */
.crest-badge { background: #fff; border-radius: 10px; padding: 3px; border: 1.5px solid var(--gold); box-shadow: 0 5px 16px rgba(0,0,0,.3); object-fit: contain; }
.brand .crest-badge { border-radius: 8px; padding: 2px; }
.footer .crest-badge { border-radius: var(--radius); padding: 6px; }

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
  .split, .rush-grid, .alumni-cta, .contact-grid { grid-template-columns: 1fr; }
  .values { grid-template-columns: 1fr; }
  .badges { grid-template-columns: repeat(2, 1fr); }
  .grid-cards { grid-template-columns: repeat(2, 1fr); }
  .events { grid-template-columns: 1fr; }
  .gallery { grid-template-columns: repeat(2, 1fr); }
  .dir-cards { grid-template-columns: 1fr; }
  .eb-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .eb-grid--chairs { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .bro-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .bro-grid, .eb-grid { grid-template-columns: minmax(0, 1fr); }
  /* Chairs stay two-up where officers go one-up: they are the supporting row,
     and a column of full-width chair cards would out-shout the board itself. */
  .eb-grid--chairs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .nav__links {
    position: fixed; inset: 72px 0 auto 0; flex-direction: column; gap: 0;
    background: rgba(var(--chrome),.98); padding: 1rem 0; border-bottom: 1px solid rgba(var(--gold-rgb),.3);
    transform: translateY(-140%); transition: transform .3s; align-items: stretch;
  }
  .nav__links.open { transform: translateY(0); }
  .nav__links a { padding: .9rem 8vw; }
  /* The desktop row aligns .nav__group with `display:flex` so its button stops
     sitting on a text baseline. Here the submenu is in normal flow, so a flex
     ROW would stand it beside its own label and push it off the screen —
     measured, at 390px. Back to block for the drawer. */
  .nav__group { display: block; }
  .nav__links .nav__cta { margin: .6rem 8vw; text-align: center; }
  .nav__toggle { display: block; }
  .nav__account { margin-left: auto; margin-right: .6rem; }
  .nav__chip-name { max-width: 92px; }
  .form-row { grid-template-columns: 1fr; }
  .stat-row { gap: 1.6rem; }
}
@media (max-width: 460px) {
  .badges, .grid-cards, .gallery { grid-template-columns: 1fr 1fr; }
  .nav__chip-name { display: none; }
}

/* ---------- Family tree ---------- */
.tree-shell { position: relative; }
.tree-viewport {
  position: relative; height: min(56vh, 480px); background:
    radial-gradient(circle at 50% 0%, #fffdf7, var(--cream-2));
  border: 1px solid rgba(var(--navy-rgb),.12); border-radius: var(--radius);
  overflow: hidden; cursor: grab; box-shadow: inset 0 2px 20px rgba(var(--navy-rgb),.06);
  /* The tree owns touch: one finger pans, two fingers pinch. (A `pan-y` here let
     the BROWSER claim vertical movement, which fought our pinch handler and made
     two-finger gestures slide only left/right.) Desktop wheel is gated separately
     in family-tree.js so the page still scrolls. */
  touch-action: none;
}
/* keep the container off the screen edge on phones so a thumb doesn't land in it */
@media (max-width: 760px) {
  .tree-shell { margin-inline: 6px; }
  .tree-viewport { height: min(50vh, 420px); }
}
.tree-viewport.grabbing { cursor: grabbing; }
.tree-canvas { position: absolute; top: 0; left: 0; transform-origin: 0 0; }
.tree-links { position: absolute; top: 0; left: 0; overflow: visible; pointer-events: none; }
.tree-links path { fill: none; stroke: var(--gold); stroke-width: 2.5; opacity: .55; }
.tree-node {
  position: absolute; display: flex; align-items: center; gap: .6rem; padding: .55rem .6rem;
  background: var(--surface); border: 2px solid var(--navy); border-radius: 12px; cursor: pointer;
  box-shadow: var(--shadow-sm); text-align: left; transition: transform .12s, box-shadow .2s, border-color .2s;
}
.tree-node:hover { transform: translateY(-2px); border-color: var(--gold); box-shadow: 0 10px 24px rgba(var(--gold-rgb),.35); z-index: 5; }
.tree-node__av { position: relative; width: 52px; height: 52px; flex: none; border-radius: 50%; overflow: hidden; background: var(--navy); color: var(--gold-bright); display: grid; place-items: center; font-family: var(--display); font-weight: 700; font-size: 1.05rem; }
.tree-node__av img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
.tree-node__meta { overflow: hidden; }
.tree-node__meta b { display: block; font-family: var(--display); font-size: 1.04rem; color: var(--heading); line-height: 1.15; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; }
.tree-node__meta small { color: var(--gold-deep); font-size: .8rem; }
.tree-controls { position: absolute; top: 12px; right: 12px; z-index: 10; display: flex; gap: .4rem; }
.tree-controls button { width: 40px; height: 40px; border-radius: 10px; border: 1px solid rgba(var(--navy-rgb),.15); background: var(--surface); color: var(--heading); font-size: 1.2rem; cursor: pointer; box-shadow: var(--shadow-sm); transition: background .15s; }
.tree-controls button:hover { background: var(--gold); color: var(--navy-deep); }
.tree-hint { text-align: center; color: var(--muted); font-size: .82rem; margin-top: .9rem; }

/* Brother modal */
.bmodal { position: fixed; inset: 0; z-index: 1400; background: rgba(var(--chrome),.9); display: none; align-items: center; justify-content: center; padding: 5vw; } /* above the fullscreen tree shell (z-index 1300) so brother cards open on top */
.bmodal.open { display: flex; }
/* max-height + overflow are what let a long bio scroll INSIDE the card. Without
   them the card grew past the viewport on a phone and could not be scrolled. */
.bmodal__card { background: var(--bg); border-radius: 18px; width: min(440px, 94vw); padding: 2rem; position: relative; box-shadow: 0 30px 80px rgba(0,0,0,.5); border-top: 6px solid var(--gold); max-height: 88vh; overflow-y: auto; overscroll-behavior: contain; }
@media (max-width: 640px) {
  .bmodal { align-items: flex-start; padding: 3vh 3vw; }   /* tall cards start at the top instead of being clipped both ends */
  .bmodal__card { max-height: 92vh; padding: 1.5rem 1.25rem; }
}
/* while any full-screen popup is open, don't let the PAGE scroll behind it */
body.modal-open { overflow: hidden; }
/* iOS Safari ignores overflow:hidden on <body> for touch scrolling — the page keeps
   moving underneath, which is what made the sheet drag feel like it was fighting
   something invisible. position:fixed is the only reliable lock; the inline `top`
   that gallery.js sets preserves the scroll position so nothing jumps.
   Deliberately a SEPARATE class from .modal-open: profile-card.js uses that one and
   does not save a scroll offset, so switching it to fixed would send the page to the
   top every time a brother card opened. */
body.modal-locked { position: fixed; left: 0; right: 0; width: 100%; overflow: hidden; }
.bmodal__close { position: absolute; top: 14px; right: 14px; background: none; border: 0; font-size: 1.3rem; color: var(--muted); cursor: pointer; }
.bmodal__head { display: flex; gap: 1.1rem; align-items: center; margin-bottom: 1.2rem; }
.bmodal__avatar { position: relative; width: 76px; height: 76px; flex: none; border-radius: 50%; background: var(--navy); color: var(--gold-bright); display: grid; place-items: center; font-family: var(--display); font-weight: 700; font-size: 1.5rem; overflow: hidden; }
.bmodal__avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
.bmodal__head h3 { color: var(--heading); margin: 0; font-size: 1.5rem; }
.bmodal__sub { margin: 0; color: var(--gold-deep); font-weight: 600; font-size: .9rem; }
.bmodal__body .bm__row { display: flex; justify-content: space-between; gap: 1rem; padding: .5rem 0; border-bottom: 1px solid rgba(var(--navy-rgb),.08); font-size: .95rem; }
.bmodal__body .bm__row span { color: var(--muted); }
.bmodal__body .bm__row b { color: var(--heading); text-align: right; }
.bmodal__body .bm__quote { font-family: var(--serif); font-size: 1.2rem; color: var(--heading); margin-top: 1rem; }

/* ---------- Brother portal ---------- */
.portal-wrap { max-width: 560px; margin-inline: auto; }
.portal-tabs { display: flex; gap: .5rem; margin-bottom: 1.4rem; }
.portal-tabs button { flex: 1; padding: .7rem; border: 1.5px solid var(--hairline); background: var(--bg); border-radius: 10px; font-weight: 600; cursor: pointer; color: var(--muted); }
.portal-tabs button.on { background: var(--navy); color: var(--on-navy); border-color: var(--heading); }
.portal-msg { text-align: center; padding: 1.5rem 1rem; }
.portal-msg__ic { font-size: 2.6rem; margin-bottom: .5rem; }
.portal-msg h3 { color: var(--heading); }
.portal-msg p { color: var(--muted); }
.portal-live { color: #1c7a41; font-weight: 600; font-size: .9rem; margin-bottom: 1rem; }
.portal-signout { display: block; margin: 1rem auto 0; background: none; border: 0; color: var(--muted); text-decoration: underline; cursor: pointer; font-size: .85rem; }

/* Shared back-navigation pill — the consoles' "← Back to site", the admin
   class drill, the board's "← Back to …" and the portal's back/cancel steps.
   Navy + gold hairline reads on both cream pages and the navy consoles. */
.back-pill {
  display: inline-flex; align-items: center; gap: .4rem;
  background: var(--navy); color: var(--gold-bright);
  border: 1px solid rgba(var(--gold-rgb),.5); border-radius: 999px;
  padding: .5rem 1.1rem; font-size: .85rem; font-weight: 600;
  cursor: pointer; text-decoration: none; line-height: 1;
  transition: border-color .15s, transform .15s;
}
.back-pill:hover { border-color: var(--gold-bright); transform: translateY(-1px); }
.back-pill--center { display: flex; width: max-content; margin: 1.1rem auto 0; }

/* ---------- Admin page ---------- */
.admin-body { background: var(--navy-deep); color: var(--on-navy); min-height: 100vh; }
.admin-topbar { display: flex; align-items: center; justify-content: space-between; padding: 1rem clamp(1rem,5vw,3rem); border-bottom: 1px solid rgba(var(--gold-rgb),.3);
  position: sticky; top: 0; z-index: 50; background: var(--navy-deep); }
.admin-topbar .brand img { height: 40px; }
.admin-topbar__links { display: inline-flex; gap: .5rem; align-items: center; }
.admin-topbar button.back-pill { font-family: inherit; }
.admin-check { display: flex; align-items: center; gap: .5rem; margin: .6rem 0; font-size: .95rem; cursor: pointer; }
.admin-check input { width: 1.05rem; height: 1.05rem; accent-color: var(--gold-bright); }
.admin-wrap { width: min(1180px, 96vw); margin: 2.5rem auto; }

/* ============================================================================
   CONSOLE MASTHEAD — the "chapter registry" signature. Full on the landing
   view; collapses to a slim bar (.is-slim) once you enter a tab. Shared by the
   Admin + Officer consoles (both are .admin-body pages).
   ============================================================================ */
.console-masthead {
  position: relative; overflow: hidden; text-align: center;
  padding: 1.7rem 1rem 1.5rem; margin-bottom: 1.6rem;
  border: 1px solid rgba(var(--gold-rgb),.30); border-radius: var(--radius);
  background:
    radial-gradient(120% 170% at 50% -45%, rgba(var(--gold-rgb),.13), transparent 55%),
    linear-gradient(180deg, var(--navy), var(--navy-deep));
  transition: padding .28s ease;
}
.console-masthead__crest { display: block; width: 60px; height: auto; margin: 0 auto .45rem;
  filter: drop-shadow(0 4px 14px rgba(0,0,0,.5)); transition: width .28s ease; }
.console-masthead__eyebrow { display: block; font-family: var(--sans); font-size: .64rem; font-weight: 700;
  letter-spacing: .32em; text-transform: uppercase; color: var(--gold); }
.console-masthead__title { font-family: var(--display); font-weight: 700; color: var(--on-navy);
  font-size: clamp(1.9rem, 4.5vw, 2.8rem); line-height: 1; margin: .3rem 0 .5rem; }
.console-masthead__rule { display: flex; align-items: center; justify-content: center; gap: .7rem;
  max-width: 320px; margin: .1rem auto .55rem; }
.console-masthead__rule::before, .console-masthead__rule::after { content: ""; height: 1px; flex: 1;
  background: linear-gradient(90deg, transparent, rgba(var(--gold-rgb),.42), transparent); }
.console-masthead__rule i { font-style: normal; color: var(--gold); font-size: .85rem; }
.console-masthead__seat { font-family: var(--serif); font-size: 1.1rem; color: var(--on-dark); margin: 0; }
.console-masthead__seat b { color: var(--gold-bright); font-weight: 700; }

/* Slim state — crest + title on one line, identity pushed to the right. */
.console-masthead.is-slim { display: flex; align-items: center; gap: .85rem; text-align: left; padding: .7rem 1.15rem; }
.console-masthead.is-slim .console-masthead__crest { width: 34px; margin: 0; }
.console-masthead.is-slim .console-masthead__eyebrow,
.console-masthead.is-slim .console-masthead__rule { display: none; }
.console-masthead.is-slim .console-masthead__title { font-size: 1.35rem; margin: 0; }
.console-masthead.is-slim .console-masthead__seat { font-size: .92rem; margin-left: auto; text-align: right; }
@media (max-width: 600px) {
  .console-masthead.is-slim { flex-wrap: wrap; }
  .console-masthead.is-slim .console-masthead__seat { margin-left: 0; width: 100%; text-align: left; }
}

/* ============================================================================
   ADMIN CONSOLE — left rail nav (crest + grouped, alphabetised sections).
   Replaces the old centre-floating pill cloud, which got unreadable once there
   were 14 sections.
   ============================================================================ */
.admin-shell { display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 1.6rem; align-items: start; }

/* The rail is capped to the viewport and scrolls its own nav list. Without the
   cap, a rail taller than the screen cannot be pinned by `sticky` at all — it
   just scrolls with the page, so the bottom sections were only reachable by
   dragging the whole page down. Crest + Sign out stay put; only the list moves. */
.admin-side {
  position: sticky; top: 90px;
  display: flex; flex-direction: column;
  max-height: calc(100vh - 110px);
  background: var(--navy); border: 1px solid rgba(var(--gold-rgb),.32);
  border-radius: var(--radius); padding: 1rem .75rem 1.1rem;
  box-shadow: var(--shadow-sm);
}
.admin-side__nav {
  flex: 1 1 auto; min-height: 0;      /* min-height:0 — a flex child refuses to shrink below its content without it */
  overflow-y: auto;
  overscroll-behavior: contain;       /* finishing the rail must not lurch the page */
  padding-right: .3rem;               /* breathing room for the scrollbar */
}
.admin-side__id, .admin-side__out, .admin-side__burger { flex: none; }
.admin-side__id { display: flex; align-items: center; gap: .6rem; padding: 0 .3rem .8rem; border-bottom: 1px solid rgba(var(--gold-rgb),.22); margin-bottom: .8rem; }
.admin-side__id .crest-badge { width: 40px; height: auto; flex: none; }
.admin-side__id b { display: block; font-family: var(--display); color: var(--gold-bright); font-size: 1.15rem; letter-spacing: .04em; }
.admin-side__id span { display: block; font-size: .7rem; letter-spacing: .12em; text-transform: uppercase; color: var(--on-dark); }

.admin-navgroup { margin-bottom: 1rem; }
.admin-navgroup__label {
  display: block; font-size: .64rem; font-weight: 800; letter-spacing: .18em;
  text-transform: uppercase; color: var(--gold); padding: 0 .5rem .4rem;
}
.admin-navbtn {
  display: flex; align-items: center; gap: .6rem; width: 100%; text-align: left;
  padding: .55rem .6rem; margin-bottom: .18rem; border: 0; border-radius: 9px;
  background: none; cursor: pointer; color: var(--on-dark);
  font-family: var(--sans); font-size: .92rem; font-weight: 500;
  transition: background .12s, color .12s;
}
.admin-navbtn i { font-style: normal; width: 20px; flex: none; text-align: center; }
.admin-navbtn > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The count badge is also a `> span`, so the rule above gave it flex:1 and it stole
   ~half the row from the label (truncating "Unclaimed"/"Title requests"). Size it to
   its content instead, leaving all remaining width to the label. */
.admin-navbtn > span.tab-count { flex: none; }
.admin-navbtn:hover { background: rgba(var(--gold-rgb),.14); color: var(--gold-bright); }
.admin-navbtn.on { background: linear-gradient(180deg, var(--gold-bright), var(--gold)); color: var(--navy-deep); font-weight: 700; }
.admin-navbtn.on .tab-count { background: rgba(7,22,52,.22); color: var(--navy-deep); }
.admin-side__out { width: 100%; margin-top: .4rem; }
.admin-side__officer { display: block; text-align: center; margin-top: auto; }
.admin-side__burger { display: none; }

/* The main column carries a faint high-res crest watermark (same art as the hero)
   so a sparse tab no longer floats in an empty navy void. It sits behind the
   content, which is lifted above it. */
.admin-main { min-width: 0; }
.admin-main .admin-head { display: block; margin-bottom: 1.1rem; }

/* Crest emblem pinned to the LOWER-RIGHT corner of the screen. A single fixed
   rule, so the Admin and Officer consoles carry an IDENTICAL watermark (same
   size, position, opacity) — in both light and dark mode, since the console is
   always dark-chrome. It sits behind the content, which is lifted above it. */
.admin-body::after {
  content: ""; position: fixed; right: 0; bottom: 0; width: 300px; height: 300px;
  background: url(../img/crest-hero.webp) right bottom / contain no-repeat;
  opacity: .06; pointer-events: none; z-index: 0;
}
.admin-topbar, .admin-wrap { position: relative; z-index: 1; }
@media (max-width: 600px) {
  .admin-body::after { width: 168px; height: 168px; opacity: .05; }
}

@media (max-width: 900px) {
  .admin-shell { grid-template-columns: 1fr; gap: 1rem; }
  /* Drawer, not a rail — let it expand to its full height instead of trapping a
     second scrollbar inside a panel that is already at the top of the page. */
  .admin-side { position: static; padding-bottom: .6rem; max-height: none; display: block; }
  .admin-side__nav { overflow-y: visible; padding-right: 0; }
  .admin-side__burger {
    display: block; width: 100%; margin-top: .2rem; padding: .6rem;
    border: 1px solid rgba(var(--gold-rgb),.4); border-radius: 10px; cursor: pointer;
    background: rgba(var(--gold-rgb),.12); color: var(--gold-bright); font-weight: 700; font-family: var(--sans);
  }
  .admin-side__nav, .admin-side__out { display: none; }        /* drawer, closed by default */
  .admin-side__officer { display: none; }
  .admin-side.open .admin-side__nav { display: block; margin-top: .8rem; }
  .admin-side.open .admin-side__out { display: block; }
  .admin-side.open .admin-side__officer { display: block; }
}
/* Login / message card: navy to match the console (box-shadow is invisible on
   navy, so it needs a gold hairline to have an edge). */
.admin-card, .admin-msg { background: linear-gradient(180deg, var(--navy), var(--navy-deep)); color: var(--on-navy);
  border: 1px solid rgba(var(--gold-rgb),.28); border-radius: var(--radius); padding: 2rem; max-width: 420px; margin: 3rem auto; box-shadow: var(--shadow); }
.admin-card h2, .admin-msg h2 { color: var(--gold-bright); }

/* Officer-permissions grid (admin Officers tab + reused nowhere else). */
.og-table { width: 100%; border-collapse: collapse; margin-top: .6rem;
  background: linear-gradient(180deg, var(--console-card-hi), var(--console-card-lo)); border: 1px solid rgba(var(--gold-rgb),.22);
  border-radius: 12px; overflow: hidden; box-shadow: 0 10px 26px rgba(0,0,0,.28); }
.og-table th, .og-table td { padding: .8rem .7rem; border-bottom: 1px solid rgba(var(--gold-rgb),.18); text-align: left; vertical-align: top; }
.og-table tr:last-child td { border-bottom: 0; }
.og-table th { color: var(--gold-bright); font-family: var(--sans); font-size: .95rem; background: rgba(var(--chrome),.55); }
.og-table td b { color: var(--on-navy); }
.og-table th small, .og-table td small { display: block; color: var(--on-dark); font-weight: 400; font-size: .78rem; margin-top: .2rem; }
.og-table th:not(:first-child), .og-table td:not(:first-child) { text-align: center; width: 160px; }
.og-table input[type=checkbox] { width: 20px; height: 20px; accent-color: var(--gold); cursor: pointer; }
.og-na { color: rgba(150,150,150,.5); }
.og-saved { display: block; color: var(--gold-bright); font-size: .68rem; margin-top: .25rem; }
.admin-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.4rem; }
.admin-head h2 { color: var(--gold-bright); margin: 0; font-family: var(--display); font-size: 1.9rem; line-height: 1.05; }
.admin-empty { text-align: center; color: var(--on-dark); padding: 2rem; }
/* Record-row card: crisp lifted navy with a gold "ledger spine" down the left,
   replacing the old washed-out grey (var(--surface) is light in light mode, but
   the console body is always navy, so grey rows read as disabled). */
.admin-row { display: flex; align-items: center; gap: 1rem;
  background: linear-gradient(180deg, var(--console-card-hi), var(--console-card-lo)); color: var(--on-navy);
  border: 1px solid rgba(var(--gold-rgb),.24); border-left: 3px solid var(--gold);
  border-radius: 12px; padding: 1rem 1.1rem; margin-bottom: .8rem;
  box-shadow: 0 10px 26px rgba(0,0,0,.28); transition: transform .12s, border-color .12s; }
.admin-row:hover { transform: translateY(-1px); border-left-color: var(--gold-bright); }
.admin-row__ph { position: relative; width: 54px; height: 54px; flex: none; border-radius: 50%; background: var(--navy); color: var(--gold-bright);
  border: 1px solid rgba(var(--gold-rgb),.28); display: grid; place-items: center; font-family: var(--display); overflow: hidden; }
.admin-row__ph img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
.admin-row__info { flex: 1; min-width: 0; }
.admin-row__info b { display: block; color: var(--on-navy); font-family: var(--serif); font-size: 1.2rem; font-weight: 700; }
/* Direct child only — the meta line. Without `>` this also hit the status chip
   nested in the name <b>, overriding its own colour. */
.admin-row__info > span { color: var(--on-navy-3); font-size: .85rem; }
.admin-row__info em { display: block; color: var(--gold-bright); font-size: .85rem; margin-top: .2rem; }
.admin-row__act { display: flex; gap: .5rem; flex: none; }
/* Refined record-row actions: hairline pills that sit quietly on the navy card
   and light up on hover — not the heavy 2px outline the site buttons use. */
.admin-row__act .btn { padding: .45rem 1rem; font-size: .84rem; border-width: 1px; font-weight: 600; }
.admin-row__act .btn--ghost { border-color: rgba(var(--gold-rgb),.42); color: var(--on-dark); background: none; }
.admin-row__act .btn--ghost:hover { border-color: var(--gold-bright); color: var(--gold-bright); background: rgba(var(--gold-rgb),.10); }
.admin-row__act .btn--danger { background: none; border: 1px solid rgba(178,58,58,.6); color: #e59a9a; }
.admin-row__act .btn--danger:hover { background: #7a2626; color: #fff; border-color: #7a2626; transform: none; }
.admin-row__act .btn--gold { box-shadow: 0 6px 16px rgba(var(--gold-rgb),.28); }
/* Where an Edit button would be on the webmaster's own row (upgrade54). Deliberately NOT
   styled as a disabled button: there is no action here to re-enable, it is a standing rule.
   --on-navy-3 because this sits on the navy console shell and must flip in dark mode. */
.admin-row__locked { display: inline-block; max-width: 15rem; color: var(--on-navy-3);
  font-size: .74rem; line-height: 1.35; text-align: right; letter-spacing: .01em; }

/* Mentoring tab (mentoring-tab.js) — one row per brother, three pill toggles.
   Painted on the navy console shell, so every colour here comes from the --on-navy
   family or --gold: a literal cream/blue-grey would not flip in dark mode. */
.admin-row--mtg { flex-wrap: wrap; align-items: flex-start; }
.mtg-toggles { display: flex; gap: .45rem; flex-wrap: wrap; flex: none; }
.mtg-toggle { display: inline-flex; align-items: center; gap: .4rem; cursor: pointer;
  border: 1px solid rgba(var(--gold-rgb),.32); border-radius: 99px; padding: .3rem .7rem;
  font-size: .8rem; font-weight: 600; color: var(--on-navy-2); background: none;
  transition: border-color .15s, color .15s, background .15s; }
.mtg-toggle:hover { border-color: rgba(var(--gold-rgb),.6); color: var(--on-navy); }
.mtg-toggle input { margin: 0; flex: none; }
.mtg-toggle--on { border-color: var(--gold-bright); color: var(--gold-bright);
  background: rgba(var(--gold-rgb),.12); }
.mtg-toggle input:disabled + span { opacity: .5; }
/* Status sits on its own line so a save message never shoves the toggles around. */
.admin-row--mtg .form-status { flex-basis: 100%; margin: .45rem 0 0; font-size: .78rem; }

/* Timestamp line on record rows — its own muted line so it never collides with actions. */
.admin-row__when { display: block; color: var(--on-navy-3); font-size: .74rem; margin-top: .25rem; letter-spacing: .01em; }

/* Signup email on Pending rows — its own line, a touch brighter than the timestamp so
   it reads clearly when vetting. Scoped under __info to beat `.admin-row__info span`. */
.admin-row__info .admin-row__email { display: block; color: var(--on-navy-2); font-size: .8rem; margin-top: .2rem; word-break: break-all; }

/* Navy/gold dropdown for the always-navy console (title-request approval). */
.zselect {
  appearance: none; -webkit-appearance: none; max-width: 100%;
  background-color: var(--console-field); color: var(--on-navy);
  border: 1px solid rgba(var(--gold-rgb),.5); border-radius: 9px;
  padding: .5rem 1.9rem .5rem .75rem; font-size: .86rem; font-weight: 600; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23E8C766' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .65rem center;
}
.zselect:hover { border-color: var(--gold-bright); }
.zselect:focus { outline: none; border-color: var(--gold-bright); box-shadow: 0 0 0 3px rgba(var(--gold-rgb),.25); }
.zselect option { background: var(--console-field); color: var(--on-navy); }

/* Positions-held editor (inside the theme-aware brother edit modal). */
.pos-editor { display: flex; flex-direction: column; gap: .4rem; }
.pos-row { display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  background: rgba(var(--gold-rgb),.10); border: 1px solid rgba(var(--gold-rgb),.28); border-radius: 8px; padding: .4rem .7rem; }
.pos-row span { color: var(--text); font-size: .9rem; }
.pos-row em { color: var(--heading); opacity: .72; font-style: normal; font-size: .8rem; }
/* Which board a recorded position belongs to. Its own line under the title, because
   deleting a row that is part of a published board is the mistake this prevents —
   and it used to be invisible from here. */
.pos-board { display: block; font-size: .74rem; margin-top: .12rem; color: var(--gold-deep); }
.pos-board--none { color: var(--muted); opacity: .8; }
.pos-del { background: none; border: none; color: var(--danger); cursor: pointer; font-size: 1.05rem; line-height: 1; padding: .1rem .35rem; }
.pos-del:hover { color: #d0433a; }
.pos-add { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; margin-top: .2rem; }
.pos-add .pos-in, .pos-add select { padding: .5rem .7rem; border-radius: 9px; border: 1px solid rgba(var(--gold-rgb),.4);
  background: var(--surface-2); color: var(--text); font-size: .88rem; }
.pos-add .pos-in { flex: 1; min-width: 110px; }
.pos-add select { min-width: 118px; }
.pos-add .pos-in:focus, .pos-add select:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px rgba(var(--gold-rgb),.22); }

@media (max-width: 620px) {
  .admin-row { flex-wrap: wrap; }
  .admin-row__act { width: 100%; }
  /* The action area goes full-width here, so a right-aligned caption strands itself
     against the edge while every other line in the row is left-aligned. */
  .admin-row__locked { text-align: left; max-width: none; }
  .admin-row__act .btn { flex: 1; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .flip__inner { transition: none; }
}

/* ============================================================================
   v4 — Members platform components
   ============================================================================ */

/* ---------- Portal: profile fieldsets + account tab ---------- */
/* Profile modal: a small "brother registry" header (echoes the console masthead's
   crest + gold eyebrow). Left-aligned so it clears the ✕ close button. Uses theme
   tokens, so it adapts to light/dark like the rest of the modal. */
.pf-masthead { display: flex; align-items: center; gap: .55rem; padding: 0 2rem .8rem 0; margin-bottom: 1rem; border-bottom: 1px solid var(--hairline); }
.pf-masthead__crest { width: 34px; height: auto; flex: none; }
.pf-masthead__eyebrow { font-family: var(--sans); font-size: .64rem; font-weight: 700; letter-spacing: .26em; text-transform: uppercase; color: var(--gold); }

.pf-group { border: 1px solid var(--hairline); border-radius: 12px; padding: 1rem 1.2rem 1.2rem; margin: 0 0 1.3rem; }
/* Leadership record — read-only positions list in the profile editor (brother_titles) */
.lead-record { list-style: none; margin: .2rem 0 0; padding: .5rem .75rem; border: 1.5px solid var(--hairline); border-radius: 10px; background: var(--surface); }
.lead-record li { font-size: .92rem; color: var(--text); padding: .2rem 0; }
.lead-record li + li { border-top: 1px solid var(--hairline); }
.lead-record li span { color: var(--muted); }
.pf-group legend { font-family: var(--display); color: var(--heading); font-size: 1.06rem; padding: 0 .55rem; }
/* Gold registry marker before each section name — echoes the console's ✦ rule. */
.pf-group legend::before { content: "✦"; color: var(--gold); font-size: .72em; margin-right: .42rem; vertical-align: middle; opacity: .85; }
.pref-row { display: flex; gap: .9rem; flex-wrap: wrap; padding-top: .55rem; }
.pref-box { display: inline-flex; align-items: center; gap: .4rem; font-size: .92rem; color: var(--text); cursor: pointer; }
/* "I'm open to…" — each option carries a line explaining why you'd tick it, so the
   three boxes stack instead of sitting in a row (upgrade55). The whole tile is the
   label, so the description is part of the click target rather than decoration. */
/* SPECIFICITY, and it is load-bearing for every checkbox on the profile form.
   Every .pref-box lives inside a .field, where `.field label { display:block }` and
   `.field input { width:100% }` are both (0,1,1) — beating the bare (0,1,0) `.pref-box`.
   So the label stops being a flex container and the checkbox stretches. That is why
   "Reach me via" rendered its boxes ABOVE their labels rather than beside them, and it
   has been that way since .pref-box was written; measured at 60px wide. Scoping under
   .field is the entire fix. Keep the prefix on all of these. */
.field .pref-box { display: inline-flex; }
.field .pref-box input[type="checkbox"] { width: auto; flex: none; }

.pref-row--stack { flex-direction: column; gap: .55rem; }
.field .pref-box--rich { display: flex; align-items: flex-start; gap: .65rem; width: 100%;
  padding: .7rem .85rem; border: 1.5px solid var(--hairline); border-radius: 10px;
  background: var(--surface); margin: 0; }
.field .pref-box--rich:hover { border-color: var(--gold); }
.field .pref-box--rich input[type="checkbox"] { margin-top: .2rem; padding: 0; }
.pref-box__txt { display: flex; flex-direction: column; gap: .1rem; }
.pref-box__txt b { color: var(--text); font-size: .92rem; font-weight: 650; letter-spacing: 0; }
.pref-box__txt small { color: var(--muted); font-size: .8rem; line-height: 1.45; font-weight: 400; }
.acct-block { background: var(--surface); border: 1px solid var(--hairline); border-radius: 12px; padding: 1.2rem 1.3rem; margin-bottom: 1.2rem; }
.acct-block h4 { margin: 0 0 .8rem; color: var(--heading); font-family: var(--display); font-size: 1.1rem; }
.acct-block--danger { border-color: #e8c9c9; }
.btn--ghost-danger { background: none; border: 1.5px solid var(--danger); color: var(--danger); }
.btn--ghost-danger:hover { background: var(--danger-bg); color: #fff; }
.form-note.center { text-align: center; }
.form-note a { color: var(--gold-deep); text-decoration: underline; }

/* ---------- Family (branch) selector ---------- */
.fam-bar { display: flex; gap: .5rem; flex-wrap: wrap; justify-content: center; margin: 1.4rem 0 .4rem; }
.fam-chip { border: 1.5px solid var(--navy-2); background: var(--surface); color: var(--heading); border-radius: 999px; padding: .42rem 1rem; font-size: .85rem; font-weight: 600; cursor: pointer; transition: all .15s; }
.fam-chip i { font-style: normal; opacity: .55; font-size: .78rem; }
.fam-chip:hover { border-color: var(--gold-deep); }
.fam-chip.on { background: var(--navy); color: var(--gold-bright); border-color: var(--heading); }

/* ---------- Roster filters ---------- */
.page-filters { display: flex; gap: .7rem; flex-wrap: wrap; align-items: center; margin: -0.4rem 0 1.4rem; }
/* max-width: a native select sizes to its LONGEST option and refuses to
   shrink, so a long profession/class option overflowed phone viewports. */
.page-filter { padding: .55rem .8rem; border-radius: 10px; border: 1.5px solid var(--hairline); background: var(--surface); color: var(--text); font-size: .9rem; max-width: 100%; }
.page-filter-hint { font-size: .84rem; color: var(--muted); }
/* Absolutely pinned to the container box: a percentage height on a grid item
   in an auto-sized track resolves to AUTO (cyclic sizing), so `height:100%`
   let a 3:4 photo keep its natural aspect and overflow the circle as an oval.
   inset:0 sizes against the positioned container instead — always a true
   square crop. overflow:hidden on the containers is the backstop. */
.bro-card__av img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
.eb-card__av img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
.bro-card__extra { color: var(--gold-deep) !important; }

/* ---------- Author chip (gallery/board) ---------- */
.author-chip { display: inline-flex; align-items: center; gap: .45rem; }
.author-chip__av { position: relative; width: 26px; height: 26px; border-radius: 50%; background: var(--navy); color: var(--gold-bright); display: inline-grid; place-items: center; font-size: .75rem; font-style: normal; overflow: hidden; flex: none; }
.author-chip__av img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
.author-chip b { font-size: .92rem; color: var(--heading); }

/* ---------- Gallery ---------- */
.gallery-teaser { margin-top: 2.4rem; }
.gallery a { display: block; border-radius: 12px; overflow: hidden; box-shadow: var(--shadow-sm); }
.gallery a img { aspect-ratio: 1; object-fit: cover; width: 100%; transition: transform .35s; }
.gallery a:hover img { transform: scale(1.06); }

/* An ATTRIBUTE has to beat a CLASS here. .gupload__prev sets display:block and
   .gedit-form display:flex, and a class rule outranks the UA stylesheet's
   [hidden]{display:none} — so both stayed on screen while "hidden". For the
   preview that meant a src-less <img> was told to render, and a src-less <img>
   draws its ALT TEXT in a broken frame: the "Preview of the photo you chose"
   box sitting in the middle of the composer. */
.gupload__prev[hidden], .gedit-form[hidden] { display: none; }

.gupload { background: var(--surface); border: 1.5px dashed var(--hairline); border-radius: var(--radius); padding: 1rem; margin-bottom: 2rem; }
.gupload__drop { display: block; text-align: center; padding: 1.6rem 1.2rem; cursor: pointer; color: var(--heading); border-radius: 11px; transition: background .15s; }
.gupload__drop:hover { background: var(--bg-2); }
.gupload__drop b { display: block; font-family: var(--display); font-size: 1.12rem; letter-spacing: .01em; }
/* The camera mark: a gold ring, drawn not typed — an emoji renders differently
   on every platform and this is the first thing on the page. */
.gupload__mark { display: grid; place-items: center; width: 46px; height: 46px; margin: 0 auto .6rem;
  border: 1.5px solid var(--gold-bright); border-radius: 50%; color: var(--gold-deep); }
.gupload__mark svg { width: 21px; height: 21px; display: block; }
.gupload__hint { display: block; color: var(--muted); font-size: .84rem; margin-top: .3rem; }
.gupload__drop:focus-within { outline: 2px solid var(--gold-bright); outline-offset: 2px; }

/* Chosen state: the plate becomes the photo, so it is obvious the file landed. */
.gupload__chosen { display: block; }
.gupload__chosen[hidden] { display: none; }

/* ---- a batch of photos: a contact sheet, not a filename --------------------
   One preview cannot represent twelve photos, and "12 files selected" is a number
   you have to take on trust. Twelve thumbnails are the receipt. */
.gupload__strip { display: block; }
.gupload__strip[hidden] { display: none; }
.gupload__stripn { display: block; text-align: center; margin-bottom: .7rem; }
.gupload__stripn b { display: block; font-size: 1rem; color: var(--heading); }
.gupload__stripn span { display: block; color: var(--muted); font-size: .82rem; }
.gupload__thumbs { display: flex; flex-wrap: wrap; gap: .35rem; justify-content: center; }
.gupload__thumbs img { width: 62px; height: 62px; object-fit: cover; border-radius: 8px;
  border: 1px solid var(--hairline); }
.gupload__more { display: inline-flex; align-items: center; justify-content: center;
  width: 62px; height: 62px; border-radius: 8px; background: var(--tint);
  border: 1px dashed var(--hairline); color: var(--muted); font-size: .82rem; font-weight: 700; }
.gupload__prev { display: block; max-width: 100%; max-height: 260px; margin: 0 auto; border-radius: 11px; box-shadow: var(--shadow-sm); }
.gupload__meta { display: flex; align-items: baseline; justify-content: center; gap: .5rem; flex-wrap: wrap; margin-top: .7rem; }
.gupload__meta b { display: inline; font-family: inherit; font-size: .92rem; font-weight: 600; max-width: 60vw;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gupload__meta span { color: var(--muted); font-size: .82rem; }
.gupload__change { display: inline-block; margin-top: .45rem; color: var(--gold-deep); font-size: .85rem;
  font-weight: 600; text-decoration: underline; }
/* Thumbnail shown beside a plain file input once an image is chosen (board
   thread photo, profile photo). --round matches the circular avatar crop. */
.file-prev { display: block; max-width: 100%; max-height: 180px; margin-top: .6rem; border-radius: 10px; box-shadow: var(--shadow-sm); }
.file-prev--round { width: 96px; height: 96px; max-height: none; object-fit: cover; border-radius: 50%; }
/* Where the photo will land, when there is no picker to say it. */
.gupload__dest { margin: .9rem 0 0; text-align: center; color: var(--muted); font-size: .86rem; }
.gupload__dest b { color: var(--heading); font-weight: 600; }
.gupload__row { display: flex; flex-wrap: wrap; gap: .7rem; margin-top: .8rem; }
.gupload__row input { flex: 1; min-width: 160px; padding: .7rem .9rem; border-radius: 10px; border: 1.5px solid var(--hairline); font-size: .95rem; }
.gupload__album { flex: 0 1 auto; min-width: 140px; max-width: 220px; }

/* The album filter chips lived here. Sections-first browsing replaced them: you
   pick a section on the front door, and inside one .gsechead names it. Removed
   with their markup rather than left as orphan CSS. */

/* Admin console gallery storage meter (navy surface -> flipping tokens only). */
.stor-meter { margin: .2rem 0 1rem; }
.stor-meter__bar { height: 12px; border-radius: 999px; background: var(--console-field); border: 1px solid var(--hairline); overflow: hidden; }
.stor-meter__bar span { display: block; height: 100%; border-radius: 999px; background: var(--gold-bright); transition: width .4s ease; }
.stor-meter__label { margin: .55rem 0 .1rem; color: var(--on-dark); font-size: .92rem; }

/* On-page gallery section manager (admin + a granted alumni president). Sits on
   the normal page surface, so page tokens — not the console navy tokens. */
.galbum-mgr { margin: -.7rem 0 1.4rem; }
.galbum-mgr__toggle { background: none; border: 1.5px solid var(--hairline); color: var(--muted);
  border-radius: 999px; padding: .35rem .85rem; font-size: .82rem; font-weight: 600; cursor: pointer;
  transition: border-color .15s, color .15s; }
.galbum-mgr__toggle:hover, .galbum-mgr--open .galbum-mgr__toggle { border-color: var(--gold-bright); color: var(--heading); }
.galbum-mgr__list { margin-top: .7rem; padding: .5rem 1rem; border: 1.5px solid var(--hairline); border-radius: 12px; background: var(--surface); }
.galbum-mgr__row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: .5rem 0; border-bottom: 1px solid var(--hairline); }
.galbum-mgr__row:last-of-type { border-bottom: 0; }
.galbum-mgr__row b { font-weight: 600; color: var(--heading); }
.galbum-mgr__acts a { color: var(--gold-deep); font-size: .85rem; text-decoration: none; }
.galbum-mgr__acts a:hover { text-decoration: underline; }
.galbum-mgr__acts--fixed { color: var(--muted); font-size: .82rem; font-style: italic; }
.galbum-mgr__add { margin: .7rem 0 .3rem; }

/* Sections as photo plates — the gallery's front door. The name sits on a solid
   band BENEATH the cover, never over it: a scrim on a photograph is banned in
   this workspace, and a 30-year archive of dim indoor shots is exactly where an
   overlay label goes unreadable. The gold hairline between cover and plate is
   the only ornament. */
.gsecs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.1rem; margin: 0 0 1.6rem; }
.gsec { display: block; padding: 0; text-align: left; cursor: pointer; overflow: hidden;
  background: var(--surface); border: 1.5px solid var(--hairline); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); transition: transform .2s, border-color .2s, box-shadow .2s; }
.gsec:hover, .gsec:focus-visible { border-color: var(--gold-bright); transform: translateY(-2px); box-shadow: var(--shadow-md, var(--shadow-sm)); }
.gsec__cover { aspect-ratio: 4 / 3; background: var(--navy); display: grid; place-items: center; overflow: hidden; }
.gsec__cover img { width: 100%; height: 100%; object-fit: cover; transition: transform .35s; }
.gsec:hover .gsec__cover img { transform: scale(1.04); }
/* The empty-section watermark. Selector needs TWO classes: `.gsec__cover img`
   above is (0,1,1) and was beating a bare `.gsec__crest` (0,1,0), so the crest
   inherited width:100% + object-fit:cover and rendered 169x254 inside a 127px
   cover — the bottom half of it simply cut off.
   Sized by WIDTH only, never a percentage height: the cover's height comes from
   aspect-ratio, and a percentage height against that is not reliably resolvable.
   The crest is a fixed 500x750 (2:3), so width:34% always lands at 68% of the
   cover's height — the whole crest, with room around it. */
.gsec__cover .gsec__crest {
  width: 34%; height: auto; max-height: 74%;
  object-fit: contain; opacity: .18;
}
/* display:block is load-bearing, not tidiness. As an inline <span> this element's
   border-top drew ACROSS the text instead of above the block — a line straight
   through "2 photos" on every card, plus stray gold dashes where the inline box
   fragmented. */
.gsec__plate { display: block; padding: .72rem .9rem .8rem; border-top: 1px solid var(--gold-bright);
  /* two lines of the name + the count: every card in a row bottoms out together
     whether its name wraps ("Pledge Classes" at 390px) or not ("E-board"). */
  min-height: calc(2 * 1.02rem * 1.25 + .78rem + .78rem + 1.52rem); }
.gsec__name { display: block; font-family: var(--display); font-size: 1.02rem; color: var(--heading);
  line-height: 1.25; letter-spacing: .005em; }
/* A label, not prose — small caps and tracking stop it competing with the Georgia name. */
.gsec__n { display: block; margin-top: .34rem; color: var(--muted); font-size: .72rem;
  font-weight: 600; letter-spacing: .07em; text-transform: uppercase; }
.gsec--all .gsec__cover { background: var(--navy); }

/* The section you're standing in — replaces the row of chips that used to say it. */
.gsechead { display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap;
  margin: 1rem 0 1.1rem; padding-bottom: .55rem; border-bottom: 1px solid var(--hairline); }
.gsechead h2 { margin: 0; font-family: var(--display); font-size: 1.35rem; color: var(--heading); line-height: 1.2; }
.gsechead span { color: var(--muted); font-size: .74rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; }

.ggrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: .8rem; }
.ggrid__cell { position: relative; padding: 0; border: 0; background: var(--navy); border-radius: 12px; overflow: hidden; cursor: pointer; aspect-ratio: 1; box-shadow: var(--shadow-sm); }
.ggrid__cell img { width: 100%; height: 100%; object-fit: cover; transition: transform .3s; }
.ggrid__cell:hover img { transform: scale(1.05); }
.ggrid__ph { display: grid; place-items: center; height: 100%; color: var(--gold-bright); }
.ggrid__hover { position: absolute; inset: auto 0 0 0; padding: .4rem .6rem; background: linear-gradient(transparent, rgba(var(--chrome),.75)); color: #fff; font-size: .85rem; text-align: left; opacity: 0; transition: opacity .2s; }
.ggrid__cell:hover .ggrid__hover { opacity: 1; }

.gmodal { position: fixed; inset: 0; z-index: 210; background: rgba(var(--chrome),.9); display: none; align-items: center; justify-content: center; padding: 3vw; }
.gmodal.open { display: flex; }
/* grid-template-rows: minmax(0, 1fr) is load-bearing. An `auto` row sizes to its
   content, so the side panel grew to its natural 760px inside a card capped at
   493px and the composer was clipped clean off the bottom. minmax(0, …) lets the
   row shrink below content, which finally gives .gmodal__side a definite height —
   without that, .gcomments cannot flex-shrink and therefore never scrolls. */
.gmodal__card { background: var(--surface); border-radius: 16px; overflow: hidden; display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(280px, 1fr); grid-template-rows: minmax(0, 1fr); width: min(1020px, 94vw); max-height: 88vh; position: relative; }
.gmodal__close { position: absolute; top: 10px; right: 12px; z-index: 2; border: 0; background: rgba(var(--chrome),.5); color: #fff; width: 34px; height: 34px; border-radius: 50%; cursor: pointer; }
.gmodal__img { background: var(--navy-deep); display: grid; place-items: center; }
.gmodal__img img { width: 100%; height: 100%; max-height: 88vh; object-fit: contain; }
/* overflow: hidden, not auto — the panel itself must NOT scroll. Only .gcomments
   inside it does. That keeps the composer pinned to the bottom instead of letting
   it scroll out of reach the moment a photo has a few comments. */
.gmodal__side { display: flex; flex-direction: column; padding: 1.1rem 1.2rem; overflow: hidden; }
.gmodal__author { padding-bottom: .7rem; border-bottom: 1px solid var(--hairline); }
.gmodal__caption { color: var(--text); font-size: .95rem; margin: .8rem 0; }
.gmodal__actions { display: flex; align-items: center; gap: .9rem; padding: .5rem 0 .8rem; border-bottom: 1px solid var(--hairline); }

/* ---- viewer chrome: overlay bars (mobile), fullscreen, immersive ---- */
/* The photo pane is the positioning context for everything that floats on it. */
.gmodal__img { position: relative; }
/* Bars are chrome ON a photograph, so the text carries its own shadow rather
   than sitting on a gradient scrim over the image. */
.gbar { position: absolute; left: 0; right: 0; z-index: 2; display: none; align-items: center; gap: .7rem;
  padding: .55rem .7rem; color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,.85); }
/* The top bar stacks: author on the first line, section pill under it. */
.gbar--top { top: 0; flex-direction: column; align-items: flex-start; gap: .4rem; }
.gbar--bot { bottom: 0; }
.gbar .glike { color: #fff; text-shadow: inherit; }

/* ---- the section pill ----
   A chapter badge rather than a grey caption: gold letterforms, gold hairline,
   a smoked bed so it holds on a bright photo, and the crest diamond as its mark.
   Its own line under the author so a long committee name and a long brother name
   never fight for the same row. */
.gpill { display: inline-flex; align-items: center; gap: .38rem; max-width: 78%;
  padding: .22rem .62rem .24rem; border-radius: 999px;
  border: 1px solid rgba(var(--gold-rgb),.55); background: rgba(7,22,52,.55);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  color: var(--gold-bright); font-family: var(--sans); font-size: .66rem; font-weight: 700;
  letter-spacing: .13em; text-transform: uppercase; text-shadow: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gpill::before { content: '✦'; flex: none; font-size: .72rem; letter-spacing: 0; opacity: .9; }
.gpill[hidden] { display: none; }          /* a class rule beats the attribute otherwise */
/* Desktop copy: it sits on the panel, not on a photo, so it drops the smoked bed
   and picks up the page's own tint. */
/* align-self: it is a flex ITEM in the side panel's column, so the default
   `stretch` blew it out to the full panel width and it stopped reading as a pill. */
.gpill--side { align-self: flex-start; margin: .55rem 0 0; background: var(--tint);
  border-color: var(--gold); color: var(--gold-deep);
  backdrop-filter: none; -webkit-backdrop-filter: none; max-width: 100%; }
:root[data-theme="dark"] .gpill--side { color: var(--gold-bright); }
.gbar .glike.on { color: #ff8a7a; }
.gbar__spacer { margin-left: auto; }
/* The author chip is painted into the bar on mobile and into the side panel on
   desktop; only one is ever displayed. */
.gbar .author-chip b { color: #fff; text-shadow: inherit; }
/* Grip, comment count and the peek preview all belong to the mobile sheet; the
   desktop side panel shows the comments themselves, so they stay off until the
   sheet exists. The preview especially: unstyled on desktop it is a bare block
   that grew to 406px and shoved the real list off the panel. */
.gsheet__grip, .gsheet__count, .gpeek { display: none; }
/* One pill shows at a time: the bars are mobile-only, the side panel is desktop. */
.gbar .gpill { display: none; }

.gfull { position: absolute; right: 10px; bottom: 10px; z-index: 3; width: 38px; height: 38px;
  display: grid; place-items: center; border: 0; border-radius: 10px; cursor: pointer;
  background: rgba(var(--chrome), .55); color: #fff; font-size: 1rem; line-height: 1;
  backdrop-filter: blur(4px); transition: background .15s; }
.gfull:hover { background: rgba(var(--chrome), .8); }
.gfull:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; }

/* Immersive — the fallback for iOS Safari, which refuses requestFullscreen() on
   anything that isn't a <video>. The sheet drops away and the photo takes the
   whole card; the bars stay so there is always a visible way back out. */
.gmodal--immersive .gmodal__side { transform: translateY(100%) !important; }
.gmodal--immersive .gmodal__card { grid-template-columns: 1fr; background: var(--navy-deep); }
.gmodal--immersive .gmodal__img img { max-height: none; height: 100%; }
/* Native fullscreen paints the pane on a black backdrop, not the cream surface. */
.gmodal__img:fullscreen { background: var(--navy-deep); }
.gmodal__img:fullscreen img { max-height: 100vh; }
.glike { border: 0; background: none; cursor: pointer; font-size: 1.05rem; color: var(--heading); font-weight: 600; }
.glike.on { color: #c0392b; }
.gdate { color: var(--muted); font-size: .82rem; }
.gdelete { margin-left: auto; border: 0; background: none; color: var(--danger); cursor: pointer; font-size: .82rem; text-decoration: underline; }
/* Edit + Delete sit together at the right end of the action row: the auto margin
   moves to whichever comes first, so Delete drops its own when Edit is showing.
   Edit stays neutral — only the destructive action reads red. */
.gedit { margin-left: auto; border: 0; background: none; color: var(--muted); cursor: pointer; font-size: .82rem; text-decoration: underline; }
.gedit:hover { color: var(--heading); }
.gedit + .gdelete { margin-left: 0; }

/* ---- Who is in this photo (upgrade60) --------------------------------------
   Names, not face boxes. The strip sits under the caption in the side panel and
   inside the comment sheet on mobile, so it is read in the same place either way. */
.gtags { margin: .55rem 0 0; }
.gtags__row { display: flex; flex-wrap: wrap; align-items: center; gap: .38rem; }
.gtags__lbl { color: var(--muted); font-size: .74rem; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; margin-right: .2rem; }
.gtag { display: inline-flex; align-items: center; gap: .1rem; border-radius: 999px;
  background: var(--tint); border: 1px solid var(--hairline); padding: 0 .2rem 0 0; }
.gtag__name { border: 0; background: none; cursor: pointer; font: inherit; font-size: .82rem;
  font-weight: 600; color: var(--heading); padding: .28rem .2rem .28rem .7rem; border-radius: 999px; }
.gtag__name:hover { color: var(--gold-deep); text-decoration: underline; }
.gtag__x { border: 0; background: none; cursor: pointer; color: var(--muted);
  font-size: .72rem; line-height: 1; padding: .3rem .45rem; border-radius: 999px; }
.gtag__x:hover { color: var(--danger); }
.gtag--add { border-style: dashed; color: var(--muted); cursor: pointer; font: inherit;
  font-size: .8rem; font-weight: 600; padding: .28rem .8rem; background: none; }
.gtag--add:hover { color: var(--gold-deep); border-color: var(--gold-bright); }
.gtagpick { margin-top: .5rem; }
.gtagpick__in { width: 100%; padding: .5rem .7rem; border-radius: 10px; font: inherit;
  font-size: .88rem; border: 1.5px solid var(--hairline); background: var(--surface); color: var(--text); }
.gtagpick__list { max-height: 190px; overflow-y: auto; margin-top: .35rem; }
.gtagpick__hit { display: flex; justify-content: space-between; align-items: baseline; gap: .6rem;
  width: 100%; text-align: left; border: 0; border-bottom: 1px solid var(--hairline);
  background: none; cursor: pointer; font: inherit; font-size: .88rem; color: var(--text); padding: .45rem .3rem; }
.gtagpick__hit:hover { background: var(--tint); }
.gtagpick__hit i { font-style: normal; color: var(--muted); font-size: .72rem; }
.gtagpick__none { color: var(--muted); font-size: .82rem; margin: .5rem .3rem; }

/* ---- Decade filter (upgrade60) ---------------------------------------------
   Only drawn when a section actually spans more than one decade — see
   decadeChipsHtml(). A filter with one option is furniture. */
.gdecs { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0 0 1rem; }
.gdec { border: 1.5px solid var(--hairline); background: var(--surface); color: var(--text);
  border-radius: 999px; padding: .35rem .85rem; font: inherit; font-size: .82rem;
  font-weight: 600; cursor: pointer; transition: border-color .15s, background .15s; }
.gdec:hover { border-color: var(--gold-bright); }
.gdec.on { background: var(--navy); color: var(--on-navy); border-color: var(--navy); }
.gdec i { font-style: normal; font-weight: 700; opacity: .6; font-size: .74rem; margin-left: .2rem; }

/* Inline post editor (caption + section). Replaces the caption line in place, so
   the photo never moves while you're typing under it. */
.gedit-form { display: flex; flex-direction: column; gap: .55rem; margin: .8rem 0; }
.gedit-form textarea { width: 100%; padding: .6rem .7rem; border-radius: 10px; border: 1.5px solid var(--hairline);
  font: inherit; font-size: .92rem; color: var(--text); background: var(--surface); resize: vertical; }
.gedit-form__row { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.gedit-form__row .btn { padding: .45rem .95rem; font-size: .82rem; }
.gedit-form .form-status { margin: 0; }
/* ONE scroller, not two. This was `flex: 1` with the default `min-height: auto`
   forced up to 120px, nested inside a side panel that ALSO scrolled — so a drag
   moved whichever of the two the browser felt like, and the composer scrolled off
   the bottom exactly when you wanted it. `min-height: 0` is the load-bearing
   declaration: without it a flex child refuses to shrink below its content, so it
   never scrolls and pushes the panel instead. The panel is now `overflow: hidden`
   (see .gmodal__side), which pins the composer to the bottom for free.
   overscroll-behavior stops a flick that reaches the end of the list from handing
   the scroll to the gallery grid behind the photo. */
.gcomments { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: .2rem 0 .6rem; }

/* ---------- the chapter ledger ----------
   Shared by the gallery viewer, the Board's thread replies and the suggestion box.
   Name in the display face, time right-aligned in small caps, body in the reading
   face, a hairline between entries. A record book, not a chat app. */
.gcomment-list { list-style: none; margin: 0; padding: 0; }
.gcomment { display: flex; gap: .7rem; padding: .75rem 0; border-bottom: 1px solid var(--hairline); }
.gcomment:last-child { border-bottom: 0; }
.gcomment__av { flex: none; width: 32px; height: 32px; border-radius: 50%; overflow: hidden;
  display: grid; place-items: center; font-style: normal; font-size: .78rem; font-weight: 700;
  background: var(--navy); color: var(--gold-bright); }
.gcomment__av img { width: 100%; height: 100%; object-fit: cover; }
.gcomment__main { flex: 1 1 auto; min-width: 0; }
.gcomment__head { display: flex; align-items: baseline; gap: .5rem; }
.gcomment__who { font-family: var(--display); font-size: .98rem; font-weight: 600;
  color: var(--heading); line-height: 1.25; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* NOT uppercased, deliberately. when() returns "2m"/"3h"/"4d"; small caps turned
   that into "2M", which reads as two MONTHS. A timestamp is data — the styling
   does not get to make it ambiguous. */
.gcomment__when { flex: none; margin-left: auto; color: var(--muted);
  font-size: .72rem; font-weight: 600; letter-spacing: .04em; font-variant-numeric: tabular-nums; }
/* overflow-wrap: a pasted URL with no spaces used to widen the whole panel. */
.gcomment__text { margin: .18rem 0 0; font-size: .93rem; line-height: 1.55;
  color: var(--text); overflow-wrap: anywhere; }
/* Delete stops being the word "delete" in red beside every timestamp — a fat-finger
   target an inch from the thing you actually want. It is a quiet mark that earns
   attention on hover or keyboard focus. */
.gcomment__x { flex: none; border: 0; background: none; cursor: pointer;
  padding: 0 .1rem; line-height: 1; font-size: .8rem; color: var(--muted);
  opacity: .35; transition: opacity .15s, color .15s; }
.gcomment:hover .gcomment__x, .gcomment__x:focus-visible { opacity: 1; color: var(--danger); }
/* A touch screen has no hover to reveal it, so there it simply stays visible. */
@media (hover: none) { .gcomment__x { opacity: .7; } }

.gcomments__note, .gcomments__empty, .gcomments__err {
  color: var(--muted); font-size: .88rem; margin: .8rem 0; }
.gcomments__err { color: var(--danger); }
.gcomments__retry { border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; font-weight: 700; color: var(--gold-deep); text-decoration: underline; }

.gcompose { display: flex; gap: .6rem; padding-top: .8rem; border-top: 1px solid var(--hairline); }
/* 16px is NOT a style choice. iOS Safari force-zooms the page on focus for any
   input below 16px and never zooms back out — that is the "I have to zoom out to
   see everything" report. This one rule covers the gallery, board replies and the
   suggestion box, which all share this form. */
.gcompose input { flex: 1; min-width: 0; padding: .6rem .85rem; border-radius: 10px;
  border: 1.5px solid var(--hairline); font-size: 16px; }
.gcompose .btn { flex: none; padding: .6rem 1.1rem; font-size: .88rem; }

/* ---------- Events ---------- */
.ev-list { display: grid; gap: 1.1rem; margin-top: 2.4rem; max-width: 860px; margin-inline: auto; }
.ev-card { display: flex; gap: 1.2rem; background: var(--surface); border-radius: var(--radius); padding: 1.2rem 1.4rem; box-shadow: var(--shadow-sm); align-items: flex-start; }
.ev-card--members { border: 1.5px solid var(--gold); }
.ev-card__date { flex: none; width: 74px; text-align: center; background: var(--navy); color: var(--on-navy); border-radius: 12px; padding: .6rem .3rem; }
.ev-card__date b { display: block; font-size: 1.6rem; font-family: var(--display); color: var(--gold-bright); line-height: 1.1; }
.ev-card__date span { font-size: .72rem; letter-spacing: .18em; }
.ev-card__date small { display: block; font-size: .68rem; opacity: .7; }
.ev-card__body h3 { color: var(--heading); margin: .15rem 0 .2rem; font-size: 1.25rem; }
.ev-card__meta { color: var(--gold-deep); font-size: .88rem; font-weight: 600; margin: 0 0 .35rem; }
.ev-card__body p { color: var(--muted); font-size: .93rem; margin: 0; }
.admin-row--past { opacity: .55; }

/* ---------- Giving campaigns ---------- */
/* One route to giving, pointing at the page that actually does it. Replaced the
   three-tile .give-grid, whose buttons were fed by config links nobody ever set —
   so the whole block hid itself for months. Those rules are gone with it. */
.give-cta { background: var(--surface); border: 1.5px solid var(--hairline); border-left: 4px solid var(--gold);
  border-radius: var(--radius); padding: 1.5rem 1.6rem; margin-top: 2.6rem; box-shadow: var(--shadow-sm);
  max-width: 640px; }
.give-cta p { color: var(--muted); font-size: .95rem; margin: 0 0 1.1rem; }
.give-cta small { display: block; margin-top: .7rem; color: var(--muted); font-size: .8rem; }

/* ---------- Discussion board ---------- */
.thread-list { display: grid; gap: .7rem; }
.thread-row { display: flex; align-items: center; gap: 1rem; text-align: left; background: var(--surface); border: 0; border-radius: 12px; padding: 1rem 1.2rem; cursor: pointer; box-shadow: var(--shadow-sm); transition: transform .15s; }
.thread-row:hover { transform: translateY(-2px); }
.thread-row__main { flex: 1; min-width: 0; }
.thread-row__main b { display: block; color: var(--heading); font-family: var(--display); font-size: 1.08rem; margin-bottom: .25rem; }
.thread-row__main span { color: var(--muted); font-size: .82rem; display: inline-flex; align-items: center; gap: .35rem; }
.thread-row__count { flex: none; color: var(--gold-deep); font-weight: 700; font-size: .9rem; }
.thr-tag { display: inline-block; font-size: .68rem; letter-spacing: .08em; text-transform: uppercase; border-radius: 6px; padding: .15rem .5rem; margin-right: .5rem; vertical-align: 2px; }
.thr-tag--offering { background: #e4f2e4; color: #2c6e2c; }
.thr-tag--seeking { background: #eee7fb; color: #5b3ea8; }
.thread-view { background: var(--surface); border-radius: var(--radius); padding: 1.6rem 1.8rem; box-shadow: var(--shadow-sm); max-width: 820px; }
.thread-view h2 { color: var(--heading); font-family: var(--display); margin: 0 0 .5rem; }
.thread-view__meta { color: var(--muted); font-size: .86rem; display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.thread-view__meta a { color: var(--danger); text-decoration: underline; }
.thread-view__body { color: var(--text); margin: 1.1rem 0 1.4rem; line-height: 1.7; }

/* ---------- Notification bell ---------- */
.bell { position: relative; margin-right: .35rem; }
.bell__btn { position: relative; border: 0; background: rgba(255,255,255,.08); border-radius: 50%; width: 40px; height: 40px; cursor: pointer; font-size: 1.05rem; display: grid; place-items: center; }
.bell__btn:hover { background: rgba(255,255,255,.16); }
.bell__badge { position: absolute; top: -3px; right: -3px; background: #c0392b; color: #fff; font-size: .66rem; font-weight: 700; border-radius: 999px; min-width: 17px; height: 17px; display: grid; place-items: center; padding: 0 4px; }
.bell__menu { position: absolute; right: 0; top: calc(100% + 10px); width: min(340px, 88vw); background: var(--surface); border-radius: var(--radius); box-shadow: 0 18px 50px rgba(var(--chrome),.35); display: none; overflow: hidden; z-index: 120; }
.bell__menu.open { display: block; }
.bell__head { padding: .8rem 1rem; font-family: var(--display); color: var(--heading); border-bottom: 1px solid var(--hairline); font-weight: 700; }
.bell__list { max-height: 340px; overflow-y: auto; }
.bell__row { display: flex; gap: .6rem; align-items: flex-start; padding: .7rem 1rem; border-bottom: 1px solid var(--hairline); color: var(--text); font-size: .86rem; }
.bell__row:hover { background: var(--bg); }
.bell__row.unread { background: var(--tint); }
.bell__row i { font-style: normal; flex: none; }
.bell__row span { flex: 1; line-height: 1.4; }
.bell__row em { font-style: normal; color: var(--muted); font-size: .74rem; flex: none; }
.bell__empty { padding: 1.2rem 1rem; color: var(--muted); font-size: .88rem; text-align: center; }
.bell__all { display: block; padding: .65rem 1rem; text-align: center; font-size: .8rem; font-weight: 600; color: var(--gold-deep); border-top: 1px solid var(--hairline); }
.bell__all:hover { background: var(--bg); }

/* ---------- Notifications page (notifications.html) ----------
   Same row anatomy as the bell dropdown, sized for a full page. Everything is
   drawn from theme tokens so it flips with dark mode like the rest of the site. */
.ntf { max-width: 680px; margin: 0 auto; }
.ntf__bar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }
.ntf__count { font-family: var(--display); color: var(--heading); font-weight: 700; }
.ntf__bar-actions { display: flex; gap: .5rem; flex-wrap: wrap; }
.ntf__btn { padding: .42rem .85rem; font-size: .78rem; }
.ntf__day { font-size: .74rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin: 1.4rem 0 .5rem; }
.ntf__day:first-of-type { margin-top: 0; }
.ntf__row { display: flex; gap: .75rem; align-items: flex-start; padding: .85rem 1rem; background: var(--surface); border-radius: 12px; margin-bottom: .5rem; box-shadow: var(--shadow-sm); }
.ntf__row.unread { background: var(--tint); }
/* The unread mark has to survive on its own — a tinted background alone is not
   a distinction for a colour-blind brother, and it disappears entirely in dark mode. */
.ntf__row.unread .ntf__ic::after { content: ''; position: absolute; top: -2px; right: -2px; width: 8px; height: 8px; border-radius: 50%; background: #c0392b; }
.ntf__ic { position: relative; font-style: normal; flex: none; font-size: 1.05rem; line-height: 1.4; }
.ntf__body { flex: 1; min-width: 0; }
.ntf__txt { display: block; line-height: 1.45; color: var(--text); font-size: .9rem; word-wrap: break-word; }
a.ntf__txt:hover { color: var(--gold-deep); }
.ntf__time { display: block; font-style: normal; color: var(--muted); font-size: .74rem; margin-top: .3rem; }
.ntf__reply { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-top: .6rem; }
.ntf__addr { font-size: .78rem; color: var(--muted); word-break: break-all; }
/* 36px square, not a bare glyph — this is the one destructive control on the
   page and it sits next to a link, so it needs a thumb-sized target of its own. */
.ntf__x { flex: none; border: 0; background: none; color: var(--muted); cursor: pointer; font-size: .82rem; line-height: 1; width: 36px; height: 36px; display: grid; place-items: center; border-radius: 8px; }
.ntf__x:hover { color: #c0392b; background: var(--bg); }
.ntf__x:disabled { opacity: .4; cursor: default; }
.ntf__row--flash { outline: 2px solid var(--gold-bright); outline-offset: 2px; }
.ntf__empty { text-align: center; color: var(--muted); padding: 2.4rem 1rem; }
.ntf__empty b { display: block; font-family: var(--display); color: var(--heading); font-size: 1.15rem; margin: .4rem 0 .35rem; }
.ntf__empty span { display: block; font-size: .88rem; max-width: 34ch; margin: 0 auto; }
.ntf__note { text-align: center; color: var(--muted); font-size: .76rem; margin-top: 1.4rem; }

/* ---------- Admin stats ---------- */
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 1.6rem; }
.stat-card { background: var(--surface); border-radius: 12px; padding: 1.1rem 1rem; text-align: center; box-shadow: var(--shadow-sm); }
.stat-card b { display: block; font-size: 1.7rem; font-family: var(--display); color: var(--heading); }
.stat-card span { color: var(--muted); font-size: .8rem; }
.stat-h { color: var(--gold-bright); font-family: var(--display); margin: 1.6rem 0 .7rem; }
.thread-view .stat-h { color: var(--heading); }
.stat-list { background: var(--surface); border-radius: 12px; overflow: hidden; box-shadow: var(--shadow-sm); }
.stat-list__row { display: flex; gap: .8rem; align-items: baseline; padding: .65rem 1rem; border-bottom: 1px solid var(--hairline); font-size: .88rem; }
.stat-list__row b { color: var(--heading); flex: none; }
.stat-list__row span { color: var(--muted); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stat-list__row em { font-style: normal; color: var(--muted); font-size: .78rem; flex: none; }
/* History tab: flag deletions and permission changes with an edge rather than
   coloured text, so it reads identically in light and dark mode. */
.stat-list__row--warn { border-left: 3px solid #b4342b; padding-left: calc(1rem - 3px); }
/* The row is a fixed-height flex line; on a phone let it wrap instead of
   truncating the actor and the action away to nothing. */
@media (max-width: 620px) {
  .stat-list__row { flex-wrap: wrap; gap: .2rem .8rem; }
  .stat-list__row span { flex: 1 0 100%; white-space: normal; }
}

/* ---------- v4 responsive ---------- */
@media (max-width: 900px) {
  .ggrid { grid-template-columns: repeat(3, 1fr); }
  .gsecs { grid-template-columns: repeat(2, 1fr); }
  .stat-grid { grid-template-columns: repeat(2, 1fr); }

  /* ---- the photo owns the screen ----
     Was: photo capped at 44vh with the details stacked under it in a scrolling
     card. Because a11y focus landed in "Add a comment…", that card opened
     scrolled to its own bottom with the keyboard up — you arrived underneath the
     photo you tapped. Now the photo fills the viewport and the details ride a
     sheet that starts closed. */
  .gmodal { padding: 0; }
  .gmodal__card { grid-template-columns: 1fr; grid-template-rows: 1fr; width: 100%; max-height: none;
    height: 100%; border-radius: 0; overflow: hidden; background: var(--navy-deep); }
  .gmodal__img { height: 100%; }
  .gmodal__img img { max-height: none; height: 100%; }
  /* The close button keeps its own absolute corner (that is what desktop uses),
     so the top bar just leaves room for it rather than containing it. */
  .gbar { display: flex; }
  .gbar--top { padding-right: 3.2rem; }
  .gmodal__close { z-index: 5; }
  .gmodal__author { display: none; }               /* lives in the top bar here */
  .gmodal__actions .glike { display: none; }       /* ditto — but the date stays,
                                                      the bar only carries the section */
  /* The count line above already says "No comments yet"; the list's own
     placeholder would say it a second time, six pixels below. */
  .gcomments__empty { display: none; }
  /* The ♥/section bar and ⛶ ride just above the closed sheet, so nothing the
     brother can act on is buried behind it. */
  /* --gvis is the sheet's currently VISIBLE height, updated on every drag frame, so
     these ride the sheet edge the whole way up instead of being pinned to the
     resting peek. --gbar-op fades them out only as the sheet approaches full, where
     they would otherwise be buried. Both fall back to the static values, so if the
     script never runs the layout is still correct. */
  /* --gsafe is the gap between these controls and the sheet's top edge. The sheet
     casts `box-shadow: 0 -10px 30px` UPWARD, so sitting flush (which is what a bare
     var(--gvis) did) put the ♥ and the section label inside a 30px black shadow —
     on a dark theme they looked like they were sliding under the comments. */
  .gmodal { --gsafe: 12px; }
  .gbar--bot { bottom: calc(var(--gvis, var(--gpeek)) + var(--gsafe)); opacity: var(--gbar-op, 1); }
  .gfull { bottom: calc(var(--gvis, var(--gpeek)) + var(--gsafe) + 2px); right: 8px; opacity: var(--gbar-op, 1); }
  .gbar .gpill { display: inline-flex; }   /* mobile carries it in the top bar */
  .gpill--side { display: none; }
  .gmodal--immersive .gbar--bot { bottom: 0; }
  .gmodal--immersive .gfull { bottom: 2px; }
  /* With the sheet up, both of these sit behind it — present but unclickable,
     which is how a control earns a bug report. Take them out of the page while
     the sheet is open; closing it brings them back. */
  /* Unclickable is worse than absent: once --gbar-op has faded them out, take them
     out of the page too. The threshold class is set by the drag controller. */
  .gmodal--covered .gbar--bot, .gmodal--covered .gfull { pointer-events: none; }
  .gbar--bot, .gfull { transition: opacity .18s, bottom .34s cubic-bezier(.32,.72,0,1); }

  /* The sheet. --gpeek is what stays on screen when it's closed: the grip, the
     caption line and the comment count. */
  .gmodal { --gpeek: 5.4rem; }
  /* Everything past the count is hidden until the sheet is open. Measured, not
     guessed: with a caption the actions row starts at 87px and the peek is 86px,
     but a photo with NO caption pulls it up to ~61px — and "Delete post" must
     never sit in a resting preview strip. visibility (not display) keeps the
     layout identical so nothing jumps when the sheet opens. */
  .gmodal:not(.gmodal--sheet) .gmodal__actions,
  .gmodal:not(.gmodal--sheet) .gcomments,
  .gmodal:not(.gmodal--sheet) .gcompose { visibility: hidden; }
  /* ONE NUMBER drives the whole thing. --gy is the sheet's live offset in px, owned
     by the drag controller in gallery.js: 0 = fully open, (height - peek) = resting.
     It was a binary class toggle, which is why there was no way to drag it.
     .gmodal--sheet is still set (whenever the sheet is above its resting point) so
     every existing rule that depends on it keeps working unchanged. */
  .gmodal__side { position: absolute; left: 0; right: 0; bottom: 0; z-index: 4;
    /* 80%, not 86%: at full the remaining strip has to be tall enough for the photo
       to still be a photo. At 86% it was 118px, which forced the scale clamp and
       left the image poking 7px under the sheet — measured, not guessed. */
    /* The bottom padding carries the safe-area inset, so the composer clears the
       home indicator and Safari's toolbar instead of hiding behind them. Because
       the composer cancels --gy, this padding is exactly its gap from the screen
       bottom at every snap. */
    height: min(80%, 80dvh); background: var(--surface);
    padding: 0 1.1rem calc(1.1rem + env(safe-area-inset-bottom, 0px));
    border-radius: 18px 18px 0 0; box-shadow: 0 -10px 30px rgba(0,0,0,.35);
    transform: translateY(var(--gy, calc(100% - var(--gpeek)))); overflow: hidden;
    transition: transform .34s cubic-bezier(.32,.72,0,1);
    will-change: transform; }
  /* While a finger is down there must be NO transition — the sheet has to track the
     thumb 1:1. Anything else reads as lag. */
  .gmodal--dragging .gmodal__side,
  .gmodal--dragging .gmodal__img img,
  .gmodal--dragging .gbar--bot,
  .gmodal--dragging .gmodal__side .gcompose,
  .gmodal--dragging .gfull { transition: none !important; }

  /* THE COMPOSER DOCKS TO THE SCREEN, not to the sheet. The sheet is a fixed-height
     box translated DOWN by --gy, so its last child sat --gy pixels BELOW the
     viewport: the comment box only swung into view once you had dragged almost the
     whole way, which reads as "you can't comment from here". Cancelling --gy pins it
     to the bottom of the screen from the first pixel of the drag. A transform, so
     still no layout per frame. Opaque and above the list, because the list runs on
     behind it.
     --gcy is --gy CLAMPED: cancelling --gy outright pinned the composer's top to a
     constant, and early in the drag the visible band is only ~90px, so an opaque
     box sat on top of the grab handle your thumb was still holding. The ceiling is
     the point past which it would start covering the header, so it now waits just
     below the header until there is room, then docks. */
  .gmodal__side .gcompose { transform: translateY(calc(-1 * var(--gcy, 0px)));
    position: relative; z-index: 2; background: var(--surface);
    transition: transform .34s cubic-bezier(.32,.72,0,1); }

  /* The photo rides the same number: it lifts and shrinks so the comments end up
     BENEATH it rather than on top of it. transform only — animating height would
     relayout the image every frame. */
  .gmodal__img img { transform: translateY(var(--gph-y, 0px)) scale(var(--gph-s, 1));
    transition: transform .34s cubic-bezier(.32,.72,0,1); will-change: transform; }

  /* The grab handle. touch-action: none stops the browser claiming the gesture as a
     page scroll before the pointer handler ever sees it. */
  .gsheet__grip { position: relative; z-index: 1; display: block; width: 100%;
    padding: .85rem 0 .55rem; border: 0; background: none; cursor: grab;
    touch-action: none; -webkit-tap-highlight-color: transparent; }
  .gmodal--dragging .gsheet__grip { cursor: grabbing; }
  .gsheet__grip::before { content: ''; display: block; width: 42px; height: 5px; margin: 0 auto;
    border-radius: 999px; background: var(--hairline); transition: background .15s, width .15s; }
  .gsheet__grip:hover::before, .gmodal--dragging .gsheet__grip::before {
    background: var(--muted); width: 54px; }

  /* The whole sheet is draggable, not just the 42px bar — a thumb should not have to
     find a hairline. touch-action is set on each non-scrolling child rather than on
     .gmodal__side, because an ancestor set to `none` also kills panning inside its
     descendants, which would stop .gcomments scrolling. */
  .gsheet__head, .gmodal__caption, .gmodal__actions { touch-action: none; }
  /* Still a button — tapping is a valid way in, dragging is just the better one. */
  .gsheet__count { display: block; width: 100%; text-align: left; border: 0; background: none;
    padding: 0 0 .3rem; margin: 0; cursor: pointer; touch-action: none;
    font-family: var(--sans); font-size: .7rem; font-weight: 700; letter-spacing: .12em;
    text-transform: uppercase; color: var(--muted); }
  .gsheet__count:hover, .gsheet__count:focus-visible { color: var(--heading); }

  /* THE PEEK. It used to be a grip and the words "1 comment" in an empty cream
     block — nothing to read, and no hint it could be pulled. Now it carries the
     newest comment, so the resting state is worth looking at and obviously has
     more behind it. Height is FIXED (one line, ellipsised) because --gpeek feeds
     the snap maths; a peek that changed height with the content would move the
     resting position from photo to photo. */
  .gpeek { display: flex; align-items: center; gap: .55rem; height: 30px; overflow: hidden;
    touch-action: none; cursor: pointer; }
  .gpeek__av { flex: none; width: 24px; height: 24px; border-radius: 50%; overflow: hidden;
    display: grid; place-items: center; font-style: normal; font-size: .62rem; font-weight: 700;
    background: var(--navy); color: var(--gold-bright); }
  .gpeek__av img { width: 100%; height: 100%; object-fit: cover; }
  .gpeek__who { flex: none; font-family: var(--display); font-size: .9rem; font-weight: 600;
    color: var(--heading); }
  .gpeek__text { flex: 1 1 auto; min-width: 0; font-size: .88rem; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .gpeek--empty { color: var(--muted); font-size: .88rem; }
  /* Once the sheet is up the real list is showing; the preview would be a duplicate. */
  .gmodal--sheet .gpeek { display: none; }
  /* The caption only appears once the sheet is open, so the closed peek is the same
     height whether or not a photo has one. */
  .gmodal:not(.gmodal--sheet) .gmodal__caption { display: none; }
  .gmodal__caption { margin: .35rem 0; }
  @media (prefers-reduced-motion: reduce) { .gmodal__side { transition: none; } }
}
@media (max-width: 560px) {
  .ggrid { grid-template-columns: repeat(2, 1fr); }
  .gupload__row { flex-direction: column; }
  .ev-card { flex-direction: column; }
  .ev-card__date { width: 100%; display: flex; align-items: baseline; gap: .5rem; justify-content: center; }
  .fam-bar { justify-content: flex-start; overflow-x: auto; flex-wrap: nowrap; padding-bottom: .4rem; }
  .fam-chip { flex: none; }
  .page-filters { flex-direction: column; align-items: stretch; }
  .thread-row { flex-wrap: wrap; }
  .bell__menu { position: fixed; right: 3vw; left: 3vw; width: auto; top: 64px; }
}

/* ---------- Admin roster management (v4.1) ---------- */
.admin-addbar { display: flex; gap: .7rem; margin: 0 0 1.1rem; flex-wrap: wrap; }
.admin-addbar .btn { padding: .6rem 1.2rem; font-size: .9rem; }
/* Status chips: solid on-brand pills (not stark pale). Neutral = slate-navy,
   positive(●) = gold, warn = muted red. Solid so they read on ANY background —
   the navy console (navy in light / black in dark) AND the cream board card —
   without needing a separate dark rule. */
.schip { display: inline-block; vertical-align: 2px; font-size: .62rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; border-radius: 6px; padding: .16rem .5rem; margin-left: .45rem; background: #33425f; color: #eef1f7; }
.schip--active { background: var(--gold); color: var(--navy-deep); }
.guide-intro h3 { color: var(--gold-bright); font-family: var(--display); margin: 0 0 .3rem; }
.guide-intro p { color: var(--on-dark); margin-bottom: 1.2rem; }
.guide-sec { background: var(--surface); border-radius: 12px; margin-bottom: .7rem; box-shadow: var(--shadow-sm); overflow: hidden; }
.guide-sec summary { cursor: pointer; padding: .95rem 1.2rem; font-weight: 700; color: var(--heading); font-family: var(--display); font-size: 1.02rem; list-style: none; }
.guide-sec summary::-webkit-details-marker { display: none; }
.guide-sec summary::before { content: '▸ '; color: var(--gold-deep); }
.guide-sec[open] summary::before { content: '▾ '; }
.guide-sec > div { padding: 0 1.3rem 1.1rem; color: var(--text); font-size: .93rem; }
.guide-sec ol, .guide-sec ul { margin: .3rem 0 .6rem; padding-left: 1.3rem; }
.guide-sec li { margin-bottom: .35rem; }

/* ============================================================================
   v5 — admin cleanup, tree editor, profile popup, calendar, welcome
   ============================================================================ */

/* ---------- Admin: grouped tabs + hints ---------- */
.admin-tabgroup { display: flex; align-items: center; gap: .8rem; margin-bottom: .55rem; flex-wrap: wrap; }
.admin-tabgroup__label { font-size: .68rem; font-weight: 800; letter-spacing: .18em; text-transform: uppercase; color: var(--gold-bright); width: 72px; flex: none; }
.admin-tabgroup .admin-tabs { margin: 0; }
.admin-hint { background: rgba(255,255,255,.07); border-left: 3px solid var(--gold); color: var(--on-dark); font-size: .88rem; padding: .7rem 1rem; border-radius: 8px; margin: 0 0 1rem; }
.admin-hint b { color: var(--gold-bright); }

/* Officer Console "Overview" landing — a card per enabled tool (officer.js renderHome). */
.oc-home { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: .9rem; margin: .2rem 0 0; }
.oc-card { display: flex; flex-direction: column; align-items: flex-start; gap: .45rem; text-align: left;
  padding: 1.15rem 1.2rem; border-radius: var(--radius); cursor: pointer; font: inherit;
  background: linear-gradient(180deg, var(--console-card-hi), var(--console-card-lo)); color: var(--on-navy);
  border: 1px solid rgba(var(--gold-rgb),.24); border-left: 3px solid var(--gold);
  box-shadow: 0 8px 22px rgba(0,0,0,.24); transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease; }
.oc-card:hover { transform: translateY(-2px); border-left-color: var(--gold-bright); box-shadow: 0 12px 28px rgba(0,0,0,.32); }
/* A tile with something actually waiting on it. Gold edge only — colour alone would
   be the whole signal, and the count beside it already says what and how many. */
.oc-card--urgent { border-left-color: var(--gold-bright); background: rgba(var(--gold-rgb),.07); }
.oc-card--urgent .oc-card__meta { color: var(--gold-bright); font-weight: 600; }
.oc-card:focus-visible { outline: none; border-color: var(--gold-bright); box-shadow: 0 0 0 3px rgba(var(--gold-rgb),.28); }
.oc-card__ic { font-size: 1.7rem; line-height: 1; }
.oc-card__label { font-weight: 600; font-size: 1.03rem; font-family: var(--display); color: var(--on-navy); }
.oc-card__meta { font-size: .85rem; color: var(--gold-bright); font-variant-numeric: tabular-nums; }
.admin-hint a { color: var(--gold-bright); text-decoration: underline; }
.admin-hint--tip { background: rgba(var(--gold-rgb),.12); }

/* Officer Console cross-tab "needs your attention" strip (officer.js fillAttn).
   Lives OUTSIDE #q so tab renders don't wipe it; hidden entirely when nothing
   is waiting — quiet is the default state. The [hidden] rule is required:
   display:flex would otherwise beat the UA's [hidden]{display:none}. */
.attn-strip { display: flex; flex-wrap: wrap; align-items: center; gap: .55rem;
  margin: 0 0 1rem; padding: .6rem .9rem; border-radius: var(--radius);
  background: linear-gradient(180deg, var(--console-card-hi), var(--console-card-lo));
  border: 1px solid rgba(var(--gold-rgb),.24); border-left: 3px solid var(--gold-bright); }
.attn-strip[hidden] { display: none; }
.attn-strip__label { color: var(--on-navy); font-size: .85rem; font-weight: 600; letter-spacing: .02em; }
.attn-strip__item { font: inherit; font-size: .85rem; cursor: pointer; border-radius: 999px;
  padding: .28rem .8rem; background: var(--console-field); color: var(--on-navy);
  border: 1px solid rgba(var(--gold-rgb),.32); transition: border-color .15s ease, color .15s ease; }
.attn-strip__item:hover { border-color: var(--gold-bright); color: var(--gold-bright); }
.attn-strip__item:focus-visible { outline: none; border-color: var(--gold-bright); box-shadow: 0 0 0 3px rgba(var(--gold-rgb),.28); }
.attn-strip__item--urgent { color: var(--gold-bright); border-color: var(--gold-bright); font-weight: 600; }

/* ---------- Admin: tree editor ---------- */
.treeed-head { display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin-bottom: .9rem; flex-wrap: wrap; }
.treeed-list { background: var(--surface); border-radius: 12px; padding: .9rem 1rem; box-shadow: var(--shadow-sm); overflow-x: auto; }
.treeed-row { display: flex; align-items: center; gap: .6rem; padding: .45rem .4rem; border-bottom: 1px solid var(--hairline); min-width: 540px; }
.treeed-row:last-child { border-bottom: 0; }
.treeed-row__connector { color: var(--gold-deep); flex: none; width: 18px; text-align: center; }
.treeed-row__name { flex: 1; min-width: 0; }
.treeed-row__name b { color: var(--heading); font-size: .95rem; }
.treeed-row__name small { display: block; color: var(--muted); font-size: .76rem; }
.treeed-reg { color: #2c6e2c; font-style: normal; }
.treeed-row__act { display: flex; gap: .35rem; flex: none; }
.treeed-row__act button { border: 1px solid var(--hairline); background: var(--bg); color: var(--heading); font-size: .74rem; font-weight: 600; border-radius: 7px; padding: .3rem .6rem; cursor: pointer; transition: all .12s; }
.treeed-row__act button:hover { border-color: var(--gold-deep); background: var(--surface); }
.treeed-row__act button.danger { color: var(--danger); }
.treeed-row__act button.danger:hover { border-color: var(--danger); }
.treeed-help p { margin-bottom: .8rem; font-size: .93rem; color: var(--text); }

/* ---------- Public tree: search, family menu, pulse, path ---------- */
.tree-search { position: relative; max-width: 380px; margin: 1.4rem auto 0; }
.tree-search input { width: 100%; padding: .7rem 1rem; border-radius: 999px; border: 1.5px solid var(--hairline); font-size: .95rem; background: var(--surface); }
.tree-search__results { position: absolute; top: calc(100% + 6px); left: 0; right: 0; background: var(--surface); border-radius: 12px; box-shadow: var(--shadow); z-index: 30; overflow: hidden; display: none; }
.tree-search__results button { display: flex; justify-content: space-between; align-items: baseline; gap: .8rem; width: 100%; text-align: left; padding: .6rem 1rem; border: 0; background: none; cursor: pointer; }
.tree-search__results button:hover { background: var(--bg-2); }
.tree-search__results button b { color: var(--heading); font-size: .92rem; }
.tree-search__results button span { color: var(--muted); font-size: .78rem; }
.tree-search__none { display: block; padding: .7rem 1rem; color: var(--muted); font-size: .88rem; }
.tree-node--family { justify-content: flex-start; }
.tree-node--family .tree-toggle { margin-left: auto; }
.tree-node--pulse { animation: nodePulse 1.2s ease-in-out 2; }
@keyframes nodePulse { 0%,100% { box-shadow: var(--shadow-sm); } 50% { box-shadow: 0 0 0 6px rgba(var(--gold-bright-rgb),.55); } }
.tree-node--path { border-color: var(--gold) !important; box-shadow: 0 0 0 2px rgba(var(--gold-rgb),.35); }
.bm-jump { color: var(--gold-deep); text-decoration: underline; }

/* ---------- Portal: slim login + perks ---------- */
.portal-duo { display: grid; grid-template-columns: minmax(0, 420px) minmax(0, 1fr); gap: 2rem; align-items: start; justify-content: center; }
.card-form--slim { max-width: 460px; }
.perks { display: grid; gap: .9rem; align-content: start; }
.perks__title { color: var(--gold-bright); font-family: var(--display); margin: 0 0 .2rem; font-size: 1.25rem; }
.perk { display: flex; align-items: center; gap: 1rem; background: rgba(255,255,255,.06); border: 1px solid rgba(var(--gold-rgb),.25); border-radius: 12px; padding: .9rem 1.1rem; color: var(--on-navy); }
.perk__ic { font-size: 1.5rem; flex: none; }
.perk b { display: block; font-family: var(--display); font-size: 1.02rem; }
.perk small { color: var(--on-dark); font-size: .82rem; line-height: 1.4; display: block; }
.perk i { margin-left: auto; font-style: normal; opacity: .7; flex: none; }
.perk--live { border-color: var(--gold); transition: transform .15s, background .15s; }
.perk--live:hover { transform: translateX(4px); background: rgba(var(--gold-rgb),.14); }
.perk--live i { color: var(--gold-bright); }

/* ---------- Profile popup ---------- */
.pmodal { position: fixed; inset: 0; z-index: 220; background: rgba(var(--chrome),.9); display: none; align-items: flex-start; justify-content: center; padding: 4vh 3vw; overflow-y: auto; }
.pmodal.open { display: flex; }
.pmodal__card { position: relative; width: min(680px, 96vw); max-height: 92vh; overflow-y: auto; }
.pmodal__close { position: absolute; top: 12px; right: 14px; z-index: 2; border: 0; background: var(--bg-2); color: var(--heading); width: 34px; height: 34px; border-radius: 50%; cursor: pointer; font-size: 1rem; }
.pmodal__close:hover { background: var(--gold); }

/* ---------- Events calendar ---------- */
.ev-toggle { display: flex; justify-content: center; gap: .5rem; margin-top: 2rem; }
.ev-toggle button { border: 1.5px solid var(--navy-2); background: var(--surface); color: var(--heading); border-radius: 999px; padding: .5rem 1.3rem; font-size: .9rem; font-weight: 600; cursor: pointer; }
.ev-toggle button.on { background: var(--navy); color: var(--gold-bright); border-color: var(--heading); }
#eventsMonth { max-width: 860px; margin: 1.6rem auto 0; }
.cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: .8rem; }
.cal-head b { font-family: var(--display); color: var(--heading); font-size: 1.35rem; }
.cal-nav { border: 1.5px solid var(--hairline); background: var(--surface); color: var(--heading); width: 38px; height: 38px; border-radius: 50%; font-size: 1.2rem; cursor: pointer; }
.cal-nav:hover { border-color: var(--gold-deep); }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cal-dow { text-align: center; font-size: .7rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); padding: .3rem 0; }
/* One grid per week so a multi-day banner can span columns. The bands sit in an
   overlay above the day cells; pointer-events:none there + auto on each band is
   what keeps every day underneath still clickable. */
.cal-weeks { display: grid; gap: 4px; margin-top: 4px; }
.cal-week { position: relative; display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
/* z-index is load-bearing: .cal-cell is position:relative and comes later in the
   DOM, so without it the day cells paint over the banners and only slivers show
   through the 4px gutters. */
/* padding-top must clear the date number's whole line box (~21px here), not just
   touch it — at 22px the bar sat 0.4px off the digits and read as crowding them. */
.cal-week__bands { position: absolute; inset: 0; z-index: 2; display: grid; grid-template-columns: repeat(7, 1fr); grid-auto-rows: 17px; column-gap: 4px; row-gap: 3px; padding-top: 25px; pointer-events: none; }
.cal-band { pointer-events: auto; align-self: start; height: 15px; line-height: 15px; font-size: .62rem; font-weight: 600; letter-spacing: .01em; color: #fff; background: var(--navy-2); border: 0; padding: 0 .5rem; text-align: left; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-family: var(--sans); box-shadow: 0 1px 2px rgba(var(--chrome), .16); }
.cal-band[disabled] { cursor: default; }
/* Must track grid-auto-rows + row-gap above (17 + 3 = 20 per lane), plus the
   gap the taller padding-top opens under the date number. If this under-reserves,
   a chip slides beneath the banner. */
.cal-cell__bandpad { flex: none; height: calc(var(--lanes, 0) * 20px + 4px); }
/* Fully rounded ends, and ONLY where the event actually begins or ends — a
   segment that carries into the next week stays square, so the shape itself
   tells you it continues. A 4px radius on a 15px bar read as square, which is
   what made this look like a highlighter stroke. The margin keeps the cap off
   the cell border instead of running the full width edge to edge. */
.cal-band--start { border-radius: 999px 0 0 999px; margin-left: 3px; }
.cal-band--end { border-radius: 0 999px 999px 0; margin-right: 3px; }
.cal-band--start.cal-band--end { border-radius: 999px; }
.cal-cell { position: relative; min-height: 74px; background: var(--surface); border: 1px solid var(--hairline); border-radius: 8px; padding: .35rem .4rem; text-align: left; font-family: var(--sans); cursor: default; display: flex; flex-direction: column; gap: 2px; overflow: hidden; }
.cal-cell--pad { background: transparent; border: 0; }
.cal-cell--today { border-color: var(--gold); box-shadow: 0 0 0 1.5px var(--gold); }
.cal-cell--has { cursor: pointer; }
.cal-cell--has:hover { border-color: var(--gold-deep); }
.cal-cell__n { font-size: .78rem; font-weight: 700; color: var(--heading); }
.cal-chip { display: block; font-size: .64rem; font-weight: 600; color: #fff; background: var(--navy-2); border-radius: 4px; padding: .1rem .3rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-chip--rush, .cal-band--rush { background: #8a5a1f; }
.cal-chip--philanthropy, .cal-band--philanthropy { background: #2c6e2c; }
.cal-chip--reunion, .cal-band--reunion { background: #7a4a9e; }
.cal-chip--meeting, .cal-band--meeting { background: #12305F; }
/* #9A7628 is the OLD gold-deep, retired for failing AA; white on it is 4.20:1.
   Hardcoded rather than var(--gold-deep) because that token flips bright in dark. */
.cal-chip--social, .cal-band--social { background: #7d5f1e; }
.cal-more { font-size: .64rem; color: var(--muted); }
.cal-detail { margin-top: 1.1rem; }
.cal-detail h3 { color: var(--heading); font-family: var(--display); margin: 0 0 .6rem; }
.cal-detail__ev { background: var(--surface); border-radius: 10px; padding: .8rem 1rem; box-shadow: var(--shadow-sm); margin-bottom: .6rem; }
.cal-detail__ev b { display: block; color: var(--heading); font-size: 1.05rem; }
.cal-detail__ev small { color: var(--gold-deep); font-weight: 600; }
.cal-detail__ev p { color: var(--muted); font-size: .9rem; margin: .3rem 0 0; }

/* ---------- Welcome page ---------- */
.welcome-step { display: flex; gap: 1.2rem; background: var(--surface); border-radius: var(--radius); padding: 1.5rem 1.6rem; box-shadow: var(--shadow-sm); margin-bottom: 1.1rem; align-items: flex-start; }
.welcome-step__n { flex: none; width: 44px; height: 44px; border-radius: 50%; background: var(--navy); color: var(--gold-bright); display: grid; place-items: center; font-family: var(--display); font-weight: 700; font-size: 1.15rem; }
.welcome-step h3 { color: var(--heading); margin: 0 0 .4rem; font-size: 1.25rem; }
.welcome-step p { color: var(--muted); font-size: .95rem; margin-bottom: .8rem; }
.welcome-step p a { color: var(--gold-deep); text-decoration: underline; }
.welcome-step .btn { padding: .6rem 1.3rem; font-size: .88rem; }
.welcome-h { color: var(--heading); font-family: var(--display); font-size: 1.5rem; margin: 0 0 .3rem; }
.welcome-sub { color: var(--muted); font-size: .95rem; margin: 0 0 1.2rem; }

/* Feature cards — one per thing the membership unlocks, each the whole link so
   the tap target is the card, not just the heading. auto-fit keeps it 3-up on a
   desktop, 2-up on a tablet and 1-up on a phone with no breakpoints of its own. */
.welcome-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(232px, 1fr)); }
.welcome-card { display: block; background: var(--surface); border-radius: var(--radius); padding: 1.3rem 1.4rem;
  box-shadow: var(--shadow-sm); text-decoration: none; border: 1px solid transparent;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease; }
.welcome-card:hover, .welcome-card:focus-visible { transform: translateY(-3px); box-shadow: var(--shadow-md);
  border-color: rgba(var(--gold-rgb),.45); }
.welcome-card__ic { font-size: 1.5rem; line-height: 1; display: block; margin-bottom: .55rem; }
.welcome-card h3 { color: var(--heading); font-size: 1.08rem; margin: 0 0 .35rem; }
.welcome-card p { color: var(--muted); font-size: .89rem; margin: 0; }
/* On the paragraph, not the card: as a block-level ::after it sat on a line of its
   own looking stranded. Here it trails the last sentence the way a link should. */
.welcome-card p::after { content: ' →'; color: var(--gold-deep); font-weight: 700; white-space: nowrap; }

.welcome-note { background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-sm);
  padding: 1.4rem 1.6rem; margin-top: 1.6rem; }
.welcome-note h3 { color: var(--heading); font-size: 1.15rem; margin: 0 0 .7rem; }
.welcome-note ul { margin: 0; padding-left: 1.1rem; }
.welcome-note li { color: var(--muted); font-size: .92rem; margin-bottom: .5rem; }
.welcome-note li b { color: var(--text); }
.welcome-note a { color: var(--gold-deep); text-decoration: underline; }

/* ---------- v5 responsive ---------- */
@media (max-width: 860px) {
  .portal-duo { grid-template-columns: 1fr; }
  .card-form--slim { max-width: none; }
}
@media (max-width: 620px) {
  .cal-cell { min-height: 52px; }
  .cal-chip { display: none; }
  /* Banners STAY on mobile — a spanning bar is the one affordance that still
     reads in a narrow grid, and hiding it would defeat the point. */
  /* 18px put the banner 3.6px ON TOP of the date number (measured at 428px) —
     the number is ~21px of padding + line box. Clear it, then leave a hair of
     air so the bar reads as sitting under the date rather than crowding it. */
  .cal-week__bands { padding-top: 23px; grid-auto-rows: 13px; }
  .cal-band { height: 12px; line-height: 12px; font-size: .5rem; padding: 0 .35rem; letter-spacing: 0; }
  .cal-band--start { margin-left: 2px; }
  .cal-band--end { margin-right: 2px; }
  .cal-cell__bandpad { height: calc(var(--lanes, 0) * 16px + 2px); }
  /* --dot, not --has: only days with an event the banner ISN'T already showing.
     Chips are hidden at this width, so the dot stays the sole marker for
     single-day events. */
  .cal-cell--dot::after { content: ''; width: 7px; height: 7px; border-radius: 50%; background: var(--gold-deep); position: absolute; bottom: 5px; left: 50%; transform: translateX(-50%); }
  .admin-tabgroup__label { width: 100%; }
  .welcome-step { flex-direction: column; }
}

/* ============================================================================
   v6 — avatar photos, banner, RSVPs, spotlight, mentor finder, alumni map
   ============================================================================ */

/* ---------- Header avatar photo ---------- */
.nav__avatar { overflow: hidden; }
.nav__avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }

/* ---------- Announcement banner ---------- */
.site-banner { position: fixed; top: 72px; left: 0; right: 0; z-index: 95;
  background: linear-gradient(90deg, var(--gold-deep), var(--gold), var(--gold-deep));
  box-shadow: 0 6px 20px rgba(0,0,0,.25); }
.site-banner__inner { width: min(var(--wrap), 94vw); margin-inline: auto; display: flex; align-items: center; gap: 1rem; padding: .55rem 0; }
.site-banner a, .site-banner span { color: var(--navy-deep); font-weight: 700; font-size: .92rem; flex: 1; }
.site-banner a { text-decoration: underline; }
.site-banner__x { border: 0; background: rgba(var(--chrome),.15); color: var(--navy-deep); width: 26px; height: 26px; border-radius: 50%; cursor: pointer; flex: none; font-size: .8rem; }
.site-banner__x:hover { background: rgba(var(--chrome),.3); }

/* ---------- Event RSVPs ---------- */
.ev-rsvp { display: flex; align-items: center; gap: .7rem; margin-top: .8rem; flex-wrap: wrap; }
.ev-rsvp__btn { border: 1.5px solid var(--navy-2); background: var(--surface); color: var(--heading); border-radius: 999px; padding: .4rem 1rem; font-size: .84rem; font-weight: 700; cursor: pointer; transition: all .15s; }
.ev-rsvp__btn:hover { border-color: var(--gold-deep); }
.ev-rsvp__btn.on { background: var(--navy); color: var(--gold-bright); border-color: var(--heading); }
.ev-rsvp b { color: var(--heading); }
.ev-rsvp__who { color: var(--muted); font-size: .8rem; width: 100%; }

/* ---- the one-question nudge (upgrade64) ------------------------------------
   A slim strip under the header, in the page flow — not a floating toast. It
   pushes the page down by its own height and leaves when answered or dismissed,
   which is far less rude on a phone than something covering the content. */
.nudge { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap;
  max-width: 1100px; margin: 1rem auto 0; padding: .8rem 1.1rem;
  background: var(--tint); border: 1.5px solid var(--gold-bright); border-radius: var(--radius); }
.nudge__ic { font-size: 1.3rem; line-height: 1; flex: none; }
.nudge__body { flex: 1 1 240px; min-width: 0; }
.nudge__ask { display: block; color: var(--heading); font-size: .96rem; }
.nudge__why { display: block; color: var(--muted); font-size: .8rem; margin-top: .1rem; }
.nudge__acts { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.nudge__in { padding: .5rem .8rem; border-radius: 10px; font: inherit; font-size: .9rem;
  border: 1.5px solid var(--hairline); background: var(--surface); color: var(--text); min-width: 190px; }
.nudge__acts .btn { padding: .5rem 1.1rem; font-size: .85rem; }
.nudge__no { border: 0; background: none; cursor: pointer; font: inherit; font-size: .82rem;
  color: var(--muted); text-decoration: underline; }
.nudge__no:hover { color: var(--heading); }
.nudge__st { width: 100%; margin: 0; }
.nudge__st:empty { display: none; }

/* ---- guests + the note (upgrade61) ---------------------------------------- */
.ev-rsvp__bring { display: inline-flex; align-items: center; gap: .35rem; color: var(--muted); font-size: .8rem; }
.ev-rsvp__g { border: 1.5px solid var(--hairline); background: var(--surface); color: var(--text);
  border-radius: 999px; padding: .25rem .5rem; font: inherit; font-size: .8rem; font-weight: 600; cursor: pointer; }
.ev-rsvp__g:hover { border-color: var(--gold-bright); }
.ev-rsvp__notebtn, .ev-rsvp__door { border: 0; background: none; cursor: pointer; font: inherit;
  font-size: .8rem; color: var(--muted); text-decoration: underline; padding: 0; }
.ev-rsvp__notebtn:hover, .ev-rsvp__door:hover { color: var(--gold-deep); }
.ev-rsvp__door { margin-left: auto; }
.ev-rsvp__n { color: var(--muted); font-size: .82rem; }
.ev-rsvp__note { color: var(--muted); font-size: .8rem; width: 100%; font-style: italic; }
.ev-rsvp__edit { width: 100%; }
.ev-rsvp__edit[hidden] { display: none; }
.ev-rsvp__notein { width: 100%; padding: .45rem .7rem; border-radius: 10px; font: inherit; font-size: .85rem;
  border: 1.5px solid var(--hairline); background: var(--surface); color: var(--text); }

/* ---- the door list (upgrade61) --------------------------------------------
   A report you print and stand at the door with. The print rule hides the whole
   page except the sheet, so there is no second window to be blocked and no second
   copy of this list to keep in sync. */
.door__h { margin: 0; font-family: var(--display); font-size: 1.4rem; color: var(--heading); }
.door__when { margin: .2rem 0 1rem; color: var(--muted); font-size: .85rem; }
.door__t { width: 100%; border-collapse: collapse; font-size: .9rem; }
.door__t td { border-bottom: 1px solid var(--hairline); padding: .45rem .3rem; vertical-align: top; }
.door__nm { font-weight: 600; color: var(--heading); }
.door__cls { color: var(--muted); font-size: .8rem; white-space: nowrap; }
.door__g { font-weight: 700; color: var(--gold-deep); white-space: nowrap; text-align: right; }
.door__note { color: var(--muted); font-size: .82rem; font-style: italic; }
.door__tot { margin: 1rem 0 0; font-size: .9rem; color: var(--text); }
.door__acts { display: flex; gap: .6rem; margin-top: 1.2rem; flex-wrap: wrap; }

@media print {
  /* display:none on the siblings, NOT visibility:hidden. Two reasons, both found by
     printing this and looking at it rather than by reasoning about it:
       1. visibility leaves the hidden page laid out, so the modal card — which is
          overflow:auto and only as tall as the screen — CLIPPED the list of names.
          Everything past the first row silently failed to print.
       2. .ev-rsvp__btn carries `transition: all .15s`, and `all` includes visibility,
          so the going/not-going button was still fading when the print snapshot was
          taken and printed on top of the sheet. display is not transitionable.
     The modal is appended straight to <body>, so `body > *` reaches every sibling. */
  body > *:not(#doorModal) { display: none !important; }
  #doorModal { position: static !important; display: block !important; overflow: visible !important;
    background: none !important; padding: 0 !important; }
  #doorModal .pmodal__card { position: static !important; overflow: visible !important;
    max-height: none !important; height: auto !important; width: 100% !important; max-width: none !important;
    margin: 0 !important; padding: 0 !important; border: 0 !important; box-shadow: none !important;
    background: #fff !important; }
  /* Ink, not screen colours: the navy-on-cream palette prints as grey mush. */
  #doorSheet, #doorSheet .door__h, #doorSheet .door__nm, #doorSheet .door__g,
  #doorSheet .door__when, #doorSheet .door__cls, #doorSheet .door__note, #doorSheet .door__tot { color: #000 !important; }
  #doorSheet .door__t td { border-bottom: 1px solid #999 !important; }
  .door__acts, #doorModal .pmodal__close { display: none !important; }
}

/* ---------- Brother spotlight ---------- */
.spot-card { display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: 2rem; background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; max-width: 860px; margin-inline: auto; text-align: left; }
.spot-card__photo { width: 100%; height: 100%; min-height: 300px; object-fit: cover; }
.spot-card__body { padding: 2rem 2.2rem 2rem 0; }
.spot-card__body h3 { color: var(--heading); font-size: 1.7rem; margin: 0 0 .2rem; }
.spot-card__sub { color: var(--gold-deep); font-weight: 600; font-size: .9rem; margin: 0 0 .9rem; }
.spot-card__quote { font-family: var(--serif); font-style: italic; color: var(--heading); font-size: 1.1rem; margin: 0 0 .8rem; }
.spot-card__bio { color: var(--muted); font-size: .95rem; margin: 0 0 1.3rem; }
@media (max-width: 720px) {
  .spot-card { grid-template-columns: 1fr; }
  .spot-card__photo { min-height: 240px; max-height: 320px; }
  .spot-card__body { padding: 0 1.5rem 1.6rem; }
}

/* ---------- Mentor finder ---------- */

/* ---------- Alumni map ---------- */
.alumni-map { position: relative; z-index: 0; isolation: isolate; height: 420px; border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); background: var(--bg-2); } /* isolate keeps Leaflet's internal z-indexes (controls=1000) from escaping over the nav/modals */
/* The Leaflet popup is white in BOTH themes, so this link cannot use
   --gold-deep — that token goes bright in dark and read at 2.33:1 there. */
.alumni-map .leaflet-popup-content a { color: #7d5f1e; text-decoration: underline; display: inline-block; padding: .1rem 0; }
/* Raster OSM tiles are a bright rectangle in the middle of the black theme. */
:root[data-theme="dark"] .alumni-map .leaflet-tile { filter: brightness(.72) invert(1) hue-rotate(180deg) saturate(.75); }
/* fullscreen map: fills the viewport, above the nav but below brother cards (1400) */
.alumni-map--full { position: fixed !important; inset: 0; z-index: 1300; height: 100dvh !important; width: 100vw; border-radius: 0; box-shadow: none; }
/* fullscreen toggle button (a Leaflet control) */
.map-fs-btn {
  width: 40px; height: 40px; border-radius: 10px; cursor: pointer;
  border: 1px solid rgba(var(--gold-rgb),.5); background: rgba(var(--chrome),.9);
  color: var(--gold-bright); font-size: 1.15rem; line-height: 1;
  box-shadow: 0 6px 16px rgba(var(--chrome),.35); backdrop-filter: blur(6px);
  display: grid; place-items: center; transition: background .15s, transform .15s;
}
.map-fs-btn:hover { background: var(--gold); color: var(--navy-deep); transform: translateY(-1px); }
@media (max-width: 620px) { .alumni-map { height: 300px; } }

/* ============================================================================
   v7 — e-board manager, polls, committees, suggestions, class pages
   ============================================================================ */

/* ---------- Admin: e-board seats ---------- */
.seat-row { display: flex; align-items: center; gap: 1rem; padding: .6rem 0; border-bottom: 1px solid var(--hairline); flex-wrap: wrap; }
.seat-row:last-child { border-bottom: 0; }
.seat-row__title { flex: none; width: 120px; font-weight: 700; color: var(--gold-deep); font-size: .85rem; text-transform: uppercase; letter-spacing: .06em; }
.seat-row__who { flex: 1; min-width: 140px; }
.seat-row__who b { color: var(--heading); }
.seat-row__who small { display: block; color: var(--muted); font-size: .78rem; }
.seat-row__who--empty { color: var(--muted); font-style: italic; }
.seat-row__act { display: flex; gap: .4rem; flex: none; }
.seat-row__act .btn { padding: .4rem .9rem; font-size: .8rem; }

/* ---------- Polls ---------- */
.poll-card { background: var(--surface); border-radius: var(--radius); padding: 1.4rem 1.6rem; box-shadow: var(--shadow-sm); margin-bottom: 1.1rem; max-width: 680px; }
.poll-card h3 { color: var(--heading); font-family: var(--display); margin: 0 0 .9rem; font-size: 1.25rem; }
.poll-opt { position: relative; display: flex; align-items: center; justify-content: space-between; width: 100%; text-align: left; border: 1.5px solid var(--hairline); background: var(--bg); border-radius: 10px; padding: .65rem .9rem; margin-bottom: .5rem; cursor: pointer; overflow: hidden; transition: border-color .15s; }
.poll-opt:hover { border-color: var(--gold-deep); }
.poll-opt.on { border-color: var(--gold); }
.poll-opt.closed { cursor: default; }
.poll-opt__bar { position: absolute; inset: 0 auto 0 0; background: rgba(var(--gold-rgb),.18); transition: width .3s; }
.poll-opt__label { position: relative; font-weight: 600; color: var(--heading); font-size: .92rem; }
.poll-opt__n { position: relative; color: var(--muted); font-size: .8rem; flex: none; }
.poll-card__meta { color: var(--muted); font-size: .82rem; margin-top: .5rem; }
.poll-card__meta a { color: var(--danger); text-decoration: underline; }
/* "edit" is not destructive — only "delete" should read as danger red. */
.poll-card__meta a[data-editpoll] { color: var(--gold-deep); }
.poll-closed { color: var(--danger); }
/* Marks a poll you wrote, so "edit / delete" next to it is self-explanatory. */
.poll-mine { color: var(--gold-deep); font-weight: 700; }

/* ---------- Board: committee tabs + suggestion box ---------- */
.sug-box { background: var(--surface); border: 1.5px dashed var(--hairline); border-radius: var(--radius); padding: 1rem 1.2rem; margin-bottom: 1.4rem; }
.sug-box__head b { color: var(--heading); font-family: var(--display); }
.sug-box__head span { color: var(--muted); font-size: .85rem; margin-left: .5rem; }
.sug-box .gcompose { border-top: 0; padding-top: .7rem; }
.sug-mine { padding: .45rem 0 0; font-size: .86rem; color: var(--text); }
.sug-mine .schip { margin: 0 .4rem 0 0; }
.sug-card { background: var(--surface); border-radius: 12px; padding: 1rem 1.2rem; box-shadow: var(--shadow-sm); margin-bottom: .8rem; }
.sug-card__body { color: var(--text); margin: 0 0 .2rem; }
.sug-card small { color: var(--muted); font-size: .76rem; }
.sug-card__resp { background: var(--bg-2); border-left: 3px solid var(--gold); border-radius: 6px; padding: .5rem .8rem; margin: .6rem 0 0; color: var(--text); font-size: .88rem; }
.sug-card__act { margin-top: .7rem; }

/* ---- a contact tip, not an ordinary suggestion (upgrade65) ----------------- */
.sug-card--tip { border-left: 3px solid var(--gold); }
.sug-card__tip { margin: 0 0 .35rem; font-size: .82rem; color: var(--on-dark); }
.sug-card__tip b { color: var(--gold-bright); }
.sug-card__tip span { color: var(--muted); font-weight: 400; }
.sug-card__tipact { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin-top: .6rem; }
.sug-card__tipact .btn { padding: .45rem 1rem; font-size: .82rem; }
.sug-card__has { color: var(--muted); font-size: .8rem; }

/* ---- "know how to reach him?" on the brother card (upgrade65) -------------- */
.bm__tipbtn { margin-top: .8rem; }
.bm__tipbtn[hidden] { display: none; }
.tipform { margin-top: .8rem; }
.tipform[hidden] { display: none; }
.tipform__ask { margin: 0 0 .5rem; color: var(--muted); font-size: .84rem; }
.tipform__in { width: 100%; margin-bottom: .45rem; padding: .55rem .8rem; border-radius: 10px;
  border: 1.5px solid var(--hairline); background: var(--surface); color: var(--text); font: inherit; font-size: .9rem; }
textarea.tipform__in { resize: vertical; }
.tipform__acts { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
.tipform__no { border: 0; background: none; cursor: pointer; font: inherit; font-size: .82rem;
  color: var(--muted); text-decoration: underline; }
.tipform__done { margin: 0; color: var(--gold-deep); font-size: .9rem; font-weight: 600; }
.sug-card__act textarea { width: 100%; min-height: 60px; border: 1.5px solid var(--hairline); border-radius: 8px; padding: .6rem .8rem; font-family: var(--sans); font-size: .88rem; margin-bottom: .5rem; }
.sug-card__act .btn { padding: .45rem 1rem; font-size: .82rem; margin-right: .4rem; }

/* ---------- Class page + modal class link ---------- */
.bm-class { color: var(--gold-deep); text-decoration: underline; }

/* ============================================================================
   v8 — lockdown notes, board redesign, mobile fixes, cream + admin restyle
   ============================================================================ */

/* ---------- global: warm form fields ---------- */
input, select, textarea { background: var(--surface-2); }

/* ---------- lockdown ---------- */
.tree-lockline { text-align: center; color: var(--muted); font-size: .95rem; background: var(--surface); border: 1.5px dashed var(--gold); border-radius: 999px; padding: .55rem 1.2rem; display: inline-block; margin: .8rem auto 0; }
.center .tree-lockline { display: inline-block; }
.tree-lockline a { color: var(--gold-deep); text-decoration: underline; }

/* ---------- mobile fixes ---------- */
.fam-select { display: none; width: 100%; max-width: 420px; margin: 1rem auto 0; padding: .7rem 1rem; border-radius: 12px; border: 1.5px solid var(--navy-2); color: var(--heading); font-weight: 600; font-size: .95rem; }
@media (max-width: 700px) {
  .fam-bar { display: none !important; }
  .fam-select { display: block; }
}
@media (max-width: 820px) {
  .alumni-cta { text-align: center; }
  .alumni-cta .lede { margin-inline: auto; }
  .alumni-cta .hero__cta { justify-content: center !important; }
}

/* ---------- board redesign ---------- */

/* The Board's front door: one card per space, same idea as the gallery's
   sections page. The rail that used to sit here repeated all nine destinations
   on every screen; now you pick a space and a back pill is how you leave.
   (.board-shell / .board-rail were removed with it.) */
.board-main { min-width: 0; }
.board-main--spaces { max-width: 980px; margin: 0 auto; }

.bsecs__group { margin: 0 0 1.9rem; }
.bsecs__label { display: block; margin: 0 0 .7rem; color: var(--muted);
  font-size: .72rem; font-weight: 700; letter-spacing: .16em; }
.bsecs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.bsec { position: relative; display: block; padding: 1.4rem 1rem 1.2rem; cursor: pointer; text-align: center;
  background: var(--surface); border: 1.5px solid var(--hairline); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); transition: transform .2s, border-color .2s; }
.bsec:hover, .bsec:focus-visible { border-color: var(--gold-bright); transform: translateY(-2px); }
.bsec__ic { display: block; font-size: 1.75rem; line-height: 1; margin-bottom: .55rem; }
.bsec__name { display: block; font-family: var(--display); font-size: 1.05rem; color: var(--heading); line-height: 1.25; }
/* Same label treatment as the gallery's section counts, so the two front doors
   read as one system. */
.bsec__n { display: block; margin-top: .3rem; color: var(--muted); font-size: .72rem;
  font-weight: 600; letter-spacing: .07em; text-transform: uppercase; }
/* An empty room stays visible but honest — never hidden, so Opportunities keeps its door. */
.bsec--empty { opacity: .55; }
.bsec--new { border-color: var(--gold-bright); }
.bsec__dot { position: absolute; top: .7rem; right: .7rem; width: 9px; height: 9px;
  border-radius: 50%; background: var(--gold); }
.bsecs__foot { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: .4rem; }

/* ---- Executive Boards (eboards.html) ----
   A board card is the Board's space card with one line added: who was president.
   That is the fact people actually scan a list of past boards for, and it turns a
   grid of dates into a grid of names. */
.ebsec { padding-top: 1.5rem; }
.ebsec__pres { display: block; margin-top: .35rem; color: var(--text);
  font-size: .86rem; font-weight: 600; line-height: 1.3; }
/* The sitting board earns the gold edge — every other card is history. */
.ebsec--now { border-color: var(--gold); }
.ebsec__badge { position: absolute; top: .6rem; left: 50%; transform: translateX(-50%);
  color: var(--gold-deep); font-size: .6rem; font-weight: 800;
  letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; }
.ebsec--now .ebsig { margin-top: .35rem; }   /* clears the ● CURRENT badge above it */

/* ---- The Alumni Fund (donations.html) ----
   Case beside action: the left column says why, the right column is the tap. A
   payment link with no case attached asks for money without earning it, so the
   two are peers on desktop — and on a phone they stack purpose-first, because a
   brother scrolling should meet the reason before the button. */
/* The card is narrower than the case on purpose: the eye should land on it, and a
   column that is the same width as its neighbour competes rather than concludes. */
.give { display: grid; grid-template-columns: 1.15fr .85fr; gap: 3rem; align-items: start;
  max-width: 940px; margin: 0 auto; }
.give-blurb { max-width: 56ch; margin: 0 auto 2.8rem; text-align: center; }

/* ---- the goal, the bar and the honour roll (upgrade66) ---------------------
   Sits above the give card, because "we are most of the way there" is the reason
   someone taps the button. Renders nothing at all when no goal is set. */
.give-goal { max-width: 620px; margin: 0 auto 2.6rem; text-align: center; }
.give-goal .give-h { margin-bottom: .7rem; }
.give-bar { height: 14px; border-radius: 999px; background: var(--tint);
  border: 1px solid var(--hairline); overflow: hidden; }
.give-bar i { display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--gold-deep), var(--gold-bright));
  transition: width .6s ease; }
.give-bar__n { margin: .6rem 0 0; color: var(--text); font-size: 1rem; }
.give-bar__n b { font-family: var(--display); font-size: 1.35rem; color: var(--heading); }
/* No amount ever sits beside a name — the roll is a list of men, nothing more. */
.give-roll { margin: 1rem 0 0; color: var(--muted); font-size: .86rem; line-height: 1.8; }
.give-roll span { display: block; font-size: .72rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--gold-deep); margin-bottom: .2rem; }
@media (prefers-reduced-motion: reduce) { .give-bar i { transition: none; } }
.give-h { font-family: var(--display); font-size: .78rem; color: var(--muted);
  margin: 0 0 .4rem; letter-spacing: .16em; text-transform: uppercase; font-weight: 700; }

/* No card around the case. Two boxes side by side made the page read as a form;
   letting the left column breathe as plain text puts the only bordered thing on
   the page around the one action, which is where the eye should land. */
.give-case { padding: .3rem .2rem 0; }
.give-list { list-style: none; margin: 0; padding: 0; }
.give-list li { position: relative; padding: .95rem 0 .95rem 1.75rem; }
.give-list li + li { border-top: 1px solid var(--hairline); }
.give-list li::before { content: '✦'; position: absolute; left: 0; top: 1.05rem;
  color: var(--gold); font-size: .8rem; }
/* Label loud, detail quiet — the three things are scannable in a glance and the
   explanation is there for whoever wants it. */
.give-list b { display: block; font-family: var(--display); font-size: 1.06rem;
  color: var(--heading); font-weight: 700; line-height: 1.25; }
.give-list span { display: block; margin-top: .22rem; color: var(--muted);
  font-size: .89rem; line-height: 1.55; }

/* The card carries the gold top rule the E-Board cards use, so "this is the
   chapter asking" reads before a word is parsed. */
.give-card { background: var(--surface); border: 1.5px solid var(--hairline);
  border-top: 4px solid var(--gold); border-radius: var(--radius); padding: 1.7rem 1.6rem 1.5rem;
  box-shadow: var(--shadow-sm); text-align: center; }
.give-card--solo { grid-column: 1 / -1; max-width: 420px; margin: 0 auto; }

/* The button IS the page. Big enough to hit with a thumb without looking. */
.give-btn { display: block; margin: 0 auto; padding: 1rem 1.4rem; border-radius: 999px;
  background: linear-gradient(180deg, var(--gold-bright), var(--gold));
  color: var(--navy-deep); text-decoration: none;
  font-family: var(--display); font-size: 1.5rem; font-weight: 700; line-height: 1.1;
  word-break: break-all; box-shadow: 0 10px 24px rgba(var(--gold-rgb),.35);
  transition: transform .15s, box-shadow .2s; }
.give-btn:hover, .give-btn:focus-visible { transform: translateY(-2px);
  box-shadow: 0 14px 30px rgba(var(--gold-rgb),.45); }
.give-btn__at { opacity: .6; margin-right: .06em; }

.give-copy { margin: .9rem auto 0; display: block; background: none; border: 0;
  color: var(--gold-deep); font: 600 .84rem var(--sans); cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px; }
.give-copy:hover { color: var(--heading); }

/* Whose account this is. Not decoration — a handle without a name behind it is
   the thing that makes a brother hesitate. */
.give-who { margin: 1.3rem 0 0; padding-top: 1.1rem; border-top: 1px solid var(--hairline); }
.give-who small { display: block; margin-top: .2rem; color: var(--muted); font-size: .76rem; }
.give-who__link { background: none; border: 0; padding: 0; cursor: pointer;
  font: 700 1rem var(--display); color: var(--heading);
  border-bottom: 1px solid var(--gold); }
.give-who__link:hover { color: var(--gold-deep); }

.give-soon { max-width: 520px; margin: 0 auto; text-align: center; }

@media (max-width: 760px) {
  .give { grid-template-columns: 1fr; gap: 1.2rem; }
  .give-card--solo { max-width: none; }
  .give-btn { font-size: 1.25rem; }
}

/* The board filters. Deliberately not .fam-bar — that one is display:none below
   700px because the family tree swaps it for a <select>, and this page has no
   select to swap to, so the filters simply vanished on every phone. Scrolls
   sideways when the row runs out of room rather than disappearing. */
.ebchips { display: flex; gap: .5rem; margin: 0 0 1.4rem; flex-wrap: wrap; }
@media (max-width: 560px) {
  .ebchips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: .35rem;
             -webkit-overflow-scrolling: touch; }
  .ebchips .fam-chip { flex: none; }
}

/* ---- the board signet ----
   Replaces a 👑 that was identical on all seventeen cards and drew itself
   differently on every operating system. This is .badge__seal (line ~447) at card
   scale: same gradient, same inset ring, so the homepage badges and these cards
   speak one language rather than two.

   Two states carry the only distinction that matters at a glance — a quiet tinted
   disc for history, the filled gold seal for the board in office. */
.ebsig { display: flex; flex-direction: column; align-items: center; justify-content: center;
  width: 56px; height: 56px; margin: 0 auto .55rem; border-radius: 50%;
  background: var(--tint); border: 1.5px solid var(--gold); color: var(--gold-deep); }
/* The device gets the whole disc. It shared it with a year under a hairline rule
   at first, which capped the glyph at 24px — and at 24px an acorn and a leaf are
   the same blob. The year is on the very next line of the card anyway. */
.ebsig__g { display: block; width: 34px; height: 34px; }
.ebsig__g svg { display: block; width: 100%; height: 100%; }
/* The sitting board wears the seal itself. `--navy-deep` is #000 in dark mode, so
   the device stays black-on-gold there rather than navy-on-gold — checked, not assumed. */
/* Softer gradient and a thinner inset ring than .badge__seal's: that rule is tuned
   for a 92px badge, and at 56px its 3px highlight ate a third of the disc. */
.ebsig--now { background: radial-gradient(circle at 35% 28%, var(--gold-bright), var(--gold));
  border: 2px solid var(--gold-bright); color: var(--navy-deep);
  box-shadow: inset 0 0 0 1.5px rgba(255,255,255,.3), 0 6px 16px rgba(0,0,0,.28); }
/* In the detail header it sits beside the back button, not centred above a card. */
.bhead .ebsig { flex: none; width: 44px; height: 44px; margin: 0; }
.bhead .ebsig__g { width: 26px; height: 26px; }

/* ---- the men who sat on it ----
   The card named its president and stopped. These are the rest of them: officers
   first (seatsOf sorts that way), initials where a brother has no photo — which is
   most of the pre-2010 boards, so the monogram is the normal case, not the fallback. */
.ebfaces { display: flex; justify-content: center; margin: .5rem 0 .15rem; }
.ebfaces__f { width: 22px; height: 22px; border-radius: 50%; overflow: hidden;
  display: grid; place-items: center; background: var(--navy); color: var(--gold-bright);
  font-family: var(--sans); font-size: .5rem; font-weight: 700; letter-spacing: 0;
  border: 1.5px solid var(--surface); box-shadow: 0 0 0 1px var(--gold); }
.ebfaces__f + .ebfaces__f { margin-left: -7px; }   /* overlap, like a stack of photos */
.ebfaces__f img { width: 100%; height: 100%; object-fit: cover; }
.ebfaces__more { background: var(--tint); color: var(--gold-deep); }

/* The Alumni page keeps a door to the boards that used to be listed on it. */
.eb-seealso { margin: 1.5rem 0 0; font-weight: 600; }
.eb-seealso a { color: var(--gold-deep); text-decoration: none; border-bottom: 1px solid transparent; }
.eb-seealso a:hover { border-bottom-color: currentColor; }

.eb-note { max-width: 60ch; margin: 0 0 1.4rem; }
.eb-tools { margin-top: 2.6rem; }
/* Semester beside year: two controls that are one answer. */
.eb-termrow { display: flex; gap: .6rem; }
.eb-termrow select { flex: 0 0 8.5rem; }
.eb-termrow input { flex: 1 1 auto; min-width: 0; }
/* Unread = solid gold, matching the gold .thr-dot and the help modal's "Gold = new".
   No override for the active row on purpose: the console's existing
   `.admin-navbtn.on .tab-count` (0,3,0) already outranks this (0,1,0) and renders
   the badge correctly on gold. An override here measured 4.19 contrast in light —
   below AA — while letting the existing rule win measures 4.93. */
.tab-count--new { background: var(--gold); color: var(--navy-deep); font-weight: 700; }

.board-controls__right { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }

@media (max-width: 900px) {
  .bsecs { grid-template-columns: repeat(2, 1fr); }
  /* The spaces <select> and the mobile help button lived here; the card front
     door replaced both, so the controls row is just "+ New thread" and sort. */
  .board-controls__right { width: 100%; }
  .board-controls__right .page-filter { flex: 1 1 0; min-width: 0; }
}

/* Introductions composer — the one place on the board that spends boldness.
   Deliberately navy+gold in BOTH themes: a single committed look, the only
   element carrying this weight, so it reads as *the* thing to do. */
.intro-card {
  background: linear-gradient(180deg, var(--navy), var(--navy-deep));
  border: 1.5px solid var(--gold);
  border-radius: var(--radius);
  padding: 1.3rem 1.4rem;
  margin: 0 0 1.2rem;
  box-shadow: var(--shadow-sm);
}
.intro-card__head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; flex-wrap: wrap; margin-bottom: .8rem;
}
.intro-card__head b {
  font-family: var(--display); font-size: 1.35rem;
  font-weight: 600; color: var(--gold-bright);
}
.intro-card__class {
  color: rgba(var(--white-rgb), .72); font-size: .8rem;
  font-weight: 600; letter-spacing: .02em;
}
.intro-card textarea {
  width: 100%; min-height: 92px; resize: vertical;
  border-radius: 10px; border: 1px solid rgba(var(--gold-rgb), .35);
  background: rgba(255, 255, 255, .06); color: var(--white);
  padding: .75rem .85rem; font-family: var(--sans); font-size: .92rem;
}
.intro-card textarea::placeholder { color: rgba(var(--white-rgb), .5); }
.intro-card textarea:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
.intro-card__foot {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; flex-wrap: wrap; margin-top: .8rem;
}
.intro-card__hint { color: rgba(var(--white-rgb), .6); font-size: .76rem; }
.intro-card .form-status { margin: .6rem 0 0; }
@media (max-width: 640px) {
  .intro-card__foot { flex-direction: column; align-items: stretch; }
  .intro-card__foot .btn { width: 100%; }
}

/* ---------- board header row: the way out sits IN the header ----------
   The back control used to be a pill on its own line above the section header,
   spending a whole row on navigation and pushing the content down. It is now a
   round button at the left of the header it belongs to. The headers themselves
   are untouched — .cat-band, .gsechead, h2 and h3 keep their own looks, and only
   their outer margin moves onto the row so the two stay optically aligned. */
.bhead { display: flex; align-items: center; gap: .8rem; margin: 0 0 1rem; }
.bhead__main { flex: 1 1 auto; min-width: 0; }
.bhead .cat-band, .bhead .gsechead, .bhead h2, .bhead h3 { margin: 0; }

.bback {
  flex: none; width: 44px; height: 44px;          /* full tap target on a phone */
  display: grid; place-items: center;
  background: var(--navy); color: var(--gold-bright);
  border: 1px solid rgba(var(--gold-rgb),.5); border-radius: 50%;
  font-size: 1.15rem; line-height: 1; cursor: pointer;
  transition: border-color .15s, transform .15s;
}
.bback:hover { border-color: var(--gold-bright); transform: translateX(-2px); }
@media (max-width: 480px) {
  .bhead { gap: .6rem; }
  .bback { width: 40px; height: 40px; }
}

/* Introductions, once he's already said hi: the composer's slot becomes the way
   back to what he wrote. Same left-border idiom as .cat-band so it reads as part
   of the section rather than a stray notice. */
.intro-done {
  display: flex; align-items: center; flex-wrap: wrap; gap: .5rem;
  margin: 0 0 1.1rem; padding: .8rem 1.1rem;
  background: var(--surface); border: 1px solid var(--hairline);
  border-left: 5px solid var(--gold); border-radius: 12px;
  color: var(--muted); font-size: .9rem; box-shadow: var(--shadow-sm);
}
.intro-done button {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-weight: 700; color: var(--gold-deep); text-decoration: underline;
}
.intro-done button:hover { color: var(--heading); }

/* Editing your own post, in place under the title. */
.thr-edit { margin: 1.1rem 0 1.4rem; }
.thr-edit .field:last-of-type { margin-bottom: .9rem; }
.thr-edit__foot { display: flex; align-items: center; gap: .7rem; flex-wrap: wrap; }

.cat-band { display: flex; gap: .8rem; align-items: center; background: var(--surface); border-radius: 12px; padding: .8rem 1.1rem; font-size: 1.3rem; box-shadow: var(--shadow-sm); border-left: 5px solid var(--navy); margin-bottom: .9rem; }
.cat-band b { display: block; color: var(--heading); font-family: var(--display); font-size: 1.05rem; }
.cat-band span { color: var(--muted); font-size: .82rem; }
.cat-band--advice { border-left-color: #1f6f6b; }
.cat-band--social { border-left-color: var(--gold-deep); }
.cat-band--opportunities { border-left-color: #2c6e2c; }
.cat-band--comm { border-left-color: var(--gold); }

.board-controls { display: flex; gap: .7rem; align-items: center; justify-content: space-between; margin: 0 0 1rem; flex-wrap: wrap; }

.thread-row { border-left: 4px solid var(--navy); }
.thread-row--advice { border-left-color: #1f6f6b; }
.thread-row--social { border-left-color: var(--gold-deep); }
.thread-row--opportunities { border-left-color: #2c6e2c; }
.thread-row--comm { border-left-color: var(--gold); border-left-style: dashed; }
.thread-row__av { position: relative; width: 40px; height: 40px; flex: none; border-radius: 50%; background: var(--navy); color: var(--gold-bright); display: grid; place-items: center; font-family: var(--display); overflow: hidden; }
.thread-row__av img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
/* Needs .thread-row__main to outrank `.thread-row__main span` (0,1,1), which sets
   display:inline-flex and was running the preview into the author line. */
.thread-row__main .thread-row__prev { display: block; color: var(--muted); font-size: .84rem; margin: .1rem 0 .2rem; }
.thread-row.unread .thread-row__main > b { color: var(--navy-deep); }
/* Dark mode remaps --navy-deep to #000 (it's a chrome token), so the rule above
   painted unread titles black on a #151515 card — 1.15 contrast. Unread means
   "emphasized", which in this theme is bright gold, not black. */
:root[data-theme="dark"] .thread-row.unread .thread-row__main > b { color: var(--heading); }
.thr-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--gold); margin-right: .45rem; vertical-align: 1px; }
.thr-hot { font-style: normal; font-size: .85rem; }

.board-empty { text-align: center; padding: 2.5rem 1rem 3rem; position: relative; }
.board-empty img { width: 130px; margin: 0 auto 1rem; opacity: .25; filter: grayscale(35%); }
.board-empty p { color: var(--muted); font-size: .95rem; }
.board-empty b { color: var(--heading); }

.react-bar { display: inline-flex; gap: .35rem; margin-top: .35rem; }
.react { border: 1px solid var(--hairline); background: var(--surface-2); border-radius: 999px; padding: .12rem .55rem; font-size: .8rem; cursor: pointer; transition: all .12s; }
.react:hover { border-color: var(--gold-deep); }
.react.on { background: var(--tint); border-color: var(--gold); }

.thread-view__photo { margin: 1rem 0; }
.thread-view__photo img { max-width: 100%; max-height: 440px; border-radius: 12px; box-shadow: var(--shadow-sm); }

/* ---------- admin console redesign ---------- */
.admin-body { background:
  radial-gradient(90% 60% at 85% -10%, rgba(var(--gold-rgb),.14), rgba(var(--gold-rgb),0) 55%),
  radial-gradient(70% 50% at 0% 100%, rgba(var(--navy-2-rgb),.7), rgba(var(--navy-2-rgb),0) 60%),
  var(--navy-deep); }
/* Dark console is pure black — the navy bottom-left glow reads as an off-identity
   blue smudge on it, so drop it and keep only the subtle gold top-right glow. */
:root[data-theme="dark"] .admin-body { background:
  radial-gradient(90% 60% at 85% -10%, rgba(var(--gold-rgb),.14), rgba(var(--gold-rgb),0) 55%),
  var(--navy-deep); }
.admin-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding-bottom: 1.1rem; border-bottom: 1px solid rgba(var(--gold-rgb),.28); margin-bottom: 1.3rem; flex-wrap: wrap; }
.admin-head__id { display: flex; align-items: center; gap: .9rem; }
.admin-head__id img { height: 52px; width: auto; }
.admin-head h2 { margin: 0; color: var(--gold-bright); }
.admin-head__sub { color: var(--on-dark); font-size: .82rem; }
.admin-tabgroup { margin-bottom: .7rem; }
.admin-tabgroup__label { color: rgba(var(--gold-bright-rgb),.75); }
.admin-tabs button { border: 1px solid rgba(var(--gold-rgb),.35); background: rgba(255,255,255,.06); color: var(--on-navy-2); border-radius: 999px; padding: .5rem 1.05rem; font-size: .86rem; font-weight: 600; cursor: pointer; transition: all .15s; }
.admin-tabs button:hover { border-color: var(--gold); color: var(--gold-bright); }
.admin-tabs button.on { background: linear-gradient(180deg, var(--gold-bright), var(--gold)); color: var(--navy-deep); border-color: transparent; box-shadow: 0 6px 18px rgba(var(--gold-rgb),.35); }
.admin-tabs button.on .tab-count { background: rgba(var(--chrome),.25); color: var(--navy-deep); }
.tab-count { background: rgba(var(--gold-rgb),.22); color: var(--gold-bright); border-radius: 999px; padding: .06rem .45rem; font-size: .72rem; }
/* Console search: navy to match (scoped to .admin-body so the light-page mentor
   bar keeps its own styling). The old .admin-row overrides here were stale
   leftovers that reset the gold ledger-spine — removed. */
.admin-body .admin-search { border: 1.5px solid rgba(var(--gold-rgb),.30); background: var(--console-field); color: var(--on-navy); }
.admin-body .admin-search::placeholder { color: var(--on-navy-3); }

/* Console cream cards -> warm parchment (was stark near-white on the navy body).
   Scoped to .admin-body so the public "My Profile" popup's .acct-block stays as-is.
   --console-panel flips (warm parchment light / lifted-dark dark), so dark mode is
   unaffected; the gold hairline reads in both. Inner content keeps its current
   dark-on-parchment / light-on-dark colors — no inner flips. */
.admin-body .acct-block,
.admin-body .guide-sec,
.admin-body .stat-card,
.admin-body .stat-list,
.admin-body .treeed-list { background: var(--console-panel); border-color: rgba(var(--gold-rgb),.28); }
/* keep the destructive "Semester rollover" card's caution border (my rule above
   would otherwise repaint it gold) — theme-agnostic muted red. */
.admin-body .acct-block--danger { border-color: rgba(178,52,43,.42); }

/* Email composer tab (email-tab.js) reuses the generic .field / .pref-box form
   classes, but it mounts on the NAVY console where --heading/--text/--muted
   resolve to dark ink and vanish. Re-point them to the console's gold+cream-on-
   navy palette, and restore the navy .zselect that ".field select" was
   overpainting cream (0,1,1 > 0,1,0). Scoped to .email-tab so the cream
   edit-modal .field labels stay untouched. */
.email-tab .field label { color: var(--gold-bright); }
.email-tab .field input,
.email-tab .field textarea {
  background: var(--console-field); border-color: rgba(var(--gold-rgb),.30); color: var(--on-navy);
}
.email-tab .field input::placeholder,
.email-tab .field textarea::placeholder { color: var(--on-navy-3); }
.email-tab .zselect {
  background-color: var(--console-field); color: var(--on-navy);
  border-color: rgba(var(--gold-rgb),.5); padding: .7rem 1.9rem .7rem .8rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23E8C766' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .65rem center;
}
.email-tab .pref-box { color: var(--on-navy); }
.email-tab .pref-box small { color: var(--on-dark); }
.email-tab input[type="checkbox"] { accent-color: var(--gold); width: 1.05rem; height: 1.05rem; }
.email-tab input[type="file"] { color: var(--on-dark); font-size: .9rem; }
.email-tab .form-note { color: var(--on-dark); }
.email-tab .form-status { display: block; color: var(--on-navy); }
.stat-card { border-top: 3px solid var(--gold); }
.stat-h { display: flex; align-items: center; gap: .6rem; }
.stat-h::after { content: ''; flex: 1; height: 1px; background: rgba(var(--gold-rgb),.3); }

/* ============================================================================
   v9 — Family Tree explorer: floating toolbar, gesture hint, fullscreen,
   dropdown family selector on every screen size
   ============================================================================ */
.tree-controls {
  top: 12px; right: 12px; bottom: auto; left: auto; transform: none;
  align-items: center; gap: .12rem;
  background: rgba(var(--chrome),.9); border: 1px solid rgba(var(--gold-rgb),.45);
  border-radius: 999px; padding: .3rem .5rem;
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  box-shadow: 0 12px 32px rgba(var(--chrome),.35);
}
.tree-controls button {
  width: 38px; height: 38px; border-radius: 50%; border: 0;
  background: transparent; color: var(--gold-bright); box-shadow: none; font-size: 1.1rem;
}
.tree-controls button:hover { background: rgba(var(--gold-rgb),.25); color: #fff; }
.tree-controls__sep { width: 1px; height: 22px; background: rgba(var(--gold-rgb),.35); margin: 0 .3rem; }

/* Vertical rail on the LEFT edge (reads top-to-bottom) so it never lies across
   the cards while it waits to fade — the horizontal pill used to cover the
   bottom row until the first drag. */
.tree-hintchip {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  writing-mode: vertical-rl;
  background: rgba(var(--chrome),.85); color: var(--on-navy-2); font-size: .78rem;
  padding: 1.1rem .45rem; border-radius: 999px; border: 1px solid rgba(var(--gold-rgb),.35);
  pointer-events: none; z-index: 9; white-space: nowrap; max-height: calc(100% - 24px);
  overflow: hidden; text-overflow: ellipsis; transition: opacity .6s;
}
.tree-hintchip.gone { opacity: 0; }
/* Fullscreen: move the Close button to the top-left so the toolbar keeps the
   top-right corner; the hint keeps the left edge. */
.tree-shell--full .tree-fullclose { left: 14px; right: auto; }
.tree-shell--full .tree-hintchip { left: 14px; }

.tree-fullclose {
  display: none; position: absolute; top: 14px; right: 14px; z-index: 12;
  border-radius: 999px; border: 1px solid rgba(var(--gold-rgb),.5);
  background: rgba(var(--chrome),.88); color: var(--gold-bright);
  font-weight: 600; font-size: .9rem; padding: .55rem 1.15rem; cursor: pointer;
}
.tree-fullclose:hover { background: var(--gold); color: var(--navy-deep); }

.tree-shell--full {
  position: fixed; inset: 0; z-index: 1300; margin: 0 !important;
  background: var(--navy-deep);
}
.tree-shell--full .tree-viewport {
  height: 100dvh; max-height: none; border-radius: 0; border: 0;
  background: radial-gradient(120% 90% at 50% 0%, #fffdf7, var(--cream-2));
}
.tree-shell--full .tree-fullclose { display: block; }
body.tree-lock { overflow: hidden; }

.tree-node--rootsel {
  border-color: var(--gold) !important;
  box-shadow: 0 0 0 3px rgba(var(--gold-rgb),.45), 0 10px 26px rgba(var(--gold-rgb),.25);
}

/* the family dropdown is now THE selector on desktop too */
.fam-select {
  display: block; appearance: none; -webkit-appearance: none;
  margin: 1.4rem auto .2rem; padding: .75rem 2.8rem .75rem 1.2rem;
  border: 1.5px solid var(--gold); background-color: var(--paper);
  border-radius: 999px; cursor: pointer; box-shadow: var(--shadow-sm);
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1l6 6 6-6' fill='none' stroke='%23C8A24B' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 1.1rem center;
}
.fam-select:hover { border-color: var(--gold-deep); }

@media (pointer: coarse) {
  .tree-toggle { padding: .3rem .55rem; font-size: .95rem; }
  .tree-controls button { width: 42px; height: 42px; }
}

/* ============================================================================
   v9 — unified chapter calendar: month grid + Up Next rail, admin in-place
   editing, symmetric layout
   ============================================================================ */
.cal-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 1.8rem; align-items: start; }
.cal-main { background: var(--surface); border-radius: var(--radius); padding: 1.4rem 1.4rem 1.6rem; box-shadow: var(--shadow-sm); }
.cal-head { margin-bottom: 1rem; }
.cal-cell { background: var(--surface-2); }
.cal-cell--sel { border-color: var(--gold-deep); box-shadow: 0 0 0 1.5px var(--gold-deep); }
.cal-cell[data-day]:not(.cal-cell--has) { cursor: pointer; }
.cal-cell[data-day]:not(.cal-cell--has):hover { border-color: rgba(var(--gold-rgb),.6); }
.cal-cell:disabled { cursor: default; }
.cal-detail { border-top: 1px solid var(--hairline); padding-top: 1rem; margin-top: 1.2rem; }
.cal-detail:empty { display: none; }
.cal-detail__ev { background: var(--surface-2); border: 1px solid var(--hairline); box-shadow: none; }
.cal-detail__none { color: var(--muted); font-size: .9rem; }
.cal-detail__add { margin-top: .4rem; font-size: .88rem; padding: .55rem 1.2rem; }
.ev-loc { color: var(--gold-deep); text-decoration: underline; text-underline-offset: 2px; }

.cal-rail { background: var(--surface); border-radius: var(--radius); padding: 1.2rem 1.2rem 1rem; box-shadow: var(--shadow-sm); position: sticky; top: 88px; }
.cal-rail__h { margin: 0 0 .9rem; color: var(--heading); font-family: var(--display); font-size: 1.1rem; }
.cal-rail__none { color: var(--muted); font-size: .9rem; }
.cal-rail__add { width: 100%; margin-top: .4rem; font-size: .88rem; padding: .55rem 0; }
.cal-rail__help { display: block; width: 100%; margin-top: .8rem; background: none; border: 0; border-top: 1px solid var(--hairline); padding: .7rem 0 .1rem; color: var(--gold-deep); font-size: .84rem; font-weight: 600; cursor: pointer; text-align: center; }
.cal-rail__help:hover { color: var(--heading); }

.unx { display: flex; gap: .8rem; padding: .7rem 0; border-bottom: 1px solid var(--hairline); cursor: pointer; align-items: flex-start; }
.unx:last-of-type { border-bottom: 0; }
.unx:hover .unx__body > b { color: var(--gold-deep); }
.unx__date { flex: none; width: 46px; text-align: center; background: var(--navy); color: var(--on-navy); border-radius: 10px; padding: .35rem 0; }
.unx__date b { display: block; font-size: 1.15rem; font-family: var(--display); color: var(--gold-bright); line-height: 1.05; }
.unx__date span { font-size: .6rem; letter-spacing: .16em; }
.unx__body { min-width: 0; }
.unx__body > b { display: block; color: var(--heading); font-size: .95rem; line-height: 1.25; }
.unx__body small { color: var(--muted); font-size: .78rem; }
.unx__cat { display: inline-block; font-size: .62rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--gold-deep); }
.unx__cat--philanthropy { color: #2c6e2c; }
.unx__cat--meeting { color: var(--heading); }
.unx__cat--reunion { color: #7a4a9e; }
.unx__cat--rush { color: #8a5a1f; }
.unx .ev-rsvp { margin-top: .4rem; }
.unx .ev-rsvp__btn { padding: .25rem .7rem; font-size: .76rem; }
.unx .ev-rsvp__who { display: none; }

.cal-adminrow { display: flex; gap: .5rem; margin-top: .6rem; }
.cal-mini { border: 1.5px solid var(--navy-2); background: var(--surface-2); color: var(--heading); border-radius: 999px; padding: .3rem .9rem; font-size: .8rem; font-weight: 600; cursor: pointer; }
.cal-mini:hover { border-color: var(--gold-deep); }
.cal-mini--del { border-color: #c0392b55; color: var(--danger); }
.cal-mini--del:hover { border-color: var(--danger); background: #fdf0ee; }

.evm-allday { display: flex; align-items: center; gap: .5rem; color: var(--heading); font-size: .92rem; font-weight: 600; margin: .2rem 0 .8rem; cursor: pointer; }
.evm-allday input { width: auto; }
.evm-times { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: .8rem; }
.evm-actions { display: flex; align-items: center; gap: .8rem; margin-top: .4rem; }
.cal-helpbody p { color: var(--text); font-size: .95rem; line-height: 1.65; margin: 0 0 .9rem; }
.cal-helpbody b { color: var(--heading); }

@media (max-width: 880px) {
  .cal-layout { grid-template-columns: 1fr; }
  .cal-rail { position: static; }
}

/* ============================================================================
   v9 — Recognized Excellence: engraved gold medallions (admin-editable)
   ============================================================================ */
.medals { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.6rem; margin-top: 2.8rem; }
.medal {
  position: relative; text-align: center; padding: 2rem 1.2rem 1.6rem;
  background: linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,.015));
  border: 1px solid rgba(var(--gold-rgb),.28); border-radius: 16px;
  overflow: hidden; transition: transform .25s, border-color .25s, box-shadow .25s;
}
.medal:hover { transform: translateY(-5px); border-color: rgba(var(--gold-rgb),.6); box-shadow: 0 18px 40px rgba(0,0,0,.35); }
.medal::before {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(115deg, transparent 30%, rgba(var(--gold-bright-rgb),.14) 48%, transparent 62%);
  transform: translateX(-120%); transition: transform .8s ease;
  pointer-events: none;
}
.medal:hover::before { transform: translateX(120%); }
.medal__seal {
  width: 96px; height: 96px; margin: 0 auto 1.1rem; border-radius: 50%;
  display: grid; place-items: center; font-size: 2.1rem; color: var(--navy-deep);
  background:
    radial-gradient(circle at 32% 28%, #f6e3a8, #E8C766 38%, #C8A24B 68%, #8f701f 100%);
  box-shadow:
    inset 0 2px 6px rgba(255,255,255,.55),
    inset 0 -4px 10px rgba(90,64,10,.45),
    0 0 0 3px rgba(var(--gold-rgb),.35),
    0 0 0 7px rgba(var(--gold-rgb),.12),
    0 10px 24px rgba(0,0,0,.4);
}
.medal__seal span { filter: drop-shadow(0 1px 0 rgba(255,240,190,.6)); }
.medal > b { display: block; font-family: var(--display); font-size: 1.12rem; color: var(--gold-bright); line-height: 1.3; }
.medal__pillar { display: block; margin-top: .3rem; font-size: .68rem; font-weight: 700; letter-spacing: .22em; text-transform: uppercase; color: var(--on-dark); }
.medal p { color: var(--on-navy-3); font-size: .84rem; line-height: 1.55; margin: .7rem 0 0; }

.award-years { display: flex; justify-content: center; gap: .5rem; flex-wrap: wrap; margin-top: 1.4rem; }
.award-years button {
  border: 1px solid rgba(var(--gold-rgb),.4); background: transparent; color: var(--on-navy-2);
  border-radius: 999px; padding: .4rem 1.1rem; font-size: .84rem; font-weight: 600; cursor: pointer;
  transition: all .15s;
}
.award-years button:hover { border-color: var(--gold); color: var(--gold-bright); }
.award-years button.on { background: linear-gradient(180deg, var(--gold-bright), var(--gold)); color: var(--navy-deep); border-color: transparent; }

.aw-year { color: var(--gold-bright); font-family: var(--display); margin: 1.4rem 0 .6rem; }

@media (max-width: 900px) { .medals { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .medals { grid-template-columns: 1fr; max-width: 320px; margin-inline: auto; } }

/* ============================================================================
   v9 — header polish, announcement banner redesign, rich account dropdown
   ============================================================================ */
/* nav link underline sweep */
.nav__links a { position: relative; padding-bottom: 4px; }
.nav__links a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: linear-gradient(90deg, var(--gold-bright), var(--gold));
  border-radius: 2px; transform: scaleX(0); transform-origin: left;
  transition: transform .22s ease;
}
.nav__links a:hover::after, .nav__links a.on::after { transform: scaleX(1); }
.nav--scrolled { background: rgba(var(--chrome), .97); box-shadow: 0 10px 30px rgba(var(--chrome),.45); border-bottom-color: rgba(var(--gold-rgb),.55); }
.brand .crest-badge { transition: box-shadow .25s; }
.brand:hover .crest-badge { box-shadow: 0 0 0 3px rgba(var(--gold-rgb),.35), 0 0 18px rgba(var(--gold-bright-rgb),.5); }

/* account dropdown: navy identity header + roomy icon rows */
.nav__chip .nav__avatar { box-shadow: 0 0 0 2px rgba(var(--gold-rgb),.55); }
.nav__caret { transition: transform .2s; }
.nav__chip[aria-expanded="true"] .nav__caret { transform: rotate(180deg); }
.nav__menu {
  width: 262px; padding: 0 0 .45rem; border-radius: 16px; overflow: hidden;
  animation: menuIn .18s ease both;
  /* The menu hangs off a position:fixed header, so anything below the bottom of
     the viewport is UNREACHABLE — page scrolling cannot move a fixed element, and
     with no height cap the menu had no scrollbar of its own either. A drag just
     fell through to the document and scrolled the page behind it. Expanding
     "Brothers Only" adds ~335px, which pushed "Sign out" off-screen on every
     phone AND on any window under ~811px tall for the admin (a 1280x800 desktop
     failed too — this was never mobile-only).
     84px = the 59-61px the menu starts at + ~25px so it never kisses the edge.
     svh, not vh or dvh: svh is the SMALL viewport — iOS Safari with its toolbars
     showing — so it fits whether the bars are up or hidden, and unlike dvh it
     will not resize mid-scroll. The plain vh line above is the fallback for iOS
     before 15.4, which ignores the svh line entirely.
     overflow: hidden above stays — it is what clips the head gradient to the
     16px radius; overflow-y: auto after it computes to x-hidden / y-auto.
     overscroll-behavior stops a flick that reaches the end of the list from
     chaining into the page behind (same trick as .bmodal__card). */
  max-height: calc(100vh - 84px);
  max-height: calc(100svh - 84px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
@keyframes menuIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
.nav__menu-head {
  display: flex; align-items: center; gap: .8rem; padding: .95rem .9rem;
  background: linear-gradient(135deg, #10294f, #0A1F44 70%);
  border-bottom: 1px solid rgba(var(--gold-rgb),.35); margin-bottom: .4rem;
}
.nav__menu-av {
  position: relative; width: 46px; height: 46px; flex: none; border-radius: 50%; overflow: hidden;
  background: linear-gradient(180deg, var(--gold-bright), var(--gold)); color: var(--navy-deep);
  display: grid; place-items: center; font-family: var(--display); font-weight: 700; font-size: 1.25rem;
  box-shadow: 0 0 0 2px rgba(var(--gold-rgb),.6);
}
.nav__menu-av img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
.nav__menu-id { min-width: 0; }
.nav__menu-id b { display: block; color: var(--on-navy); font-family: var(--display); font-size: 1.02rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav__menu-id > span { display: block; color: var(--on-dark); font-size: .72rem; overflow: hidden; text-overflow: ellipsis; }
.role-pill {
  display: inline-block; margin-top: .4rem; font-size: .6rem; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase; padding: .16rem .55rem; border-radius: 999px;
  background: rgba(255,255,255,.1); color: var(--on-navy-2); border: 1px solid rgba(255,255,255,.18);
}
.role-pill--admin {
  background: linear-gradient(180deg, var(--gold-bright), var(--gold));
  color: var(--navy-deep); border-color: transparent;
}
.nav__menu a, .nav__menu button { display: flex; align-items: center; gap: .65rem; margin: 0 .45rem; width: auto; padding: .6rem .55rem; }
.nav__menu a i, .nav__menu button i { font-style: normal; flex: none; width: 22px; text-align: center; }
.nav__menu-admin em { font-style: normal; margin-left: auto; }
.nav__menu-badge {
  background: #c0392b; color: #fff; font-size: .64rem; font-weight: 700;
  border-radius: 999px; padding: .12rem .5rem; margin-left: .3rem;
}
.nav__menu-divider { margin: .4rem .9rem; }

/* ============================================================================
   Crest system — featured "Our Arms" showcase + faint section watermarks
   ============================================================================ */
.has-watermark { position: relative; overflow: hidden; }
/* Floating crest watermark: a transparent PNG (no rectangle) that adapts to
   theme + section background. Sits fully on-screen on the right, behind content. */
.sect-watermark {
  position: absolute; top: 50%; right: 2%; transform: translateY(-50%);
  width: min(430px, 40%); aspect-ratio: 500 / 750; z-index: 0;
  pointer-events: none; user-select: none;
}
.sect-watermark__img {
  display: block; width: 100%; height: 100%;
  background: center / contain no-repeat;
  opacity: .22;
}
/* which colored crest + how strong, per section background:
   - brotherhood is cream (light) -> dark crest;  navy/black -> gold crest
   - contact is navy/black in both themes         -> gold crest always      */
#brotherhood .sect-watermark__img { background-image: url("../img/crest-float-dark.webp"); }
#contact     .sect-watermark__img { background-image: url("../img/crest-float-gold.webp"); opacity: .2; }
:root[data-theme="dark"] #brotherhood .sect-watermark__img { background-image: url("../img/crest-float-gold.webp"); opacity: .26; }
:root[data-theme="dark"] #contact     .sect-watermark__img { opacity: .26; filter: drop-shadow(0 0 26px rgba(var(--gold-rgb),.18)); }
.has-watermark > .wrap { position: relative; z-index: 1; }
@media (max-width: 560px) { .sect-watermark { display: none; } }  /* protect form legibility on tiny screens */

/* reveal (slide in from the right) + gentle continuous float — only when motion is allowed */
.fx .sect-watermark {
  opacity: 0; transform: translateY(-50%) translateX(50px);
  transition: opacity 1.1s ease, transform 1.2s cubic-bezier(.2,.7,.2,1);
}
.fx .sect-watermark.in { opacity: 1; transform: translateY(-50%) translateX(0); }
.fx .sect-watermark.in .sect-watermark__img { animation: wm-float 7s ease-in-out infinite; }
@keyframes wm-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-16px); } }


/* ============================================================================
   Networking Phase A — completion meter, open-to chips, Connect bar
   ============================================================================ */
/* profile completion meter (My Profile popup) */
.pmeter { display: flex; align-items: center; gap: .8rem; background: var(--surface-2); border: 1px solid rgba(var(--gold-rgb),.4); border-radius: 12px; padding: .65rem .9rem; margin-bottom: 1.1rem; }
.pmeter__bar { flex: 1; height: 8px; background: var(--hairline); border-radius: 999px; overflow: hidden; }
.pmeter__bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--gold), var(--gold-bright)); border-radius: 999px; transition: width .4s ease; }
.pmeter > span { flex: none; color: var(--muted); font-size: .8rem; }
.pmeter > span b { color: var(--heading); }
.pmeter--done { color: var(--heading); font-size: .88rem; background: var(--tint); border-color: var(--gold); }

/* "open to" badges on the profile card */
.ot-chips { display: flex; gap: .45rem; flex-wrap: wrap; margin: 0 0 .9rem; }
.ot-chip { background: var(--tint); border: 1px solid rgba(var(--gold-rgb),.55); color: var(--heading); border-radius: 999px; padding: .28rem .8rem; font-size: .78rem; font-weight: 700; }

/* Connect bar at the bottom of a brother card */
.bm__connect { display: flex; align-items: center; gap: .9rem; margin-top: 1.2rem; padding-top: 1rem; border-top: 1px solid var(--hairline); flex-wrap: wrap; }
.bm__connect span { color: var(--muted); font-size: .78rem; flex: 1; min-width: 180px; }
.bm__connect-btn { font-size: .88rem; padding: .55rem 1.3rem; }
.bm__connect-btn:disabled { opacity: .75; cursor: default; }
/* Once the note field opens the bar stops being a row: the textarea needs the
   full width, and 120px (the site-wide .field default) is far too tall for one
   optional line inside an already-scrolling profile modal. */
.bm__connect--open { display: block; }
.bm__connect--open .field { margin-bottom: 0; }
.bm__connect--open .field textarea { min-height: 66px; }
.bm__connect-send { display: flex; align-items: center; gap: .9rem; margin-top: .7rem; flex-wrap: wrap; }
.bm__connect-send span { color: var(--muted); font-size: .78rem; flex: 1; min-width: 180px; }

/* tiny open-to icons on roster cards */
.bro-card__ots { font-style: normal; margin-left: .3rem; letter-spacing: .1em; }
.bro-card__ot { font-style: normal; font-size: .8rem; }

/* "How networking works" trigger */
.net-help { background: none; border: 0; color: var(--gold-deep); font-weight: 600; font-size: .84rem; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; padding: 0; }
.net-help:hover { color: var(--heading); }

/* ============================================================================
   Mentoring — two lists, each self-contained (upgrade55)
   ============================================================================ */
/* Two equal columns that become one on a narrow screen. The cards are equal-height
   so the two headers line up; the lists inside scroll rather than letting one card
   run to four screens while the other shows an empty state. */
.mtg-intro { margin-bottom: 1.4rem; }
.mtg-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.2rem;
  align-items: start; margin-bottom: 3rem; }
.mtg-card { background: var(--surface); border: 1.5px solid var(--hairline); border-radius: var(--radius);
  padding: 1.2rem 1.25rem; box-shadow: var(--shadow-sm); display: flex; flex-direction: column; }
.mtg-card__head { display: flex; align-items: baseline; justify-content: space-between; gap: .6rem;
  flex-wrap: wrap; }
.mtg-card__head h2 { font-family: var(--display); font-size: 1.35rem; color: var(--heading); margin: 0; }
.mtg-card__count { font-size: .8rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--gold-deep); flex: none; }
.mtg-card__blurb { margin: .5rem 0 .9rem; font-size: .89rem; color: var(--muted); line-height: 1.5; }
.mtg-card__tools { display: flex; gap: .6rem; flex-wrap: wrap; }
.mtg-card__tools .admin-search { flex: 1 1 100%; margin: 0; }
.mtg-card__tools .page-filter { flex: 1 1 100%; }
/* One column inside the card — .bro-grid's three columns are for a full-width page. */
.bro-grid--stack { grid-template-columns: 1fr; max-height: 30rem; overflow-y: auto;
  margin-top: .9rem; padding-right: .2rem; }
.mtg-card__foot { margin-top: auto; padding-top: 1rem; }
.mtg-card__foot .btn { width: 100%; }
.mtg-card__foothint { margin: .55rem 0 0; font-size: .78rem; color: var(--muted); line-height: 1.45; }

@media (max-width: 820px) { .mtg-grid { grid-template-columns: 1fr; } }

/* Phase C — invite status chip */
.schip--warn { background: #a4392f; color: #fff; }
.acct-block textarea { width: 100%; min-height: 110px; }

/* invite-link greeting on the portal auth card */
.invite-banner { background: var(--tint); border: 1.5px solid var(--gold); border-radius: 12px; padding: .85rem 1rem; margin-bottom: 1rem; }
.invite-banner b { display: block; color: var(--heading); font-size: .95rem; }
.invite-banner span { display: block; color: var(--muted); font-size: .84rem; line-height: 1.5; margin-top: .2rem; }
.invite-banner span b { display: inline; color: var(--heading); }

/* ============================================================================
   v10 — header: legible crest + Greek monogram, and a nav that never overflows
   ============================================================================ */
.brand { flex: none; }
.brand img { height: 52px; }
.brand__txt { font-size: 1.75rem; letter-spacing: .06em; line-height: 1.05; white-space: nowrap; }
.brand__txt small { font-size: .58rem; letter-spacing: .2em; margin-top: .22rem; }
.nav__inner { gap: 1rem; }
.nav__links a { white-space: nowrap; }
.nav__account { flex: none; }

/* Tighten the links before handing off to the hamburger. */
@media (max-width: 1180px) {
  .nav__links { gap: 1.05rem; }
  .nav__links a { font-size: .86rem; }
}

/* The links + bell + account chip stopped fitting on one line far above the old
   760px hamburger breakpoint — the nav wrapped onto the hero and "Contact" slid
   under the notification bell. Hand off while there's still room. */
@media (max-width: 1023px) {
  .nav__links {
    position: fixed; inset: 72px 0 auto 0; flex-direction: column; gap: 0;
    background: rgba(var(--chrome),.98); padding: 1rem 0;
    border-bottom: 1px solid rgba(var(--gold-rgb),.3);
    transform: translateY(-140%); transition: transform .3s; align-items: stretch;
    /* The panel is position:fixed, so anything past the viewport bottom cannot
       be scrolled to by the page — it is simply unreachable. Surfacing Find a
       Mentor and Worldwide Map pushed the panel to ~666px, which put "Contact"
       off the bottom of a 390x664 phone. Same failure the account menu had.
       svh, not vh: the SMALL viewport, i.e. iOS Safari with its toolbars
       showing, and unlike dvh it won't resize mid-scroll. */
    max-height: calc(100vh - 72px);
    max-height: calc(100svh - 72px);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .nav__links.open { transform: translateY(0); }
  .nav__links a { padding: .9rem 8vw; font-size: 1rem; }
  .nav__links a::after { display: none; }   /* underline sweep is for the desktop row */
  .nav__links .nav__cta { margin: .6rem 8vw; text-align: center; }
  .nav__toggle { display: block; }
  .nav__account { margin-left: auto; margin-right: .6rem; }

  /* Nothing collapses on a phone. The panel is already a vertical column here,
     so the group becomes a labelled sub-list with all six always visible — a
     brother who doesn't know the group exists would never think to tap it. */
  .nav__group { position: static; }
  .nav__group-btn {
    display: block; width: 100%; text-align: left; pointer-events: none;
    padding: 1rem 8vw .3rem; color: var(--on-navy-3);
    font-size: .72rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  }
  .nav__group-btn .nav__caret { display: none; }
  .nav__group-menu {
    position: static; transform: none; display: block; background: none;
    box-shadow: none; border-radius: 0; min-width: 0;
    padding: 0 0 0 .8rem; margin: 0 8vw .5rem;
    border-left: 2px solid rgba(var(--gold-rgb),.3);
  }
  .nav__group-menu::before { display: none; }
  .nav__group-menu a { padding: .7rem .5rem; font-size: 1rem; color: var(--on-navy-2); }
  .nav__group-menu a:hover { background: none; color: var(--gold-bright); }
  .nav__group-menu a.on { color: var(--gold-bright); }
}

@media (max-width: 620px) {
  .brand img { height: 44px; }
  .brand__txt { font-size: 1.45rem; }
  .brand__txt small { font-size: .52rem; letter-spacing: .16em; }
}

/* ---- Phone header: make the row actually fit -------------------------------
   On a ~428px phone the row wanted ~417px of the ~394px available: the brand
   subtitle ("EST. 1996 · GENESEO", ~140px) and the ADMIN text badge (~55px)
   overflowed it, shoving the hamburger off the right edge entirely (so the nav
   links were unreachable) and clipping the account chip. Trim to the essentials
   — crest + ΚΔΧ, theme, bell, avatar, hamburger — and everything fits with room
   to spare. Nothing is lost: the subtitle is on the hero, and the dropdown still
   shows the "★ Admin" role pill. */
@media (max-width: 620px) {
  .nav__inner { gap: .35rem; flex-wrap: nowrap; }
  .brand { gap: .5rem; min-width: 0; flex: none; }
  .brand img { height: 38px; }
  .brand__txt { font-size: 1.25rem; }
  .brand__txt small { display: none; }
  .theme-toggle { width: 40px; height: 40px; margin-right: .1rem; }
  .bell { margin-right: .15rem; }
  .bell__btn { width: 40px; height: 40px; font-size: .95rem; }
  .bell ~ .nav__account { margin-left: .2rem; }
  .nav__chip { padding: .22rem .4rem; gap: .35rem; }
  .nav__chip .admin-badge { display: none; }
  .nav__toggle { flex: none; padding: 8px 7px; margin-left: .25rem; }
}

/* Roomier, easier-to-tap mobile menu rows. */
@media (max-width: 1023px) {
  .nav__links a { padding: 1rem 8vw; border-bottom: 1px solid rgba(var(--gold-rgb),.10); }
  .nav__links a:last-of-type { border-bottom: 0; }
}

/* Below the breakpoint .nav__links is position:fixed and leaves the flow, so the
   bell (a sibling injected before .nav__account) would drift left beside the
   brand. Push the bell right; the chip then tucks in beside it. */
@media (max-width: 1023px) {
  .bell { margin-left: auto; }
  .bell ~ .nav__account { margin-left: .35rem; }
  .nav__toggle { margin-left: .4rem; }
}

/* Crossing the hamburger breakpoint flips .nav__links to position:fixed with
   translateY(-140%). Because transform is transitioned, the menu visibly slid
   up out of view — a split-second flash of the whole menu on every resize.
   Only allow the animation once the layout has settled (class set by JS). */
@media (max-width: 1023px) {
  .nav__links { transition: none; }
  .nav-anim .nav__links { transition: transform .3s; }
}


/* ============================================================================
   THEME TOKENS — light aliases the existing palette; [data-theme="dark"] is a
   full BLACK + GOLD identity (not a dimmed navy). Backgrounds go black, the
   navy chrome family + --chrome go black, and text flips to a legible gold.
   ============================================================================ */
:root {
  --bg:        var(--cream);
  --bg-2:      var(--cream-2);
  --surface:   var(--white);
  --surface-2: var(--paper);
  --heading:   var(--navy);
  --text:      var(--ink);
  --hairline:  #e6ded0;
  --tint:      #fdf6e0;
  --chrome:    7, 22, 52;     /* nav / modals / overlays (navy in light) */
  --on-dark:   #cdd6e6;       /* body text that sits on navy sections */
  --scroll-track: #0A1F44;   /* solid NAVY channel — a transparent/near-white track read as clunky */
  /* Text + surfaces that sit ON navy-family backgrounds. The navy tokens go
     BLACK in dark mode, so anything painted on them must come from these
     tokens — never literal cream/blue-grey hex (it won't flip and reads
     white-on-black). --on-navy strong > --on-navy-2 secondary > --on-navy-3 muted. */
  --on-navy:   var(--cream);
  --on-navy-2: #d7deec;
  --on-navy-3: #93a4c2;
  --console-card-hi: #16294b;  /* console record-row / table gradient */
  --console-card-lo: #112240;
  --console-field:   #0f2143;  /* console inputs + navy dropdowns */
  --console-panel:   #ece4d2;  /* warm parchment cards on the navy console (was stark #FBF8F1) */
}
:root[data-theme="dark"] {
  /* True neutral black. The page stays essentially dead black; the separation
     between page and cards comes from lifting the CARDS, not from greying out
     the background — so the deep-black look survives on OLED. */
  --bg:        #050505;   /* page — still reads as pure black */
  --bg-2:      #0b0b0b;   /* alternating band sections */
  --surface:   #151515;   /* cards: lifted enough to show an edge */
  --surface-2: #1f1f1f;   /* inputs / nested panels */
  /* text -> gold family (high contrast on black) */
  --heading:   #f3d16b;   /* bright gold headings/titles */
  --text:      #ecdcaa;   /* pale gold body copy — legible */
  --muted:     #b19b64;   /* dim gold for secondary text */
  --on-dark:   #e8d8ab;   /* pale gold on the (now black) navy sections */
  /* the navy chrome family -> black */
  --navy:      #0b0b0b;
  --navy-2:    #131313;
  --navy-deep: #000000;
  --chrome:    8, 8, 8;    /* nav bar, modal scrims, overlays -> near-black */
  /* The *-rgb tint triplets are deliberately NOT redefined here: dark mode has
     always built its subtle glows from the light-mode brand colors (they were
     hardcoded literals before tokenization), and flipping them to the near-black
     dark surfaces would erase every border and shadow. Re-theming a chapter?
     Change the triplets in the top :root block only. */
  /* keep gold accents; hairlines + tints go gold */
  --gold:        #C8A24B;   --gold-rgb: 200,162,75;
  --gold-bright: #EAC873;
  --gold-deep:   #C8A24B;   /* no light-mode override existed → gold-deep text was too dim on the black console */
  --hairline:  rgba(var(--gold-rgb),.24);
  --tint:      rgba(var(--gold-rgb),.12);
  --shadow:    0 20px 55px rgba(0,0,0,.75);
  --shadow-sm: 0 8px 22px rgba(0,0,0,.6);
  --shadow-md: 0 14px 38px rgba(0,0,0,.68);
  --danger:    #e58a80;   /* the light-mode reds read 2.8-3.5:1 on black — this is 7.2:1 */
  --danger-bg: #b4342b;   /* fills keep the deep red so white text on them still passes */
  --scroll-track: #14110a;   /* near-black channel in dark mode; thumb stays gold */
  /* on-navy family -> gold text on the now-black navy surfaces */
  --on-navy:   #ecdcaa;
  --on-navy-2: #e8d8ab;
  --on-navy-3: #b19b64;
  --console-card-hi: #161616;  /* lifted blacks, matching the dark card identity */
  --console-card-lo: #101010;
  --console-field:   #191919;
  --console-panel:   #1a1712;  /* subtly-warm lifted dark; ≈ old #151515 so dark barely shifts */
  color-scheme: dark;
}
:root[data-theme="dark"] body { background: var(--bg); color: var(--text); }

/* hard-coded surfaces the tokens can't reach */
:root[data-theme="dark"] input,
:root[data-theme="dark"] select,
:root[data-theme="dark"] textarea {
  color: var(--text);
  /* M8: the .24 hairline read at 1.46:1 — a control's only boundary needs 3:1. */
  border-color: rgba(var(--gold-rgb),.45);
  /* background-color, NOT the shorthand: the shorthand also resets
     background-image, which silently deleted the chevron on every
     appearance:none select (.fam-select, .zselect) in dark mode. */
  background-color: var(--surface-2);
}
:root[data-theme="dark"] .nav__links a { color: var(--on-dark); }
:root[data-theme="dark"] .nav__menu { background: #0d0d0d; border-color: rgba(var(--gold-rgb),.4); }
:root[data-theme="dark"] .nav__menu a, :root[data-theme="dark"] .nav__menu button { color: var(--on-dark); }
:root[data-theme="dark"] .nav__menu-head { background: linear-gradient(135deg, #1f1f1f, #050505 70%); }
:root[data-theme="dark"] .tree-viewport,
:root[data-theme="dark"] .tree-shell--full .tree-viewport {
  background: radial-gradient(circle at 50% 0%, #161616, #050505);
}
/* Cards get their edge from a box-shadow, which is invisible against black.
   The lifted --surface does most of the work; a faint hairline finishes it. */
:root[data-theme="dark"] .value,
:root[data-theme="dark"] .card-form,
:root[data-theme="dark"] .event,
:root[data-theme="dark"] .ev-card,
:root[data-theme="dark"] .thread-row,
:root[data-theme="dark"] .thread-view,
:root[data-theme="dark"] .stat-card,
:root[data-theme="dark"] .stat-list,
:root[data-theme="dark"] .guide-sec,
:root[data-theme="dark"] .welcome-step,
:root[data-theme="dark"] .welcome-card,
:root[data-theme="dark"] .welcome-note,
:root[data-theme="dark"] .spot-card,
:root[data-theme="dark"] .poll-card,
:root[data-theme="dark"] .cal-detail__ev,
:root[data-theme="dark"] .admin-card,
:root[data-theme="dark"] .admin-msg,
:root[data-theme="dark"] .admin-row,
:root[data-theme="dark"] .treeed-list,
:root[data-theme="dark"] .bell__menu,
:root[data-theme="dark"] .gmodal__card { border: 1px solid var(--hairline); }

/* The step circle is --navy, and the navy tokens flip to black in dark mode — so
   it came out DARKER than the near-black card it sits on and the number all but
   disappeared. A gold wash keeps the existing gold numeral readable.
   KEEP THIS RULE BELOW the list above: a CSS comment does NOT terminate a selector
   list, so parking it mid-list silently hands this gold wash to every selector in
   it (that regression shipped in 508aac0 and washed out the profile modal). */
:root[data-theme="dark"] .welcome-step__n { background: rgba(var(--gold-rgb),.18); }

/* Controls that borrowed navy for their border would vanish on a black card. */
:root[data-theme="dark"] .fam-chip,
:root[data-theme="dark"] .ev-toggle button,
:root[data-theme="dark"] .ev-rsvp__btn,
:root[data-theme="dark"] .tree-controls button,
:root[data-theme="dark"] .tree-node,
:root[data-theme="dark"] .btn--navy { border-color: rgba(var(--gold-rgb),.35); }
:root[data-theme="dark"] .tree-links path { stroke: var(--gold); opacity: .85; }
:root[data-theme="dark"] .cal-chip--meeting { background: #2a2410; }
:root[data-theme="dark"] .gmodal, :root[data-theme="dark"] .pmodal,
:root[data-theme="dark"] .bmodal, :root[data-theme="dark"] .admin-modal { background: rgba(0,0,0,.72); }
/* a soft gold halo lifts the crest off the black hero */
:root[data-theme="dark"] .hero__crest-img {
  filter: drop-shadow(0 0 34px rgba(var(--gold-rgb),.18)) drop-shadow(0 18px 46px rgba(0,0,0,.6));
}

/* the theme toggle button in the nav */
.theme-toggle {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  border: 1px solid rgba(var(--gold-rgb),.45); background: rgba(255,255,255,.08);
  color: var(--gold-bright); font-size: 1rem; cursor: pointer; line-height: 1;
  display: grid; place-items: center; margin-right: .4rem; transition: background .15s, transform .15s;
}
.theme-toggle:hover { background: rgba(var(--gold-rgb),.2); transform: translateY(-1px); }
@media (max-width: 460px) { .theme-toggle { width: 40px; height: 40px; margin-right: .25rem; } }
/* Console topbar: push the toggle to the right, beside the back pill. */
.admin-topbar .theme-toggle { margin-left: auto; margin-right: .8rem; }
/* Pages with no header at all (404): float it in the corner. */
.theme-toggle--fixed { position: fixed; top: 1rem; right: 1rem; z-index: 100; }

/* Gallery viewer: step between photos without closing it. Sits on the photo,
   so it takes the on-navy tokens rather than the page text colour. */
.gmodal__nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 4;
  width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid rgba(var(--gold-rgb),.45); background: rgba(var(--chrome), .62);
  color: var(--on-navy); font-size: 1.6rem; line-height: 1; cursor: pointer;
  display: grid; place-items: center; padding: 0 0 3px;
  transition: background .15s, border-color .15s, opacity .15s;
}
.gmodal__nav:hover { background: rgba(var(--chrome), .85); border-color: var(--gold-bright); }
.gmodal__nav--prev { left: 10px; }
.gmodal__nav--next { right: 10px; }
.gmodal__nav[hidden] { display: none; }
/* Immersive mode is a deliberately bare photo — the arrows would fight it. */
.gmodal--immersive .gmodal__nav { opacity: 0; pointer-events: none; }
@media (max-width: 560px) { .gmodal__nav { width: 38px; height: 38px; font-size: 1.35rem; } }

/* ============================================================================
   SCROLL ANIMATIONS — reveal-on-scroll, staggered cascades, section-title
   line-wipe, medal "stamp", hero entrance + parallax, and a scroll-progress
   bar. All motion is opt-in behind <html class="fx">, which an inline head
   snippet sets ONLY when the visitor allows motion. No .fx => everything is
   static and fully visible, so no-JS and reduced-motion users never see a
   blank or hidden element. GPU-only (transform/opacity) to stay jank-free.
   ============================================================================ */

/* thin gold progress bar across the top; fills with page scroll */
.scroll-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 300;
  transform: scaleX(0); transform-origin: 0 50%; pointer-events: none;
  background: linear-gradient(90deg, var(--gold), var(--gold-bright));
}
@supports (animation-timeline: scroll()) {
  .fx .scroll-progress { animation: sp-grow linear both; animation-timeline: scroll(root); }
}
@keyframes sp-grow { to { transform: scaleX(1); } }

/* reveal-on-scroll: hidden until JS adds .in when the element enters view */
.fx .reveal {
  opacity: 0; transform: translateY(20px);
  transition: opacity .7s cubic-bezier(.2,.7,.2,1), transform .7s cubic-bezier(.2,.7,.2,1);
}
.fx .reveal--left  { transform: translateX(-42px); }
.fx .reveal--right { transform: translateX(42px); }
.fx .reveal.in { opacity: 1; transform: none; }
/* On phones the horizontal slide-in pokes ~30px past the right edge (a ~360px block
   at translateX(42px)) → page-level horizontal scroll. Split halves stack vertically
   here anyway, so drop the sideways offset and keep only the vertical rise. */
@media (max-width: 640px) {
  .fx .reveal--left, .fx .reveal--right { transform: translateY(20px); }
}

/* staggered group: direct children cascade in, offset by their --i index */
.fx .stagger > * {
  opacity: 0; transform: translateY(22px);
  transition: opacity .6s cubic-bezier(.2,.7,.2,1), transform .6s cubic-bezier(.2,.7,.2,1);
  transition-delay: calc(var(--i, 0) * 85ms);
}
.fx .stagger.in > * { opacity: 1; transform: none; }

/* section-title rule wipes open once its header is revealed */
.fx .reveal .rule { transform: scaleX(0); transform-origin: 0 50%; transition: transform .8s cubic-bezier(.2,.7,.2,1) .15s; }
.fx .reveal.in .rule { transform: scaleX(1); }

/* award medals: the seal "stamps" in with a slight overshoot */
.fx .medals.in .medal__seal { animation: seal-stamp .6s cubic-bezier(.2,.9,.3,1.25) both; animation-delay: calc(var(--i, 0) * 90ms + .12s); }
@keyframes seal-stamp { 0% { transform: scale(.5); } 55% { transform: scale(1.08); } 100% { transform: scale(1); } }

/* hero: headline / tagline / CTAs rise in on load, staggered */
.fx .hero__text > * { opacity: 0; animation: hero-rise .9s cubic-bezier(.2,.7,.2,1) both; }
.fx .hero__kicker { animation-delay: .10s; }
.fx .hero__text h1 { animation-delay: .24s; }
.fx .hero__rule { animation-delay: .38s; }
.fx .hero__tag { animation-delay: .50s; }
.fx .hero__cta { animation-delay: .62s; }
@keyframes hero-rise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }

/* hero parallax — desktop only, where the browser supports scroll timelines */
@supports (animation-timeline: view()) {
  @media (min-width: 900px) {
    .fx .hero__crest-col { animation: hero-parallax linear both; animation-timeline: scroll(root); animation-range: 0 70vh; }
    @keyframes hero-parallax { to { transform: translateY(-46px); } }
  }
}

/* ============================================================================
   Skeleton loaders — placeholder shimmer shown while a view's data fetches,
   then swapped for the real cards. Skeleton markup REUSES the component classes
   (.bro-card / .ggrid__cell / .thread-row / .admin-row) so the layout matches
   exactly; .sk just paints the shimmer. Decorative — always aria-hidden.
   ============================================================================ */
.sk { position: relative; overflow: hidden; background: rgba(130,142,164,.20); border-radius: 8px; }
.sk::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.13), transparent);
  transform: translateX(-100%); animation: sk-shimmer 1.25s ease-in-out infinite;
}
.sk-line { display: block; height: .72em; margin: .4em 0; }
:root[data-theme="dark"] .sk { background: rgba(200,210,230,.10); }
[aria-hidden="true"].sk-wrap, .sk-wrap[aria-hidden="true"] { pointer-events: none; }
@keyframes sk-shimmer { 100% { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .sk::after { animation: none; } }

/* ============================================================================
   🎓 Pledge Classes tab (admin console) — summary line, ⚠️ flags, bulk merge bar.
   Rows reuse .admin-row, so only these three bits are new.
   ============================================================================ */
.cls-sum { color: var(--on-dark); font-size: .9rem; margin: 0 0 .9rem; }
.cls-warn { color: #ffcf6b; }
.admin-row__when.cls-warn { color: #ffcf6b; }
/* Pending vet: a signup name the chapter roster doesn't recognize. */
.admin-row__when.admin-flag { color: #e59a9a; font-weight: 600; }
.cls-bulk {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  margin: .6rem 0 1.2rem; padding: .7rem .8rem;
  border: 1px solid rgba(var(--gold-rgb),.28); border-radius: 10px; background: var(--navy);
}
.cls-bulk label { color: var(--gold-bright); font-size: .85rem; font-weight: 600; }
.cls-bulk .form-note { margin: 0; }

/* ===========================================================================
   Brother of the Month — the vote for next month (upgrade67)
   Sits under the spotlight on the homepage, members only. Percentages are live
   by the owner's decision; the ballot itself is never rendered here.
   =========================================================================== */
.botm {
  max-width: 620px; margin: 0 auto; text-align: left;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius); padding: 1.4rem 1.4rem 1.15rem;
  box-shadow: var(--shadow-sm);
}
.botm__head h3 {
  font-family: var(--display); font-size: 1.28rem; color: var(--heading);
  margin: 0 0 .18rem;
}
.botm__meta { margin: 0 0 1rem; font-size: .86rem; color: var(--muted); }

.botm__list { display: flex; flex-direction: column; gap: .45rem; }

.botm-row {
  display: flex; align-items: center; gap: .8rem; width: 100%;
  padding: .55rem .65rem; border: 1px solid transparent; border-radius: 10px;
  background: var(--surface-2); cursor: pointer; text-align: left; font: inherit;
  transition: border-color .14s, background .14s, transform .14s;
}
.botm-row:hover { border-color: var(--gold); transform: translateX(2px); }
.botm-row:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.botm-row.is-mine { border-color: var(--gold); background: var(--tint); }

.botm-row__pic {
  width: 42px; height: 42px; border-radius: 50%; object-fit: cover; flex: none;
  border: 2px solid var(--hairline);
}
.botm-row__pic--none {
  display: flex; align-items: center; justify-content: center;
  background: var(--navy); color: var(--gold-bright);
  font-family: var(--display); font-size: 1.05rem;
}
.botm-row__body { flex: 1; min-width: 0; }
.botm-row__name {
  display: block; font-weight: 600; color: var(--heading); font-size: .95rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.botm-row__name em { color: var(--gold-deep); font-style: normal; font-weight: 500; font-size: .84rem; }
.botm-row__sub { display: block; font-size: .78rem; color: var(--muted); margin-bottom: .3rem; }
.botm-row__bar { display: block; height: 6px; border-radius: 999px; background: var(--hairline); overflow: hidden; }
.botm-row__bar > span { display: block; height: 100%; background: var(--gold); border-radius: 999px; transition: width .3s ease; }
.botm-row__pct {
  flex: none; min-width: 46px; text-align: right;
  font-family: var(--display); font-size: 1.02rem; color: var(--gold-deep); font-weight: 600;
}

.botm__pick { margin-top: 1rem; }
.botm__pick label { display: block; font-size: .82rem; color: var(--muted); margin-bottom: .3rem; }
.botm__pick select {
  width: 100%; padding: .55rem .6rem; border-radius: 9px;
  border: 1px solid var(--hairline); background: var(--surface-2); color: var(--text); font: inherit;
}
.botm__note { margin: .85rem 0 0; font-size: .8rem; color: var(--muted); }

/* The spotlight card can now feature a brother with no photo — the vote may elect one. */
.spot-card__photo--none {
  display: flex; align-items: center; justify-content: center;
  background: var(--navy); color: var(--gold-bright); font-size: 2.4rem;
}

@media (max-width: 560px) {
  .botm { padding: 1.1rem 1rem 1rem; }
  .botm-row { gap: .6rem; padding: .5rem .45rem; }
  .botm-row__pic { width: 36px; height: 36px; }
  .botm-row__pct { min-width: 40px; font-size: .95rem; }
}

/* Brother of the Month — the admin/officer side. Painted on the console's navy chrome,
   so every colour here is a theme token: the navy family flips to black in dark mode and
   a literal hex would render invisible or off-identity. */
.botm-admin__list { display: flex; flex-direction: column; gap: .5rem; margin-top: .7rem; }
.botm-admin__row {
  display: flex; align-items: center; gap: .8rem;
  padding: .55rem .7rem; border-radius: 10px;
  background: linear-gradient(180deg, var(--console-card-hi), var(--console-card-lo));
  border: 1px solid rgba(var(--gold-rgb),.22);
}
.botm-admin__name { flex: 0 0 34%; color: var(--on-navy); font-weight: 600; font-size: .92rem; }
.botm-admin__warn { color: var(--on-navy-3); font-style: normal; font-weight: 400; font-size: .8rem; }
.botm-admin__bar {
  flex: 1; height: 8px; border-radius: 999px;
  background: var(--console-field); overflow: hidden;
}
.botm-admin__bar > span { display: block; height: 100%; background: var(--gold); border-radius: 999px; }
.botm-admin__pct {
  flex: none; min-width: 82px; text-align: right;
  color: var(--gold-bright); font-size: .88rem; font-weight: 600;
}
@media (max-width: 640px) {
  .botm-admin__row { flex-wrap: wrap; }
  .botm-admin__name { flex: 1 1 100%; }
  .botm-admin__pct { min-width: 70px; }
}

/* ===========================================================================
   Edit a brother from his card (upgrade68) — shown only to the admin and to an
   officer holding members.edit.
   =========================================================================== */
.bm__edit { margin-top: 1rem; padding-top: .9rem; border-top: 1px solid var(--hairline); }
.bm__edit-btn { width: 100%; }

/* Standing badge + the active-mentor warning in the console's Mentoring tab.
   Painted on navy chrome, so these are theme tokens — the navy family flips to
   black in dark mode and a literal hex would go invisible or off-identity. */
.mtg-standing {
  display: inline-block; margin-left: .45rem; padding: .1rem .45rem;
  border-radius: 999px; font-size: .72rem; font-weight: 600; letter-spacing: .02em;
  background: var(--console-field); color: var(--on-navy-2);
  border: 1px solid rgba(var(--gold-rgb),.22); vertical-align: middle;
}
.mtg-standing--active { color: var(--gold-bright); border-color: rgba(var(--gold-rgb),.5); }
.mtg-warn {
  display: block; margin-top: .3rem; font-size: .78rem; color: var(--gold-bright);
}
