/* ===========================================================================
   fbi-core.css - the ONE stylesheet every fanbaseintel.com page links.

   WHAT THIS IS
     The design system made executable. Tokens (colour, type, rhythm) live here
     and nowhere else. Pages keep their own layout CSS; they must not re-declare
     anything in this file.

   WHAT IT REPLACES
     design-tokens.css + apply-fbtokens.py solved the COLOUR half on 2026-09-03
     and its own header said the type scale was "a separate, bigger change".
     This is that change. The :root below is design-tokens.css verbatim plus the
     type layer, so this file is a strict superset - retire the old one.

   WHY IT EXISTS
     Every page carried its own inline :root and its own hand-written type
     scale, written from memory by whichever session built it. Measured on live
     2026-09-03 across just three pages: three hero sizes (86/56/48px floors),
     three display leadings (.9/.94/.96), three body leadings (1.4/1.55/1.6),
     and the same mono label built twice under two names with two specs
     (.kicker 11px/.22em vs .eyebrow 10px/.18em). None of that is a decision
     anyone made. It is drift.

   ---------------------------------------------------------------------------
   LINKING THIS FILE CANNOT MOVE AN EXISTING PAGE. That is deliberate and it is
   the whole migration strategy: there are NO bare element rules in here (no
   h1{}, no section{}, no body{}). It only defines custom properties and opt-in
   .fbi-* classes. So step 1 is safe to roll onto all 25 pages at once, and
   step 2 (pointing a page's own selectors at the vars) happens page by page.
   Do not add a bare element selector to this file - it would turn a safe
   sitewide roll into a sitewide restyle.
   ---------------------------------------------------------------------------

   USAGE
     <link rel="stylesheet" href="/fbi-core.css">   after the Google Fonts link
     Then in the page's own CSS, replace hardcoded values with the vars:
       .hero h1{ font-size:var(--t-hero); line-height:var(--lh-display); }
     Or use the primitives directly on new markup:
       <p class="fbi-kicker">01 / The offer</p>

   ENFORCED BY
     ops/scripts/audit-design.mjs - run it against live URLs before any deploy.

   Deploy path: /var/www/html/fanbaseintel/fbi-core.css  (served at /fbi-core.css)
   =========================================================================== */

