/* =====================================================================
   FOUND MEN HUB — application styles
   Built to the Claude Design handoff. Mobile-first; the column simply
   widens to --content-max on larger screens. Warm, calm, low-pressure.
   ===================================================================== */

/* ---------- base / reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: transparent; }
body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--text-body);
  background: var(--surface-page);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* IMP-178: emoji must not lean.
     A man's own words are quoted in italics all over the app - the feed card,
     the chat list, search results, a host's note. The emoji font has no italic
     face, so the browser was FAKING one by shearing the glyph sideways, which
     is why the laughing face in the feed card looked like it was falling over.
     Every font in --font-sans is a system face with real italics, so switching
     synthesis off changes nothing for the words and stops the shear on the
     emoji. Set here so it reaches the cards drawn in JavaScript too. */
  font-synthesis-style: none;
}
h1, h2, h3, h4 { font-family: var(--font-display); color: var(--text-strong); line-height: var(--leading-tight); margin: 0; }
p { margin: 0; text-wrap: pretty; }
a { color: var(--text-link); text-decoration: none; }
button { font-family: inherit; cursor: pointer; }
input, textarea, select { font-family: inherit; }
i[data-lucide] { display: inline-flex; vertical-align: middle; }

/* type specimens */
.t-eyebrow { font-size: var(--text-caption); font-weight: var(--weight-bold); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--text-muted); }
.t-muted   { color: var(--text-muted); }
.t-subtle  { color: var(--text-subtle); }

/* ---------- app shell ---------- */
.fmh-app {
  max-width: var(--content-max);
  margin: 0 auto;
  min-height: 100vh;
  background: var(--surface-page);
  position: relative;
}
.fmh-main {
  padding: var(--space-4);
  padding-bottom: calc(var(--tabbar-h) + var(--space-12) + env(safe-area-inset-bottom, 0px));
}
.fmh-main.flush { padding-left: 0; padding-right: 0; }

/* sections */
.fmh-section-label {
  font-size: var(--text-caption); font-weight: var(--weight-bold);
  letter-spacing: 0.07em; text-transform: uppercase; color: var(--text-muted);
}

/* ---------- brand mark (three bars) ---------- */
.fmh-mark { display: inline-flex; flex-direction: column; gap: 3px; }
.fmh-mark span { height: 4px; border-radius: 2px; background: var(--color-brand); display: block; }
.fmh-mark span:nth-child(1) { width: 100%; }
.fmh-mark span:nth-child(2) { width: 74%; }
.fmh-mark span:nth-child(3) { width: 48%; }

/* ---------- top bar ---------- */
.fmh-topbar {
  position: sticky; top: 0; z-index: 30;
  background: var(--surface-card);
  border-bottom: 1px solid var(--border-hairline);
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px var(--space-4) 12px;
}
.fmh-topbar .brand-lockup { display: flex; align-items: center; gap: 11px; }
.fmh-topbar .brand-name { font-weight: var(--weight-display); font-size: var(--text-h3); letter-spacing: -0.01em; color: var(--text-strong); }
.fmh-topbar .brand-name a { color: inherit; }
.fmh-topbar .actions { display: flex; align-items: center; gap: 6px; }

/* page header (back + title) */
.fmh-pagebar {
  position: sticky; top: 0; z-index: 30;
  background: var(--surface-card);
  border-bottom: 1px solid var(--border-hairline);
  display: flex; align-items: center; gap: var(--space-2);
  padding: 6px var(--space-3) 10px;
}
.fmh-pagebar .title { font-weight: var(--weight-display); font-size: var(--text-h3); color: var(--text-strong); flex: 1; min-width: 0; }
.fmh-pagebar .title.big { font-size: var(--text-h2); }
/* IMP-185: when the title IS a link it must not look like one - same colour,
   same weight, no underline, no visited state. Inheriting is not enough here
   because the base `a` rule sets a link colour, so the colour is restated.
   The only tell is that it dims while held, which is what every other tappable
   thing in the app does and is nothing at all until a man touches it. */
.fmh-pagebar .title a { color: inherit; text-decoration: none; }
.fmh-pagebar .title a:visited { color: inherit; }
.fmh-pagebar .title a:active { opacity: 0.6; }
/* breadcrumb extras — hidden on mobile (plain back arrow + title only) */
.fmh-pagebar .pb-crumb, .fmh-pagebar .pb-sep { display: none; }
/* Pages that show BOTH bars (the leaders console, notifications) keep the brand bar
   pinned and let the title bar scroll away — two stacked sticky headers would overlap. */
.fmh-topbar + .fmh-pagebar { position: static; }

/* title row on a top-level page - see page_heading() in ui.php */
.fmh-pagehead { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: var(--touch-min); margin-bottom: 12px; }
.fmh-pagehead h1 { font-size: 21px; min-width: 0; }
.fmh-pagehead .ph-actions { display: flex; align-items: center; gap: 2px; flex: none; }
/* IMP-159: Contacts' Interests button - its icons stacked, one showing, cross-fading */
.dir-int-btn .int-cycle { position: relative; display: inline-block; width: 17px; height: 17px; flex: none; }
.dir-int-btn .int-cycle .ic { position: absolute; inset: 0; display: flex; opacity: 0; transform: scale(.8); transition: opacity .5s ease, transform .5s ease; }
.dir-int-btn .int-cycle .ic.on { opacity: 1; transform: none; }
.dir-int-btn .int-cycle svg, .dir-int-btn .int-cycle i { width: 17px; height: 17px; }

/* ---------- icon button ---------- */
.fmh-iconbtn {
  width: var(--touch-min); height: var(--touch-min);
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: none; color: var(--text-body);
  border-radius: var(--radius-pill); flex: none; transition: background .15s ease;
}
.fmh-iconbtn:hover { background: var(--btn-ghost-bg-hover); }
/* A toggle that is currently ON - the pin in a chat's title bar. Lit rather
   than merely darker, so "pinned" reads at a glance and not on inspection. */
.fmh-iconbtn.on { color: var(--color-brand); background: var(--color-brand-soft); }
.fmh-iconbtn.on:hover { background: var(--color-brand-soft); box-shadow: var(--ring-brand); }
.fmh-iconbtn.primary { background: var(--btn-primary-bg); color: var(--btn-primary-fg); }
.fmh-iconbtn.primary:hover { background: var(--btn-primary-bg-hover); }

/* bell with badge */
.fmh-bell { position: relative; }
.fmh-bell .badge {
  position: absolute; top: 5px; right: 5px;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--radius-pill);
  background: var(--color-brand); color: #fff;
  font-size: 11px; font-weight: var(--weight-bold);
  display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid var(--surface-card);
}

/* ---------- avatar ---------- */
.fmh-avatar {
  border-radius: var(--radius-pill);
  background: var(--avatar-bg); color: var(--avatar-fg);
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: var(--weight-bold); flex: none; position: relative;
  overflow: visible; text-decoration: none;
}
.fmh-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
.fmh-avatar.xs { width: var(--avatar-xs); height: var(--avatar-xs); font-size: 10px; }
.fmh-avatar.sm { width: var(--avatar-sm); height: var(--avatar-sm); font-size: 12px; }
.fmh-avatar.md { width: var(--avatar-md); height: var(--avatar-md); font-size: var(--text-small); }
.fmh-avatar.lg { width: var(--avatar-lg); height: var(--avatar-lg); font-size: var(--text-h3); }
.fmh-avatar.xl { width: var(--avatar-xl); height: var(--avatar-xl); font-size: var(--text-h1); }
.fmh-avatar .status {
  position: absolute; right: -1px; bottom: -1px;
  width: 32%; height: 32%; min-width: 10px; min-height: 10px;
  border-radius: var(--radius-pill); border: 2px solid var(--surface-card);
}
.fmh-avatar .status.free   { background: var(--color-success); }
.fmh-avatar .status.busy   { background: var(--color-warning); }
.fmh-avatar .status.offline{ background: var(--grey-300); }

/* ---------- cards ---------- */
.fmh-card {
  background: var(--card-bg);
  border-radius: var(--radius-lg);
  box-shadow: var(--elevation-1);
  padding: var(--space-4);
}
.fmh-card.bordered { box-shadow: none; border: 1px solid var(--card-border); }
.fmh-card.panel { background: var(--surface-panel); box-shadow: var(--elevation-2); }
a.fmh-card, button.fmh-card { display: block; width: 100%; text-align: left; border: 1px solid var(--card-border); box-shadow: var(--elevation-1); transition: box-shadow .15s ease, transform .05s ease; }
a.fmh-card:hover, button.fmh-card:hover { box-shadow: var(--elevation-2); }
a.fmh-card:active, button.fmh-card:active { transform: scale(0.99); }

/* IMP-123: a card whose meet-up is today or tomorrow. The notification body is
   frozen at write time and cannot say so, so the card says it instead. Border
   rather than a tinted background - the list already uses background for the
   per-type icon tile, and a second colour field would fight it.

   IMP-124: .fmh-card, not a.fmh-card - the meet-up outcome card is a div and
   would otherwise never show the border.

   These MUST sit after the a.fmh-card rules above. That block sets a default
   border at equal specificity, so declared earlier it would win on every
   notification card and the plum border would vanish. */
.fmh-card.is-imminent { border: 1px solid var(--color-brand); box-shadow: 0 0 0 1px var(--color-brand); }
a.fmh-card.is-imminent:hover { box-shadow: 0 0 0 1px var(--color-brand), var(--elevation-2); }
.fmh-card.is-cancelled { opacity: .72; }
/* IMP-171: a notification whose ask has already been dealt with. Same recede as
   a cancelled one — it stays readable and stays clickable, it just stops
   competing with the cards that still want something. */
.fmh-card.is-done { opacity: .72; }

/* IMP-125 double-booking. Amber, never red: a clash is information, not an
   error - two things at 7pm is sometimes a deliberate "coffee then the match".
   No specificity trap here (.fmh-pill.warn is 0-2-0 against .fmh-pill's 0-1-0,
   and .fmh-note is new), so unlike .is-imminent these are free to move. */
.fmh-pill.warn { color: var(--color-warning); background: var(--color-warning-soft); }
.fmh-pill.success { color: var(--color-success); background: var(--color-success-soft); }
.fmh-note { display: flex; gap: 9px; align-items: flex-start; padding: 10px 12px; border-radius: var(--radius-md); font-size: 13px; line-height: 1.45; color: var(--text-body); background: var(--surface-panel); }
.fmh-note i[data-lucide] { flex: none; margin-top: 1px; }
.fmh-note.warn { color: var(--color-warning); background: var(--color-warning-soft); }
.fmh-note.warn strong { color: var(--color-warning); }
.fmh-note[hidden] { display: none !important; } /* display:flex above outranks the UA [hidden] rule */

.fmh-stack { display: flex; flex-direction: column; gap: var(--space-3); }
.fmh-stack-lg { display: flex; flex-direction: column; gap: var(--space-6); }

/* ---------- buttons ---------- */
.fmh-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: var(--touch-min); padding: 0 var(--space-6);
  border: 1px solid transparent; border-radius: var(--radius-md);
  font-size: var(--text-small); font-weight: var(--weight-bold);
  text-decoration: none; transition: background .15s ease, box-shadow .15s ease, transform .05s ease;
}
.fmh-btn:active { transform: scale(0.97); }
.fmh-btn.sm { min-height: 40px; padding: 0 var(--space-4); font-size: 13.5px; }
.fmh-btn.full { width: 100%; }
.fmh-btn.primary { background: var(--btn-primary-bg); color: var(--btn-primary-fg); }
.fmh-btn.primary:hover { background: var(--btn-primary-bg-hover); }
.fmh-btn.secondary { background: var(--btn-secondary-bg); color: var(--btn-secondary-fg); border-color: var(--btn-secondary-border); }
.fmh-btn.secondary:hover { background: var(--btn-secondary-bg-hover); }
.fmh-btn.ghost { background: transparent; color: var(--btn-ghost-fg); }
.fmh-btn.ghost:hover { background: var(--btn-ghost-bg-hover); }
.fmh-btn.danger { background: var(--btn-danger-bg); color: var(--btn-danger-fg); }
.fmh-btn[disabled], .fmh-btn.disabled { opacity: .5; pointer-events: none; }

/* ---------- chips ---------- */
.fmh-chip {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 34px; padding: 0 var(--space-3);
  border-radius: var(--radius-pill); border: 1px solid var(--chip-border);
  background: var(--chip-bg); color: var(--chip-fg);
  font-size: 13px; font-weight: var(--weight-bold);
  text-decoration: none; transition: background .15s ease, color .15s ease, border-color .15s ease;
  white-space: nowrap;
}
.fmh-chip.sm { min-height: 28px; font-size: 12px; padding: 0 10px; }
.fmh-chip.selected { background: var(--chip-selected-bg); color: var(--chip-selected-fg); }
.fmh-chip.outline { background: var(--surface-card); border-color: var(--border-strong); color: var(--text-body); }
.fmh-chip.outline.on { background: var(--surface-panel); border-color: var(--border-brand); color: var(--color-brand); }
.fmh-chip .x { margin-left: 2px; opacity: .7; font-weight: var(--weight-bold); }

/* Interest tags on a chat. Visually distinct from the type chip beside them —
   a leading dot rather than an icon — so "Encouragement" (a fixed kind) and
   "Surfing" (a free tag) don't read as the same class of thing. */
.fmh-chip.tag::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: var(--color-brand); opacity: .55; flex: none;
}
.fmh-chip.tag.selected::before { background: currentColor; opacity: .8; }
/* A chip carrying its interest's own icon has no use for the dot — the icon
   already marks it as a free tag, and says which one. Kept as an opt-in class
   so the few chips with no interest id to hand still get the dot. */
.fmh-chip.tag.has-ico::before { display: none; }
.fmh-chip .chip-ico { flex: none; opacity: .8; }
.fmh-chip.selected .chip-ico { opacity: 1; }
/* The who-step filter modal drops the dot. In Chats a tag chip sits beside a
   type chip and the dot is what tells them apart; in that modal every chip
   under "Interests" is a tag, so the dot distinguished nothing and only added
   noise to a list meant to be scanned fast. Scoped, not deleted - the Chats
   use it still earns it. */
#who-filter-modal .fmh-chip.tag::before { display: none; }
a.fmh-chip.tag:hover { border-color: var(--border-brand); color: var(--color-brand); }
/* The two scope toggles at the top of Chats read as switches, not filters. */
.fmh-chip.toggle { border-color: var(--border-strong); }
.fmh-chip.toggle.selected { border-color: var(--chip-selected-bg); }
/* Chips wrapping a hidden checkbox (the tag pickers) must look tappable. */
label.fmh-chip { cursor: pointer; user-select: none; }
label.fmh-chip:hover { border-color: var(--border-brand); }
/* .fmh-chip sets display:inline-flex, which beats the UA's [hidden] rule — so
   the tag-search filter silently did nothing. Author rule needed to win back. */
.fmh-chip[hidden] { display: none !important; }

/* Description line under the type chips in the configure modal. */
.fmh-typedesc {
  font-size: 12.5px; color: var(--text-muted); line-height: 1.45;
  margin: 8px 2px 0; min-height: 18px;
}
/* Inline near-duplicate suggestions under the new-tag box. */
.fmh-dupe {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 10px; font-size: 12.5px;
}
/* display:flex beats the browser's own [hidden] rule, so the empty box sat
   there showing a bare "Did you mean:" with nothing after it until the dupe
   check had something to say. The attribute has to win. */
.fmh-dupe[hidden] { display: none; }
/* Second-chance prompt on a chat whose creator skipped the configure modal. */
.fmh-nudge {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 13px 15px; border-color: var(--border-brand);
}
.fmh-nudge-text { flex: 1 1 220px; min-width: 0; }
.fmh-nudge-title { font-weight: var(--weight-bold); color: var(--text-strong); font-size: 14px; }
.fmh-nudge-text p { margin: 3px 0 0; font-size: 12.5px; color: var(--text-muted); line-height: 1.45; }
.fmh-nudge-acts { display: flex; gap: 8px; align-items: center; margin-left: auto; }
.fmh-nudge-acts form { margin: 0; }
.fmh-chips { display: flex; gap: var(--space-2); flex-wrap: wrap; }
/* IMP-129: the who-step filter icon, sat beside the men search box. Boxed to
   match the input's height and border so the two read as one control strip -
   a bare icon floating next to a bordered field looks like a mistake. */
.wz-filter-btn {
  flex: none; width: 46px; height: 46px; box-sizing: border-box;
  align-self: center; vertical-align: top;
  border: 1px solid var(--input-border); border-radius: var(--radius-md);
  background: var(--input-bg);
}
/* The badge ring is drawn in --surface-card by .fmh-bell, but this button sits
   on the input fill - without this the ring reads as a render fault. */
.wz-filter-btn .badge { border-color: var(--input-bg); }
/* The same count on the open-invitation button, which is a text button rather
   than an icon - so the badge rides inline instead of on a corner. */
.wz-openbadge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; margin-left: 7px; padding: 0 5px;
  border-radius: 9px; background: var(--color-brand); color: #fff;
  font-size: 11px; font-weight: var(--weight-bold); line-height: 1;
}
.fmh-chips.scroll { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 2px; -ms-overflow-style: none; scrollbar-width: none; }
.fmh-chips.scroll::-webkit-scrollbar { display: none; }

/* favourite star inside a "where" location pill */
.loc-star { background: none; border: 0; padding: 0 0 0 4px; margin-left: 2px;
  display: inline-flex; align-items: center; line-height: 0;
  color: var(--text-subtle); cursor: pointer; transition: color .15s ease; }
.loc-star.on { color: var(--color-brand); }
.loc-star.on svg { fill: currentColor; }

/* location autocomplete dropdown */
.loc-suggest { position: fixed; z-index: 1100;
  background: var(--surface-card); border: 1px solid var(--border-hairline);
  border-radius: var(--radius-md); box-shadow: var(--elevation-2, 0 6px 20px rgba(0,0,0,.10));
  max-height: 240px; overflow: auto; }
.loc-suggest[hidden] { display: none; }
.loc-suggest-item { display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: 10px 14px; font-size: 15px; color: var(--text-strong); cursor: pointer; }
.loc-suggest-item:hover { background: var(--surface-panel); }
/* venues found on the map, listed under the shared pool */
.loc-suggest-head { padding: 9px 14px 4px; font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--text-subtle);
  border-top: 1px solid var(--border-hairline); margin-top: 4px; }
.loc-suggest-item .loc-main { display: block; }
.loc-suggest-item .loc-sub  { display: block; font-size: 12.5px; color: var(--text-subtle);
  margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---------- chats: the three scope tabs ----------
   An underline bar rather than pills: pills at this width wrap onto two lines
   and read as separate switches, when they are one choice. */
.chat-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border-hairline); }
.chat-tab {
  flex: 1 1 0; min-width: 0; text-align: center;
  padding: 10px 4px 11px; margin-bottom: -1px;
  font-size: 13.5px; font-weight: 700; color: var(--text-muted);
  border-bottom: 2px solid transparent;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-decoration: none; transition: color .15s, border-color .15s;
}
.chat-tab:hover { color: var(--text-body); }
.chat-tab.on    { color: var(--color-brand); border-bottom-color: var(--color-brand); }

/* ---------- badges ---------- */
.fmh-badge {
  display: inline-flex; align-items: center; gap: 5px;
  height: 24px; padding: 0 10px; border-radius: var(--radius-pill);
  font-size: 12px; font-weight: var(--weight-bold);
}
.fmh-badge.brand   { background: var(--surface-panel); color: var(--color-brand); }
.fmh-badge.neutral { background: var(--surface-sunken); color: var(--text-muted); }
.fmh-badge.success { background: var(--color-success-soft); color: var(--color-success); }
.fmh-badge.warning { background: var(--color-warning-soft); color: var(--color-warning); }
.fmh-badge.info    { background: var(--color-info-soft); color: var(--color-info); }

