/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

/* Custom font faces - Jomhuria for headings, Figtree for body */
@font-face {
  font-family: 'Jomhuria';
  src: url("/assets/Jomhuria-Regular-56cc73bc.ttf") format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Figtree';
  src: url("/assets/Figtree-VariableFont_wght-89352678.ttf") format('truetype');
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}

/* Base typography styles */
html, body {
  font-family: 'Figtree', system-ui, sans-serif;
}

/* Headings use Jomhuria with larger sizes */
h1, h2, h3, h4, h5, h6,
.font-heading {
  font-family: 'Jomhuria', system-ui, sans-serif !important;
  font-weight: 400;
  line-height: 0.85;
}

/* Card titles — single source of truth for product / showcase card names.
   Defeats the h3 element defaults (36px, line-height 0.85, uppercase) and
   Jomhuria's display sizing. Sized like normal e-commerce card titles. */
.font-card-title,
h1.font-card-title,
h2.font-card-title,
h3.font-card-title,
h4.font-card-title,
h5.font-card-title,
h6.font-card-title {
  font-family: 'Figtree', system-ui, sans-serif !important;
  font-weight: 600 !important;
  font-size: 0.875rem !important;       /* 14px */
  line-height: 1.35 !important;
  text-transform: none !important;
  letter-spacing: 0 !important;
}

@media (min-width: 768px) {
  .font-card-title,
  h1.font-card-title,
  h2.font-card-title,
  h3.font-card-title,
  h4.font-card-title,
  h5.font-card-title,
  h6.font-card-title {
    font-size: 0.9375rem !important;    /* 15px */
  }
}

/* h1, h2, h3 are uppercase */
h1, h2, h3 {
  text-transform: uppercase !important;
}

/* Larger heading sizes for Jomhuria display font */
h1 { font-size: 4rem; }      /* 64px */
h2 { font-size: 3rem; }      /* 48px */
h3 { font-size: 2.25rem; }   /* 36px */
h4 { font-size: 1.875rem; }  /* 30px */
h5 { font-size: 1.5rem; }    /* 24px */
h6 { font-size: 1.25rem; }   /* 20px */

@media (min-width: 640px) {
  h1 { font-size: 5rem; }    /* 80px */
  h2 { font-size: 3.5rem; }  /* 56px */
  h3 { font-size: 2.5rem; }  /* 40px */
}

@media (min-width: 1024px) {
  h1 { font-size: 6rem; }    /* 96px */
  h2 { font-size: 4rem; }    /* 64px */
  h3 { font-size: 3rem; }    /* 48px */
}

/* Mobile-specific enhancements */

/* Safe area insets for notched devices (iPhone X+, etc.) */
@supports (padding: max(0px)) {
  .safe-area-inset-bottom {
    padding-bottom: max(env(safe-area-inset-bottom), 0rem);
  }

  .safe-area-inset-top {
    padding-top: max(env(safe-area-inset-top), 0rem);
  }

  .safe-area-inset-left {
    padding-left: max(env(safe-area-inset-left), 0rem);
  }

  .safe-area-inset-right {
    padding-right: max(env(safe-area-inset-right), 0rem);
  }
}

/* Smooth scrolling */
html {
  scroll-behavior: smooth;
}

/* Improve touch interactions on mobile */
@media (hover: none) and (pointer: coarse) {
  /* Remove tap highlight color */
  * {
    -webkit-tap-highlight-color: transparent;
  }

  /* Increase touch target sizes */
  button,
  a,
  input,
  select,
  textarea,
  [role="button"] {
    min-height: 44px;
    min-width: 44px;
  }

  /* Improve scrolling performance */
  * {
    -webkit-overflow-scrolling: touch;
  }
}

