/* NSP Listicles front-end. Rae: this file is yours — tokens up top, layout below.
   Versioned by filemtime, so saves bust cache automatically. */

.nspl {
  /* Was a literal #1E295B -- which is --np-midnight-navy, the Family Favorites sub-brand
     colour, not this site's navy. First correction pointed this at --np-dark-blue
     (#165272), which was still wrong: a real post's .entry-title actually computes
     --global-palette3 (#10344a), a Kadence customizer slot one shade darker and cooler
     than --np-dark-blue, not that token. Pointed at the real variable itself now, so this
     tracks whatever the customizer says rather than a second, separately-maintained
     approximation of it -- with the same fallback chain in case that slot is ever unset. */
  --nspl-navy: var(--global-palette3, var(--np-dark-blue, #165272));
  --nspl-pink: #F2799B;
  --nspl-pink-wash: #fdeef2;
  --nspl-gold: #E8C845;
  --nspl-gold-wash: #fdf8e3;
  --nspl-band: #EEF3F7;
  --nspl-ink: #2f4858;
  --nspl-muted: #5f7480;
  --nspl-line: #e3e8ef;
  --nspl-disp: var(--np-font-condensed, "Archivo", "Arial Narrow", sans-serif);
  /* Was a separate serif import (Source Serif 4 / Georgia) -- replaced with the site's own
     body face so every listicle reads in the same two type families as the rest of the
     site (condensed for display, this for everything else) rather than introducing a
     third. Named --nspl-body, not --nspl-serif, since a "serif" variable now holding a
     sans-serif stack would be exactly the kind of stale name that misleads later. */
  --nspl-body: var(--np-font-body, "acumin-pro", "Helvetica Neue", Arial, sans-serif);
  color: var(--nspl-ink);
}

/* ---------- hero ---------- */
/*
No more ".nspl-post .entry-hero/.entry-header { display: none }" here -- Kadence's own
entry_header used to render for every listicle post (title, meta, categories, all of it)
and get hidden after the fact purely by CSS, because this header itself was built by a
`the_content` filter that could only replace what's inside .entry-content, with no way to
suppress Kadence's own separate call to entry_header alongside it. Now that this header is
its own function (nsp_listicle_render_header(), inc/listicles.php) called directly from
template-parts/content/single-entry.php in the same two places entry_header itself would
render, that file skips entry_header outright for a listicle post ($np_is_listicle) --
nothing to hide, because nothing duplicate ever renders.
*/
.nspl-head { max-width: 720px; margin: 0 auto; padding: 2.5rem 1rem 2rem; text-align: center; }
/*
On mobile the 1rem side padding here stacked on top of the page's own 16px mobile gutter
(set sitewide on `.entry-content-wrap`), landing the title 16px deeper than the body copy
below it -- measured live at 40px from the viewport edge against 24px for a spot's own
name. Zeroed here so the hero content aligns with the rest of the page instead of adding a
second inset on top of the one the page already has.
*/
@media (max-width: 767px) {
  .nspl-head { padding-left: 0; padding-right: 0; }
}
/*
Every margin edit made to this hero block until now had NO effect, and here is why: this
template renders inside `.single-content`, and Kadence's content.min.css carries
`.single-content h1, .single-content h2, ... { margin: 1.5em 0 0.5em }` and
`.single-content address, .single-content figure, .single-content hr, .single-content p,
.single-content table, ... { margin: 0 0 var(--global-md-spacing) }`. Both are one class
plus one element -- (0,1,1) -- which outranks a bare `.nspl-eyebrow`/`.nspl-h1` class at
(0,1,0), regardless of what value was in the losing rule. Confirmed live: `.nspl-eyebrow`
computed a 32px margin-bottom (`var(--global-md-spacing)`) no matter what this file said,
and `.nspl-h1` computed `margin-top: 74.4px` -- 1.5em against its own ~49.6px font-size --
though this file has never set a top margin on it at all.

Every selector below that resolves to one of Kadence's targeted tags (p, h1-h6, ul, ol,
figure, address, hr, table) is prefixed with `.nspl ` for exactly this reason: two classes,
(0,2,0) or better, safely beats (0,1,1) regardless of source order. This is the same fix
already proven for `.nspl-chips`'s padding, applied everywhere else it was silently needed.
*/
/* margin-bottom is 1.3rem, matching .nspl-dek's own value exactly -- measured live at 21px
   between .nspl-dek and .nspl-meta, and copied rather than a new number chosen, per the
   request to use that same spacing rule here. */
.nspl .nspl-eyebrow { font-family: var(--nspl-body); font-weight: 700; font-size: clamp(.9rem, 1.3vw, 1.05rem); letter-spacing: .18em; color: var(--nspl-pink); text-transform: uppercase; margin: 0 0 1.3rem; }
/*
Size/line-height/letter-spacing match the plain-post title exactly now, not a value of
their own -- above 768px that's a shared rule in style.css ("Post title: large on
desktop"), so a future change to one title reaches both. Below 768px, .entry-title is
left at Kadence's own unstyled default there (the browser's own `h1 { font-size: 2em }`,
computing to 32px against this site's 16px root, 1.5 line-height inherited from `body`,
no letter-spacing) rather than anything this theme sets -- .nspl-h1 needs that written out
explicitly here instead of inheriting the same way, since nothing upstream of it happens
to compute the same 2em relationship. Font-family, weight, colour and margin are untouched
-- those already matched (--nspl-disp/--nspl-navy both resolve through the same tokens
--np-font-condensed/--global-palette3 the plain title itself uses).
*/
.nspl .nspl-h1 { font-family: var(--nspl-disp); font-weight: 800; font-size: 2rem; line-height: 1.5; letter-spacing: normal; color: var(--nspl-navy); margin: 0 0 .9rem; text-wrap: balance; }
.nspl .nspl-dek { font-family: var(--nspl-body); font-style: italic; font-size: 1.18rem; color: var(--nspl-muted); margin: 0 0 1.3rem; line-height: 1.5; }
/* Matches .entry-meta's own plain treatment (content.min.css: 80% size, no weight/
   tracking/case set) instead of the bold, tracked, uppercase treatment this used to have
   of its own -- .85rem is that 80% against this site's 16px root (.entry-meta's own 80%
   resolves against `body`'s local 17px instead, landing 13.6px either way). Colour moves
   from --nspl-muted to --nspl-ink, matching .entry-meta's own inherited body-text colour
   (#2f4858) rather than the washed-out grey this treatment used for a de-emphasised byline
   -- the plain post's date/author line reads as regular text, not muted metadata. */
.nspl .nspl-meta { font-family: var(--nspl-body); font-weight: 400; font-size: .85rem; letter-spacing: normal; text-transform: none; color: var(--nspl-ink); margin: 0 0 1.5rem; }
.nspl .nspl-intro { text-align: center; font-family: var(--nspl-body); font-size: 1.06rem; line-height: 1.75; margin: 0; }
.nspl-rule { width: 64px; height: 4px; border-radius: 2px; background: var(--nspl-gold); margin: 2rem auto 0; }

/* ---------- shared spot pieces ---------- */
/*
Name and price share a row that wraps: `.nspl-title-row` is what `nsp_listicle_render_item()`
now wraps both in, so a long name pushes the badge onto its own second line instead of the
two crowding one. `.nspl-name` drops the bottom margin it used to carry on its own -- the
row supplies that spacing now, once, rather than the heading and the row each contributing
some and the total drifting depending on what else sits beside it.
*/
.nspl-title-row { display: flex; flex-wrap: wrap; align-items: center; gap: .6em; margin: 0 0 .35rem; }
/* .nspl-name's own font declaration lives with .nspl-kbyg h3's, further down, so the two
   heading styles cannot drift apart. This section only exists to note that its margin is
   handled by .nspl-title-row above, not repeated here as a second, conflicting value. */
/* Larger, and off the condensed display face onto the body one at semibold (600) --
   "acumin pro regular" here means the non-condensed family, at a weight that still reads
   as address metadata rather than body prose. The pink dot (.nspl-pin) that used to lead
   it is gone from the markup this renders, not just hidden here. */
.nspl .nspl-addr { font-family: var(--nspl-body); font-weight: 600; font-size: .95rem; letter-spacing: .02em; text-transform: none; color: var(--nspl-muted); margin: 0 0 .85rem; display: flex; align-items: center; gap: .5em; flex-wrap: wrap; }
/*
Styled as one of the shared tag pills now (`.np-tag`, in style.css) rather than its own
one-off badge -- no stroke, the body font instead of the condensed display face, the same
shape and padding as a "Perfect For" chip. Only the two colours differ, per the ask: the
ground stays the existing gold wash, and the text becomes a genuinely dark mustard rather
than the pale `--nspl-gold` token, which would have next to no contrast against a wash of
itself.
*/
.nspl-price {
  --np-tag-bg: var(--nspl-gold-wash);
  --np-tag-ink: #8a6b12;
  font-weight: 700;
  font-size: .8rem;
  letter-spacing: .04em;
  border-radius: 999px;
  padding: .3em .9em;
}
/*
`.nspl .nspl-chips`, not the bare class, and that second class is load-bearing.

Kadence's `.single-content ul, .single-content ol { padding-left: 2em }` is one class plus
one element -- (0,1,1) -- which outranked the bare `.nspl-chips` at (0,1,0), so this list
carried a 2em left indent no sibling paragraph had, and the pills started well to the right
of the name/address/blurb text above and below them. Two classes -- (0,2,0) -- beats that
outright regardless of source order. Confirmed live: chips computed `padding-left: 34px`
before this, `0px` after, with every sibling already at 0.
*/
.nspl .nspl-chips { display: flex; flex-wrap: wrap; gap: .45rem; margin: 0 0 1rem; padding: 0; list-style: none; }
/* Font-family only, per the ask -- this is a lead-in label, not a pill, so it does not
   join the shared tag rule below. */
.nspl-chips-lbl { font-family: var(--nspl-body); font-weight: 700; font-size: .68rem; letter-spacing: .14em; color: var(--nspl-navy); text-transform: uppercase; align-self: center; }
/* border, font-family and colour/background now come from the shared ".np-tag, .nspl-chips
   li..." rule in style.css -- this supplies only what is specific to this chip: its two
   colours (the pink wash as the ground, solid pink as the same hue at full opacity) and
   its size/shape, none of which changed.

   Targets the `a` now rather than the `li` itself: perfect_for is a real public taxonomy
   (see register_taxonomy() in listicles.php), so each chip is a link to its own term
   archive, and the pill needs to be what the link's own click/hover target is, not just
   text floating inside a separately-styled li.

   The li itself is flex/align-items:center below because the anchor sits one level deeper
   than the flex items .nspl-chips' own display:flex actually blockifies (that only reaches
   its direct children, the lis, not a grandchild) -- left as a plain, un-blockified inline
   `a`, its padding paints beyond its own line box without the li's height accounting for
   it, so the pill's visible box (padding included) sat off-centre inside the li's own,
   shorter box: confirmed live, the li measured 27px tall against a 22px pill sitting
   4.5px down from its top edge but only 0.6px up from its bottom. Making the li its own
   flex container blockifies the anchor the same way `.nspl-chips` blockifies the li, and
   centres it regardless of what height the li ends up at (its own content, or stretched to
   match a taller sibling row item like `.nspl-chips-lbl`). */
.nspl-chips li:not(.nspl-chips-lbl) {
  display: flex;
  align-items: center;
}
.nspl-chips li:not(.nspl-chips-lbl) a {
  --np-tag-bg: var(--nspl-pink-wash);
  --np-tag-ink: var(--nspl-pink);
  font-weight: 600;
  font-size: .74rem;
  letter-spacing: .04em;
  border-radius: 999px;
  padding: .3em .9em;
  text-decoration: none;
}
/* Hover/focus "raises the opacity" of the wash: --np-tag-bg is that same hue's ink colour
   (--np-tag-ink) diluted down to a pale tint already, so moving the mix further toward the
   full-strength ink is the same effect a true alpha-based wash would get from turning its
   opacity up, without changing the hue itself. */
.nspl-chips li:not(.nspl-chips-lbl) a:hover,
.nspl-chips li:not(.nspl-chips-lbl) a:focus-visible {
  background: color-mix(in srgb, var(--np-tag-ink) 35%, var(--np-tag-bg));
}
.nspl .nspl-blurb { font-family: var(--nspl-body); font-size: 1.02rem; line-height: 1.75; margin: 0; }

/*
No card any more -- no ground, no border, no box padding. Full width of whatever contains
it: the split/stack body column (which has none of its own), or, in a Guide Card, the
card itself rather than the card's padded body.

That second case needed its own rule. `.nspl-spot--card .nspl-body` carries its own side
padding (1.35rem) that every other layout's body does not, and `.nspl-kbyg` -- an ordinary
block child -- inherited that inset like any other content, landing 21px short of the
card's actual edge on each side. Confirmed live: kbyg computed 357px inside a 400px body.
Negative margins matching that padding break it back out to the card's true width; equal
positive padding keeps its own content (icons, the top border) from touching the rounded
corner. Split and stack need no equivalent, since their bodies have no padding to escape.
*/
.nspl-kbyg { margin-top: 1.5rem; padding-top: 1.5rem; border-top: 1px solid var(--nspl-line); }
.nspl-spot--card .nspl-kbyg {
  margin-left: -1.35rem;
  margin-right: -1.35rem;
  padding-left: 1.35rem;
  padding-right: 1.35rem;
}
/*
A container query collapsing this to 2 columns on a narrow card was tried here and reverted:
2 columns is fine for an even item count, but a 3-item list (a common case) leaves the third
item alone on its own row at half the card's width -- which reads as "this isn't using the
full width" even though the grid itself still spans it. A Guide Card is roughly half the
page column even on a wide desktop, so it is never really the "3 columns always" context the
general rule below is for; one column, always, is the one shape that is always full-width
regardless of how many items there are. `.nspl` prefixed on top for the same specificity
reason as elsewhere in this file: `.nspl-spot--card .nspl-kbyg ul` alone ties the general
rule's own specificity, and that rule comes later in the file, so a tie would let it win.
*/
.nspl .nspl-spot--card .nspl-kbyg ul { grid-template-columns: 1fr; }
/*
Font only, shared between `.nspl-name` and `.nspl-kbyg h3` -- "carry the same font styles"
is true by construction, not by two rules kept manually in sync. Margin is deliberately
NOT in this shared declaration, because the two need different values from the start:
`.nspl-name` takes none of its own (`.nspl-title-row` supplies the spacing beside the price
badge instead), and `.nspl-kbyg h3` wants real room below it as a section heading. Each
gets its margin from its own rule below rather than the shared one being overridden twice.
The star that used to sit before the KBYG heading is gone with the card it belonged to: a
decorative icon read right beside a small uppercase label, not beside a heading the size of
an item title.
*/
.nspl .nspl-name,
.nspl .nspl-kbyg h3 { font-family: var(--nspl-disp); font-weight: 800; font-size: 1.55rem; letter-spacing: -.01em; color: var(--nspl-navy); }
.nspl .nspl-name { margin: 0; }
.nspl .nspl-kbyg h3 { margin-bottom: 1rem; }
/*
A literal 3-column grid, always -- not `auto-fit`.

That was tried in between: `repeat(auto-fit, minmax(240px, 1fr))` sized the grid to
whatever space was actually available, which fixed a real, measured problem (three
105px slivers inside a narrow Guide Card) but also meant the column count answered "how
wide is the container" rather than always being 3. Reverted on explicit instruction: 3
columns is the wanted shape regardless of context, with rows following naturally from
however many items there are -- 6 items reads as two full rows of 3.

The tablet/mobile collapse is media queries again for the same reason: a fixed column
count needs a breakpoint to know when to change, which is exactly what a container-fitted
grid does not need and a literal one does. 760px matches the breakpoint this file already
uses elsewhere; 480px is one step narrower, for phones specifically.
*/
.nspl .nspl-kbyg ul { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.1rem 1.5rem; }
@media (max-width: 760px) {
  .nspl .nspl-kbyg ul { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .nspl .nspl-kbyg ul { grid-template-columns: 1fr; }
}
/*
Each item is icon-plus-text now rather than text on a dot bullet. The icon is a real
Feather glyph chosen per item in the editor (`nsp_listicle_kbyg_icons()`), not a fixed
per-position icon, so `.nspl-kbyg-icon` only sizes and colours whatever `<svg>` PHP put
there -- it has no opinion on which icon that is.
*/
.nspl-kbyg li { display: flex; align-items: flex-start; gap: .7rem; font-family: var(--nspl-body); font-size: .92rem; font-weight: 500; line-height: 1.5; color: var(--nspl-ink); }
.nspl-kbyg-icon { flex: none; width: 20px; height: 20px; margin-top: .1em; color: var(--nspl-pink); }
.nspl-kbyg-icon svg { display: block; width: 100%; height: 100%; }
.nspl-kbyg-copy { min-width: 0; }
.nspl-kbyg b { font-weight: 700; color: var(--nspl-navy); }

/*
photos -- fixed 4:3, cropped, at the site's own image corner.

The radius is `var(--np-img-radius)`, promoted to :root in style.css specifically so this
template did not need its own 12px that could drift from the homepage cards' 8px. Ratio and
crop follow the exact mechanism the homepage cards already use: `aspect-ratio` on the
container plus `object-fit: cover` on the `<img>`, so the box holds its shape whatever the
source photo's own dimensions are -- a portrait photo crops rather than stretching the card
taller. The placeholder (`.nspl-ph`, shown when no photo is set) takes the same ratio, so a
missing photo and a real one occupy the same space and nothing reflows once one is added.
*/
.nspl .nspl-photo, .nspl .nspl-ph { position: relative; margin: 0; border-radius: var(--np-img-radius); overflow: hidden; aspect-ratio: 4 / 3; }
.nspl-img { display: block; width: 100%; height: 100%; object-fit: cover; }
.nspl-ph { background: linear-gradient(135deg, #2c3a76, #7ebcc7); display: flex; align-items: center; justify-content: center; }
.nspl-ph span { font-family: var(--nspl-disp); font-weight: 700; font-size: .72rem; letter-spacing: .2em; text-transform: uppercase; color: rgba(255,255,255,.85); border: 1px solid rgba(255,255,255,.55); border-radius: 999px; padding: .4em 1.1em; }
/* The single-photo credit line, small caps under the image -- matches .nspl-caro's own
   credit (below), since a single photo and a carousel are the same component either way. */
.nspl .nspl-credit { font-family: var(--nspl-body); font-size: .74rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--nspl-muted); margin: .6rem 0 0; }

/*
The carousel: CSS scroll-snap, not a hand-built slide engine.

`.nspl-caro-track` is the actual scroller -- `overflow-x: auto` plus `scroll-snap-type`
gets native touch and trackpad swipe with real momentum, on every device, for free.
`listicle.js` only reads the scroll position (to know which slide is current, for the dots
and the caption) and writes it (for the arrow buttons); it never simulates a drag itself.

The `gap` between slides is what "expose the gap between them" asked for: because slides
are laid out with real space between them rather than touching, that space is visible
mid-scroll as one slide moves past and the next arrives, exactly like the reference. It is
also why each slide needs its own `border-radius` (`var(--np-img-radius)`, this site's own
corner rather than the reference's): with visible gaps, every slide is a distinct rounded
tile, not one continuous strip that only needs rounding at its two outer ends.

The scrollbar is hidden (`scrollbar-width: none` / the pseudo-element below) because the
dots already are the position indicator; a native scrollbar under them would be redundant
chrome the reference does not have either.
*/
.nspl-caro { position: relative; }
.nspl-caro-track {
  display: flex;
  gap: 14px;
  aspect-ratio: 4 / 3;
  overflow-x: auto;
  /* Explicit, not left to default: the CSS overflow spec computes a lone `visible` axis up
     to `auto` whenever its other axis is non-visible, so leaving this unset was silently
     making the track scrollable vertically too -- no slide is ever taller than the track,
     but trackpads still rubber-band/scroll on that phantom auto axis. Hidden here since
     there is nothing to ever scroll in this direction. */
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.nspl-caro-track::-webkit-scrollbar { display: none; }
.nspl-slide { position: relative; flex: 0 0 100%; scroll-snap-align: center; margin: 0; height: 100%; border-radius: var(--np-img-radius); overflow: hidden; }
.nspl-slide .nspl-img { width: 100%; height: 100%; }
/*
The mobile "peek": each slide gives back a sliver of its own width, so the next slide's
edge shows past the right side of the viewport -- the visual hint to swipe the reference
uses. 92% rather than 100% at this width only; desktop keeps a clean single full-width
slide, matching the reference there too.
*/
@media (max-width: 640px) {
  .nspl-slide { flex-basis: 92%; }
}

/*
The pill: one control, not three floating pieces. `.nspl-caro-nav-bar` is the whole white
shape -- both arrows and the dots sit inside it with no background or shadow of their own,
so the group reads as a single object overlaid on the image, matching the reference.
*/
.nspl-caro-nav-bar {
  position: absolute;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  z-index: 1;
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .35rem .55rem;
  background: #fff;
  border-radius: 999px;
  box-shadow: 0 4px 14px rgba(0,0,0,.22);
}
.nspl-caro-nav { display: flex; align-items: center; justify-content: center; width: 26px; height: 26px; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--nspl-navy); cursor: pointer; }
.nspl-caro-nav svg { display: block; width: 17px; height: 17px; }
.nspl-caro-nav:hover, .nspl-caro-nav:focus-visible { background: rgba(30,41,91,.08); }
/* Kadence ships a global `button:focus` ring (its own accessibility default) that fires on
   every mouse click, not just keyboard focus, and it doesn't match this pill at all -- a
   square-ish outline flashing on a 26px circle. `.nspl-caro-nav:focus` is two classes'
   worth of specificity (the pseudo-class counts as one) against Kadence's bare
   `button:focus`, so this wins outright without `!important`. The real, keyboard-only
   indicator below is untouched. */
.nspl-caro-nav:focus { outline: none; box-shadow: none; }
.nspl-caro-nav:focus-visible { outline: 2px solid var(--nspl-navy); outline-offset: 2px; }
.nspl-caro-dots { display: flex; align-items: center; gap: .4rem; }
.nspl-caro-dots i { width: 7px; height: 7px; border-radius: 50%; background: #d8d8dc; }
.nspl-caro-dots i.on { background: var(--nspl-navy); }
/* The caption under the pill, kept current by listicle.js as the reader scrolls -- see the
   PHP renderer for why this is one shared element rather than one per slide. Reserves its
   line height even when the current slide has no credit, so the pill above does not jump
   up and down as the reader moves between captioned and uncaptioned photos. */
.nspl .nspl-credit--caro { min-height: 1.2em; text-align: center; margin-top: .7rem; }

/* ---------- split rows ---------- */
.nspl-group--split .nspl-spot--split { display: grid; grid-template-columns: 1fr 1fr; gap: 2.25rem; align-items: start; padding: 2.5rem 0; }
.nspl-group--split .nspl-spot--split + .nspl-spot--split { border-top: 1px solid var(--nspl-line); }
.nspl-group--split .nspl-spot--split:nth-child(even) .nspl-media { order: 2; }
/*
KBYG is a direct grid child here, a sibling of .nspl-media and .nspl-body rather than
nested inside the body -- see nsp_listicle_render_item() -- which is what makes
`grid-column: 1 / -1` meaningful: it spans both of the spot's columns, not just the one
its parent happens to occupy. Nested inside .nspl-body it could only ever be as wide as
that column, which was the actual cause of "KBYG needs to be 100% width".

`order: 3` is not decorative. Media takes `order: 2` on even rows to flip left/right, and
with no order of its own KBYG (order 0, same as the un-flipped body) would sort *between*
the body and the flipped media on those rows instead of staying below both -- order ties
fall back to source position, and only media has been pulled out of that position. A
number higher than either guarantees last regardless of which row this is.
*/
.nspl-group--split .nspl-spot--split > .nspl-kbyg { grid-column: 1 / -1; order: 3; }
@media (max-width: 760px) {
  .nspl-group--split .nspl-spot--split { grid-template-columns: 1fr; padding: 2rem 0; }
  .nspl-group--split .nspl-spot--split:nth-child(even) .nspl-media { order: 0; }
}

/* ---------- editorial stack ---------- */
/*
No width cap here any more -- it had one (720px) while Split Rows and Guide Cards had
none, which is why a Stack-layout spot ("Heritage Park") rendered visibly narrower than
its neighbours despite all three sharing the same page column. It also contradicted this
layout's own admin label, "Editorial Stack (full-width photo)": a photo inside a
720px-capped group can never actually be full width. Every group now stretches to the
same 100% of .content-container that the other two already did.
*/
.nspl-spot--stack { padding: 2.75rem 0; }
.nspl-spot--stack + .nspl-spot--stack { border-top: 1px solid var(--nspl-line); }
.nspl-spot--stack .nspl-media { margin-bottom: 1.4rem; }
/* .nspl-kbyg h3 tracks .nspl-name here too, not a separately-chosen matching value -- one
   rule, so a future size change to either can't drift the two apart again. */
.nspl-spot--stack .nspl-name,
.nspl-spot--stack .nspl-kbyg h3 { font-size: 1.8rem; }
/*
On mobile only, Stack's title drops back to the shared 1.55rem base -- the same size Split
Rows titles already are there, since Split has no size override of its own at any width.
1.8rem was sized for Stack's full-bleed desktop photo; at a phone's own width that gap next
to Split, sitting in the very same page column, reads as inconsistent rather than
intentional. Desktop keeps the two visually distinct sizes untouched -- this is a
mobile-only correction, not a change to the general rule above.
*/
@media (max-width: 767px) {
  .nspl-spot--stack .nspl-name,
  .nspl-spot--stack .nspl-kbyg h3 { font-size: 1.55rem; }
}

/* ---------- guide cards ---------- */
.nspl-group--card { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; padding: 2rem 0 2.5rem; }
@media (max-width: 760px) { .nspl-group--card { grid-template-columns: 1fr; } }
.nspl-spot--card { border: 1px solid var(--nspl-line); border-radius: 14px; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 6px 18px rgba(30,41,91,.07); }
/*
Inset ~7px from the card edge instead of flush, and a shorter box than the plain 4:3 the
other layouts use -- 4:3 at a Guide Card's own width (roughly half the page, in a 2-column
grid) still ran fairly tall for a compact card. 3:2 keeps the crop shallower without
reintroducing the old problem of an unbounded height driven by the source photo.

The inset itself is padding on `.nspl-media`, not a margin on the photo/caro: padding
keeps `.nspl-media`'s own border-radius (matching the card's 14px, `overflow: hidden`)
doing the rounding at the *outer* edge, while the photo underneath keeps its own smaller
`--np-img-radius` -- two concentric radii, the outer one from the card context and the
inner one the same value every other image on the site uses.
*/
.nspl-spot--card .nspl-media { padding: 7px; border-radius: 14px; overflow: hidden; }
/* The carousel's ratio now lives on its inner track, not the outer .nspl-caro, so the
   override has to reach that element specifically -- .nspl-caro itself no longer has an
   aspect-ratio of its own to override. */
.nspl-spot--card .nspl-photo,
.nspl-spot--card .nspl-ph,
.nspl-spot--card .nspl-caro-track { aspect-ratio: 3 / 2; }
.nspl-spot--card .nspl-body { padding: 1.25rem 1.35rem 1.5rem; }
/* Same reasoning as the Stack override above: .nspl-kbyg h3 shares this value rather than
   sitting at the unrelated 1.55rem base every other layout was overriding it away from. */
.nspl-spot--card .nspl-name,
.nspl-spot--card .nspl-kbyg h3 { font-size: 1.3rem; }

/*
The flip: a Guide Card's write-up, Know Before You Go and link buttons live on a second
face, revealed by rotating the *whole card* 180deg in 3D rather than growing it to fit
everything at once.

The card's own chrome -- border, radius, the clip that rounds the photo's top corners,
the shadow -- moves from the outer `.nspl-spot--card` onto each `.nspl-flip-face` instead
of staying on the outer article. That is what makes the *card* look like it is rotating
(border, shadow and all) rather than a flat sheet of content spinning inside a card frame
that never moves: the outer article becomes a plain, invisible perspective box, and each
face is a complete card in its own right, one showing at a time.

`perspective` sits on the article itself; each face rotates independently rather than
sharing one rotating wrapper (front turns 0deg -> 180deg, back turns 180deg -> 360deg,
`backface-visibility` hiding whichever one is edge-on at any moment) -- there is
deliberately no `.nspl-flip-inner` any more. An earlier version routed both faces through
one such wrapper (`transform-style: preserve-3d` + a single rotation on the wrapper) so
they could share a CSS Grid cell for sizing, but that wrapper sat between the article and
the grid stretching it, and getting its own height to reliably track the article's
stretched height -- through a flex box, a percentage, whatever was tried -- never worked
consistently (confirmed live: two cards with identical CSS computing two different
heights). Making the article itself `display: grid` and putting both faces directly in its
one cell removes that middle layer entirely: they are stretched by the exact same
`align-items: stretch` this file already uses one level up for `.nspl-group--card`, with no
intermediate box for a stretch to get lost in.
*/
.nspl-spot--card.nspl-spot--flip {
  position: relative;
  border: 0;
  border-radius: 0;
  overflow: visible;
  box-shadow: none;
  perspective: 1600px;
  display: grid;
}
.nspl-flip-face {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: #fff;
  border: 1px solid var(--nspl-line);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 6px 18px rgba(30,41,91,.07);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transition: transform .6s cubic-bezier(.4, .2, .2, 1);
  transform: rotateY(0deg);
}
.nspl-flip-back { transform: rotateY(180deg); }
.nspl-spot--flip.is-flipped .nspl-flip-front { transform: rotateY(180deg); }
.nspl-spot--flip.is-flipped .nspl-flip-back { transform: rotateY(360deg); }
/* Keeps the hidden face from intercepting clicks/taps meant for the visible one mid-flip
   and while settled -- backface-visibility alone hides it visually but not from hit-testing
   in every browser. */
.nspl-spot--flip:not(.is-flipped) .nspl-flip-back,
.nspl-spot--flip.is-flipped .nspl-flip-front { visibility: hidden; }
/* Both faces' bodies are flex columns now so `.nspl-flip-btn`'s own `margin-top: auto` can
   push it to the bottom of the card regardless of how much copy sits above it, on either
   face, rather than trailing wherever the content happens to end. */
.nspl-flip-front .nspl-body,
.nspl-flip-back .nspl-body { display: flex; flex-direction: column; flex: 1; }
.nspl-flip-btn {
  margin-top: auto;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: .4em;
  font-family: var(--nspl-body);
  font-weight: 700;
  font-size: .78rem;
  letter-spacing: .04em;
  color: #fff;
  background: var(--nspl-pink);
  border: 1.5px solid var(--nspl-pink);
  border-radius: 999px;
  padding: .5em 1.1em;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.nspl-flip-btn svg { width: 14px; height: 14px; flex: none; }
.nspl-flip-btn:hover, .nspl-flip-btn:focus-visible { color: #fff; background: var(--nspl-navy); border-color: var(--nspl-navy); }
.nspl-flip-btn:focus { outline: none; }
.nspl-flip-btn:focus-visible { outline: 2px solid var(--nspl-navy); outline-offset: 2px; }

/*
Website/map link buttons -- optional, per spot. One filled (the primary action, whichever
was filled in first) and one outlined, matching the ghost-button pairing already used
elsewhere on the site rather than inventing a third button style.
*/
.nspl-links { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.1rem; }
.nspl-btn {
  display: inline-flex;
  align-items: center;
  font-family: var(--nspl-body);
  font-weight: 700;
  font-size: .85rem;
  letter-spacing: .01em;
  text-decoration: none;
  color: #fff;
  background: var(--nspl-navy);
  border: 1.5px solid var(--nspl-navy);
  border-radius: 999px;
  padding: .55em 1.3em;
  transition: opacity .15s;
}
/* Kadence's own `a:hover, a:focus, a:active { color: var(--global-palette-highlight-alt) }`
   is (0,1,1) and would otherwise win over a single `.nspl-btn` class on click -- named
   explicitly here, same fix as everywhere else on the site a plain-class link ran into it. */
.nspl-btn:hover, .nspl-btn:focus-visible, .nspl-btn:active { opacity: .85; color: #fff; }
.nspl-btn--ghost { color: var(--nspl-navy); background: transparent; }
.nspl-btn--ghost:hover, .nspl-btn--ghost:focus-visible, .nspl-btn--ghost:active { color: var(--nspl-navy); background: rgba(30,41,91,.06); opacity: 1; }

/* ---------- map band ---------- */
.nspl-map-band { background: var(--nspl-band); border-radius: 14px; padding: 2.5rem 2rem 2.75rem; margin: 2.5rem 0 1rem; }
.nspl .nspl-map-band h2 { font-family: var(--nspl-disp); font-weight: 800; font-size: 1.5rem; color: var(--nspl-navy); margin: 0 0 1.25rem; text-align: center; }
.nspl-map { position: relative; height: 300px; border-radius: 12px; border: 1px solid #d3dde6; background:
    linear-gradient(#dfe7ee 1px, transparent 1px) 0 0 / 40px 40px,
    linear-gradient(90deg, #dfe7ee 1px, transparent 1px) 0 0 / 40px 40px,
    linear-gradient(160deg, #eef4f8, #e2ecf2);
  display: flex; align-items: center; justify-content: center; }
.nspl-map-note { font-family: var(--nspl-disp); font-weight: 700; font-size: .72rem; letter-spacing: .2em; text-transform: uppercase; color: var(--nspl-muted); border: 1px solid #c6d3dd; border-radius: 999px; padding: .4em 1.1em; background: #fff; }
.nspl-map-legend { display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; justify-content: center; margin-top: 1.1rem; }
.nspl-map-legend span { font-family: var(--nspl-disp); font-weight: 600; font-size: .82rem; color: var(--nspl-navy); }
.nspl-map-legend b { color: var(--nspl-pink); }
.nspl-map-legend em { font-style: normal; color: var(--nspl-muted); font-weight: 500; }