/* A badge wrapped in a link (profile collection badges → filtered Contacts).
   The <a> is a bare wrapper so the pill keeps its own colours; only the hover
   lift marks it as tappable. */
.fmh-badge-link { display: inline-flex; text-decoration: none; }
.fmh-badge-link:hover .fmh-badge,
.fmh-badge-link:focus-visible .fmh-badge { filter: brightness(1.08); box-shadow: 0 0 0 1px var(--border-brand); }
a.fmh-chip:hover, a.fmh-chip:focus-visible { border-color: var(--border-brand); color: var(--color-brand); }

/* ---------- forms ---------- */
.fmh-field { margin-bottom: var(--space-4); }
.fmh-field label { display: block; font-size: var(--text-small); font-weight: var(--weight-bold); margin-bottom: var(--space-2); color: var(--text-strong); }
.fmh-input, .fmh-textarea {
  width: 100%; min-height: 46px; padding: 0 14px;
  border: 1px solid var(--input-border); border-radius: var(--radius-md);
  background: var(--input-bg); font-size: 15px; color: var(--text-strong);
  outline: none; transition: border-color .15s ease, box-shadow .15s ease;
}
.fmh-textarea { padding: 12px 14px; line-height: var(--leading-normal); resize: vertical; min-height: 110px; }
/* IMP-119. The padding above is "0 14px" because a single-line input centres its
   text inside the 46px min-height, so vertical padding would only fight that.
   On a textarea there is nothing to centre: the text starts at the top edge and
   sat flush against it. .fmh-textarea already corrects this, but eleven
   textareas across the app are marked .fmh-input instead — so fix it on the
   element rather than relabelling eleven call sites and hoping the twelfth
   remembers. min-height is reset because 46px is an input's height, not a
   textarea's; rows= should decide that, and did not while a min-height outranked it. */
textarea.fmh-input {
  padding: 12px 14px;
  min-height: 0;
  line-height: var(--leading-normal);
}
.fmh-input::placeholder, .fmh-textarea::placeholder { color: var(--input-placeholder); }
.fmh-input:focus, .fmh-textarea:focus { border-color: var(--input-border-focus); box-shadow: var(--ring-brand); }
.fmh-input.pill { border-radius: var(--radius-pill); }

/* ---------- chat composer (IMP-132) ----------
   A box that grows with what is written, rather than a one-line input that
   hides the start of a thought as it is being typed. The 40vh cap is the whole
   point of having a cap: past it the box scrolls inside itself, because a box
   that keeps growing pushes Send off the bottom of a phone — the one control
   the man actually needs to reach.
   resize is left vertical here and switched off by app.js, so the drag handle
   survives for anyone without JS while never fighting the auto-grow. */
.fmh-composer { margin-top: 16px; display: flex; flex-direction: column; gap: 9px; }
.fmh-composer-box {
  display: block; width: 100%;
  max-height: 40vh; overflow-y: auto;
  resize: vertical;
}
/* An @name reads as a name, not a URL: brand colour and weight, no underline
   until hover. It is a link to his profile, which is the thing a man actually
   wants after reading one. */
.fmh-mention {
  color: var(--color-brand); font-weight: 700; text-decoration: none;
}
.fmh-mention:hover { text-decoration: underline; }

/* The @ picker. Modelled on .fmh-menu (same surface, hairline and elevation)
   but positioned against the composer rather than right-aligned to a trigger,
   and capped so a big room scrolls instead of covering the message it is
   being written about. */
.fmh-atwrap { position: relative; }
.fmh-atbox {
  position: absolute; left: 0; right: 0; bottom: 100%; z-index: 60;
  margin-bottom: 6px; padding: 6px;
  background: var(--surface-card); border: 1px solid var(--border-hairline);
  border-radius: 14px; box-shadow: var(--elevation-3);
  max-height: 232px; overflow-y: auto;
  display: none; flex-direction: column;
}
.fmh-atbox.open { display: flex; }
/* IMP-139/140: on a touch screen the list docks to the top of the on-screen
   keyboard (app.js sets `top` from the visual viewport), full width. Three
   rows plus a sliver of the fourth, so it reads as scrollable while leaving
   the line being typed room above it. */
.fmh-atbox.docked {
  position: fixed; left: 8px; right: 8px; top: 0; bottom: auto;
  margin: 0; max-height: 158px; z-index: 300;
}
/* Touch browsers without visualViewport: in the flow above the box, where a
   keyboard cannot reach it. */
.fmh-atbox.inline { position: static; margin: 0; max-height: 158px; }
.fmh-atbox button {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  background: none; border: none; border-radius: 9px; cursor: pointer;
  text-align: left; width: 100%; color: var(--text-strong);
}
.fmh-atbox button:hover, .fmh-atbox button.active { background: var(--surface-page); }
.fmh-at-name { font-size: 14px; font-weight: 700; }
.fmh-at-user { font-size: 12px; color: var(--text-subtle); }
.fmh-at-pic {
  width: 28px; height: 28px; border-radius: 50%; flex: none; object-fit: cover;
  background: var(--surface-panel); color: var(--text-muted);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
}
/* IMP-187: the same round slot, holding an emoji rather than a man's initial,
   so the two lists sit on the same left edge. No fill behind it - a coloured
   glyph on a grey disc reads as a badge rather than as the character itself. */
.fmh-at-pic.emo { font-size: 18px; background: none; }

.fmh-composer-foot { display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
.fmh-composer-hint { font-size: 12.5px; }

/* IMP-134: on a chat page the composer takes whatever the messages leave, so
   the box fills the screen and Send lands on the bottom edge of the viewport
   rather than floating under a short conversation.
   min-height, NOT height: once a chat is long enough to overflow, the wrapper
   simply grows past the viewport and the composer falls back to its natural
   size - a busy chat must not be forced to scroll inside a fixed frame.
   The reserve is the same arithmetic as .fmh-center-screen (the shell chrome
   above and below .fmh-main), and it is trustworthy here for the reason
   IMP-104 and IMP-117 were not: the wrapper starts at the top of the page
   content, so the chips row and any nudge card are measured rather than
   guessed at. --fmh-chrome-top is already :root, and already 120px on
   desktop. */
.fmh-chat-fill {
  --fmh-chat-reserve: calc(var(--fmh-chrome-top) + var(--space-4) + var(--tabbar-h) + var(--space-12));
  display: flex; flex-direction: column;
  min-height: calc(100vh - var(--fmh-chat-reserve));    /* fallback */
  min-height: calc(100dvh - var(--fmh-chat-reserve));
}
/* No tab bar on this page, so .fmh-main's bottom padding is clearance for
   something that is not there - reclaim it and let the composer reach the
   bottom edge. Scoped to the flag stream.php sets from $show_tabbar, so the
   prayer room (the one chat that DOES carry the bar) keeps its clearance and
   its composer stays reachable. */
.fmh-main.chat-flush { padding-bottom: var(--space-4); }
.fmh-main.chat-flush .fmh-chat-fill {
  --fmh-chat-reserve: calc(var(--fmh-chrome-top) + var(--space-4) + var(--space-4));
}
.fmh-composer.fill { flex: 1 1 auto; min-height: 0; }
.fmh-composer.fill .fmh-composer-box {
  flex: 1 1 auto;
  min-height: 86px;   /* the three rows it opens at when there is no room to give */
  max-height: none;   /* filling the screen IS the cap - the 40vh one is spent */
}

/* ---------- search box (unified input + category dropdown) ---------- */
.search-box {
  border: 1.5px solid var(--border-hairline); border-radius: var(--radius-md);
  background: var(--input-bg);
  transition: border-color .15s ease, box-shadow .15s ease;
  overflow: hidden;
}
.search-box:focus-within { border-color: var(--input-border-focus); box-shadow: var(--ring-brand); }
.search-box-row {
  display: flex; align-items: center; min-height: 46px;
}
.search-box-icon {
  flex: none; display: inline-flex; padding: 0 4px 0 14px; color: var(--text-subtle); pointer-events: none;
}
.search-box-input {
  all: unset; flex: 1; min-width: 0; height: 100%;
  padding: 0 8px; font-size: 15px; color: var(--text-strong); font-family: var(--font-sans);
}
.search-box-input::placeholder { color: var(--input-placeholder); }
.search-box-cat {
  all: unset; flex: none;
  padding: 6px 28px 6px 12px; margin: 5px 5px 5px 0;
  font-size: 13px; font-weight: var(--weight-medium); font-family: var(--font-sans);
  color: var(--text-body); cursor: pointer;
  border-left: 1px solid var(--border-hairline);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 8px center;
}
.search-box-cat:focus { color: var(--color-brand); }

/* search result rows */
.search-row {
  display: flex; gap: 12px; align-items: center;
  border-bottom: 1px solid var(--border-hairline); padding: 13px 16px;
  text-decoration: none; color: inherit;
}
.search-row-ico {
  width: 44px; height: 44px; border-radius: 13px;
  background: var(--surface-panel); color: var(--color-brand);
  display: inline-flex; align-items: center; justify-content: center; flex: none;
}
.search-row-title { display: block; font-weight: 700; color: var(--text-strong); font-size: 16px; }
.search-row-sub   { display: block; font-size: 13px; color: var(--text-subtle); }

.fmh-alert { padding: var(--space-3) var(--space-4); border-radius: var(--radius-md); font-size: var(--text-small); margin-bottom: var(--space-4); }
.fmh-alert.error { background: var(--color-danger-soft); color: var(--color-danger); }
.fmh-alert.ok    { background: var(--color-success-soft); color: var(--color-success); }

/* ---------- switch ---------- */
.fmh-switch { position: relative; display: inline-block; width: 50px; height: 30px; flex: none; }
.fmh-switch.sm { width: 40px; height: 24px; }
.fmh-switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.fmh-switch .track {
  position: absolute; inset: 0; border-radius: var(--radius-pill);
  background: var(--switch-track-off); transition: background .2s ease;
}
.fmh-switch .knob {
  position: absolute; top: 3px; left: 3px; width: 24px; height: 24px;
  border-radius: var(--radius-pill); background: var(--switch-knob);
  box-shadow: var(--elevation-1); transition: transform .2s cubic-bezier(.4,.1,.2,1);
}
.fmh-switch.sm .knob { width: 18px; height: 18px; }
.fmh-switch input:checked ~ .track { background: var(--switch-track-on); }
.fmh-switch input:checked ~ .knob { transform: translateX(20px); }
.fmh-switch.sm input:checked ~ .knob { transform: translateX(16px); }

/* ---------- segmented control ---------- */
.fmh-seg { display: flex; gap: 4px; padding: 4px; background: var(--surface-sunken); border-radius: 16px; }
.fmh-seg label { flex: 1; }
.fmh-seg input { position: absolute; opacity: 0; }
.fmh-seg .opt {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px; width: 100%;
  height: 46px; border-radius: 12px; font-size: 14.5px; font-weight: var(--weight-bold);
  color: var(--text-muted); cursor: pointer; transition: all .15s ease;
}
.fmh-seg input:checked ~ .opt { background: var(--surface-card); color: var(--color-brand); box-shadow: 0 1px 4px rgba(63,23,48,0.12); }

/* ---------- list rows ---------- */
.fmh-list { background: var(--surface-card); border: 1px solid var(--border-hairline); border-radius: 18px; box-shadow: var(--elevation-1); }
.fmh-row { display: flex; align-items: center; gap: var(--space-3); padding: 13px 14px; border-top: 1px solid var(--border-hairline); background: none; width: 100%; text-align: left; border-left: none; border-right: none; border-bottom: none; }
.fmh-row:first-child { border-top: none; }
.ico-tile { width: 40px; height: 40px; border-radius: 12px; display: inline-flex; align-items: center; justify-content: center; flex: none; }
.ico-tile.sm { width: 38px; height: 38px; border-radius: 11px; }
.ico-tile.brand { background: var(--color-brand); color: #fff; }
.ico-tile.panel { background: var(--surface-panel); color: var(--color-brand); }
.ico-tile.sunken { background: var(--surface-sunken); color: var(--text-body); }
.fmh-row .grow { flex: 1; min-width: 0; }
.fmh-row .row-title { font-weight: var(--weight-bold); color: var(--text-strong); font-size: 15px; display: block; }
.fmh-row .row-sub { font-size: 12.5px; color: var(--text-muted); line-height: 1.4; display: block; margin-top: 1px; }

/* ---------- profile hero card ---------- */
/* Rounded card (was a square full-bleed band that clashed with the full-width
   header + rounded sections below). */
.profile-hero {
  background: var(--surface-card);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  box-shadow: var(--elevation-1);
  padding: 24px 18px 20px;
  display: flex; flex-direction: column; align-items: center; text-align: center;
}
/* tap-to-upload avatar (own profile) */
.avatar-upload-form { display: inline-block; }
.avatar-upload { position: relative; display: inline-block; cursor: pointer; }
.avatar-upload-badge {
  position: absolute; right: -2px; bottom: -2px;
  width: 28px; height: 28px; border-radius: var(--radius-pill);
  background: var(--color-brand); color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid var(--surface-card); box-shadow: var(--elevation-1);
}
.avatar-upload:hover .avatar-upload-badge { background: var(--color-brand-strong, var(--color-brand)); }

/* two-column profile hero (viewing another man, or editing own) */
.profile-hero.viewing  { flex-direction: row; align-items: flex-start; text-align: left; gap: 24px; }
.profile-hero.viewing .ph-photo { flex: none; display: flex; flex-direction: column; align-items: center; max-width: 150px; }
.profile-hero.viewing .ph-photo h1 { line-height: 1.2; word-break: break-word; }
.profile-hero.viewing .ph-text  { flex: 1; min-width: 0; }
.profile-hero.editable { flex-direction: row; align-items: center; text-align: left; gap: 20px; }
.profile-hero.editable .ph-photo { flex: none; display: flex; flex-direction: column; align-items: center; max-width: 150px; }
.profile-hero.editable .ph-photo h1 { line-height: 1.2; word-break: break-word; }
/* Quiet link-weight button under his own name - the name is his to fix, but
   it is not something he does often enough to earn a full button. */
.ph-name-edit {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 4px;
  padding: 4px 8px; border: none; border-radius: 8px; background: none;
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--color-brand); cursor: pointer;
}
.ph-name-edit:hover { background: var(--surface-page); }
.profile-hero.editable .ph-text  { flex: 1; min-width: 0; }
.profile-hero.editable .ph-text .fmh-hint { justify-content: flex-start; }
/* Action pair on another man's profile (Request 1:1 / Message). These were two
   `.fmh-btn.full` buttons side by side: each claimed width:100%, and a flex item
   won't shrink below its own content, so Message ran off the right edge in the
   narrow text column. They now share the row and wrap when there isn't room. */
.profile-actions { display: flex; flex-wrap: wrap; gap: 10px; max-width: 320px; }
/* Size to content, then share what's left. A fixed 130px basis squeezed
   "Suggest Meet-up" onto two lines; nowrap keeps a label whole and lets the row
   wrap to stacked full-width buttons instead, which is the readable failure. */
.profile-actions .fmh-btn { flex: 1 1 auto; min-width: 0; padding: 0 var(--space-4); white-space: nowrap; }
.profile-bio {
  width: 100%; border: none; background: transparent; outline: none;
  font-size: 14px; font-family: var(--font-sans); color: var(--text-body);
  line-height: 1.5; padding: 0; resize: none;
  field-sizing: content; min-height: 1.5em;
}
.profile-bio::placeholder { color: var(--input-placeholder); }

/* ---------- profile attribute pills (interests / skills) ---------- */
/* Compact: name + in-pill eye toggle + remove ×, wrapping inline so the list
   stays tight as a man adds more. Solid pill = public, dashed = only-me. */
.attr-pills { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: 14px; }
.attr-pills:empty { display: none; }
.attr-pills:empty + .fmh-row { border-top: none; }
.attr-pill {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 0 4px 0 12px; min-height: 34px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--chip-border); background: var(--chip-bg);
}
.attr-pill .attr-pill-name { font-size: 13px; font-weight: var(--weight-bold); color: var(--chip-fg); white-space: nowrap; }
a.attr-pill-name { text-decoration: none; display: inline-flex; align-items: center; gap: 5px; }
.attr-pill-name .chip-ico { flex: none; opacity: .8; }
a.attr-pill-name:hover { text-decoration: underline; }

/* ---------- interest page (interest.php) ----------
   Faces in a wrapping grid rather than a list: it is "who's here", not a
   directory to work through. No counts anywhere, by design. */
.int-hero { padding: 20px 18px; display: flex; flex-direction: column; align-items: center; text-align: center; }
.int-title { font-size: 23px; margin-top: 10px; line-height: 1.2; word-break: break-word; }
.int-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 14px; }
.int-actions form { margin: 0; }
/* IMP-186 - "On your profile" as the first control rather than a label with
   its undo further down the page. It reads as done, not as something to press
   for the sake of it: the tick is brand, the rest is the plain secondary
   button, so it sits level with Start a chat instead of competing with it. */
.int-on { color: var(--color-brand); }
.int-on svg, .int-on i { color: var(--color-brand); }
.int-faces {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(78px, 1fr)); gap: 14px 8px;
  background: var(--surface-card); border: 1px solid var(--border-hairline);
  border-radius: 18px; box-shadow: var(--elevation-1); padding: 16px 10px;
}
.int-face {
  display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0;
  text-decoration: none; color: var(--text-strong);
}
.int-face > span:last-child {
  font-size: 12.5px; font-weight: 600; line-height: 1.25; text-align: center;
  max-width: 100%; overflow-wrap: anywhere;
}
.int-more {
  display: inline-flex; align-items: center; gap: 2px; margin: 8px 2px 0;
  font-size: 13.5px; font-weight: 600; color: var(--color-brand); text-decoration: none;
}
.int-empty { font-size: 14px; margin: 0 2px; line-height: 1.5; }
/* IMP-189 - marks the interest's own room in its list of chats. Quiet: it is
   saying which of these is the front door, not shouting about it. */
