/* ============================================================================
 * Heliomath COMPONENTS — reusable, class-based UI built on the tokens.
 *
 * The components layer. Unlike base.css (bare-element defaults, global by
 * nature), everything here is a CLASS selector, so it only styles elements that
 * opt in by using the class. Load order: tokens -> base -> components -> utilities.
 *
 * TOKENS: colour / type / structure come from heliomath_tokens.css via var().
 * No hard-coded hex or raw px type sizes.
 *
 * NAMING: BEM. Buttons are `.btn` (no prefix — this is THE button) + `--variant`
 * modifiers, mirroring the .mp-ld-*__el / --modifier vocabulary elsewhere.
 *
 * ⚠ `.btn` COLLIDES WITH BOOTSTRAP 4 (loaded globally in external_base.html,
 * which also owns `.btn`). Until Heliomath sheds that ported Bootstrap/Grokkoli
 * stack, this file may load on pages that still carry legacy `.btn` buttons — so
 * every bare `.btn` selector below is GUARDED with
 * `:not(.btn-grokkoli-primary):not(.filter)` to skip them (those are the legacy
 * button classes in play). Our own buttons always carry a `.btn--variant`, so
 * they're unaffected. When the ported stack is retired, delete the guards for a
 * pristine `.btn` base. (`--btn-ring` lives on the variants, not the guarded
 * base, so the guard's raised specificity can't override the per-variant ring.)
 *
 * This file starts with BUTTONS; further components (logo below; cards, inputs…)
 * append under their own banners.
 * ========================================================================== */


/* ============================================================================
 * COLOUR ROLES  —  accent (primary) + flare (secondary), as utilities
 *
 * Two accent roles, meant to be used LIBERALLY on headers, marks, chips, etc.
 * (and as the button variants below):
 *   accent  ->  --accent-primary (cornflower) — the primary accent
 *   flare   ->  the SECONDARY accent (--flare; coral/peach today). The name is the
 *               ROLE, not the hue, so it survives a future swap (e.g. green/cyan).
 *
 *   .text-*   colours FOREGROUND (text). Use flare on LARGE text only on light
 *             surfaces — coral fails WCAG at body sizes.
 *   .fill-*   paints a BACKGROUND *and* its contrasting label together — never a
 *             bare background (that is how you get an unreadable label).
 *
 * SURFACE ADAPTATION (defined ONCE, here): the flare COLOUR (and its focus ring)
 * brightens to peach on dark bands — .text-flare / .fill-flare / .btn--flare read
 * the --flare-* context tokens, so they adapt with NO per-component dark override.
 * The flare LABEL token (--flare-label) adapts too, but only .fill-flare uses it:
 * the BUTTONS carry a fixed dark (midnight) label, which clears contrast on coral,
 * peach AND cornflower, so it needs no surface flip. Accent is surface-stable.
 * ========================================================================== */
:root {
    --flare-paint:        var(--flare);              /* the flare colour, in context */
    --flare-paint-hover:  var(--flare-hover);
    --flare-paint-active: var(--flare-active);
    --flare-label:        var(--text-on-dark-fill);  /* label on a flare fill: white on coral */
    --flare-ring:         var(--focus-ring-flare);
}
/* Dark bands re-point the flare context (incl. the legacy .dark-blue-background
 * band the comparison table still uses). */
.mp-section--dark,
.mp-section--dark-alt,
.dark-blue-background {
    --flare-paint:        var(--flare-on-dark);      /* peach */
    --flare-paint-hover:  var(--flare-on-dark-hover);
    --flare-paint-active: var(--flare-on-dark-active);
    --flare-label:        var(--text-on-light-fill); /* night — white fails on peach */
    --flare-ring:         var(--focus-ring-flare-on-dark);
}

