/**
 * Announcement bar.
 * Two display modes (sections/announcement-bar.liquid):
 * - rotate (default): one block at a time. Auto-rotation is a per-instance
 *   CSS keyframe animation computed in the liquid file (see --index /
 *   --announcement-count); manual (prev/next, via header.js's
 *   <announcement-bar>) instead toggles .is-active, transitioned here.
 * - marquee: every block scrolling continuously in one direction (see the
 *   "Marquee mode" block below).
 */

announcement-bar {
  display: block;
}

.announcement-bar {
  position: relative;
}

/* Hairline on the default ground only, which is what the old
   .color-scheme--light variant did - a bar that carries an explicit scheme
   (Waimers runs the brand purple) paints an edge-to-edge ground and never
   had one. A default bar emits no scheme class at all, so :not() on the
   scheme classes is exactly "the light strip". */
.announcement-bar:not([class*="color-scheme-"]) {
  border-bottom: 1px solid var(--color-line);
}

/* The bar's ground continues BEHIND the header by exactly one radius, so
   the header's rounded top corners have something to reveal. This is the
   reference theme's trick, measured on their live page: their bar is 56px
   tall but paints an 86px background - 56 + the 30px radius - and every
   section does the same, which is why each rounded top there shows the
   PREVIOUS section's colour rather than the page. Without it our header's
   crest was white-on-white and read as no curve at all.

   inherit keeps the extension in step with whichever colour scheme the
   merchant picks for the bar (dark, light or brand). */
.announcement-bar::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  top: 100%;
  height: var(--section-radius);
  background-color: inherit;
  pointer-events: none;
}

/* Pinned to the viewport's left edge rather than the page-width gutter:
   the strip is full-bleed, and the icons read as a fixed utility anchored
   to the corner while the messages scroll past them. Absolute (not a flex
   child) so they never take width from the marquee. */
.announcement-bar__social {
  position: absolute;
  inset-inline-start: var(--space-5);
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  /* Opaque backdrop in the bar's own colour so scrolling messages vanish
     behind the icons instead of running through them. Padding gives the
     text a moment of clearance before it reappears. */
  height: 100%;
  padding-inline-end: var(--space-5);
  /* Same ground as the bar itself, whatever scheme that resolves to - this
     used to need a per-modifier override (dark/light/brand each set it
     separately) because those modifiers pulled from different token pairs;
     the scheme picker's --color-bg is already correct for every scheme. */
  background-color: var(--color-bg);
}

/* Deliberately NOT given the hover fill the footer and contact icons carry.
   These sit in a 40px utility strip at the very top of the page, at 16px,
   against scrolling text - a disc sweeping in behind each one is noise in a
   place that should stay quiet. Opacity is the whole hover here.

   The press bounce (base.css) still applies: a tap should feel like it
   landed, and that reads at any size. Fill and bounce are separate
   affordances, and this control only wants one of them. */
.announcement-bar__social-link {
  display: inline-flex;
  color: currentcolor;
  opacity: 0.7;
}

.announcement-bar__social-link:hover,
.announcement-bar__social-link:focus-visible {
  opacity: 1;
}

/* The hover spring. Overshoot past the target and settle back, which is what
   separates a spring from a glide - the same curve the press bounce uses, so
   the two halves of touching this icon feel like one material.

   It rides the `scale` PROPERTY while the press bounce (base.css) rides
   `transform`. Two different properties, so they compose instead of
   overwriting each other - and that composition is why :active needs its own
   scale below. A pointer is essentially always hovering when it presses, so
   without it the press would resolve to 0.86 x 1.18 = 1.01: a click that
   visibly does nothing. Pulling scale down on press instead lands at
   0.86 x 0.92 = 0.79, and the button reads as properly pushed. */
@media (prefers-reduced-motion: no-preference) {
  .announcement-bar__social-link {
    transition: opacity 150ms ease, scale 450ms cubic-bezier(0.34, 1.56, 0.64, 1);
  }

  .announcement-bar__social-link:hover,
  .announcement-bar__social-link:focus-visible {
    scale: 1.18;
  }

  .announcement-bar__social-link:active {
    scale: 0.92;
    transition-duration: 90ms;
    transition-timing-function: ease-out;
  }
}

.announcement-bar__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  /* 40px. It was 52, matched to a reference bar of 56, and on this store
     that made the top of the page 164px before any content: 52 of bar plus
     112 of header. The header is the right height - it holds a logo, three
     menus and five icons, and it is the height that reads correctly once
     the bar has scrolled away. The bar was the part carrying weight it had
     not earned for one line of text.
     
     40 keeps the strip a deliberate shape rather than a hairline, which was
     the point of raising it, and gives the fold back 12px. */
  min-height: 36px;
  padding-block: var(--space-1);
}

.announcement-bar__control {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  color: currentColor;
  opacity: 0.6;
}

.announcement-bar__control:hover {
  opacity: 1;
}

.announcement-bar__control--prev svg {
  transform: rotate(180deg);
}

.announcement-bar__track {
  position: relative;
  flex: 1 1 auto;
  display: grid;
  min-height: 20px;
}

/* Every item occupies the same grid cell; opacity (animated or forced by
   header.js in manual mode) decides which one is visible. */
.announcement-bar__item {
  grid-area: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  opacity: 0;
}

