.progress {
  animation: progress 1s infinite linear;
}

.left-right {
    transform-origin: 0% 50%;
}
    @keyframes progress {
    0% {
        transform:  translateX(0) scaleX(0);
    }
    40% {
        transform:  translateX(0) scaleX(0.4);
    }
    100% {
        transform:  translateX(100%) scaleX(0.5);
    }
}
/*
 * PWA Visibility System
 *
 * This CSS file handles PWA-specific styling that activates when
 * the app is running in standalone mode (installed as PWA).
 *
 * Loaded separately from Tailwind to ensure proper cascade behavior.
 */
html,
body {
    overscroll-behavior-y: none;
}
/* Default state: PWA elements hidden in browser mode */
.pwa-show {
    display: none !important;
}

.pwa-hide {
    display: block;
}

.pwa-header {
    padding-top: 0;
}

.pwa-bottom-nav {
    padding-bottom: 0;
}

.pwa-main-content {
    padding-bottom: 0;
}

/* PWA standalone mode - activated when app is installed */
@media all and (display-mode: standalone) {
    /* Show PWA-specific elements */
    .pwa-show {
        display: flex !important;
    }

    /* PWA page header needs display block not flex */
    .pwa-page-header.pwa-show {
        display: block !important;
    }

    /* Hide browser-specific elements */
    .pwa-hide {
        display: none !important;
    }

    /* PWA header extends under status bar */
    .pwa-header {
        padding-top: env(safe-area-inset-top);
    }

    /* PWA bottom nav respects home indicator */
    .pwa-bottom-nav {
        padding-bottom: env(safe-area-inset-bottom);
    }

    /* Main content - reset negative margin, add bottom padding for nav */
    .pwa-main-content {
        margin-top: 0 !important;
        padding-top: 0;
        padding-bottom: calc(5rem + env(safe-area-inset-bottom));
    }

    /* Hide footer in PWA mode */
    footer {
        display: none !important;
    }

    /* Adjust breadcrumbs for PWA - hide them as we have bottom nav */
    nav[aria-label="Breadcrumb"] {
        display: none !important;
    }

    /* Remove the drop-shadow container in PWA mode */
    .pwa-content-card {
        background: transparent !important;
        box-shadow: none !important;
        border-radius: 0 !important;
        padding-left: 0.5rem !important;
        padding-right: 0.5rem !important;
        padding-top: 0.5rem !important;
        padding-bottom: 0.5rem !important;
        margin: 0 !important;
    }
}

/*
 * Native iOS app mode (docs/native_ios_hybrid_plan.md Phase 3)
 *
 * The shell's WKWebView UA ends in "CellaryiOS/<version>"; the server stamps
 * <body class="native-app"> (ApplicationController#native_app_request?).
 * These rules mirror the standalone block above so app-mode pages get the
 * same chrome swap, with one deliberate exception: no bottom-nav spacing.
 * The native tab bar lives OUTSIDE the webview (and the pwa-bottom-nav
 * partial isn't rendered server-side in app mode), so .pwa-main-content
 * keeps its default padding-bottom instead of the 5rem standalone reserve.
 */
body.native-app .pwa-show {
    display: flex !important;
}

body.native-app .pwa-page-header.pwa-show {
    display: block !important;
}

body.native-app .pwa-hide {
    display: none !important;
}

body.native-app .pwa-header {
    padding-top: env(safe-area-inset-top);
}

body.native-app .pwa-main-content {
    margin-top: 0 !important;
    padding-top: 0;
}

body.native-app footer {
    display: none !important;
}

body.native-app nav[aria-label="Breadcrumb"] {
    display: none !important;
}

body.native-app .pwa-content-card {
    background: transparent !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    padding-left: 0.5rem !important;
    padding-right: 0.5rem !important;
    padding-top: 0.5rem !important;
    padding-bottom: 0.5rem !important;
    margin: 0 !important;
}

