/*
Theme Name: Fireplace Stop North
Theme URI: https://fireplacestopnorth.com
Author: Web Conductors
Author URI: https://webconductors.com
Description: Editorial block theme for The Fireplace Stop North — a destination hearth, hot tub and outdoor showroom in Seguin, Ontario. Ported from the approved Lovable design: Fraunces/Inter, stop-sign red on near-black, live-burn photography.
Requires at least: 6.5
Tested up to: 6.9
Requires PHP: 7.4
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: fireplace-stop-north
Tags: full-site-editing, block-patterns, editorial, one-column, custom-colors, custom-logo, block-styles
*/

/* ---------------------------------------------------------------------------
   Everything global lives in theme.json. This file carries only the effects
   that theme.json cannot express: keyframe animation, the grain overlay, and
   the hover treatments the approved design depends on.
   --------------------------------------------------------------------------- */

/* --- Micro label ---------------------------------------------------------- */
/* The 0.18em uppercase eyebrow used above almost every heading in the design. */
.fpsn-eyebrow {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--micro);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 600;
  line-height: 1.4;
}

/* A short rule that sits before eyebrow text on dark hero sections. */
.fpsn-eyebrow--ruled::before {
  content: "";
  display: inline-block;
  width: 32px;
  height: 1px;
  margin-right: 12px;
  vertical-align: middle;
  background: var(--wp--preset--color--accent);
}

/* --- Ember glow ----------------------------------------------------------- */
/* Lift + red bloom on hover. Applied to feature cards and primary buttons.    */
.fpsn-ember-glow,
.fpsn-ember-glow .wp-block-button__link {
  transition:
    box-shadow 600ms var(--wp--custom--transition),
    transform 600ms var(--wp--custom--transition);
}

@media (hover: hover) {
  .fpsn-ember-glow:hover,
  .fpsn-ember-glow:focus-within,
  .fpsn-ember-glow .wp-block-button__link:hover {
    box-shadow: var(--wp--preset--shadow--glow);
    transform: translateY(-2px);
  }
}

/* --- Slow zoom on image cards --------------------------------------------- */
.fpsn-zoom-card {
  overflow: hidden;
  position: relative;
}

.fpsn-zoom-card img,
.fpsn-zoom-card .wp-block-cover__image-background {
  transition: transform 1500ms var(--wp--custom--transition);
}

@media (hover: hover) {
  .fpsn-zoom-card:hover img,
  .fpsn-zoom-card:hover .wp-block-cover__image-background,
  .fpsn-zoom-card:focus-within img,
  .fpsn-zoom-card:focus-within .wp-block-cover__image-background {
    transform: scale(1.05);
  }
}

/* The showroom cards sit at dimRatio 20 so the photography stays bright, which
   leaves their 11px captions measuring ~2.2:1 against the lighter frames — the
   one contrast finding on this page that comes from real rendered pixels rather
   than from a detector guessing at an ancestor's background.

   A scrim anchored to the bottom edge fixes the caption without darkening the
   photograph, which raising dimRatio would have done. */
.fpsn-zoom-card::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 60%;
  background: linear-gradient(to top, rgb(20 20 20 / 0.78), rgb(20 20 20 / 0.34) 42%, transparent);
  pointer-events: none;
  z-index: 1;
}

/* Core gives the inner container z-index 1; the scrim must sit under the text,
   not over it. */
.fpsn-zoom-card > .wp-block-cover__inner-container {
  position: relative;
  z-index: 2;
}

/* --- Film grain ----------------------------------------------------------- */
/* Sits over dark editorial bands so large black fields don't read as flat.    */
.fpsn-grain {
  position: relative;
  isolation: isolate;
}

.fpsn-grain::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

.fpsn-grain > * {
  position: relative;
  z-index: 1;
}

/* --- Brand marquee -------------------------------------------------------- */
/* Two counter-scrolling rows of brand names. The track is duplicated in the
   pattern markup, so translating -50% produces a seamless loop.               */
.fpsn-marquee {
  position: relative;
  overflow: hidden;
}

.fpsn-marquee::before,
.fpsn-marquee::after {
  content: "";
  position: absolute;
  inset-block: 0;
  width: clamp(48px, 10vw, 128px);
  z-index: 2;
  pointer-events: none;
}

.fpsn-marquee::before {
  left: 0;
  background: linear-gradient(to right, var(--wp--preset--color--background), transparent);
}