:root{
  /* audit 2026-09-03: without this, native scrollbars, <select> menus, date
     pickers and Chrome autofill all render in the LIGHT palette on top of a
     dark page. One line, every page that links this file. */
  color-scheme:dark;
  /* --- surfaces, lines, ink. Canonical, from design-tokens.css. ----------- */
  --bg:#000000; --panel:#0a0b0a; --cell:#121410; --line:#1b1d19; --line-2:#2b2f29;
  --ink:#ffffff; --muted:#b0b5aa; --muted-2:#81877a;
  --muted-3:#545a4f;   /* faintest rule / disabled - large text only */ --dim:#3b3b3b;
  --accent:#b4ff3c; --accent-2:#cfff7a; --accent-dim:rgba(180,255,60,.10); --accent-line:rgba(180,255,60,.30);
  --glow:rgba(180,255,60,.14);

  /* --- THE SERIES PALETTE ------------------------------------------------
     One colour per metric, shared by every chart, dot, icon and legend on the
     site and in the panel. Lifted verbatim from growth-tool-d2.php so the two
     surfaces cannot drift: a dot on /engagement is the same lime as "New fans"
     on the stats chart and the Followers band on the targeting map.

     A dot and its icon must always take the SAME token - set the colour once on
     the row and let both read currentColor, never two hardcoded values kept in
     step by hand.

     These were REFERENCED by /engagement (var(--views) etc) and defined NOWHERE,
     here or in the page. An undefined var() in a stroke or background is invalid
     at computed-value time, so every package-card dot and every slider icon on
     that page rendered with no brand colour at all. */
  --s-fans:#b4ff3c;    /* new fans      - followers targeting */
  --s-likes:#FF2E88;   /* post likes    - likers targeting    */
  --s-views:#00E5FF;   /* story views   - hashtag targeting   */
  --s-slikes:#FF8A00;  /* story likes   - location targeting  */
  --s-alt:#A855F7;     /* timeline / following / list         */

  /* /engagement's four metrics, mapped onto the series palette above. */
  --views:var(--s-views); --likes:var(--s-likes);
  --saves:var(--s-fans);  --shares:var(--s-slikes);

  /* Text greys are these two solid tokens ONLY. Never set body or label text
     with rgba(244,244,239,.X) - low-opacity greys land a different value per
     line, which is what "all over the place" looks like. Opacity-rgba is for
     structural hairlines only. The nav scopes the older #868686 pair to
     .fbnav itself (Derek 2026-09-03); that exception stays inside the nav and
     is never copied outward. */

  /* --- fonts. Two names for DM Sans existed (--sans and --body) and pages
         mixed them, so a component copied between pages could silently lose
         its face. --body is canonical; --sans is kept as an alias so older
         page CSS keeps resolving. Do not introduce a third name. ---------- */
  --display:"Anton",sans-serif;
  --body:"DM Sans",sans-serif;
  --sans:var(--body);
  --mono:"JetBrains Mono",monospace;

  /* --- TYPE SCALE (the rule that did not exist before). ------------------
     Sizes are the homepage's, which /affiliate already matched exactly - so
     this is the live reference, not a new invention. If a headline needs to
     read heavier the lever is the next step UP, never tighter leading. */
  --t-hero:   clamp(56px,10.6vw,132px);  /* page H1, one per page            */
  --t-h2:     clamp(33px,5.4vw,64px);    /* section head                     */
  --t-h3:     clamp(22px,2.6vw,30px);    /* sub-head inside a section        */
  /* Figures are their own family, not a text step. Folio numbers, prices and
     stat values are signature devices in this system, so they get steps rather
     than an exemption from the scale. All three are set to values already on
     the site, so adopting them moves nothing. */
  --t-folio:     clamp(86px,15vw,190px); /* oversized decorative folio       */
  --t-figure:    clamp(62px,10vw,98px);  /* price hero / big stat digits     */
  --t-figure-sm: clamp(32px,4.6vw,50px); /* stat value inside a cell         */
  --t-lead:   15px;                      /* standfirst paragraph             */
  --t-body:   14px;                      /* body copy                        */
  --t-kicker: 11px;                      /* mono eyebrow above a heading     */
  --t-label:  10px;                      /* mono label, code, metadata       */

  /* --- LEADING. Three values, and .96 is a floor, not a starting point.
         Display lines must never touch (Derek 2026-09-03: "remove this from
         our design style, you do this a lot"). Anton has one weight; crushing
         the leading is not a substitute for it. ---------------------------- */
  --lh-display:.96;
  --lh-figure:1;    /* digits sit on one line, no descenders to clear */
  --lh-body:1.55;
  --lh-mono:1;

  /* --- TRACKING. Digits get LOOSE tracking - negative tracking on figures
         (9,410 / $97) hurts legibility. Never tighten a number. ------------ */
  --ls-display:.005em;
  --ls-figure:.01em;
  --ls-kicker:.22em;
  --ls-label:.16em;

  /* --- RHYTHM. Defined since 2026-09-03, used by zero pages: every page
         hand-rolls its section padding instead, which is why vertical rhythm
         differs by ~20% page to page. Migrating a page means pointing its
         section rule at --gap-sect. Never hand-roll these - change the token. */
  --maxw:1080px;
  --gap-head:18px;        /* header block to its first content block  */
  --gap-sub:64px;         /* sub-heading break inside a section       */
  --gap-sect:88px;        /* section break                            */
  --gap-block:44px;       /* standalone block between two sections    */
  --gap-sect-tight:34px;  /* after an embed that carries its own pad  */

  /* --- CARD SPACING (CLAUDE.md, non-negotiable). Padding is equal on all
         four sides; top spacing never differs from bottom inside the same
         container. --------------------------------------------------------- */
  --pad-card:16px;
  --gap-in-card:12px;
  --gap-cards:16px;

  --ease:cubic-bezier(.2,.7,.2,1);
}

/* ===========================================================================
   PRIMITIVES - opt in by class. Nothing here applies to bare elements.
   =========================================================================== */

.fbi-hero{
  font-family:var(--display); font-weight:400;
  font-size:var(--t-hero); line-height:var(--lh-display);
  letter-spacing:var(--ls-display); text-transform:uppercase;
  margin:0; color:var(--ink);
}
.fbi-h2{
  font-family:var(--display); font-weight:400;
  font-size:var(--t-h2); line-height:var(--lh-display);
  letter-spacing:var(--ls-display); text-transform:uppercase;
  margin:0; color:var(--ink);
}
.fbi-h3{
  font-family:var(--display); font-weight:400;
  font-size:var(--t-h3); line-height:var(--lh-display);
  letter-spacing:var(--ls-display); text-transform:uppercase;
  margin:0; color:var(--ink);
}
.fbi-figure{
  font-family:var(--display); font-weight:400;
  font-size:var(--t-figure); line-height:var(--lh-figure);
  letter-spacing:var(--ls-figure);
  margin:0; color:var(--ink);
}