/* Foreground (text): headers, ✓/✗ marks, inline emphasis. */
.text-accent { color: var(--accent-primary); }
.text-flare  { color: var(--flare-paint); }
/* The link blue (azure) as a foreground utility for NON-link emphasis text. Same
 * family as .text-accent but darker/more saturated, so it clears WCAG at BODY size
 * where accent (cornflower) doesn't — reach for this on small/body-size coloured
 * emphasis (e.g. the bold inline labels in a dense list). Always underlined <a>
 * links get --link from base.css already; this is for text that isn't a link. */
.text-link   { color: var(--link); }

/* Fill: a painted element that carries its own contrasting label. */
.fill-accent { background-color: var(--accent-primary); color: var(--text-on-dark-fill); }
.fill-flare  { background-color: var(--flare-paint);    color: var(--flare-label); }


/* ============================================================================
 * BUTTONS  —  .btn (structural base) + a --variant skin.
 *
 *   .btn           structural base — layout + the shared dark (midnight) label
 *   .btn--accent   + cornflower fill — any surface
 *   .btn--flare    + secondary-accent fill (coral on light, peach on dark, via the
 *                  --flare-* context tokens above)
 *
 * Each variant supplies only its FILL, hover/active shades and matching focus ring;
 * the base owns the label. Variant colours reuse the accent / flare roles above.
 * Works on <button> and <a>. Pill by default.
 * ========================================================================== */

/* Generic .btn box geometry — ported from base.css (which Heliomath no longer loads).
 * MUST sit BEFORE the guarded base + the .btn--* variants below: it is a single-class
 * selector like them, so on equal specificity SOURCE ORDER decides — the variants'
 * fills (background-color: var(--flare-paint) etc.) have to come later to win. (base.css
 * loaded before this file, giving that order for free; here we recreate it.) Heliomath's
 * own buttons layer the guarded base + a variant on top; this bare rule mainly gives the
 * LEGACY .btn-grokkoli-* buttons (e.g. the About contact submit) their box. Its #212529
 * colour is always overridden downstream, so it never paints. */
.btn {
    display: inline-block;
    font-weight: 400;
    color: #212529;
    text-align: center;
    vertical-align: middle;
    -webkit-user-select: none;
    user-select: none;
    background-color: transparent;
    border: 1px solid transparent;
    padding: 0.375rem 0.75rem;
    font-size: 1rem;
    line-height: 1.5;
    border-radius: 0.25rem;
    transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.btn:not(:disabled):not(.disabled) { cursor: pointer; }

/* --- Structural base (layout + the shared dark label; FILL + ring come from the
 *     variant) --- */
.btn:not(.btn-grokkoli-primary):not(.filter) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5em;                        /* room for an icon beside the label */
    margin: 0;
    padding: 0.85rem 1.7em;             /* 15px / 28px at the 18px label floor; scales with the label */
    border: 1px solid transparent;     /* keeps fills and outline variants the same box size */
    border-radius: var(--radius-pill);
    /* Fluid label from the token (--type-control-size): floor 18px, cap 24px. Our
     * button fills all take a dark midnight label (set here, so a variant needn't
     * repeat it); the token holds the contrast note — cornflower is the tightest. */
    font-family: var(--font-family-base);
    font-size: var(--type-control-size);
    font-weight: var(--font-weight-bold);
    color: var(--text-primary);        /* dark (midnight) label — shared by every variant */
    line-height: 1.2;
    text-align: center;
    text-decoration: none;             /* for <a class="btn"> */
    white-space: nowrap;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    transition: background-color 0.18s ease, color 0.18s ease,
                box-shadow 0.18s ease, transform 0.18s ease;
}
.btn:not(.btn-grokkoli-primary):not(.filter):hover {
    opacity: 1;
}

/* Pressed: a subtle downward nudge PLUS the variant's own colour ring — a solid
 * 2px OUTLINE in the fill colour (--btn-ring-color) held 3px off the edge
 * (outline-offset), so it reads as a detached ring that follows the pill contour,
 * NOT the old translucent box-shadow that hugged the button. Full opacity, exact
 * fill colour — matches the style-guide button press. Unlike the focus ring below
 * (keyboard-only), this fires on ANY press — including the hero CTA, which is a
 * non-focusable <div class="btn"> that never gets :focus but does get :active. */