.fpsn-marquee::after {
  right: 0;
  background: linear-gradient(to left, var(--wp--preset--color--background), transparent);
}

.fpsn-marquee__track {
  display: flex;
  align-items: center;
  gap: 48px;
  width: max-content;
  padding-inline: 32px;
  white-space: nowrap;
  will-change: transform;
}

.fpsn-marquee__track > * {
  flex: 0 0 auto;
  font-family: var(--wp--preset--font-family--display);
  font-weight: 600;
  color: color-mix(in srgb, var(--wp--preset--color--foreground) 75%, transparent);
}

.fpsn-marquee__track--forward {
  animation: fpsn-marquee 50s linear infinite;
  font-size: clamp(1.5rem, 3vw, 2.25rem);
}

.fpsn-marquee__track--reverse {
  animation: fpsn-marquee-reverse 65s linear infinite;
  font-size: clamp(1.25rem, 2.4vw, 1.875rem);
  font-style: italic;
  opacity: 0.72;
}

@keyframes fpsn-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

@keyframes fpsn-marquee-reverse {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0); }
}

/* --- Scroll reveal -------------------------------------------------------- */
.fpsn-fade-up {
  animation: fpsn-fade-up 1s var(--wp--custom--transition) both;
}

@keyframes fpsn-fade-up {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* --- Ember pulse (the "open now" dot) ------------------------------------- */
.fpsn-ember-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--wp--preset--color--accent);
  animation: fpsn-ember 4s ease-in-out infinite;
}

@keyframes fpsn-ember {
  0%, 100% { opacity: 0.85; }
  50%      { opacity: 1; }
}

/* --- Reduced motion ------------------------------------------------------- */
/* Honour the OS setting: stop the marquee, the reveal and the hover lift.     */
@media (prefers-reduced-motion: reduce) {
  .fpsn-marquee__track--forward,
  .fpsn-marquee__track--reverse,
  .fpsn-fade-up,
  .fpsn-ember-dot {
    animation: none !important;
  }

  .fpsn-marquee__track {
    transform: none !important;
  }

  .fpsn-zoom-card img,
  .fpsn-zoom-card .wp-block-cover__image-background,
  .fpsn-ember-glow,
  .fpsn-ember-glow .wp-block-button__link {
    transition: none !important;
  }

  .fpsn-ember-glow:hover,
  .fpsn-zoom-card:hover img {
    transform: none !important;
  }
}

/* --- Editorial helpers ---------------------------------------------------- */
/* A 2px accent rule above a column — used in the split Wellness/Outdoor band. */
.fpsn-rule-top {
  border-top: 2px solid var(--wp--preset--color--accent);
}

/* Left accent rule for the brand-heritage list. */
.fpsn-rule-left {
  border-left: 2px solid var(--wp--preset--color--accent);
}

/* Big decorative opening quote mark. */
.fpsn-quotemark {
  font-family: var(--wp--preset--font-family--display);
  font-size: clamp(3rem, 6vw, 4.5rem);
  line-height: 0.6;
  color: var(--wp--preset--color--accent);
}

/* Keeps hero copy readable over photography regardless of the image beneath. */
.fpsn-hero__scrim {
  background: linear-gradient(180deg, rgba(0,0,0,0.15) 0%, rgba(0,0,0,0.55) 55%, rgba(0,0,0,0.85) 100%);
}

/* --- Accessibility -------------------------------------------------------- */
.fpsn-skip-link:focus {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 100000;
  padding: 12px 20px;
  background: var(--wp--preset--color--primary);
  color: var(--wp--preset--color--primary-foreground);
  text-decoration: none;
}

/* Give every interactive element a visible focus ring on dark bands. */
.has-primary-background-color :focus-visible,
.has-secondary-background-color :focus-visible {
  outline: 2px solid var(--wp--preset--color--accent);
  outline-offset: 2px;
}

/* --- Brand detail meta ---------------------------------------------------- */
.fpsn-brand-details {
  display: grid;
  gap: var(--wp--preset--spacing--50);
}

.fpsn-brand-details__label {
  margin: 0;
  color: var(--wp--preset--color--accent);
}

.fpsn-brand-details__highlights {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px var(--wp--preset--spacing--50);
  margin: calc(var(--wp--preset--spacing--40) * -1 + 12px) 0 0;
  padding: 0;
  list-style: none;
}

