/*
 * FinanceProspector — Base / Design Tokens
 * Foundation: v1.0  |  Extended: v2.0
 * --------------------------------------------------------
 * Canonical CSS custom properties sourced from:
 *   - Color System v1.0
 *   - Typography Design System v2.0
 *   - Spacing & Layout System v1.0
 *   - Grid & Responsive System v1.0
 *   - Buttons & Interactive Elements v1.0
 * Do not add layout or component rules to this file.
 */

:root {

    /* ── Brand Colors ─────────────────────────────────── */
    --fp-color-navy:        #173F73;   /* headings, nav, icons, footer */
    --fp-color-green:       #42B649;   /* editorial stars, success, highlights */
    --fp-color-blue:        #2563EB;   /* links, CTAs, focus states */
    --fp-color-white:       #ffffff;

    /* ── Neutral Palette ──────────────────────────────── */
    --fp-color-gray-50:     #F9FAFB;   /* page backgrounds */
    --fp-color-gray-100:    #F3F4F6;   /* alternate sections */
    --fp-color-gray-200:    #E5E7EB;   /* borders */
    --fp-color-gray-300:    #D1D5DB;   /* dividers */
    --fp-color-gray-500:    #6B7280;   /* body copy */
    --fp-color-gray-600:    #4B5563;   /* strong body */
    --fp-color-gray-700:    #374151;   /* high emphasis */

    /* Legacy alias — maintained for header component compatibility */
    --fp-color-divider:     #E5E7EB;   /* = --fp-color-gray-200 */

    /* ── Typography Scale ─────────────────────────────── */
    /* Desktop sizes; reduce ~10% tablet, ~15% mobile */
    --fp-font-display-xl:   56px;      /* Homepage Hero headline */
    --fp-font-display-l:    52px;      /* Landing page heroes */
    --fp-font-h1:           48px;
    --fp-font-h2:           36px;
    --fp-font-h3:           28px;
    --fp-font-h4:           22px;
    --fp-font-body-l:       18px;      /* Hero copy / introductions */
    --fp-font-body-m:       16px;      /* Standard paragraphs */
    --fp-font-body-s:       14px;      /* Supporting text */
    --fp-font-caption:      13px;      /* Metadata */
    --fp-font-label:        16px;      /* Buttons / navigation / filters */

    /* ── Font Weights ─────────────────────────────────── */
    --fp-weight-body:       400;
    --fp-weight-medium:     500;
    --fp-weight-label:      600;       /* Labels / buttons / card titles */
    --fp-weight-heading:    700;

    /* ── Line Heights ─────────────────────────────────── */
    --fp-line-display:      1.10;
    --fp-line-heading:      1.20;
    --fp-line-body:         1.65;

    /* ── Letter Spacing ───────────────────────────────── */
    --fp-tracking-display:  -0.03em;
    --fp-tracking-heading:  -0.02em;
    --fp-tracking-subhead:  -0.01em;
    --fp-tracking-body:     0;
    --fp-tracking-caption:  0.01em;

    /* ── Accessible Category Text Colours ─────────────── */
    /* AA-compliant text variants of the frozen category identity
     * colours above. Use ONLY where a category label appears as
     * normal-size text on a light surface. The identity colours
     * remain correct for icons, accents and tints. */
    /* HERO SYSTEM v1.0 - Category/Collection Hero Standard.
       ONE shared illustration zone for every comparable page-level hero.
       Artwork is fitted INTO the zone (contain), never assigned a
       per-page width, so scale cannot drift from page to page.
       Derived from the approved Buying Guides render: its portrait
       artwork is height-constrained and reproduces 208 x 253.45. */
    --fp-hero-illustration-zone-w: 264px;
    --fp-hero-illustration-zone-h: 254px;

    --fp-category-business-banking-text:   #2563EB;  /* 5.17:1 on white */
    --fp-category-corporate-cards-text:    #0F766E;  /* 5.47:1 */
    --fp-category-business-lending-text:   #15803D;  /* 5.02:1 */
    --fp-category-crypto-text:             #C2410C;  /* 5.18:1 */
    --fp-category-payments-text:           #7C3AED;  /* 5.70:1 */
    --fp-category-investing-text:          #A16207;  /* 4.92:1 */
    --fp-category-business-insurance-text: #B91C1C;  /* 6.47:1 */

    /* ── RESOURCE CENTER BADGE COLOUR SYSTEM v1.0 ─────────
     * Content-type badge colours for FP-C-005 and any future badge surface.
     *
     * THE POOL IS CLOSED. A badge colour may only be one of the SEVEN approved
     * FinanceProspector category colour families declared directly above:
     *   Blue #2563EB · Purple #7C3AED · Red #B91C1C · Green #15803D ·
     *   Orange #C2410C · Yellow #A16207 · Teal #0F766E
     * These aliases introduce NO new hex values. Never hard-code a badge colour
     * and never add an eighth family here.
     *
     * BADGE COLOUR ENCODES THE CONTENT TYPE, NOT THE ARTICLE'S FINANCIAL
     * CATEGORY. A Business Banking guide and a Business Insurance guide are
     * both GUIDE green. The alias points at a category token only because that
     * is where the approved hex lives; the category meaning does not carry over.
     *
     * A MAPPING IS PERMANENT AND SITE-WIDE once assigned. Adding a content type
     * means claiming an unused family here, not recolouring an existing one.
     *
     * RED IS RESERVED. #B91C1C carries financial warning / loss / error meaning
     * across the product, so it is deliberately NOT assigned to a neutral
     * content type. Use it only for a genuinely cautionary badge, and only with
     * explicit approval.
     *
     * ASSIGNED — all three verified AA on white at 11px/600 (see docs):
     *   GUIDE       Green   #15803D  5.02:1
     *   COMPARISON  Blue    #2563EB  5.17:1
     *   PRICING     Purple  #7C3AED  5.70:1
     *
     * UNCLAIMED and available: Orange #C2410C, Yellow #A16207, Teal #0F766E.
     * RESERVED, do not claim casually: Red #B91C1C.
     *
     * The badge renders as coloured text on white with a 1px currentColor
     * border, so one token drives foreground and border together. Every family
     * also clears 3:1 for the border as a non-text UI component. */
    --fp-badge-guide:      var(--fp-category-business-lending-text);  /* Green  #15803D */
    --fp-badge-comparison: var(--fp-category-business-banking-text);  /* Blue   #2563EB */
    --fp-badge-pricing:    var(--fp-category-payments-text);          /* Purple #7C3AED */
    /* v3.57.119 - Best Of article type: core blue (owner brief NEXT-THEME-HEADING-AND-BADGE-BRIEF.md). Guide stays green. */
    --fp-badge-best-of:    var(--fp-color-blue);                      /* Blue   #2563EB */

    /* ── Editorial Score Text ─────────────────────────── */
    /* --fp-color-green (#42B649) is 2.62:1 on white and fails AA
     * as text. This accessible variant is used for the numeric
     * FinanceProspector Score value. The brand green is unchanged. */
    --fp-color-score-text:  #15803D;   /* 5.02:1 on white */

    /* ── Governed hero heading green (approved 2026-09-28) ── */
    /* Dark Green, Palette v1.1 FINAL. 4.14:1 on white - AA for large text.
     * Used ONLY by the four governed hero headings (Business Banking,
     * Accounting & Bookkeeping Software, Buying Guides, Best Financial
     * Products & Services). Independent of --fp-color-score-text, which
     * scores keep. */
    --fp-color-hero-heading: #338E39;

    /* ── FP Star v1.0 empty states (Palette v1.1 pale colours) ── */
    --fp-star-empty-fp:        #D5EFD7;   /* Pale Green - FP Editorial Score */
    --fp-star-empty-community: #CCD5E0;   /* Pale Navy  - community ratings  */

    /* ── Spacing Scale (8px base) ─────────────────────── */
    --fp-space-xxs:         4px;       /* micro-spacing, compact components only */
    --fp-space-xs:          8px;
    --fp-space-s:           16px;
    --fp-space-m:           24px;
    --fp-space-l:           32px;
    --fp-space-xl:          48px;
    --fp-space-xxl:         64px;
    --fp-space-xxxl:        96px;
    --fp-space-hero:        128px;

    /* ── Layout ───────────────────────────────────────── */
    --fp-container-max-width:   1200px;
    --fp-container-reading:     760px;
    --fp-margin-desktop:        32px;
    --fp-margin-tablet:         24px;
    --fp-margin-mobile:         20px;
    --fp-gutter-desktop:        24px;
    --fp-gutter-tablet:         20px;
    --fp-gutter-mobile:         16px;

    /* ── Border Radius ────────────────────────────────── */
    --fp-radius-card:       12px;
    --fp-radius-button:     10px;

    /* ── CTA system — Bible ch. 54.8 ─────────────────────── */
    --fp-color-blue-hover:   #1D4ED8;   /* Primary hover, Text CTA pressed */
    --fp-color-blue-pressed: #1E40AF;   /* Primary pressed */
    --fp-cta-width:          144px;     /* universal box CTA width  */
    --fp-cta-height:         44px;      /* universal box CTA height */
    --fp-cta-icon-gap:       6px;       /* icon-to-label gap, Primary */
    --fp-radius-input:      10px;
    --fp-radius-pill:       999px;

    /* ── Shadows ──────────────────────────────────────── */
    --fp-shadow-0:  none;
    --fp-shadow-1:  0 1px 3px rgba(0, 0, 0, 0.10), 0 1px 2px rgba(0, 0, 0, 0.06);
    --fp-shadow-2:  0 4px 6px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.06);
    --fp-shadow-3:  0 10px 15px rgba(0, 0, 0, 0.10), 0 4px 6px rgba(0, 0, 0, 0.05);

    /* Design-Bible "Level 1 subtle card shadow". Deliberately a
     * SEPARATE token: --fp-shadow-1 above is an existing, different
     * value used by frozen components and must not be redefined. */
    --fp-shadow-card-level-1: 0 1px 2px rgba(23, 63, 115, 0.05);

    /* Pale green surface — FinanceProspector proprietary score row.
     * Brand green at 8% so the row reads as a tint rather than a fill. */
    --fp-color-green-tint:  rgba(66, 182, 73, 0.08);

    /* ── Major homepage section gap ───────────────────── */
    /* Total rendered whitespace between adjacent major homepage
     * sections. This is the SUM of one section's padding-bottom and the
     * next section's padding-top — it is not a value to be applied to
     * both. Sections split it as (gap - 32) bottom + 32 top at 640px and
     * above, and (gap - 24) bottom + 24 top below 640px, following the
     * Explore -> Editor's Picks reference implementation.
     * Applies to Hero -> Explore -> Editor's Picks -> Resource Center. */
    /* Anchored to the approved Header -> Hero distance, which is produced
     * entirely by .fp-hero padding-top (the header contributes 0 padding,
     * border and margin). Those rendered distances are 96 / 64 / 48px, so
     * the major section gaps now match the boundary the design already uses
     * between the header and the hero. */
    --fp-section-gap-mobile:    48px;   /* 24 bottom + 24 top */
    --fp-section-gap-tablet:    64px;   /* 32 bottom + 32 top */
    --fp-section-gap-desktop:   96px;   /* 64 bottom + 32 top */

    /* ── THE GOVERNED MAJOR-SECTION GAP (v3.54.2) ──────────
     *
     * ⚠ THIS SUPERSEDES THE THREE TOKENS ABOVE AS THE SITE-WIDE STANDARD.
     * They are retained because they still document the homepage's former
     * padding-split arithmetic, which the comments in hero.css and
     * resource-center.css refer to. Nothing reads them as a value.
     *
     * ONE number for the vertical distance between two adjacent MAJOR page
     * sections, on every template. It is NOT split between two sections and
     * it is NOT a padding: the section BELOW the boundary owns it as its own
     * margin-top, and the section above contributes nothing. That is the
     * FROZEN v3.40.61 category rhythm rule, now the homepage's rule too.
     *
     * The value is not new and was not chosen here. It is the distance the
     * Business Banking category page already rendered at every major
     * transition - Top Picks -> Use Cases -> Comparisons -> Guides &
     * Resources -> FAQs -> Glossary - measured on staging at 80.00px from
     * 640 up and 64.00px below it. Business Banking is the canonical
     * reference; the homepage now matches it rather than keeping its own
     * 96 / 64 / 48 padding-split system.
     *
     * ⚠ MAJOR SECTION -> MAJOR SECTION ONLY. Never apply it to heading->dek,
     * heading->cards, cards within a grid, paragraphs, table notes, FAQ rows
     * or anything inside a module. Those own their component spacing.
     *
     * ⚠ NOT the header->hero distance and NOT the last-section->footer
     * distance. Both are separate approved boundaries with their own values
     * (.fp-hero padding-top, and the footer's padding-top), and neither is a
     * transition between two major sections. */
    --fp-section-gap:           64px;  /* < 640 — matches .fp-cat-* margin-top */

    /* ── CTA Arrow ────────────────────────────────────── */
    /* Single homepage-wide gap between CTA text and its trailing arrow.
     * Applied as margin-left on the arrow span, with NO whitespace between
     * the text and the span in markup — so the gap is exact everywhere and
     * the arrow can never wrap away from the final word. */
    --fp-cta-arrow-gap:     4px;

    /* ── Focus Ring ───────────────────────────────────── */
    --fp-focus-ring-width:  2px;
    --fp-focus-ring-color:  #2563EB;
    --fp-focus-ring-offset: 2px;

    /* ── Button Tokens ────────────────────────────────── */
    --fp-button-height-sm:  40px;
    --fp-button-height-md:  48px;
    --fp-button-height-lg:  56px;
    --fp-button-radius:     10px;
    --fp-button-padding-x:  24px;
    --fp-button-padding-y:  16px;
    --fp-button-transition: 150ms ease;

}
/* The >=640 value of the governed major-section gap. Declared as its own
   :root override so there is exactly ONE place the standard changes, and both
   the homepage and the category pages pick it up automatically.
   64px below 640, 80px from 640 up - the Business Banking measurements. */