.int-main-tag {
  font-size: 10.5px; font-weight: var(--weight-bold); text-transform: uppercase;
  letter-spacing: var(--tracking-caps); color: var(--color-brand);
  background: var(--surface-panel); border-radius: 999px;
  padding: 2px 7px; margin-left: 6px; vertical-align: 1px; white-space: nowrap;
}
.int-note  { font-size: 12.5px; margin: 8px 2px 0; line-height: 1.5; }
.int-clip  { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.int-remove {
  background: none; border: none; cursor: pointer; font: inherit;
  font-size: 13px; color: var(--text-subtle); text-decoration: underline; padding: 6px;
}
.int-desc { margin: 8px auto 0; max-width: 460px; font-size: 14.5px; line-height: 1.5; color: var(--text-body); }
.int-suggested {
  display: inline-flex; align-items: flex-start; gap: 6px; margin: 10px auto 0; max-width: 460px;
  font-size: 13px; line-height: 1.45; color: var(--color-brand); background: var(--surface-panel);
  border-radius: var(--radius-md); padding: 7px 11px; text-align: left;
}
.int-suggested i[data-lucide], .int-suggested svg { flex: none; margin-top: 2px; }

/* Home card: new + suggested interests. One row per tag - the name opens the
   page, Add and × act in place. */
.int-nudge-row { display: flex; align-items: center; gap: 6px; padding: 6px 6px 6px 11px; border-radius: var(--radius-md); background: var(--surface-panel); }
.int-nudge-row form { margin: 0; flex: none; }
.int-nudge-link { flex: 1; min-width: 0; text-decoration: none; color: inherit; display: flex; flex-direction: column; }
.int-nudge-name { font-weight: var(--weight-bold); font-size: 14px; color: var(--text-strong); }
.int-nudge-link:hover .int-nudge-name { text-decoration: underline; }
.int-nudge-sub { font-size: 12.5px; line-height: 1.35; color: var(--text-muted); overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow-wrap: anywhere; }
.int-nudge-add { min-height: 32px; padding: 0 11px; }
/* The weekly "Worth a look" card in the Home feed - land clear of the sticky bars. */
.int-recs { scroll-margin-top: 90px; }
/* On a phone the list needs the width more than the card needs its icon. */
@media (max-width: 520px) {
  .fmh-banner.int-nudge > .icon { display: none; }
  .fmh-banner.int-nudge { padding: 14px 12px; }
}

/* manager/interest.php */
.ie-card { padding: 16px; margin-top: 14px; }
.ie-label { display: block; font-size: 12.5px; font-weight: 600; color: var(--text-muted); margin: 14px 0 5px; }
.ie-card > .ie-label:first-of-type { margin-top: 0; }
.ie-hint { font-size: 12.5px; color: var(--text-subtle); margin: 5px 0 0; line-height: 1.45; }
.ie-filter { margin: 6px 0 8px; max-width: 280px; }
.ie-chips { max-height: 220px; overflow-y: auto; padding: 2px; }
.ie-check { display: flex; gap: 10px; align-items: flex-start; margin-top: 16px; font-size: 14px; color: var(--text-strong); cursor: pointer; }
.ie-check input { margin-top: 3px; }
.ie-men { max-height: 300px; overflow-y: auto; border: 1px solid var(--border-hairline); border-radius: var(--radius-md); }
.ie-man { display: flex; align-items: center; gap: 10px; padding: 8px 12px; cursor: pointer; font-size: 14px; color: var(--text-strong); border-bottom: 1px solid var(--border-hairline); }
.ie-man:last-child { border-bottom: none; }
.ie-man.has { opacity: .55; cursor: default; }
.ie-man[hidden] { display: none !important; }
/* Admin interest list: quick search + "needs work" (no men or no related tags). */
.int-admin-tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 8px; }
.int-admin-tools .fmh-input { flex: 1 1 220px; max-width: 360px; }
.int-admin-work { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text-muted); cursor: pointer; }
#int-list .fmh-row[hidden] { display: none !important; }
#int-list .fmh-row.int-first { border-top: none; }
#int-list .fmh-row.int-needs-work { box-shadow: inset 0 0 0 2px var(--color-danger); border-radius: 12px; }
.int-zero { color: var(--color-danger); font-weight: 600; }
/* IMP-185b - a tag that asks its men for a detail, marked in the admin list.
   Brand rather than danger: it is a setting you chose, not a problem. */
.int-asks { color: var(--color-brand); font-weight: 600; }
.int-asks svg { vertical-align: -1px; }
.int-admin-state { margin-top: 10px; }
#int-list .fmh-row.int-disabled .row-title { color: var(--text-muted); text-decoration: line-through; }
/* Claude drafts (edit page, bulk modal, review page). */
.ai-draft-bar { display: flex; align-items: center; gap: 10px 12px; flex-wrap: wrap; margin-top: 16px; padding: 10px 12px; border-radius: var(--radius-md); background: var(--surface-panel, rgba(122,46,84,.05)); }
.ai-draft-bar .ie-hint { flex: 1 1 220px; }
.fmh-input.ai-filled { animation: ai-fill 1.6s ease-out; }
@keyframes ai-fill { 0% { box-shadow: 0 0 0 3px var(--border-brand); } 100% { box-shadow: 0 0 0 0 transparent; } }
.fmh-chip.ai-pick { outline: 2px dashed var(--border-brand); outline-offset: 1px; }
#ai-modal .fmh-btn[hidden], .ai-progress[hidden], .ai-new[hidden] { display: none !important; }
.ai-progress { height: 6px; border-radius: 3px; background: var(--border-hairline); overflow: hidden; }
.ai-progress span { display: block; height: 100%; width: 0; background: var(--border-brand); transition: width .3s; }
.ai-waiting { display: flex; align-items: center; gap: 10px; padding: 13px 16px; margin-top: 16px; border-color: var(--border-brand); font-size: 13.5px; color: var(--text-strong); text-decoration: none; }
.ai-waiting .grow { flex: 1; min-width: 0; }
.attr-pill form { display: inline-flex; margin: 0; }
.attr-pill-eye, .attr-pill-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0; border: none; background: none;
  border-radius: var(--radius-pill); cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.attr-pill-eye { color: var(--color-brand); }
.attr-pill-eye:hover { background: var(--surface-panel); }
.attr-pill-x { color: var(--text-subtle); font-size: 17px; font-weight: var(--weight-bold); line-height: 1; }
.attr-pill-x:hover { background: var(--surface-sunken); color: var(--text-strong); }
.attr-pill.private { background: var(--surface-card); border-style: dashed; }
.attr-pill.private .attr-pill-eye { color: var(--text-subtle); }
.attr-pill.locked { opacity: .5; }
.attr-pill.locked .attr-pill-eye, .attr-pill.locked .attr-pill-x { cursor: default; }

/* ---------- empty state ---------- */
.fmh-empty { text-align: center; padding: var(--space-8) var(--space-4); }
.fmh-empty .icon { width: 64px; height: 64px; border-radius: var(--radius-pill); background: var(--surface-panel); color: var(--color-brand); display: inline-flex; align-items: center; justify-content: center; margin-bottom: var(--space-4); }
.fmh-empty h2 { font-size: var(--text-h2); font-weight: var(--weight-display); color: var(--text-strong); }
.fmh-empty p { margin: var(--space-2) auto 0; max-width: 300px; font-size: var(--text-small); color: var(--text-body); line-height: var(--leading-normal); }
.fmh-empty .actions { margin-top: var(--space-6); display: flex; flex-direction: column; align-items: center; gap: var(--space-2); }

/* ---------- togetherness banner ---------- */
.fmh-banner { display: flex; align-items: center; gap: 13px; background: var(--surface-card); border-radius: var(--radius-lg); padding: 14px 16px; box-shadow: var(--elevation-1); text-decoration: none; color: inherit; }
.fmh-banner .icon { width: 46px; height: 46px; border-radius: var(--radius-pill); background: var(--surface-panel); color: var(--color-brand); display: inline-flex; align-items: center; justify-content: center; flex: none; }
.banner-with { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }

/* IMP-126: the banner listing several plans on one day. The base .fmh-banner
   centres its children, which is right for one line and wrong for a list. */
.fmh-banner.is-multi { align-items: flex-start; }
.banner-list { display: flex; flex-direction: column; gap: 6px; margin-top: 9px; }
.banner-item { display: flex; align-items: center; gap: 9px; padding: 7px 9px 7px 11px; border-radius: var(--radius-md); background: var(--surface-panel); text-decoration: none; color: inherit; }
.banner-item:hover { background: var(--surface-page); }
.banner-item .bi-when { font-weight: var(--weight-bold); color: var(--color-brand); font-size: 13px; flex: none; }
.banner-item .bi-what { font-size: 13.5px; color: var(--text-body); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.banner-item .bi-go { margin-left: auto; flex: none; color: var(--text-subtle); display: inline-flex; }
.fmh-pill { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: var(--weight-medium); color: var(--color-brand); background: var(--surface-panel); border-radius: var(--radius-pill); padding: 3px 10px 3px 7px; line-height: 1.3; }
.fmh-pill i[data-lucide] { width: 13px; height: 13px; flex: none; }
.fmh-pill.subtle { color: var(--text-subtle); background: transparent; border: 1px dashed var(--border-hairline); padding: 2px 9px 2px 6px; }

/* ---------- bottom tab bar + FAB ---------- */
.fmh-tabbar {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 0;
  width: 100%; max-width: var(--content-max);
  background: var(--tabbar-bg); border-top: 1px solid var(--border-hairline);
  display: flex; align-items: stretch; z-index: 40;
  /* v83c (IMP-148): the inset is ADDED to the height, not taken out of it.
     With border-box, a fixed 64px plus a bottom inset left the tabs only a
     few pixels of content box — Android Chrome reports a gesture-bar inset
     while its URL bar is showing, so scrolling to the top squashed the icons
     away and left the labels alone. */
  height: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.fmh-tab {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  color: var(--tabbar-fg); font-size: 11px; font-weight: var(--weight-medium); text-decoration: none;
}
/* Both selectors on purpose: Lucide swaps the <i> for an <svg> once it
   hydrates, and `flex: none` is what stops the icon being shrunk to nothing
   if the bar is ever short of room (IMP-148). */
.fmh-tab i[data-lucide],
.fmh-tab svg[data-lucide] { width: 24px; height: 24px; flex: none; }
.fmh-tab.active { color: var(--tabbar-fg-active); }
.fmh-tab.fab-slot { position: relative; }
.fmh-fab {
  position: absolute; top: -18px; left: 50%; transform: translateX(-50%);
  width: var(--fab-size); height: var(--fab-size); border-radius: var(--radius-pill);
  background: var(--fab-bg); color: var(--fab-fg);
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: var(--elevation-3); border: 4px solid var(--surface-page);
  transition: transform .05s ease, background .15s ease;
}
.fmh-fab:active { transform: translateX(-50%) scale(0.94); }
.fmh-fab i[data-lucide] { width: 26px; height: 26px; }
.fmh-tab.fab-slot .label { margin-top: 28px; }

/* ---------- contact details: field + its eye (v84a) ----------
   The eye belongs beside the thing it hides, the way it does on an interest
   pill. Under the fields it was covered by the phone keyboard. */
.contact-field { display: flex; align-items: center; gap: 8px; }
.contact-field .fmh-input { flex: 1; min-width: 0; }
.contact-eye {
  flex: none; width: 42px; height: 42px; border-radius: var(--radius-md);
  background: var(--surface-panel); border: 1px solid var(--border-hairline);
  color: var(--text-subtle); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: color .15s ease, background .15s ease;
}
.contact-eye svg { width: 18px; height: 18px; }
.contact-eye.on { color: var(--color-brand); background: var(--surface-card); }

/* ---------- toast ---------- */
.fmh-toast {
  position: fixed; left: 16px; right: 16px; bottom: calc(var(--tabbar-h) + 16px);
  max-width: calc(var(--content-max) - 32px); margin: 0 auto;
  background: var(--toast-bg); color: var(--toast-fg);
  padding: 13px 16px; border-radius: var(--radius-md); box-shadow: var(--elevation-3);
  font-size: var(--text-small); font-weight: var(--weight-medium); text-align: center;
  z-index: 80; display: flex; align-items: center; justify-content: center; gap: var(--space-2);
  opacity: 0; transform: translateY(8px); transition: opacity .2s ease, transform .2s ease; pointer-events: none;
}
.fmh-toast.show { opacity: 1; transform: translateY(0); pointer-events: auto; }
.fmh-toast.success i[data-lucide] { color: var(--color-success); }
.fmh-toast-action {
  background: none; border: none; color: var(--color-brand-light, #d4a0c0); font-weight: 700;
  font-size: inherit; cursor: pointer; padding: 0 4px; margin-left: 6px; text-decoration: underline;
  text-underline-offset: 2px;
}

/* ---------- dropdown menu ---------- */
.fmh-menu-wrap { position: relative; }
.fmh-menu {
  position: absolute; right: 0; top: 40px; z-index: 50;
  background: var(--surface-card); border: 1px solid var(--border-hairline);
  border-radius: 14px; box-shadow: var(--elevation-3); padding: 6px;
  display: none; flex-direction: column; min-width: 180px;
}
.fmh-menu.open { display: flex; }
.fmh-menu button, .fmh-menu a {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  background: none; border: none; border-radius: 9px; cursor: pointer;
  font-size: 14px; color: var(--text-strong); text-align: left; text-decoration: none; width: 100%;
}
.fmh-menu button:hover, .fmh-menu a:hover { background: var(--surface-page); }
.fmh-menu button.danger { color: var(--color-danger); }
/* v110a: the three notify rows are one choice, not three actions, and they only
   read that way if they are fenced off from the actions beneath them. The menu
   can't be a <fieldset> — each row is its own form — so the grouping is drawn:
   a rule under the block, and the rows themselves inset so they hang under the
   NOTIFY ME heading rather than lining up with Tags and Delete. */
.fmh-menu .menu-sep { height: 1px; margin: 6px 6px 4px; background: var(--border-hairline); }
.fmh-menu .menu-pick { padding-left: 20px; }
/* v110b: which one is set has to be readable at a glance. The chosen row goes
   plum and semibold (icon too, via currentColor on the Lucide stroke); the other
   two drop back to muted so they read as the alternatives. The tick stays —
   colour alone is not an accessible indicator, and it survives a plum-blind eye. */
.fmh-menu button.menu-pick { color: var(--text-muted); }
.fmh-menu button.menu-pick[aria-pressed="true"] {
  color: var(--color-brand); font-weight: var(--weight-bold);
}
/* Marks a row a regular man never sees. Pushed to the right so it reads as an
   annotation on the row, not part of its label. */
.fmh-menu .menu-su {
  margin-left: auto; padding-left: 8px; font-size: 10.5px; font-weight: var(--weight-bold);
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-subtle); white-space: nowrap;
}
.fmh-menu .menu-note { display: flex; align-items: center; gap: 8px; padding: 8px 12px 4px; font-size: 11px; font-weight: var(--weight-bold); letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-subtle); }

/* ---------- footer credit ----------
   Mobile: the credit/legal bar doesn't fit the app-shell layout, so it's
   hidden below 900px — every link in it (Privacy Notice, Cookie Policy,
   Settings, Log out) already has a home in the mobile profile page and tab
   bar, so nothing becomes unreachable. Desktop re-shows it below. */
.fmh-foot { display: none; text-align: center; padding: var(--space-6) var(--space-4); font-size: var(--text-caption); color: var(--text-subtle); }
.fmh-foot a { color: var(--text-muted); }

/* ---------- auth screens ---------- */
.fmh-auth { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-6); gap: var(--space-6); }
.fmh-auth .brandblock { text-align: center; }
.fmh-auth .brandblock .fmh-mark { width: 34px; margin: 0 auto 12px; }
.fmh-auth .brandblock .fmh-mark span { height: 5px; }
.fmh-auth .brandblock h1 { font-size: var(--text-h1); color: var(--text-strong); }
.fmh-auth .brandblock p { color: var(--text-muted); font-size: var(--text-small); margin-top: 4px; }
.fmh-auth .fmh-card { width: 100%; max-width: 380px; }

/* Photo variant (login): full-bleed image under a dark overlay. The overlay is
   darker on the right, where the card sits on desktop, and even all over on a
   phone, where the card sits over the middle of the picture. */