.btn:not(.btn-grokkoli-primary):not(.filter):active {
    transform: translateY(1px);
    outline: 2px solid var(--btn-ring-color);
    outline-offset: 3px;
    box-shadow: none;    /* kill base.css a:focus azure link ring on <a class="btn"> */
}

/* Focus ring — the same detached fill-colour outline, shown on ANY focus INCLUDING
 * a mouse click/press: deliberately NOT gated to :focus-visible, so the ring appears
 * on press and PERSISTS until blur — the style-guide button behaviour. Needs a
 * focusable element: a <button> / <a class="btn"> gets it; a non-focusable
 * <div class="btn"> can only ever show the transient :active ring above. Floor-safe
 * (plain :focus, no :focus-visible dependency). */
.btn:not(.btn-grokkoli-primary):not(.filter):focus {
    outline: 2px solid var(--btn-ring-color);
    outline-offset: 3px;
    box-shadow: none;    /* kill base.css a:focus azure link ring on <a class="btn"> */
}

/* Disabled: dim, no press. (For <a>, use aria-disabled and stop navigation in
 * JS — a link can't be natively disabled.) */
.btn:not(.btn-grokkoli-primary):not(.filter):disabled,
.btn:not(.btn-grokkoli-primary):not(.filter)[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
}

/* --- Variant: accent (cornflower) — any surface ------------------------- */
.btn--accent {
    --btn-ring: var(--focus-ring);              /* cornflower ring (soft box-shadow, legacy) */
    --btn-ring-color: var(--accent-primary);    /* detached outline ring — exact fill colour, full opacity */
    background-color: var(--accent-primary);
}
.btn--accent:hover  { background-color: var(--accent-primary-hover); }
.btn--accent:active { background-color: var(--accent-primary-active); }

.btn--accent-on-dark {
    --btn-ring: var(--focus-ring);              /* cornflower ring (soft box-shadow, legacy) */
    --btn-ring-color: var(--accent-primary-on-dark);    /* detached outline ring — exact fill colour, full opacity */
    background-color: var(--accent-primary-on-dark);
}
.btn--accent-on-dark:hover  { background-color: var(--accent-primary-on-dark-hover); }
.btn--accent-on-dark:active { background-color: var(--accent-primary-on-dark-active); }


/* --- Variant: flare (secondary accent) — fill adapts to its surface ------ *
 * coral fill on light, peach fill on dark, plus the matching focus ring — all via
 * the --flare-* context tokens. (The label is the base .btn's midnight, on both.) */
.btn--flare {
    --btn-ring: var(--flare-ring);
    --btn-ring-color: var(--flare-paint);       /* detached outline ring — coral on light / peach on dark, full opacity */
    background-color: var(--flare-paint);
}
.btn--flare:hover  { background-color: var(--flare-paint-hover); }
.btn--flare:active { background-color: var(--flare-paint-active); }

/* No underline on button CTAs. base.css underlines every <a>; when an <a> WRAPS a
 * .btn (<a class="main-cta"><div class="btn">…), that line is painted across the button
 * label — and a descendant's text-decoration:none CANNOT remove a line drawn by an
 * ancestor, so it must be killed on the <a> itself. Global — every .main-cta CTA, on any
 * page. (An <a class="btn"> needs no help: there the decoration originates on the link,
 * so the .btn base already clears it.) */
a.main-cta { text-decoration: none; }
a .btn { text-decoration: none; }  /* also clear it on a directly-inline .btn child */

