/* ==========================================================================
   ATMOSPHERE — photography, texture, and ambient motion
   --------------------------------------------------------------------------
   Everything in this file is decorative. It must never carry information, and
   every piece of it has to survive being switched off by prefers-reduced-motion
   without the layout moving. Photography is Pexels; each band gets a heavy teal
   duotone wash so a stock photo still reads as this brand rather than as stock.
   ========================================================================== */

/* ==========================================================================
   1. PHOTO BANDS
   A .band-bg sits as the first child of a .hero / .page-head. It is its own
   element (rather than a pseudo-element) so the parallax can transform it
   without fighting the glow already living on ::before.
   ========================================================================== */

.hero,
.page-head {
  /* Soft postcard curve along the bottom of every coloured band. The band
     already has overflow:hidden, so the photo follows the curve too. */
  border-bottom-left-radius: 50% 42px;
  border-bottom-right-radius: 50% 42px;
}

.band-bg {
  position: absolute;
  inset: -12% 0 -12% 0;   /* overscan so parallax never exposes an edge */
  z-index: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  will-change: transform;
  pointer-events: none;
}

/* Halftone screen over the photograph.
   NOTE: this lives on .band-bg::before deliberately. .hero and .page-head both
   already use their own ::before for the radial glow, and putting a second
   ::before rule on those elements merges the two declaration blocks into one
   pseudo-element — the glow's border-radius:50% and fixed width would turn the
   dot screen into a circle. The photo layer's ::before is free, and it is
   where the dots belong anyway. */
.band-bg::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background-image: radial-gradient(circle, rgba(8,26,30,.34) 1px, transparent 1.1px);
  background-size: 6px 6px;
  opacity: .38;
  -webkit-mask-image: linear-gradient(to bottom, #000, rgba(0,0,0,.25) 70%, transparent);
          mask-image: linear-gradient(to bottom, #000, rgba(0,0,0,.25) 70%, transparent);
}

/* The duotone wash. Teal body, warm amber light thrown in from the top right
   so the photo picks up the brand's own light rather than the photographer's. */
.band-bg::after {
  z-index: 2;
  content: "";
  position: absolute;
  inset: 0;
  background:
    /* warm light from the top right */
    radial-gradient(74% 70% at 88% 0%, rgba(245,179,63,.34), rgba(245,179,63,0) 60%),
    /* dark where the headline sits, opening up toward the photograph */
    linear-gradient(102deg, rgba(12,60,63,.94) 0%, rgba(16,72,75,.82) 34%, rgba(20,82,86,.50) 66%, rgba(23,89,92,.38) 100%),
    /* settle the foot of the band so the curve reads */
    linear-gradient(to bottom, rgba(23,89,92,0) 62%, rgba(12,58,61,.55) 100%);
}

/* Keep the existing radial glow and all real content above the photo.
   Target .wrap specifically rather than `.hero > *` — a universal child rule
   has the same specificity as .band-bg and, coming later in this file, would
   win and turn the photo layer into position:relative, collapsing it to zero
   height so no photograph ever appears. */
.hero::before,
.page-head::before { z-index: 1; }
.hero > .wrap,
.page-head > .wrap { position: relative; z-index: 3; }

/* Per-page photography. Pexels, verified. */
.band-bg--sunset   { background-image: url("https://images.pexels.com/photos/5477148/pexels-photo-5477148.jpeg?auto=compress&cs=tinysrgb&w=1800"); }
.band-bg--town     { background-image: url("https://images.pexels.com/photos/1012262/pexels-photo-1012262.jpeg?auto=compress&cs=tinysrgb&w=1800"); }
.band-bg--coast    { background-image: url("https://images.pexels.com/photos/1478522/pexels-photo-1478522.jpeg?auto=compress&cs=tinysrgb&w=1800"); }
.band-bg--marina   { background-image: url("https://images.pexels.com/photos/8202697/pexels-photo-8202697.jpeg?auto=compress&cs=tinysrgb&w=1800"); }
.band-bg--waterway { background-image: url("https://images.pexels.com/photos/1038375/pexels-photo-1038375.jpeg?auto=compress&cs=tinysrgb&w=1800"); }
.band-bg--dusk     { background-image: url("https://images.pexels.com/photos/1171545/pexels-photo-1171545.jpeg?auto=compress&cs=tinysrgb&w=1800"); }
.band-bg--keys     { background-image: url("https://images.pexels.com/photos/30912992/pexels-photo-30912992.jpeg?auto=compress&cs=tinysrgb&w=1800"); }

/* ==========================================================================
   1b. PHOTO GRADE
   One colour grade on every content photograph, so twenty-seven images from
   twenty-seven photographers read as a single shoot. Tokens in tokens.css.
   The band photos above are excluded on purpose: their teal duotone wash
   already grades them, and a sepia filter on .band-bg would warp that wash.
   ========================================================================== */
.ad__media img,
.fp__media img,
.deal__media img,
.fb-cover img,
.fb-article__img img,
.cover-card img,
.arch img,
.row-alt__media img,
.csa-spread__half img {
  filter: var(--photo-grade);
}

/* The About-page photos had no wash at all; give them the same one. */
.row-alt__media { position: relative; }
.row-alt__media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  mix-blend-mode: multiply;
  background: var(--photo-wash);
  opacity: var(--photo-wash-opacity);
}