/* PWA View Transitions - simple cross-fade */
@media all and (display-mode: standalone) {
    @view-transition {
        navigation: auto;
    }

    ::view-transition-old(root),
    ::view-transition-new(root) {
        animation-duration: 200ms;
        animation-timing-function: ease-out;
    }
}

/* Safe area utilities for PWA */
.pt-safe {
    padding-top: env(safe-area-inset-top);
}

.pb-safe {
    padding-bottom: env(safe-area-inset-bottom);
}

.pl-safe {
    padding-left: env(safe-area-inset-left);
}

.pr-safe {
    padding-right: env(safe-area-inset-right);
}
swiper-slide a img {
  top:-100%; left:0; right: 0; bottom:-100%;
}

swiper-slide a {
  display: block;
  overflow: hidden;
}
/* Tasting Notes Mockup Styles */

.tasting-sidebar-container {
  display: flex;
  flex-direction: column;
}

@media (min-width: 1024px) {
  .tasting-sidebar-container {
    flex-direction: row;
  }

  .tasting-sidebar {
    display: block !important;
    width: 288px;
    flex-shrink: 0;
  }

  .tasting-main-content {
    flex: 1;
    padding-right: 1rem;
  }
}

@media (max-width: 1023px) {
  .tasting-main-content {
    flex: 1;
  }
}

/* --- Vue island pre-mount skeleton --------------------------------------
   Server-rendered inside #tasting-notes-app; Vue's mount() replaces it.
   Holds vertical space so the page doesn't jump when the island appears. */

.tn-skeleton {
  min-height: 60vh;
  padding-top: 0.5rem;
  animation: tn-skeleton-pulse 1.8s ease-in-out infinite;
}

.tn-skeleton-bar {
  background-color: #e5e7eb;
  border-radius: 0.5rem;
}

.tn-skeleton-title {
  height: 2.25rem;
  width: 66%;
  max-width: 22rem;
  margin-bottom: 0.75rem;
}

.tn-skeleton-meta {
  height: 1rem;
  width: 40%;
  max-width: 12rem;
  margin-bottom: 1.5rem;
}

.tn-skeleton-search {
  /* matches the h-11 producer-search row */
  height: 2.75rem;
  margin-bottom: 1.5rem;
}

.tn-skeleton-card {
  height: 18rem;
  border-radius: 0.75rem;
}

@keyframes tn-skeleton-pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.55;
  }
}

/* Brisk ease-in when the mounted app replaces the skeleton */
.tn-app-enter {
  animation: tn-app-enter 150ms ease-in both;
}

@keyframes tn-app-enter {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* Owner settings-sidebar placeholder — desktop only (the real sidebar is an
   off-canvas overlay below lg, so no space to hold there) */
.tn-skeleton-sidebar {
  display: none;
}

@media (min-width: 1024px) {
  .tn-skeleton {
    /* matches the mounted .tasting-sidebar-container lg gap (App.vue) */
    gap: 2rem;
  }

  .tn-skeleton-sidebar {
    display: block;
    width: 288px;
    flex-shrink: 0;
    padding: 1rem 1rem 0;
  }

  .tn-skeleton-sidebar-title {
    height: 1.25rem;
    width: 50%;
    margin-bottom: 1rem;
  }

  .tn-skeleton-sidebar-block {
    height: 14rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tn-skeleton,
  .tn-app-enter {
    animation: none;
  }
}
.playfair-display-600 {
  font-family: "Playfair Display", serif;
  font-optical-sizing: auto;
  font-weight: 600
  font-style: normal;
}

.fraunces-400i {
  font-family: "Fraunces", serif;
  font-optical-sizing: auto;
  font-weight: 600;
  font-style: italic;
  font-variation-settings:
    "SOFT" 50,
    "WONK" 0;
}

/* Upright Fraunces for display headings (producer marquee). */
.fraunces-600 {
  font-family: "Fraunces", serif;
  font-optical-sizing: auto;
  font-weight: 600;
  font-style: normal;
  font-variation-settings:
    "SOFT" 50,
    "WONK" 0;
}
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *


 */

 [x-cloak] { display: none !important; }
 