/* Prevent text selection on interactive elements */
button,
[role="button"],
.no-select {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

/* Optimize animations for mobile */
@media (prefers-reduced-motion: no-preference) {
  .smooth-transform {
    will-change: transform;
  }
}

/* Disable animations if user prefers reduced motion */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Homepage hero — slow Ken Burns drift.
   Subtle cinematic motion on the static fallback hero. The image starts
   slightly overscanned (scale 1.06) so panning never exposes an edge, and
   eases in and back out via `alternate` so the loop never hard-cuts. */
@keyframes hero-ken-burns {
  from { transform: scale(1.06) translate3d(0, 0, 0); }
  to   { transform: scale(1.18) translate3d(-2%, -1.5%, 0); }
}

.hero-ken-burns {
  transform: scale(1.06);
  transform-origin: 50% 50%;
  will-change: transform;
  animation: hero-ken-burns 26s ease-in-out infinite alternate;
}

@media (prefers-reduced-motion: reduce) {
  .hero-ken-burns {
    animation: none;
    transform: none;
  }
}

/* Brand illustrations — ambient float for decorative art (e.g. the /meista
   salmon school). Small amplitude, long duration: reads as organic drift,
   not UI motion. */
@keyframes illustration-float {
  from { transform: translateY(0) rotate(0deg); }
  to   { transform: translateY(-8px) rotate(-1.5deg); }
}

.illustration-float {
  animation: illustration-float 7s ease-in-out infinite alternate;
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  .illustration-float {
    animation: none;
  }
}

/* Hero illustration choreography — a one-shot entrance on a wrapper element
   plus an infinite ambient drift on the img itself. One transform per element:
   nesting keeps the two animations from overwriting each other.
   Per-layer variety comes from CSS custom properties on the img
   (--drift-base rotation, --drift-duration, negative --drift-delay to
   desync layers) so a single keyframe serves every illustration. */
@keyframes hero-art-enter {
  from { opacity: 0; transform: translateY(40px) scale(0.93); }
  to   { opacity: 1; transform: translateY(0) scale(var(--enter-scale, 1)); }
}

.hero-art-enter {
  animation: hero-art-enter 1.6s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.hero-art-enter-delayed {
  animation: hero-art-enter 1.6s cubic-bezier(0.22, 1, 0.36, 1) 0.5s both;
}

@keyframes illustration-drift {
  from {
    transform: translateY(0) rotate(var(--drift-base, 0deg));
  }
  to {
    transform: translateY(var(--drift-rise, -18px))
      rotate(calc(var(--drift-base, 0deg) + var(--drift-swing, 2.5deg)));
  }
}

.illustration-drift {
  animation: illustration-drift var(--drift-duration, 12s) ease-in-out
    var(--drift-delay, 0s) infinite alternate;
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  .hero-art-enter,
  .hero-art-enter-delayed,
  .illustration-drift {
    animation: none;
  }
}

/* ── Gutter illustrations (.kuvitus-rail / .kuvitus-art) ─────────────────────
   Art in the whitespace beside the content column, never over it. A rail's
   positioned parent is a content-width box; the rail hangs off its side and is
   exactly as wide as the gap left over to the viewport edge:

     width = 50vw − half the content width − inner gutter − outer margin

   so art at `width: 100%` physically cannot reach the content column. Rails
   only render from xl up, where that gap is wide enough to hold an
   illustration. This replaced fixed `top-[Nrem]` overlays, which drifted
   behind cards as rows changed length.

   Motion is scroll-driven and CSS-only: one transform per element (same rule
   as the hero art) — the rail parallaxes across the whole pass, the art fades
   and settles as it enters. @supports keeps browsers without scroll-driven
   animations (Firefox) on the static art. */
.kuvitus-rail {
  position: absolute;
  width: calc(50vw - 50% - 3.5rem);
  display: none;
  justify-content: center;
  pointer-events: none;
  user-select: none;
}

/* Below 1400px the gutter is too narrow to hold an illustration at a size
   worth showing — the page runs without art rather than with slivers. */
@media (min-width: 1400px) {
  .kuvitus-rail { display: flex; }
}

.kuvitus-rail--left {
  right: calc(100% + 2.5rem);
}

.kuvitus-rail--right {
  left: calc(100% + 2.5rem);
}

.kuvitus-art {
  width: 100%;
  height: auto;
  opacity: var(--kuvitus-opacity, 0.95);
  transform: rotate(var(--kuvitus-rot, 0deg));
}

@keyframes kuvitus-parallax {
  from { transform: translateY(var(--kuvitus-depth, 40px)); }
  to   { transform: translateY(calc(var(--kuvitus-depth, 40px) * -1)); }
}

@keyframes kuvitus-enter {
  from {
    opacity: 0;
    transform: translateY(2rem) scale(0.9)
      rotate(calc(var(--kuvitus-rot, 0deg) * 1.8));
  }
  to {
    opacity: var(--kuvitus-opacity, 0.95);
    transform: translateY(0) scale(1) rotate(var(--kuvitus-rot, 0deg));
  }
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .kuvitus-rail {
      animation: kuvitus-parallax linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
      will-change: transform;
    }

    .kuvitus-art {
      animation: kuvitus-enter linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 60%;
      will-change: transform, opacity;
    }
  }
}

/* ── Gutter travel along a curve (offset-path) ───────────────────────────────
   Upgrade of `kuvitus-parallax` above: instead of sliding straight up the
   gutter, the art walks a shallow S — drifting a little towards the viewport
   edge on the way in and back on the way out, which reads as hand-drawn rather
   than mechanical. Same scroll timeline, no JS.

   The motion sits on `.kuvitus-art`, NOT on the rail, and that placement is the
   whole trick. `shape()` coordinates resolve against the element's *containing
   block*, and the element is then placed on the path outright — its own `left`
   and `top` stop mattering. Put on the rail (whose containing block is the
   content-width parent) that drops the art into the middle of the content
   column; put on the art (whose containing block is the rail) `from 50% 50%` is
   the centre of the rail, which is exactly where the flex centring already puts
   it, so the art starts where it always did and the curve plays out inside the
   rail box.

   Staying inside the rail is what preserves the invariant from `.kuvitus-rail`:
   the art cannot reach the content column because the rail cannot. The art pays
   for the excursion out of its own width — `--kuvitus-sway-amp` shrinks it by
   that much on each side — so the rail's 2.5rem inner and 1rem outer clearances
   are untouched.

   Browsers without shape() (Firefox, older Safari) keep the straight
   `kuvitus-parallax` on the rail from the block above. */
.kuvitus-rail--left  { --kuvitus-sway-dir: -1; }
.kuvitus-rail--right { --kuvitus-sway-dir:  1; }

@keyframes kuvitus-travel {
  from { offset-distance: 0%; }
  to   { offset-distance: 100%; }
}

@supports (animation-timeline: view()) and (offset-path: shape(from 0 0, line to 1px 1px)) {
  @media (prefers-reduced-motion: no-preference) {
    /* The art carries the travel now, so the rail stops moving — leaving both
       on would double the parallax. */
    .kuvitus-rail {
      animation: none;
    }

    .kuvitus-art {
      /* Half the rail's inner clearance: even a control point pulled fully
         outward stays well short of the gap the rail keeps from the content. */
      --kuvitus-sway-amp: 14px;
      --kuvitus-sway: calc(var(--kuvitus-sway-amp) * var(--kuvitus-sway-dir, 1));

      width: calc(100% - 2 * var(--kuvitus-sway-amp));
      offset-rotate: 0deg;
      offset-path: shape(
        from 50% calc(50% + var(--kuvitus-depth, 40px)),
        curve to 50% calc(50% - var(--kuvitus-depth, 40px))
          with calc(50% + var(--kuvitus-sway)) calc(50% + var(--kuvitus-depth, 40px) * 0.4)
             / calc(50% - var(--kuvitus-sway)) calc(50% - var(--kuvitus-depth, 40px) * 0.4)
      );

      /* Entrance over the first part of the pass, travel across the whole of
         it. offset-* and transform are separate properties, so the enter
         keyframe's transform and the travel never overwrite each other. */
      animation: kuvitus-enter linear both, kuvitus-travel linear both;
      animation-timeline: view(), view();
      animation-range: entry 0% entry 60%, cover 0% cover 100%;
    }
  }
}

/* ── Inlined kuvitus: per-colour assembly ────────────────────────────────────
   A motif rendered through KuvitusHelper#kuvitus_inline_svg keeps its fill
   classes (`<motif>__cls-N`, one per colour — see script/optimize_kuvitus.mjs),
   and those classes are the only grouping a flat Illustrator export has. On a
   `.kuvitus-assemble` element they fade in one colour at a time, in the file's
   own paint order, so the drawing builds itself instead of appearing whole.

   Opacity only, on purpose: these colours are interlocking shapes, not stacked
   layers, so moving or scaling them independently tears the artwork apart.

   The catch-all rule comes first and holds the last slot's delay; the per-class
   rules below it have equal specificity and win by order, which caps the
   stagger for motifs with more colours than slots (karhu-3 has 33). */
@keyframes kuvitus-layer-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@media (prefers-reduced-motion: no-preference) {
  .kuvitus-assemble [class*="__cls-"] {
    animation: kuvitus-layer-in var(--kuvitus-layer-duration, 0.42s) ease-out both;
    animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) + 11 * var(--kuvitus-layer-stagger, 0.09s));
  }

  .kuvitus-assemble [class$="__cls-1"]  { animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) +  0 * var(--kuvitus-layer-stagger, 0.09s)); }
  .kuvitus-assemble [class$="__cls-2"]  { animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) +  1 * var(--kuvitus-layer-stagger, 0.09s)); }
  .kuvitus-assemble [class$="__cls-3"]  { animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) +  2 * var(--kuvitus-layer-stagger, 0.09s)); }
  .kuvitus-assemble [class$="__cls-4"]  { animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) +  3 * var(--kuvitus-layer-stagger, 0.09s)); }
  .kuvitus-assemble [class$="__cls-5"]  { animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) +  4 * var(--kuvitus-layer-stagger, 0.09s)); }
  .kuvitus-assemble [class$="__cls-6"]  { animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) +  5 * var(--kuvitus-layer-stagger, 0.09s)); }
  .kuvitus-assemble [class$="__cls-7"]  { animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) +  6 * var(--kuvitus-layer-stagger, 0.09s)); }
  .kuvitus-assemble [class$="__cls-8"]  { animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) +  7 * var(--kuvitus-layer-stagger, 0.09s)); }
  .kuvitus-assemble [class$="__cls-9"]  { animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) +  8 * var(--kuvitus-layer-stagger, 0.09s)); }
  .kuvitus-assemble [class$="__cls-10"] { animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) +  9 * var(--kuvitus-layer-stagger, 0.09s)); }
  .kuvitus-assemble [class$="__cls-11"] { animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) + 10 * var(--kuvitus-layer-stagger, 0.09s)); }
  .kuvitus-assemble [class$="__cls-12"] { animation-delay: calc(var(--kuvitus-assemble-delay, 0.5s) + 11 * var(--kuvitus-layer-stagger, 0.09s)); }
}