.fpsn-brand-details__highlights li {
  padding-left: 20px;
  position: relative;
  line-height: 1.6;
}

.fpsn-brand-details__highlights li::before {
  content: "\25C6"; /* ◆ — the marquee's separator, reused as the bullet */
  position: absolute;
  left: 0;
  font-size: 0.6em;
  top: 0.55em;
  color: var(--wp--preset--color--accent);
}

.fpsn-brand-details__models {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--wp--preset--spacing--40);
  margin-top: calc(var(--wp--preset--spacing--40) * -1 + 12px);
}

.fpsn-brand-details__model {
  padding-top: var(--wp--preset--spacing--30);
  border-top: 1px solid var(--wp--preset--color--hairline);
}

.fpsn-brand-details__model-name {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--large);
  font-weight: 600;
  margin: 0 0 4px;
}

.fpsn-brand-details__model-meta {
  font-size: var(--wp--preset--font-size--micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--wp--preset--color--muted-foreground);
  margin: 0 0 10px;
}

.fpsn-brand-details__model-blurb {
  margin: 0;
  line-height: 1.6;
  color: var(--wp--preset--color--muted-foreground);
}

.fpsn-brand-details__note {
  margin: 0;
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--preset--color--muted-foreground);
}

/* --- Marquee separator ---------------------------------------------------- */
.fpsn-marquee__dot {
  font-size: 0.4em;
  color: var(--wp--preset--color--accent);
  transform: translateY(-0.35em);
}

/* --- Brand archive card --------------------------------------------------- */
.fpsn-brand-card {
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: var(--wp--preset--spacing--30);
  border-top: 1px solid var(--wp--preset--color--hairline);
  transition: border-color 300ms var(--wp--custom--transition);
}

.fpsn-brand-card:hover {
  border-top-color: var(--wp--preset--color--accent);
}

/* --- Trust bar ------------------------------------------------------------ */
/* Vertical rules between items on desktop only; they read as clutter stacked. */
@media (min-width: 782px) {
  .fpsn-trustbar .wp-block-column + .wp-block-column {
    border-left: 1px solid var(--wp--preset--color--hairline);
    padding-left: var(--wp--preset--spacing--40);
  }
}

@media (max-width: 781px) {
  .fpsn-trustbar {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: var(--wp--preset--spacing--30);
  }
}

/* --- Install gallery ------------------------------------------------------ */
/* CSS columns give a true masonry flow without JS or a layout library.       */
.fpsn-installs__head {
  max-width: 62ch;
  margin-bottom: var(--wp--preset--spacing--60);
}

.fpsn-installs__eyebrow {
  color: var(--wp--preset--color--accent);
  margin: 0 0 var(--wp--preset--spacing--20);
}

.fpsn-installs__heading {
  margin: 0 0 var(--wp--preset--spacing--30);
  font-size: var(--wp--preset--font-size--display-s);
}

.fpsn-installs__intro {
  margin: 0;
  line-height: 1.7;
  color: var(--wp--preset--color--muted-foreground);
}

.fpsn-installs__grid {
  columns: 2;
  column-gap: 12px;
}

@media (min-width: 782px) {
  .fpsn-installs__grid { columns: 3; }
}

@media (min-width: 1100px) {
  .fpsn-installs__grid { columns: 4; }
}

.fpsn-installs__item {
  margin: 0 0 12px;
  break-inside: avoid;
  overflow: hidden;
  background: var(--wp--preset--color--muted);
  border: 1px solid var(--wp--preset--color--hairline);
}

.fpsn-installs__item img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform 500ms var(--wp--custom--transition);
}

@media (hover: hover) {
  .fpsn-installs__item:hover img { transform: scale(1.02); }
}

@media (prefers-reduced-motion: reduce) {
  .fpsn-installs__item img { transition: none !important; }
  .fpsn-installs__item:hover img { transform: none !important; }
}

.fpsn-installs__count {
  margin: var(--wp--preset--spacing--40) 0 0;
  color: var(--wp--preset--color--muted-foreground);
}

/* Dark surface variant */
.has-primary-background-color .fpsn-installs__item {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.12);
}

.has-primary-background-color .fpsn-installs__intro,
.has-primary-background-color .fpsn-installs__count {
  color: rgba(255, 255, 255, 0.72);
}