/* .main-cta is an <a> that merely WRAPS a .btn (the hero + pricing "See Learning
 * Plans" CTAs). base.css gives every <a> a focus/press ring, so it appears *in
 * addition* to the button's own ring — a confusing double ring around the CTA.
 * Suppress the link's ring (and neutralise base.css's focus pill padding / negative
 * margins so nothing shifts), and instead surface the BUTTON's ring while the link
 * is focused/pressed. The inner <div class="btn"> can't be focused itself, so
 * forwarding the ring here is what preserves a visible keyboard-focus indicator
 * (WCAG 2.4.7) — and it matches the persist-until-blur behaviour of a standalone
 * button. Falls back to the default ring for any wrapped button without --btn-ring. */
a.main-cta:focus,
a.main-cta:active {
    box-shadow: none;
    outline: none;
    padding-left: 0;
    padding-right: 0;
    margin-left: 0;
    margin-right: 0;
}
a.main-cta:focus .btn,
a.main-cta:active .btn {
    outline: 2px solid var(--btn-ring-color, var(--accent-primary));
    outline-offset: 3px;
}

/* ============================================================================
 * CARD  —  .card (+ modifiers)
 *
 * The generic surface tile for marketing content — testimonial quotes,
 * success-story items, the closing-CTA panel, and so on. An elevated white
 * surface sitting on the light/beige field, separated from it by a hairline
 * border AND a soft shadow: white-on-beige is only ~1.05:1, so a card ALWAYS
 * needs both to read as a distinct surface (see --border-hairline / the elevated
 * shadows in the tokens). Radius comes from --radius-card, so every card in the
 * system rounds the same amount.
 *
 * SHELL ONLY. A card owns its own surface, border, radius, shadow and inset
 * (padding) — and NOTHING about how its contents are arranged. The consumer lays
 * out the inside (flex/grid, gaps, alignment) via its own section-scoped rule,
 * which sits at higher specificity and rides on top of this shell.
 *
 * TUNABLE: --card-padding exposes the inset so a consumer can retune it WITHOUT
 * re-declaring the shell — set it on the element (e.g. the roomier CTA panel).
 *
 *   .card              the shell
 *   .card--interactive adds a hover lift (rise + deeper shadow) for a card that
 *                      is, or wraps, a tappable target. Reduced-motion users keep
 *                      the shadow cue but lose the transform.
 * ========================================================================== */
.card {
    --card-padding: var(--space-lg);
    background-color: var(--surface-elevated);
    border: 1px solid var(--border-warm);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-elevated);
    padding: var(--card-padding);
}

/* Hover lift — only for cards that invite interaction. */
.card--interactive {
    transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.card--interactive:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-elevated-hover);
}
@media (prefers-reduced-motion: reduce) {
    .card--interactive:hover { transform: none; }
}


/* ============================================================================
 * LOGO  —  .logo (+ --on-dark)
 *
 * The Heliomath wordmark — on nearly every screen. Two artwork files
 * (logo-midday.png / logo-midday-on-dark.png, both 500x84) swapped by CSS: the
 * default is the light-surface logo; add --on-dark on a DARK background. As a
 * background image, only the artwork for the MATCHED class is fetched — no double
 * download.
 *
 * Sized by HEIGHT via --logo-height; the width follows from the 500x84 ratio via
 * calc() (floor-safe — sidesteps aspect-ratio, which is above our browser floor).
 * PNG source is 500px wide, so keep the displayed width <=~250px to stay crisp on
 * 2x screens (the 2.5rem default is ~238px — fine).
 *
 * Give it an accessible name in markup (it's a background image, so no alt):
 *   as a link:  <a href="/" class="logo" aria-label="Heliomath"></a>
 *   standalone: <span class="logo" role="img" aria-label="Heliomath"></span>
 *   on dark:    add --on-dark, e.g. class="logo logo--on-dark"
 * ========================================================================== */