/* ── Cross-document view transitions ─────────────────────────────────────────
   The layout sets `<meta name="turbo-visit-control" content="reload">`, so
   every in-app navigation is a real document load — which is exactly what the
   native cross-document View Transition API animates. No JS, and browsers
   without it (Firefox) navigate the way they always did.

   The page itself gets a short cross-fade rather than the 250ms default: long
   enough to stop the hard cut, short enough that it never feels like waiting.
   The one element that actually travels is the hero illustration, which exists
   on both the homepage hero and the /meista closing section — naming it on both
   makes the browser tween the bear between the two positions instead of fading
   one out and the other in.

   A `view-transition-name` must be unique per document, so `.kuvitus-hero-motif`
   belongs on exactly one element per page. */
@view-transition { navigation: auto; }

/* Opting out for reduced motion is done by cancelling the animations, not by
   dropping `navigation: auto`: Chrome parses `@view-transition` inside a
   conditional group rule but does not act on it, so a media-wrapped opt-in
   silently never transitions. With no animations left to wait for the browser
   finishes the transition on the first frame, which is the hard cut those
   visitors asked for. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

@keyframes page-fade-out { to   { opacity: 0; } }
@keyframes page-fade-in  { from { opacity: 0; } }

::view-transition-old(root) { animation: page-fade-out 0.16s ease both; }
::view-transition-new(root) { animation: page-fade-in  0.16s ease both; }

.kuvitus-hero-motif { view-transition-name: kuvitus-hero-motif; }

::view-transition-group(kuvitus-hero-motif) {
  animation-duration: 0.55s;
  animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}

/* The two placements are the same drawing at different sizes, so cross-fading
   the snapshots on top of the move only muddies it — hold the old one and let
   the group do the travelling. */
