/* ==========================================================================
   CarpForum-Theme.css
   Single shared stylesheet - /SharedCSS/CarpForum-Theme.css
   Colour intentionally muted/greyscale for now (matches IPCheckUser.asp).
   Layout/proportions are the settled part; palette is a placeholder pass.
   ========================================================================== */

:root{
  --cf-navy:#2B3648;       /* header/footer BACKGROUND only - always dark in both themes, so not overridden below */
  --cf-heading:#2B3648;    /* heading/emphasis TEXT colour - separate from --cf-navy on purpose (see dark-mode note below) */
  --cf-accent:#5B6B85;     /* was bright blue, now muted steel-blue */
  --cf-accent-dark:#48566E;
  --cf-bg:#F0F2F5;         /* matches IPCheckUser.asp body background */
  --cf-card:#FFFFFF;
  --cf-border:#DEE2E6;     /* matches IPCheckUser.asp card borders */
  --cf-text:#212529;
  --cf-muted:#6C757D;      /* matches IPCheckUser.asp muted text */
  --cf-icon-bg:#E9ECEF;    /* flat grey icon tiles, no colour-coding yet */
  --cf-unread-bg:#FFF3C4;  /* forum-area icon tile when it contains unread posts - old site's yellow folder */
  --cf-unread-icon:#8A6D00;
  --container-max: 1440px;
  --container-pad: clamp(16px, 3vw, 32px);
  --header-h: 72px; /* was 60px - bumped 2026-08-20 to fit the new ~64px fish mark alongside the wordmark */
  --rightpane-w: 300px;
}

/* ===== dark mode (2026-08-18) =====
   Toggled via <html data-theme="dark">, set by header.asp from Session("DarkMode") -
   see Settings.asp. Works site-wide "for free" because every component already styles
   itself through these variables rather than hardcoded colours - the header/footer are
   the only exception (already permanently dark-styled with fixed near-white text in both
   themes, which is why --cf-navy isn't redefined here - see its :root comment).
   --cf-heading is deliberately separate from --cf-navy: --cf-navy stays dark (it's a
   BACKGROUND colour, header/footer), while --cf-heading is TEXT that needs to flip light
   in dark mode - conflating the two originally made every page heading unreadable here
   (dark text on a now-dark page background), caught by an actual screenshot, not just
   review.
   Known gap: badge colours hardcoded inline in the Topics1/2/1.1/2.2 draft pages'
   page-local <style> blocks (e.g. .t1-badge.pin) bypass these variables entirely, so
   they won't switch with the rest of the page yet - fold those into variables here
   once a topics layout direction is picked and promoted out of the drafts. */
:root[data-theme="dark"]{
  --cf-heading:#F0F2F5;
  --cf-accent:#8091AD;
  --cf-accent-dark:#A3B2C9;  /* lighter, not darker - this is the hover/emphasis shade, and hovers should brighten on a dark background */
  --cf-bg:#12161C;
  --cf-card:#1B212A;
  --cf-border:#2C333D;
  --cf-text:#E4E7EB;
  --cf-muted:#8B95A1;
  --cf-icon-bg:#242B35;
  --cf-unread-bg:#4A3B12;
  --cf-unread-icon:#F5C518;
}

body{
  background: var(--cf-bg);
  color: var(--cf-text);
  font-family: "Segoe UI", system-ui, -apple-system, Roboto, sans-serif;
  padding-top: var(--header-h);
}

.cf-container{
  width:100%;
  max-width: var(--container-max);
  margin-inline:auto;
  padding-inline: var(--container-pad);
}

/* ===== fixed header ===== */
.cf-header{
  position:fixed; top:0; left:0; right:0; z-index:1030;
  height: var(--header-h);
  background: var(--cf-navy);
  border-bottom: 1px solid rgba(255,255,255,.08);
  box-shadow: 0 1px 3px rgba(0,0,0,.15);
}
.cf-header .cf-container{
  height:100%;
  display:flex; align-items:center; justify-content:space-between; gap:1rem;
}
.cf-brand{
  display:flex; align-items:center; gap:.6rem;
  color:#fff; text-decoration:none; font-weight:800; font-size:1.15rem;
  letter-spacing:-.02em; flex-shrink:0;
}
.cf-brand img{ height:52px; width:auto; display:block; } /* was 34px, then 46px - bumped again 2026-08-20, still reading small next to the rest of the header */
/* Fish mark, added 2026-08-20 alongside the wordmark - deliberately taller than it (64px vs
   52px) so the fish reads as the primary mark and the wordmark as a secondary label. Source
   asset /Image/CFLogoTrans640x480.png is Karl's full-resolution master (kept untouched) -
   /Image/CFLogoFish-Header.png is a purpose-built export for this exact slot: transparent
   padding cropped tight, then resized once to 420x192 (~3x this 64px display height, for
   retina) with high-quality bicubic resampling, rather than shipping the 640x480 master and
   making every page's browser downscale it live. See memory note (fish logo asset prep) for
   the full reasoning. */
.cf-brand-fish{ height:64px; width:auto; display:block; }