@media (min-width: 640px) {
    :root {
        --fp-section-gap: 80px;
    }
}


/* ── Accessibility Utility ────────────────────────────── */
.screen-reader-text {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}


/* ═══════════════════════════════════════════════════════════
   UNIVERSAL CTA SYSTEM — Bible chapter 54
   Shared by FP-C-003, FP-C-004 and FP-C-005. Geometry is fixed:
   labels never wrap, buttons never resize, font size is never
   reduced to make a label fit. If a label does not fit, the
   label is wrong — not the button.
   ═══════════════════════════════════════════════════════════ */

/*
 * Selectors are `a.fp-cta` (0,1,1) rather than `.fp-cta` (0,1,0). The legacy
 * per-component rules — .fp-pick-card__cta, .fp-category-card__link,
 * .fp-resource-card__cta — are also (0,1,0) and their stylesheets load AFTER
 * base.css, so on source order they were winning and overriding colour, font
 * and display. Primary rendered blue-on-blue as a result.
 */
a.fp-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--fp-cta-icon-gap);          /* 6px */
    /* width/height are pinned with min- and max- as well. A single `height`
       declaration can be defeated by any parent-theme or component rule that
       sets `min-height` — GeneratePress ships several — because min-height
       wins over height regardless of specificity. Pinning all three makes the
       geometry unoverridable by anything short of !important. */
    width: var(--fp-cta-width);           /* 144px */
    min-width: var(--fp-cta-width);
    max-width: var(--fp-cta-width);
    height: var(--fp-cta-height);         /* 44px */
    min-height: var(--fp-cta-height);
    max-height: var(--fp-cta-height);
    flex-shrink: 0;
    padding: 0 var(--fp-space-s);         /* 16px */
    border-radius: var(--fp-radius-button);
    border: 1px solid transparent;        /* both variants — see 54.1 */
    box-sizing: border-box;
    flex: 0 0 auto;
    font-size: var(--fp-font-body-s);     /* 14px */
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    /* ── B2: single transition for the whole box-CTA system ──
       Previously each component defined its own, so equivalent CTAs
       animated differently: Explore ran `text-decoration, color`,
       Read Review ran `text-decoration-color` (a property that never
       changes, so nothing eased), and Read Article had no component
       rule at all and inherited GeneratePress's
       `a, button, input { transition: color .1s, background-color .1s }`.
       Three behaviours for one class. Declared here at (0,1,1) it
       outranks both the (0,1,0) component rules and GP's (0,0,1).
       Lists only the properties that actually change between states —
       never geometry, so a state change can never animate layout. */
    transition: background-color var(--fp-button-transition),
                border-color     var(--fp-button-transition),
                color            var(--fp-button-transition);
}