/* The mono eyebrow. This existed twice, as .kicker (11px/.22em/500) and as
   .eyebrow (10px/.18em/400), for the same visual role. One name now. */
.fbi-kicker{
  font-family:var(--mono); font-weight:500;
  font-size:var(--t-kicker); line-height:var(--lh-mono);
  letter-spacing:var(--ls-kicker); text-transform:uppercase;
  margin:0; color:var(--muted);
}
.fbi-kicker b,.fbi-kicker strong{ color:var(--accent); font-weight:500; }

.fbi-label{
  font-family:var(--mono); font-weight:500;
  font-size:var(--t-label); line-height:var(--lh-mono);
  letter-spacing:var(--ls-label); text-transform:uppercase;
  margin:0; color:var(--muted-2);
}

.fbi-lead{
  font-family:var(--body); font-weight:400;
  font-size:var(--t-lead); line-height:var(--lh-body);
  margin:0; color:var(--muted);
}
.fbi-body{
  font-family:var(--body); font-weight:400;
  font-size:var(--t-body); line-height:var(--lh-body);
  margin:0; color:var(--muted);
}

/* Lime accent word inside a display line. The editorial style sets these in
   italic, which is why the homepage loads the DM Sans italic axis. */
.fbi-accent{ color:var(--accent); }

/* Container. Auth pages are deliberately narrower and opt out by not using it. */
.fbi-wrap{
  width:100%; max-width:var(--maxw); margin-inline:auto;
  padding-inline:22px; box-sizing:border-box;
}

/* Section rhythm. */
.fbi-sect{ padding-block:var(--gap-sect); }
.fbi-sect--tight{ padding-block:var(--gap-sect-tight); }

/* Card. Equal padding all four sides, always. */
.fbi-card{
  background:var(--panel); border:1px solid var(--line); border-radius:0;
  padding:var(--pad-card); box-sizing:border-box;
}
.fbi-card > * + *{ margin-top:var(--gap-in-card); }
.fbi-card > :last-child{ margin-bottom:0; }

/* ===========================================================================
   COMPONENTS - the blocks that already exist on three or more pages, each
   currently built under a different name on every page. Surveyed from live
   2026-09-03; the names each one replaces are listed above it so you can find
   and retire them.

   Every class here is new, so adding this file to a page changes nothing until
   the page opts in. Same safety property as the tokens above.
   =========================================================================== */

/* --- SECTION + SECTION HEADER ---------------------------------------------
   The single most duplicated block on the site: a mono eyebrow, a display
   heading, and a lead paragraph. Found under SIX different names -
   .folio-lbl/.hi-eyebrow and .rc-kicker/.rc-ahead (home), .kicker/.sec-head
   (affiliate), .eyebrow-pill/.head (reviews), .seclbl (engagement),
   .res-eyebrow/.res-lede (results).

   The heading inside it MUST be a real <h2>. On most pages today it is a
   <div class="sec-head">, which is why the site has 15 sections and no
   document outline. Use .fbi-h2 on the h2 itself. */
.fbi-sec{ padding-block:var(--gap-sect); }
.fbi-sec--tight{ padding-block:var(--gap-sect-tight); }

.fbi-sec-head{ margin:0 0 var(--gap-sub); max-width:62ch; }
.fbi-sec-head > * + *{ margin-top:var(--gap-head); }
/* A lead sits closer to its heading than the next section does. */
.fbi-sec-head .fbi-lead{ max-width:58ch; }

/* --- BUTTON ---------------------------------------------------------------
   Four systems today: .btn.btn-primary.btn-lg (home), .cta (pricing),
   .btn-quiet and .direct (affiliate), .pill and .cell (reviews).

   44px min height is the tap target, not a style choice - the site had targets
   under it. Radius stays 0 per the anchor decision. */
.fbi-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:10px;
  min-height:44px; padding:0 22px; box-sizing:border-box;
  font-family:var(--mono); font-weight:500; font-size:12px;
  letter-spacing:var(--ls-label); text-transform:uppercase;
  text-decoration:none; border:1px solid transparent; border-radius:0;
  cursor:pointer; transition:background .14s var(--ease),color .14s var(--ease),
    border-color .14s var(--ease);
}
/* fbi:press-state */
.fbi-btn{-webkit-tap-highlight-color:transparent;transition:background .14s var(--ease),color .14s var(--ease),
    border-color .14s var(--ease),transform .16s}
