/* Hello Theme Functions — utility CSS overrides
 * Moved from Customizer Additional CSS for version control + portability.
 * Generic GeneratePress/site-level overrides only. Element-specific styling
 * belongs in the GP Element's own CSS field. Plugin-specific styling belongs
 * in that plugin's CSS file (e.g., directory-styles.css in hello-directory-plugin).
 */

/* Query loop layout */
.auto-width.gb-query-loop-wrapper {
    flex: 1;
}

/* Curated-page section headings: a rule across. SWAPPED with the page-title
 * treatment (Brandy 2026-08-09 PM: "page titles should have what the headers
 * are and the headers should have what the page titles are") — headings now
 * carry the thin solid rule the titles had; the titles took the 2px dashed. */
.page .entry-content h2.wp-block-heading {
    padding-bottom: 0.4em;
    border-bottom: 1px dashed var(--contrast-3, #e5e5e5);
}

/* BF/advent pill jump menu: WRAPPED rows were touching (Brandy 2026-08-09
 * screenshot). Root cause: listicle-blocks sets `.hs-jump-menu{line-height:1}`
 * on a <p> of inline-block pills — fine for one row (listicles, THE's thin
 * data), crushed the moment the pill set wraps (prod BF = 13 sections).
 * line-height is the correct lever for inline-block rows; row-gap is a no-op
 * on a non-flex container. */
.hs-jump-menu {
    line-height: 2.6;
}

/* Mobile: the sidebar stacks below the content (<768px) with nothing marking
 * where the page ends and the sidebar begins — the first sidebar promo read
 * as part of the article (Brandy 2026-08-09). Clear gap + light divider. */
@media (max-width: 767.98px) {
    #right-sidebar {
        margin-top: 48px;
        padding-top: 24px;
        border-top: 2px solid #e8e8e8;
    }
}

/* Sticky sidebar layout */
@media (min-width: 768px) {
    .sticky-container > .gb-inside-container,
    .sticky-container {
        position: sticky;
        top: 80px;
    }
    #right-sidebar .inside-right-sidebar {
        height: 100%;
    }
}

/* Misc widget + comment overrides */
select#wp-block-categories-1 { width: 100%; }
p.no-comments { display: none; }

/* Instagram embed full-width override (ported from hello-img-link-to-directory.css).
 * Overrides Instagram's default 540px min/max that centers the embed with whitespace
 * either side on wider containers. */
.instagram-media {
    max-width: 100% !important;
    min-width: 100% !important;
}

/* Archive header (fallback for empty term archives — see hello-theme-functions.php) */
.page-header {
    margin-bottom: 2em;
}
.page-header .page-title {
    margin: 0 0 0.5em;
}
.page-header .taxonomy-description {
    font-size: 1.1em;
    color: #666;
}
.page-header .taxonomy-description p:last-child {
    margin-bottom: 0;
}

/* ===== Mobile Quick Links Bar =====
 * Coupled to GP Element #3649 "Mobile Quick Links Menu" (Hook element,
 * no built-in CSS field). If that Element is deleted, remove this section too.
 */
.mobile-quick-links-container {
    width: 100%;
    background: #222;
    display: flex;
    justify-content: center;
    padding: 8px 0;
}

.mobile-quick-links-menu {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    gap: 20px;
}

.mobile-quick-links-menu li a {
    color: white;
    font-weight: 600;
    text-transform: uppercase;
    text-decoration: none;
    font-size: 14px;
    letter-spacing: 1px;
    transition: color 0.2s ease;
}