/* Honour reduced-motion for the whole system (previously only
   .fp-pick-card__cta carried this). */
@media (prefers-reduced-motion: reduce) {
    a.fp-cta { transition: none; }
}

/* ── Primary: external provider destinations ────────────── */
a.fp-cta--primary {
    background-color: var(--fp-color-blue);
    border-color: var(--fp-color-blue);
    color: var(--fp-color-white);
}

a.fp-cta--primary:hover {
    background-color: var(--fp-color-blue-hover);
    border-color: var(--fp-color-blue-hover);
    color: var(--fp-color-white);
}

a.fp-cta--primary:active {
    background-color: var(--fp-color-blue-pressed);
    border-color: var(--fp-color-blue-pressed);
    color: var(--fp-color-white);
}

a.fp-cta--primary:visited { color: var(--fp-color-white); }

/* ── Disabled (v3.56.7; v3.56.12 full colour) ──────────────
 * A CTA whose destination does not exist yet renders as an <a> with NO href
 * (so no URL of any kind, and not focusable) marked aria-disabled="true".
 * v3.56.12: the same solid Core Blue #2563EB and white text as every other
 * primary CTA - the former half opacity made it read as a faded blue. It
 * stays non-functional: no href, pointer-events off (so no hover or active
 * state) and the default cursor. */