.logo {
    --logo-height: 2.25rem;                      /* 36px — override to resize; width follows */
    display: inline-block;
    height: var(--logo-height);
    width: calc(var(--logo-height) * 500 / 84);  /* preserve the 500x84 aspect ratio */
    background: url("../img/logo-midday.e76aee391730.png") center / contain no-repeat;
}
.logo--on-dark {
    background-image: url("../img/logo-midday-on-dark.cab02bc91848.png");
    /* Full opacity — no dimming. (Was 0.9, which made the LD hero wordmark read
     * darker/more muted than the same artwork on the account-access pages, where
     * it's a plain <img> at full strength.) */
}
/* Logo LINKS — every anchor that wraps the wordmark: the LD-hero wordmark (.logo as an <a>),
 * the top-nav wordmark (.navbar-brand, the <a> around the .navbar-logo img), and the bare hero
 * logo anchors on the plans + about pages (.logo-link, an <a> wrapping the wordmark <img>).
 * Suppress base.css's a:focus treatment: the pill ring + its ±0.4em padding/margin (which
 * shifted the logo) + the --radius-pill (which rounded/clipped it). The translucent --link-fill
 * is excluded in heliomath_base (the matching :not() list on the fill rule). A logo isn't a text
 * link — it carries no pill. Only horizontal padding/margin are reset, so each logo's own layout
 * (.logo's margin-bottom, .navbar-brand's vertical padding) stays. */
.logo:focus,
.logo:active,
.navbar-brand:focus,
.navbar-brand:active,
.logo-link:focus,
.logo-link:active {
    outline: none;
    box-shadow: none;
    border-radius: 0;
    padding-left: 0;
    padding-right: 0;
    margin-left: 0;
    margin-right: 0;
}


/* ============================================================================
 * HEADER / NAV LAYOUT
 *
 * Small overrides for the shared Bootstrap header on Heliomath pages — scoped by
 * controlled loading (this file loads only on Heliomath pages, never Grokkoli).
 * Sit the logo (in .navbar-brand) and the nav items (login, etc.) on one vertical
 * centre line. .navbar-brand is made a centred flex box so the inline-block logo
 * doesn't ride the text baseline.
 * ========================================================================== */
.navbar .navbar-collapse {
    align-items: center;
}
.navbar .navbar-brand {
    display: inline-flex;
    align-items: center;
    margin-top: 0;
    margin-bottom: 0;
}

/* The transparent-header chrome for the dark-header pages (logo insets + size,
 * vertical centring, pill gap) lives in heliomath_nav.css now — one definition
 * shared by the learning-differences page AND the account-access flow, so they
 * line up pixel-for-pixel. The generic brand-centring above still applies to every
 * Heliomath page (incl. home). */


/* ============================================================================
 * LAYOUT COMPAT — the Bootstrap-4 STRUCTURAL rules the shared nav markup relies
 * on, ported verbatim from base.css so Heliomath pages need not load it. The nav
 * markup (external/legacy/home_base) is shared with Grokkoli, so its Bootstrap
 * classes must stay in the HTML; here we supply only their box/flex STRUCTURE —
 * the skin is in the sections below + heliomath_nav / heliomath_marketing.
 * base.css's grid (.container/.row/.col-*), heading-size classes and :root
 * Bootstrap vars are UNUSED on Heliomath and were dropped, not ported. Retire this
 * whole block once the nav markup stops using the Bootstrap navbar classes.
 * ========================================================================== */

/* Flex nav bar + fixed positioning (base.css .navbar + .fixed-top). The transparent
 * hero nav is re-pointed to position:absolute by heliomath_marketing.css; the solid
 * nav keeps fixed. Per-page padding/skin overrides this in the sections below. */
.navbar {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    padding: 0.5rem 1rem;
}

/* --- Wrap behaviour: nav items stay on top, logo drops below ------------ *
 * On the solid content-page nav (terms / success-stories / legal) and the
 * auth-page nav (login / signup / reset), when the bar runs out of room the nav
 * items should hold the top line and the LOGO should be what's forced to the
 * second line — the same rhythm the hero pages have. `wrap-reverse` places the
 * wrapped line ABOVE the first, so it flips the stack order WITHOUT disturbing
 * the single-line desktop layout (logo left, buttons right) and needs no width
 * breakpoint — it triggers exactly at the natural wrap point. The transparent
 * HERO navs (about / plans / LD) are excluded: they hide their nav logo, so
 * there's nothing to reflow there.
 *
 * Two DOM shapes are covered: legacy/alpha bases make the logo + nav separate
 * children of .navbar (so .navbar is what wraps); external_base nests both inside
 * .navbar-collapse (so the collapse wraps). Setting wrap-reverse on both is safe
 * — whichever container isn't the wrapping one holds a single child, so it's a
 * no-op there. */
