/* ══════════════════════════════════════════════════════════════════════
   BBA Peptides Forum — visual design system (bbaforum.com)
   Sampled verbatim from the shipped store, not approximated: tokens below
   were cross-checked against design/store_final.html's live :root (canvas/
   ink/hairline/radius/shadow/motion/ring scales) and design/site-header.css
   + site-header.js + site-footer.js + chat.js for the header/footer/pill/
   button idiom. This is the SAME design system wearing a forum layout, not
   a lookalike — nothing here invents a new palette, radius, or type rule.

   STRUCTURE is the "Atella" dashboard reference izzy supplied (persistent
   sidebar, stat cluster, split hero, 3-up card grid, two bottom panels) —
   but every surface, radius and type choice below is BBA's own: STIX Two
   Text serif for headlines/identity names, IBM Plex Sans for UI/body, IBM
   Plex Mono UPPERCASE for every label/meta/number, hairline borders over
   shadows, 8px radius ceiling (not the reference's pillowy 14px), navy
   #102A4A for the one dark panel (not near-black, not purple).

   FONT LOADING — reuses the exact mechanism store_final.html uses: a
   self-hosted stylesheet at /vendor/fonts.css (no Google Fonts / CDN, no
   new font service). _layout-reference.html links it at that root-relative
   path, matching the store's own <link rel="stylesheet" href="/vendor/
   fonts.css">. Because bbaforum.com is a separate REGISTRABLE domain and
   not a subdomain of the store (forum/wrangler.toml explains why), whoever
   wires the forum's static hosting must COPY that folder into the forum's
   own deploy root — cross-origin @font-face requests are blocked without a
   CORS header the main site doesn't currently send, and there is no
   same-site relaxation to fall back on between two different registrable
   domains the way there would have been across a subdomain. Until that's
   the font stack's system fallbacks (Georgia for the serif, Segoe UI /
   Helvetica for the sans, Consolas for the mono) keep the page fully
   legible and on-model. See the mockup's <head> comment for the same note.

   Prefixed .bf- (BBA Forum) throughout — deliberately distinct from the
   store's .bba- prefix (site-header.js / site-footer.js / chat.js) so this
   sheet can never collide with those scripts if a future page loads both.
═══════════════════════════════════════════════════════════════════════ */

/* ── TOKENS — sampled verbatim from store_final.html's :root ─────────── */
:root{
  /* Canvas & surfaces */
  --canvas:      #F2F1EE;
  --canvas-deep: #EAE7E0;
  --surface-1:   #FFFFFF;
  --surface-2:   #FAF8F4;
  --surface-3:   #F0EDE6;
  --paper:       #F4F2EE;
  --paper-warm:  #EDE9E2;

  /* Dark panel — the hero's one dark surface. Navy, not near-black. */
  --navy:        #102A4A;
  --navy-deep:   #0A1E36;
  --navy-mid:    #1A3A5C;

  /* Brand accents */
  --teal:        #0C6E78;
  --teal-bright: #2BB9C9;
  --accent:      #0C6E78;
  --accent-press:#0A5A63;
  --blue:        #2E78C2;
  --brand-red:   #CD4642;   /* accents / alerts ONLY — never a UI default */
  --clay:        #C98A4B;

  /* Ink / text — on light surfaces */
  --ink:         #14181C;
  --ink-soft:    rgba(20,24,28,.80);
  --body:        rgba(20,24,28,.62);
  --text-ghost:  rgba(20,24,28,.38);
  /* Ink / text — on the navy hero panel */
  --ink-invert:  #FFFFFF;
  --body-invert: rgba(255,255,255,.72);
  --ghost-invert:rgba(255,255,255,.48);

  /* Hairlines — the system leads with these, not shadows */
  --hairline:      #DDD9D1;
  --hair-1:        rgba(20,26,32,.10);
  --hair-2:        rgba(20,26,32,.16);
  --hair-3:        rgba(20,26,32,.26);
  --cool-panel:    #EEF2F6;
  --hairline-cool: #D0D8E4;

  /* Gradients — brand teal→blue, used sparingly (hero media panel only) */
  --grad-brand:   linear-gradient(180deg,#0C6E78 0%,#2E78C2 100%);
  --grad-brand-h: linear-gradient(90deg,#0C6E78 0%,#2E78C2 100%);

  /* Status — green/amber lifted from chat.js's own presence dots, so a
     forum "open" thread and a "Mia is online" dot read as the same idea */
  --status-open:   #22B26A;
  --status-locked: rgba(20,24,28,.42);
  --status-amber:  #C8912B;

  /* Type families */
  --f-display: 'STIX Two Text', 'Times New Roman', Georgia, serif;
  --f-text:    'IBM Plex Sans', 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
  --f-mono:    'IBM Plex Mono', Consolas, 'Courier New', monospace;

  /* Type scale */
  --t-h1: clamp(32px, 4.2vw, 44px);
  --t-h2: clamp(29px, 3vw, 36px);
  --t-h3: clamp(20px, 2.2vw, 26px);

  /* Radii — tight scale, 8px ceiling on cards. No pillowy 14px anywhere. */
  --radius-xs:   3px;
  --radius-sm:   5px;
  --radius-md:   8px;
  --radius-pill: 999px;

  /* Shadows — used sparingly; hairlines carry most edges */
  --shadow-xs:   0 1px 2px rgba(14,32,56,.06);
  --shadow-sm:   0 2px 8px rgba(14,32,56,.08), 0 1px 2px rgba(14,32,56,.04);
  --shadow-md:   0 6px 24px rgba(14,32,56,.10), 0 2px 6px rgba(14,32,56,.05);
  --shadow-navy: 0 4px 20px rgba(16,42,74,.16);

  /* Motion */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --dur-base: 160ms;
  --dur-slow: 320ms;

  /* Focus ring — teal, 15–18:1 on paper per the store's own a11y pass */
  --ring-width:  2px;
  --ring-offset: 2px;
  --ring-color:  #0C6E78;

  /* Layout */
  --wrap:      1200px;
  --gutter:    clamp(20px, 5vw, 32px);
  --s1: 8px; --s2: 16px; --s3: 32px; --s4: 64px;
  --sidebar-w: 250px;
  --topbar-h:  64px;
}

/* ── RESET & BASE ──────────────────────────────────────────────────── */
*, *::before, *::after{ box-sizing:border-box; margin:0; padding:0; }
html{ font-size:15px; scroll-behavior:smooth; }
@media (prefers-reduced-motion:reduce){ html{ scroll-behavior:auto; } }

body.bf-body{
  font-family:var(--f-text);
  background:var(--canvas);
  color:var(--ink);
  -webkit-font-smoothing:antialiased;
  line-height:1.55;
  min-height:100vh;
}

img, svg{ display:block; max-width:100%; }
ul, ol{ list-style:none; }
button{ font:inherit; }
a{ color:inherit; }

/* Prevent ANY element in this system from forcing body-level horizontal
   scroll — the one hard failure mode at 375px. Long unbroken strings
   (thread titles, emails) wrap instead of pushing width. */
.bf-shell, .bf-main, .bf-card-grid, .bf-bottom-row{ min-width:0; }
.bf-headline, .bf-hero-title, .bf-card-title, .bf-thread-title{ overflow-wrap:anywhere; }

/* ── ACCESSIBILITY ─────────────────────────────────────────────────── */
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}
.bf-skip{
  position:absolute; left:-9999px; top:0; z-index:1001;
  background:var(--navy); color:#fff; padding:12px 16px;
  border-radius:0 0 var(--radius-sm) 0; font-family:var(--f-text);
  font-size:14px; text-decoration:none; display:inline-flex; align-items:center;
  min-height:44px;
}
.bf-skip:focus{ left:0; }

:where(a, button, input, select, textarea, summary, [tabindex]:not([tabindex="-1"])):focus{
  outline:none;
}
:where(a, button, input, select, textarea, summary, [tabindex]:not([tabindex="-1"])):focus-visible{
  outline:var(--ring-width) solid var(--ring-color);
  outline-offset:var(--ring-offset);
  border-radius:var(--radius-xs);
}

@media (prefers-reduced-motion:reduce){
  *, *::before, *::after{
    animation-duration:0.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:0.001ms !important;
    scroll-behavior:auto !important;
  }
}

/* Touch: every interactive row/button/link grows to the 44px WCAG 2.5.5/
   2.5.8 floor. Desktop keeps its denser, keyboard/mouse rhythm — same
   split the store's own footer + header already ship (site-footer.js
   ".bba-foot-list a", site-header.css ".bba-cart"). */
@media (pointer:coarse){
  .bf-nav-row, .bf-user-chip, .bf-thread-row, .bf-schedule-row,
  .bf-browse-all, .btn, .btn-link, .bf-post-reply{
    min-height:44px;
  }
}

/* ── TYPE PRIMITIVES ───────────────────────────────────────────────── */
.bf-eyebrow{
  font-family:var(--f-mono);
  font-size:11px;
  font-weight:500;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--teal);
  margin:0 0 8px;
}
.bf-eyebrow.on-dark{ color:var(--teal-bright); }
.bf-eyebrow.neutral{ color:var(--body); }