/* --- Headings that are links ---------------------------------------------- */
/* theme.json colours every link with the accent red. On a heading sitting over
   photography that turns the card title red and nearly illegible, so headings
   keep their own colour and signal interactivity with an underline instead. */
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
.wp-block-post-title a,
.wp-block-heading a {
  color: inherit;
  text-decoration: none;
}

h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
.wp-block-post-title a:hover,
.wp-block-heading a:hover,
h1 a:focus-visible, h2 a:focus-visible, h3 a:focus-visible,
h4 a:focus-visible, h5 a:focus-visible, h6 a:focus-visible,
.wp-block-post-title a:focus-visible,
.wp-block-heading a:focus-visible {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.14em;
  text-decoration-color: var(--wp--preset--color--accent);
}

/* Card titles on photography need a little weight behind them. */
.wp-block-cover .wp-block-heading {
  text-shadow: 0 1px 24px rgba(0, 0, 0, 0.45);
}

/* --- Eyebrows over photography -------------------------------------------- */
/* The accent red is a 0.7rem uppercase label at 0.18em tracking. Over a photo
   that fails contrast badly, so inside a cover the eyebrow goes white and the
   brand colour survives in the rule mark instead. WP's colour classes are
   !important, hence the override. */
.wp-block-cover .fpsn-eyebrow.has-accent-color,
.wp-block-cover .fpsn-eyebrow.has-primary-foreground-color {
  color: #ffffff !important;
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6);
}

/* Body copy over a photo gets the same treatment. */
.wp-block-cover p.has-primary-foreground-color {
  text-shadow: 0 1px 16px rgba(0, 0, 0, 0.5);
}

/* --- Full-bleed layout ---------------------------------------------------- */
/* One gutter value, matching theme.json's root padding. Covers do not pick up
   WordPress's root-padding variable reliably when nested inside <main>, so the
   gutter is applied explicitly rather than left to inheritance. */
:root {
  --fpsn-gutter: clamp(24px, 5vw, 64px);
}

.wp-block-cover.alignfull {
  /* Core gives cover a default horizontal padding that stacks with the gutter
     below and pushes hero copy 16px right of every other section. */
  padding-left: 0;
  padding-right: 0;
}

.wp-block-cover.alignfull > .wp-block-cover__inner-container {
  padding-left: var(--fpsn-gutter);
  padding-right: var(--fpsn-gutter);
  box-sizing: border-box;
}

/* Header, main and footer each carry their own padding, so the inherited stack
   gap just opens a white seam between full-bleed bands. */
.wp-site-blocks > main,
.wp-site-blocks > footer {
  margin-block-start: 0;
}

/* Sections inside main butt directly against each other for the same reason. */
main > .wp-block-group > * + *,
main > .wp-block-cover + *,
main > * + * {
  margin-block-start: 0;
}

/* --- Navigation breakpoint ------------------------------------------------- */
/* Core collapses the nav to an overlay only below 600px. With five items, a
   submenu and a CTA button, this nav wraps onto two lines well before that, so
   the overlay takes over below 1024px instead. */
@media (max-width: 1023px) {
  .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
    display: none;
  }

  .wp-block-navigation__responsive-container-open:not(.always-shown) {
    display: flex;
  }

  .wp-block-navigation__responsive-container.is-menu-open {
    display: flex;
    padding-top: var(--wp--preset--spacing--60);
  }

  /* The quote CTA STAYS on mobile. It is the primary conversion action and a
     binding acceptance criterion (one click from every page), so it must never
     be hidden behind the hamburger. It just gets tighter. */
  .fpsn-header__right > .wp-block-buttons .wp-block-button__link {
    padding: 12px 18px;
    font-size: 0.875rem;
  }
}

@media (max-width: 480px) {
  .fpsn-header__right > .wp-block-buttons .wp-block-button__link {
    padding: 11px 14px;
    font-size: 0.8125rem;
  }
}

/* Give the overlay menu the theme's type rather than core's default. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
  gap: var(--wp--preset--spacing--30);
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--xx-large);
  font-weight: 600;
  letter-spacing: -0.015em;
}

/* --- Accent on dark surfaces ---------------------------------------------- */
/* #df1616 on #141414 is 3.7:1 — below WCAG AA for the 11px eyebrow labels and
   the footer links. A lighter tint of the same hue clears 4.5:1 while staying
   unmistakably the brand red. Applied only where the ground is near-black. */