::view-transition-old(kuvitus-hero-motif),
::view-transition-new(kuvitus-hero-motif) {
  animation-duration: 0.55s;
  animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
  height: 100%;
  object-fit: contain;
}

/* Pull-to-refresh prevention (if needed) */
body {
  overscroll-behavior-y: contain;
}

/* Hide scrollbar on mobile for cleaner look (optional) */
@media (max-width: 768px) {
  ::-webkit-scrollbar {
    width: 0;
    height: 0;
  }
}

/* Focus styles for accessibility */
button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid #3E5536; /* moss-green-600 */
  outline-offset: 2px;
}

/* Mobile menu slide animations */
@keyframes slideInRight {
  from {
    transform: translateX(100%);
  }
  to {
    transform: translateX(0);
  }
}

@keyframes slideOutRight {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(100%);
  }
}

/* Loading states */
.loading-shimmer {
  background: linear-gradient(
    90deg,
    rgba(240, 240, 240, 0) 0%,
    rgba(240, 240, 240, 0.8) 50%,
    rgba(240, 240, 240, 0) 100%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}

@keyframes shimmer {
  0% {
    background-position: -200% 0;
  }
  100% {
    background-position: 200% 0;
  }
}

/* Hide scrollbar utility class */
.scrollbar-hide {
  -ms-overflow-style: none;  /* Internet Explorer 10+ */
  scrollbar-width: none;  /* Firefox */
}

.scrollbar-hide::-webkit-scrollbar {
  display: none;  /* Safari and Chrome */
}

.hero-block-background {
  position: relative;
  isolation: isolate;
  background-color: #26412f;
  background-image:
    radial-gradient(circle at 65% 5%, rgba(255, 239, 210, 0.55), transparent 42%),
    linear-gradient(120deg, rgba(19, 41, 28, 0.4), rgba(53, 87, 57, 0.35) 45%, rgba(19, 41, 28, 0.4)),
    url("/assets/hero-block-background-89c2ea02.svg");
  background-size: cover;
  background-position: center 32%;
  background-repeat: no-repeat;
  color: #fff;
  overflow: hidden;
}

.hero-block-background::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(circle at 75% 12%, rgba(255, 226, 185, 0.75), transparent 55%),
    linear-gradient(185deg, rgba(18, 34, 24, 0.25), rgba(18, 34, 24, 0.55));
  pointer-events: none;
}