/* Single-block bars (no rotation) and the very first paint before the
   computed keyframes attach: show block 0. */
.announcement-bar__item:first-child {
  opacity: 1;
}

/* Manual mode (header.js's prev/next): plain class toggle, so it needs its
   own transition (the auto-rotate keyframes above already bake motion into
   themselves). Same ~350ms crossfade + slide as the auto keyframes. */
@media (prefers-reduced-motion: no-preference) {
  .announcement-bar[data-manual='true'] .announcement-bar__item {
    transition: opacity 350ms ease, transform 350ms ease;
  }
}

.announcement-bar[data-manual='true'] .announcement-bar__item {
  animation-play-state: paused;
  opacity: 0;
  transform: translateY(6px);
}

.announcement-bar[data-manual='true'] .announcement-bar__item.is-active {
  opacity: 1;
  transform: translateY(0);
}

.announcement-bar[data-paused='true'] .announcement-bar__item {
  animation-play-state: paused;
}

/* The per-instance keyframe rotation (inlined by sections/announcement-bar.liquid)
   auto-advances content indefinitely; disable it so only the first item shows,
   same as the single-block/no-JS state above. Also drops the manual-mode
   transition above ("instant swap" instead of a crossfade). */
@media (prefers-reduced-motion: reduce) {
  .announcement-bar__item {
    animation: none !important;
    transform: none !important;
  }
}

.announcement-bar__text,
.announcement-bar__link {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
}

.announcement-bar__text p,
.announcement-bar__link p {
  margin: 0;
}

/* Underline only on hover/focus, not permanently - keeps the bar feeling
   like copy rather than a wall of link text - plus a small trailing arrow. */
.announcement-bar__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  color: currentColor;
  text-decoration: none;
}

.announcement-bar__link:hover,
.announcement-bar__link:focus-visible {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.announcement-bar__link svg {
  flex: 0 0 auto;
}

/* ------------------------------------------------------------------ */
/* Marquee mode                                                        */
/* ------------------------------------------------------------------ */
.announcement-bar--marquee .announcement-bar__inner {
  justify-content: flex-start;
  overflow: hidden;
}

.announcement-bar__marquee {
  width: 100%;
  overflow: hidden;
}

.announcement-bar__marquee-track {
  display: flex;
  width: max-content;
}

.announcement-bar__marquee-run {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
}

.announcement-bar__marquee-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-7);
  padding-inline-start: var(--space-7);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ✦ separator glyph between messages, not a border - matches the
   marquee's "ticker" feel better than a hairline. Suffixed onto each item
   (rather than a ::before on the next one) so the very first item in a run
   doesn't need a :first-child exception. */
.announcement-bar__marquee-item::after {
  /* Empty alt text on generated content: browsers that support the
     content alt syntax expose nothing to assistive tech, so the glyph
     stays decorative instead of being read out between every message.
     Older engines ignore the alt part and still render the glyph. */
  content: '\2726' / '';
  font-size: 10px;
  /* Scheme-agnostic: mixes toward the bar's own ink instead of a hardcoded
     white/black pair, so the glyph stays a muted tint of the running text
     on any ground rather than needing a light/dark override. */
  color: color-mix(in srgb, var(--color-ink) 50%, transparent);
}

@media (prefers-reduced-motion: no-preference) {
  .announcement-bar__marquee-track {
    animation: announcement-marquee var(--marquee-duration, 30s) linear infinite;
  }

  .announcement-bar--marquee:hover .announcement-bar__marquee-track {
    animation-play-state: paused;
  }
}

@keyframes announcement-marquee {
  from {
    transform: translateX(0);
  }
  to {
    /* The track holds two identical runs back to back, so translating by
       exactly half its width scrolls through one full run - the instant it
       finishes, the second (identical) run is sitting exactly where the
       first one started, and the loop repeats with no visible seam. */
    transform: translateX(-50%);
  }
}

/* Reduced motion: static, centered first message only - matches the
   rotate-mode fallback above instead of leaving a full scrolling row
   motionless (which would just look like unfinished layout). */
@media (prefers-reduced-motion: reduce) {
  .announcement-bar--marquee .announcement-bar__inner {
    justify-content: center;
  }

  .announcement-bar__marquee-track {
    transform: none;
  }

  .announcement-bar__marquee-run[aria-hidden='true'] {
    display: none;
  }

  .announcement-bar__marquee-item:not(:first-child) {
    display: none;
  }
}


/* The light/dark switch at the end of the bar, the mirror of the socials at
   the start. Same absolute placement so the marquee and the rotating text
   stay centred between them. */
.announcement-bar__theme {
  position: absolute;
  inset-inline-end: var(--space-5);
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
  display: flex;
  align-items: center;
}

.announcement-bar__theme-toggle {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-pill);
  color: currentcolor;
  opacity: 0.8;
}

.announcement-bar__theme-toggle:hover,
.announcement-bar__theme-toggle:focus-visible {
  opacity: 1;
  background-color: color-mix(in srgb, currentcolor 14%, transparent);
}

.announcement-bar__theme-toggle:focus-visible {
  outline: 2px solid currentcolor;
  outline-offset: 2px;
}

/* Keep the text clear of the switch on narrow screens, where the bar has
   no side padding to spare. */
@media screen and (max-width: 749px) {
  .announcement-bar__inner {
    padding-inline-end: calc(var(--space-5) + 32px);
  }
}