:root {
  --fpsn-accent-on-dark: hsl(0 82% 65%); /* #ef5d5d — 5.6:1 on #141414 */
}

.has-primary-background-color .has-accent-color,
.has-secondary-background-color .has-accent-color,
.fpsn-footer .has-accent-color,
.fpsn-footer a,
.has-primary-background-color a:not(.wp-block-button__link),
.has-secondary-background-color a:not(.wp-block-button__link) {
  color: var(--fpsn-accent-on-dark) !important;
}

.fpsn-footer a:hover,
.has-primary-background-color a:not(.wp-block-button__link):hover {
  color: #ffffff !important;
  text-decoration: underline;
}

/* Headings that are links stay on the heading colour even on dark bands. */
.has-primary-background-color .wp-block-heading a,
.fpsn-footer .wp-block-heading a {
  color: inherit !important;
}

/* ============================================================================
   BRAND MARKS
   The roster is the client's borrowed credibility: a visitor is meant to
   RECOGNISE Jotul, Big Green Egg or Beachcomber on sight, which a mark does in
   about 200ms and a name set in type does not. Any brand we hold no mark for
   falls back to its name, so a gap degrades to readable rather than to a hole.

   Note this strip sits on WHITE, so marks are normalised DOWN to near-black
   with brightness(0) — no invert. Inverting here would erase them.
   ========================================================================== */
.fpsn-brand-mark {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
}

.fpsn-brand-mark img {
  height: clamp(24px, 2.6vw, 38px);
  width: auto;
  display: block;
  filter: brightness(0) opacity(0.62);
  transition: filter 300ms ease, opacity 300ms ease;
}

/* A mark built as a solid coloured SHAPE with its lettering knocked out of it
   cannot be normalised: flattening Enviro's red oval to black yields a
   featureless blob. Those keep their own colour and simply sit back at rest. */
.fpsn-brand-mark.is-colour img {
  filter: none;
  /* 0.88, not the 0.62 used for normalised marks. These sit at their own
     luminance rather than the band's, and the lightest of them (Fireplace
     Xtrordinair, ~2.1:1 against white before any fade) washes out entirely if
     it is dimmed as hard as the dark line-art marks are. */
  opacity: 0.88;
}

/* The name fallback should read as a peer of the marks, not as a heading. */
.fpsn-brand-mark--name {
  font-family: var(--wp--preset--font-family--display);
  font-weight: 600;
  font-size: clamp(1.1rem, 1.9vw, 1.55rem);
  color: color-mix(in srgb, var(--wp--preset--color--foreground) 62%, transparent);
}

@media (hover: hover) and (pointer: fine) {
  .fpsn-marquee:hover .fpsn-brand-mark img { filter: brightness(0) opacity(0.8); }
  .fpsn-marquee:hover .fpsn-brand-mark.is-colour img { filter: none; opacity: 0.9; }
  .fpsn-brand-mark:hover img { filter: none; opacity: 1; }
}

/* The track sets a display font size for the name fallbacks; a mark must not
   inherit it or the line-box grows and the two rows drift out of rhythm. */
.fpsn-marquee__track > .fpsn-brand-mark { font-size: 0; line-height: 0; }
.fpsn-marquee__track > .fpsn-brand-mark--name { font-size: clamp(1.1rem, 1.9vw, 1.55rem); line-height: 1.1; }

@media (prefers-reduced-motion: reduce) {
  .fpsn-brand-mark img { transition: none; }
}

/* The brand-mark block as used on a page, rather than inside the marquee. */
.fpsn-brand-mark-block .fpsn-brand-mark img {
  height: var(--fpsn-mark-h, 40px);
}

/* On the dark brand header the marks must be lifted to white, the opposite of
   the white marquee band. Colour-forward marks are exempt in both directions. */
.fpsn-brand-mark-block.is-on-dark .fpsn-brand-mark img {
  filter: brightness(0) invert(1) opacity(0.9);
}

.fpsn-brand-mark-block.is-on-dark .fpsn-brand-mark.is-colour img {
  filter: none;
  opacity: 1;
}

/* The mark band keeps its height even when we hold no artwork for that brand,
   so one missing logo does not pull a card out of line with the rest of the
   roster grid. */
.fpsn-brand-mark-block {
  display: flex;
  align-items: center;
  min-height: var(--fpsn-mark-h, 40px);
}