.hero-block-background::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    linear-gradient(90deg, rgba(8, 15, 11, 0.35), transparent 38%, transparent 62%, rgba(12, 22, 16, 0.3)),
    linear-gradient(0deg, rgba(8, 14, 11, 0.2), transparent 60%);
  mix-blend-mode: normal;
  pointer-events: none;
}

.hero-block-background > * {
  position: relative;
  z-index: 1;
}

@media (max-width: 768px) {
  .hero-block-background {
    background-position: center 60%;
    background-image:
      radial-gradient(circle at 70% 0%, rgba(255, 228, 189, 0.65), transparent 60%),
      linear-gradient(170deg, rgba(16, 32, 23, 0.5), rgba(47, 83, 55, 0.45)),
      url("/assets/hero-block-background-89c2ea02.svg");
    background-size: 180% auto, cover;
  }
}

/* Real-time order status update animation */
@keyframes statusPulse {
  0% {
    box-shadow: 0 0 0 0 rgba(62, 85, 54, 0.4);
  }
  50% {
    box-shadow: 0 0 0 10px rgba(62, 85, 54, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(62, 85, 54, 0);
  }
}

.order-status-updated {
  animation: statusPulse 1s ease-out;
}

/* Toast notification styles */
.new-order-toast {
  animation: slideInFromRight 0.3s ease-out;
}

@keyframes slideInFromRight {
  from {
    opacity: 0;
    transform: translateX(100%);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

/* Feature showcase tooltip animations */
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.animate-fade-in-up {
  animation: fadeInUp 0.3s ease-out forwards;
}

/* Live inventory update animations */
@keyframes inventoryPulse {
  0% {
    box-shadow: 0 0 0 0 rgba(212, 148, 74, 0.6);
  }
  50% {
    box-shadow: 0 0 0 12px rgba(212, 148, 74, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(212, 148, 74, 0);
  }
}

.inventory-updated {
  animation: inventoryPulse 1s ease-out;
}

@keyframes pricePulse {
  0% {
    box-shadow: 0 0 0 0 rgba(139, 90, 60, 0.6);
  }
  50% {
    box-shadow: 0 0 0 12px rgba(139, 90, 60, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(139, 90, 60, 0);
  }
}

.price-updated {
  animation: pricePulse 1s ease-out;
}

/* Real-time item list animations */
@keyframes fadeIn {
  from {
    opacity: 0;
    transform: scale(0.95);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateX(-20px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes slideOut {
  from {
    opacity: 1;
    transform: translateX(0);
  }
  to {
    opacity: 0;
    transform: translateX(20px);
  }
}

.animate-fade-in {
  animation: fadeIn 0.4s ease-out forwards;
}

.animate-slide-in {
  animation: slideIn 0.4s ease-out forwards;
}

.animate-slide-out {
  animation: slideOut 0.3s ease-out forwards;
}

/* Real-time update highlight */
.realtime-updated {
  animation: realtimeHighlight 1s ease-out;
}

@keyframes realtimeHighlight {
  0% {
    background-color: rgba(212, 148, 74, 0.3);
  }
  100% {
    background-color: transparent;
  }
}

/* New item badge animation */
@keyframes newItemBadge {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
  }
}

.new-item-badge {
  animation: newItemBadge 0.4s ease-out forwards;
}

/* Demo dashboard animations */
@keyframes slideInLeft {
  from {
    opacity: 0;
    transform: translateX(-30px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes slideInRight {
  from {
    opacity: 0;
    transform: translateX(30px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.animate-slide-in-left {
  animation: slideInLeft 0.4s ease-out forwards;
}

.animate-slide-in-right {
  animation: slideInRight 0.4s ease-out forwards;
}

/* Hero background color */
.bg-hero-dark {
  background-color: #31332f !important;
}

.text-hero-dark {
  color: #31332f !important;
}

/* Admin Trix Editor Styles */
.admin-trix-editor trix-editor {
  min-height: 300px;
  border: 1px solid #d1d5db;
  border-radius: 0 0 0.5rem 0.5rem;
  padding: 1rem;
}

.admin-trix-editor trix-toolbar {
  border: 1px solid #d1d5db;
  border-bottom: none;
  border-radius: 0.5rem 0.5rem 0 0;
  background: #f9fafb;
  padding: 0.5rem;
}

/* ===== Chat WhatsApp-Style Styles ===== */

/* Chat wallpaper - subtle dot pattern on moss-green-50 */
.chat-wallpaper {
  background-color: #f0f5f1;
  background-image: url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='3' cy='3' r='1.2' fill='%2344754b' fill-opacity='0.04'/%3E%3Ccircle cx='13' cy='13' r='1.2' fill='%2344754b' fill-opacity='0.04'/%3E%3C/svg%3E");
}

/* Message bubble tail - own message (right, green) */
.bubble-tail-right {
  position: relative;
}
.bubble-tail-right::after {
  content: '';
  position: absolute;
  top: 0;
  right: -6px;
  width: 0;
  height: 0;
  border-left: 6px solid #44754b;
  border-bottom: 6px solid transparent;
}

/* Message bubble tail - their message (left, white) */
.bubble-tail-left {
  position: relative;
}
.bubble-tail-left::after {
  content: '';
  position: absolute;
  top: 0;
  left: -6px;
  width: 0;
  height: 0;
  border-right: 6px solid white;
  border-bottom: 6px solid transparent;
}

/* Typing indicator bouncing dots */
@keyframes typingBounce {
  0%, 60%, 100% { transform: translateY(0); }
  30% { transform: translateY(-4px); }
}

.typing-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background-color: #9ca3af;
  animation: typingBounce 1.4s infinite ease-in-out;
}
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }

/* Message slide-in animation */
@keyframes messageAppear {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
.message-appear {
  animation: messageAppear 0.15s ease-out;
}

/* Active conversation in sidebar */
.conversation-active {
  background-color: #f0f5f1 !important;
  border-right: 3px solid #44754b;
}

/* Chat textarea auto-grow limit */
.chat-textarea {
  max-height: 120px;
  overflow-y: auto;
}

/* Noutopiste map marker */
.noutopiste-marker {
  background: transparent !important;
  border: none !important;
}

.noutopiste-upcoming-badge {
  display: inline-block;
  margin-top: 4px;
  padding: 1px 8px;
  background: #bf763b;
  color: white;
  font-size: 10px;
  font-weight: 700;
  font-family: 'Figtree', sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  border-radius: 9999px;
  white-space: nowrap;
  box-shadow: 0 1px 4px rgba(0,0,0,0.2);
}