a.fp-cta[aria-disabled="true"] {
    pointer-events: none;
    cursor: default;
}

/* ── Secondary: internal actions ────────────────────────── */
a.fp-cta--secondary {
    background-color: var(--fp-color-white);
    border-color: var(--fp-color-blue);
    color: var(--fp-color-blue);
}

/* ── B1: colour is re-asserted on hover/active ───────────
 * GeneratePress emits `a:hover, a:focus, a:active { color: var(--contrast) }`
 * (#222222) from an inline <style> that loads AFTER base.css. That selector
 * is (0,1,1) — the SAME specificity as `a.fp-cta--secondary` — so source
 * order decided it and GP won, turning every Secondary CTA's label dark on
 * hover and active. These rules previously set background-color only, so
 * nothing re-stated the colour. Primary was never affected because its
 * hover/active rules already declare `color`. Stating colour here fixes all
 * 18 Secondary CTAs at (0,2,1) without !important or a specificity hack. */
a.fp-cta--secondary:hover   { background-color: var(--fp-color-gray-50);  color: var(--fp-color-blue); }
a.fp-cta--secondary:active  { background-color: var(--fp-color-gray-100); color: var(--fp-color-blue); }
a.fp-cta--secondary:visited { color: var(--fp-color-blue); }

/* ── Focus: outline only, so it can never shift layout ──── */
a.fp-cta:focus-visible {
    outline: 2px solid var(--fp-color-blue);
    outline-offset: 2px;
    /* ── B3: hold the button's own radius while focused ──────
       The component :focus-visible rules were written when these were
       TEXT links and set border-radius 2px/4px for a tight ring. Applied
       to a boxed CTA they squared the 10px corners for the duration of
       focus. Restating the button radius here at (0,2,1) keeps focus
       purely additive: it adds a ring and changes nothing else. */
    border-radius: var(--fp-radius-button);
}