/* Brand badge (Karl's ask, 2026-08-21) - a full diagonal ribbon across the header fish logo,
   reading "DEV" or "NEW" depending which host Header.asp detects it's being served from (see
   that file's own strBrandBadge comment) - same one class/rule for both, just different text.
   Never appears on real production www.carpforum.co.uk - this rule ships everywhere via SINK
   (one file, no per-environment CSS), but the badge markup itself only renders server-side
   when the host matches dev.CF or new.CF, so there's nothing to hide once this code eventually
   reaches production.
   Sized big on purpose (Karl: "make it bigger, cover the fish as much as you like") - the
   ribbon overhangs the wrap on both sides (left/right go negative) for the classic
   corner-ribbon look, clipped cleanly by the wrap's own overflow:hidden so it doesn't spill
   into the wordmark/nav next to it. */
.cf-brand-fish-wrap{ position:relative; display:inline-flex; height:64px; flex-shrink:0; overflow:hidden; }
.cf-brand-badge{
  position:absolute; left:-18%; right:-18%; top:50%; transform:translateY(-50%) rotate(-12deg);
  background:#D9480F; color:#fff; font-size:1.05rem; font-weight:900; letter-spacing:.05em;
  padding:.25rem 0; text-align:center; text-transform:uppercase;
  box-shadow:0 1px 4px rgba(0,0,0,.4); pointer-events:none; white-space:nowrap;
}