.header:not(.transparent).navbar,
.auth-page .header.navbar,
.header:not(.transparent) .navbar-collapse,
.auth-page .header .navbar-collapse {
    flex-wrap: wrap-reverse;
    /* Breathing room BETWEEN the wrapped rows only. row-gap applies to the space
     * between flex lines, so on the single-line desktop bar (one row) it has no
     * effect — the desktop spacing is unchanged. Only appears once the bar wraps. */
    row-gap: 22px;   /* space between the wrapped rows; literal (no token lands at 22px) */
}

/* Guarantee a gap between the logo and the leftmost nav item so they can't touch
 * when the single-line bar gets tight (e.g. ~344px, before it wraps): space-between
 * has run out of slack and the auth pages zero the brand's margins. This margin sits
 * to the LEFT of the first pill; on desktop the ml-auto push swallows it (plenty of
 * slack there), so the wide-bar spacing is unchanged. Solid + auth navs only — the
 * hero navs hide their logo, so there's nothing for the pill to touch. */
.header:not(.transparent) .navbar-nav .nav-item:first-child,
.auth-page .header .navbar-nav .nav-item:first-child {
    margin-left: var(--space-sm);
}
.fixed-top {
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
    z-index: 1030;
}
.navbar-brand {
    display: inline-block;
    padding-top: 0.3125rem;
    padding-bottom: 0.3125rem;
    margin-right: 1rem;
    font-size: 1.25rem;
    line-height: inherit;
    white-space: nowrap;
}
.navbar-nav {
    display: flex;
    flex-direction: column;
    padding-left: 0;
    margin-bottom: 0;
    list-style: none;
}
.nav-link {
    display: block;
    padding: 0.5rem 1rem;
}
.navbar-nav .nav-link {
    padding-right: 0;
    padding-left: 0;
}
.navbar-collapse {
    flex-basis: 100%;
    flex-grow: 1;
    align-items: center;
}
.navbar-toggler {
    padding: 0.25rem 0.75rem;
    font-size: 1.25rem;
    line-height: 1;
    background-color: transparent;
    border: 1px solid transparent;
    border-radius: 0.25rem;
}
/* .navbar-expand (unconditional, present in the markup alongside -lg) keeps the bar
 * horizontal at every width and hides the toggler — the Heliomath nav never collapses
 * to a hamburger, so base.css's .collapse / .navbar-expand-lg / hamburger-icon rules
 * never take effect and were not ported. */
.navbar-expand { flex-flow: row nowrap; justify-content: flex-start; }
.navbar-expand .navbar-nav { flex-direction: row; }
.navbar-expand .navbar-nav .nav-link { padding-right: 0.5rem; padding-left: 0.5rem; }
.navbar-expand .navbar-collapse { display: flex !important; flex-basis: auto; }
.navbar-expand .navbar-toggler { display: none; }

/* ...BUT the header nav must still be allowed to WRAP. .navbar-expand forces row
 * NOWRAP (flex-flow), which on narrow phones makes the hero navs overflow the
 * viewport — worst on the LD page, which adds a "Learning Plans" pill beside Login:
 * the links can't wrap, so they clip and push Login off-screen, forcing ~100px of
 * horizontal scroll. Re-enable wrap so the links drop below the logo instead.
 * (These out-specify .navbar-expand; desktop is unaffected — wrap only triggers when
 * the row doesn't fit.)
 *
 * BOTH selectors are needed because the two base templates nest the logo
 * differently: legacy_base puts .navbar-brand as a DIRECT child of .navbar (wrapped
 * by the first selector), while external_base nests brand + links INSIDE
 * .navbar-collapse (wrapped by the second). Without the collapse rule the LD/hero
 * nav on external_base can't wrap — .navbar has a single child — and overflows. */
