/* ============================================================
 * assets/css/announce.css
 *
 * The scrolling announcement pill. Loaded on every page by
 * includes/head.php and includes/admin-head.php.
 *
 * Plain CSS, not Tailwind classes, on purpose. tailwind.css in
 * this project is a COMMITTED, PRE-COMPILED file — there is no
 * build step on the host — so a class that is not already in it
 * simply does nothing. Writing the ticker as its own stylesheet
 * means it works the moment the files are uploaded, with no
 * `npx tailwindcss` run and nothing to remember on the next
 * deploy.
 *
 * The palette below is the same one tailwind.config.js declares,
 * written out in hex so the two never drift apart silently.
 * ============================================================ */

/* How much vertical room the sticky chrome takes.
 *
 * The header is 4.5rem and sticky at the top; the announcement bar
 * sticks underneath it. Anything else on the site that wants to stick
 * below both — the boosting page's order panel is the first — reads
 * --ilz-chrome rather than hard-coding a sum that goes wrong the day
 * the bar is dismissed or has no announcements to show.
 *
 * announce.js keeps --ilz-bar in step with what is actually on screen:
 * the bar's real height while it is up, 0px once it is dismissed or
 * when there was never an announcement. The value below is the
 * before-JavaScript default and matches a single-line bar.
 */
:root {
  --ilz-header: 4.5rem;
  --ilz-bar: 3.5rem;
  --ilz-chrome: calc(var(--ilz-header) + var(--ilz-bar));
}

.ilz-announce-wrap {
  /* Sticks directly beneath the site header. Below it in the stacking
     order (the header is z-50) so the account menu still opens over
     the bar rather than behind it. */
  position: sticky;
  top: var(--ilz-header);
  z-index: 40;
  padding-top: 0.75rem;
  pointer-events: none;   /* the bar itself takes the clicks back */
}

.ilz-announce-wrap .shell {
  pointer-events: none;
}

/* ── The pill ────────────────────────────────────────────── */