.cf-header-search{ flex:1 1 auto; max-width:420px; }
.cf-header-search .form-control{
  background: rgba(255,255,255,.08);
  border:1px solid rgba(255,255,255,.15);
  color:#fff;
}
.cf-header-search .form-control::placeholder{ color:#B9C4D6; }
.cf-header-search .form-control:focus{
  /* Text colour hardcoded, not var(--cf-text), 2026-08-24 (Karl's ask, found on dark theme) -
     this focus background is unconditionally white in BOTH themes (a deliberate "actively
     typing" state, not meant to flip with the site theme), but var(--cf-text) DOES flip -
     #E4E7EB (pale, meant for dark-mode page backgrounds) on dark theme, landing on this
     hardcoded-white box as near-invisible text. Matching the white background with an equally
     fixed dark text colour (the light theme's own --cf-text value, #212529) is correct
     regardless of which theme the rest of the site is in. */
  background:#fff; color:#212529;
  box-shadow: 0 0 0 .2rem rgba(91,107,133,.25);
}
.cf-header-search .input-group-text{
  background: rgba(255,255,255,.08);
  border:1px solid rgba(255,255,255,.15);
  color:#B9C4D6;
}

.cf-header-actions{ display:flex; align-items:center; gap:.5rem; flex-shrink:0; }
.cf-header-actions .btn{ font-weight:600; font-size:.88rem; }
/* .btn-cf-ghost is dark-background-only (near-white text/border) - deliberately kept
   scoped to the header, unlike .btn-cf below. A light-background ghost variant would
   need its own class if one's ever needed outside the header. */
.cf-header-actions .btn-cf-ghost{
  color:#E4EAF3; border:1px solid rgba(255,255,255,.25); background:transparent;
}
/* Fixed 2026-08-23 (Karl caught it): the account button rendered very slightly taller than
   Tools once it could contain a 22px avatar <img> instead of just an icon glyph - an inline
   image's line-box math doesn't quite match an icon-font glyph's, even at the same visual
   size. inline-flex + align-items:center sidesteps that entirely - both buttons now centre
   their content the same way regardless of whether it's an <i> icon or an <img>, so their
   heights match exactly rather than relying on line-height/vertical-align lining up by luck. */
.cf-header-actions .dropdown-toggle{ display:inline-flex; align-items:center; }
.cf-header-actions .btn-cf-ghost:hover{ background: rgba(255,255,255,.08); color:#fff; }
/* Account dropdown avatar (2026-08-23, Karl's ask) - same rounded mask as WhosOnline.asp's
   .wo-avatar, just smaller to sit inline in a btn-sm next to the username text instead of a
   list row. Falls back to the bi-person-circle icon (inline onerror in header.asp, and by
   default for anyone without a custom avatar at all - see Session("HasCustomAvatar")). */
.cf-header-avatar{ width:22px; height:22px; border-radius:50%; object-fit:cover; vertical-align:middle; margin-right:.3rem; }

/* PM unread badge (2026-08-24, PMv2) - amber-pill numeral badge, same language as
   TopicMANAGER.asp's .tm-unread (not a bare dot - Karl's "count of messages, not topics" ask
   carries through to this badge too). Used inline after "My Messages" in the Tools dropdown and
   navlinks.asp's mobile equivalent. */
.cf-header-pm-badge{ display:inline-block; background:var(--bs-warning); color:#fff; font-weight:700; border-radius:10px; padding:.05rem .45rem; font-size:.7rem; vertical-align:middle; }

/* Standalone header PM icon-button (2026-08-24, PMv2) - reworked same day (Karl's feedback pass)
   from a numeral badge floated ON TOP of the icon (covered it, illegible) to a solid amber
   circular button - same "filled = active" language as the subscribe-bell treatment elsewhere
   (e.g. MessagesDesktop.asp's .m1-title-subscribe unsubscribe state) - plus the count as plain
   text beside it, never overlapping the glyph. .cf-header-pm-btn-unread only applies while
   there's something unread; the base .cf-header-pm-circle stays a plain muted-outline circle
   otherwise, matching the ghost-button treatment of the dropdowns either side of it. */
.cf-header-pm-btn{ text-decoration:none; gap:.35rem; padding:0; }
.cf-header-pm-circle{ width:32px; height:32px; border-radius:50%; display:inline-flex; align-items:center; justify-content:center; color:rgba(255,255,255,.85); border:1px solid rgba(255,255,255,.25); font-size:1rem; }
.cf-header-pm-btn:hover .cf-header-pm-circle{ background:rgba(255,255,255,.08); color:#fff; }
.cf-header-pm-btn-unread .cf-header-pm-circle{ background:var(--bs-warning); border-color:var(--bs-warning); color:#fff; }
.cf-header-pm-btn-unread:hover .cf-header-pm-circle{ background:var(--bs-warning); filter:brightness(1.08); }
.cf-header-pm-count{ color:var(--bs-warning); font-weight:700; font-size:.85rem; }

/* Flash (2026-08-24, Karl's ask - "in case the colour alone is not enough to catch the user's
   attention") - a slow, gentle pulse on the circle only (not the count text, which would be
   harder to read mid-fade), so it's noticeable without being obnoxious. Applied only while
   lngPMUnreadCount>0 (see Header.asp) - never animates when there's nothing new. */
@keyframes cf-pm-flash{ 0%, 100% { opacity:1; } 50% { opacity:.45; } }
.cf-header-pm-flash .cf-header-pm-circle{ animation: cf-pm-flash 1.6s ease-in-out infinite; }

.cf-burger{ display:none; color:#fff; border:1px solid rgba(255,255,255,.25); background:transparent; }

/* .btn-cf - solid fill, background-agnostic, so global rather than header-scoped (was
   accidentally .cf-header-actions-only, which is why LogIn.asp's submit button rendered
   as a bare unstyled Bootstrap .btn - fixed 2026-08-18). */
.btn-cf{
  background: var(--cf-accent); border-color: var(--cf-accent); color:#fff; font-weight:600;
}
.btn-cf:hover{ background: var(--cf-accent-dark); border-color: var(--cf-accent-dark); color:#fff; }

/* Icon <-> label spacing on ANY icon+text button, site-wide (Karl, 2026-08-31 - trialled on
   Profile.asp's Tools box first, then promoted here). Bootstrap's .btn is inline-block, which
   left an <i class="bi"> sitting almost against its label on every button that has both. Switch
   .btn to inline-flex and use `gap` for the space: it only ever falls BETWEEN two children, so
   an icon-only button (single child) or a text-only button picks up nothing - no stray padding,
   no per-page classes, no markup changes. .55em scales with each button's own font-size, so a
   .btn-sm gets a proportionally smaller gap. */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:.55em;
}

/* ===== layout: main content + right ad rail ===== */
/* .cf-body-wrap holds both columns. .cf-rightpane is position:sticky *within*
   .cf-body-wrap (not the viewport) - it sticks while the user scrolls through .cf-main,
   then naturally un-sticks and scrolls away once .cf-body-wrap ends (see footer.asp,
   which closes it right before the footer).
   Used to be three columns - a desktop nav rail (Members/Who's Online) sat where
   .cf-main now starts. Removed 2026-08-19 (Karl's call): those links moved into a
   "Community" dropdown in the header instead (see header.asp) - see memory note
   community-header-menu. Mobile is unaffected; navlinks.asp's offcanvas menu already
   had its own "Community" section covering the same links, independent of the rail. */
.cf-body-wrap{
  display:flex; align-items:flex-start; gap: clamp(16px,2.5vw,28px);
  padding-block: 1.5rem;
}

.cf-rightpane{
  width: var(--rightpane-w); flex-shrink:0;
  position: sticky; top: calc(var(--header-h) + 20px);
}
.cf-ad-slot{ padding:.75rem; text-align:center; }
.cf-ad-slot + .cf-ad-slot{ margin-top:1rem; }
.cf-ad-slot-label{
  font-size:.68rem; text-transform:uppercase; letter-spacing:.05em;
  color: var(--cf-muted); margin-bottom:.5rem;
}
.cf-ad-placeholder{
  display:flex; align-items:center; justify-content:center;
  background: var(--cf-icon-bg); border:1px dashed var(--cf-border);
  border-radius:8px; color: var(--cf-muted); font-size:.85rem;
}

/* ===== promo rail (DB-driven, 2026-09-02) =====
   Replaces the hardcoded .cf-ad-slot placeholders above (kept for now, unused).
   Each .cf-promo-slot = one position in dbo.PromoSlots. The card image sets its
   own height (width:100% / height:auto), so an advertiser's 300x250 MPU and a
   short 300x100 article thumbnail both sit naturally in the same rail. */
.cf-promo-slot{ margin-bottom:1rem; transition:opacity .25s ease; }
.cf-promo-slot:last-child{ margin-bottom:0; }
.cf-promo-slot-label{
  font-size:.68rem; text-transform:uppercase; letter-spacing:.05em;
  color: var(--cf-muted); margin-bottom:.4rem; text-align:center;
}
.cf-promo-card{
  display:block; border:1px solid var(--cf-border); border-radius:8px;
  overflow:hidden; background: var(--cf-card); text-decoration:none; color:inherit;
}
.cf-promo-card img{ display:block; width:100%; height:auto; }
.cf-promo-card .cf-promo-caption{
  padding:.5rem .65rem; font-size:.82rem; line-height:1.35; color: var(--cf-text);
}
.cf-promo-card:hover .cf-promo-caption{ color: var(--cf-accent); }
.cf-promo-actions{
  display:flex; align-items:center; justify-content:space-between; gap:.5rem;
  padding:.3rem .5rem; border:1px solid var(--cf-border); border-top:none;
  border-radius:0 0 8px 8px; margin-top:-1px;
}
.cf-promo-actions button{
  border:none; background:none; padding:.1rem .35rem; line-height:1; cursor:pointer;
  color: var(--cf-muted); font-size:.78rem;
}
.cf-promo-actions button:hover{ color: var(--cf-accent); }
.cf-promo-actions .cf-promo-fav{ font-size:.95rem; }
.cf-promo-actions .cf-promo-fav.on{ color: var(--cf-unread-icon); }
.cf-promo-slot.is-dismissing{ opacity:0; }
/* Kind="Embed" - a raw markup block (an affiliate/ad-network iframe, etc). Keep it
   from spilling past the 300px rail; the snippet brings its own sizing otherwise. */
.cf-promo-embed{ max-width:100%; overflow:hidden; }
.cf-promo-embed iframe,
.cf-promo-embed img{ max-width:100%; }

/* ===== Semantic "soft" buttons, 2026-08-24 (Karl's palette-standardisation pass) =====
   Built on Bootstrap 5.3's own native subtle/border/emphasis theme tokens
   (--bs-{color}-bg-subtle / -border-subtle / -text-emphasis) instead of hand-rolled rgba()
   tints - those tokens are already dark-mode-aware via [data-bs-theme="dark"] (see Header.asp,
   which sets that attribute alongside this site's own data-theme), with a genuinely different
   pre-computed value per mode, so no manual [data-theme="dark"] override block is needed here
   the way the old page-local .btn-soft-success (MessagesDesktop.asp, since superseded) needed
   one. One shared definition, used everywhere a "soft"/outline-by-default, filled-when-true
   treatment is wanted - see StyleToDo.md for the outline/fill convention this pairs with. */
.btn-soft-warning, .btn-soft-danger, .btn-soft-success, .btn-soft-info, .btn-soft-secondary, .btn-soft-primary{
  border-width:1px; border-style:solid; font-weight:600;
}
.btn-soft-warning{ background:var(--bs-warning-bg-subtle); border-color:var(--bs-warning-border-subtle); color:var(--bs-warning-text-emphasis); }
.btn-soft-warning:hover{ background:var(--bs-warning-border-subtle); color:var(--bs-warning-text-emphasis); }
.btn-soft-danger{ background:var(--bs-danger-bg-subtle); border-color:var(--bs-danger-border-subtle); color:var(--bs-danger-text-emphasis); }
.btn-soft-danger:hover{ background:var(--bs-danger-border-subtle); color:var(--bs-danger-text-emphasis); }
.btn-soft-success{ background:var(--bs-success-bg-subtle); border-color:var(--bs-success-border-subtle); color:var(--bs-success-text-emphasis); }
.btn-soft-success:hover{ background:var(--bs-success-border-subtle); color:var(--bs-success-text-emphasis); }
.btn-soft-info{ background:var(--bs-info-bg-subtle); border-color:var(--bs-info-border-subtle); color:var(--bs-info-text-emphasis); }
.btn-soft-info:hover{ background:var(--bs-info-border-subtle); color:var(--bs-info-text-emphasis); }
.btn-soft-secondary{ background:var(--bs-secondary-bg-subtle); border-color:var(--bs-secondary-border-subtle); color:var(--bs-secondary-text-emphasis); }
.btn-soft-secondary:hover{ background:var(--bs-secondary-border-subtle); color:var(--bs-secondary-text-emphasis); }
.btn-soft-primary{ background:var(--bs-primary-bg-subtle); border-color:var(--bs-primary-border-subtle); color:var(--bs-primary-text-emphasis); }
.btn-soft-primary:hover{ background:var(--bs-primary-border-subtle); color:var(--bs-primary-text-emphasis); }

/* ===== full-width footer ===== */
.cf-footer{
  width:100%;
  background: var(--cf-navy);
  color:#C7D0DE;
  margin-top: 2rem;
}
.cf-footer-inner{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap: .75rem;
  padding-block: 1.25rem;
  font-size:.85rem;
}
/* margin-left:auto, 2026-08-23 (Karl's ask) - same flexbox quirk documented in
   MessagesDesktop.asp/MessagesMobile.asp's own toolbar comments: once .cf-footer-inner wraps
   onto two lines on a narrow screen, a lone wrapped flex item lands at the START of its own
   line under justify-content:space-between, not the end - so the Home/Rules/FAQs links were
   sitting left-aligned under the copyright line instead of right-justified. margin-left:auto
   is the robust fix, same as those other two files. */
.cf-footer-links{ display:flex; gap:1rem; margin-left:auto; }
.cf-footer-links a{ color:#C7D0DE; text-decoration:none; }
.cf-footer-links a:hover{ color:#fff; text-decoration:underline; }

/* ===== numbered pager (2026-08-25, Karl's ask) =====
   Markup comes from Includes/Pager.asp - see that file for the window logic and why Prev/Next
   render as an inert <span> rather than a disabled <a> when unavailable.
   Deliberately borrows .t1-sort-btn's exact padding/border/radius so the pager reads as the same
   family of control as the sort bar above the list, rather than a second visual language. */
.cf-pager{
  display:flex; align-items:center; justify-content:space-between; gap:.5rem; flex-wrap:wrap;
  padding:.9rem 1.25rem; border-top:1px solid var(--cf-border);
}
.cf-pager-nav, .cf-pager-page{
  font-size:.8rem; font-weight:600; color:var(--cf-muted); text-decoration:none;
  padding:.3rem .65rem; border-radius:6px; border:1px solid var(--cf-border);
  white-space:nowrap;
}
.cf-pager-nav:hover, .cf-pager-page:hover{ background:var(--cf-bg); color:var(--cf-text); }

/* Disabled Prev/Next: Karl's "semi hidden... there to give the page balance left to right, but
   not in your face suggesting you can click it". Done with opacity rather than a hardcoded grey
   deliberately - opacity dims against whatever the current theme's background is, so it stays
   correctly faint in BOTH light and dark mode with one rule, where a fixed light-grey would go
   nearly invisible on light and glow on dark.
   The border is KEPT (2026-08-25, Karl's follow-up - a first pass dropped it to transparent to
   de-emphasise further, but that left the dead side of the row visibly lighter-weight than the
   live side): the button holds its full outlined shape so both ends of the pager balance, and the
   opacity alone carries "not clickable". Opacity dims the border along with the text, so it
   still reads as faint rather than as a live control. */
.cf-pager-nav.disabled{ opacity:.3; cursor:default; }
.cf-pager-nav.disabled:hover{ background:none; color:var(--cf-muted); }

.cf-pager-pages{ display:flex; gap:.25rem; flex-wrap:wrap; justify-content:center; align-items:center; }
.cf-pager-page{ min-width:2rem; text-align:center; padding:.3rem .5rem; }
.cf-pager-page.active{
  background:var(--cf-accent); border-color:var(--cf-accent); color:#fff;
}
/* Ellipsis between the window and the first/last page jump. Deliberately borderless and
   unclickable - it's a gap indicator, not a control, and giving it the page buttons' outline
   would imply it does something. */
.cf-pager-gap{ color:var(--cf-muted); font-size:.8rem; padding:0 .15rem; user-select:none; }

/* Sponsor/advertiser credits (2026-08-25, Karl's ask - carried over from the old site's footer,
   which listed the same three). Its own row ABOVE the copyright line rather than squeezed into
   .cf-footer-inner, which is already a two-item flex row (copyright left / nav links right) and
   has nowhere to put three more items without crowding.
   Right-aligned to match how the old site presented them, and laid out as a wrapping flex row
   rather than three hard-coded lines so they reflow to two lines (or one per line) on a narrow
   screen instead of overflowing. The descriptive half is deliberately dimmer than the linked
   business name - the name is the part that's being credited and the part that's clickable. */
.cf-footer-sponsors{
  display:flex; flex-wrap:wrap; justify-content:flex-end; gap:.35rem 1.5rem;
  padding-top:1.25rem; font-size:.82rem;
}
.cf-footer-sponsor{ white-space:nowrap; }
.cf-footer-sponsor .lbl{ color:#8C9AB0; margin-right:.35rem; }
.cf-footer-sponsor a{ color:#C7D0DE; text-decoration:none; font-weight:600; }
.cf-footer-sponsor a:hover{ color:#fff; text-decoration:underline; }
.cf-nav-link{
  display:flex; align-items:center; gap:.6rem;
  padding:.55rem .75rem; border-radius:8px;
  color: var(--cf-text); text-decoration:none; font-weight:500; font-size:.92rem;
}
.cf-nav-link i{ width:18px; text-align:center; color: var(--cf-muted); }
.cf-nav-link:hover{ background: var(--cf-bg); }
.cf-nav-link.active{ background: var(--cf-icon-bg); color: var(--cf-accent-dark); font-weight:600; }
.cf-nav-link.active i{ color: var(--cf-accent-dark); }
.cf-nav-divider{ margin:.5rem .75rem; border-top:1px solid var(--cf-border); }
.cf-nav-label{
  font-size:.72rem; text-transform:uppercase; letter-spacing:.04em;
  color: var(--cf-muted); font-weight:700; padding:.6rem .75rem .2rem;
}

.cf-main{ flex:1 1 auto; min-width:0; }

.cf-card{
  background: var(--cf-card);
  border:1px solid var(--cf-border);
  border-radius:12px;
  box-shadow: 0 1px 3px rgba(0,0,0,.06);
}

/* ===== forum area listing ===== */
.cf-area-group{ margin-bottom:1.5rem; }
.cf-area-group-title{
  font-size:.78rem; text-transform:uppercase; letter-spacing:.05em;
  color: var(--cf-muted); font-weight:700; margin-bottom:.5rem;
}
.cf-area{
  display:flex; align-items:center; gap:1rem;
  padding: .55rem 1.25rem; /* was 1rem block - too much whitespace per row, 2026-08-20 */
  border-bottom:1px solid var(--cf-border);
}
.cf-area:last-child{ border-bottom:none; }
.cf-area-icon{
  width:44px; height:44px; border-radius:10px; flex-shrink:0;
  display:flex; align-items:center; justify-content:center;
  font-size:1.2rem; color: var(--cf-muted);
  background: var(--cf-icon-bg);
}
/* Unread/read colour coding (2026-08-20, Karl's ask) - old site's yellow-folder-means-
   unread/grey-folder-means-all-read convention, restored per-forum-area via FlagUnRead
   from stp_Forums. Icon glyphs themselves stay whatever ForumIcon() picked (Karl likes
   them each being different) - only the tile colour changes. */
.cf-area-icon.unread{ background: var(--cf-unread-bg); color: var(--cf-unread-icon); }
/* Icon + name + description are one click target (2026-08-20, Karl's call) - on a layout
   this loose, only the name text being clickable made landing the click harder than it needed
   to be. .cf-area-link wraps both, taking over the icon+info flex pairing .cf-area itself used
   to do directly - .cf-area-stats/.cf-area-lastpost stay outside it, unchanged. */
.cf-area-link{ display:flex; align-items:center; gap:1rem; flex:1 1 auto; min-width:0; text-decoration:none; color:inherit; border-radius:8px; }
/* "Light bar" hover wash (2026-08-20, Karl's ask) - now that icon+wording is one big click
   target with plenty of empty space in it, a hover highlight is the cue that clicking there
   navigates away. Scoped to .cf-area-link itself, not the whole .cf-area row - .cf-area-stats/
   .cf-area-lastpost outside it aren't clickable, so they deliberately don't light up. Colour
   matches the row's own read/unread state (translucent so it stays "very slightly" per Karl,
   without needing separate light/dark tokens). */
.cf-area-link:hover{ background: rgba(108,117,125,.1); }
.cf-area-link.unread:hover{ background: rgba(245,197,24,.18); }
.cf-area-info{ flex:1 1 auto; min-width:0; }
.cf-area-title{ font-weight:600; color:var(--cf-heading); font-size:1rem; text-decoration:none; }
.cf-area-link:hover .cf-area-title{ color:var(--cf-accent); }
.cf-area-desc{ color:var(--cf-muted); font-size:.85rem; margin-top:.1rem; }

.cf-area-stats{
  flex-shrink:0; text-align:center; color:var(--cf-muted); font-size:.8rem;
  width:80px;
}
.cf-area-stats b{ display:block; color:var(--cf-text); font-size:.95rem; }
/* display:contents at desktop widths (2026-08-25) - this wrapper only DOES anything below
   767.98px (see that media query); up here it's invisible to layout so the two .cf-area-stats
   children remain direct flex-items of .cf-area exactly as before it was added. */
.cf-area-statsgroup{ display:contents; }

/* width 220px -> 160px, 2026-08-25 (Karl's report: "why is there such a gap to the left of these
   new icons?" once Forums.asp gained its mark-as-read column). The gap wasn't caused by that
   button - this column's content (username on one line, "24 Aug 2026 22:57" under it, both at
   .82rem) only ever filled ~130px of the old 220px, so the slack had always been there; nothing
   sat to its right to make it visible. 160px still fits the longest date string without wrapping,
   and .lp-title already ellipsises a long username, so nothing clips. Safe to change here rather
   than override per-page: Forums.asp is the only consumer of .cf-area-lastpost (TopicsDesktop/
   TopicsMobile use .cf-area-link and .cf-area-title only). */
.cf-area-lastpost{
  flex-shrink:0; width:160px; font-size:.82rem; color:var(--cf-muted);
  display:flex; align-items:center; gap:.5rem;
}
.cf-area-lastpost img{ width:32px; height:32px; border-radius:50%; flex-shrink:0; }
.cf-area-lastpost .lp-text{ min-width:0; }
.cf-area-lastpost .lp-title{
  color:var(--cf-accent-dark); font-weight:600; white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; display:block;
}

/* ---- responsive shedding, widest to narrowest ----
   >=1200: icon + title/desc + stats + full last-post block
   992-1199: drop last-post block, keep stats
   768-991: nav rail hidden, hamburger nav appears instead
   <768: stats shrink, desc hidden, header search hidden */
@media (max-width: 1199.98px){
  .cf-area-lastpost{ display:none; }
  .cf-rightpane{ display:none; }
}
@media (max-width: 991.98px){
  .cf-burger{ display:inline-flex; }
  .cf-header-search{ max-width:none; }
  /* Wordmark hidden, fish kept (2026-08-20, Karl's ask - found on his own phone in portrait;
     threshold raised from 767.98px to 991.98px on 2026-08-21 - Karl was still seeing the
     wordmark on a tablet-width portrait screen, still wide enough to push the username
     dropdown/Community buttons off-screen. Moved to match the SAME breakpoint the burger
     itself appears at, rather than picking another narrower guess: the fish stays put at
     every width per Karl's explicit "branding, all the time" ask, and the wordmark now only
     shows once the burger is gone too (>=992px), where there's unambiguously enough room for
     everything. See Header.asp's own comment for the aria-label move that keeps the link's
     accessible name correct once the wordmark img is hidden here. */
  .cf-brand-word{ display:none; }
}
/* Belt-and-braces, 2026-08-21 (Karl's ask - found the width-based rules above NOT applying on
   his iPhone 12 in portrait: burger missing AND wordmark showing, both from the same media
   query block above, so this looks like a stale/cached CF-Theme.css on that device rather than
   a logic bug in the rules themselves - see TODO.md). This second rule keys off actual
   mobile+portrait (coarse pointer = touch-primary device, not just "narrow window") rather than
   viewport width, so it fires independently of whatever's wrong with the width-based rules
   above - covers the burger too, not just the wordmark, since a missing burger is the actual
   functional break (no way to open the mobile nav at all), the wordmark just being visible is
   only cosmetic. Note this lives in the SAME file as the rules above though, so it won't help
   if the real problem turns out to be that whole file being stale/cached on the device - only
   if the width-based rules themselves were ever wrong. */
@media (pointer: coarse) and (orientation: portrait){
  .cf-burger{ display:inline-flex; }
  .cf-brand-word{ display:none; }
}
@media (max-width: 767.98px){
  .cf-area{ padding: .85rem 1rem; gap:.5rem; }
  .cf-area-icon{ width:38px; height:38px; font-size:1rem; }
  .cf-area-desc{ display:none; }
  /* Stacked, not side-by-side, below this width (2026-08-25, Karl's ask - portrait phone had the
     forum name wrapping onto 3 lines because "topics"/"posts" side-by-side plus the mark-read
     column left too little room for it). Same two numbers, same labels, just topics-over-posts
     in one right-aligned column instead of two columns - roughly halves the width this pair
     costs the row, most of which goes straight back to .cf-area-info/.cf-area-title. */
  .cf-area-statsgroup{ display:flex; flex-direction:column; align-items:flex-end; gap:.05rem; flex-shrink:0; }
  .cf-area-stats{ width:auto; display:flex; gap:.3rem; font-size:.7rem; }
  .cf-area-stats b{ display:inline; font-size:.8rem; }
  /* Mark-as-read column narrowed 44px -> 30px below this width too (same report - Karl: "the mark
     all as read icons could have a smaller column, narrower"). Icon glyph shrunk to match so it
     doesn't look oversized in the smaller box; still comfortably tappable. */
  .fh-markread{ width:30px; }
  .fh-markread a{ font-size:.9rem; }
  /* Read Next button (2026-08-26) shrunk the same way and for the same reason as .fh-markread
     just above - it now lives inside .cf-area-info (Forums.asp's own <style> block), not out
     here as a column, but the same phone-width pressure applies. */
  .cf-area-readnext{ width:1.75rem; height:1.75rem; font-size:.9rem; }
  .cf-header-search{ display:none; }
}
.offcanvas-header{ border-bottom:1px solid var(--cf-border); }

/* ===== reusable "are you sure?" confirmation overlay =====
   Same shape as the old site's custom delete-post confirm (Karl's own build, a few months
   back, for a desktop app's Delete button - Shared\Code\ForumEngine\Includes\HTML\
   PageFooter_CF_MOD.htm has the original: icon, bold title, muted message, full-width red
   "Yes"/light "No" stacked buttons). Rebuilt generic and theme-aware here (the original was
   hardcoded white/light-only) - markup lives once in footer.asp, wired up by JS/ConfirmDialog.js
   for any trigger carrying data-confirm-title. First user: Profile.asp's Ban User (2026-08-21).
   See MessagesToDo.md for Delete Post, a documented future user of this same overlay. */
.cf-confirm-overlay{
  display:none; position:fixed; inset:0; background:rgba(0,0,0,.6); z-index:2000;
  align-items:center; justify-content:center; padding:1rem;
}
.cf-confirm-overlay.show{ display:flex; }
.cf-confirm-box{
  background:var(--cf-card); color:var(--cf-text); width:100%; max-width:340px;
  padding:1.75rem 1.5rem; border-radius:16px; text-align:center;
  box-shadow:0 10px 30px rgba(0,0,0,.35);
}
.cf-confirm-icon{ color:var(--bs-danger); font-size:3rem; margin-bottom:.75rem; }
.cf-confirm-title{ font-weight:700; margin-bottom:.5rem; color:var(--cf-heading); }
.cf-confirm-message{ color:var(--cf-muted); font-size:.9rem; margin-bottom:1.5rem; }
.cf-confirm-actions{ display:flex; flex-direction:column; gap:.6rem; }
.cf-confirm-actions .btn{ width:100%; }
.cf-confirm-no{ background:var(--cf-bg); border:1px solid var(--cf-border); color:var(--cf-text); }
.cf-confirm-no:hover{ background:var(--cf-icon-bg); color:var(--cf-text); }

/* ===== loading overlay (2026-08-27) =====
   Informational sibling of .cf-confirm-* above - same box size/style, but it asks nothing and
   has no buttons: it just tells the user the page is busy while a navigation/refresh is in
   flight. Markup lives once in footer.asp, wired up by JS/LoadingDialog.js (a separate file
   from ConfirmDialog.js, Karl's call - the two dialogs do genuinely different jobs). First
   user: IPCheckUser.asp's date-range links. z-index sits above the confirm overlay so a
   "loading" that starts right after a "yes, continue" stacks on top rather than behind. */
.cf-loading-overlay{
  display:none; position:fixed; inset:0; background:rgba(0,0,0,.6); z-index:2100;
  align-items:center; justify-content:center; padding:1rem;
}
.cf-loading-overlay.show{ display:flex; }
.cf-loading-box{
  background:var(--cf-card); color:var(--cf-text); width:100%; max-width:340px;
  padding:1.75rem 1.5rem; border-radius:16px; text-align:center;
  box-shadow:0 10px 30px rgba(0,0,0,.35);
}
.cf-loading-icon{ color:var(--cf-accent); font-size:3rem; margin-bottom:.75rem; line-height:1; }
.cf-loading-icon i{ display:inline-block; animation:cf-hourglass 1.2s ease-in-out infinite; }
.cf-loading-message{ font-weight:700; margin:0; color:var(--cf-heading); }
@keyframes cf-hourglass{
  0%,45%   { transform:rotate(0deg); }
  55%,100% { transform:rotate(180deg); }
}
@media (prefers-reduced-motion: reduce){
  .cf-loading-icon i, .cf-overlay-loading .bi{ animation:none; }
}

/* ===== content overlay (2026-08-27) =====
   A "window in window" - backdrop + a centred panel that fetched HTML is dropped into. NOT an
   iframe, NOT a new browser window. Sibling of the confirm/loading overlays but this one shows
   arbitrary content. Markup in footer.asp (#cfOverlay), wired by JS/OverlayDialog.js: any
   <a data-overlay> has its click intercepted, the panel opens and the link's href is fetched
   with ?embed=1 for a chrome-less fragment. First user: IP links in IPCheckUser.asp ->
   Admin/IPDetail.asp. Deliberately modest width so plenty of the page behind stays visible on
   a desktop monitor; near-full-width with internal scroll on a phone. z-index above the
   confirm (2000) and loading (2100) overlays. */
.cf-overlay-backdrop{
  display:none; position:fixed; inset:0; background:rgba(0,0,0,.55); z-index:2200;
  align-items:flex-start; justify-content:center; padding:2rem 1rem; overflow-y:auto;
}
.cf-overlay-backdrop.show{ display:flex; }
.cf-overlay-panel{
  position:relative; width:100%; max-width:560px;
  background:var(--cf-card); color:var(--cf-text);
  border:1px solid var(--cf-border); border-radius:16px;
  box-shadow:0 16px 48px rgba(0,0,0,.4);
  max-height:calc(100vh - 4rem); display:flex; flex-direction:column; overflow:hidden;
}
.cf-overlay-close{
  position:absolute; top:.5rem; right:.5rem; z-index:1;
  width:2rem; height:2rem; line-height:1; padding:0;
  display:flex; align-items:center; justify-content:center;
  border:1px solid var(--cf-border); border-radius:50%;
  background:var(--cf-bg); color:var(--cf-muted); font-size:1.25rem; cursor:pointer;
}
.cf-overlay-close:hover{ background:var(--cf-icon-bg); color:var(--cf-text); }
.cf-overlay-body{ overflow-y:auto; }
.cf-overlay-loading{ padding:2.5rem 1rem; text-align:center; color:var(--cf-muted); }
.cf-overlay-loading .bi{ display:block; font-size:2rem; margin-bottom:.5rem;
  animation:cf-hourglass 1.2s ease-in-out infinite; }
.cf-overlay-msg{ padding:2rem 1.25rem; text-align:center; color:var(--cf-muted); }
@media (max-width: 575.98px){
  .cf-overlay-backdrop{ padding:1rem .5rem; }
  .cf-overlay-panel{ max-height:calc(100vh - 2rem); }
}

/* ===== sortable tables (2026-08-29) =====
   Any <table class="cf-sortable"> gets click-to-sort headers via JS/TableSort.js. First user:
   Admin/BlockASNConfirm.asp's "members on this ASN" table. */
table.cf-sortable th{ cursor:pointer; user-select:none; white-space:nowrap; }
table.cf-sortable th:hover{ color:var(--cf-heading); }
.cf-sort-arrow{ font-size:.7em; color:var(--cf-muted); }

/* ===== stored message-body formatting (2026-08-31) =====
   MessagePOST.asp / MessageEDIT.asp store posts as HTML: ConvLayoutToMsg() turns the editor's
   <BOLD>/<ITALIC>/<RED>/... layout tags into <span class="bold">, <span class="red">, etc.
   The Messages-system port never brought the matching CSS across, so those spans (and every
   historic post that already uses them) rendered as plain text. These are deliberately bare
   class names - that's the format already sitting in ~20 years of stored MessageText, and
   nothing in Bootstrap or the rest of this file uses them. They only ever appear inside a
   rendered message / PM body. */
.bold      { font-weight:700; }
.italic    { font-style:italic; }
.underline { text-decoration:underline; }
.strike    { text-decoration:line-through; }

.red    { color:#e03131; }
.green  { color:#2f9e44; }
.blue   { color:#1c7ed6; }
.yellow { color:#f08c00; }   /* amber - pure yellow is unreadable on a light card */
.purple { color:#9c36b5; }
.brown  { color:#a0522d; }
.orange { color:#e8590c; }
.grey   { color:var(--cf-muted); }
.black  { color:var(--cf-text); }   /* theme-aware - literal #000 would vanish in dark mode */

/* "In reply to Post #N" prefix (MessagePOST.asp adds <span class="inreply">). */
.inreply { display:inline-block; font-size:.82em; color:var(--cf-muted); margin-bottom:.25rem; }