/* ==========================================================================
   2. SUNBURST RAYS
   Retro postcard rays behind the hero. Very low contrast — if you can see
   where a ray ends, it is too strong.
   ========================================================================== */
.rays {
  position: absolute;
  top: -46%;
  right: -18%;
  width: 1150px;
  height: 1150px;
  z-index: 1;
  pointer-events: none;
  background: repeating-conic-gradient(
    from 0deg,
    rgba(245,179,63,.11) 0deg 5deg,
    rgba(245,179,63,0)   5deg 17deg
  );
  border-radius: 50%;
  -webkit-mask-image: radial-gradient(closest-side, #000 12%, rgba(0,0,0,.55) 46%, transparent 76%);
          mask-image: radial-gradient(closest-side, #000 12%, rgba(0,0,0,.55) 46%, transparent 76%);
  animation: fd-spin 150s linear infinite;
}
@keyframes fd-spin { to { transform: rotate(360deg); } }

/* ==========================================================================
   3. SURFACE TEXTURE
   A halftone dot screen and a fine paper grain. Together they are what stop
   the big cream areas reading as flat CSS. This is the publication's DNA —
   every printed ad on earth is a dot screen up close.
   ========================================================================== */
.section,
.hero,
.page-head { position: relative; }

.texture-dots::before,
.texture-grain::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}

.texture-dots::before {
  background-image: radial-gradient(circle, rgba(46,36,28,.16) 0.9px, transparent 1px);
  background-size: 7px 7px;
  opacity: .5;
  -webkit-mask-image: linear-gradient(to bottom, #000, transparent 55%);
          mask-image: linear-gradient(to bottom, #000, transparent 55%);
}

.texture-grain::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: .05;
  mix-blend-mode: multiply;
}

/* Content must clear the texture layers. */
.texture-dots > *,
.texture-grain > * { position: relative; z-index: 1; }

/* On the dark bands the dot screen goes light instead of dark. */
.section--dark.texture-dots::before,
.hero.texture-dots::before {
  background-image: radial-gradient(circle, rgba(251,243,230,.20) 0.9px, transparent 1px);
}

/* ==========================================================================
   4. PALM SILHOUETTE
   A single frond leaning into a dark section from the corner. Placed with a
   mask so it never becomes a hard-edged sticker.
   ========================================================================== */
/* The asset is already cream, so opacity alone controls it — no filter chain
   to go wrong. It is an <img> rather than a background so it scales cleanly. */
.frond {
  position: absolute;
  z-index: 1;
  pointer-events: none;
  width: 440px;
  max-width: 55%;
  opacity: .13;
  user-select: none;
}
.frond--tl { top: -78px;    left: -104px; transform: rotate(-12deg); }
.frond--br { bottom: -96px; right: -88px; transform: rotate(170deg); }

/* ==========================================================================
   5. DEAL TICKER
   A marquee of this month's offers. It reads as the strip along the top of a
   newspaper, and it is the one piece of motion on the page that never stops.
   Built from the issue data, so it is always the real offers.
   ========================================================================== */
.ticker {
  position: relative;
  z-index: 3;
  overflow: hidden;
  background: var(--citrus);
  border-block: var(--bw) solid var(--line);
  padding-block: 0.7rem;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 5%, #000 95%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 5%, #000 95%, transparent);
}
.ticker__track {
  display: flex;
  width: max-content;
  gap: 0;
  animation: fd-marquee 62s linear infinite;
}
.ticker:hover .ticker__track { animation-play-state: paused; }
.ticker__item {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding-inline: 1.1rem;
  font-family: var(--mono);
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  color: var(--ink);
  white-space: nowrap;
}
.ticker__item b {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: -0.01em;
}
.ticker__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--coral); flex: none; }
@keyframes fd-marquee { to { transform: translateX(-50%); } }

/* ==========================================================================
   6. AMBIENT MOTION
   ========================================================================== */
.drift { animation: fd-drift 9s ease-in-out infinite; }
@keyframes fd-drift {
  0%, 100% { transform: translateY(0)     rotate(-3deg); }
  50%      { transform: translateY(-13px) rotate(-1.6deg); }
}

/* The hero cover already rotates on hover; keep the drift from fighting it. */
.cover-card.drift:hover { animation-play-state: paused; }

/* Warm light that breathes across the dark CTA. */
.glow-pulse::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(58% 68% at 22% 108%, rgba(242,96,60,.30), rgba(242,96,60,0) 62%);
  animation: fd-breathe 11s ease-in-out infinite;
}
@keyframes fd-breathe {
  0%, 100% { opacity: .5; }
  50%      { opacity: 1; }
}

/* ==========================================================================
   7. REDUCED MOTION + SMALL SCREENS
   Everything ambient stops. Nothing here changes layout, so nothing shifts.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .rays,
  .ticker__track,
  .drift,
  .glow-pulse::after { animation: none !important; }
  .band-bg { transform: none !important; }
}

@media (max-width: 760px) {
  .rays  { width: 720px; height: 720px; top: -30%; right: -34%; }
  .frond { width: 260px; opacity: .12; }
  .ticker__track { animation-duration: 40s; }
  .hero, .page-head {
    border-bottom-left-radius: 50% 24px;
    border-bottom-right-radius: 50% 24px;
  }
}