.fmh-auth.photo {
  background-color: #1d1d1b;
  background-image: linear-gradient(rgba(12, 10, 12, .62), rgba(12, 10, 12, .72)), url("../img/login-bg-1000.jpg");
  background-size: cover; background-position: 30% center;
}
.fmh-auth.photo .brandblock h1 { color: #fff; }
.fmh-auth.photo .brandblock p { color: rgba(255, 255, 255, .8); }
.fmh-auth.photo .brandblock .fmh-mark span { background: #fff; }
.fmh-auth.photo .fmh-card { box-shadow: 0 18px 50px rgba(0, 0, 0, .45); }
.fmh-auth.photo .auth-foot { color: rgba(255, 255, 255, .8); }
.fmh-auth.photo .auth-foot a { color: #fff; }
@media (min-width: 900px) {
  .fmh-auth.photo {
    background-image: linear-gradient(90deg, rgba(12, 10, 12, .30) 0%, rgba(12, 10, 12, .55) 50%, rgba(12, 10, 12, .82) 100%), url("../img/login-bg-2000.jpg");
    background-position: left center;
    align-items: flex-end; padding-right: clamp(32px, 9vw, 140px);
  }
  .fmh-auth.photo > * { width: 380px; }
}

/* ---------- progress dots (wizard) ---------- */
.fmh-dots { display: inline-flex; gap: 7px; align-items: center; }
.fmh-dots span { height: 7px; width: 7px; border-radius: var(--radius-pill); background: var(--border-strong); transition: all .2s ease; }
.fmh-dots span.on { width: 22px; background: var(--color-brand); }
.fmh-dots span.done { background: var(--color-brand); }

/* ---------- stepper (cascade) ---------- */
.fmh-stepper { display: flex; flex-direction: column; }
.fmh-step { display: flex; gap: 12px; }
.fmh-step .rail { display: flex; flex-direction: column; align-items: center; flex: none; }
.fmh-step .dot { width: 30px; height: 30px; border-radius: var(--radius-pill); display: inline-flex; align-items: center; justify-content: center; flex: none; border: 2px solid var(--stepper-pending); background: var(--surface-card); color: var(--text-subtle); font-weight: var(--weight-bold); font-size: 13px; }
.fmh-step .dot.done { background: var(--stepper-done); border-color: var(--stepper-done); color: #fff; }
.fmh-step .dot.active { border-color: var(--stepper-active); color: var(--color-brand); box-shadow: var(--ring-brand); }
.fmh-step .line { width: 2px; flex: 1; background: var(--stepper-line); margin: 4px 0; min-height: 12px; }
.fmh-step:last-child .line { display: none; }
.fmh-step .body { flex: 1; min-width: 0; padding-bottom: var(--space-6); }
.fmh-step .body .name { display: inline-flex; align-items: center; gap: 9px; font-weight: var(--weight-bold); color: var(--text-strong); }
.fmh-step .body .meta { font-size: 13px; color: var(--text-muted); margin-top: 2px; }

/* countdown pill */
.fmh-countdown { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: var(--weight-bold); color: var(--color-brand); background: var(--surface-panel); padding: 6px 11px; border-radius: var(--radius-pill); }
@keyframes fmhPulse { 0%,100% { opacity: 1; } 50% { opacity: .55; } }
.fmh-countdown.pulse { animation: fmhPulse 1.6s ease-in-out infinite; }

/* audience / rank pickers */
.aud-check { width: 24px; height: 24px; border-radius: var(--radius-pill); border: 2px solid var(--border-strong); display: inline-flex; align-items: center; justify-content: center; flex: none; color: transparent; font-size: 13px; font-weight: 700; }
.aud-check::after { content: '✓'; }
.aud-check.on { background: var(--color-brand); border-color: var(--color-brand); color: #fff; }
.picked .aud-check, .men-row.picked .aud-check { background: var(--color-brand); border-color: var(--color-brand); color: #fff; }
.rank-row { display: flex; align-items: center; gap: 10px; padding: 9px 11px; border-radius: 14px; border: 1px solid var(--border-brand); background: var(--surface-card); box-shadow: var(--elevation-1); margin-bottom: 8px; }
.rank-row .num { width: 24px; height: 24px; border-radius: var(--radius-pill); background: var(--color-brand); color: #fff; font-size: 13px; font-weight: 800; display: inline-flex; align-items: center; justify-content: center; flex: none; }
.rank-row .ctrls { display: inline-flex; gap: 4px; flex: none; }
.rank-row .ctrls button { width: 30px; height: 30px; border-radius: 9px; border: 1px solid var(--border-hairline); background: var(--surface-card); color: var(--text-body); display: inline-flex; align-items: center; justify-content: center; }
.rank-row .ctrls button.rm { border: none; background: transparent; color: var(--text-subtle); }
.rank-row .ctrls button:disabled { opacity: .4; }

/* ---------- stat blocks (dashboard headline numbers) ---------- */
/* The auto-fit grid of stat cards, and the number + caption inside each.
   Promoted from repeated inline styles so a change to the headline scale
   propagates to every leaders/admin dashboard at once. */
.fmh-statgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; }
.fmh-stat { margin-top: 10px; font-size: 24px; font-weight: 800; color: var(--text-strong); }
.fmh-stat-cap { font-size: 12.5px; color: var(--text-muted); }

/* ---------- section / card headings ---------- */
.fmh-card-title { font-weight: var(--weight-bold); font-size: 17px; color: var(--text-strong); }
/* title + trailing action on one baseline-aligned row */
.fmh-headrow { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }

/* IMP-115: the row every feed card opens with - what this is on the left, when
   it happened on the right. The timestamp used to live in the headline row,
   where a long headline squeezed it onto its own wrapped line; up here it
   always lands in the same place on every card. */
.fmh-feed-eyebrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 9px; }
.fmh-feed-when    { font-size: 13px; color: var(--text-subtle); flex: none; }
/* The unread tally on a grouped chat card (IMP-114). Filled rather than
   outlined: it is the one thing on the card that says "there is more here than
   the line you are reading", and an outline reads as decoration at 11px. */
.fmh-feed-pill    { flex: none; font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em;
                    text-transform: uppercase; line-height: 1; padding: 3px 7px; border-radius: 999px;
                    background: var(--color-brand); color: var(--text-on-brand, #fff); }

/* misc helpers */
.fmh-divider { height: 1px; background: var(--border-hairline); border: none; margin: var(--space-4) 0; }
/* IMP-104: this used to be sized 100vh minus the tab bar, but the box starts
   BELOW the sticky header — so it overhung the bottom by the header's height,
   pushed its own centre down by roughly half of that, and made the page scroll
   on a screen that should not. The chrome above is subtracted too, and dvh is
   used so a phone's retracting address bar doesn't reintroduce the same error.
   --fmh-chrome-top is measured, not guessed: 61px to the foot of the mobile
   pagebar, 120px to the foot of the desktop header plus its breadcrumb row. */
/* IMP-117: .fmh-main's own padding is chrome too - space-4 above the box, and
   tabbar-h + space-12 below it. Subtracting only the tab bar left the box
   ~64px taller than the room it had, so the page scrolled and the box carried
   its own centre down with it: the card sat low, exactly as reported. Reserve
   everything that is actually spoken for and the arithmetic closes. */
:root { --fmh-chrome-top: 61px; }
.fmh-center-screen {
  --fmh-center-reserve: calc(var(--fmh-chrome-top) + var(--space-4) + var(--tabbar-h) + var(--space-12));
  min-height: calc(100vh - var(--fmh-center-reserve));   /* fallback */
  min-height: calc(100dvh - var(--fmh-center-reserve));
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: var(--space-8) var(--space-6);
}
@media (min-width: 900px) {
  /* The tab bar is display:none up here, but .fmh-main still reserves its
     height as padding, so the sum above holds unchanged - only the header
     above the box is taller. */
  :root { --fmh-chrome-top: 120px; }
}
/* IMP-117: .flow is for a centred block that is NOT the only thing on the
   page - the meet-up outcome screens carry a private-notes card and a modal
   after them. Claiming a whole viewport there makes the page scroll and puts
   the block's centre a long way down the scroll height, which is why the card
   read as sitting too low. Top-aligned with room to breathe instead. */
.fmh-center-screen.flow {
  min-height: 0;
  justify-content: flex-start;
  padding-top: calc(var(--space-8) + var(--space-4));
}
.fmh-hint { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text-subtle); }

/* ---------- desktop top header (hidden on mobile) ---------- */
.fmh-deskhead { display: none; }
.fmh-deskhead .dh-brand { display: inline-flex; align-items: center; gap: 11px; text-decoration: none; }
.fmh-deskhead .dh-brand-name { font-weight: var(--weight-display); font-size: var(--text-h3); letter-spacing: -0.01em; color: var(--text-strong); }
.fmh-deskhead .dh-nav { display: flex; align-items: center; gap: 2px; }
.fmh-deskhead .dh-link { padding: 9px 14px; border-radius: var(--radius-md, 14px); text-decoration: none; font-size: 15px; font-weight: var(--weight-medium); color: var(--text-body); transition: background .15s ease, color .15s ease; }
.fmh-deskhead .dh-link:hover { background: var(--surface-page); }
.fmh-deskhead .dh-link-icon { display: inline-flex; align-items: center; justify-content: center; padding: 9px 12px; }
.fmh-deskhead .dh-link.active { background: var(--surface-panel); color: var(--color-brand); }
.fmh-deskhead .dh-actions { display: flex; align-items: center; gap: 6px; }
.fmh-deskhead .dh-avatar { display: inline-flex; border-radius: var(--radius-pill); }
.fmh-deskhead .dh-avatar.active, .fmh-deskhead .fmh-iconbtn.active { box-shadow: var(--ring-brand); }

/* ---------- create (+) explode menu ---------- */
.fmh-fab-float { display: none; }
.fmh-create { position: fixed; inset: 0; z-index: 1500; visibility: hidden; pointer-events: none; }
.fmh-create.open { visibility: visible; pointer-events: auto; }
.fmh-create-scrim { position: absolute; inset: 0; background: rgba(20,8,16,0.42); opacity: 0; transition: opacity .2s ease; }
.fmh-create.open .fmh-create-scrim { opacity: 1; }
.fmh-create-sheet {
  position: fixed; left: 50%; bottom: calc(var(--tabbar-h) + 16px + env(safe-area-inset-bottom, 0px));
  width: min(360px, calc(100% - 28px));
  background: var(--surface-card, #fff); border: 1px solid var(--border-hairline, #eadfe6);
  border-radius: 20px; box-shadow: var(--elevation-3, 0 16px 40px rgba(40,12,28,.22));
  padding: 8px; display: flex; flex-direction: column; gap: 2px;
  opacity: 0; transform: translateX(-50%) translateY(14px) scale(.96); transform-origin: bottom center;
  transition: opacity .2s ease, transform .22s cubic-bezier(.34,1.3,.64,1);
  /* IMP-195: the sheet grows with the number of things a man can make, and a
     leader has several more than most - past a point the first item ran off
     the top of the screen and could not be reached at all. Bound it by what is
     actually on screen and let it scroll inside itself. dvh as well as vh,
     because on a phone the address bar is part of the answer. */
  max-height: calc(100vh  - var(--tabbar-h) - 32px - env(safe-area-inset-bottom, 0px));
  max-height: calc(100dvh - var(--tabbar-h) - 32px - env(safe-area-inset-bottom, 0px));
  overflow-y: auto; overscroll-behavior: contain;
}

/* A long menu (.two-up, set in footer.php from the number of items) goes into
   two columns wherever there is room for them. The width condition matters as
   much as the class: two columns of icon, title and description inside a 360px
   sheet would be worse than a scroll, so a narrow phone keeps one column and
   scrolls, and a phone held sideways gets the lot at once. Descriptions are
   held to two lines so one long one cannot make every row beside it taller. */
@media (min-width: 600px) {
  .fmh-create-sheet.two-up {
    width: min(600px, calc(100% - 28px));
    display: grid; grid-template-columns: 1fr 1fr; align-content: start; gap: 2px 4px;
  }
  .fmh-create-sheet.two-up .fmh-create-sep { grid-column: 1 / -1; }
  .fmh-create-sheet.two-up .ci-txt small {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
}
.fmh-create.open .fmh-create-sheet { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
.fmh-create-item { display: flex; align-items: center; gap: 13px; padding: 11px 12px; border-radius: 14px; text-decoration: none; color: var(--text-strong, #2c1622); opacity: 0; transform: translateY(8px); transition: opacity .18s ease, transform .18s ease, background .15s ease; }
.fmh-create.open .fmh-create-item { opacity: 1; transform: translateY(0); }
.fmh-create.open .fmh-create-item:nth-child(2) { transition-delay: 35ms; }
.fmh-create.open .fmh-create-item:nth-child(3) { transition-delay: 70ms; }
.fmh-create.open .fmh-create-item:nth-child(4) { transition-delay: 105ms; }
.fmh-create.open .fmh-create-item:nth-child(5) { transition-delay: 140ms; }
.fmh-create.open .fmh-create-item:nth-child(6) { transition-delay: 175ms; }
.fmh-create.open .fmh-create-item:nth-child(7) { transition-delay: 210ms; }
.fmh-create-item:hover { background: var(--surface-page, #f5f2ec); }
.fmh-create-item .ci-ico { width: 42px; height: 42px; flex: none; border-radius: 12px; display: inline-flex; align-items: center; justify-content: center; background: var(--surface-panel, #f3e9ef); color: var(--color-brand, #7A2E54); }
.fmh-create-item.help .ci-ico { background: var(--surface-sunken, #efe9f0); color: var(--text-muted, #6c5563); }
.fmh-create-item .ci-txt { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.fmh-create-item .ci-txt b { font-size: 14.5px; font-weight: var(--weight-bold, 700); }
.fmh-create-item .ci-txt small { font-size: 12px; color: var(--text-subtle, #897583); }
.fmh-create-sep { height: 1px; background: var(--border-hairline, #eadfe6); margin: 5px 8px; }
/* the + glyph rotates to a × while the menu is open */
.fmh-fab svg, .fmh-fab-float svg { transition: transform .2s ease; }
body.fmh-create-open .fmh-fab svg, body.fmh-create-open .fmh-fab-float svg { transform: rotate(45deg); }
body.fmh-create-open { overflow: hidden; }

/* ---------- segmented tabs (feedback type switch) ---------- */
.fmh-seg-opt { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 7px; min-height: 38px; border-radius: 13px; text-decoration: none; font-size: 13.5px; font-weight: var(--weight-bold, 700); color: var(--text-muted, #6c5563); }
.fmh-seg-opt.on { background: var(--surface-card, #fff); color: var(--color-brand, #7A2E54); box-shadow: 0 1px 4px rgba(63,23,48,0.12); }

/* ---------- footer columns (desktop only; mobile keeps the slim credit) ---------- */
.fmh-foot .foot-cols { display: none; }
.fmh-foot .foot-credit-links { display: block; margin-top: 4px; }

/* ---------- games (draughts + scrabble mockup) ---------- */
.game-players { display: flex; align-items: center; gap: 8px; padding: 2px 2px 0; }
.game-player { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; }
.game-player.opp { justify-content: flex-end; }
.game-player-name { font-weight: var(--weight-bold); font-size: 15px; color: var(--text-strong); }
.game-you-tag { font-size: 11px; font-weight: var(--weight-medium); color: var(--color-brand); background: var(--surface-panel); border-radius: var(--radius-pill); padding: 1px 7px; vertical-align: 1px; }
.game-player-pieces { font-size: 13px; color: var(--text-subtle); display: flex; align-items: center; gap: 4px; }
.game-player-score { font-size: 13px; color: var(--text-subtle); font-weight: var(--weight-medium); }
.game-vs { font-size: 12px; color: var(--text-subtle); font-weight: var(--weight-bold); text-transform: uppercase; letter-spacing: 0.5px; flex: none; }
.game-turn-bar { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: var(--weight-medium); color: var(--color-brand); background: var(--surface-panel); border-radius: var(--radius-sm); padding: 7px 12px; }
.game-turn-bar i[data-lucide] { width: 15px; height: 15px; flex: none; }

.game-board-wrap { display: flex; justify-content: center; }
.game-board.draughts { display: grid; grid-template-columns: repeat(8, 1fr); width: 100%; max-width: 380px; aspect-ratio: 1; border-radius: var(--radius-md); overflow: hidden; box-shadow: var(--elevation-1); border: 2px solid var(--border-hairline); }
.game-board .sq { position: relative; display: flex; align-items: center; justify-content: center; }
.game-board .sq.light { background: #F0E0C8; }
.game-board .sq.dark { background: #8B6F47; }
.game-board .sq.selected { background: #6A8D3D; }
.game-board .sq.move-hint::after { content: ''; position: absolute; width: 30%; height: 30%; border-radius: 50%; background: rgba(106,141,61,0.5); }
.game-board .pc { display: flex; align-items: center; justify-content: center; width: 72%; height: 72%; border-radius: 50%; box-shadow: 0 2px 4px rgba(0,0,0,0.3); }
.game-board .pc.dk { background: var(--color-brand); border: 2px solid #5E1E3D; }
.game-board .pc.lt { background: #F5F0E8; border: 2px solid #C8B8A0; }
.game-board .pc.king { position: relative; }
.game-board .pc.dk.king { box-shadow: 0 0 0 2px #D4A843, 0 2px 4px rgba(0,0,0,0.3); }
.game-board .pc.lt.king { box-shadow: 0 0 0 2px #D4A843, 0 2px 4px rgba(0,0,0,0.3); }
.game-board .pc.king i[data-lucide] { width: 14px; height: 14px; color: #D4A843; }
.piece { display: inline-block; width: 12px; height: 12px; border-radius: 50%; }
.piece.dark { background: var(--color-brand); border: 1px solid #5E1E3D; }
.piece.light { background: #F5F0E8; border: 1px solid #C8B8A0; }

.game-board.scrabble { display: grid; grid-template-columns: repeat(15, 1fr); width: 100%; max-width: 380px; aspect-ratio: 1; border-radius: var(--radius-sm); overflow: hidden; box-shadow: var(--elevation-1); gap: 1px; background: var(--border-hairline); }
.scr-sq { background: #D4C8A8; display: flex; align-items: center; justify-content: center; position: relative; font-size: 9px; }
.scr-sq.tw { background: #D94F4F; }
.scr-sq.dw { background: #E8A0B8; }
.scr-sq.st { background: #E8A0B8; }
.scr-sq.has-tile { background: #F5E6C8; }
.scr-label { font-size: 6px; font-weight: 700; color: rgba(255,255,255,0.8); text-align: center; line-height: 1.1; }
.scr-label i[data-lucide] { width: 10px; height: 10px; color: rgba(255,255,255,0.8); }
.scr-tile { font-size: 11px; font-weight: 700; color: #3B2F1E; display: flex; align-items: baseline; gap: 1px; }
.scr-tile sub { font-size: 7px; color: #8B7B5E; }
.scrabble-rack { display: flex; justify-content: center; gap: 6px; padding: 8px 0; }
.scr-tile.rack { width: 36px; height: 36px; background: #F5E6C8; border-radius: 4px; display: flex; align-items: center; justify-content: center; font-size: 16px; font-weight: 700; color: #3B2F1E; box-shadow: 0 2px 4px rgba(0,0,0,0.12); cursor: grab; }
.scr-tile.rack sub { font-size: 9px; }

.game-actions { display: flex; gap: 8px; justify-content: center; padding: var(--space-2) 0 0; }
.game-move { display: flex; align-items: center; gap: 8px; padding: 6px 2px; font-size: 14px; color: var(--text-body); border-top: 1px solid var(--border-hairline); }
.game-move:first-of-type { border-top: none; }

/* =====================================================================
   DESKTOP / WEB LAYOUT  (≥900px)
   Progressive enhancement of the same mobile app. A horizontal top header
   replaces the bottom tab-bar; the create (+) menu drops from a floating
   bottom-right FAB; the footer expands into columns. No markup changes.
   ===================================================================== */
@media (min-width: 900px) {

  /* full-bleed shell — header + footer span the viewport, content is centred */
  .fmh-app { max-width: none; }

  /* full-width top header; inner content held to a centred band */
  .fmh-deskhead {
    display: flex; align-items: center; gap: var(--space-4);
    position: sticky; top: 0; z-index: 40;
    background: var(--surface-card); border-bottom: 1px solid var(--border-hairline);
    padding: 12px max(var(--space-6), calc((100% - 1120px) / 2));
  }
  .fmh-deskhead .dh-nav { flex: 1; justify-content: center; }
  .fmh-topbar { display: none; }
  .fmh-tabbar { display: none; }

  /* inline desktop search — a unified pill: text left, circular magnifier button right */
  .fmh-deskhead .dh-search {
    display: flex; align-items: center;
    width: 240px; height: 42px;
    padding: 3px;
    background: var(--surface-card);
    border: 1.5px solid var(--border-hairline); border-radius: 999px;
    box-shadow: 0 1px 3px rgba(0,0,0,.08);
    transition: border-color .15s, box-shadow .15s;
    overflow: hidden;
  }
  .fmh-deskhead .dh-search:focus-within { border-color: var(--color-brand); box-shadow: 0 0 0 3px rgba(122,46,84,.10); }
  .fmh-deskhead .dh-search input {
    all: unset;
    flex: 1; min-width: 0; height: 100%;
    padding: 0 4px 0 16px;
    color: var(--text-strong); font-family: var(--font-sans); font-size: 14px;
  }
  .fmh-deskhead .dh-search input::placeholder { color: var(--text-subtle); }
  .fmh-deskhead .dh-search .dh-search-btn {
    flex: none; width: 34px; height: 34px; border-radius: 999px;
    border: none; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--surface-panel); color: var(--text-body);
    transition: background .15s, color .15s;
  }
  .fmh-deskhead .dh-search .dh-search-btn:hover { background: var(--color-brand); color: #fff; }

  /* type-ahead panel under the header search. Anchored to the pill's right edge
     so a wider panel grows inwards and never runs off the band. */
  .fmh-deskhead .dh-search-wrap { position: relative; }
  .fmh-deskhead .dh-suggest {
    position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
    width: 380px; max-width: 90vw; max-height: min(70vh, 520px); overflow-y: auto;
    background: var(--surface-card);
    border: 1px solid var(--border-hairline); border-radius: 16px;
    box-shadow: 0 12px 32px rgba(0,0,0,.14);
    padding: 6px;
  }
  .fmh-deskhead .dh-sug-label {
    font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    color: var(--text-subtle); padding: 10px 10px 5px;
  }
  .fmh-deskhead .dh-sug-row {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px; border-radius: 11px;
    text-decoration: none; color: inherit; cursor: pointer;
  }
  .fmh-deskhead .dh-sug-row:hover,
  .fmh-deskhead .dh-sug-row.on { background: var(--surface-panel); }
  .fmh-deskhead .dh-sug-ico {
    flex: none; width: 32px; height: 32px; border-radius: 10px;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--surface-panel); color: var(--color-brand);
  }
  .fmh-deskhead .dh-sug-row.on .dh-sug-ico { background: var(--surface-card); }
  .fmh-deskhead .dh-sug-ico i { width: 16px; height: 16px; }
  .fmh-deskhead .dh-sug-txt { flex: 1; min-width: 0; }
  .fmh-deskhead .dh-sug-title {
    display: block; font-weight: 700; font-size: 14px; color: var(--text-strong);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .fmh-deskhead .dh-sug-sub {
    display: block; font-size: 12.5px; color: var(--text-subtle);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .fmh-deskhead .dh-sug-all {
    display: block; text-align: center; text-decoration: none;
    margin-top: 4px; padding: 11px 10px; border-top: 1px solid var(--border-hairline);
    font-size: 13.5px; font-weight: 700; color: var(--color-brand);
    border-radius: 0 0 11px 11px;
  }
  .fmh-deskhead .dh-sug-all:hover,
  .fmh-deskhead .dh-sug-all.on { background: var(--surface-panel); }
  .fmh-deskhead .dh-sug-none {
    padding: 18px 12px; text-align: center; font-size: 13.5px; color: var(--text-subtle);
  }

  /* the mobile pagebar search icon is redundant on desktop (inline field above) */
  .fmh-pagebar .pb-search { display: none; }

  /* page sub-bar becomes a lightweight breadcrumb under the header — no box,
     no border, sits flush above the content band */
  .fmh-pagebar {
    position: static; max-width: 760px; margin: 0 auto; width: 100%;
    background: transparent; border-bottom: none;
    padding: var(--space-4) 0 0; gap: 6px;
  }
  .fmh-pagebar .pb-back { display: none; }
  .fmh-pagebar .pb-crumb, .fmh-pagebar .pb-sep { display: inline-flex; align-items: center; }
  .fmh-pagebar .pb-crumb { color: var(--text-subtle); font-size: 14px; font-weight: var(--weight-medium); text-decoration: none; }
  .fmh-pagebar .pb-crumb:hover { color: var(--color-brand); }
  .fmh-pagebar .pb-sep { color: var(--text-subtle); }
  .fmh-pagebar .title,
  .fmh-pagebar .title.big { font-size: 14px; font-weight: var(--weight-bold); color: var(--text-strong); flex: 1 1 auto; }

  /* content: centred, capped line length, no tab-bar spacer needed */
  .fmh-main { max-width: 760px; margin: 0 auto; padding: var(--space-6) var(--space-6) var(--space-10); }

  /* the create (+) menu now drops from a floating bottom-right FAB */
  .fmh-fab-float {
    display: inline-flex; align-items: center; justify-content: center;
    position: fixed; right: 28px; bottom: 28px; z-index: 1501;
    width: 58px; height: 58px; border-radius: var(--radius-pill); border: none; cursor: pointer;
    background: var(--fab-bg, #7A2E54); color: var(--fab-fg, #fff);
    box-shadow: var(--elevation-3); transition: transform .1s ease, background .15s ease;
  }
  .fmh-fab-float:hover { transform: translateY(-2px); }
  .fmh-fab-float:active { transform: scale(0.95); }
  .fmh-create-sheet { left: auto; right: 28px; bottom: 98px; transform-origin: bottom right;
    transform: translateX(0) translateY(14px) scale(.96);
    /* It floats clear of the tab bar here, so the ceiling is measured from its
       own resting place rather than from the bar it no longer sits above. */
    max-height: calc(100vh  - 98px - 16px);
    max-height: calc(100dvh - 98px - 16px); }
  .fmh-create.open .fmh-create-sheet { transform: translateX(0) translateY(0) scale(1); }

  /* desktop footer: full-width band with a distinct sunken background so it
     reads as a separate zone from the cream page; content held to the band */
  .fmh-foot {
    display: block;
    text-align: left;
    background: var(--surface-sunken);
    border-top: 1px solid var(--border-hairline);
    padding: var(--space-8) max(var(--space-6), calc((100% - 1120px) / 2)) var(--space-6);
  }
  .fmh-foot .foot-cols { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: var(--space-6); }
  .fmh-foot .foot-brand .foot-brand-name { display: block; font-weight: var(--weight-display); font-size: var(--text-h3); color: var(--text-strong); margin: 8px 0 6px; }
  .fmh-foot .foot-brand p { font-size: 13px; color: var(--text-muted); line-height: 1.5; max-width: 240px; }
  .fmh-foot .foot-col h4 { font-size: var(--text-caption); font-weight: var(--weight-bold); letter-spacing: 0.07em; text-transform: uppercase; color: var(--text-muted); margin: 0 0 10px; }
  .fmh-foot .foot-col a { display: block; font-size: 13.5px; color: var(--text-body); padding: 4px 0; }
  .fmh-foot .foot-col a:hover { color: var(--color-brand); }
  .fmh-foot .foot-credit { margin-top: var(--space-6); padding-top: var(--space-4); border-top: 1px solid var(--border-hairline); font-size: var(--text-caption); color: var(--text-subtle); }
  .fmh-foot .foot-credit-links { margin-top: 0; margin-left: 8px; display: inline; }
}

/* ============================================================
   Focused compose modal — the meet-up wizard (added 2026-06-22)
   Bounded, self-contained dialog: header + scrollable body + an
   in-card footer (so the Next/Send bar never floats free). Used on
   $fmh_bare pages (no deskhead / tab-bar / create-FAB behind it).
   ============================================================ */
body.fmh-bare { overflow: hidden; }
body.fmh-bare .fmh-app { max-width: none; min-height: 0; background: transparent; }
body.fmh-bare .fmh-main { padding: 0; max-width: none; margin: 0; }

.mu-modal {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  padding: 0; background: var(--surface-page);
}
.mu-dialog {
  display: flex; flex-direction: column;
  width: 100%; height: 100%; max-height: 100%;
  background: var(--surface-card); overflow: hidden;
}
.mu-dialog-head {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  padding: 12px 12px 12px; border-bottom: 1px solid var(--border-hairline);
}
.mu-dialog-title { flex: 1; text-align: center; font-weight: 800; font-size: 16px; color: var(--text-strong); }
.mu-step-counter { width: 44px; text-align: right; font-size: 13px; font-weight: 600; color: var(--text-subtle); }
.mu-dots-wrap { flex-basis: 100%; display: flex; justify-content: center; margin-top: 8px; }
.mu-dialog-body { flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 18px 18px 24px; }
.mu-dialog-foot {
  display: flex; align-items: center; gap: 10px; flex: none;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--border-hairline); background: var(--surface-card);
}

/* v83a: a short modal that should NOT fill the phone's screen. The default
   above is a full-height sheet, which is right for the meet-up wizard and
   wrong for four lines of instructions - it reads as a page that failed to
   load. Opt in with .mu-modal.sheet > .mu-dialog.compact; everything without
   those classes is untouched. */
@media (max-width: 899px) {
  .mu-modal.sheet { align-items: flex-end; background: rgba(20, 8, 16, .42); }
  .mu-dialog.compact {
    height: auto; max-height: 88vh;
    border-radius: 20px 20px 0 0;
  }
}

/* desktop: a centred, bounded card over a dimmed scrim */
@media (min-width: 900px) {
  .mu-modal { padding: 24px; background: rgba(20, 8, 16, 0.42); }
  .mu-dialog {
    width: 100%; max-width: 680px; height: auto; max-height: calc(100vh - 48px);
    border-radius: 24px; box-shadow: var(--elevation-3, 0 16px 40px rgba(40,12,28,.22));
  }
}

/* ============================================================
   Welcome tour — first-login carousel (added 2026-06-22)
   Token names use CSS-var fallbacks so it stays safe if a token
   is renamed. Bottom-sheet on phones, centred dialog on desktop.
   ============================================================ */
body.fmh-tour-open { overflow: hidden; }

.fmh-tour {
  position: fixed; inset: 0; z-index: 2000;
  display: flex; align-items: flex-end; justify-content: center;
  padding: 16px;
  background: rgba(34, 24, 38, .55);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  animation: fmh-tour-fade .2s ease;
}
@keyframes fmh-tour-fade { from { opacity: 0; } to { opacity: 1; } }

.fmh-tour-card {
  position: relative; width: 100%; max-width: 440px;
  background: var(--surface-card, #fff);
  border-radius: 24px;
  box-shadow: 0 18px 50px rgba(40, 20, 45, .30);
  padding: 30px 22px 18px;
  animation: fmh-tour-rise .28s cubic-bezier(.2, .8, .2, 1);
}
@keyframes fmh-tour-rise {
  from { transform: translateY(18px); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

.fmh-tour-skip {
  position: absolute; top: 12px; right: 14px;
  background: none; border: 0; cursor: pointer;
  font: inherit; font-size: 13px; color: var(--text-muted, #6a6270);
  padding: 6px 8px; border-radius: 8px;
}
.fmh-tour-skip:hover { color: var(--text-strong, #1a1320); }

.fmh-tour-track { position: relative; min-height: 246px; }
.fmh-tour-slide {
  position: absolute; inset: 0;
  opacity: 0; visibility: hidden; transform: translateX(12px);
  transition: opacity .25s ease, transform .25s ease;
  display: flex; flex-direction: column; align-items: center; text-align: center;
}
.fmh-tour-slide.on {
  position: relative; opacity: 1; visibility: visible; transform: none;
}
.fmh-tour-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 64px; height: 64px; border-radius: 20px;
  background: var(--surface-panel, #f1eaf0); color: var(--color-brand, #7A2E54);
  margin-bottom: 16px;
}
.fmh-tour-slide h2 {
  font-size: 21px; font-weight: 800; margin: 0 0 10px;
  color: var(--text-strong, #1a1320);
}
.fmh-tour-slide p {
  font-size: 15px; line-height: 1.6; margin: 0 0 14px;
  color: var(--text-body, #3a3340); max-width: 34ch;
}
.fmh-tour-go {
  display: inline-flex; align-items: center; gap: 6px;
  font-weight: 700; font-size: 14px; text-decoration: none;
  color: var(--color-brand, #7A2E54);
}
.fmh-tour-go:hover { text-decoration: underline; }

.fmh-tour-dots { display: flex; gap: 7px; justify-content: center; margin: 18px 0 14px; }
.fmh-tour-dots .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--border-hairline, #ddd5dc); transition: all .2s ease;
}
.fmh-tour-dots .dot.on { background: var(--color-brand, #7A2E54); width: 20px; border-radius: 4px; }

.fmh-tour-nav { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.fmh-tour-nav button {
  display: inline-flex; align-items: center; gap: 4px;
  font: inherit; font-weight: 700; font-size: 15px;
  border: 0; border-radius: 13px; cursor: pointer;
  padding: 12px 16px; min-height: 44px;
}
.fmh-tour-prev { background: transparent; color: var(--text-muted, #6a6270); padding-left: 6px; }
.fmh-tour-prev:hover { color: var(--text-strong, #1a1320); }
.fmh-tour-next { background: var(--color-brand, #7A2E54); color: #fff; padding-right: 14px; }
.fmh-tour-next:hover { filter: brightness(1.06); }
.fmh-tour-count { font-size: 13px; color: var(--text-muted, #6a6270); }

@media (min-width: 900px) { .fmh-tour { align-items: center; } }

/* ---------- calendar ---------- */
/* --- Calendar layout: combined grid + list --- */
.cal-layout { display: flex; flex-direction: column; gap: 16px; }
.cal-sidebar-inner {
  background: var(--surface-card); border: 1px solid var(--border-hairline);
  border-radius: 18px; padding: 16px; box-shadow: var(--elevation-1);
}
.cal-main { flex: 1; min-width: 0; }
@media (min-width: 720px) {
  .cal-layout { flex-direction: row; align-items: flex-start; gap: 20px; }
  .cal-sidebar { width: 300px; flex: none; position: sticky; top: 12px; }
  .cal-main { flex: 1; }
}

/* IMP-103: the calendar status filter. Replaces a label + three chips whose
   selected style was scoped to a .cal-filters wrapper the markup had lost — so
   all three rendered unfilled and the page never showed what it was filtered to.
   flex: 1 1 0 gives true thirds regardless of label length, so the row lines up
   with the full-width "Suggest Meet" button above it. */
.cal-seg { display: flex; gap: var(--space-2); margin-bottom: 14px; }
.cal-seg-btn {
  flex: 1 1 0; min-width: 0;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 34px; padding: 0 var(--space-2);
  border-radius: var(--radius-pill); border: 1px solid var(--chip-border);
  background: var(--chip-bg); color: var(--chip-fg);
  font-size: 13px; font-weight: var(--weight-bold);
  text-decoration: none; white-space: nowrap;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.cal-seg-btn:hover, .cal-seg-btn:focus-visible { border-color: var(--border-brand); color: var(--color-brand); }
.cal-seg-btn.on {
  background: var(--chip-selected-bg); border-color: var(--chip-selected-bg);
  color: var(--chip-selected-fg);
}
/* Without this the filled segment loses its contrast on hover. */
.cal-seg-btn.on:hover, .cal-seg-btn.on:focus-visible {
  color: var(--chip-selected-fg); border-color: var(--chip-selected-bg);
}
/* "Unconfirmed" is the long one; on the narrowest phones give it the room. */
@media (max-width: 360px) { .cal-seg-btn { font-size: 12px; padding: 0 4px; } }

.cal-month-nav {
  display: flex; align-items: center; justify-content: center; gap: 12px;
}
.cal-month-label { font-size: 16px; font-weight: 700; color: var(--text-strong); min-width: 140px; text-align: center; }
.cal-month-arrow {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 999px; color: var(--text-body);
  transition: background .15s;
}
.cal-month-arrow:hover { background: var(--surface-panel); }

.cal-grid { margin-top: 10px; }
.cal-grid-head {
  display: grid; grid-template-columns: repeat(7, 1fr); text-align: center;
  font-size: 11px; font-weight: 700; color: var(--text-muted); text-transform: uppercase;
  letter-spacing: .03em; padding-bottom: 6px;
  border-bottom: 1px solid var(--border-hairline);
}
.cal-grid-body {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; padding-top: 4px;
}
.cal-day {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  aspect-ratio: 1; border-radius: var(--radius-md);
  text-decoration: none; color: var(--text-body); font-size: 14px;
  position: relative; transition: background .15s; cursor: pointer;
}
.cal-day.empty { pointer-events: none; }
.cal-day:hover { background: var(--surface-panel); }

/* Today: a square outline round the whole cell.
   It used to be a filled plum circle on the number — which is exactly what a day
   of confirmed meet-ups looks like, so an empty today and a busy day were the
   same picture. Marking the cell rather than the number means the two never
   compete: today with nothing on is an empty square, and today with something on
   is a square holding the usual filled or ringed number. The tighter radius is
   deliberate, so it reads as a square against all the circles. */
.cal-day.today {
  background: none;
  border-radius: var(--radius-sm);
  box-shadow: inset 0 0 0 2px var(--color-brand);
}
.cal-day.today:hover { background: var(--surface-panel); }
.cal-day.today .cal-day-num { font-weight: 700; }

/* The chosen day keeps a ring, but a soft one on a rounded cell — the strong
   plum square is today's marker now, and two identical rings would just move the
   confusion rather than fix it. A plain panel fill would not do either: that is
   what hover already looks like. */
.cal-day.selected { background: var(--surface-panel); box-shadow: inset 0 0 0 2px var(--plum-100, #E7D6DF); }
.cal-day.selected.today { background: var(--surface-panel); box-shadow: inset 0 0 0 2px var(--color-brand); }

.cal-day.has-items { font-weight: 600; color: var(--text-strong); }
.cal-day.cal-confirmed .cal-day-num {
  background: var(--color-brand); color: #fff;
  width: 30px; height: 30px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700;
}
.cal-day.cal-unconfirmed .cal-day-num {
  border: 2px solid var(--color-brand); color: var(--text-strong);
  width: 30px; height: 30px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700;
}
.cal-show-all { margin-top: 10px; }

/* ---- Directory ---- */

/* Toolbar */
.dir-toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.dir-interests-link { display: inline-flex; align-items: center; gap: 6px; margin: -4px 2px 12px; font-size: 13.5px; font-weight: 600; color: var(--text-link); text-decoration: none; }
.dir-interests-link:hover { text-decoration: underline; }
.dir-search-wrap { flex: 1; display: flex; align-items: center; gap: 8px; padding: 8px 14px; background: var(--surface-card); border: 1px solid var(--border-hairline); border-radius: var(--radius-pill); color: var(--text-subtle); }
.dir-search-wrap svg { flex: none; }
.dir-search { flex: 1; border: none; background: none; outline: none; font-size: 14px; color: var(--text-body); font-family: inherit; }
.dir-search::placeholder { color: var(--text-subtle); }
.dir-toolbar-btns { display: flex; gap: 4px; flex: none; }
.dir-tbtn { display: inline-flex; align-items: center; justify-content: center; position: relative; width: 38px; height: 38px; border-radius: var(--radius-md); border: 1px solid var(--border-hairline); background: var(--surface-card); color: var(--text-body); cursor: pointer; transition: background .15s, color .15s, border-color .15s; }
.dir-tbtn:hover { border-color: var(--color-brand); color: var(--color-brand); }
.dir-tbtn.active { background: var(--color-brand); color: #fff; border-color: var(--color-brand); }
.dir-filter-count { position: absolute; top: -4px; right: -4px; min-width: 18px; height: 18px; border-radius: 9px; background: var(--color-brand); color: #fff; font-size: 11px; font-weight: 700; display: flex; align-items: center; justify-content: center; padding: 0 4px; line-height: 1; }

/* Active filter pills strip */
.dir-active-filters { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.dir-fpill { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px 4px 12px; border-radius: var(--radius-pill); font-size: 12px; font-weight: 600; background: var(--color-brand-soft, rgba(122,46,84,.08)); color: var(--color-brand); cursor: pointer; border: none; transition: background .15s; }
.dir-fpill:hover { background: var(--color-brand); color: #fff; }
.dir-fpill svg { pointer-events: none; }

/* Status line */
.dir-status { font-size: 13px; font-weight: 600; color: var(--text-subtle); margin-bottom: 10px; }

/* Card grid view */
.dir-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 12px; }
.dir-card { position: relative; display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 18px 10px 14px; background: var(--surface-panel); border-radius: var(--radius-lg); color: inherit; transition: box-shadow .15s; }
.dir-card:hover { box-shadow: var(--shadow-card); }
.dir-card-link { display: flex; flex-direction: column; align-items: center; gap: 8px; text-decoration: none; color: inherit; }
.dir-card-name { font-size: 14px; font-weight: 700; color: var(--text-strong); text-align: center; line-height: 1.3; }
.dir-you { font-weight: 400; color: var(--text-subtle); font-size: 12px; }
.dir-card-badge { display: inline-flex; align-items: center; gap: 3px; font-size: 11.5px; font-weight: 600; color: var(--color-brand); background: var(--color-brand-soft, rgba(122,46,84,.08)); padding: 2px 8px; border-radius: var(--radius-pill); }
.dir-qm { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: var(--radius-pill); background: var(--color-brand-soft, rgba(122,46,84,.08)); color: var(--color-brand); text-decoration: none; transition: background .15s, transform .1s; flex-shrink: 0; }
.dir-qm:hover { background: var(--color-brand); color: #fff; transform: scale(1.08); }
.dir-card .dir-qm { position: absolute; top: 8px; right: 8px; width: 28px; height: 28px; }

/* List view */
.dir-list { display: flex; flex-direction: column; gap: 0; }
.dir-list-item { display: flex; align-items: center; gap: 12px; padding: 10px 4px; border-bottom: 1px solid var(--border-hairline); }
.dir-list-link { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; text-decoration: none; color: inherit; }
.dir-list-name { font-size: 14px; font-weight: 700; color: var(--text-strong); }
.dir-list-badge { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; font-weight: 600; color: var(--color-brand); margin-left: 6px; }

/* Grouped sections */
.dir-group-head { font-size: 12px; font-weight: 700; color: var(--text-subtle); text-transform: uppercase; letter-spacing: .03em; padding: 14px 4px 6px; display: flex; align-items: center; gap: 6px; }
.dir-group-head:first-child { padding-top: 0; }

/* Filter modal extras */
.dir-filter-clear { border: none; background: none; color: var(--color-brand); font-size: 13px; font-weight: 600; cursor: pointer; padding: 4px 8px; }
.dir-filter-section { margin-bottom: 20px; }
.dir-filter-section-head { display: flex; align-items: center; justify-content: space-between; cursor: pointer; padding: 8px 0; user-select: none; }
.dir-filter-section-title { font-size: 14px; font-weight: 700; color: var(--text-strong); display: flex; align-items: center; gap: 6px; }
.dir-filter-section-body { padding: 4px 0 0; }
.dir-filter-option { display: flex; align-items: center; gap: 10px; padding: 8px 4px; cursor: pointer; border-radius: var(--radius-sm); transition: background .1s; }
.dir-filter-option:hover { background: var(--surface-panel); }
.dir-filter-cb { width: 20px; height: 20px; border-radius: 5px; border: 2px solid var(--border-hairline); flex: none; display: flex; align-items: center; justify-content: center; transition: background .15s, border-color .15s; }
.dir-filter-cb.checked { background: var(--color-brand); border-color: var(--color-brand); }
.dir-filter-cb.checked::after { content: ''; display: block; width: 6px; height: 10px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg); margin-top: -2px; }
.dir-filter-optname { flex: 1; font-size: 14px; color: var(--text-body); }
.dir-filter-optcount { font-size: 12px; color: var(--text-subtle); font-weight: 600; }

/* Group rows (used in Grouped view for group-level rows) */
.dir-group-row { display: flex; align-items: center; gap: 0; }
.dir-group-row .dir-group-link { display: flex; align-items: center; gap: 14px; flex: 1; min-width: 0; text-decoration: none; color: inherit; padding: 12px 0; }
.dir-group-row .dir-qm { margin-right: 4px; }

/* Join interest button/badge */
.dir-join-btn { display: inline-flex; align-items: center; gap: 4px; padding: 5px 12px; border-radius: var(--radius-pill); font-size: 12px; font-weight: 600; background: var(--color-brand); color: #fff; border: none; cursor: pointer; transition: opacity .15s; }
.dir-join-btn:hover { opacity: .85; }
.dir-joined-badge { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 600; color: var(--color-success, #2e7d32); }

/* =====================================================================
   iOS safe areas — IMP-92
   The tour asks every man to add Fearless to his home screen, and the head
   declares viewport-fit=cover with a black-translucent status bar. In that
   standalone mode the page genuinely starts at y=0, underneath the status
   bar and the Dynamic Island. Anything painted in that strip cannot be
   tapped — iOS takes the touch before the page sees it — which is why the
   bell and the avatar were unreachable on an iPhone.

   The bottom edge was already handled (tab bar, modal footers). The top and
   the sides were not. Every element pinned to an edge pads itself by the
   matching inset; env() resolves to 0 everywhere else, so nothing changes on
   Android, desktop, or an iPhone used in the browser.
   ===================================================================== */

/* Sides: in landscape the notch eats one edge of the shell. */
.fmh-app {
  padding-left: env(safe-area-inset-left, 0px);
  padding-right: env(safe-area-inset-right, 0px);
}

/* The two mobile headers. Base padding is preserved and the inset added. */
.fmh-topbar  { padding-top: calc(8px + env(safe-area-inset-top, 0px)); }
.fmh-pagebar { padding-top: calc(6px + env(safe-area-inset-top, 0px)); }

/* When both bars show, the brand bar has already cleared the status bar and
   the title bar sits below it — padding it again would double the gap. */
.fmh-topbar + .fmh-pagebar { padding-top: 6px; }

/* Modals are full-screen on mobile, so their head — and its close button —
   sits on the top edge exactly as the topbar does. */
.mu-dialog-head { padding-top: calc(12px + env(safe-area-inset-top, 0px)); }

/* Bottom-anchored overlays clear the home indicator. */
.fmh-tour  { padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }
.fmh-toast { bottom: calc(var(--tabbar-h) + 16px + env(safe-area-inset-bottom, 0px)); }

@media (min-width: 900px) {
  /* iPad in landscape, installed: same story, smaller inset. */
  .fmh-deskhead { padding-top: calc(12px + env(safe-area-inset-top, 0px)); }
}

/* ── Reactions ────────────────────────────────────────────────────────────
   One reaction, two places: praying hands in the prayer room, a thumbs up on
   announcements. Deliberately quiet — a hairline pill that only takes brand
   colour once it is his. It must never read as a like button. */
.fmh-react            { display:flex; align-items:center; gap:8px; margin-top:9px; }
.fmh-react-btn        { display:inline-flex; align-items:center; gap:6px;
                        padding:4px 11px; border-radius:999px; cursor:pointer;
                        font-size:12.5px; font-weight:600; line-height:1;
                        background:transparent; color:var(--text-muted);
                        border:1px solid var(--border-hairline);
                        transition:background .12s ease, border-color .12s ease, color .12s ease; }
.fmh-react-btn:hover  { color:var(--text-body); border-color:var(--border-strong, var(--border-hairline)); }
.fmh-react-btn.on     { color:var(--color-brand); border-color:var(--color-brand);
                        background:color-mix(in srgb, var(--color-brand) 8%, transparent); }
/* Inside the pill now (IMP-115), so it inherits the pill's colour - muted
   when nobody has reacted as him, brand when he has. :empty keeps a zero from
   opening a gap that never closes. */
.fmh-react-count      { font-size:12.5px; font-weight:700; color:inherit; }
.fmh-react-btn .fmh-react-count:not(:empty) { margin-left:6px; }

/* ---------- a chat message (IMP-190) ----------
   The bubble IS the row. It used to be the middle column of three - a 32px
   avatar on the left, a 30px slot for the "..." on the right - which cost
   every message 84px of the width it was written in and left the composer
   below sitting on a different left edge from the conversation above it.
   Both passengers now ride in the bubble's own top line. */
.fmh-msg-bubble {
  background: var(--surface-card);
  border: 1px solid var(--border-hairline);
  border-radius: 16px;
  padding: 11px 13px;
  min-width: 0;
}
/* Name and avatar together are one link to one man, so they travel as one
   target rather than as a picture and a word that happen to sit side by side. */
.fmh-msg-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.fmh-msg-who  {
  display: inline-flex; align-items: center; gap: 7px; min-width: 0;
  text-decoration: none; color: inherit; flex: 1 1 auto;
}
.fmh-msg-who:hover .fmh-msg-name { text-decoration: underline; }
.fmh-msg-name {
  font-weight: var(--weight-bold); color: var(--text-strong); font-size: 14px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fmh-msg-when { font-size: 12px; color: var(--text-subtle); flex: none; }
/* Tight to the right edge, and no taller than the line it sits on - the point
   of moving it in here was to stop it reserving a column of its own. */
.fmh-msg-menu { flex: none; display: inline-flex; margin-right: -4px; }
.fmh-msg-menu .fmh-iconbtn { width: 26px; height: 26px; }
.fmh-msg-menu .fmh-menu { top: 30px; }

/* ---------- emoji answers on a chat message (IMP-191) ----------
   Under the words, not beside them: a man reads the message, then answers it.
   The row wraps rather than scrolls - six is few enough that it never needs to,
   and a hidden seventh chip is a tally nobody can read. */
.fmh-emoji-row {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 9px;
  position: relative;          /* the picker hangs off THIS, not off the button */
}
.fmh-emoji-chips { display: contents; }
.fmh-emoji-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: 999px; cursor: pointer;
  line-height: 1; font-size: 12.5px; font-weight: var(--weight-bold);
  background: transparent; color: var(--text-muted);
  border: 1px solid var(--border-hairline);
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.fmh-emoji-chip:hover { color: var(--text-body); }
.fmh-emoji-chip.on {
  color: var(--color-brand); border-color: var(--color-brand);
  background: color-mix(in srgb, var(--color-brand) 8%, transparent);
}
.fmh-emoji-glyph { font-size: 14px; line-height: 1; }
.fmh-emoji-n     { font-size: 12px; color: inherit; }
/* Quiet, and always there. A control that only appears on hover does not exist
   on a phone, and this is a phone app first. */
.fmh-emoji-add {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0; border-radius: 999px; cursor: pointer;
  background: transparent; border: 1px solid transparent;
  color: var(--text-subtle); opacity: .7;
}
.fmh-emoji-add:hover { opacity: 1; color: var(--color-brand); border-color: var(--border-hairline); }
/* Static, deliberately: .fmh-menu-wrap would make this 26px button the box the
   picker is measured against, and .fmh-menu's right:0 would then hang 200px of
   popover off the left edge of the phone. Measured against the row instead, its
   left edge is the bubble's left edge, which is always on screen however many
   chips have pushed the button along. */
.fmh-emoji-wrap { display: inline-flex; position: static; }
/* Borrows .fmh-menu wholesale - surface, hairline, elevation, and the open
   class app.js already toggles - and only changes where and which way it lays out. */
.fmh-emoji-pick {
  flex-direction: row; min-width: 0; padding: 5px; gap: 2px;
  left: 0; right: auto; top: calc(100% + 4px);
}
.fmh-emoji-pick.open { display: flex; }
/* Selector deliberately two-deep: .fmh-menu button already sets a full-width
   12px-padded list row, and a one-class rule would lose to it. */
.fmh-emoji-pick .fmh-emoji-opt {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; padding: 0; font-size: 20px; line-height: 1;
  background: none; border: none; border-radius: 9px; cursor: pointer;
}
.fmh-emoji-pick .fmh-emoji-opt:hover { background: var(--surface-page); }

/* A card that is a link, but carries a real button inside it (the feed's
   announcement acknowledgement). The link is stretched behind the content
   rather than wrapped around it, so the button stays a button. */
.fmh-card-stretch          { position:relative; border:1px solid var(--card-border);
                             box-shadow:var(--elevation-1); transition:box-shadow .15s ease; }
.fmh-card-stretch:hover    { box-shadow:var(--elevation-2); }
.fmh-stretch               { position:absolute; inset:0; z-index:1; border-radius:inherit; }
.fmh-card-stretch .fmh-react { position:relative; z-index:2; margin-top:0; }
/* IMP-160: event highlights - on the feed, at the top of the event's page, and the picker */
.ev-img      { display:block; width:100%; aspect-ratio:16/9; object-fit:cover; border-radius:10px;
               background:var(--surface-sunken, #f1ecef); margin-bottom:12px; }
.ev-when     { display:inline-flex; align-items:center; gap:6px; font-size:14px; font-weight:700; color:var(--color-brand); }
.ev-hero     { padding:12px; margin-bottom:14px; flex:none; }
.ev-hero .ev-img { max-height:220px; }
.ev-hero-row { display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; padding:0 2px; }
.ev-pick     { position:relative; display:flex; align-items:center; justify-content:center; min-height:120px;
               border:1.5px dashed var(--card-border); border-radius:12px; overflow:hidden; cursor:pointer;
               color:var(--text-muted); font-size:14px; }
.ev-pick input { position:absolute; inset:0; opacity:0; cursor:pointer; }
.ev-pick img { width:100%; aspect-ratio:16/9; object-fit:cover; display:block; }
.ev-pick-empty { display:inline-flex; align-items:center; gap:8px; }
.ev-pick.has { border-style:solid; }
.ev-pick.has .ev-pick-empty { display:none; }
/* v94: the event card's buttons wrap on a narrow phone rather than squash; the
   ones he taps sit above the card's stretched link. */
.ev-actions  { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-top:12px; }
.ev-raise    { position:relative; z-index:2; margin:0; }
.ev-got      { font-size:13px; padding:4px 11px 4px 8px; }
.ev-ticket-row { display:flex; align-items:center; justify-content:space-between; gap:8px 10px; flex-wrap:wrap;
                 margin:10px 2px 0; padding-top:10px; border-top:1px solid var(--border-hairline); font-size:13px; }
.ev-edit-link  { display:inline-flex; align-items:center; gap:5px; margin:8px 2px 0; font-size:13px; font-weight:600; color:var(--text-link); text-decoration:none; }
.ev-pick-keep { display:flex; align-items:center; gap:8px; margin-top:8px; font-size:14px; color:var(--text-body); }
/* v94: an app event on the Meet-ups calendar - a double-line square round the
   number. Square, so it never reads as a meet-up's circle; doubled, so it never
   reads as today's single square. A meet-up on the same day keeps its circle
   inside the square. */
.cal-day.cal-event .cal-day-num {
  position: relative; min-width: 26px; min-height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700; color: var(--text-strong);
}
.cal-day.cal-event.cal-confirmed .cal-day-num { color: #fff; }
.cal-day.cal-event .cal-day-num::after {
  content: ''; position: absolute; inset: -4px; pointer-events: none;
  border: 4px double var(--color-brand); border-radius: 4px;
}
.cal-event-row .ico-tile { color: var(--color-brand); }
.cal-event-row .fmh-badge { flex: none; white-space: nowrap; }
.cal-legend { display:flex; flex-wrap:wrap; gap:6px 14px; margin-top:10px; font-size:12px; color:var(--text-muted); }
.cal-legend span { display:inline-flex; align-items:center; gap:6px; }
.cal-legend i.k { display:inline-block; width:12px; height:12px; }
.cal-legend .k-conf  { background:var(--color-brand); border-radius:999px; }
.cal-legend .k-unc   { border:2px solid var(--color-brand); border-radius:999px; }
.cal-legend .k-event { border:4px double var(--color-brand); border-radius:2px; width:14px; height:14px; }

/* v86: Today's thought on Home */
.home-thought { border-color: rgba(122,46,84,.28); }
.home-thought-body { margin-top:4px; font-size:15.5px; line-height:1.55; color:var(--text-body);
                     display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:12; line-clamp:12; overflow:hidden; }
.home-thought-acts { display:flex; align-items:center; gap:8px; margin-top:12px; flex-wrap:wrap; }
.home-thought-acts > * { position:relative; z-index:2; }

/* v86a: Thought for the Day threads (stream.php) */
.fmh-thought-label { display:flex; align-items:center; gap:5px; font-size:11.5px; font-weight:700; color:var(--color-brand); margin-bottom:6px; }
.fmh-msg-bubble.fmh-thought-bubble { border-color: rgba(122,46,84,.32) !important; }
.fmh-thought-replies { margin:10px 0 0 22px; padding-left:14px; border-left:2px solid var(--border-hairline); display:flex; flex-direction:column; gap:10px; }
.fmh-thought-replies .fmh-composer { margin-top:2px; }
.fmh-thought-back { display:inline-flex; align-items:center; gap:6px; font-size:13.5px; font-weight:600; color:var(--color-brand); text-decoration:none; margin:0 0 12px; }
a.fmh-thought-old { display:block; padding:12px 14px; text-decoration:none; color:inherit; }
.fmh-thought-old-body { font-size:14px; line-height:1.5; color:var(--text-body);
                        display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:3; line-clamp:3; overflow:hidden; }
.fmh-thought-old-foot { display:flex; align-items:center; gap:6px; margin-top:8px; font-size:12.5px; color:var(--text-muted); }
.fmh-thought-old-foot svg:last-child { margin-left:auto; }
@media (max-width: 480px) { .fmh-thought-replies { margin-left:8px; padding-left:10px; } }

/* Icon-only: a thumbs up needs no caption. */
.fmh-react-btn.icon-only   { padding:5px 9px; gap:0; }
/* Once it is his, the thumb fills — the clearest possible "yes, that's me",
   and the one state difference that survives being 16px on a feed card. */
.fmh-react-btn.on .fmh-glyph-thumbs-up path { fill:currentColor; }

/* ---------- view-as bar (superadmin only, and only while a hat is on) ------ */
:root { --viewas-h: 40px; }

.fmh-viewas {
  position: fixed; top: 0; left: 0; right: 0; height: var(--viewas-h);
  z-index: 1600;                     /* over the create sheet, under modals */
  display: flex; align-items: center; gap: var(--space-3);
  padding: 0 var(--space-3);
  background: var(--color-brand); color: #fff;
  box-shadow: 0 1px 6px rgba(0,0,0,.22);
  font-size: 12.5px;
}
.fmh-viewas .va-flag  { display: flex; align-items: center; gap: 7px; min-width: 0; flex: 1; }
.fmh-viewas .va-flag b     { font-weight: 700; white-space: nowrap; }
.fmh-viewas .va-flag small { opacity: .78; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fmh-viewas .va-btns  { display: flex; align-items: center; gap: 5px; flex: none; }

.va-btn {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  padding: 4px 9px; border-radius: 999px; line-height: 1;
  font-size: 12px; font-weight: 600; white-space: nowrap;
  background: rgba(255,255,255,.14); color: #fff;
  border: 1px solid rgba(255,255,255,.28);
}
.va-btn:hover  { background: rgba(255,255,255,.24); }
.va-btn.on     { background: #fff; color: var(--color-brand); border-color: #fff; }
.va-min        { display: inline-flex; cursor: pointer; flex: none; padding: 4px;
                 background: transparent; border: 0; color: #fff; opacity: .8; }
.va-min:hover  { opacity: 1; }

/* Push the page down so the bar never sits on top of the sticky headers —
   which are the very thing you put the hat on to look at. */
body.fmh-viewas-on:not(.fmh-viewas-min)                { padding-top: var(--viewas-h); }
body.fmh-viewas-on:not(.fmh-viewas-min) .fmh-topbar,
body.fmh-viewas-on:not(.fmh-viewas-min) .fmh-pagebar,
body.fmh-viewas-on:not(.fmh-viewas-min) .fmh-deskhead  { top: var(--viewas-h); }

/* .fmh-viewas-pill sets display, which outranks the UA sheet's [hidden] rule —
   without this the collapsed pill sits on top of the expanded bar. */
.fmh-viewas[hidden], .fmh-viewas-pill[hidden] { display: none !important; }

.fmh-viewas-pill {
  /* Bottom-left: clear of the header it is meant to stop obscuring, clear of
     the FAB bottom-right, and lifted above the mobile tab bar. */
  position: fixed; left: 12px; z-index: 1600; cursor: pointer;
  bottom: calc(var(--tabbar-h) + 12px + env(safe-area-inset-bottom, 0px));
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; border-radius: 999px; border: 0;
  font-size: 12px; font-weight: 700; line-height: 1;
  background: var(--color-brand); color: #fff;
  box-shadow: 0 2px 8px rgba(0,0,0,.28);
}

@media (max-width: 560px) {
  .fmh-viewas .va-flag small { display: none; }
  .fmh-viewas .va-btn span   { display: none; }   /* icons only — the bar must not wrap */
  .fmh-viewas .va-btn        { padding: 5px 8px; }
}

/* ---------- stream audience chip (IMP-106) ---------- */
/* A restricted chat has to look different at a glance, not just read
   differently — the bug was that it looked identical to a public one. */
.fmh-chip.sm.audience-locked {
  background: color-mix(in srgb, var(--color-brand) 10%, transparent);
  border-color: var(--color-brand);
  color: var(--color-brand);
  font-weight: 700;
}
.fmh-chip.sm.audience-soft { color: var(--text-body); border-color: var(--border-strong); }
.fmh-chip.sm.audience-open { color: var(--text-subtle); }

/* ---------- meet-up outcome screens (IMP-104) ---------- */
/* These were the only full-screen states rendered as bare text straight onto
   the page background; every other screen in the app puts its content on a
   card. */
.fmh-outcome-card {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  width: 100%; max-width: 380px;
  padding: var(--space-8) var(--space-6);
}
/* A destructive action that still has to look like a button beside its
   neighbour — same shape and border, colour carrying the meaning instead. */
.fmh-btn.secondary.quiet-danger { color: var(--btn-danger-bg); }
.fmh-btn.secondary.quiet-danger:hover {
  color: var(--btn-danger-bg);
  border-color: var(--btn-danger-bg);
  background: color-mix(in srgb, var(--btn-danger-bg) 7%, transparent);
}

/* ---------- meet-up header card (IMP-148) ----------
   One card carrying heading, when, where, "In calendar" and the host's note,
   in place of a bare heading plus two panels. Deliberately shaped like
   .fmh-outcome-card on the confirmed screen - same centring, same round icon,
   same title weight - so the page a man opens the day he is asked and the page
   he opens the day it happens read as one thing. */
.mu-head {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 24px 18px; margin-bottom: 18px;
}
.mu-head-ico {
  width: 56px; height: 56px; border-radius: var(--radius-pill);
  background: var(--surface-panel); color: var(--color-brand);
  display: inline-flex; align-items: center; justify-content: center;
}
.mu-head-title {
  font-size: 20px; line-height: 1.3; font-weight: var(--weight-display);
  color: var(--text-strong); margin: 12px 0 0;
}
.mu-head-line {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  flex-wrap: wrap; margin-top: 7px;
  font-size: 14px; font-weight: var(--weight-bold); color: var(--text-body); line-height: 1.4;
}
.mu-head-line i[data-lucide] { flex: none; color: var(--text-muted); }
.mu-head-line a { color: var(--color-brand); text-decoration: none; font-size: 13px; }
.mu-head-pills { margin-top: 12px; }
/* The note reads as a quotation, not as a field: it is the host's own words. */
.mu-head-note {
  position: relative; display: flex; align-items: flex-start; gap: 8px; margin-top: 14px;
  width: 100%; padding: 10px 12px; border-radius: var(--radius-md);
  background: var(--surface-panel); text-align: center;
}
/* v82a: centred like everything above it. The pencil is pulled out of the flow
   so it cannot shift the words off the card's centre line. */
.mu-head-note .body {
  flex: 1; min-width: 0; font-size: 14px; line-height: 1.5; color: var(--text-body);
  white-space: pre-line; overflow-wrap: anywhere; font-style: italic;
  padding: 0 14px;
}
.mu-head-note.empty .body { color: var(--text-subtle); font-style: normal; }
.mu-head-edit {
  position: absolute; top: 8px; right: 8px;
  background: none; border: 0; cursor: pointer; padding: 2px;
  color: var(--text-muted); line-height: 0; border-radius: var(--radius-sm);
}
.mu-head-edit:hover { color: var(--color-brand); }

/* The cascade list's own heading, which used to be a third card above it. */
.mu-list-head { margin-bottom: 14px; }
.mu-list-head .who { font-size: 13px; font-weight: var(--weight-bold); color: var(--text-strong); }
.mu-list-head .how { font-size: 12.5px; color: var(--text-subtle); line-height: 1.45; margin-top: 2px; }

/* On a phone the status badge was squeezing the name into two lines beside it.
   Wrapping puts the badge underneath instead, which reads better and is what
   the name wanted all along. */
@media (max-width: 480px) { .fmh-step .body .name { flex-wrap: wrap; } }

/* Home Screen card's three answers (v83). They do not fit one phone row, so
   the row wraps and the primary answer stays last - the position the eye
   finishes on. */
.home-install-acts {
  display: flex; flex-wrap: wrap; gap: 8px;
  justify-content: flex-end; align-items: center; margin-top: 12px;
}
.home-install-acts > form { margin: 0; }

/* Host controls on the live step. Wrapping row, everything the same weight. */
.mu-step-acts { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.mu-step-acts > form { margin: 0; }

/* ---------- meet-up reply row (v62) ----------
   Three equal answers on one row - I'm in, Suggest another time, Not this
   time - or two when the host switched counter-offers off.
   Icon over label rather than beside it: three side-by-side labels do not fit
   a phone's width, and "Suggest another time" would otherwise either overflow
   or push its neighbours narrow. Stacked, each cell wraps inside itself and
   the row stays level, because every button is stretched to the tallest.
   minmax(0, 1fr) rather than 1fr, so a long label cannot widen its own column. */
.mu-reply-row {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px; align-items: stretch;
}
.mu-reply-row.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.mu-reply-row > form { margin: 0; display: flex; }
.mu-reply-btn.fmh-btn {
  width: 100%; height: 100%; min-height: 70px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 5px; padding: 10px 6px;
  white-space: normal; text-align: center; line-height: 1.2; font-size: 13.5px;
}

/* The last "Adjust meet-up" on a confirmed card: who, when, and his word. */
.mu-adjusted {
  display: flex; align-items: flex-start; gap: 8px; text-align: left;
  max-width: 300px; margin: 12px auto 0; padding: 9px 12px;
  background: var(--surface-panel); border-radius: 12px;
  font-size: 13px; line-height: 1.45; color: var(--text-body);
}
.mu-adjusted svg, .mu-adjusted i { flex: none; margin-top: 2px; color: var(--color-brand); }

/* The reasons men gave, on the host's "No takers this time" screen. */
.mu-reasons {
  width: 100%; max-width: 300px; margin-top: 16px;
  display: flex; flex-direction: column; gap: 8px; text-align: left;
}
.mu-reason {
  background: var(--surface-card); border: 1px solid var(--border-hairline);
  border-radius: 12px; padding: 9px 12px;
  font-size: 13.5px; line-height: 1.45; color: var(--text-body);
}
.mu-reason strong { display: block; font-size: 13px; color: var(--text-strong); }

/* v74: getting-started checklist on Home (same steps as his profile). */
.home-setup-steps { display: flex; flex-direction: column; gap: 2px; margin-top: 12px; }
.home-setup-step { display: flex; align-items: center; gap: 10px; padding: 9px 4px; border-top: 1px solid var(--border-hairline); text-decoration: none; color: inherit; }
.home-setup-step:first-child { border-top: none; }
.home-setup-step .hs-tick { flex: none; width: 20px; height: 20px; border-radius: 50%; border: 2px solid var(--border-strong, #c9bfc4); display: inline-flex; align-items: center; justify-content: center; }
.home-setup-step.done .hs-tick { background: var(--color-success, #2f7d4f); border-color: var(--color-success, #2f7d4f); color: #fff; }
.home-setup-step .hs-label { display: block; font-size: 14px; font-weight: 600; color: var(--text-strong); }
.home-setup-step.done .hs-label { font-weight: 500; color: var(--text-muted); text-decoration: line-through; }
.home-setup-step .hs-hint { display: block; font-size: 12.5px; color: var(--text-body); line-height: 1.45; margin-top: 1px; }

/* v74: the quick meet-up button on a Contacts tile says what it does - phones
   have no hover, so a bare coffee cup with a title was a guess. */
.dir-qm.has-label { width: auto; padding: 0 9px 0 7px; gap: 4px; font-size: 11.5px; font-weight: 700; }
.fmh-btn[hidden], .home-install[hidden] { display: none !important; }

/* ---------- viewing as a test account (v75) ---------- */
/* Amber rather than brand plum, so it never reads as the hat bar: this one
   means you are signed in as someone else. */
.fmh-viewas.is-test, .fmh-viewas-pill.is-test { background: #8A5A00; }
.fmh-viewas.is-test .va-btn.on { color: #8A5A00; }
.fmh-viewas .va-pick { display: inline-flex; }
.fmh-viewas .va-pick select {
  font: inherit; font-size: 12px; font-weight: 600; color: #fff; cursor: pointer;
  background: rgba(255,255,255,.14); border: 1px solid rgba(255,255,255,.28);
  border-radius: 999px; padding: 3px 8px; max-width: 120px;
}
.fmh-viewas .va-pick select option { color: #2b2230; }
@media (max-width: 560px) {
  .fmh-viewas.is-test .va-btn.on span { display: inline; }   /* "Back to me" must stay readable */
  .fmh-viewas .va-pick select { max-width: 84px; }
}
.fmh-badge.test { background: #FBEFD9; color: #8A5A00; }

/* ---- Interest icons (v76): Tabler inline SVGs + the picker ---- */
svg.ti { display: inline-block; vertical-align: middle; flex: none; }
.ie-icon-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.icon-tiles { display: flex; gap: 6px; flex-wrap: wrap; }
.icon-tile { position: relative; width: 44px; height: 44px; border-radius: 12px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-panel); color: var(--color-brand); border: 2px solid transparent; cursor: pointer; padding: 0; }
.icon-tile input { position: absolute; opacity: 0; pointer-events: none; }
.icon-tile:has(input:checked) { border-color: var(--color-brand); background: var(--surface-card, #fff); }
.icon-tile:has(input:focus-visible) { outline: 2px solid var(--color-brand); outline-offset: 2px; }
.icon-tile.none { color: var(--text-subtle); }
.icon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(48px, 1fr)); gap: 6px; max-height: 50vh; overflow-y: auto; }
.icon-grid .icon-tile { width: 100%; }
.icon-grid .icon-tile:hover { border-color: var(--border-brand); }

/* v76c: bin on an announcement card (leaders), outside the card's link */
.ann-del-wrap { position: relative; }
.ann-del-wrap .ann-del-btn { position: absolute; right: 10px; bottom: 8px; color: var(--text-subtle); }
.ann-del-wrap .ann-del-btn:hover { color: var(--color-danger); }

/* v77: the message a notification pointed at */
.fmh-msg-target { scroll-margin-top: 90px; }
/* v85b: the glow sits on the bubble only, thin ring, slow gentle fade */
.fmh-msg-target .fmh-msg-bubble, .fmh-msg-target .mu-chat-bubble { transition: box-shadow 1.2s ease; }
.fmh-msg-target.fmh-flash .fmh-msg-bubble, .fmh-msg-target.fmh-flash .mu-chat-bubble { box-shadow: 0 0 0 1.5px rgba(122,46,84,.55), 0 0 10px rgba(122,46,84,.18); }

/* ---------- v87: meet-up page, wider on desktop ----------
   The page used the 760px reading column with a 380px card in it, so a laptop
   showed a narrow strip of meet-up and a lot of background. Up here it widens,
   and meetup.php moves the chat and private notes into a column beside it. */
@media (min-width: 900px) {
  .fmh-main.mu-wide { max-width: 1180px; }
  body:has(.mu-layout.two-col) .fmh-pagebar { max-width: 1180px; padding-left: var(--space-6); padding-right: var(--space-6); }
  .fmh-main.mu-wide:not(:has(.mu-layout.two-col)) { max-width: 760px; }
  .mu-layout.two-col { display: grid; grid-template-columns: minmax(0, 1fr) minmax(320px, 420px); gap: 28px; align-items: start; }
  .mu-layout:not(.two-col) .mu-col-main { max-width: 760px; margin: 0 auto; }
  .mu-col-side { display: none; }
  .mu-layout.two-col .mu-col-side { display: block; position: sticky; top: 16px; }
  .mu-col-side .mu-chat { margin-top: 0; padding: 18px; border-top: none; background: var(--surface-card);
                          border: 1px solid var(--border-hairline); border-radius: var(--radius-lg, 22px); }
  .mu-col-side #mu-notes { margin-top: 18px; }
  .mu-col-side #mu-notes:first-child { margin-top: 0; }
  /* The centred outcome card and its lines were sized for a phone. */
  .mu-wide .fmh-center-screen.flow { padding-top: var(--space-6); padding-left: 0; padding-right: 0; }
  .mu-wide .fmh-outcome-card { max-width: 620px; }
  .mu-wide .fmh-outcome-card > p,
  .mu-wide .fmh-outcome-card > div[style*="max-width"] { max-width: 440px !important; }
  .mu-wide .fmh-center-screen > p,
  .mu-wide .fmh-center-screen > div[style*="max-width"] { max-width: 440px !important; }
}

/* ---------- v87a: confirmed meet-up card ----------
   Phone: one centred stack, as before. Desktop: the card fills its column,
   the headline and the note/adjustment sit side by side, the buttons in one row. */
.mu-out-grid, .mu-out-head, .mu-out-aside { display: flex; flex-direction: column; align-items: center; width: 100%; }
.mu-out-actions { margin-top: 20px; display: flex; flex-direction: column; align-items: center; gap: 10px; width: 100%; max-width: 300px; }
@media (min-width: 900px) {
  .mu-layout.two-col .fmh-center-screen.flow { padding-top: 0; }
  .mu-layout.two-col .fmh-outcome-card { max-width: none; padding: var(--space-6); }
  .mu-wide .mu-out-grid.has-aside { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; align-items: center; }
  .mu-wide .mu-out-aside > div[style*="max-width"] { max-width: none !important; margin-top: 0 !important; }
  .mu-wide .mu-out-aside .mu-adjusted { max-width: none; width: 100%; }
  .mu-wide .mu-out-actions { flex-direction: row; max-width: none; margin-top: 24px; }
  .mu-wide .mu-out-actions > .fmh-btn { flex: 1 1 0; min-width: 0; }
}

/* v97: meet-up photos. A tidy square grid of up to six, and a full-screen
   viewer on a dark ground so the photo, not the chrome, is what you see. */
/* The consent tick above the photo picker. Given room to breathe rather than
   tucked beside the button: it is a promise about other people, not a setting. */
.mu-consent { display: flex; gap: 9px; align-items: flex-start; margin: 0 0 11px;
              font-size: 13px; line-height: 1.45; color: var(--text-body); cursor: pointer; }
.mu-consent input { margin: 2px 0 0; flex: none; width: 17px; height: 17px; accent-color: var(--color-brand); }

/* A shared photo on Home. Sits in the feed like any other card. */
.fd-photos { display: grid; gap: 6px; margin-top: 11px; border-radius: 8px; overflow: hidden; }
.fd-photos.n1 { grid-template-columns: 1fr; }
.fd-photos.n2 { grid-template-columns: repeat(2, 1fr); }
.fd-photos.n3, .fd-photos.n4 { grid-template-columns: repeat(2, 1fr); }
.fd-photos img { width: 100%; height: 100%; object-fit: cover; display: block; background: var(--surface-panel); }
.fd-photos.n1 img { max-height: 340px; }
.fd-photos.n2 img, .fd-photos.n3 img, .fd-photos.n4 img { aspect-ratio: 1 / 1; }
.fd-photos a { display: block; min-width: 0; position: relative; }
.fd-photos .more { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
                   background: rgba(0,0,0,.45); color: #fff; font-weight: var(--weight-bold); font-size: 17px; }

.mu-photo-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.mu-photo-tile { position: relative; aspect-ratio: 1 / 1; padding: 0; border: 0; border-radius: var(--radius-md);
                 overflow: hidden; background: var(--surface-panel); cursor: zoom-in; }
.mu-photo-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mu-photo-dialog .mu-dialog-body { display: flex; align-items: center; justify-content: center; background: #111; }
.mu-photo-full { display: block; max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
@media (min-width: 900px) {
  .mu-photo-dialog { max-width: 960px; height: auto; max-height: 92vh; border-radius: var(--radius-lg); }
  .mu-photo-full { max-height: calc(92vh - 130px); }
}

/* ── Prayer requests (v105) ──────────────────────────────────────────────────
   A request card is NOT a link. The praying button and the replies link are
   both real controls, and a stretch-link laid over the top of them leaves the
   browser to decide which one a thumb meant. */
.pr-ask-btn { width: 100%; justify-content: center; margin-bottom: 14px; }
.pr-card { padding: 14px 15px; }
.pr-card-head { display: flex; gap: 10px; align-items: center; margin-bottom: 9px; }
.pr-card-who { font-weight: 700; color: var(--text-strong); font-size: 14.5px; }
.pr-card-meta { font-size: 12px; color: var(--text-subtle); display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.pr-aud { display: inline-flex; align-items: center; gap: 4px; }
.pr-card-body { font-size: 15px; color: var(--text-body); line-height: 1.5; white-space: pre-wrap; }
.pr-card-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 11px; }
.pr-replies { display: inline-flex; align-items: center; gap: 5px; font-size: 13.5px; font-weight: 600;
              color: var(--color-brand); text-decoration: none; margin-left: auto; }
.pr-replies:hover { text-decoration: underline; }
/* An anonymous request shows no initials and no photo. Initials are a name. */
.pr-anon-mark { flex: none; width: 34px; height: 34px; border-radius: 50%; display: inline-flex;
                align-items: center; justify-content: center; background: var(--surface-sunken);
                border: 1px dashed var(--border-hairline); color: var(--text-subtle); }
.pr-feed .pr-card-head { margin-top: 4px; }

/* ---------- v106: mobile Menu overlay ---------- */
/* Trigger pair. The topbar is mobile-only, so re-laying it out here is safe:
   brand and menu group to the left, the icons keep the right-hand edge. */
.fmh-topbar { justify-content: flex-start; gap: 4px; padding-left: 12px; padding-right: 12px; }
.fmh-topbar .actions { margin-left: auto; gap: 2px; }
/* v106d: the brand lockup is a <button> now. Strip the UA button chrome and
   give it the tap height; min-width:0 so a longer space name ellipses instead
   of shoving the avatar off the edge — "Fearless" fits, a future space's name
   might not. Four round targets plus this leaves ~45px of slack at 375px. */
.fmh-topbar .brand-lockup { gap: 8px; min-width: 0; }
.fmh-brandmenu {
  height: var(--touch-min); padding: 0 6px 0 0;
  background: none; border: 0; cursor: pointer;
  font: inherit; color: inherit; text-align: left;
  border-radius: var(--radius-md);
}
.fmh-brandmenu:active { background: var(--surface-panel); }
.fmh-topbar .brand-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The caret is what says "this does something". Muted so it reads as chrome
   beside the wordmark rather than as part of the mark. */
.fmh-brandmenu-caret { display: inline-flex; align-items: center; color: var(--text-muted); margin-left: -2px; }
body.fmh-navmenu-open .fmh-brandmenu-caret { transform: rotate(180deg); }
.pb-menu { display: flex; align-items: center; gap: 2px; margin-left: auto; }

/* The page bar's own trigger: bars, no word. Square, like the icon buttons
   it sits among. */
.fmh-menubtn {
  display: inline-flex; align-items: center; justify-content: center;
  height: var(--touch-min); padding: 0 8px;
  background: none; border: 0; cursor: pointer;
  color: var(--text-body); border-radius: var(--radius-pill);
  font: inherit; font-size: var(--text-small); font-weight: 600;
  line-height: 1; white-space: nowrap;
}
.fmh-menubtn-icon { width: var(--touch-min); padding: 0; }
.fmh-menubtn:active { background: var(--surface-panel); }
.fmh-menubtn-label { display: inline-block; }
.fmh-menubars { display: flex; flex-direction: column; gap: 3px; width: 18px; }
.fmh-menubars span { display: block; height: 2px; border-radius: 2px; background: currentColor; }
.fmh-menubars span:nth-child(2) { width: 74%; }

/* Prayer, one tap from anywhere. Deliberately NOT inside the overlay.
   v106a: grey like search and the bell rather than plum. It sits in a row of
   line icons, and the one coloured glyph read as a state — as though prayer
   were switched on — rather than as another way through. */
.fmh-praybtn { color: var(--text-body); }

.fmh-navmenu { position: fixed; inset: 0; z-index: 90; }
.fmh-navmenu-scrim { position: absolute; inset: 0; background: rgba(20, 12, 16, .45); }
.fmh-navmenu-sheet {
  position: relative;
  max-height: 88vh; overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--surface-card);
  border-radius: 0 0 var(--radius-lg, 18px) var(--radius-lg, 18px);
  box-shadow: var(--elevation-3, 0 16px 40px rgba(40,12,28,.22));
  padding-bottom: 10px;
  animation: fmhMenuDrop .16s ease-out;
}
@keyframes fmhMenuDrop { from { transform: translateY(-10px); opacity: .4; } to { transform: none; opacity: 1; } }
.fmh-navmenu-sheet:focus { outline: none; }
/* .fmh-iconbtn sets display:flex, which beats the UA stylesheet's rule for
   the hidden attribute — so the back arrow stayed visible on the main
   panel. Anything inside the sheet obeys hidden. */
.fmh-navmenu-sheet [hidden] { display: none !important; }
body.fmh-navmenu-open { overflow: hidden; }

.fmh-navmenu-head {
  display: flex; align-items: center; gap: 6px;
  padding: calc(10px + env(safe-area-inset-top, 0px)) var(--space-3) 10px;
  border-bottom: 1px solid var(--border-hairline);
  position: sticky; top: 0; background: var(--surface-card); z-index: 1;
}
.fmh-navmenu-title { flex: 1; font-weight: var(--weight-display); font-size: var(--text-h3); color: var(--text-strong); }

.fmh-navmenu-nav { padding: 6px var(--space-2) 0; }
.fmh-navmenu-row {
  display: flex; align-items: center; gap: 13px;
  min-height: 52px; padding: 0 12px;
  border-radius: var(--radius-md);
  font-weight: var(--weight-display); font-size: var(--text-h3);
  color: var(--text-strong);
}
.fmh-navmenu-row.active { background: var(--color-brand-soft); color: var(--color-brand); }
.fmh-navmenu-ico { display: flex; color: var(--text-muted); flex: none; }
.fmh-navmenu-row.active .fmh-navmenu-ico { color: inherit; }

.fmh-navmenu-more {
  display: flex; align-items: center; gap: 13px; width: calc(100% - var(--space-3));
  margin: 8px var(--space-2) 0; padding: 12px;
  background: var(--surface-panel);
  border: 0; border-radius: var(--radius-md); cursor: pointer;
  font: inherit; text-align: left; color: var(--text-strong);
}
.fmh-navmenu-more > span:nth-child(2) { flex: 1; font-weight: var(--weight-display); }
.fmh-navmenu-more small { display: block; font-weight: 400; font-size: var(--text-small); color: var(--text-muted); }

.fmh-navmenu-group { padding: 14px var(--space-3) 0; }
.fmh-navmenu-group h4 {
  font-size: var(--text-small); text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-muted); margin-bottom: 4px;
}
.fmh-navmenu-group a { display: block; padding: 11px 0; color: var(--text-strong); border-bottom: 1px solid var(--border-hairline); }
.fmh-navmenu-group a:last-child { border-bottom: 0; }
.fmh-navmenu-ver { padding: 14px var(--space-3) 4px; font-size: var(--text-small); color: var(--text-muted); }

/* Desktop has the full nav in its own header — the sheet and its triggers have
   nothing to add there, and a stray hamburger beside it would just confuse. */
@media (min-width: 900px) {
  .fmh-navmenu, .pb-menu { display: none !important; }
}

/* No narrow-phone override any more. The bar carries brand + Menu + four
   icons; at 4px gaps that fits 375px with room to spare, now the two console
   icons have gone to the overlay. Measure before adding a sixth. */

/* On a page bar the title is already competing with a back arrow and a search
   icon, and "Thought for the Day" was wrapping to two lines. The word "Menu"
   teaches the control on the top-level pages, where the brand bar has room for
   it; by the time a man is inside a page he has met it, and the bars alone can
   give the title its width back. */


/* IMP-185 — a man's own detail on an interest ("Football (Hearts, Man United)").
   Set in the tag's own size, weight and colour: his team is part of what the
   tag says about him, not a footnote to it. Inherits from .attr-pill-name. */
.attr-detail { font-weight: inherit; font-size: inherit; color: inherit; opacity: 1; }
.attr-pill-det {
  background: none; border: none; cursor: pointer; padding: 3px 4px;
  display: inline-flex; align-items: center; color: var(--text-subtle); line-height: 0;
}
.attr-pill-det:hover { color: var(--color-brand); }
/* Nothing filled in yet: the button carries its own words, so it can't be
   missed the way a bare + was. It sits ON the pill rather than on top of it -
   no border, the pill's own background - because it's an invitation, not a
   second control competing with the tag's name. */
.attr-pill-det.empty, .attr-pill-det.labelled {
  gap: 3px; padding: 3px 6px; border-radius: 999px; line-height: 1;
  background: transparent; border: none;
  color: var(--color-brand); font-size: 11.5px; font-weight: var(--weight-bold);
  white-space: nowrap;
}
.attr-pill-det.empty:hover, .attr-pill-det.labelled:hover { background: var(--surface-panel); }

/* IMP-185a - the same invitation on the interest page itself. There it stands
   on its own rather than beside a tag, so it gets a little more room and a
   size that holds its own under the description. */
.int-detail-btn { display: flex; justify-content: center; margin-top: 10px; }
.int-detail-btn .attr-pill-det { font-size: 13.5px; padding: 6px 12px; max-width: 100%; white-space: normal; text-align: left; }
.attr-pill.locked .attr-pill-det { cursor: default; }

/* ---------------------------------------------------------------------------
   IMP-186a — a little life on the interest hero icon.

   Scoped to `.int-hero .ico-tile` on purpose: one icon, big, on a page that is
   about that one thing. The same icon in a list or a chip stays perfectly
   still — a directory of twitching icons is a fidget, not a flourish.

   Every motion is mostly stillness. The movement happens in the last fifth of
   a long cycle, so it reads as an occasional flicker of life rather than
   something looping at you while you're trying to read the description.

   Only these few icons move, and only where the movement is the thing itself
   doing what it does: a ball spins, a bike rolls, a pick strums, a weight gets
   lifted. Adding one is a name and a keyframe — but the reason to move should
   come from the object, not from the fact that we can.
   --------------------------------------------------------------------------- */
.int-hero .ico-tile [data-ti] {
  transform-origin: 50% 50%;
  will-change: transform;
}

@keyframes fmh-ti-spin {
  0%, 78%  { transform: rotate(0deg); }
  100%     { transform: rotate(360deg); }
}
/* A roll rather than a spin: forward, a small lean into it, and back. */
@keyframes fmh-ti-roll {
  0%, 72%  { transform: translateX(0) rotate(0deg); }
  84%      { transform: translateX(2.5px) rotate(7deg); }
  93%      { transform: translateX(-1.5px) rotate(-4deg); }
  100%     { transform: translateX(0) rotate(0deg); }
}
/* A strum: three quick shakes, then nothing for six seconds. */
@keyframes fmh-ti-strum {
  0%, 80%      { transform: rotate(0deg); }
  85%          { transform: rotate(-13deg); }
  90%          { transform: rotate(10deg); }
  95%          { transform: rotate(-6deg); }
  100%         { transform: rotate(0deg); }
}
/* A lift: up, held for a beat, down. */
@keyframes fmh-ti-lift {
  0%, 74%      { transform: translateY(0); }
  84%, 90%     { transform: translateY(-3px); }
  100%         { transform: translateY(0); }
}

.int-hero .ico-tile [data-ti="ball-football"]  { animation: fmh-ti-spin  7.5s ease-in-out infinite; }
.int-hero .ico-tile [data-ti="bike"]           { animation: fmh-ti-roll  6.5s ease-in-out infinite; }
.int-hero .ico-tile [data-ti="guitar-pick"]    { animation: fmh-ti-strum 7s   ease-in-out infinite; }
.int-hero .ico-tile [data-ti="dumbbell"],
.int-hero .ico-tile [data-ti="barbell"]        { animation: fmh-ti-lift  6s   ease-in-out infinite; }

/* Stillness is the default for anyone who has asked their phone for it. */
@media (prefers-reduced-motion: reduce) {
  .int-hero .ico-tile [data-ti] { animation: none !important; }
}

/* ---------------------------------------------------------------------------
   IMP-188 — pictures in a chat message.

   The attach button sits on the LEFT of the composer foot and Send stays on the
   right, so the two controls never swap places as the strip appears and the
   foot changes height. The thumbnails go ABOVE the foot rather than beside the
   button: on a phone there is no room beside anything.
   --------------------------------------------------------------------------- */

.fmh-sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.fmh-attach {
  margin-right: auto;                 /* Send keeps the right-hand edge */
  display: inline-flex; align-items: center; gap: 5px;
  padding: 7px 9px; border-radius: 10px; cursor: pointer;
  color: var(--text-subtle); border: 1px solid transparent;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.fmh-attach:hover { background: var(--surface-panel); color: var(--color-brand); }
/* The input is hidden, so the focus ring has to live on the label instead —
   otherwise a man on a keyboard cannot tell where he is. */
.fmh-attach:focus-within {
  border-color: var(--color-brand); color: var(--color-brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-brand) 22%, transparent);
}
.fmh-attach-n {
  font-size: 11.5px; font-weight: 800; line-height: 1;
  background: var(--color-brand); color: #fff;
  padding: 3px 6px; border-radius: 999px;
}

.fmh-shots-strip { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 9px; }
.fmh-shot-thumb { position: relative; flex: none; }
.fmh-shot-thumb img {
  width: 64px; height: 64px; object-fit: cover;
  border-radius: 10px; border: 1px solid var(--border-hairline); display: block;
}
.fmh-shot-x {
  position: absolute; top: -6px; right: -6px;
  width: 22px; height: 22px; border-radius: 50%; cursor: pointer;
  border: 2px solid var(--surface-card); background: var(--text-strong); color: #fff;
  font-size: 14px; line-height: 1; padding: 0;
  display: flex; align-items: center; justify-content: center;
}

/* IMP-190 - one picture is shown WHOLE.
   This used to be a fixed box (width:100%, max-height:340px) filled with
   object-fit:cover, which centre-crops: on a tall screensnip that quietly ate
   the top AND the bottom, the two ends of the thing the man was pointing at.
   The cap itself was right - without it a portrait phone photo is most of a
   scroll on its own - so what changed is WHAT is capped. Sizing the picture
   rather than a box lets the browser fit it inside the bubble width and the
   height cap while keeping its shape: a wide photo still fills the bubble, a
   tall screenshot comes out narrower and entire, and a small one is no longer
   blown up. min(70vh, ...) so a tall picture uses most of a phone screen -
   where it is actually being read - without running away on a monitor. */
.fmh-msg-shots { margin-top: 9px; display: grid; gap: 6px; }
.fmh-msg-shots.multi { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.fmh-msg-shots img {
  width: auto; height: auto;
  max-width: 100%; max-height: min(70vh, 520px);
  margin: 0 auto;
  border-radius: 12px; border: 1px solid var(--border-hairline); display: block;
}
/* Several still tile, because a grid wants cells of one size and each picture
   there is a thumbnail to be tapped. Cropped from the top rather than the
   middle: the subject of a photo is usually nearer the top than the bottom. */
.fmh-msg-shots.multi img {
  width: 100%; height: 150px; max-height: 150px;
  object-fit: cover; object-position: center top;
}
.fmh-msg-shots a { display: block; min-width: 0; }

/* =====================================================================
   THE LANDING PAGE (welcome.php) — the one page a man sees before he
   has an account, and the only page anyone outside the church ever sees.

   Namespaced .fmh-lp, NOT .fmh-tour: includes/tour.php already owns
   .fmh-tour for the first-login carousel, and that is a fixed, flexed,
   full-screen overlay. Sharing the prefix laid this page out sideways.

   Deliberately NOT built from the app's component classes. A marketing
   page that reused .fmh-card, .fmh-chip and the message bubble would
   break silently every time one of those is tuned for the app proper —
   and it would break in the one place where nobody is logged in to
   notice. These mocks borrow the TOKENS (colour, radius, type scale)
   and nothing else, so they keep looking like the app without being
   welded to it.

   Nothing in here collects anything. See the docblock in welcome.php:
   this page's whole privacy argument is that it has no form on it.
   ===================================================================== */

.fmh-lp { background: var(--surface-page); }
.fmh-lp-wrap { max-width: 1040px; margin: 0 auto; padding: 0 var(--space-6); }

/* ---------- hero ---------- */
.fmh-lp-hero {
  position: relative; text-align: center; color: #fff;
  padding: clamp(56px, 12vh, 104px) var(--space-6) clamp(48px, 9vh, 80px);
  background-color: #1d1d1b;
  background-image: linear-gradient(rgba(12, 10, 12, .58), rgba(12, 10, 12, .78)),
                    url("../img/login-bg-1000.jpg");
  background-size: cover; background-position: 30% center;
}
@media (min-width: 900px) {
  .fmh-lp-hero {
    background-image: linear-gradient(rgba(12, 10, 12, .52), rgba(12, 10, 12, .74)),
                      url("../img/login-bg-2000.jpg");
    background-position: center 35%;
  }
}
.fmh-lp-hero .fmh-mark { width: 38px; margin: 0 auto var(--space-4); }
.fmh-lp-hero .fmh-mark span { height: 5px; background: #fff; }
.fmh-lp-hero h1 {
  color: #fff; font-size: clamp(38px, 9vw, 62px); font-weight: var(--weight-display);
  letter-spacing: var(--tracking-tight); margin: 0;
}
.fmh-lp-lede {
  color: rgba(255, 255, 255, .88); font-size: clamp(17px, 2.4vw, 21px);
  line-height: var(--leading-snug); margin: var(--space-4) auto 0; max-width: 30ch;
}
.fmh-lp-cta { display: flex; flex-direction: column; gap: 10px; align-items: center; margin-top: var(--space-8); }
@media (min-width: 560px) { .fmh-lp-cta { flex-direction: row; justify-content: center; } }
.fmh-lp-cta .fmh-btn { min-width: 210px; }
/* On the photo, the secondary button has to read as a button and not as a hole
   punched in the picture. */
.fmh-lp-hero .fmh-btn.secondary {
  background: rgba(255, 255, 255, .10); color: #fff;
  border-color: rgba(255, 255, 255, .45); backdrop-filter: blur(3px);
}
.fmh-lp-hero .fmh-btn.secondary:hover { background: rgba(255, 255, 255, .18); color: #fff; }
.fmh-lp-note {
  margin: var(--space-6) auto 0; max-width: 46ch;
  font-size: var(--text-small); line-height: var(--leading-normal);
  color: rgba(255, 255, 255, .78);
}

/* ---------- a tour section: words one side, a screen the other ---------- */
.fmh-lp-sec { padding: clamp(44px, 8vh, 76px) 0; }
.fmh-lp-sec + .fmh-lp-sec { border-top: 1px solid var(--border-hairline); }
.fmh-lp-grid { display: grid; gap: var(--space-8); align-items: center; }
@media (min-width: 860px) {
  .fmh-lp-grid { grid-template-columns: 1fr 1fr; gap: clamp(40px, 6vw, 80px); }
  /* Alternating sides, so the eye zig-zags down the page instead of running
     straight past seven identical rows. */
  .fmh-lp-sec:nth-of-type(even) .fmh-lp-words { order: 2; }
}
.fmh-lp-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: var(--radius-md);
  background: var(--surface-panel); color: var(--color-brand); margin-bottom: var(--space-4);
}
.fmh-lp-words h2 {
  font-size: clamp(24px, 3.4vw, 32px); font-weight: var(--weight-display);
  letter-spacing: var(--tracking-tight); margin: 0 0 var(--space-3);
}
.fmh-lp-words p {
  color: var(--text-body); font-size: var(--text-body-lg);
  line-height: var(--leading-relaxed); margin: 0; max-width: 42ch;
}

/* ---------- the phone ---------- */
.fmh-lp-stage { display: flex; justify-content: center; }
.fmh-lp-phone {
  width: 268px; flex: none; border-radius: 34px; padding: 9px;
  background: var(--ink-900); box-shadow: var(--elevation-3);
}
.fmh-lp-screen {
  background: var(--surface-page); border-radius: 26px; overflow: hidden;
  padding: 12px 11px 16px; min-height: 248px;
}
.fmh-lp-bar {
  display: flex; align-items: center; gap: 7px; padding: 0 2px 11px;
  font-size: 13px; font-weight: var(--weight-display); color: var(--text-strong);
}
.fmh-lp-bar .ic { color: var(--color-brand); display: inline-flex; }
.fmh-lp-bar .sp { margin-left: auto; color: var(--text-subtle); font-weight: var(--weight-regular); font-size: 11px; }

/* mock building blocks — small on purpose: the frame is 246px of usable width */
.fmh-lp-card {
  background: var(--surface-card); border: 1px solid var(--border-hairline);
  border-radius: var(--radius-md); padding: 10px 11px; font-size: 12px;
  line-height: var(--leading-normal); color: var(--text-body);
}
.fmh-lp-card + .fmh-lp-card { margin-top: 8px; }
.fmh-lp-card b { color: var(--text-strong); font-weight: var(--weight-bold); }
.fmh-lp-sub { color: var(--text-muted); font-size: 11px; }
.fmh-lp-row { display: flex; align-items: center; gap: 8px; }
.fmh-lp-av {
  width: 24px; height: 24px; border-radius: var(--radius-pill); flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--avatar-bg); color: var(--avatar-fg);
  font-size: 10px; font-weight: var(--weight-bold);
}
.fmh-lp-pill {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px;
  border-radius: var(--radius-pill); font-size: 11px; font-weight: var(--weight-bold);
  background: var(--surface-panel); color: var(--text-body); border: 1px solid transparent;
}
.fmh-lp-pill.on { background: var(--color-brand); color: var(--color-brand-on); }
.fmh-lp-pill.out { background: transparent; border-color: var(--border-hairline); color: var(--text-muted); }
.fmh-lp-pills { display: flex; flex-wrap: wrap; gap: 5px; }
.fmh-lp-date {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  width: 38px; height: 38px; flex: none; border-radius: var(--radius-sm);
  background: var(--color-brand); color: #fff; line-height: 1;
}
.fmh-lp-date .d { font-size: 15px; font-weight: var(--weight-display); }
.fmh-lp-date .m { font-size: 9px; letter-spacing: var(--tracking-wide); text-transform: uppercase; margin-top: 2px; }
.fmh-lp-input {
  display: flex; align-items: center; gap: 6px; margin-top: 9px;
  border: 1px solid var(--border-strong); border-radius: var(--radius-pill);
  padding: 6px 6px 6px 11px; background: var(--surface-card);
  font-size: 11.5px; color: var(--text-subtle);
}
.fmh-lp-send {
  margin-left: auto; width: 22px; height: 22px; border-radius: var(--radius-pill);
  background: var(--color-brand); color: #fff; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
}

/* ---------- the plain-spoken bit ---------- */
.fmh-lp-plain { background: var(--surface-inverse); color: var(--grey-050); padding: clamp(48px, 9vh, 84px) 0; }
.fmh-lp-plain h2 {
  color: #fff; font-size: clamp(24px, 3.4vw, 32px); font-weight: var(--weight-display);
  letter-spacing: var(--tracking-tight); margin: 0 0 var(--space-8); text-align: center;
}
.fmh-lp-three { display: grid; gap: var(--space-6); }
@media (min-width: 760px) { .fmh-lp-three { grid-template-columns: repeat(3, 1fr); gap: var(--space-8); } }
.fmh-lp-three h3 { color: #fff; font-size: var(--text-h3); margin: var(--space-3) 0 6px; }
.fmh-lp-three p { color: rgba(245, 242, 236, .75); font-size: var(--text-small); line-height: var(--leading-relaxed); margin: 0; }
.fmh-lp-three .ico { color: var(--plum-300); }

/* ---------- where you stand ---------- */
.fmh-lp-end { padding: clamp(48px, 9vh, 84px) 0; text-align: center; }
.fmh-lp-end h2 {
  font-size: clamp(24px, 3.4vw, 32px); font-weight: var(--weight-display);
  letter-spacing: var(--tracking-tight); margin: 0 0 var(--space-4);
}
.fmh-lp-end p { color: var(--text-body); font-size: var(--text-body-lg); line-height: var(--leading-relaxed); margin: 0 auto var(--space-4); max-width: 54ch; }
.fmh-lp-end .fmh-lp-cta { margin-top: var(--space-6); }

/* ---------- foot ---------- */
.fmh-lp-foot {
  border-top: 1px solid var(--border-hairline); padding: var(--space-8) 0 var(--space-12);
  text-align: center; font-size: var(--text-small); color: var(--text-muted);
}
.fmh-lp-foot a { color: var(--text-muted); }
.fmh-lp-foot a:hover { color: var(--color-brand); }
/* One line, quiet, and no pitch. The men using this are not the customer, and
   the front door of their ministry is not a shop window — the case for the
   product is made on courageousdesign.co.uk, not here. */
.fmh-lp-by { margin-top: 10px; font-size: var(--text-caption); color: var(--text-subtle); }