.header.navbar,
.header .navbar-collapse { flex-wrap: wrap; }

/* Utilities still used by the shared markup (nav logo + #main). */
.align-top { vertical-align: top !important; }
.d-inline-block { display: inline-block !important; }
.ml-auto { margin-left: auto !important; }
.clearfix::after { display: block; clear: both; content: ""; }


/* ============================================================================
 * STANDARD (solid) NAV — the alpha_base header (blog + logged-in app pages).
 *
 * Ported from grokkoli_base.css so these pages don't depend on it (the blog is
 * being de-legacied first). SCOPED `:not(.transparent)` so it styles ONLY the solid
 * Bootstrap header, never the external_base hero nav (which is `.transparent`, and
 * painted by heliomath_marketing / heliomath_nav) — this file loads on both. The
 * grokkoli logo's fixed 165x28 (tuned to the broccoli mark) becomes the Heliomath
 * wordmark's height-based sizing, matching heliomath_nav.css. The matching fixed-nav
 * CLEARANCE (#main padding-top) is set per-page (e.g. heliomath_blog.css), because
 * external_base pages instead want their hero to sit UNDER the transparent nav.
 * ========================================================================== */
.header.navbar-light:not(.transparent) {
    /* wrap-reverse (not plain wrap): when the solid bar runs out of room the nav
     * items hold the top line and the LOGO drops below — see the "Wrap behaviour"
     * block above. This rule has the SAME specificity as that block's navbar
     * selector but is LATER in source, so it's the one that actually decides the
     * solid navbar's wrap direction; it must agree with it. */
    flex-wrap: wrap-reverse;
    min-height: calc(4vh + 2.5rem);              /* ~64px bar */
    padding: 0 var(--space-md);
    /* No row-gap between the two wrapped rows (nav items on top, logo below) on narrow
     * screens: the logo (5px block padding) and the nav pills already carry their own
     * vertical padding, so any row-gap on top reads as too much inside the solid white
     * bar. 0 lets that inherent padding do the spacing. Overrides the shared 22px
     * row-gap from the wrap-reverse rule above (same specificity, but this is later).
     * Inert on wide screens anyway (one row = no row-gap). The transparent auth nav
     * keeps its 22px, which reads fine over the hero. */
    row-gap: 0;
    background-color: var(--surface-elevated);   /* white bar */
    border-bottom: 1px solid var(--border-subtle);
    /* Pin typography so the nav is IDENTICAL whether or not the legacy grokkoli_base
     * (Quicksand + letter-spacing:1px on <body>) is also loaded: the blog drops grokkoli_base,
     * while the scholarship + success-stories pages keep it — the top nav must match on all. */
    font-family: var(--font-family-base);
    letter-spacing: normal;
}
/* Logo: height-based (the Heliomath wordmark), not grokkoli's fixed 165x28. */
.header:not(.transparent) .navbar-logo {
    height: 2.25rem;   /* 36px; width follows the artwork ratio */
    width: auto;
}
/* Nav items (Login, the family/account dropdowns): dark ink, accent on hover. */
.header:not(.transparent) .navbar-nav .nav-link {
    color: var(--text-primary);
    font-size: 1rem;                          /* pin: neutralise grokkoli_base's responsive .nav-item sizing */
    font-weight: var(--font-weight-regular);
    text-decoration: none;                    /* no underline at rest (overrides heliomath_base's a{underline}) — underline appears on hover only */
}
.header:not(.transparent) .navbar-nav .nav-link:hover  { color: var(--accent-primary); text-decoration: underline; }
.header:not(.transparent) .navbar-nav .nav-link:active { color: var(--accent-primary-active); }
.header:not(.transparent) .nav-item {
    margin-left: var(--space-sm);
    margin-right: var(--space-2xs);
}
/* Dropdown menus — right-aligned under their toggle, tokenised divider + items. */
.header:not(.transparent) .dropdown-menu {
    right: 0;
    left: unset;
    padding-top: 15px;
    padding-bottom: 15px;
    min-width: 14rem;
}
.header:not(.transparent) .dropdown-menu .divider {
    border-bottom: 1px solid var(--border-subtle);
    padding-top: 10px;
    margin-bottom: 10px;
}
.header:not(.transparent) .dropdown-menu a {
    color: var(--text-primary);
}


