/*
Theme Name: FS Scout
Theme URI: https://folliculitisscout.com/
Author: Folliculitis Scout
Description: Ultra-lean theme for the Folliculitis Scout blog. Mobile-first, no page builder, no widgets, no jQuery. Renders cmsmasters shortcode posts and nothing else.
Version: 1.0.0
Requires at least: 6.5
Requires PHP: 8.1
License: Proprietary
Text Domain: fs-scout
*/

/* ============================================================================
   TOKENS - taken from the Next app's globals.css so the two halves of the
   domain look like one site. A reader crossing from /skin-care/ to /products/
   must not notice they changed application.
   ========================================================================= */

:root {
  --fs-navy:        #12395f;   /* headings, the CTA colour the Next app uses   */
  --fs-ink:         #1f2933;   /* body text - Next's --fs-color-text-strong    */
  --fs-body:        #4b5563;   /* secondary text                              */
  --fs-muted:       #6b7280;
  --fs-line:        #e5e7eb;
  --fs-bg:          #ffffff;
  --fs-bg-soft:     #fafafa;
  --fs-accent:      #2f80ed;   /* Next's brand-primary - links, eyebrows      */
  --fs-healing:     #10b981;   /* RESERVED: means "FA Safe" on the Next side.
                                  Do not use it for navigation or CTAs here.  */
  /* THE STICKY HEADER'S HEIGHT, as a token because two different things need it and they must
     never drift apart: .fs-header-inner min-height (56px) + its 1px bottom border, plus 8px so
     content does not sit flush against it. Anything the browser SCROLLS INTO VIEW has to clear
     this or it lands underneath the header. */
  --fs-header-h:    65px;

  --fs-maxw:        720px;     /* measure. Healthline runs ~680-720px.        */
  --fs-maxw-wide:   1100px;
}

/* ============================================================================
   RESET - minimal. No normalize.css, no bootstrap.
   ========================================================================= */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  /* Every in-page anchor stops this far below the viewport top instead of underneath the sticky
     header. Set once here rather than per-element so a future #anchor cannot get it wrong. */
  scroll-padding-top: var(--fs-header-h);
}