/* ── Never underline a box CTA — Bible ch. 54.9 ──────────
 * Box CTAs change SURFACE on hover; only text and navigation
 * links underline. Declared on every state so an inherited or
 * global link rule cannot reintroduce it. */
a.fp-cta,
a.fp-cta:hover,
a.fp-cta:focus,
a.fp-cta:focus-visible,
a.fp-cta:active,
a.fp-cta:visited {
    text-decoration: none;
}

/* ── External-link icon: fixed, never animated ──────────── */
.fp-cta__icon {
    font-size: 16px;
    line-height: 1;
    flex: 0 0 auto;
}

/*
 * No transform, scale, translate, geometry, padding or
 * border-width change in ANY state — see Bible 54.9. Hover and
 * pressed alter colour only; focus uses outline + outline-offset.
 */


/* ══════════════════════════════════════════════════════════
 * PAGE-SHELL FOOTER GOVERNANCE  —  site-wide, v3.40.75
 * ══════════════════════════════════════════════════════════
 * ★ THE DESIGN RULE IS 64px. READ THIS BEFORE TOUCHING ANY NUMBER BELOW.
 *
 *   last painted page content -> footer = 64px
 *
 * That is FinanceProspector's natural closing rhythm - the .fp-info
 * padding-bottom the informational family has always shipped - and it is what
 * a finished page is supposed to look like. Measured on the pages no rule has
 * ever touched: About Us 1865 -> 1929, Affiliate Disclosure 1891 -> 1955, and
 * the same 64px at 390. Every current page resolves to it naturally.
 *
 * ⚠ 800px IS A SHORT-PAGE MINIMUM, NOT THE FOOTER-PLACEMENT TARGET. It exists only
 * so a genuinely abnormal future page - an empty stub, a page whose content
 * failed to render - cannot collapse the shell. IT DOES NOT ENGAGE ON ANY
 * CURRENT PAGE and must never be raised to "improve" spacing: raising it is
 * precisely how v3.40.74 manufactured hundreds of pixels of empty page.
 * If a page looks too short, the answer is content, not this number.
 *
 * HOW 800 WAS DERIVED, AND WHY IT SUPERSEDES v3.40.75's 600. Candidates were
 * measured against every short page at every governed width. 800 is the
 * LARGEST value that keeps every insertion under 200px - the line between
 * breathing room and visible filler. It reaches exactly ONE page: the
 * Resources index, +182px at 1440 and +152px at 1280, natural at 1024, 768
 * and 390. 900 would push that to +282, 1000 to +382, and from 1100 it starts
 * moving the Comparisons index too. Nothing engages at true 390 at any
 * candidate, because every short page is already 1900px or more there.
 *
 * ⚠ CONTENT SOLVED THIS, NOT THE FLOOR. The Contributor page was the reason
 * this rule was revisited, and it no longer needs it: the approved author
 * sections took its stage from 800 to 1567 at 1440 and from 1051 to 2267 at
 * 390, so it now clears the minimum naturally at every width. When a page
 * looks too short the first question is what it owes the reader, not what
 * number to raise here.
 *
 * ⚠ NEVER EXPRESS THIS FLOOR IN vh, %, OR ANY VIEWPORT UNIT. v3.40.74 used
 * min-height:100vh and was rejected on sight: the empty band GROWS WITH THE
 * WINDOW - 164px of dead space on Contributor at 1440x900, 564px at 1300px
 * tall, over 400px at 2048. Reducing the percentage does not fix it, because
 * the dependency on viewport height is itself the defect. An absolute floor
 * cannot behave that way.
 *
 * ⚠ THE WHITE BACKGROUND IS LOAD-BEARING, NOT DECORATION. #page is otherwise
 * TRANSPARENT and the white surface is painted by the content stage
 * (.fp-info, .fp-resources-index, .fp-collection, .fp-article). body carries
 * rgb(247,248,249). So the instant the shell is taller than its stage, body's
 * grey shows through as a band immediately above the navy footer - exactly
 * what v3.40.74 shipped: 100px on Contributor, 282px on Resources, measured
 * live, with elementFromPoint returning div#page.site (transparent) over
 * body.wp-singular (grey). Painting #page white removes the grey PAINTER
 * rather than hiding it, so the boundary is white -> navy at 0px even if the
 * floor ever does engage. Do not delete this declaration.
 *
 *   footer start = MAX( 600px safety floor , natural content end + 64px )
 *
 * Long pages stay entirely content-driven. */