.bf-headline{
  font-family:var(--f-display);
  font-weight:500;
  font-size:var(--t-h1);
  letter-spacing:-.015em;
  line-height:1.08;
  color:var(--ink);
  margin:0 0 12px;
}
.bf-supporting{
  font-family:var(--f-text);
  font-size:15px;
  line-height:1.55;
  color:var(--body);
  max-width:56ch;
  margin:0;
}
.bf-section-title{
  font-family:var(--f-display);
  font-weight:500;
  font-size:var(--t-h3);
  letter-spacing:-.01em;
  line-height:1.2;
  color:var(--ink);
  margin:0;
}

/* ── BUTTONS ───────────────────────────────────────────────────────── */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  min-height:42px; padding:0 20px;
  font-family:var(--f-text); font-size:14px; font-weight:600;
  border-radius:var(--radius-pill); border:0; cursor:pointer;
  text-decoration:none; white-space:nowrap;
  transition:background var(--dur-base) var(--ease-out),
             border-color var(--dur-base) var(--ease-out),
             box-shadow var(--dur-base) var(--ease-out);
}
.btn-primary{ background:var(--teal); color:#fff; }
.btn-primary:hover{ background:var(--accent-press); }

/* Full-width dark variant — navy, matching the hero panel + .btn-primary's
   own :hover target (--navy-mid) from store_final.html, so "dark button"
   reads as one family across the store and the forum. */
.btn-dark{
  display:flex; width:100%; align-items:center; justify-content:center;
  gap:8px; min-height:44px; padding:0 18px;
  background:var(--navy); color:#fff;
  font-family:var(--f-text); font-size:14px; font-weight:600;
  border-radius:var(--radius-md); border:0; cursor:pointer; text-decoration:none;
  transition:background var(--dur-base) var(--ease-out);
}
.btn-dark:hover{ background:var(--navy-mid); }

.btn-link{
  display:inline-flex; align-items:center; gap:6px;
  font-family:var(--f-text); font-size:13.5px; font-weight:600;
  color:var(--teal); text-decoration:underline; text-underline-offset:3px;
  background:none; border:0; cursor:pointer; padding:2px 0;
  transition:color var(--dur-base) var(--ease-out);
}
.btn-link:hover{ color:var(--accent-press); }
.btn-link.on-dark{ color:var(--body-invert); text-decoration-color:var(--ghost-invert); }
.btn-link.on-dark:hover{ color:#fff; }

/* ── PILLS / BADGES ────────────────────────────────────────────────── */
.bf-pill{
  display:inline-flex; align-items:center; gap:6px;
  height:24px; padding:0 10px;
  font-family:var(--f-mono); font-size:10.5px; font-weight:500;
  letter-spacing:.08em; text-transform:uppercase;
  border-radius:var(--radius-pill); white-space:nowrap;
}
/* Category tag — soft teal tint, matches the store's own hover fill
   (rgba(12,110,120,.08)) used on .bba-cart / .bba-drawer a:focus-visible */
.bf-pill-category{
  background:rgba(12,110,120,.08);
  color:var(--teal);
  border:1px solid rgba(12,110,120,.18);
}
/* Status — a leading dot carries the state; text stays neutral ink */
.bf-pill-status{
  background:var(--surface-1);
  color:var(--ink-soft);
  border:1px solid var(--hair-1);
}
.bf-pill-status::before{
  content:''; width:6px; height:6px; border-radius:50%; flex:none;
}
.bf-pill-status.is-open::before{ background:var(--status-open); }
.bf-pill-status.is-locked::before{ background:var(--status-locked); }
.bf-pill-status.is-locked{ color:var(--body); }

/* ── LAYOUT SHELL ──────────────────────────────────────────────────── */
.bf-shell{
  display:flex;
  align-items:stretch;
  min-height:100vh;
}

/* ── ANNOUNCEMENT BAR — same slot/idiom as the store's .bba-promo ────── */
.bf-promo{
  background:var(--teal);
  color:#F7F5F1;
  font-family:var(--f-mono);
  font-size:11px; font-weight:500; letter-spacing:.14em; text-transform:uppercase;
  text-align:center; padding:9px 16px;
  border-bottom:1px solid rgba(4,20,26,.35);
  line-height:1.4;
}
.bf-promo .bf-dot{ color:var(--brand-red); }
.bf-promo a{ color:#fff; font-weight:600; text-decoration:underline; text-underline-offset:2px; }
@media (max-width:520px){ .bf-promo{ font-size:10.5px; padding:8px 12px; letter-spacing:.08em; } }

/* ── SIDEBAR ───────────────────────────────────────────────────────── */
.bf-sidebar{
  flex:none;
  width:var(--sidebar-w);
  display:flex; flex-direction:column;
  background:var(--surface-1);
  border-right:1px solid var(--hair-1);
  position:sticky; top:0; align-self:flex-start;
  height:100vh; overflow-y:auto;
  padding:20px 16px;
}

.bf-brand{ padding:4px 8px 16px; }
.bf-brand-mark{ display:inline-flex; align-items:center; min-height:44px; text-decoration:none; }
.bf-brand-mark img{ width:120px; height:auto; }
/* Pure-HTML degrade: if the cross-origin logo can't load (see file header
   note on /vendor/fonts.css + forum's separate subdomain), the alt text
   below renders as the wordmark instead of a broken-image glyph. */
.bf-affiliation{
  font-family:var(--f-text); font-size:12px; line-height:1.4;
  color:var(--body); margin:8px 2px 0; max-width:22ch;
}

.bf-nav-groups{ display:flex; flex-direction:column; gap:20px; flex:1; }
.bf-nav-label{
  font-family:var(--f-mono); font-size:10.5px; font-weight:600;
  letter-spacing:.14em; text-transform:uppercase; color:var(--text-ghost);
  padding:0 10px; margin-bottom:6px;
}
.bf-nav-group{ display:flex; flex-direction:column; gap:2px; }

.bf-nav-row{
  display:flex; align-items:center; gap:11px;
  min-height:40px; padding:0 10px;
  border-radius:var(--radius-md);
  font-family:var(--f-text); font-size:14px; font-weight:500;
  color:var(--ink-soft); text-decoration:none;
  position:relative;
  transition:background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}
.bf-nav-row:hover{ background:rgba(20,26,32,.045); color:var(--ink); }
.bf-nav-icon{ flex:none; width:18px; height:18px; color:var(--body); }
.bf-nav-row:hover .bf-nav-icon{ color:var(--ink); }

.bf-nav-row.is-active{
  background:rgba(12,110,120,.08);
  color:var(--teal);
  font-weight:600;
}
.bf-nav-row.is-active .bf-nav-icon{ color:var(--teal); }
.bf-nav-row.is-active::before{
  content:''; position:absolute; left:0; top:8px; bottom:8px; width:3px;
  border-radius:var(--radius-pill); background:var(--teal);
}

.bf-nav-utility{
  display:flex; flex-direction:column; gap:2px;
  margin-top:20px; padding-top:16px; border-top:1px solid var(--hair-1);
}

.bf-sidebar-ruo{
  font-family:var(--f-mono); font-size:9.5px; line-height:1.6;
  letter-spacing:.02em; color:var(--text-ghost);
  margin-top:16px; padding:12px 10px 4px; border-top:1px solid var(--hair-1);
}

/* ── TOPBAR ────────────────────────────────────────────────────────── */
.bf-main-col{ flex:1; min-width:0; display:flex; flex-direction:column; }

.bf-topbar{
  position:sticky; top:0; z-index:20;
  display:flex; justify-content:flex-end; align-items:center;
  min-height:var(--topbar-h); padding:0 var(--gutter);
  background:rgba(252,251,248,.90);
  -webkit-backdrop-filter:blur(16px) saturate(140%);
  backdrop-filter:blur(16px) saturate(140%);
  border-bottom:1px solid var(--hair-1);
}

.bf-user-chip{
  display:flex; align-items:center; gap:9px;
  min-height:44px; padding:5px 14px 5px 6px;
  background:var(--surface-1);
  border:1px solid var(--hair-1); border-radius:var(--radius-pill);
  box-shadow:var(--shadow-xs);
  cursor:pointer;
  transition:border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.bf-user-chip:hover{ border-color:var(--hair-2); box-shadow:var(--shadow-sm); }
.bf-avatar{
  width:30px; height:30px; border-radius:50%; flex:none;
  background:var(--teal); color:#fff;
  font-family:var(--f-text); font-size:12.5px; font-weight:600;
  display:flex; align-items:center; justify-content:center;
}
.bf-user-name{ font-family:var(--f-text); font-size:13.5px; font-weight:600; color:var(--ink); }
.bf-user-chip svg{ width:14px; height:14px; color:var(--body); flex:none; }

/* ── MAIN CONTENT ──────────────────────────────────────────────────── */
.bf-main{
  flex:1;
  max-width:1080px;
  width:100%;
  margin:0 auto;
  padding:var(--s3) var(--gutter) var(--s4);
  display:flex; flex-direction:column; gap:var(--s3);
}

/* ── PAGE HEAD + STAT CLUSTER ──────────────────────────────────────── */
.bf-page-head{
  display:flex; flex-wrap:wrap; align-items:flex-end; justify-content:space-between;
  gap:24px;
}
.bf-page-head-text{ flex:1; min-width:260px; }

.bf-stat-cluster{ display:flex; gap:28px; }
.bf-stat{ display:flex; flex-direction:column; gap:4px; }
.bf-stat:not(:first-child){ border-left:1px solid var(--hairline); padding-left:28px; }
.bf-stat-number{
  font-family:var(--f-text); font-weight:700; font-size:27px; line-height:1;
  color:var(--ink); display:flex; align-items:baseline; gap:4px;
}
.bf-stat-unit{ font-family:var(--f-mono); font-size:11px; color:var(--body); }
.bf-stat-caption{
  font-family:var(--f-mono); font-size:10px; font-weight:500;
  letter-spacing:.1em; text-transform:uppercase; color:var(--body);
  line-height:1.5;
}
@media (max-width:480px){
  .bf-stat-cluster{ flex-direction:column; gap:14px; }
  .bf-stat:not(:first-child){ border-left:0; border-top:1px solid var(--hairline); padding-left:0; padding-top:14px; }
}

/* ── HERO CARD ─────────────────────────────────────────────────────── */
.bf-hero-card{
  display:flex;
  border-radius:var(--radius-md);
  border:1px solid var(--hair-1);
  overflow:hidden;
  box-shadow:var(--shadow-sm);
}

.bf-hero-media{
  flex:0 0 34%;
  min-width:200px;
  background:var(--grad-brand);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:14px; padding:28px 20px; position:relative;
}
.bf-hero-glyph{
  width:56px; height:56px; border-radius:50%;
  background:rgba(255,255,255,.16);
  border:1px solid rgba(255,255,255,.3);
  display:flex; align-items:center; justify-content:center;
}
.bf-hero-glyph svg{ width:24px; height:24px; color:#fff; }
.bf-hero-media-meta{
  position:absolute; left:16px; bottom:14px;
  font-family:var(--f-mono); font-size:10px; letter-spacing:.1em; text-transform:uppercase;
  color:rgba(255,255,255,.82);
}

.bf-hero-body{
  flex:1; min-width:0;
  background:var(--navy);
  box-shadow:var(--shadow-navy);
  color:#fff;
  padding:32px clamp(20px,3vw,40px);
  display:flex; flex-direction:column; justify-content:center; gap:10px;
}
.bf-hero-title{
  font-family:var(--f-display); font-weight:500;
  font-size:clamp(22px,2.6vw,28px); line-height:1.18; letter-spacing:-.01em;
  color:#fff; margin:0;
}
.bf-hero-meta{
  font-family:var(--f-mono); font-size:11px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--body-invert);
}
.bf-hero-actions{ display:flex; align-items:center; gap:20px; margin-top:14px; flex-wrap:wrap; }

@media (max-width:760px){
  .bf-hero-card{ flex-direction:column; }
  .bf-hero-media{ flex:none; padding:24px; }
  .bf-hero-media-meta{ position:static; margin-top:4px; }
}

/* ── SECTION HEADER ROW ────────────────────────────────────────────── */
.bf-section-head{
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:16px; flex-wrap:wrap;
}
.bf-browse-all{
  font-family:var(--f-text); font-size:13.5px; font-weight:600;
  color:var(--teal); text-decoration:underline; text-underline-offset:3px;
  display:inline-flex; align-items:center; gap:5px; white-space:nowrap;
  padding:4px 0;
}
.bf-browse-all:hover{ color:var(--accent-press); }

/* ── CARD GRID / CATEGORY CARD ─────────────────────────────────────── */
.bf-card-grid{
  display:grid;
  grid-template-columns:repeat(3, 1fr);
  gap:20px;
}
@media (max-width:1100px){ .bf-card-grid{ grid-template-columns:repeat(2, 1fr); } }
@media (max-width:700px){ .bf-card-grid{ grid-template-columns:1fr; } }

.bf-category-card{
  display:flex; flex-direction:column;
  background:var(--surface-1);
  border:1px solid var(--hair-1);
  border-radius:var(--radius-md);
  padding:22px;
  transition:box-shadow var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}
.bf-category-card:hover{ box-shadow:var(--shadow-xs); border-color:var(--hair-2); }

.bf-card-badges{ display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:14px; }
.bf-card-title{
  font-family:var(--f-display); font-weight:500; font-size:19px; line-height:1.25;
  color:var(--ink); margin:0 0 8px;
}
.bf-card-desc{
  font-family:var(--f-text); font-size:13.5px; line-height:1.55; color:var(--body);
  margin:0 0 18px;
}
.bf-progress-row{
  display:flex; align-items:baseline; justify-content:space-between;
  font-family:var(--f-mono); font-size:10.5px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--body); margin-bottom:8px;
}
.bf-progress-row strong{ color:var(--ink-soft); font-weight:600; }
.bf-progress-rule{ height:1px; background:var(--hairline); margin-bottom:18px; }
.bf-card-footer{
  font-family:var(--f-mono); font-size:10.5px; letter-spacing:.04em; text-transform:uppercase;
  color:var(--text-ghost); margin-top:14px; line-height:1.5;
}
.bf-card-footer strong{ color:var(--body); font-weight:500; text-transform:none; letter-spacing:0; }

/* ── BOTTOM ROW — two equal panels ─────────────────────────────────── */
.bf-bottom-row{ display:grid; grid-template-columns:1fr 1fr; gap:20px; }
@media (max-width:700px){ .bf-bottom-row{ grid-template-columns:1fr; } }

.bf-panel{
  background:var(--surface-1);
  border:1px solid var(--hair-1);
  border-radius:var(--radius-md);
  padding:24px;
}
.bf-panel-title{ margin-bottom:16px; }

.bf-schedule-list{ display:flex; flex-direction:column; }
.bf-schedule-row{
  display:flex; align-items:center; gap:14px;
  padding:12px 4px; min-height:44px;
  border-top:1px solid var(--hair-1);
  text-decoration:none; color:inherit;
  border-radius:var(--radius-sm);
  transition:background var(--dur-base) var(--ease-out);
}
.bf-schedule-list li:first-child .bf-schedule-row{ border-top:0; }
.bf-schedule-row:hover{ background:rgba(20,26,32,.03); }
.bf-date-block{
  flex:none; width:46px; text-align:center;
  display:flex; flex-direction:column; align-items:center; gap:1px;
}
.bf-date-weekday{
  font-family:var(--f-mono); font-size:9.5px; font-weight:600;
  letter-spacing:.1em; text-transform:uppercase; color:var(--teal);
}
.bf-date-day{ font-family:var(--f-text); font-size:19px; font-weight:700; color:var(--ink); line-height:1.1; }
.bf-schedule-copy{ flex:1; min-width:0; }
.bf-schedule-title{ font-family:var(--f-text); font-size:14px; font-weight:600; color:var(--ink); margin-bottom:2px; }
.bf-schedule-sub{ font-family:var(--f-text); font-size:12.5px; color:var(--body); }
.bf-schedule-row svg{ flex:none; width:16px; height:16px; color:var(--text-ghost); }

/* Deliberate empty state — a new forum starts with nothing, and this
   should read as designed-for, not broken or unfinished. */
.bf-empty-state{
  display:flex; flex-direction:column; align-items:flex-start; gap:12px;
  padding:20px 4px 4px;
}
.bf-empty-icon{
  width:40px; height:40px; border-radius:50%;
  background:var(--cool-panel); display:flex; align-items:center; justify-content:center;
}
.bf-empty-icon svg{ width:18px; height:18px; color:var(--body); }
.bf-empty-copy{ font-family:var(--f-text); font-size:13.5px; line-height:1.55; color:var(--body); max-width:34ch; }

/* ── THREAD LIST ROW ───────────────────────────────────────────────── */
.bf-thread-list{ display:flex; flex-direction:column; background:var(--surface-1); border:1px solid var(--hair-1); border-radius:var(--radius-md); overflow:hidden; }
.bf-thread-row{
  display:flex; align-items:center; gap:14px;
  padding:14px 18px; min-height:44px;
  border-top:1px solid var(--hair-1);
  text-decoration:none; color:inherit;
  transition:background var(--dur-base) var(--ease-out);
}
.bf-thread-list li:first-child .bf-thread-row{ border-top:0; }
.bf-thread-row:hover{ background:rgba(20,26,32,.025); }
.bf-thread-avatar{
  flex:none; width:32px; height:32px; border-radius:50%;
  background:var(--cool-panel); color:var(--navy);
  font-family:var(--f-text); font-size:12px; font-weight:700;
  display:flex; align-items:center; justify-content:center;
}
.bf-thread-main{ flex:1; min-width:0; }
.bf-thread-title{
  font-family:var(--f-display); font-weight:500; font-size:15.5px;
  color:var(--ink); line-height:1.35; margin-bottom:3px;
  overflow:hidden; text-overflow:ellipsis; display:-webkit-box; -webkit-line-clamp:1; -webkit-box-orient:vertical;
}
.bf-thread-meta{ font-family:var(--f-mono); font-size:10.5px; letter-spacing:.04em; text-transform:uppercase; color:var(--body); }
.bf-thread-side{ flex:none; display:flex; align-items:center; gap:16px; }
.bf-thread-replies{ font-family:var(--f-mono); font-size:11px; color:var(--body); text-align:right; white-space:nowrap; }
.bf-thread-replies strong{ color:var(--ink-soft); font-weight:600; }
.bf-thread-time{ font-family:var(--f-mono); font-size:10.5px; color:var(--text-ghost); white-space:nowrap; min-width:52px; text-align:right; }

@media (max-width:640px){
  .bf-thread-row{ flex-wrap:wrap; }
  .bf-thread-side{ width:100%; justify-content:space-between; padding-left:46px; }
}

/* ── POST BLOCK ────────────────────────────────────────────────────── */
.bf-post{
  display:flex; gap:14px;
  background:var(--surface-1);
  border:1px solid var(--hair-1);
  border-radius:var(--radius-md);
  padding:20px;
}
.bf-post-avatar{
  flex:none; width:38px; height:38px; border-radius:50%;
  background:var(--teal); color:#fff;
  font-family:var(--f-text); font-size:14px; font-weight:600;
  display:flex; align-items:center; justify-content:center;
}
.bf-post-body{ flex:1; min-width:0; }
.bf-post-head{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; margin-bottom:8px; }
.bf-post-author{ font-family:var(--f-text); font-size:14px; font-weight:700; color:var(--ink); }
.bf-post-time{ font-family:var(--f-mono); font-size:10.5px; letter-spacing:.04em; text-transform:uppercase; color:var(--text-ghost); }
.bf-post-text{ font-family:var(--f-text); font-size:14.5px; line-height:1.6; color:var(--ink-soft); margin-bottom:14px; }
.bf-post-text p + p{ margin-top:10px; }
.bf-post-reply{
  display:inline-flex; align-items:center; gap:6px;
  font-family:var(--f-text); font-size:13px; font-weight:600; color:var(--teal);
  background:none; border:0; cursor:pointer; padding:4px 0;
}
.bf-post-reply:hover{ color:var(--accent-press); }
.bf-post-reply svg{ width:14px; height:14px; }

/* Held-for-moderation state — muted, explained, never looks like an error */
.bf-post-review{
  background:var(--canvas);
  border-style:dashed;
  border-color:var(--hair-2);
}
.bf-post-review .bf-post-avatar{ background:var(--hairline); color:var(--body); }
.bf-post-review .bf-post-author,
.bf-post-review .bf-post-text{ color:var(--body); }
.bf-review-note{
  display:inline-flex; align-items:center; gap:6px;
  font-family:var(--f-mono); font-size:10px; font-weight:600;
  letter-spacing:.08em; text-transform:uppercase; color:var(--status-amber);
  margin-bottom:10px;
}
.bf-review-note svg{ width:12px; height:12px; }
.bf-review-explainer{
  font-family:var(--f-mono); font-size:11px; line-height:1.6; color:var(--text-ghost);
  margin-top:10px; padding-top:10px; border-top:1px solid var(--hair-1);
}

/* ── DEMO SECTION DIVIDER (mockup only — groups the forum-specific
   components the reference layout didn't have: thread list, post, review
   state, pill-state swatch) ───────────────────────────────────────────── */
.bf-demo-section{ display:flex; flex-direction:column; gap:16px; }
.bf-demo-divider{
  display:flex; align-items:center; gap:14px;
  font-family:var(--f-mono); font-size:10px; font-weight:600;
  letter-spacing:.14em; text-transform:uppercase; color:var(--text-ghost);
  margin:8px 0 -4px;
}
.bf-demo-divider::after{ content:''; flex:1; height:1px; background:var(--hairline); }

/* ── FOOTER — recognisably the store's footer (site-footer.js idiom) ─── */
.bf-foot{
  background:var(--surface-3);
  border-top:1px solid var(--hair-1);
  margin-top:8px;
  color:rgba(20,24,28,.72);
  font-family:var(--f-text);
}
.bf-foot-inner{ max-width:1080px; margin:0 auto; padding:36px var(--gutter) 30px; }
.bf-foot-cols{ display:flex; flex-wrap:wrap; gap:32px 56px; }
.bf-foot-col-label{
  font-family:var(--f-mono); font-size:11px; letter-spacing:.14em; text-transform:uppercase;
  color:rgba(20,24,28,.72); margin:0 0 12px;
}
.bf-foot-list{ display:flex; flex-direction:column; gap:2px; }
.bf-foot-list a{
  color:rgba(20,24,28,.80); text-decoration:none; font-size:14px;
  display:flex; align-items:center; min-height:26px; width:fit-content; padding-right:8px;
}
.bf-foot-list a:hover{ color:var(--teal); }
@media (pointer:coarse), (max-width:760px){
  .bf-foot-list{ gap:0; }
  .bf-foot-list a{ min-height:44px; }
}
.bf-foot-ruo{
  margin:28px 0 0; padding:16px 0 0; border-top:1px solid var(--hair-1);
  font-family:var(--f-mono); font-size:11px; line-height:1.6; letter-spacing:.01em;
  color:rgba(20,24,28,.72);
}
.bf-foot-copy{
  margin:10px 0 0; font-family:var(--f-mono); font-size:11px; letter-spacing:.06em;
  text-transform:uppercase; color:rgba(20,24,28,.68);
}
.bf-foot-credit{
  color:rgba(20,24,28,.68); text-decoration:underline; text-underline-offset:2px;
  display:inline-flex; align-items:center; gap:5px; min-height:26px; vertical-align:middle;
}
.bf-foot-credit:hover{ color:var(--teal); }
@media (pointer:coarse), (max-width:760px){ .bf-foot-credit{ min-height:44px; } }

/* ── SIDEBAR → TOP BAR under ~860px ───────────────────────────────────
   Pure CSS, no reorder needed: the sidebar is already first in DOM order,
   so switching .bf-shell to a column keeps it visually on top. Internally
   it flips to a horizontally-scrollable row so nothing ever forces the
   BODY to scroll sideways — only this one strip does, deliberately. ─── */
@media (max-width:860px){
  .bf-shell{ flex-direction:column; min-height:0; }
  .bf-sidebar{
    position:sticky; top:0; z-index:30; align-self:auto;
    width:100%; height:auto; max-height:none;
    flex-direction:row; align-items:center; gap:14px;
    padding:8px 12px;
    border-right:0; border-bottom:1px solid var(--hair-1);
    background:rgba(252,251,248,.92);
    -webkit-backdrop-filter:blur(16px) saturate(140%);
    backdrop-filter:blur(16px) saturate(140%);
    overflow-x:auto; overflow-y:visible;
  }
  .bf-brand{ flex:none; padding:2px 4px; }
  .bf-brand-mark img{ width:96px; }
  .bf-affiliation, .bf-sidebar-ruo{ display:none; } /* RUO persists via the footer */
  .bf-nav-groups{ flex-direction:row; align-items:center; gap:18px; flex:none; }
  .bf-nav-group{ flex-direction:row; align-items:center; gap:2px; }
  .bf-nav-label{ display:none; }
  .bf-nav-row{ white-space:nowrap; padding:0 10px; }
  .bf-nav-row.is-active::before{ left:8px; right:8px; top:auto; bottom:0; width:auto; height:2px; }
  .bf-nav-utility{ flex-direction:row; margin:0; padding:0 0 0 14px; border-top:0; border-left:1px solid var(--hair-1); flex:none; }
}


/* ═══════════════════════════════════════════════════════════════════════
   THE CLASSIC FORUM SURFACES (izzy reversed the Telegram-rooms pivot,
   2026-08-21). Everything below is the chrome + compose + post-detail work
   the SSR routes need on top of the dashboard components already declared
   above — and every value reads ONLY the :root custom properties this file
   already declares. No new palette, no new radius or shadow scale, no
   second type stack. The chat-bubble block that briefly lived here is
   deleted rather than left orphaned: dead CSS is how two design systems
   quietly diverge.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── SHELL ADJUSTMENTS ────────────────────────────────────────────────── */
/* The wordmark is set in the display serif rather than fetched as an image:
   the forum is a separate origin from the store (see this file's header on
   /vendor/*), and a cross-origin logo that fails to load would leave a
   broken-image glyph where the brand should be. */
.bf-brand-word{
  font-family:var(--f-display); font-weight:500; font-size:19px;
  letter-spacing:.01em; color:var(--ink);
}
.bf-brand-mark:hover .bf-brand-word{ color:var(--teal); }

.bf-topbar{ justify-content:space-between; gap:16px; }
.bf-topbar-home{
  font-family:var(--f-mono); font-size:11px; font-weight:600;
  letter-spacing:.14em; text-transform:uppercase; color:var(--body);
  text-decoration:none; display:inline-flex; align-items:center; min-height:44px;
}
.bf-topbar-home:hover{ color:var(--teal); }
.bf-account{ display:flex; align-items:center; gap:14px; }
/* The chip is a STATIC label here, not a menu button — no pointer affordance
   for something that doesn't open. */
span.bf-user-chip{ cursor:default; }

/* The footer sits inside .bf-main (one column, one gap rhythm), so it bleeds
   back out to the full width of the main column instead of floating in the
   content gutter. */
.bf-main > .bf-foot{
  margin:var(--s3) calc(var(--gutter) * -1) calc(var(--s4) * -1);
}
.bf-foot-affil{
  font-family:var(--f-text); font-size:13px; font-weight:600;
  color:var(--ink); margin-top:18px;
}

/* ── PAGE HEAD EXTRAS ─────────────────────────────────────────────────── */
.bf-page-head-actions{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
/* A thread title is prose, not a display line — it wraps, it can be long, and
   it must not run at the 44px hero size. */
.bf-thread-headline{
  font-size:clamp(23px, 2.6vw, 31px); line-height:1.22; max-width:26ch;
}
.bf-marker-row{ display:flex; flex-wrap:wrap; gap:8px; margin-top:12px; }

/* ── PILLS ────────────────────────────────────────────────────────────── */
/* "In review" reuses the system's amber (the same one chat.js uses for a
   pending state) — a queued post is waiting, not broken, so it never gets the
   red reserved for alerts. */
.bf-pill-status.is-review{ color:#7A5A16; }
.bf-pill-status.is-review::before{ background:var(--status-amber); }

/* ── THREAD LIST ──────────────────────────────────────────────────────── */
/* A muted row is the VIEWER'S OWN held or removed thread — nobody else's copy
   of the page contains the row at all (the API filters it in SQL), so this
   styling is never what keeps a stranger from reading it. */
.bf-thread-row.is-muted{ background:var(--surface-2); }
.bf-thread-row.is-muted .bf-thread-title{ color:var(--body); }
.bf-thread-list .bf-pill{ flex:none; }

.bf-card-title a{ text-decoration:none; }
.bf-card-title a:hover{ color:var(--teal); }
.bf-card-footer a{ color:inherit; text-decoration:none; }
.bf-card-footer a:hover strong{ color:var(--teal); }

/* ── RULE LIST (posting rules, "before you post") ─────────────────────── */
.bf-rule-list{ display:flex; flex-direction:column; gap:9px; }
.bf-rule-list li{
  position:relative; padding-left:18px;
  font-family:var(--f-text); font-size:13.5px; line-height:1.55; color:var(--body);
}
.bf-rule-list li::before{
  content:''; position:absolute; left:2px; top:8px;
  width:5px; height:5px; border-radius:50%; background:var(--teal);
}
.bf-rule-list strong{ color:var(--ink-soft); font-weight:600; }
.bf-panel-foot{ margin-top:16px; }

/* ── POST LIST (thread view) ──────────────────────────────────────────── */
.bf-post-list{
  display:flex; flex-direction:column;
  background:var(--surface-1);
  border:1px solid var(--hair-1); border-radius:var(--radius-md);
  overflow:hidden;
}
.bf-post-list .bf-post{ border-top:1px solid var(--hair-1); }
.bf-post-list .bf-post:first-child{ border-top:0; }
/* The opening post carries the thread — a teal spine marks it without a
   second background colour. */
.bf-post-op{ box-shadow:inset 3px 0 0 var(--teal); }
.bf-post-time{ text-decoration:none; }
.bf-post-time:hover{ color:var(--teal); }
.bf-post-head .bf-pill{ flex:none; }

/* ── REPORT DISCLOSURE ────────────────────────────────────────────────── */
/* Native <details> — the report path works with JS disabled right up to the
   submit, which is the point: moderation surfaces don't get to be the ones
   that need a working script. */
.bf-report{ margin-top:14px; }
.bf-report summary{
  cursor:pointer; list-style:none; display:inline-flex; align-items:center;
  min-height:28px; font-family:var(--f-mono); font-size:10.5px;
  letter-spacing:.06em; text-transform:uppercase; color:var(--text-ghost);
}
.bf-report summary::-webkit-details-marker{ display:none; }
.bf-report summary:hover{ color:var(--brand-red); }
.bf-report-form{
  margin-top:10px; padding:14px; max-width:380px;
  display:flex; flex-direction:column; gap:8px;
  background:var(--surface-2);
  border:1px solid var(--hair-1); border-radius:var(--radius-sm);
}
.bf-report-form label{
  font-family:var(--f-mono); font-size:10.5px; letter-spacing:.06em;
  text-transform:uppercase; color:var(--body);
}
.bf-report-form select, .bf-report-form input[type=text]{
  width:100%; min-height:42px; padding:9px 10px;
  font:400 14px var(--f-text); color:var(--ink);
  background:var(--surface-1);
  border:1px solid var(--hair-2); border-radius:var(--radius-sm);
}
.bf-report-form button{ align-self:flex-start; }

/* ── PAGINATION ───────────────────────────────────────────────────────── */
/* Keyset links ("older" / "more replies"), never numbered pages — there is no
   page N to link to in a keyset walk. */
.bf-pager{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding-top:4px;
}
.bf-pager a{ min-height:44px; display:inline-flex; align-items:center; }

/* ── COMPOSE (new thread + reply + the handle gate) ───────────────────── */
.bf-compose-card{
  background:var(--surface-1);
  border:1px solid var(--hair-1); border-radius:var(--radius-md);
  padding:22px;
  display:flex; flex-direction:column; gap:16px;
}
.bf-compose-gate{ align-items:flex-start; }
.bf-compose-gate .btn{ align-self:flex-start; }
/* The rules sit directly above the box, not behind a link: this is the one
   moment a first-time poster is deciding what to type. */
.bf-compose-rules{
  padding:14px 16px;
  background:var(--surface-2);
  border:1px solid var(--hair-1); border-radius:var(--radius-sm);
}
.bf-compose-form{ display:flex; flex-direction:column; gap:16px; }
.bf-field{ display:flex; flex-direction:column; gap:6px; }
.bf-field label{
  font-family:var(--f-mono); font-size:11px; font-weight:600;
  letter-spacing:.06em; text-transform:uppercase; color:var(--body);
}
.bf-compose-form input[type=text], .bf-compose-form select, .bf-compose-form textarea{
  width:100%; padding:12px;
  font:400 15px/1.6 var(--f-text); color:var(--ink);
  background:var(--surface-1);
  border:1px solid var(--hair-2); border-radius:var(--radius-sm);
}
/* 16px on touch: anything smaller makes iOS Safari zoom the page on focus,
   which is its own horizontal-scroll bug. */
@media (pointer:coarse){
  .bf-compose-form input[type=text], .bf-compose-form select,
  .bf-compose-form textarea, .bf-handle-form input{ font-size:16px; }
}
.bf-compose-form input[type=text]{ min-height:46px; }
.bf-compose-form select{ min-height:46px; }
.bf-compose-form textarea{ resize:vertical; min-height:150px; }
.bf-compose-actions{ display:flex; align-items:center; gap:16px; flex-wrap:wrap; }

.bf-handle-form{ display:flex; gap:10px; flex-wrap:wrap; align-items:center; }
.bf-handle-form input{
  flex:1; min-width:200px; min-height:46px; padding:12px;
  font:400 15px var(--f-text); color:var(--ink);
  background:var(--surface-1);
  border:1px solid var(--hair-2); border-radius:var(--radius-sm);
}

/* ── MOBILE ───────────────────────────────────────────────────────────── */
@media (max-width:860px){
  .bf-page-head{ align-items:flex-start; }
  .bf-page-head-actions{ width:100%; }
  .bf-page-head-actions .btn, .bf-page-head-actions .btn-dark{ flex:1; justify-content:center; }
  .bf-thread-headline{ max-width:none; }
  .bf-main > .bf-foot{ margin-bottom:0; }

  /* THE MOBILE COMPOSER.
     A composer in normal flow does NOT move when the on-screen keyboard
     opens — the LAYOUT viewport is unchanged while the VISUAL viewport
     shrinks, so the box ends up underneath the keyboard and the person
     cannot see what they are typing. forms.js measures the real inset from
     window.visualViewport (ignoring anything under ~60px, which is browser
     chrome collapsing, not a keyboard), writes it here as --kb and adds
     .is-lifted; only then does the card leave the flow and pin itself
     exactly --kb above the layout viewport's bottom edge — i.e. sitting on
     top of the keyboard. Same mechanism, same token name, as design/chat.js
     in the store.

     position:FIXED, not sticky: a sticky bottom offset measurably does not
     move this card (its containing block is the .bf-main flex column, and
     Chrome leaves the box where it is) — verified on a 375x812 touch
     viewport before writing this rule, not assumed. With no keyboard open
     the card is an ordinary block at the end of the thread; nothing is
     pinned to the screen while you are only reading. */
  .bf-compose-card[data-composer].is-lifted{
    position:fixed; left:0; right:0; bottom:var(--kb, 0px); z-index:60;
    max-height:calc(100dvh - var(--kb, 0px) - 8px); overflow-y:auto;
    padding:14px; gap:12px;
    border-left:0; border-right:0; border-bottom:0;
    border-radius:var(--radius-md) var(--radius-md) 0 0;
    box-shadow:0 -6px 24px rgba(14,32,56,.10);
  }
  /* Lifted = a keyboard is genuinely open, so the card sheds everything that
     is not the box you are typing in — on a 300px-tall visual viewport the
     rules block would push the textarea back off screen. */
  .bf-compose-card[data-composer].is-lifted .bf-compose-rules{ display:none; }
  .bf-compose-card[data-composer].is-lifted .bf-section-title{ display:none; }
  .bf-compose-card[data-composer].is-lifted textarea{ min-height:96px; }
}

@media (max-width:520px){
  /* At 375px nothing may force the BODY to scroll sideways. The thread row's
     side column drops under the title instead of fighting it for width, and
     the report form stops being a fixed 380px. */
  .bf-thread-row{ flex-wrap:wrap; }
  .bf-thread-side{ width:100%; justify-content:space-between; gap:10px; }
  .bf-report-form{ max-width:none; }
  .bf-pager{ flex-wrap:wrap; gap:8px; }
  .bf-post-list{ border-radius:var(--radius-sm); }
  .bf-compose-card{ padding:16px; }
}

/* ── TOUCH TARGETS, RE-ASSERTED LAST ──────────────────────────────────────
   The @media (pointer:coarse) block near the top of this file raises these to
   the 44px WCAG 2.5.5/2.5.8 floor, but it is declared BEFORE the components
   themselves (.btn min-height:42px, .bf-nav-row min-height:40px) and carries
   the same specificity — so the later component rule won and every nav row
   and button measured 40–42px on a phone. Measured on a 375×812 touch
   viewport, not assumed. Re-asserting at the end of the cascade is the fix
   that does not require reordering rules other pages already depend on. */
@media (pointer:coarse){
  .bf-nav-row, .btn, .btn-dark, .btn-link,
  .bf-thread-row, .bf-schedule-row, .bf-browse-all, .bf-post-reply,
  .bf-user-chip, .bf-topbar-home{ min-height:44px; }
  /* A category card's title is its main target, not decoration — it gets a
     real hit box. The "Latest:" line under it is prose with a link in it, so
     it only gets breathing room. */
  .bf-card-title a{ display:inline-flex; align-items:center; min-height:44px; }
  .bf-card-footer a{ display:inline-block; padding:6px 0; }
  .bf-report summary{ min-height:44px; }
}
@media (pointer:coarse){
  /* The report form is a moderation surface — its controls get the same floor
     as every other tappable thing, not the desktop 42px. */
  .bf-report-form select, .bf-report-form input[type=text], .bf-report-form button{ min-height:44px; }
  /* Links inside the posting-rules list are prose, but they are the only way
     into the policy from the composer, so they get a real hit box. */
  .bf-rule-list a{ display:inline-block; padding:5px 0; }
}