.ilz-announce {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 0.625rem;

  /* Fully rounded. A pill, not a banner — the difference is what
     stops it reading as part of the page chrome. */
  border-radius: 9999px;
  border: 1px solid transparent;
  padding: 0.4375rem 0.5rem 0.4375rem 0.5rem;

  font-size: 0.8125rem;
  line-height: 1.25rem;

  box-shadow: 0 1px 2px rgba(26, 18, 48, 0.04), 0 4px 14px rgba(26, 18, 48, 0.06);
  backdrop-filter: blur(8px);

  animation: ilz-announce-in 0.45s cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes ilz-announce-in {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── Tones ───────────────────────────────────────────────── */

/* A step deeper than the ivory-300 the rest of the site uses for
   surfaces. On a #FAFAFC page, #EDE9FE reads as "slightly off-white"
   rather than as lavender, and a notice bar that does not register as
   a colour is a notice bar nobody notices. */
.ilz-announce--lavender {
  background: #E9E3FD;
  border-color: #D5CBFB;
  color: #453A64;
  --ilz-announce-accent: #7C5CFC;
}

.ilz-announce--gold {
  background: #FEF3C7;
  border-color: #FDE68A;
  color: #7C2D12;
  --ilz-announce-accent: #EA580C;
}

.ilz-announce--coral {
  background: #7C5CFC;
  border-color: #6366F1;
  color: #FFFFFF;
  --ilz-announce-accent: #FFFFFF;
  box-shadow: 0 6px 24px rgba(124, 92, 252, 0.3);
}

.ilz-announce--success {
  background: #DCFCE7;
  border-color: #BBF7D0;
  color: #14532D;
  --ilz-announce-accent: #16A34A;
}

.ilz-announce--danger {
  background: #FADCDC;
  border-color: #F5C2C2;
  color: #4E1917;
  --ilz-announce-accent: #C7413B;
}

/* ── Tones, dark ─────────────────────────────────────────── */

.dark .ilz-announce--lavender {
  background: rgba(55, 47, 145, 0.32);
  border-color: rgba(124, 92, 252, 0.35);
  color: #DDD6FE;
  --ilz-announce-accent: #A78BFA;
}

.dark .ilz-announce--gold {
  background: rgba(124, 45, 18, 0.32);
  border-color: rgba(245, 158, 11, 0.35);
  color: #FDE68A;
  --ilz-announce-accent: #FBBF24;
}

.dark .ilz-announce--coral {
  background: #6366F1;
  border-color: #7C5CFC;
  color: #FFFFFF;
  --ilz-announce-accent: #FFFFFF;
}

.dark .ilz-announce--success {
  background: rgba(20, 83, 45, 0.35);
  border-color: rgba(34, 197, 94, 0.35);
  color: #DCFCE7;
  --ilz-announce-accent: #22C55E;
}

.dark .ilz-announce--danger {
  background: rgba(78, 25, 23, 0.4);
  border-color: rgba(199, 65, 59, 0.4);
  color: #FADCDC;
  --ilz-announce-accent: #C7413B;
}

/* ── Megaphone ───────────────────────────────────────────── */

.ilz-announce__mark {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 1.875rem;
  height: 1.875rem;
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.65);
  color: var(--ilz-announce-accent);
}

.dark .ilz-announce__mark {
  background: rgba(255, 255, 255, 0.1);
}

.ilz-announce--coral .ilz-announce__mark {
  background: rgba(255, 255, 255, 0.2);
}

.ilz-announce__mark svg {
  width: 0.9375rem;
  height: 0.9375rem;
}

/* A slow, small tilt. Enough to catch the eye on arrival and not
   enough to be the thing you look at for the rest of the visit. */
@media (prefers-reduced-motion: no-preference) {
  .ilz-announce__mark svg {
    animation: ilz-announce-ring 4.5s ease-in-out infinite;
    transform-origin: 20% 60%;
  }
}

@keyframes ilz-announce-ring {
  0%, 82%, 100% { transform: rotate(0deg); }
  86%           { transform: rotate(-9deg); }
  90%           { transform: rotate(7deg); }
  94%           { transform: rotate(-4deg); }
}

/* ── The marquee ─────────────────────────────────────────── */

.ilz-announce__viewport {
  flex: 1 1 auto;
  min-width: 0;          /* without this the flex child refuses to shrink */
  overflow: hidden;

  /* Faded edges rather than a hard cut, so a word entering the strip
     appears rather than snapping into existence at the boundary. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 2.5rem, #000 calc(100% - 2.5rem), transparent);
          mask-image: linear-gradient(90deg, transparent, #000 2.5rem, #000 calc(100% - 2.5rem), transparent);
}

.ilz-announce__track {
  display: flex;
  width: max-content;
  will-change: transform;
  animation: ilz-announce-scroll var(--ilz-announce-duration, 30s) linear infinite;
}

/* Reading a moving line is hard; stopping it should be as easy as
   pointing at it. Focus counts too, for anyone tabbing to the link
   inside. */
.ilz-announce:hover .ilz-announce__track,
.ilz-announce:focus-within .ilz-announce__track {
  animation-play-state: paused;
}

@keyframes ilz-announce-scroll {
  from { transform: translateX(0); }
  /* Exactly one copy's width. The track holds two identical runs, so
     at -50% the second run sits where the first began and the loop
     has no seam. */
  to   { transform: translateX(-50%); }
}

.ilz-announce__run {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  white-space: nowrap;
}

.ilz-announce__item {
  font-weight: 500;
  color: inherit;
  text-decoration: none;
}

a.ilz-announce__item:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.ilz-announce__dot {
  margin: 0 1.25rem;
  opacity: 0.45;
}

/* ── Close ───────────────────────────────────────────────── */

.ilz-announce__close {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border: 0;
  border-radius: 9999px;
  background: transparent;
  color: inherit;
  opacity: 0.5;
  cursor: pointer;
  transition: opacity 0.2s, background-color 0.2s;
}

.ilz-announce__close:hover {
  opacity: 1;
  background: rgba(255, 255, 255, 0.55);
}

.dark .ilz-announce__close:hover {
  background: rgba(255, 255, 255, 0.12);
}

.ilz-announce__close svg {
  width: 0.875rem;
  height: 0.875rem;
}

/* The dismissal itself, so the bar leaves rather than blinking out. */
.ilz-announce-wrap.is-leaving {
  transition: opacity 0.25s ease, transform 0.25s ease;
  opacity: 0;
  transform: translateY(-6px);
}

/* ── Small screens ───────────────────────────────────────── */

@media (max-width: 640px) {
  :root { --ilz-header: 4.25rem; --ilz-bar: 3rem; }

  .ilz-announce-wrap {
    padding-top: 0.5rem;
  }

  .ilz-announce {
    font-size: 0.75rem;
    padding: 0.375rem 0.375rem;
    gap: 0.5rem;
  }

  .ilz-announce__mark {
    width: 1.625rem;
    height: 1.625rem;
  }

  .ilz-announce__viewport {
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 1.25rem, #000 calc(100% - 1.25rem), transparent);
            mask-image: linear-gradient(90deg, transparent, #000 1.25rem, #000 calc(100% - 1.25rem), transparent);
  }

  .ilz-announce__dot { margin: 0 0.875rem; }
}

/* ── Reduced motion ──────────────────────────────────────── *
 *
 * Somebody who has asked their system to stop things moving does
 * not want a permanent horizontal crawl at the top of every page.
 * The track stops and becomes a normal, scrollable strip, so the
 * announcements are all still readable — just under the reader's
 * own control.
 */

@media (prefers-reduced-motion: reduce) {
  .ilz-announce__track {
    animation: none;
    width: 100%;
  }

  .ilz-announce__track > .ilz-announce__run[aria-hidden='true'] {
    display: none;
  }

  .ilz-announce__viewport {
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-mask-image: none;
            mask-image: none;
  }

  .ilz-announce__viewport::-webkit-scrollbar { display: none; }
}

/* ── Print ───────────────────────────────────────────────── */

@media print {
  .ilz-announce-wrap { display: none; }
}