#page {
    min-height: 800px;
    background-color: var(--fp-color-white);
}

/* ⚠ THE FRONT PAGE IS A STRUCTURAL EXCEPTION, NOT A PREFERENCE.
 * front-page.php renders .fp-hero, .fp-explore-category, .fp-editors-picks,
 * .fp-resource-center and .fp-why-trust as DIRECT CHILDREN OF <body>,
 * siblings of #page, leaving that wrapper 0px tall with an empty #content
 * inside it - measured, against 1840px on About Us. A floor on an empty
 * wrapper governs nothing; it would simply insert 600px of blank page between
 * the last homepage section and the footer. The homepage needs no floor
 * regardless: its natural footer top is 2887 at 1440.
 *
 * ⚠ DO NOT MOVE THE FLOOR TO body TO "SIMPLIFY" THIS. On every other template
 * body also contains the header and footer, so a floor there pins the
 * footer's BOTTOM to the viewport bottom and lifts its TOP a footer-height
 * above the fold - 383px at 1440x900. That is the opposite of the rule. */
body.home #page {
    min-height: 0;
}

/* ── FP STAR v1.0 RATING ROWS (approved 2026-09-28) ───────────────────────
   One governed construction for every rating on the site (homepage Editorial
   Framework card + Top Picks). The star is the frozen FP Star v1.0 geometry,
   drawn by masking a colour with assets/images/fp-star/fp-star-cell.v1.0.svg
   (one 16 x 15px position, repeated) - no font glyph, no opacity.
     base layer  = every position in the EMPTY colour
     fill layer  = the same positions in the FILLED colour, clipped by
                   clip-path: inset() to the inline --fp-fill share. The share
                   puts a partial star's edge at exactly fraction x the VISIBLE
                   star width (fp_rating_fill_percent). clip-path is geometric,
                   so the edge is not snapped to whole pixels the way a box
                   width is (measured: +/-0.25 pts of a star vs +/-3.9 pts).
   FP Editorial Score: Core Green over Pale Green. Community: Core Navy over
   Pale Navy. The row keeps the old glyph row's box: 16px per position x 15px. */