.mobile-quick-links-menu li a:hover,
.mobile-quick-links-menu li a:focus { color: #fcb900; }

.mobile-quick-links-menu li:not(:last-child):after {
    content: "|";
    color: #444;
    margin: 0 12px;
}

@media (max-width: 768px) {
    .mobile-quick-links-container { padding: 10px 0; }
    .mobile-quick-links-menu li a { font-size: 12px; }
    .mobile-quick-links-menu { gap: 12px; }
    .mobile-quick-links-menu li:not(:last-child):after { margin: 0 8px; }
}

@media (min-width: 769px) {
    .mobile-quick-links-container { display: none; }
}

/* HS-451 — three rules for `hs_breadcrumb()`'s Schema.org <nav><ol><li> markup used to
   sit here and were DELETED. That markup does not exist and never did on this site: the
   function appears in no plugin, and htf/v1/content-scan over prod post_content returned
   0 for `hs_breadcrumb` and 0 for `breadcrumb-separator`. Dead selectors describing a
   structure we do not emit, sitting immediately above the rules that DO apply — which is
   how "style breadcrumbs sitewide the same" reads as unfinished when the live styling was
   already one block. */

/* Breadcrumbs — LIVE output is Yoast [wpseo_breadcrumb], wrapped by HTF in
   <p id="breadcrumbs">: structure is <span><span><a>…</a></span> » <span
   class="breadcrumb_last">Title</span></span>.
   Style the Yoast structure into a quiet horizontal trail.                    */
#breadcrumbs {
    font-size: 13px;
    line-height: 1.5;
    color: #6b7280;
    margin: 0 0 16px;
    letter-spacing: .01em;
}
#breadcrumbs a {
    color: #6b7280;
    text-decoration: none;
    transition: color .15s ease;
}
#breadcrumbs a:hover,
#breadcrumbs a:focus {
    color: var(--accent, #1a1a1a);
    text-decoration: underline;
}
/* HS-443: trimming the current-page crumb is done in PHP, not here — see
   htf_trim_last_breadcrumb_link() on the wpseo_breadcrumb_single_link filter in
   htf-runtime.php. A CSS rule can only say "hide the last crumb", which is
   positional, and on a two-crumb trail (Home » Shop) that collapses the whole
   breadcrumb to "Home". The PHP version is conditional on an ancestor surviving.
   .breadcrumb_last still renders on those short trails, so it keeps its styling.
   🔴 HS-451: its declarations used to be duplicated HERE as well. `#breadcrumbs
   .breadcrumb_last { color:#374151; font-weight:600 }` was overridden in full by
   `p#breadcrumbs .breadcrumb_last` further down this file — same two properties,
   one element token more specific — so the colour on this copy had never once
   applied. Two rules for one thing, one of them a lie about what the page looks
   like. The surviving rule is in the HS-398 block below. */

/* Mobile: tighten the gap between the mobile menu and the trail. GP one-container
   puts padding:40px on .site-content (main.css:1224) — 40px of dead air on a
   phone. 768px matches GP Menu Plus's mobile breakpoint (HS-222 note below). */
@media (max-width: 768px) {
    #breadcrumbs {
        margin: 0 0 10px;
    }
    .one-container .site-content {
        padding-top: 14px;
    }
}

/* HS-117 — curated-index "Updated <date>" freshness line. Now emitted from
   generate_after_entry_header (below the title/underline, above the body),
   right-justified. Quiet grey, matching the breadcrumb register
   (13px / #6b7280). NOT breadcrumb markup. */
.hs-curated-updated {
    font-size: 13px;
    line-height: 1.5;
    color: #6b7280;
    letter-spacing: .01em;
    text-align: right;
    margin: .25em 0 1em;
}

/* HS-117 — title underline on curated index pages (additive; no theme rule
   for this existed previously). Scoped to the curated-index body class.
   SWAPPED 2026-08-09 PM (Brandy): the title now carries the heavier dashed
   rule; the section h2s took the thin solid one (see the h2 rule at top). */