body {
  margin: 0;
  background: var(--fs-bg);
  color: var(--fs-ink);
  /* 18px. MEASURED FROM THE LIVE SITE, not chosen - fs_contents/theme/posts.css
     sets `.cmsmasters_text p, p { font-size: 18px !important }` at every width.
     This is the size 380,922 clicks' worth of readers already read this content
     at, and 82% of them are on a phone. Do not drop it back to 16 or 17. */
  font: 400 18px/1.65 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

img, svg, video { max-width: 100%; height: auto; display: block; }
a { color: var(--fs-accent); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 {
  margin: 0 0 .5em;
  color: var(--fs-navy);
  line-height: 1.2;
  letter-spacing: -.02em;
  font-weight: 800;
}
/* THE LIVE SITE'S TYPE SCALE, COPIED EXACTLY. Source: posts.css on
   folliculitisscout.com, which switches at 768px - so this uses the SAME
   breakpoint rather than a clamp(), because a clamp only approximates it and
   cannot be checked line-for-line against the original.

        live mobile / live >=768px
   h1        30 / 45      h3   20 / 26
   h2        23 / 35      h4   19 / 21

   The previous clamps topped out at 41.6 / 28.8 / 21.6 - smaller than live at
   every level, and the gap widened further down the scale. Desktop half is in
   the 768px block at the foot of this file. */
h1 { font-size: 30px; }
h2 { font-size: 23px; }
h3 { font-size: 20px; }
h4 { font-size: 19px; }

/* 16px MINIMUM on anything focusable. Safari on iOS zooms the page when a
   focused input is under 16px and never zooms back. */
input, select, textarea, button { font: inherit; font-size: max(16px, 1rem); }

.fs-wrap { width: 100%; max-width: var(--fs-maxw); margin: 0 auto; padding: 0 16px; }
.fs-wrap--wide { max-width: var(--fs-maxw-wide); }
.fs-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ============================================================================
   HEADER
   ========================================================================= */

/* ============================================================================
   HEADER - matched to the Next site's header, values read from
   fs-app/src/app/styles/header.css and globals.css on 2026-09-19 rather than
   eyeballed from a screenshot.
   ========================================================================= */

.fs-header {
  /* Next's own rule has its colour stops out of order (100% then 95%), which the browser clamps -
     the effect is simply #4CB8E3 fading to white. Written in the correct order here so it renders
     identically without carrying the mistake across. */
  background: linear-gradient(180deg, #4CB8E3 0%, #ffffff 100%);
  box-shadow: 0 2px 10px rgba(23, 52, 83, .03);
  position: sticky; top: 0; z-index: 50;
}

.fs-header-inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: 1.5rem;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;   /* hamburger | logo | links */
  align-items: center;
  gap: 1rem;
}

.fs-header-logo { display: flex; align-items: center; min-width: 0; }
.fs-header-logo img { width: 250px; height: auto; display: block; }

/* THE HAMBURGER IS DESKTOP-HIDDEN, exactly as Next does it - the links sit inline instead. */
.fs-header-menu-btn {
  display: none;
  align-items: center; justify-content: center;
  width: 42px; height: 42px;
  color: #6b7683;
  cursor: pointer;
  list-style: none;                        /* kills the default <details> triangle */
}
.fs-header-menu-btn::-webkit-details-marker { display: none; }

/* The desktop row renders the SAME menu the drawer does, so it arrives as a <ul> from
   wp_nav_menu() rather than bare <a> tags - these rules flatten that list into a row. */
.fs-header-links { justify-self: end; }
.fs-header-links ul {
  display: flex; gap: 22px;
  margin: 0; padding: 0; list-style: none;
}
.fs-header-links li { margin: 0; }
.fs-header-links a { color: var(--fs-navy); font-weight: 600; font-size: .95rem; white-space: nowrap; }
.fs-header-links a:hover { color: var(--fs-accent); text-decoration: none; }

/* THE DRAWER. Only ever visible below 768px; above that the inline links are the navigation. */
.fs-nav { position: relative; }
.fs-nav > ul,
.fs-nav > div > ul { display: none; }

@media (max-width: 767px) {
  .fs-header-inner {
    grid-template-columns: 42px minmax(0, 1fr);      /* hamburger | logo. Links move into the drawer. */
    padding: .625rem .75rem;
    gap: .5rem;
  }
  .fs-header-menu-btn { display: inline-flex; }
  .fs-header-links    { display: none; }
  .fs-header-logo img { width: 180px; max-width: 100%; }

  /* The open drawer. Absolute so it overlays the page instead of pushing the carousel down -
     a menu that reflows the article underneath it is a layout shift on every tap. */
  .fs-nav[open] > ul,
  .fs-nav[open] > div > ul {
    display: block;
    position: absolute; top: calc(100% + .625rem); left: 0;
    min-width: 230px;
    margin: 0; padding: 8px;
    list-style: none;
    background: #fff;
    border: 1px solid var(--fs-line);
    border-radius: 12px;
    box-shadow: 0 12px 28px rgba(23, 52, 83, .12);
    z-index: 60;
  }
  .fs-nav[open] > ul li,
  .fs-nav[open] > div > ul li { margin: 0; }
  .fs-nav[open] a {
    display: block;
    padding: 12px 14px;                    /* 44px tall - 82% of clicks are thumbs */
    color: var(--fs-ink); font-weight: 600;
    border-radius: 8px;
  }
  .fs-nav[open] a:hover { background: var(--fs-bg-soft); text-decoration: none; }
}

.fs-trust {
  background: var(--fs-bg-soft);
  border-bottom: 1px solid var(--fs-line);
  font-size: .8rem; color: var(--fs-body);
}
.fs-trust-inner {
  display: flex; gap: 20px; padding: 8px 16px;
  overflow-x: auto; scrollbar-width: none; white-space: nowrap;
}
.fs-trust-inner::-webkit-scrollbar { display: none; }
.fs-trust b { color: var(--fs-ink); font-weight: 700; }

/* ============================================================================
   SEARCH - posts and pages only, enforced in functions.php
   ========================================================================= */

.fs-search { display: flex; gap: 8px; margin: 0; }
.fs-search input[type="search"] {
  flex: 1; min-width: 0; padding: 11px 14px;
  border: 1px solid var(--fs-line); border-radius: 999px; background: #fff;
}
.fs-search button {
  padding: 11px 18px; border: 0; border-radius: 999px;
  background: var(--fs-navy); color: #fff; font-weight: 700; cursor: pointer;
}

/* ============================================================================
   HERO + CARDS - the Healthline list pattern: eyebrow, headline, dek,
   thumbnail LEFT on rows.
   ========================================================================= */

.fs-eyebrow {
  display: inline-block; margin-bottom: 6px;
  color: var(--fs-accent); font-size: .78rem; font-weight: 800;
  letter-spacing: .04em; text-transform: uppercase;
}

.fs-hero { margin: 24px 0 8px; }
.fs-hero img { width: 100%; border-radius: 14px; aspect-ratio: 16/9; object-fit: cover; }
.fs-hero h1 { margin: 14px 0 8px; }
.fs-hero p { margin: 0; color: var(--fs-body); }

.fs-section-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; margin: 32px 0 12px;
}
.fs-section-head h2 { margin: 0; }
.fs-section-head a { font-size: .9rem; font-weight: 700; }

.fs-list { list-style: none; margin: 0; padding: 0; }
.fs-list li { border-top: 1px solid var(--fs-line); }
.fs-list li:first-child { border-top: 0; }

.fs-card {
  display: grid;
  grid-template-columns: 96px 1fr;      /* thumb LEFT, Healthline's row shape */
  gap: 14px; align-items: start;
  padding: 16px 0;
}
.fs-card img { width: 96px; height: 72px; border-radius: 8px; object-fit: cover; }
.fs-card-noimg { width: 96px; height: 72px; border-radius: 8px; background: var(--fs-bg-soft); }
.fs-card h3 { margin: 0; font-size: 22px; line-height: 1.35; font-weight: 700; }
.fs-card h3 a { color: var(--fs-ink); }
.fs-card h3 a:hover { color: var(--fs-accent); text-decoration: none; }
.fs-card-meta { margin-top: 6px; font-size: .82rem; color: var(--fs-muted); }

/* ============================================================================
   SINGLE POST
   ========================================================================= */

.fs-post-head { margin: 24px 0 18px; }
.fs-post-head h1 { margin: 6px 0 10px; }
.fs-post-meta { font-size: .86rem; color: var(--fs-muted); }
.fs-post-feature { margin: 0 0 22px; }
.fs-post-feature img { width: 100%; border-radius: 14px; }

.fs-content { font-size: 18px; }   /* live: .cmsmasters_text p { 18px !important } */
.fs-content > * + * { margin-top: 1.1em; }
.fs-content h2 { margin-top: 1.8em; }
.fs-content h3 { margin-top: 1.5em; }
.fs-content ul, .fs-content ol { padding-left: 1.3em; }
.fs-content li + li { margin-top: .4em; }
.fs-content img { border-radius: 10px; }
.fs-content blockquote {
  margin: 1.4em 0; padding: .2em 0 .2em 1.1em;
  border-left: 3px solid var(--fs-healing); color: var(--fs-body); font-style: italic;
}
.fs-content table { width: 100%; border-collapse: collapse; font-size: .95rem; }
.fs-content th, .fs-content td { padding: 10px 12px; border: 1px solid var(--fs-line); text-align: left; }
.fs-content th { background: var(--fs-bg-soft); font-weight: 700; }

/* ---------------------------------------------------------------------------
   CMSMASTERS SHORTCODE LAYOUT.

   MEASURED 2026-09-19 across all 58 published posts - the entire vocabulary is
   fourteen shortcodes, and eight of them are structural:

     column 1,681 | text 1,507 | row 1,334 | divider 959 | heading 869
     js 491 | image 486 | button 344 | toggles 58 | css 49 | tabs 19 | td 24

   The PLUGIN renders these, so they survive a theme change - but the old parent
   theme (cosmetista) carried five CSS files styling them and we do not inherit
   that. functions.php pulls the plugin's own stylesheet; the rules below are the
   safety net that keeps a post READABLE even if that file ever moves.

   DO NOT DELETE THIS BLOCK while any post still contains a [cmsmasters_ tag.
   ------------------------------------------------------------------------ */

.fs-content .cmsmasters_row { margin: 0 0 1.2em; }
.fs-content .cmsmasters_row_inner,
.fs-content .cmsmasters_column { width: 100% !important; float: none !important; margin: 0 0 1em; }
.fs-content .cmsmasters_text > *:first-child { margin-top: 0; }
.fs-content .cmsmasters_divider { border: 0; border-top: 1px solid var(--fs-line); margin: 1.6em 0; }
/* zero-height divider = spacer only; keeps the same rhythm. See FS-DIVIDER-SPACING-2026-09-21.md */
.fs-content div.cl[id^="cmsmasters_divider_"] { margin: 1.6em 0; }
.fs-content .cmsmasters_image img { width: 100%; height: auto; border-radius: 10px; }
.fs-content .cmsmasters_button {
  display: inline-block; padding: 12px 22px; border-radius: 999px;
  background: var(--fs-navy); color: #fff !important; font-weight: 700; text-decoration: none;
}
.fs-content .cmsmasters_button:hover { background: var(--fs-accent); }

/* Product-name links. Same hover the cards and the carousel already use. */
.fs-content h2 a:hover,
.fs-content h3 a:hover,
.fs-content h4 a:hover { color: var(--fs-accent); text-decoration: none; }

.fs-content .cmsmasters_toggle { border-top: 1px solid var(--fs-line); padding: 12px 0; }

/* Posts embed their own CSS and JS - 49 [cmsmasters_css] and 491 [cmsmasters_js]
   across the set. Keep them contained so a post cannot blow out the page. */
.fs-content { overflow-wrap: anywhere; }
.fs-content iframe { max-width: 100%; }

/* ============================================================================
   COMMENTS - existing ones render, the form does not (functions.php)
   ========================================================================= */

.fs-comments { margin: 40px 0 0; padding-top: 24px; border-top: 1px solid var(--fs-line); }
.fs-comments h2 { font-size: 1.2rem; }
.fs-comments ol { list-style: none; margin: 0; padding: 0; }
.fs-comments li { padding: 14px 0; border-top: 1px solid var(--fs-line); }
.fs-comments li:first-child { border-top: 0; }
.fs-comment-author { font-weight: 700; color: var(--fs-ink); font-size: .95rem; }
.fs-comment-date { color: var(--fs-muted); font-size: .8rem; }

/* ============================================================================
   ADS - renders nothing at all when unconfigured
   ========================================================================= */

.fs-ad { margin: 28px 0; text-align: center; }
.fs-ad:empty { display: none; }

/* ============================================================================
   PAGINATION / FOOTER
   ========================================================================= */

.fs-pagination { display: flex; gap: 8px; flex-wrap: wrap; margin: 32px 0; }
.fs-pagination .page-numbers {
  padding: 9px 14px; border: 1px solid var(--fs-line); border-radius: 8px;
  color: var(--fs-ink); font-weight: 600; font-size: .92rem;
}
.fs-pagination .page-numbers.current { background: var(--fs-navy); border-color: var(--fs-navy); color: #fff; }

.fs-footer { margin-top: 56px; padding: 32px 0; background: var(--fs-bg-soft); border-top: 1px solid var(--fs-line); }
.fs-footer-cols { display: grid; gap: 24px; }
.fs-footer h4 { margin: 0 0 10px; font-size: .95rem; color: var(--fs-ink); }
.fs-footer ul { list-style: none; margin: 0; padding: 0; }
.fs-footer li + li { margin-top: 8px; }
.fs-footer a { color: var(--fs-body); font-size: .92rem; }
.fs-footer-note { margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--fs-line); font-size: .82rem; color: var(--fs-muted); }

/* ============================================================================
   FEATURED CAROUSEL - native scroll-snap, zero JavaScript.
   Healthline's technique, verified against their live homepage 2026-09-19.
   ========================================================================= */

.fs-feat { margin: 22px 0 6px; scroll-margin-top: var(--fs-header-h); }

/* THE TRACK. overflow-x + scroll-snap is the entire mechanism: the browser does the paging, the
   momentum and the snapping. A JS carousel reimplements all three, badly, and ships ~20KB to do it. */
.fs-feat-track {
  display: flex;
  gap: 12px;                               /* the gutter that makes the peek read as deliberate */

  /* NO mask-image HERE. IT WAS TRIED AND REMOVED 2026-09-19 - DO NOT ADD IT BACK.
     A fade on the track masks EVERYTHING inside it, body copy included: headlines and excerpts
     dissolved mid-word ("...Best Shampoos for" fading out was the actual symptom). Text must never
     be faded to hint at a scroll.
     It was also dishonest - a constant fade on the right of the LAST slide advertises content that
     is not there. The peek below has neither problem: it shows a sliver only where a slide
     actually exists, so on the last slide nothing peeks right and the previous one peeks LEFT,
     which is the correct signal. The cue corrects itself with no scroll tracking at all. */
  overflow-x: auto;
  overscroll-behavior-x: contain;          /* a swipe past the last slide must not navigate back */
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;                 /* makes the dot links glide instead of jump */
  scrollbar-width: none;                   /* Firefox */
  border-radius: 14px;
}
.fs-feat-track::-webkit-scrollbar { display: none; }

/* focus-visible, not focus: role="region" + tabindex="0" makes this keyboard-scrollable, and
   without the -visible qualifier every mouse click would draw a ring around the whole carousel. */
.fs-feat-track:focus-visible { outline: 3px solid var(--fs-accent); outline-offset: 3px; }

.fs-feat-slide {
  /* 88%, NOT 100%. The 12% left over lets the NEXT slide's image show at the right edge, which is
     the whole affordance: a reader sees a sliver of a different photo and knows it scrolls. A
     grey gradient over empty space says "something is cut off"; a real image says "another
     article is here". Healthline does the same thing - their tiles always peek. */
  flex: 0 0 88%;
  scroll-snap-align: start;
  scroll-snap-stop: always;                /* a fast flick advances ONE slide, never skips two */
  min-width: 0;

  /* WHY THE PAGE USED TO JUMP WHEN YOU TAPPED A DOT.
     A dot is <a href="#fs-slide-2">. Following it does NOT merely scroll the track sideways - the
     browser scrolls every scrollable ancestor, the PAGE included, until that element's top edge
     meets the viewport top. The viewport top is behind a 57px sticky header, so the carousel
     lurched upward and the image ended up half-hidden under the navy bar.
     scroll-margin-top moves the line the browser aims for down to just below the header. The
     horizontal snap is unaffected; only the vertical resting point changes. */
  scroll-margin-top: var(--fs-header-h);
}

/* aspect-ratio reserves the box BEFORE the image arrives. Without it the text below jumps down as
   each image loads, which is Cumulative Layout Shift and a Core Web Vitals failure on the page
   carrying 47% of the site's impressions. */
.fs-feat-img { display: block; aspect-ratio: 3 / 2; background: var(--fs-bg-soft); border-radius: 14px; overflow: hidden; }
.fs-feat-img img { width: 100%; height: 100%; object-fit: cover; display: block; }

.fs-feat-body { padding: 14px 2px 0; }
.fs-feat-body h2 { margin: 6px 0 .35em; font-size: 26px; line-height: 1.22; }
.fs-feat-body h2 a { color: var(--fs-navy); }
.fs-feat-body h2 a:hover { color: var(--fs-accent); text-decoration: none; }
.fs-feat-body p { margin: 0; color: var(--fs-body); font-size: 17px; line-height: 1.55; }

/* THE DOTS. Anchors to #fs-slide-N - an href moves the track with no script at all.
   44px hit area: the visible dot is 10px, which is far below the minimum touch target, and 82% of
   this site's clicks are thumbs. */
.fs-feat-nav { display: flex; justify-content: center; gap: 4px; margin-top: 14px; }
.fs-feat-nav a {
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border-radius: 50%;
}
.fs-feat-nav a span {
  display: block; width: 10px; height: 10px; border-radius: 50%;
  background: var(--fs-line); transition: background .18s ease, transform .18s ease;
}
.fs-feat-nav a:hover span,
.fs-feat-nav a:focus-visible span { background: var(--fs-accent); transform: scale(1.25); }

/* :target styles the dot for the slide the reader actually jumped to. Pure CSS state, no script. */
.fs-feat-slide:target { scroll-snap-align: start; }

/* Respect the OS setting. Someone with vestibular sensitivity gets an instant jump instead of a
   slide - the carousel still works, it just stops moving. */
@media (prefers-reduced-motion: reduce) {
  .fs-feat-track { scroll-behavior: auto; }
  .fs-feat-nav a span { transition: none; }
}

/* ============================================================================
   DESKTOP. Mobile is the default above - this is the variation, not the base.
   ========================================================================= */

@media (min-width: 768px) {
  /* Headings only - body copy stays 18px at every width, exactly as live does. */
  h1 { font-size: 45px; }
  h2 { font-size: 35px; }
  h3 { font-size: 26px; }
  h4 { font-size: 21px; }
  .fs-card { grid-template-columns: 160px 1fr; gap: 18px; }
  .fs-card img, .fs-card-noimg { width: 160px; height: 106px; }
  .fs-card h3 { font-size: 26px; }
  /* LESS PEEK ON DESKTOP. There is no swipe here - the dots are the control - so the sliver is a
     hint that more exists, not an invitation to drag. Too much of it just looks broken on a wide
     screen. */
  .fs-feat-slide { flex: 0 0 94%; }
  .fs-feat-img { aspect-ratio: 21 / 9; }   /* wider crop once there is room for it */
  .fs-feat-body h2 { font-size: 34px; }
  .fs-feat-body p  { font-size: 18px; }
  .fs-footer-cols { grid-template-columns: 2fr 1fr 1fr; }
  .fs-content .cmsmasters_column.one_half { width: calc(50% - 12px) !important; float: left !important; margin-right: 24px; }
  .fs-content .cmsmasters_column.one_half:last-child { margin-right: 0; }
  /* Contain those floats. Without this the row has no height and the NEXT row is painted over
     this one - measured 2026-09-21, the button sat at y=444-491 and the following row began at
     y=450, so 12 of 29 affiliate links were intercepted. Rationale: fs-app/FS-SESSION-LOG. */
  .fs-content .cmsmasters_row_margin::after { content: ""; display: table; clear: both; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ------------------------------------------------------- adsense slots ---- */
/* Reserves slot space so filling an ad does not shift the page. Rationale and
   measurements: fs-app/ADSENSE-LOADER-AND-CLS-2026-09-20.md */

ins.adsbygoogle {
	display: block;
	min-height: 280px;
}

@media ( max-width: 480px ) {
	ins.adsbygoogle {
		aspect-ratio: 1;
		min-height: 0;
	}
}


/* Ads disabled for this request: collapse the slots rather than reserve space
   they will never use. See the .md above. */
body.fs-ads-off ins.adsbygoogle {
	display: none !important;
}

/* Theme-placed ad units. Previously unstyled, so the header unit butted against
   the trust strip. */
#ad-container {
	margin: 2rem 0;
}

/* Share row. Replaces the cmsmasters social links; markup from fs-share.php.
   Buttons sit in their own flex row so a wrapped button aligns under the first BUTTON, not the
   label. 44px min tap target - the originals were 22px inline text. See FS-SHARE-2026-09-21.md */
.fs-share { display: flex; align-items: flex-start; gap: 12px; margin: 3.4em 0 2.4em; }
.fs-share__label { flex: none; font-weight: 600; color: var(--fs-body); line-height: 44px; }
.fs-share__btns { display: flex; flex-wrap: wrap; gap: 8px; }
.fs-share__btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 18px; border: 0; border-radius: 999px;
  background: var(--fs-accent); color: #fff; cursor: pointer;
  font: inherit; font-size: .95rem; font-weight: 600; line-height: 1; text-decoration: none;
}
.fs-share__btn:hover, .fs-share__btn:focus-visible { background: var(--fs-navy); color: #fff; text-decoration: none; }

/* Sources panel. Native <details>, collapsed; markup from fs-sources.php.
   44px summary tap target. See FS-SOURCES-2026-09-21.md */
.fs-content .fs-sources { margin: 2.4em 0; border-top: 1px solid var(--fs-line); border-bottom: 1px solid var(--fs-line); }
.fs-content .fs-sources__summary {
  display: flex; align-items: center; gap: 8px; min-height: 44px;
  cursor: pointer; list-style: none;
  font-weight: 600; color: var(--fs-navy); font-size: 1rem;
}
.fs-content .fs-sources__summary::-webkit-details-marker { display: none; }
.fs-content .fs-sources__summary::before { content: "+"; font-weight: 700; color: var(--fs-accent); width: 1em; }
.fs-content .fs-sources[open] .fs-sources__summary::before { content: "\2212"; }
.fs-content .fs-sources__summary:hover { color: var(--fs-accent); }
.fs-content .fs-sources__body { padding-bottom: 1.2em; font-size: .95rem; color: var(--fs-body); }
.fs-content .fs-sources__body ul { margin: 0; padding-left: 1.2em; }
.fs-content .fs-sources__body li { margin: 0 0 .7em; line-height: 1.55; }

/* Desktop only: 18px in a 688px column is 77 characters per line, past the 45-75 desktop measure.
   20px lands at ~70. Mobile stays 18px / 38 chars. See FS-DIVIDER-SPACING-2026-09-21.md sibling
   note in REPO-TASKLIST P4. Inherited by every child, so no per-element rules needed. */
@media (min-width: 1024px) {
  .fs-content { font-size: 20px; }
}

/* Table of contents. Native <details>, collapsed; markup from fs-toc.php.
   Editorial, not a boxed widget: accent rule + eyebrow label, matching .fs-eyebrow and .fs-card.
   See FS-TOC-2026-09-21.md */
.fs-content .fs-toc { margin: 2.6em 0; padding-left: 18px; border-left: 3px solid var(--fs-accent); }

.fs-content .fs-toc__title {
  display: flex; align-items: center; gap: 10px; min-height: 44px;
  cursor: pointer; list-style: none;
  color: var(--fs-accent); font-size: .78em; font-weight: 800;
  letter-spacing: .04em; text-transform: uppercase;
}
.fs-content .fs-toc__title::-webkit-details-marker { display: none; }
.fs-content .fs-toc__title::after {
  content: ""; width: 7px; height: 7px; margin-top: -3px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); transition: transform .15s ease;
}
.fs-content .fs-toc[open] .fs-toc__title::after { transform: rotate(-135deg); margin-top: 2px; }
.fs-content .fs-toc__title:hover { color: var(--fs-navy); }

.fs-content .fs-toc ul { margin: 0 0 .5em; padding: 0; list-style: none; }
.fs-content .fs-toc ul ul { margin: .4em 0 .6em; padding-left: 14px; border-left: 1px solid var(--fs-line); }
.fs-content .fs-toc li { margin: 0; line-height: 1.45; }
.fs-content .fs-toc a {
  display: block; padding: 10px 0;        /* 18px line box was the whole tap target before */
  color: var(--fs-ink); font-size: .9em;  /* em: follows the body bump. rem did not. */
  text-decoration: none;
}
.fs-content .fs-toc a:hover { color: var(--fs-accent); text-decoration: underline; }

@media (prefers-reduced-motion: reduce) {
  .fs-content .fs-toc__title::after { transition: none; }
}

/* Back to top. Appears only after the reader has scrolled past the first screen.
   Sentinel + IntersectionObserver, no scroll listener. See FS-TOC-2026-09-21.md */
.fs-top-sentinel { position: absolute; top: 0; left: 0; width: 1px; height: 70vh; pointer-events: none; visibility: hidden; }
.fs-top {
  position: fixed; right: 16px; bottom: 16px; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  width: 48px; height: 48px; border: 0; border-radius: 50%;
  background: var(--fs-navy); color: #fff; cursor: pointer;
  box-shadow: 0 4px 14px rgba(18, 57, 95, .28);
  opacity: 0; transform: translateY(8px); pointer-events: none;
  transition: opacity .18s ease, transform .18s ease, background .18s ease;
}
.fs-top.is-on { opacity: 1; transform: none; pointer-events: auto; }
.fs-top:hover, .fs-top:focus-visible { background: var(--fs-accent); }
.fs-top svg { width: 20px; height: 20px; display: block; }
@supports (padding: max(0px)) {
  .fs-top { bottom: max(16px, env(safe-area-inset-bottom)); }
}
@media (prefers-reduced-motion: reduce) {
  .fs-top { transition: none; }
}