.fp-stars {
    position: relative;
    display: inline-block;
    height: 15px;
    line-height: 1;
    font-size: 0;
    /* -2px reproduces the old glyph row's position exactly (measured on the
       homepage table: 387.516 / 433.203px, live and build). An empty
       inline-block sits on its bottom edge; the glyph row sat on its text
       baseline, which varied with the OS fallback font. */
    vertical-align: -2px;
}
.fp-stars--n10 { width: 160px; }
.fp-stars--n5  { width: 80px; }
.fp-stars__base,
.fp-stars__fill {
    position: absolute;
    left: 0;
    top: 0;
    height: 15px;
    -webkit-mask: url(../images/fp-star/fp-star-cell.v1.0.svg) 0 0 / 16px 15px repeat-x;
            mask: url(../images/fp-star/fp-star-cell.v1.0.svg) 0 0 / 16px 15px repeat-x;
}
.fp-stars__base,
.fp-stars__fill { width: 100%; }
.fp-stars__fill {
    -webkit-clip-path: inset(0 calc(100% - var(--fp-fill, 0%)) 0 0);
            clip-path: inset(0 calc(100% - var(--fp-fill, 0%)) 0 0);
}
.fp-stars--green .fp-stars__base { background-color: var(--fp-star-empty-fp); }        /* #D5EFD7 */
.fp-stars--green .fp-stars__fill { background-color: var(--fp-color-green); }         /* #42B649 */
.fp-stars--navy  .fp-stars__base { background-color: var(--fp-star-empty-community); } /* #CCD5E0 */
.fp-stars--navy  .fp-stars__fill { background-color: var(--fp-color-navy); }          /* #173F73 */

/* ── CTA arrow (v3.56.0) ────────────────────────────────────
 * The theme's Inter subset has no U+2192, so every "→" in these spans
 * rendered through per-glyph system fallback (SF on macOS, Segoe elsewhere).
 * The arrow is now DRAWN: a mask in currentColor over the glyph's box, so it
 * follows the link's colour and hover states exactly as the glyph did.
 *
 * Geometry is the fallback glyph's, measured in Chromium. Its advance is not
 * one ratio (SF switches optical size: 0.909em at 14px, 0.899em at 16px,
 * 0.881em at 17px; Segoe differs again), so the box is 0.90em, the closest
 * single value: within 0.33px of the glyph at every size in use. Ink spans
 * 0.10-0.80 of the box across and 0.05-0.66em above the baseline.
 * The box runs from the baseline to 0.71em above it, SYMMETRIC ABOUT THE
 * ARROW'S STEM (0.355em): where an arrow is a flex item and gets centred, the
 * stem lands where the centred glyph's stem did. It sits inside the line box
 * of any line-height >= 1, so no line grows. The "→" stays in the markup
 * (text-indented out of view), so the accessible text is unchanged. */