.fbi-btn:active{transform:scale(.97)}
@media(prefers-reduced-motion:reduce){.fbi-btn:active{transform:scale(.99)}}
/* fbi:press-state:end */
.fbi-btn--primary{ background:var(--accent); color:#000000; }
.fbi-btn--primary:hover{ background:var(--accent-2); }
.fbi-btn--quiet{ background:transparent; color:var(--ink); border-color:var(--line-2); }
.fbi-btn--quiet:hover{ border-color:var(--accent-line); color:var(--accent); }
.fbi-btn--block{ display:flex; width:100%; }

/* The small bordered badge/link - a Trustpilot score, a tag. Not a button:
   it is smaller than the tap target on purpose because it is inline in copy. */
.fbi-pill{
  display:inline-flex; align-items:center; gap:8px;
  padding:7px 12px; border:1px solid var(--line-2); border-radius:0;
  font-family:var(--mono); font-size:var(--t-label);
  letter-spacing:var(--ls-label); text-transform:uppercase;
  color:var(--muted); text-decoration:none;
}
a.fbi-pill{ min-height:32px; }
a.fbi-pill:hover{ color:var(--ink); border-color:var(--accent-line); }

/* --- STAT STRIP -----------------------------------------------------------
   Three systems today: .strip/.cell/.k/.l (reviews), .vstat/.sl/.sv (home),
   .pcell/.pv/.pl (pricing). Three names for "the big number".

   The 1px gap over a --line background is what draws the hairline grid without
   double borders where cells meet. */
.fbi-stats{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:1px; background:var(--line); border:1px solid var(--line);
}
.fbi-stat{ background:var(--panel); padding:var(--pad-card); }
/* A stat cell is often a link (the Trustpilot cells on /reviews are). It has to
   carry its own tap target and lose the underline when it is. */
a.fbi-stat{ display:block; text-decoration:none; min-height:44px;
  transition:background .14s var(--ease); }
a.fbi-stat:hover{ background:var(--cell); }
.fbi-stat-v{
  font-family:var(--display); font-weight:400;
  font-size:var(--t-figure-sm); line-height:var(--lh-figure);
  letter-spacing:var(--ls-figure); color:var(--ink); margin:0;
}
.fbi-stat-v .fbi-accent{ color:var(--accent); }
.fbi-stat-l{
  font-family:var(--mono); font-weight:500; font-size:var(--t-label);
  line-height:var(--lh-mono); letter-spacing:var(--ls-label);
  text-transform:uppercase; color:var(--muted-2); margin:var(--gap-in-card) 0 0;
}

/* --- SPEC LIST ------------------------------------------------------------
   The numbered row with a dotted leader and a value on the right:
   "01  Instagram account ................ x1". On pricing and affiliate.

   It is a <ul>, because it is a list. The leader is a flexed border-bottom on a
   spacer span rather than a background of dots, so it lands on the text
   baseline at every width. */
.fbi-spec{ list-style:none; margin:0; padding:0; }
.fbi-spec-row{
  display:flex; align-items:baseline; gap:14px;
  padding:14px 0; border-top:1px solid var(--line);
}
.fbi-spec-row:last-child{ border-bottom:1px solid var(--line); }
.fbi-spec-n{
  font-family:var(--mono); font-weight:500; font-size:var(--t-label);
  letter-spacing:var(--ls-label); color:var(--accent); flex:none;
}
.fbi-spec-name{
  font-family:var(--body); font-size:var(--t-lead);
  line-height:var(--lh-body); color:var(--ink);
}
.fbi-spec-lead{ flex:1; border-bottom:1px dotted var(--line-2); transform:translateY(-4px); }
.fbi-spec-v{
  font-family:var(--mono); font-weight:500; font-size:var(--t-label);
  letter-spacing:var(--ls-label); text-transform:uppercase;
  color:var(--muted-2); flex:none;
}

@media (max-width:560px){
  .fbi-spec-lead{ display:none; }
  .fbi-spec-row{ gap:10px; }
}

@media (prefers-reduced-motion:reduce){
  *{ animation-duration:.01ms !important; animation-iteration-count:1 !important;
     transition-duration:.01ms !important; }
}

/* audit 2026-09-03: removes the ~300ms double-tap delay on controls. Scoped to
   controls rather than the page, so pinch-zoom stays available (the viewport
   tag no longer blocks it). */
a,button,input,select,textarea,label,summary{ touch-action:manipulation; }