/* ============================================================================
 * FOOTER  —  #footer (the shared public footer)
 *
 * Codifies templates/external_footer.html onto the tokens: a full-width band on
 * the sunken surface with columns of nav links + a copyright line, content
 * centred to the page width. Targets the existing #footer / .footer-content /
 * .links / .link-group markup and overrides the legacy grokkoli_base footer.
 * (The broccoli mascot is Grokkoli-only and hidden for other brands.)
 * ========================================================================== */
#footer {
    background-color: var(--surface-sunken);
    border-top: 1px solid var(--border-on-sunken);
    padding: var(--space-lg) var(--space-gutter);
    font-weight: var(--font-weight-light);   /* 300 */
}

/* Content centred to the page width (= the standard --mp-content-max; keep in sync). */
#footer .footer-content {
    width: 100%;
    max-width: 68rem;
    margin-left: auto;
    margin-right: auto;
}

/* Link columns — flex-wrap so they stack as the viewport narrows. */
#footer .links {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--space-md) var(--space-md);   /* row-gap  column-gap */
    margin-bottom: var(--space-lg);
}
#footer .link-group {
    display: flex;
    flex-direction: column;
    /* Size each link to its own text, not the column's widest item. A flex column
     * defaults to align-items:stretch, which stretched every <a> to the widest link's
     * width — so a short link's box (and its pressed pill fill) spanned the whole
     * column. flex-start lets each link be content-width and left-aligned. */
    align-items: flex-start;
    gap: var(--space-xs);
    margin: 0;
}

/* Footer links: understated dark ink, underline on hover. */
#footer a {
    color: var(--text-lively);
    font-size: var(--type-caption-size);   /* 14–16px — footer links needn't be large */
    line-height: 1.4;
    text-decoration: none;
    /* Pill breathing room around the text — present in ALL states, with an equal negative
     * margin cancelling it so the box the flex column lays out (the MARGIN box) is
     * unchanged: text stays put, links keep their spacing, columns keep their width. And
     * because these hold at rest, they hold on press too — `#footer a` (an id) out-
     * specifies base.css's `a:focus`, so its focus padding/negative-margin can't touch
     * these and can't shift the link. Result: a proper padded pill, zero movement.
     * (base.css's own cancel works for inline links but misbehaves on these flex items.) */
    padding: 3px 10px;
    margin: -3px -10px;   /* cancels the padding for layout; also clears legacy link margins */
    max-width: none;    /* clear the legacy link max-width */
    min-width: 0;       /* clear the legacy link min-width */
}
#footer a:hover  { color: var(--link-hover);  text-decoration: underline; }
#footer a:active { color: var(--link-active); }
/* On PRESS the pill fill is the affordance, so drop the underline while focused. Needed
 * because a pointer press is ALSO a hover, and #footer a:hover's underline (1,1,1)
 * out-specifies base.css's a:focus text-decoration:none (0,1,1) — this restates it at
 * matching specificity, later in source order, so it wins during a press but leaves the
 * plain hover underline intact. */
#footer a:focus { text-decoration: none; }
/* Focus ring is NOT defined here — base.css owns link focus site-wide. */

/* Copyright line. */
#footer p {
    color: var(--text-lively);
    font-size: var(--type-caption-size);
    margin: 0;
}