.fp-cta-arrow,
.tp-arrow,
.fp-uc__arrow,
.fp-categories-index__arrow {
    display: inline-block;
    width: 0.9em;
    height: 0.71em;
    vertical-align: 0;
    overflow: hidden;
    text-indent: 200%;
    white-space: nowrap;
    background-color: currentColor;
    -webkit-mask: url(../images/icons/fp-arrow-right.svg) 0 0 / 100% 100% no-repeat;
            mask: url(../images/icons/fp-arrow-right.svg) 0 0 / 100% 100% no-repeat;
}

/* ── HERO TITLE SCALE (v3.56.1, breakpoints v3.56.2) ─────────
 * ONE scale for the four equivalent hero titles: the category title
 * (.fp-category-hero__art-title), the Best Of / Buying Guides H1
 * (.fp-collection__headline) and the All Providers H1 (.fp-aph__title).
 * 40 / 44 / -1.2px wherever it fits; smaller only where a title would
 * otherwise run to three lines (site owner's rule: no hero title longer
 * than two lines anywhere from 360 to 1440px).
 *   < 380px      28 / 30.8 / -0.84px "Bookkeeping Software" needs ~292px;
 *                                   a 360px window with a 17px scrollbar
 *                                   leaves the category title 301px
 *   380-479px    30 / 33 / -0.9px   needs ~313px; 321px+ from 380px even
 *                                   with a 17px scrollbar
 *   1280-1379px  36 / 39.6 / -1.08px the three-up category title area is
 *                                   387-426px there; at 40px it needs ~417px
 * SCROLLBAR ALLOWANCE (v3.56.2). Media queries measure the window INCLUDING
 * a classic scrollbar (15px macOS "always show", 17px Windows); the layout
 * is that much narrower. The 380px and 1380px edges sit 20px above the
 * widths where the next size up first fits without a scrollbar (the 1360px
 * edge of v3.56.1 left Accounting on three lines at 1360-1370px, and 360-371px
 * at 30px, whenever a scrollbar showed).
 * Line height stays 1.10 and tracking -0.03em at every step. The side
 * headings stay below the title: 24px on phones (--fp-hero-side-heading-phone),
 * 36px to 1199, 34px from 1200. Measurements: qa/v3.56.1/ and
 * qa/v3.56.1-h1-wrap-diagnosis/ (every 1px, 360-1440, 0/15/17px scrollbar). */
:root {
    --fp-hero-title-size:  40px;
    --fp-hero-title-line:  44px;
    --fp-hero-title-track: -1.2px;
    --fp-hero-side-heading-phone: 24px;
}
@media (max-width: 479.98px) {
    :root {
        --fp-hero-title-size:  30px;
        --fp-hero-title-line:  33px;
        --fp-hero-title-track: -0.9px;
    }
}
@media (max-width: 379.98px) {
    :root {
        --fp-hero-title-size:  28px;
        --fp-hero-title-line:  30.8px;
        --fp-hero-title-track: -0.84px;
    }
}
@media (min-width: 1280px) and (max-width: 1379.98px) {
    :root {
        --fp-hero-title-size:  36px;
        --fp-hero-title-line:  39.6px;
        --fp-hero-title-track: -1.08px;
    }
}

/* HERO LABEL SCALE (v3.56.4) - the blue uppercase labels in every hero:
 *   Category hero    Card 1 "Best ..." and Card 3 "How We Evaluate ..."
 *   Collection hero  both side-column eyebrows (Buying Guides, Best Financial
 *                    Products & Services, Comparisons)
 *   All Providers    both side-column eyebrows
 * 14 / 600 on the v3.56.2 16.25px line below 1280px, 16 / 600 on an 18px line
 * from 1280px; Core Blue, uppercase, 1.04px tracking, centred in their own
 * card or column. Each component reads these two tokens and keeps only its
 * own spacing. Badges, pills and article eyebrows are NOT hero labels. */
:root {
    --fp-hero-label-size: 14px;
    --fp-hero-label-line: 16.25px;
}
@media (min-width: 1280px) {
    :root {
        --fp-hero-label-size: 16px;
        --fp-hero-label-line: 18px;
    }
}