body.page .entry-title,
body.hs-curated-index .entry-title {
    border-bottom: 2px dashed var(--contrast-3, #dcdcdc);
    padding-bottom: .3em;
    margin-bottom: .5em;
}

/* The archive-template H1 (Articles page + category archives) draws its
   underline on the WRAPPING GB container, not the headline — bring it to the
   same 2px dashed as every other page H1. */
.site .gb-container-04da9225 {
    border-bottom-width: 2px;
    border-bottom-color: var(--contrast-3, #dcdcdc);
}

/* HS-117 — .hs-jump-menu styling now lives ONLY in listicle-blocks
   build/style-index.css (single source), enqueued on curated pages by
   htf_is_curated_index() in hello-theme-functions.php. No local copy here. */

/* Fixed-ratio crop for dynamic featured-image cards.
   GenerateBlocks core's .gb-block-image img{height:auto} outranks a block's own
   height setting, so the crop is applied here via a class on the image. The
   aspect-ratio holds the shape at any column width — no fixed heights needed.
   Add "hs-home-card-crop" to the image block's Advanced → Additional CSS class(es). */
.gb-block-image img.hs-home-card-crop {
    aspect-ratio: 800 / 525;
    width: 100%;
    height: auto;
    object-fit: cover;
}

/* ==========================================================================
   HS-222 — Find mega-menu (desktop) + Gifts campaign icon
   Desktop-only (min-width: 769px = complement of GP's mobile menu breakpoint).

   BREAKPOINT DEPENDENCY: the 769px here MUST stay the complement of GP Menu
   Plus's `mobile_menu_breakpoint` setting (generate_menu_plus_settings option;
   gp-premium default '768' — verified absent from the option on THE, so the
   default governs). If an admin raises that setting, update this media query
   to (breakpoint + 1). As a belt-and-braces guard, every structural rule below
   is ALSO scoped `.main-navigation:not(.toggled)` — GP's menu.js puts
   `.toggled` on the nav element when the mobile menu is open — so a breakpoint
   mismatch degrades to GP's working accordion instead of freezing it.

   GRID PLACEMENT is class-driven (`mm-col-1`…`mm-col-5` in each group item's
   _menu_item_classes, set in the menu editor), NOT nth-child, so reordering
   groups in the menu editor cannot scramble the layout. The two column-5
   groups both carry `mm-col-5` and stack in source order. A group missing its
   mm-col-* class auto-flows after the placed items (visible, not silent).
   Row 1 is a 15-track grid shared by THREE `mega-top` launchers (Best
   Subscriptions, Gift Guide, Browse the full Directory), each spanning 5
   tracks (`grid-column: span 5`) so they auto-flow left-to-right in menu
   source order and tile evenly with no overlap; the category groups sit in
   rows 2-3 as 3-track spans (mm-col-1..5 = 5 tracks × 3 columns each,
   preserving the original 5-column visual ratio on a 15-track LCM grid).
   All three launchers stay clickable real links — the pointer-events:none
   group-header rule excludes `mega-top`.

   GP's dropdown show/hide mechanism (.main-navigation ul ul left/opacity/
   height/pointer-events, main.min.css) is left intact — only layout and
   position are overridden here. Mobile gets GP's untouched accordion.
   ========================================================================== */

/* Gift icon on the Gifts item (menu class `campaign`) — inline SVG mask,
   zero extra requests, inherits menu text color */
.main-nav > ul > li.campaign > a::before {
    content: '';
    display: inline-block;
    width: .9em;
    height: .9em;
    margin-right: .35em;
    vertical-align: -.08em;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 12 20 22 4 22 4 12'/%3E%3Crect x='2' y='7' width='20' height='5'/%3E%3Cline x1='12' y1='22' x2='12' y2='7'/%3E%3Cpath d='M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z'/%3E%3Cpath d='M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z'/%3E%3C/svg%3E") no-repeat center / contain;
            mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 12 20 22 4 22 4 12'/%3E%3Crect x='2' y='7' width='20' height='5'/%3E%3Cline x1='12' y1='22' x2='12' y2='7'/%3E%3Cpath d='M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z'/%3E%3Cpath d='M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z'/%3E%3C/svg%3E") no-repeat center / contain;
}

@media (min-width: 769px) {
    /* Every rule in this block is scoped :not(.toggled) so none of it can
       apply inside GP's open mobile accordion (see header comment). */

    /* Panel anchors to the nav bar, not the li */
    .main-navigation:not(.toggled) { position: relative; }
    .main-navigation:not(.toggled) .main-nav > ul > li.mega-menu { position: static; }

    /* Panel layout (GP's hidden state — left:-99999px/opacity:0/height:0 —
       still applies; this only changes what the panel looks like when shown) */
    .main-navigation:not(.toggled) .main-nav > ul > li.mega-menu > ul.sub-menu {
        display: grid;
        grid-template-columns: repeat(15, 1fr);
        gap: 0 24px;
        padding: 24px 32px;
        width: 100%;
        box-sizing: border-box;
        float: none;
        text-align: left;
    }

    /* Shown state: outrank GP's `left:auto` show rule to pin the panel
       full-width against the nav bar */
    .main-navigation:not(.toggled) .main-nav ul li.mega-menu:hover > ul.sub-menu,
    .main-navigation:not(.toggled) .main-nav ul li.mega-menu.sfHover > ul.sub-menu {
        left: 0;
        right: 0;
    }

    /* Top row: three `mega-top` launchers (Best Subscriptions, Gift Guide,
       Browse the full Directory) — each spans 5 of the 15 tracks and
       auto-flows left-to-right in menu source order, tiling evenly across
       the full row with no overlap. */
    .main-navigation:not(.toggled) li.mega-menu > .sub-menu > li.mega-top {
        grid-row: 1;
        grid-column: span 5;
        border-bottom: 1px solid rgba(0, 0, 0, .08);
        margin-bottom: 8px;
        padding-bottom: 4px;
    }
    .main-navigation:not(.toggled) li.mega-menu > .sub-menu > li.mega-top > a { font-weight: 600; }

    /* Class-based grid placement (mm-col-* set in the menu editor on each
       group item — reorder-safe, see header comment). mm-col-1..5 occupy
       rows 2-3 (row 1 = the three mega-top launchers); each spans 3 of the
       15 tracks, preserving the original 5-column visual ratio. The two
       mm-col-5 groups (On a Budget, Seasonal) auto-stack in the same
       columns. If mega-top is absent, implicit row 1 collapses to zero
       height — no visual gap. */
    .main-navigation:not(.toggled) li.mega-menu > .sub-menu > li.mm-col-1 { grid-column: 1 / 4; grid-row: 2 / span 2; }
    .main-navigation:not(.toggled) li.mega-menu > .sub-menu > li.mm-col-2 { grid-column: 4 / 7; grid-row: 2 / span 2; }
    .main-navigation:not(.toggled) li.mega-menu > .sub-menu > li.mm-col-3 { grid-column: 7 / 10; grid-row: 2 / span 2; }
    .main-navigation:not(.toggled) li.mega-menu > .sub-menu > li.mm-col-4 { grid-column: 10 / 13; grid-row: 2 / span 2; }
    .main-navigation:not(.toggled) li.mega-menu > .sub-menu > li.mm-col-5 { grid-column: 13 / 16; grid-row: auto; }

    /* Group headers = non-link labels. The :not(.toggled) scope is what keeps
       this pointer-events:none OUT of the open mobile accordion — without it,
       a breakpoint mismatch makes the accordion's group rows un-tappable.
       mega-top launchers are REAL links and stay clickable. */
    .main-navigation:not(.toggled) li.mega-menu > .sub-menu > li:not(.mega-top) > a {
        font-weight: 700;
        pointer-events: none;
        cursor: default;
    }

    /* Level-3 lists: always open, static, laid out inside the panel */
    .main-navigation:not(.toggled) li.mega-menu > .sub-menu li > ul.sub-menu {
        position: static;
        display: block;
        left: auto;
        opacity: 1;
        pointer-events: auto;
        height: auto;
        overflow: visible;
        width: auto;
        box-shadow: none;
        float: none;
        transition: none;
    }

    /* No flyout arrows inside the panel (mobile accordion keeps its toggles) */
    .main-navigation:not(.toggled) li.mega-menu .sub-menu .dropdown-menu-toggle { display: none; }
}

/* ==========================================================================
   HS-222 — mobile hamburger menu (THE-test round)
   ========================================================================== */

/* Hamburger shows ONLY Find + More. Deals/Best/Reviews/Spoilers/Gifts carry
   `mobile-hide` in _menu_item_classes — they already live in the quick-links
   bar, which renders at exactly these widths (see Mobile Quick Links Bar
   above: hidden at min-width:769px). Desktop nav keeps all 7 items. */
@media (max-width: 768px) {
    .main-navigation.toggled .main-nav > ul > li.mobile-hide { display: none; }
}

/* SCROLL FIX — the open mobile menu must stay on-screen and scroll internally.
   Two independent problems fixed for the vanish-on-scroll bug:
   (1) PRIMARY (JS, see htf-mobile-menu-fix in hello-theme-functions.php):
   GP menu.js checkMobile() force-closed the open menu on every window
   `resize` — which real phones fire when the URL bar collapses during
   scroll — because it checks the visibility of #mobile-menu-control-wrapper's
   toggle, which is never visible on this site (the gp-premium mobile header
   replaces #masthead at mobile widths). The wrapper is removed from the DOM.
   (2) HERE: mobile_header_sticky makes #mobile-header position:fixed once
   scrolled; the fixed nav had no max-height/overflow, so any open-menu
   content below the viewport fold was unreachable (page scroll doesn't move
   a fixed element). Give the toggled menu list its own scroll context sized
   to the viewport minus the 60px header bar; overscroll-behavior:contain
   keeps internal scrolling from chaining to the body.
   The top:0 pin is a guard: auto_hide_sticky currently applies only to the
   desktop #site-navigation (mobile_header_auto_hide_sticky is off), but if it
   is ever enabled, gp-premium would slide the whole fixed nav — open panel
   included — off-screen by inline `top`; the pin keeps an OPEN menu exempt. */
#mobile-header.toggled {
    top: 0 !important;
}
.main-navigation.toggled .main-nav > ul {
    max-height: calc(100vh - 60px);
    max-height: calc(100dvh - 60px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
}

/* ==========================================================================
   HS-331 — Lander pager styled to match the CATEGORY-ARCHIVE pager.
   Brandy 2026-08-08: "style them like the fucking categories."

   The archive pager is a GenerateBlocks button block whose CSS is emitted by
   the archive element (`.gb-button-wrapper .gb-button-1be5c84d`). That CSS is
   NOT enqueued on curated/lander pages, so the native query-page-numbers block
   there renders as a bare <nav> with plain `.page-numbers` links. The values
   below are copied VERBATIM from the archive rules so the two match exactly —
   if the archive pager is ever restyled in GB, update these to match.

   Scoped to `.hs-lander-pager` (a className on the pager block itself), so it
   cannot touch the site nav, the mobile menu, or the archive's own pager.
   ========================================================================== */
.hs-lander-pager {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	/* Breathing room on BOTH sides: the pager sits between the last card and the
	   site's terms/disclosure paragraph, and with only a top margin it crowded
	   that text on mobile (Brandy 2026-08-08). row-gap covers wrapped rows when
	   the numbers exceed one line on a narrow screen. */
	row-gap: 10px;
	margin-top: 2em;
	margin-bottom: 2em;
}

/* Mobile: cards stack full-width, so the pager needs more separation than the
   desktop rhythm to read as its own element rather than part of the card above
   or the paragraph below. */
@media (max-width: 768px) {
	.hs-lander-pager {
		margin-top: 2.75em;
		margin-bottom: 2.75em;
	}
}

.hs-lander-pager .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-size: 15px;
	text-align: center;
	padding: 10px 15px;
	margin-right: 2.5px;
	margin-left: 2.5px;
	border-radius: 10px;
	border: 1px solid var(--contrast-3);
	background-color: var(--base-3);
	color: var(--contrast);
	text-decoration: none;
}

.hs-lander-pager .page-numbers:hover,
.hs-lander-pager .page-numbers:active,
.hs-lander-pager .page-numbers:focus,
.hs-lander-pager .page-numbers.current {
	background-color: var(--accent);
	color: var(--base-3);
}

/* HS-398 (Brandy 2026-08-11): bwp-external-links paints its sprite icon on
   every a.ext-link; on anchors that WRAP AN IMAGE the icon floats beside the
   photo. Kill icon + padding for image-wrapping anchors only — text links
   keep their icons. :has() is in every current browser; older ones just keep
   the icon (cosmetic, acceptable). */
a.ext-link:has(img),
a.ext-link:has(img):link,
a.ext-link:has(img):visited,
a.ext-link:has(img):hover,
a.ext-link:has(img):active {
    background: none !important;
    padding-right: 0 !important;
}

/* ==========================================================================
   HS-382 — homepage newest-section lead cards: shorter crop (Brandy 2026-08-11,
   "less tall", 2:1 first try). Same mechanism as hs-home-card-crop; the two
   lead image blocks swap to this class via the Home page content.
   ========================================================================== */
.gb-block-image img.hs-home-card-crop--short {
    aspect-ratio: 2 / 1;
    width: 100%;
    height: auto;
    object-fit: cover;
}

/* ==========================================================================
   HS-382 — featured-card titles hold exactly 3 lines: clamp longer titles AND
   reserve the full 3-line box for shorter ones, so card heights stop depending
   on title length.
   HS-478 — restored to 3. An earlier edit meant for the .hs-post-grid block
   below landed here instead; the comment still said 3 over a value of 4.
   ========================================================================== */
.htf-featured-primary h3.gb-headline,
.htf-featured-secondary h3.gb-headline {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
    min-height: 3lh;
}

/* ==========================================================================
   HS-382 — column-bottom alignment for homepage lead cards (Brandy
   2026-08-11: "the stuff isn't aligned", featured + newest). The lead card's
   grid column already stretches to its row's height; these rules make the
   card CONTENT fill it — the image absorbs the slack (object-fit cover), so
   the lead card's bottom lines up with the sibling column's. Desktop only;
   mobile stacks and needs the fixed-ratio crops instead.
   Newest-section lead loops are targeted by GB uid (3ed6eab0 / cdfcf079 —
   stable in the Home page content, re-check on homepage rebuilds).
   ========================================================================== */
@media (min-width: 769px) {
    .htf-featured-primary,
    .gb-grid-wrapper-3ed6eab0,
    .gb-grid-wrapper-cdfcf079,
    .htf-featured-primary .gb-grid-column,
    .gb-grid-wrapper-3ed6eab0 .gb-grid-column,
    .gb-grid-wrapper-cdfcf079 .gb-grid-column,
    .htf-featured-primary .gb-query-loop-item > .gb-container,
    .gb-grid-wrapper-3ed6eab0 .gb-query-loop-item > .gb-container,
    .gb-grid-wrapper-cdfcf079 .gb-query-loop-item > .gb-container {
        height: 100%;
    }
    .htf-featured-primary .gb-query-loop-item > .gb-container,
    .gb-grid-wrapper-3ed6eab0 .gb-query-loop-item > .gb-container,
    .gb-grid-wrapper-cdfcf079 .gb-query-loop-item > .gb-container {
        display: flex;
        flex-direction: column;
    }
    .htf-featured-primary .gb-block-image,
    .gb-grid-wrapper-3ed6eab0 .gb-block-image,
    .gb-grid-wrapper-cdfcf079 .gb-block-image {
        flex: 1 1 auto;
        min-height: 0;
    }
    /* GB wraps the image in a link INSIDE the <figure>. That <a> is inline and
       auto-height, so img{height:100%} has nothing to resolve against. */
    .htf-featured-primary .gb-block-image > a,
    .gb-grid-wrapper-3ed6eab0 .gb-block-image > a,
    .gb-grid-wrapper-cdfcf079 .gb-block-image > a {
        display: block;
        height: 100%;
    }
    /* HS-601 — the PRIMARY featured image runs from the top of the right-hand
       images to the BOTTOM of the right-hand images (Brandy 2026-08-19: "i really
       want the image height of the primary featured to go from the top of the pics
       in the right side to the bottom of the pics") — past the 2x2's middle title
       row, not stopping short of it.
       🔴 The height:100% above NEVER RESOLVED for the primary card: the outer grid
       (.gb-grid-wrapper-ddd16ddb) carries align-items:flex-start from its block
       settings, so both columns are content-height. HS-382's "the image absorbs the
       slack" premise was therefore never true — and because this rule also switched
       the crop OFF (aspect-ratio:auto), the image fell back to its NATURAL shape.
       A portrait featured image (ARMRA, 1080x1350) rendered the card ~750px tall
       beside a ~600px column. Landscape images hid it for months.
       ⚠️ Overriding that align-items in THIS file does not work: WordPress enqueues
       theme-utilities.css BEFORE the GenerateBlocks stylesheet, so an equal-specificity
       rule loses on source order. It tests green as an injected <style> and does
       nothing once it ships from the file. That cost a deploy.
       So the height is stated directly instead. The right column is the same width
       as this one and holds two rows of the same 800/525 crop, so its lower image
       edge sits at
           2 * ((W - 10px column gap) / 2) * 525/800  +  91px
       (91px = the secondary title block between the rows: 3px + a 3-line clamp at
       64.8px + 13px + 10px column padding) = 0.65625 * W + 84px.
       W is this column's own inline size, so a container query unit states it exactly
       at every width. Measured in a real browser against the rendered page:
       355px wide -> 317, 405 -> 350, 467 -> 391, 505 -> 416, 555 -> 448, 595 -> 475;
       the fit holds within 1px, and live prod measured 0/-1px at 1024/1440/1920.
       If cqw is ever unsupported the declaration drops and the base aspect-ratio
       crop takes over — it degrades SHORT, never tall. */
    .htf-featured-primary .gb-query-loop-item > .gb-container {
        container-type: inline-size;
    }
    .htf-featured-primary .gb-block-image {
        flex: none;
        height: calc(65.625cqw + 84px);
    }
    /* aspect-ratio is deliberately NOT reset to auto. A definite height wins
       whenever it resolves; the ratio from the base rule stays behind it as the
       fallback crop, so the image can never revert to its natural shape and blow
       the card out again. */
    .htf-featured-primary .gb-block-image img.hs-home-card-crop,
    .gb-grid-wrapper-3ed6eab0 .gb-block-image img.hs-home-card-crop--short,
    .gb-grid-wrapper-cdfcf079 .gb-block-image img.hs-home-card-crop--short {
        height: 100%;
        object-fit: cover;
    }
}

/* ==========================================================================
   HS-382 — lozenge CTA wrap (Brandy 2026-08-11, "still overflow on the best
   subscriptions page"). The directory's .box-button sets white-space:nowrap
   at the same specificity as listicle-blocks' wrap fix, and wins on source
   order wherever both stylesheets load (curated landers). Long "From $X at
   Brand" labels then overflow the card. Two classes + element beats both.
   ========================================================================== */
a.lozenge-button.box-button {
    white-space: normal;
    overflow-wrap: anywhere;
    max-width: 100%;
}

/* ==========================================================================
   HS-382 — hs_post_grid card titles hold exactly 4 lines: same clamp+reserve as
   the featured cards, so grid rows align regardless of headline length. FOUR,
   not three — HS-478 landed the four-line change that was aimed at this block
   and had been applied to the featured block instead.
   ========================================================================== */
.hs-post-grid .hs-dcard__title {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    line-clamp: 4;
    overflow: hidden;
    min-height: 4lh;
}

/* Post titles, NOT box names (Brandy 2026-08-11): Poppins 22 / weight 400.
   MUST out-specify `.listicle-card-3up .hs-dcard__title` (the BF/advent
   box-name treatment) — post-grid cards carry BOTH classes and that rule sits
   later in this file, so at equal specificity it was winning and the titles
   rendered 1.7rem/500/uppercase. Three classes beats two; do not "simplify"
   this selector back down. */
.hs-post-grid .listicle-card-3up .hs-dcard__title {
    font-family: "Poppins", sans-serif;
    font-size: 22px;
    font-weight: 400;
    text-transform: none;
    text-align: left;
    line-height: 1.3;
    margin: 12px 16px 6px;
}

/* ==========================================================================
   HS-382 — gift-guide 3up cards (Brandy 2026-08-11): images crop to one
   ratio so all three columns align, and the block headers step up.
   ========================================================================== */
.listicle-card-3up .hs-dcard__image img {
    aspect-ratio: 4 / 3;
    width: 100%;
    height: auto;
    object-fit: cover;
}
.listicle-card-3up .hs-dcard__title {
    /* Same treatment as the BF/advent post cards (.hs-dcard--post
       .hs-dcard__title + --box): big medium-weight centered ALL-CAPS name. */
    font-size: 1.7rem;
    font-weight: 500;
    line-height: 1.15;
    text-align: center;
    text-transform: uppercase;
    margin: 16px 16px 6px;
    white-space: normal;
    overflow-wrap: break-word;
    word-break: break-word;
}
.listicle-card-3up .hs-dcard__title a {
    color: #111;
    text-decoration: none;
}

/* ==========================================================================
   HS-382 — gift-guide section headers match the Black Friday page (Brandy
   2026-08-11): the listicle-container titles take the same curated-page
   heading treatment as .entry-content h2.wp-block-heading above.
   ========================================================================== */
.page .entry-content .listicle-container-title {
    padding-bottom: 0.4em;
    border-bottom: 1px dashed var(--contrast-3, #e5e5e5);
}

/* ==========================================================================
   HS-398 — title separator parity (Brandy 2026-08-11).
   (a) Shop singles (/shop/<entry>/) had NO rule under the H1: the existing
       treatment is scoped `body.page .entry-title` and these are a CPT.
       Same 2px dashed as every other page H1; the affiliate disclosure now
       hooks after the entry header so it lands UNDER this line.
   (b) /subscriptions/ + /shop/ archives: the sorter rides ABOVE the rule.
       The archive H1 draws no border itself — the rule goes on the sort form's
       bottom edge, so title → sorter → line → grid.
   ========================================================================== */
body.single-shop .entry-title {
    border-bottom: 2px dashed var(--contrast-3, #dcdcdc);
    padding-bottom: .3em;
    margin-bottom: .5em;
}

.hs-sort {
    border-bottom: 2px dashed var(--contrast-3, #dcdcdc);
    padding-bottom: .5em;
    margin-bottom: 1em;
}

/* ==========================================================================
   HS-398 — breadcrumb + separator consistency (Brandy 2026-08-11, four URLs).
   All CSS-only on purpose: the trail CONTENT is HS-443's PHP and is being
   edited in a parallel session — these rules hold whatever it emits.

   (a) A one-item trail is not a breadcrumb. Top-level pages (spoilers hub,
       gift guide, /shop/) render just "Hello Subscription" with nothing after
       it — hide the block entirely. Detection is structural, not per-page: no
       separator span means no hierarchy to show.
   (b) NO rule under the breadcrumb. "Separator" in Brandy's instruction meant
       the » BETWEEN crumbs, not a horizontal line — a dashed border under the
       block was my misreading and is removed.
   (c) The current page (Yoast's .breadcrumb_last) reads as bold plain text —
       the convention the Balsamiq guide describes, and the answer to "bold
       last part of crumb".
   (d) /shop/ drew TWO rules: the archive H1 container has one and the sort
       form (HS-398) added another. Where a sorter exists it owns the rule.
   ========================================================================== */
p#breadcrumbs:not(:has(.hs-crumb-sep)) {
    display: none;
}

p#breadcrumbs .breadcrumb_last {
    font-weight: 600;
    color: var(--contrast, #222);
}

.site:has(.hs-sort) .gb-container-04da9225 {
    border-bottom-width: 0;
}
