/* ========================================
   Islafy — Design System & Component Styles
   Enhanced with animations & polish
   ======================================== */

/* --- Custom Properties (Design Tokens) --- */
:root {
  /* Brand greens.

     WCAG 2.1 note: --color-primary is 3.39:1 on white. That clears the 3:1
     bar for non-text (borders, dots, focus rings, decorative fills) but
     fails the 4.5:1 text bar, so it must never carry text or sit behind
     white text. Use --color-primary-dark for text and for filled buttons. */
  --color-primary: #1D9E75;        /* non-text only — 3.39:1 on white */
  --color-primary-light: #E1F5EE;
  --color-primary-dark: #0F6E56;   /* text/links/fills — 6.20:1 on white, 5.46:1 on the mint tint */
  --color-primary-darker: #0A5241; /* link + button hover — 9.15:1 on white */
  --color-primary-grad: #0C8265;   /* far gradient stop under white text — 4.78:1 */
  --color-primary-border: #9FE1CB;

  /* Map palette */
  --color-sea-blue: #d4eaf5;
  --color-island-green: #b8d4a8;

  /* Spot type colors */
  --color-beach: #1D9E75;
  --color-lagoon: #378ADD;
  --color-nature: #EF9F27;
  --color-diving: #D4537E;
  --color-viewpoint: #7F77DD;
  --color-river: #5DCAA5;

  /* Neutrals */
  --color-text: #1a1a1a;
  --color-text-muted: #6b7280;        /* 4.83:1 on white — the lightest grey that passes */
  --color-text-muted-strong: #4b5563; /* 7.56:1 — muted text on the mint/blue tints */
  --color-border: #e5e7eb;
  --color-bg: #ffffff;
  --color-bg-gray: #f9fafb;

  /* Typography */
  --font-family: 'Inter', system-ui, -apple-system, sans-serif;
  --line-height-body: 1.65;
  --line-height-guide: 1.7;

  /* Layout */
  --container-max: 1100px;
  --sidebar-width: 280px;
  --nav-height: 64px;

  /* Shadows */
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.06);
  --shadow-md: 0 4px 6px rgba(0,0,0,0.04), 0 2px 12px rgba(0,0,0,0.06);
  --shadow-lg: 0 8px 24px rgba(0,0,0,0.06), 0 4px 16px rgba(0,0,0,0.08);
  --shadow-xl: 0 16px 48px rgba(0,0,0,0.08), 0 8px 24px rgba(0,0,0,0.1);
  --shadow-glow: 0 0 20px rgba(29, 158, 117, 0.15);
}

/* --- Base Reset & Typography --- */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  scroll-behavior: smooth;
}

body {
  font-family: var(--font-family);
  color: var(--color-text);
  line-height: var(--line-height-body);
  background: var(--color-bg);
  overflow-x: hidden;
}

a {
  color: var(--color-primary-dark);
  text-decoration: none;
  transition: color 0.2s;
}

a:hover {
  color: var(--color-primary-darker);
  text-decoration: none;
}

a[style*="color:white"]:hover,
a[style*="color: white"]:hover,
a[style*="color:#fff"]:hover {
  color: white;
}

img {
  max-width: 100%;
  display: block;
}

/* --- Animations --- */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

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

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

@keyframes pulse-ring {
  0% { transform: scale(1); opacity: 1; }
  100% { transform: scale(2.5); opacity: 0; }
}

@keyframes float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-8px); }
}

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

@keyframes spin {
  to { transform: rotate(360deg); }
}

@keyframes gradientShift {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

@keyframes wave {
  0% { transform: translateX(0) translateZ(0) scaleY(1); }
  50% { transform: translateX(-25%) translateZ(0) scaleY(0.55); }
  100% { transform: translateX(-50%) translateZ(0) scaleY(1); }
}

.animate-fade-in-up {
  animation: fadeInUp 0.6s ease-out both;
}

.animate-fade-in {
  animation: fadeIn 0.5s ease-out both;
}

.animate-slide-left {
  animation: slideInLeft 0.5s ease-out both;
}

.animate-slide-right {
  animation: slideInRight 0.5s ease-out both;
}

/* Stagger delays */
.delay-1 { animation-delay: 0.1s; }
.delay-2 { animation-delay: 0.2s; }
.delay-3 { animation-delay: 0.3s; }
.delay-4 { animation-delay: 0.4s; }
.delay-5 { animation-delay: 0.5s; }
.delay-6 { animation-delay: 0.6s; }

/* Section labels */
.section-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  margin-bottom: 14px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.section-label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, var(--color-border), transparent);
}

/* Price styling */
.price {
  font-weight: 600;
  color: var(--color-primary-dark);
}

/* Guide content */
.guide-content {
  line-height: var(--line-height-guide);
}

/* --- Layout Utilities --- */
.container {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 24px;
}

.two-col {
  display: flex;
  gap: 48px;
  align-items: flex-start;
}

/* Used instead of `py-8` when the page above has no hero band — a spot with no
   cover photo, say. Nothing then separates the title from the site header, so
   the column opens with the extra room the hero would otherwise have given it.
   Sits on the flex container rather than the title so the sidebar drops by the
   same amount and the two stay level. */
.two-col--no-hero {
  padding-top: 56px;
  padding-bottom: 32px;
}

.two-col__main {
  flex: 1;
  min-width: 0;
}

.two-col__sidebar {
  width: var(--sidebar-width);
  flex-shrink: 0;
  position: sticky;
  top: calc(var(--nav-height) + 20px);
}

/* --- Navigation (Glassmorphism) --- */
.nav {
  height: var(--nav-height);
  display: flex;
  align-items: center;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid rgba(229, 231, 235, 0.6);
  position: sticky;
  top: 0;
  z-index: 100;
  transition: box-shadow 0.3s;
}

.nav--scrolled {
  box-shadow: var(--shadow-md);
}

.nav__logo {
  font-size: 22px;
  font-weight: 800;
  color: var(--color-primary-dark);
  letter-spacing: -0.03em;
  position: relative;
}

.nav__logo::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 2px;
  background: var(--color-primary);
  border-radius: 1px;
  transition: width 0.3s;
}

.nav__logo:hover::after {
  width: 100%;
}

.nav__links {
  display: flex;
  gap: 8px;
  list-style: none;
  margin-left: auto;
}

.nav__links a {
  color: var(--color-text);
  font-size: 14px;
  font-weight: 500;
  padding: 6px 14px;
  border-radius: 8px;
  transition: all 0.2s;
}

.nav__links a:hover {
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
}

.nav__links a.active {
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  font-weight: 600;
}

/* --- Breadcrumb --- */
.breadcrumb {
  font-size: 13px;
  color: var(--color-text-muted);
  padding: 16px 0;
  animation: fadeIn 0.4s ease-out;
}

.breadcrumb a {
  color: var(--color-text-muted);
  transition: color 0.2s;
}

.breadcrumb a:hover {
  color: var(--color-primary-dark);
}

.breadcrumb span {
  margin: 0 8px;
  opacity: 0.5;
}

/* --- Hero --- */
.hero {
  text-align: center;
  padding: 80px 24px 64px;
  position: relative;
  /* The two decorative circles below are positioned outside this box on
     purpose — ::before sits at right:-20% and is 500px wide. On a desktop
     that bleed is absorbed by the margin either side of the content; on a
     360px phone it reaches roughly 70px past the viewport and drags the
     document wider than the screen, which reads as a blank strip down the
     right of the whole landing page.

     Clipped on the horizontal axis only. `overflow-x: hidden` would force
     the vertical axis to compute as `auto` and turn the hero into a scroll
     container, which would cut ::before's `top: -50%` bleed as well; `clip`
     leaves the other axis `visible`, so the decoration still spills upward
     exactly as designed and only the part that would widen the page is cut.

     Fixing it here rather than on `body`, which already carries
     `overflow-x: hidden` and is evidently not containing this. */
  overflow-x: clip;
  overflow-y: visible;
  /* Background is set via inline style from landing page config */
}

.hero--wave {
  padding-bottom: 112px;
  margin-bottom: -48px;
}

.hero::before,
.hero::after {
  pointer-events: none;
}

.hero::before {
  content: '';
  position: absolute;
  top: -50%;
  right: -20%;
  width: 500px;
  height: 500px;
  background: radial-gradient(circle, rgba(29, 158, 117, 0.08) 0%, transparent 70%);
  border-radius: 50%;
  animation: float 6s ease-in-out infinite;
}

.hero::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: -10%;
  width: 400px;
  height: 400px;
  background: radial-gradient(circle, rgba(55, 138, 221, 0.06) 0%, transparent 70%);
  border-radius: 50%;
  animation: float 8s ease-in-out infinite reverse;
}

.hero__title {
  font-size: 48px;
  font-weight: 800;
  color: var(--color-text);
  margin-bottom: 14px;
  letter-spacing: -0.03em;
  position: relative;
  animation: fadeInUp 0.7s ease-out;
}

.hero__subtitle {
  font-size: 18px;
  color: var(--color-text-muted);
  max-width: 520px;
  margin: 0 auto 32px;
  position: relative;
  animation: fadeInUp 0.7s ease-out 0.15s both;
}

.hero__search {
  max-width: 500px;
  margin: 0 auto;
  position: relative;
  z-index: 50;
  animation: fadeInUp 0.7s ease-out 0.3s both;
}

.hero__search input {
  width: 100%;
  padding: 16px 22px 16px 48px;
  border: 2px solid rgba(159, 225, 203, 0.5);
  border-radius: 14px;
  font-size: 15px;
  font-family: var(--font-family);
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(8px);
  outline: none;
  transition: all 0.3s;
  box-shadow: var(--shadow-sm);
}

.hero__search input:focus {
  border-color: var(--color-primary);
  box-shadow: var(--shadow-md), 0 0 0 4px rgba(29, 158, 117, 0.08);
  background: white;
}

.hero__search input::placeholder {
  color: #6b7280;
}

.hero__search-icon {
  position: absolute;
  left: 18px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-text-muted);
  transition: color 0.2s;
}

/* Wave separator */
.hero-wave {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  overflow: hidden;
  line-height: 0;
  z-index: 2;
  pointer-events: none;
}

.hero-wave svg {
  position: relative;
  display: block;
  width: calc(100% + 1.3px);
  height: 48px;
}

/* --- Area Card --- */
.area-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

.area-card {
  border: 1px solid var(--color-border);
  border-radius: 16px;
  overflow: hidden;
  transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
  background: var(--color-bg);
  cursor: pointer;
}

.area-card:hover {
  box-shadow: var(--shadow-lg);
  transform: translateY(-4px);
  border-color: var(--color-primary-border);
}

.area-card__image {
  height: 160px;
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  padding: 16px;
  font-size: 0;
  color: white;
  position: relative;
  overflow: hidden;
}

.area-card__image::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,0.3), transparent 60%);
  transition: opacity 0.3s;
}

.area-card:hover .area-card__image::after {
  opacity: 0.7;
}

.area-card__body {
  padding: 18px 18px 16px;
}

.area-card__name {
  font-size: 17px;
  font-weight: 700;
  margin-bottom: 4px;
  transition: color 0.2s;
}

.area-card:hover .area-card__name {
  color: var(--color-primary-dark);
}

.area-card__desc {
  font-size: 13px;
  color: var(--color-text-muted);
  margin-bottom: 10px;
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.area-card__count {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-primary-dark);
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.area-card__count::before {
  content: '';
  width: 6px;
  height: 6px;
  background: var(--color-primary);
  border-radius: 50%;
  display: inline-block;
}

/* --- Spot Card --- */
.spot-card {
  display: flex;
  gap: 16px;
  padding: 16px;
  border: 1px solid var(--color-border);
  border-radius: 14px;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  background: var(--color-bg);
  position: relative;
}

.spot-card:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--color-primary-border);
  transform: translateX(4px);
}

.spot-card__image {
  width: 110px;
  height: 85px;
  border-radius: 10px;
  flex-shrink: 0;
  transition: transform 0.3s;
  overflow: hidden;
}

.spot-card:hover .spot-card__image {
  transform: scale(1.03);
}

.spot-card__body {
  flex: 1;
  min-width: 0;
}

.spot-card__name {
  font-size: 15px;
  font-weight: 600;
  margin-bottom: 2px;
  transition: color 0.2s;
}

.spot-card:hover .spot-card__name {
  color: var(--color-primary-dark);
}

.spot-card__area {
  font-size: 12px;
  color: var(--color-text-muted);
  margin-bottom: 4px;
}

.spot-card__desc {
  font-size: 13px;
  color: var(--color-text-muted);
  line-height: 1.5;
}

.spot-card__meta {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
}

/* --- Badges & Tags --- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 600;
  padding: 4px 12px;
  border-radius: 20px;
  text-transform: capitalize;
  transition: transform 0.2s;
}

.badge:hover {
  transform: scale(1.05);
}

.badge--beach { background: rgba(29, 158, 117, 0.1); color: var(--color-primary-dark); }
.badge--lagoon { background: rgba(55, 138, 221, 0.1); color: var(--color-lagoon); }
.badge--nature { background: rgba(239, 159, 39, 0.1); color: var(--color-nature); }
.badge--diving { background: rgba(212, 83, 126, 0.1); color: var(--color-diving); }
.badge--viewpoint { background: rgba(127, 119, 221, 0.1); color: var(--color-viewpoint); }
.badge--river { background: rgba(93, 202, 165, 0.1); color: var(--color-river); }

.badge--must-visit {
  background: linear-gradient(135deg, var(--color-primary-dark), var(--color-primary-grad));
  color: white;
  box-shadow: 0 2px 8px rgba(29, 158, 117, 0.3);
}

.tag {
  display: inline-block;
  font-size: 12px;
  font-weight: 500;
  padding: 3px 12px;
  border-radius: 8px;
  background: var(--color-bg-gray);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
  transition: all 0.2s;
}

.tag:hover {
  background: var(--color-primary-light);
  border-color: var(--color-primary-border);
  color: var(--color-primary-dark);
}

/* Type dot (small colored circle) */
.type-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
  position: relative;
}

.type-dot--beach { background: var(--color-beach); }
.type-dot--lagoon { background: var(--color-lagoon); }
.type-dot--nature { background: var(--color-nature); }
.type-dot--diving { background: var(--color-diving); }
.type-dot--viewpoint { background: var(--color-viewpoint); }
.type-dot--river { background: var(--color-river); }

/* --- Filter Chips --- */
.filter-chips {
  display: flex;
  gap: 8px;
  padding: 14px 0;
  flex-wrap: wrap;
}

.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 16px;
  border-radius: 24px;
  font-size: 13px;
  font-weight: 500;
  border: 1px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-text);
  cursor: pointer;
  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

.filter-chip:hover {
  border-color: var(--color-primary-border);
  background: var(--color-primary-light);
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}

.filter-chip--active {
  background: linear-gradient(135deg, var(--color-primary-dark), var(--color-primary-grad));
  color: white;
  border-color: transparent;
  box-shadow: 0 2px 8px rgba(29, 158, 117, 0.3);
}

.filter-chip--active:hover {
  background: linear-gradient(135deg, var(--color-primary-darker), var(--color-primary-dark));
  border-color: transparent;
}

/* --- Blog Card --- */
.blog-card {
  border: 1px solid #e5e7eb;
  border-radius: 14px;
  overflow: hidden;
  background: #fff;
  cursor: pointer;
  transition: box-shadow 0.2s, transform 0.2s;
}

.blog-card:hover {
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
  transform: translateY(-2px);
}

.blog-card__image {
  height: 180px;
  position: relative;
  display: flex;
  align-items: flex-end;
  padding: 12px;
}

.blog-card__tag {
  font-size: 11px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.9);
  color: #374151;
  backdrop-filter: blur(4px);
}

.blog-card__body {
  padding: 16px 18px 18px;
}

.blog-card__title {
  font-size: 16px;
  font-weight: 700;
  line-height: 1.3;
  margin-bottom: 8px;
}

.blog-card__title a {
  color: #111827;
  text-decoration: none;
}

.blog-card__title a:hover {
  color: var(--color-primary-dark);
}

.blog-card__excerpt {
  font-size: 13px;
  color: #6b7280;
  line-height: 1.5;
  margin-bottom: 12px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.blog-card__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  color: #6b7280;
}

.blog-card__author {
  font-weight: 500;
  color: #6b7280;
}

@media (max-width: 640px) {
  #blogGrid {
    grid-template-columns: 1fr !important;
  }
}

/* --- Service Chip (inline in guide text) --- */
.service-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 16px;
  border-radius: 24px;
  font-size: 13px;
  font-weight: 600;
  background: linear-gradient(135deg, var(--color-primary-light), #d4f5e9);
  color: var(--color-primary-dark);
  border: 1px solid var(--color-primary-border);
  cursor: pointer;
  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  white-space: nowrap;
}

.service-chip:hover {
  background: linear-gradient(135deg, var(--color-primary-border), var(--color-primary-light));
  box-shadow: 0 2px 8px rgba(29, 158, 117, 0.2);
  transform: translateY(-1px);
}

.service-chip::before {
  content: '→';
  font-weight: 700;
  transition: transform 0.2s;
}

.service-chip:hover::before {
  transform: translateX(2px);
}

/* --- Local Tip Box --- */
.local-tip {
  border-left: 4px solid var(--color-primary);
  background: linear-gradient(135deg, var(--color-primary-light), #e8faf3);
  padding: 20px 24px;
  border-radius: 0 12px 12px 0;
  margin: 24px 0;
  position: relative;
  overflow: hidden;
  transition: box-shadow 0.3s;
}

.local-tip:hover {
  box-shadow: var(--shadow-md);
}

.local-tip::before {
  content: '';
  position: absolute;
  top: -20px;
  right: -20px;
  width: 80px;
  height: 80px;
  background: radial-gradient(circle, rgba(29, 158, 117, 0.08) 0%, transparent 70%);
  border-radius: 50%;
}

.local-tip__label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-primary-dark);
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.local-tip__label::before {
  content: '💡';
  font-size: 14px;
}

.local-tip__text {
  font-size: 14px;
  color: var(--color-primary-dark);
  line-height: var(--line-height-guide);
}

/* --- Sidebar Widget --- */
.sidebar-widget {
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 18px;
  margin-bottom: 16px;
  transition: all 0.3s;
  background: white;
}

.sidebar-widget:hover {
  box-shadow: var(--shadow-sm);
  border-color: var(--color-primary-border);
}

.sidebar-widget__title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--color-border);
}

.sidebar-widget__row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding: 10px 0;
  font-size: 13px;
  border-bottom: 1px solid var(--color-bg-gray);
  transition: background 0.2s;
}

.sidebar-widget__row:hover {
  background: var(--color-bg-gray);
  margin: 0 -8px;
  padding-left: 8px;
  padding-right: 8px;
  border-radius: 6px;
}

.sidebar-widget__row:last-child {
  border-bottom: none;
}

.sidebar-widget__row-label {
  color: var(--color-text-muted);
}

.sidebar-widget__row-value {
  font-weight: 500;
  text-align: right;
}

/* A sidebar widget that folds shut on a phone. See IslafyWeb.MobileComponents:
   the markup is a <details> rendered `open`, and an inline script clears `open`
   only below the 768px breakpoint. Everything that makes it *look* collapsible
   -- the pointer, the chevron -- therefore lives in the media query too, so
   above the breakpoint this is a .sidebar-widget and nothing more. */
.collapsible-widget__summary {
  /* <summary> defaults to `display: list-item`, which would put a disclosure
     triangle in front of the title. Dropping the list-item display removes it
     in every current browser; the -webkit- pseudo covers older Safari, which
     draws its own marker regardless of display. */
  display: block;
  list-style: none;
}

.collapsible-widget__summary::-webkit-details-marker {
  display: none;
}

/* ...but "nothing more" needs saying out loud, because a <summary> keeps
   toggling its <details> at every width. Taking the pointer off it is what
   makes the desktop widget permanently open: a click on the title lands on the
   widget box behind it instead, so there is nothing to fold, and no pointer
   cursor suggests otherwise. This is also the half that survives with
   JavaScript off. The keyboard half is cancelled by the inline script in
   IslafyWeb.MobileComponents; with scripting off a keyboard can still toggle
   the widget, which beats hiding an open <details>' content with CSS -- see
   the note above for why that is not an option.

   The cost is that the title itself can no longer be drag-selected on desktop.
   It is an 11px uppercase label, so that is the cheaper side of the trade. */
@media (min-width: 769px) {
  .collapsible-widget__summary {
    pointer-events: none;
    cursor: default;
  }
}

/* Where to stay: one card per place, each with its own booking buttons
   underneath. The gap only shows between rendered children, so a service with
   no messengers keeps its card flush. */
.where-to-stay__item {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.where-to-stay__item + .where-to-stay__item {
  margin-top: 14px;
}

/* --- Price Table --- */
.price-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 14px;
  border: 1px solid var(--color-border);
  border-radius: 12px;
  overflow: hidden;
}

.price-table th {
  text-align: left;
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  padding: 12px 16px;
  background: var(--color-bg-gray);
  border-bottom: 1px solid var(--color-border);
}

.price-table td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--color-bg-gray);
  transition: background 0.2s;
}

.price-table tr:hover td {
  background: rgba(225, 245, 238, 0.3);
}

.price-table tr:last-child td {
  border-bottom: none;
}

.price-table td:nth-child(2) {
  font-weight: 600;
  color: var(--color-primary-dark);
  white-space: nowrap;
}

.price-table td:nth-child(3) {
  color: var(--color-text-muted);
  font-size: 13px;
}

/* --- Quick Facts --- */
.quick-facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
}

.quick-fact {
  padding: 12px 0;
  border-bottom: 1px solid var(--color-bg-gray);
}

.quick-fact:nth-child(odd) {
  padding-right: 10px;
}

.quick-fact:nth-child(even) {
  padding-left: 10px;
}

.quick-fact__label {
  font-size: 10px;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 500;
}

.quick-fact__value {
  font-size: 14px;
  font-weight: 600;
  margin-top: 3px;
}

/* --- Photo Strip --- */
.photo-strip {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 4px;
  border-radius: 16px;
  overflow: hidden;
  margin-bottom: 32px;
  box-shadow: var(--shadow-md);
}

.photo-strip__item {
  height: 240px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 13px;
  font-weight: 500;
  overflow: hidden;
  cursor: pointer;
}

.photo-strip__item::before {
  content: '';
  position: absolute;
  inset: 0;
  background: inherit;
  transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 0;
}

.photo-strip__item:hover::before {
  transform: scale(1.08);
}

.photo-strip__item--overlay::after {
  content: '📷 View all photos';
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(2px);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 600;
  color: white;
  transition: all 0.3s;
  z-index: 1;
}

.photo-strip__item--overlay:hover::after {
  background: rgba(0, 0, 0, 0.55);
}

/* --- Map Placeholder --- */
.map-container {
  background: var(--color-sea-blue);
  position: relative;
  overflow: hidden;
  border-radius: 12px;
}

.map-pin {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2.5px solid white;
  position: absolute;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 2;
}

.map-pin::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 2px solid currentColor;
  opacity: 0;
  animation: pulse-ring 2s ease-out infinite;
}

.map-pin:hover {
  transform: scale(1.5);
  z-index: 10;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

.map-pin--beach { background: var(--color-beach); color: var(--color-beach); }
.map-pin--lagoon { background: var(--color-lagoon); color: var(--color-lagoon); }
.map-pin--nature { background: var(--color-nature); color: var(--color-nature); }
.map-pin--diving { background: var(--color-diving); color: var(--color-diving); }
.map-pin--viewpoint { background: var(--color-viewpoint); color: var(--color-viewpoint); }
.map-pin--river { background: var(--color-river); color: var(--color-river); }

.map-popup {
  position: absolute;
  background: white;
  border-radius: 12px;
  padding: 14px 16px;
  box-shadow: var(--shadow-xl);
  font-size: 13px;
  z-index: 20;
  min-width: 190px;
  border: 1px solid rgba(0,0,0,0.06);
  animation: fadeInUp 0.3s ease-out;
}

.map-popup::after {
  content: '';
  position: absolute;
  bottom: -6px;
  left: 24px;
  width: 12px;
  height: 12px;
  background: white;
  transform: rotate(45deg);
  box-shadow: 3px 3px 4px rgba(0,0,0,0.04);
  border-right: 1px solid rgba(0,0,0,0.06);
  border-bottom: 1px solid rgba(0,0,0,0.06);
}

.map-popup__name {
  font-weight: 700;
  font-size: 14px;
  margin-bottom: 2px;
}

.map-popup__meta {
  color: var(--color-text-muted);
  font-size: 12px;
  margin-bottom: 8px;
}

.map-popup__link {
  font-size: 12px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  transition: gap 0.2s;
}

.map-popup__link:hover {
  gap: 6px;
}

.map-legend {
  position: absolute;
  bottom: 20px;
  right: 20px;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(8px);
  border-radius: 12px;
  padding: 12px 16px;
  box-shadow: var(--shadow-md);
  font-size: 11px;
  z-index: 10;
  border: 1px solid rgba(0,0,0,0.06);
}

.map-legend__item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  font-weight: 500;
}

/* --- Meta Pills --- */
.meta-pills {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.meta-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 500;
  padding: 6px 14px;
  border-radius: 24px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  border: 1px solid var(--color-primary-border);
  transition: all 0.2s;
}

.meta-pill:hover {
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}

/* --- Steps (How to get there) --- */
.steps {
  counter-reset: step;
  list-style: none;
}

.step {
  counter-increment: step;
  position: relative;
  padding-left: 40px;
  padding-bottom: 24px;
  border-left: 2px solid var(--color-primary-border);
  margin-left: 14px;
  transition: border-color 0.2s;
}

.step:last-child {
  border-left: 2px solid transparent;
  padding-bottom: 0;
}

.step::before {
  content: counter(step);
  position: absolute;
  left: -15px;
  top: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--color-primary-dark), var(--color-primary-grad));
  color: white;
  font-size: 12px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 6px rgba(29, 158, 117, 0.3);
  transition: transform 0.2s;
}

.step:hover::before {
  transform: scale(1.15);
}

.step__text {
  font-size: 14px;
  line-height: 1.6;
}

/* --- Travel options (How to get there) ---
   Deliberately unboxed: the numbered steps are the section's visual weight,
   the way they were before options existed. A single option renders as the
   section label, an optional muted meta line, and the steps — no card, no
   border, no title. */
.travel-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  margin-bottom: 12px;
  font-size: 13px;
  color: var(--color-text-muted);
}

/* Middot between the duration and the price, on one muted line. */
.travel-meta__item + .travel-meta__item::before {
  content: "\00b7";
  margin-right: 8px;
}

.travel-option__description {
  font-size: 14px;
  color: #374151;
  line-height: 1.6;
  margin: 0 0 14px;
}

/* Tabs, CSS only: one hidden radio per option drives its label (the tab) and
   the panel that follows it, through the `+` sibling combinator. The public
   pages are plain server-rendered HTML, so there is no JavaScript here; a
   radio group is keyboard operable on its own (Tab to the group, arrow keys
   between tabs). The flex container plus `order` puts every label on the tab
   row and every panel, full width, underneath it. */
.travel-tabs {
  display: flex;
  flex-wrap: wrap;
  position: relative;
}

/* Visually hidden, still focusable: `display: none` would take the radios out
   of the tab order and break keyboard operation entirely. */
.travel-tabs__radio {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Same chip idiom as the service hint inside a step: light green fill when
   active, nothing but muted text when not. No card, no shadow. */
.travel-tabs__tab {
  order: 1;
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  margin: 0 8px 16px 0;
  padding: 6px 14px;
  border: 1px solid transparent;
  border-radius: 20px;
  background: var(--color-bg-gray);
  font-size: 13px;
  font-weight: 600;
  color: var(--color-text-muted);
  cursor: pointer;
  overflow-wrap: anywhere;
  transition: all 0.2s;
}

.travel-tabs__tab:hover {
  color: var(--color-primary-dark);
}

.travel-tabs__radio:checked + .travel-tabs__tab {
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

/* The tab is the only visible part of the control, so it carries the focus
   ring for its hidden radio. */
.travel-tabs__radio:focus-visible + .travel-tabs__tab {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.travel-tabs__panel {
  order: 2;
  width: 100%;
  display: none;
}

.travel-tabs__radio:checked + .travel-tabs__tab + .travel-tabs__panel {
  display: block;
}

/* --- Footer --- */
.footer {
  border-top: 1px solid var(--color-border);
  padding: 40px 0;
  margin-top: 72px;
  text-align: center;
  color: var(--color-text-muted);
  font-size: 13px;
  background: var(--color-bg-gray);
}

.footer a {
  color: var(--color-text-muted);
  margin: 0 14px;
  padding: 4px 0;
  position: relative;
  transition: color 0.2s;
}

.footer a::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 0;
  height: 1px;
  background: var(--color-primary);
  transition: width 0.3s;
}

.footer a:hover {
  color: var(--color-primary-dark);
}

.footer a:hover::after {
  width: 100%;
}

/* --- Nearby Spots --- */
.nearby-spot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 6px;
  border-bottom: 1px solid var(--color-bg-gray);
  font-size: 13px;
  border-radius: 6px;
  transition: all 0.2s;
}

.nearby-spot:hover {
  background: var(--color-primary-light);
  padding-left: 10px;
}

.nearby-spot:last-child {
  border-bottom: none;
}

.nearby-spot__name {
  font-weight: 500;
  color: var(--color-primary-dark);
}

.nearby-spot__distance {
  color: var(--color-text-muted);
  font-size: 12px;
  font-weight: 500;
}

/* --- Mobile Menu --- */
.nav__hamburger {
  display: none;
  width: 36px;
  height: 36px;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  cursor: pointer;
  background: none;
  border: none;
  color: var(--color-text);
  margin-left: auto;
  transition: background 0.2s;
}

.nav__hamburger:hover {
  background: var(--color-bg-gray);
}

.nav__hamburger span {
  display: block;
  width: 18px;
  height: 2px;
  background: currentColor;
  border-radius: 1px;
  position: relative;
  transition: all 0.3s;
}

.nav__hamburger span::before,
.nav__hamburger span::after {
  content: '';
  position: absolute;
  width: 18px;
  height: 2px;
  background: currentColor;
  border-radius: 1px;
  left: 0;
  transition: all 0.3s;
}

.nav__hamburger span::before { top: -6px; }
.nav__hamburger span::after { top: 6px; }

.nav__hamburger.open span { background: transparent; }
.nav__hamburger.open span::before { top: 0; transform: rotate(45deg); }
.nav__hamburger.open span::after { top: 0; transform: rotate(-45deg); }

.mobile-menu {
  display: none;
  position: fixed;
  top: var(--nav-height);
  left: 0;
  right: 0;
  background: rgba(255, 255, 255, 0.97);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--color-border);
  box-shadow: var(--shadow-lg);
  z-index: 99;
  padding: 8px 0;
  animation: fadeIn 0.2s ease-out;
}

.mobile-menu.open {
  display: block;
}

.mobile-menu a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 24px;
  font-size: 15px;
  font-weight: 500;
  color: var(--color-text);
  transition: all 0.2s;
}

.mobile-menu a:hover,
.mobile-menu a.active {
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

/* --- Search Dropdown --- */
.search-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: white;
  border-radius: 14px;
  box-shadow: var(--shadow-xl);
  border: 1px solid var(--color-border);
  overflow: hidden;
  display: none;
  z-index: 60;
  animation: fadeInUp 0.2s ease-out;
}

.search-dropdown.open {
  display: block;
}

.search-dropdown__item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 18px;
  transition: background 0.15s;
  cursor: pointer;
}

.search-dropdown__item:hover {
  background: var(--color-bg-gray);
}

.search-dropdown__item-name {
  font-size: 14px;
  font-weight: 500;
}

.search-dropdown__item-meta {
  font-size: 12px;
  color: var(--color-text-muted);
}

.search-dropdown__hint {
  padding: 10px 18px;
  font-size: 11px;
  color: var(--color-text-muted);
  background: var(--color-bg-gray);
  border-top: 1px solid var(--color-border);
}

/* --- Updated Timestamp --- */
.updated-at {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--color-text-muted);
}

.updated-at svg {
  opacity: 0.5;
}

/* --- Table of Contents --- */
.toc {
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 18px;
  margin-bottom: 16px;
  background: white;
}

.toc__title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  margin-bottom: 10px;
}

.toc__link {
  display: block;
  padding: 6px 0 6px 12px;
  font-size: 13px;
  color: var(--color-text-muted);
  border-left: 2px solid var(--color-border);
  transition: all 0.2s;
}

.toc__link:hover,
.toc__link.active {
  color: var(--color-primary-dark);
  border-left-color: var(--color-primary);
  background: linear-gradient(90deg, var(--color-primary-light), transparent);
  padding-left: 14px;
}

/* --- Feedback Row --- */
.feedback-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 20px;
  margin-top: 32px;
  border-top: 1px solid var(--color-border);
  font-size: 13px;
  color: var(--color-text-muted);
}

.feedback-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 16px;
  border-radius: 8px;
  border: 1px solid var(--color-border);
  background: white;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s;
  color: var(--color-text);
}

.feedback-btn:hover {
  border-color: var(--color-primary-border);
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

/* --- Difficulty Badge --- */
/* Layout only. The colour is inlined by <.difficulty_badge>, which reads it
   from the difficulty level record so admins can recolour or add levels. */
.difficulty {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 600;
  padding: 4px 12px;
  border-radius: 20px;
}

/* --- Photo Gallery --- */
/* Every photo is the same small box, in a grid that wraps instead of scrolling
   sideways, so a gallery of four shows four thumbnails and nothing is hidden
   behind a lead image. Used by spot, area, service, route and blog pages, so
   the track size has to hold up in both the full container and the narrower
   content column. */
.photo-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 8px;
}

.photo-gallery__item {
  display: block;
  padding: 0;
  border: none;
  background: none;
  border-radius: 12px;
  overflow: hidden;
  cursor: pointer;
  aspect-ratio: 4 / 3;
  transition: transform 0.15s, box-shadow 0.15s;
}

.photo-gallery__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.photo-gallery__item:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
}

.photo-gallery__item:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* A video in the same grid. Everything that makes a tile a tile — the 4:3 box,
   the radius, the clipping, the hover lift, the focus ring — is inherited from
   .photo-gallery__item above, because an admin who dragged a clip into third
   place meant a tile in third place and not a differently shaped thing. The
   only thing this modifier adds is the positioning context the badges below
   need; they are the tile's whole visual difference.

   Source order does the layering: the poster (or the placeholder standing in
   for it) is written first, the play badge and the provider chip after, so
   they paint over it without a z-index anywhere. */
.photo-gallery__item--video {
  position: relative;
}

/* Always present on a video tile, poster or no poster — it is the one mark
   that says "this plays" before anything is clicked. Light on dark so it
   reads over a bright still and a dark one alike. */
.photo-gallery__play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.9);
  color: var(--color-text);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
  /* The button is the whole tile. A badge that took the click would leave a
     dead ring in the middle of the target and nowhere obvious to press. */
  pointer-events: none;
  transition: background 0.15s, transform 0.15s;
}

.photo-gallery__item--video:hover .photo-gallery__play {
  background: rgba(255, 255, 255, 1);
  transform: translate(-50%, -50%) scale(1.08);
}

/* Stands in for the poster when there is none. `Islafy.Media.poster_url/2`
   returns nil rather than falling back to the video's own url, so this is a
   real and ordinary state — no ffmpeg on the server means an uploaded clip
   often has no still — and it is drawn as a deliberate one: a filled dark
   panel with a film icon, not the grey box and torn-page glyph a browser
   shows for an image it could not load. */
.photo-gallery__placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #1f2937;
  color: #9ca3af;
}

/* Which service an embed comes from, told at a glance rather than by reading
   a url. Only embeds carry it; an uploaded file has no provider. */
.photo-gallery__provider {
  position: absolute;
  bottom: 6px;
  left: 6px;
  padding: 2px 6px;
  border-radius: 9999px;
  font-size: 10px;
  font-weight: 600;
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
}

/* The players themselves, cloned out of their <template> into the lightbox.
   gallery.js sets display, width, height and border inline on the clone —
   it has to, since it runs on admin pages too and those never load this
   file — so what is left here is the polish that only the public side needs.
   Nothing below repeats a property gallery.js sets. */
.gallery-player {
  border-radius: 12px;
  background: #000;
}

/* A 16:9 clip in a 4:3 box, or the other way about, is letterboxed rather
   than cropped: this is the frame the visitor came to watch. */
.gallery-player--file {
  object-fit: contain;
}

/* --- Currency Hint --- */
.currency-hint {
  font-size: 11px;
  color: var(--color-text-muted);
  font-weight: 400;
}

/* --- Trust Banner --- */
.trust-banner {
  background: var(--color-bg-gray);
  border: 1px solid var(--color-border);
  border-radius: 16px;
  padding: 28px 32px;
  display: flex;
  align-items: center;
  gap: 24px;
}

.trust-banner__icon {
  width: 56px;
  height: 56px;
  border-radius: 14px;
  background: var(--color-primary-light);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--color-primary-dark);
}

.trust-banner__text h3 {
  font-size: 15px;
  font-weight: 700;
  margin-bottom: 4px;
}

.trust-banner__text p {
  font-size: 13px;
  color: var(--color-text-muted);
  line-height: 1.5;
}

/* --- Spot Mini Map --- */
.spot-map {
  border: 1px solid var(--color-border);
  border-radius: 14px;
  overflow: hidden;
  margin-bottom: 16px;
  background: white;
}

.spot-map__map {
  height: 160px;
  background: var(--color-sea-blue);
  position: relative;
  cursor: pointer;
  transition: filter 0.2s;
}

.spot-map__map:hover {
  filter: brightness(0.97);
}

.spot-map__pin {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -100%);
  z-index: 2;
}

.spot-map__pin-dot {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 3px solid white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  position: relative;
}

.spot-map__pin-dot::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid;
  opacity: 0.25;
  animation: pulse-ring 2s ease-out infinite;
}

.spot-map__pin-label {
  position: absolute;
  top: -32px;
  left: 50%;
  transform: translateX(-50%);
  background: white;
  padding: 3px 10px;
  border-radius: 6px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
}

/* Mini island shapes for spot map */
.spot-map__island {
  position: absolute;
  background: var(--color-island-green);
  border-radius: 40%;
  opacity: 0.7;
}

.spot-map__body {
  padding: 12px 16px;
}

.spot-map__coords {
  font-size: 11px;
  color: var(--color-text-muted);
  font-family: monospace;
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.spot-map__coords svg {
  opacity: 0.4;
}

/* --- Directions Dropdown --- */
.directions-wrap {
  position: relative;
}

.directions-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px;
  font-size: 13px;
  font-weight: 600;
  font-family: var(--font-family);
  background: var(--color-primary-dark);
  color: white;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  transition: all 0.2s;
  box-shadow: 0 2px 6px rgba(29, 158, 117, 0.3);
}

.directions-btn:hover {
  background: var(--color-primary-darker);
  box-shadow: 0 4px 12px rgba(29, 158, 117, 0.4);
  transform: translateY(-1px);
}

.directions-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: white;
  border-radius: 12px;
  box-shadow: var(--shadow-xl);
  border: 1px solid var(--color-border);
  overflow: hidden;
  display: none;
  z-index: 30;
  animation: fadeInUp 0.2s ease-out;
}

.directions-dropdown.open {
  display: block;
}

.directions-dropdown__item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  font-size: 13px;
  font-weight: 500;
  color: var(--color-text);
  transition: background 0.15s;
  border-bottom: 1px solid #f3f4f6;
}

.directions-dropdown__item:last-child {
  border-bottom: none;
}

.directions-dropdown__item:hover {
  background: var(--color-bg-gray);
  color: var(--color-primary-dark);
}

.directions-dropdown__icon {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: 16px;
}

.directions-dropdown__icon--google {
  background: #e8f5e9;
}

.directions-dropdown__icon--apple {
  background: #f3f4f6;
}

.directions-dropdown__icon--waze {
  background: #e3f2fd;
}

.directions-dropdown__label {
  font-weight: 600;
}

.directions-dropdown__desc {
  font-size: 11px;
  color: var(--color-text-muted);
  font-weight: 400;
}

/* --- Cookie Consent Banner --- */
.cookie-banner {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(17, 24, 39, 0.95);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: white;
  padding: 16px 24px;
  z-index: 300;
  display: none;
  animation: fadeInUp 0.3s ease-out;
}

.cookie-banner.show {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
}

.cookie-banner__text {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.8);
  max-width: 600px;
  line-height: 1.5;
}

.cookie-banner__text a {
  color: var(--color-primary-border);
  text-decoration: underline;
}

.cookie-banner__btn {
  padding: 8px 20px;
  font-size: 13px;
  font-weight: 600;
  font-family: var(--font-family);
  border-radius: 8px;
  border: none;
  cursor: pointer;
  transition: all 0.2s;
  white-space: nowrap;
}

.cookie-banner__btn--accept {
  background: var(--color-primary-dark);
  color: white;
}

.cookie-banner__btn--accept:hover {
  background: var(--color-primary-darker);
}

.cookie-banner__btn--decline {
  background: transparent;
  color: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.2);
}

.cookie-banner__btn--decline:hover {
  border-color: rgba(255, 255, 255, 0.4);
  color: white;
}

/* --- Newsletter Signup --- */
.newsletter {
  background: linear-gradient(135deg, var(--color-primary-light), #d4eaf5);
  border-radius: 16px;
  padding: 32px;
  text-align: center;
}

.newsletter__title {
  font-size: 18px;
  font-weight: 700;
  margin-bottom: 6px;
}

.newsletter__desc {
  font-size: 14px;
  color: var(--color-text-muted);
  margin-bottom: 16px;
  max-width: 400px;
  margin-left: auto;
  margin-right: auto;
}

.newsletter__form {
  display: flex;
  gap: 8px;
  max-width: 420px;
  margin: 0 auto;
}

.newsletter__input {
  flex: 1;
  /* Flex items default to min-width:auto, and an <input> carries an intrinsic
     width of roughly 20 characters, so `flex: 1` alone will not let this shrink.
     With .newsletter__btn set to nowrap beside it, the row grew wider than
     .newsletter and the button sat outside the rounded box on narrow phones. */
  min-width: 0;
  padding: 12px 16px;
  font-size: 14px;
  font-family: var(--font-family);
  border: 2px solid var(--color-primary-border);
  border-radius: 10px;
  outline: none;
  background: white;
  transition: border-color 0.2s;
}

.newsletter__input:focus {
  border-color: var(--color-primary);
}

.newsletter__btn {
  padding: 12px 24px;
  font-size: 14px;
  font-weight: 600;
  font-family: var(--font-family);
  background: var(--color-primary-dark);
  color: white;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  transition: all 0.2s;
  white-space: nowrap;
}

.newsletter__btn:hover {
  background: var(--color-primary-darker);
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(29, 158, 117, 0.3);
}

/* Below the form's own 420px max-width there is no room for a field and a
   nowrap button side by side, so the button moves under the field and both go
   full width. min-width:0 on the input covers the range just above this, where
   the row still fits but only once the field is allowed to shrink. */
@media (max-width: 480px) {
  .newsletter__form {
    flex-direction: column;
  }
}

/* --- Reviews --- */
.review-card {
  padding: 16px 0;
  border-bottom: 1px solid var(--color-border);
}

.review-card:last-child {
  border-bottom: none;
}

.review-stars {
  display: inline-flex;
  gap: 2px;
  color: #facc15;
}

.review-stars--empty {
  color: #e5e7eb;
}

/* Star rating picker (review forms).

   Five native radios in one group, so it is a single tab stop with arrow-key
   selection and a checked state the accessibility tree can read. The inputs
   run 5..1 in the DOM and the row is reversed, which is what lets
   `input:checked ~ label` fill the chosen star and every lower one. Filled
   and empty differ by glyph (★ / ☆) as well as by colour, so the rating is
   never carried by colour alone. */
.star-picker-field {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}

.star-picker {
  display: flex;
  flex-direction: row-reverse;
  justify-content: flex-end;
  gap: 4px;
}

.star-picker__star {
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
  color: var(--color-text-muted);
  user-select: none;
  transition: color 0.15s;
}

.star-picker__star::before {
  content: '\2606';
}

.star-picker__input:checked ~ .star-picker__star::before,
.star-picker__star:hover::before,
.star-picker__star:hover ~ .star-picker__star::before {
  content: '\2605';
}

.star-picker__input:checked ~ .star-picker__star,
.star-picker__star:hover,
.star-picker__star:hover ~ .star-picker__star {
  color: #EF9F27;
}

.star-picker__input:focus-visible + .star-picker__star {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

.rating-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  margin-bottom: 4px;
}

.rating-bar__track {
  flex: 1;
  height: 6px;
  background: var(--color-bg-gray);
  border-radius: 3px;
  overflow: hidden;
}

.rating-bar__fill {
  height: 100%;
  background: var(--color-primary);
  border-radius: 3px;
  transition: width 0.5s ease-out;
}

/* --- Engagement Stats Bar --- */
.engagement-stats {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 8px 0;
  flex-wrap: wrap;
}

.engagement-stat {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--color-text-muted);
  font-weight: 500;
}

.engagement-stat svg {
  opacity: 0.5;
  flex-shrink: 0;
}

.engagement-stat__value {
  font-weight: 600;
  color: var(--color-text);
}

/* --- Currency Selector --- */
.currency-selector {
  position: relative;
  margin-left: 8px;
}

.currency-selector__btn {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 5px 10px;
  font-size: 12px;
  font-weight: 600;
  font-family: var(--font-family);
  background: var(--color-bg-gray);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  cursor: pointer;
  color: var(--color-text-muted);
  transition: all 0.2s;
  white-space: nowrap;
}

.currency-selector__btn:hover {
  border-color: var(--color-primary-border);
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

.currency-selector__btn .flag {
  font-size: 14px;
  line-height: 1;
}

/* The word beside the globe, shown only until a currency has been picked —
   after that the button reads as the flag and the code, which is shorter. On
   a phone the header has no room for it and the globe alone is enough.

   Clipped rather than `display: none`: the flag is aria-hidden, so removing
   this text from the accessibility tree as well would leave the button with
   no accessible name at all. Font size is untouched on purpose — the button
   gets narrower, the type stays legible. */
@media (max-width: 768px) {
  .currency-selector__label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  .currency-selector__btn {
    padding: 5px 8px;
    gap: 4px;
  }
}

.currency-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  background: white;
  border-radius: 12px;
  box-shadow: var(--shadow-xl);
  border: 1px solid var(--color-border);
  overflow: hidden;
  display: none;
  z-index: 110;
  min-width: 200px;
  animation: fadeInUp 0.2s ease-out;
}

.currency-dropdown.open {
  display: block;
}

.currency-dropdown__header {
  padding: 10px 14px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  background: var(--color-bg-gray);
  border-bottom: 1px solid var(--color-border);
}

.currency-dropdown__item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 500;
  color: var(--color-text);
  cursor: pointer;
  transition: background 0.15s;
  border-bottom: 1px solid #f3f4f6;
}

.currency-dropdown__item:last-child {
  border-bottom: none;
}

.currency-dropdown__item:hover {
  background: var(--color-bg-gray);
}

.currency-dropdown__item.active {
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-weight: 600;
}

.currency-dropdown__item .flag {
  font-size: 16px;
}

.currency-dropdown__item .code {
  font-family: monospace;
  font-size: 11px;
  color: var(--color-text-muted);
  margin-left: auto;
}

/* Rich text content (from rich editor) */
.rich-content ul { list-style: disc; padding-left: 1.5em; margin: 0.5em 0; }
.rich-content ol { list-style: decimal; padding-left: 1.5em; margin: 0.5em 0; }
.rich-content li { margin: 0.25em 0; }
.rich-content h1 { font-size: 1.5em; font-weight: 700; margin: 0.75em 0 0.25em; }
.rich-content h2 { font-size: 1.25em; font-weight: 700; margin: 0.75em 0 0.25em; }
.rich-content h3 { font-size: 1.1em; font-weight: 600; margin: 0.5em 0 0.25em; }
.rich-content p { margin: 0.5em 0; }
.rich-content blockquote { border-left: 3px solid #1D9E75; padding-left: 1em; margin: 0.75em 0; color: #4b5563; font-style: italic; }
.rich-content a { color: var(--color-primary-dark); text-decoration: underline; }
.rich-content strong { font-weight: 700; }
.rich-content em { font-style: italic; }
.rich-content pre { background: #f3f4f6; padding: 0.75em 1em; border-radius: 8px; font-size: 0.9em; overflow-x: auto; margin: 0.5em 0; }
.rich-content code { background: #f3f4f6; padding: 0.15em 0.4em; border-radius: 4px; font-size: 0.9em; }

/* Converted price display */
.converted-price {
  font-size: 11px;
  font-weight: 500;
  color: var(--color-text-muted);
  margin-left: 4px;
  opacity: 0;
  transition: opacity 0.3s;
}

/* Inherit color when inside elements with explicit white text (buttons, colored backgrounds) */
[style*="color:white"] .converted-price,
[style*="color: white"] .converted-price,
.text-white .converted-price,
.text-primary .converted-price {
  color: inherit;
  opacity: 0.7;
}
[style*="color:white"] .converted-price.visible,
[style*="color: white"] .converted-price.visible,
.text-white .converted-price.visible,
.text-primary .converted-price.visible {
  opacity: 0.8;
}

.converted-price.visible {
  opacity: 1;
}

/* For block-level conversion (below the price) */
.converted-price--block {
  display: block;
  margin-left: 0;
  margin-top: 2px;
}

/* --- Booking Modal --- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: 200;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
  animation: fadeIn 0.2s ease-out;
}

.modal-overlay.open {
  display: flex;
}

.modal {
  background: white;
  border-radius: 20px;
  box-shadow: var(--shadow-xl);
  width: 100%;
  max-width: 440px;
  max-height: 90vh;
  overflow-y: auto;
  animation: fadeInUp 0.3s ease-out;
}

.modal__header {
  padding: 20px 24px 0;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}

.modal__close {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: none;
  background: var(--color-bg-gray);
  color: var(--color-text-muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.15s;
  flex-shrink: 0;
}

.modal__close:hover {
  background: #fee2e2;
  color: #ef4444;
}

.modal__title {
  font-size: 18px;
  font-weight: 700;
  margin-bottom: 2px;
}

.modal__subtitle {
  font-size: 13px;
  color: var(--color-text-muted);
}

.modal__body {
  padding: 20px 24px;
}

.modal__service-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: var(--color-bg-gray);
  border-radius: 12px;
  margin-bottom: 20px;
  border: 1px solid var(--color-border);
}

.modal__service-icon {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.modal__service-name {
  font-size: 14px;
  font-weight: 600;
}

.modal__service-meta {
  font-size: 12px;
  color: var(--color-text-muted);
}

.modal__form-group {
  margin-bottom: 14px;
}

.modal__form-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: 5px;
}

.modal__form-input {
  width: 100%;
  padding: 10px 14px;
  font-size: 14px;
  font-family: var(--font-family);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  outline: none;
  transition: all 0.2s;
  background: white;
}

.modal__form-input:focus {
  border-color: var(--color-primary-border);
  box-shadow: 0 0 0 3px rgba(29, 158, 117, 0.08);
}

.modal__form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.modal__operator {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  background: #f0fdf4;
  border: 1px solid #bbf7d0;
  border-radius: 10px;
  margin-bottom: 16px;
  font-size: 13px;
  color: #166534;
}

.modal__operator svg {
  flex-shrink: 0;
}

.modal__footer {
  padding: 0 24px 24px;
}

.modal__submit {
  width: 100%;
  padding: 12px;
  font-size: 15px;
  font-weight: 700;
  font-family: var(--font-family);
  border: none;
  border-radius: 12px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  background: #25D366;
  color: white;
  box-shadow: 0 2px 8px rgba(37, 211, 102, 0.3);
}

.modal__submit:hover {
  background: #20bd5a;
  box-shadow: 0 4px 16px rgba(37, 211, 102, 0.4);
  transform: translateY(-1px);
}

.modal__submit svg {
  flex-shrink: 0;
}

.modal__disclaimer {
  text-align: center;
  font-size: 11px;
  color: var(--color-text-muted);
  margin-top: 10px;
  line-height: 1.4;
}

/* --- Responsive --- */
@media (max-width: 768px) {
  .nav__hamburger {
    display: flex;
  }
  .two-col {
    flex-direction: column;
  }

  /* The sidebar stacks below the content on a phone, so an in-page table of
     contents would sit after the sections it links to. Scrolling is the
     navigation here. */
  .toc {
    display: none;
  }

  /* A phone screen is short enough that the desktop opening reads as a hole,
     and the stacked layout already puts the title on a line of its own. */
  .two-col--no-hero {
    padding-top: 36px;
  }

  .two-col__sidebar {
    width: 100%;
    position: static;
  }

  /* Opt-in, per page. Once the columns stack, a destination's context -- what
     the place is, how you get there -- is worth more up top than the grid it
     sits beside, so the sidebar leads. Reordering the whole <aside> rather
     than individual widgets keeps the sidebar in one piece; the widgets that
     matter most are collapsible (see .collapsible-widget) so they cost a row
     each and the grid stays close to the fold. Ordering only, no DOM move:
     above the breakpoint the flex row is untouched. */
  .two-col--sidebar-first .two-col__sidebar {
    order: -1;
  }

  /* Opt-in, per page. The same idea taken further, for a sidebar that has to
     break around the main column rather than sit above it. The area page
     stacks map, folded widgets, spots, "Was this helpful?", which means items
     from both columns interleave.

     `display: contents` drops the <aside>'s own box, promoting each widget to
     a flex item of .two-col so it can take an `order` of its own. That is the
     only way to interleave two containers' children without moving either in
     the DOM. Dropping the box used to drop the element from the accessibility
     tree as well; that is long fixed, and the <aside> was checked against a
     current Chromium here to be sure it still carries its landmark.

     The 48px column gap sat between two blocks and would now sit between
     every widget, so spacing comes from the widgets' own margins and the main
     column states the room it needs. */
  /* Opt-in, per page. Lifts one sidebar widget above the content and leaves
     every other one below it, which is what a service page wants on a phone:
     who the operator is and when they are open, before the detail. Unlike
     --sidebar-split this does not move the rest of the aside, so the reading
     order is lead, content, everything else. */
  .two-col--lead-first > .two-col__sidebar {
    display: contents;
  }

  .two-col--lead-first > .two-col__sidebar > * {
    order: 3;
    align-self: stretch;
  }

  .two-col--lead-first > .two-col__sidebar > .two-col__sidebar-lead {
    order: 1;
    margin-bottom: 20px;
  }

  .two-col--lead-first > .two-col__main {
    order: 2;
  }

  .two-col--sidebar-split {
    gap: 0;
  }

  .two-col--sidebar-split > .two-col__sidebar {
    display: contents;
  }

  /* Widgets read after the map and before the spots; the two exceptions are
     hooked by class. `align-self` replaces the width the <aside> used to give
     them, since .two-col aligns its items to the start rather than stretching
     them. */
  .two-col--sidebar-split > .two-col__sidebar > * {
    order: 2;
    align-self: stretch;
  }

  .two-col--sidebar-split > .two-col__sidebar > .two-col__sidebar-lead {
    order: 1;
  }

  .two-col--sidebar-split > .two-col__main {
    order: 3;
    margin: 16px 0 32px;
  }

  .two-col--sidebar-split > .two-col__sidebar > .two-col__sidebar-trail {
    order: 4;
  }

  .collapsible-widget__summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    cursor: pointer;
    /* The whole bar is the tap target, so kill the drag-select that a
       double-tap would otherwise leave behind. */
    user-select: none;
    -webkit-user-select: none;
  }

  /* Chevron, drawn from two borders. Only exists below the breakpoint, so the
     desktop title keeps its exact box. */
  .collapsible-widget__summary::after {
    content: "";
    flex-shrink: 0;
    width: 7px;
    height: 7px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
    transition: transform 0.2s;
  }

  .collapsible-widget[open] > .collapsible-widget__summary::after {
    transform: translateY(1px) rotate(-135deg);
  }

  /* Closed, nothing follows the title, so its rule and the space under it
     would hang off the bottom of an otherwise empty box. */
  .collapsible-widget:not([open]) > .collapsible-widget__summary {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
  }

  .area-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .hero__title {
    font-size: 32px;
  }

  .hero__subtitle {
    font-size: 16px;
  }

  .photo-strip {
    grid-template-columns: 1fr 1fr;
  }

  .photo-strip__item {
    height: 160px;
  }

  .nav__links {
    display: none;
  }

  /* `.nav__links` carries `margin-left: auto`, and that is what pushes
     everything after it — the two switchers, Saved, Search and the
     hamburger — over to the right edge. Hiding the links on a phone takes
     that push away with them, so the whole group collapses back against the
     logo and sits in the middle of the bar with empty space to its right.

     The push moves onto the logo instead, which is the one element that
     stays put at both sizes. Deliberately scoped to this breakpoint: on a
     wider screen `.nav__links` is visible and still owns the spacing, and a
     second `auto` margin would split the free space between the two and
     drag the links away from the right-hand group. */
  .nav__logo {
    margin-right: auto;
  }

  /* Six items and a logo across a 360px bar, with two of them held at the
     44px tap-target floor, leaves nothing spare. Halving the gap buys back
     the margin that keeps it off the container padding. */
  .currency-selector {
    margin-left: 4px;
  }

  /* `.currency-dropdown` hangs from `right: 0` and is at least 200px wide, so
     it opens leftward from whichever button owns it. That is fine for the
     currency switcher, which sits about 220px in from the right edge. The
     language switcher is one button further left, at roughly 172px, so its
     panel starts near -28px on a 360px screen and `body`'s
     `overflow-x: hidden` removes it completely — the button appears dead
     rather than obviously misplaced.

     Opening it rightward from its own left edge instead puts it at roughly
     128-328px, inside the container either way. Only the language panel
     needs this; the currency one still has room to open the way it was
     designed to, and moving both would swap a bug for an inconsistency. */
  #languageDropdown {
    right: auto;
    left: 0;
  }

  .quick-facts {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 480px) {
  .area-grid {
    grid-template-columns: 1fr;
  }

  .spot-card {
    flex-direction: column;
  }

  .spot-card__image {
    width: 100%;
    height: 140px;
  }

  .photo-strip {
    grid-template-columns: 1fr;
  }

  .hero__title {
    font-size: 28px;
  }

  .modal__form-row { grid-template-columns: 1fr !important; }
}

/* Accessibility: visible focus indicators */
:focus-visible {
  outline: 2px solid var(--color-primary, #1D9E75);
  outline-offset: 2px;
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--color-primary, #1D9E75);
  outline-offset: 0;
}

/* Accessibility: respect reduced motion preference */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Accessibility: controls that must stay focusable but out of sight.
   Clipped rather than display:none or visibility:hidden, both of which drop
   the control out of the tab order and out of the accessibility tree. Pair it
   with a visible <label for>, and give that label the focus styling. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The clipped input has nowhere to draw a focus ring, so its label wears it. */
.drop-zone:focus-within {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Accessibility: skip navigation link */
.skip-link {
  position: absolute;
  top: -100%;
  left: 16px;
  padding: 8px 16px;
  background: var(--color-primary-dark, #0F6E56);
  color: white;
  z-index: 200;
  font-weight: 600;
  border-radius: 0 0 6px 6px;
  text-decoration: none;
}
.skip-link:focus {
  top: 0;
}

/* Mobile: minimum touch target sizes */
@media (max-width: 768px) {
  .currency-selector__btn,
  .nav__hamburger,
  .gallery-close,
  .gallery-prev,
  .gallery-next,
  .travel-tabs__tab {
    min-width: 44px;
    min-height: 44px;
  }
}

/* --- Pre-launch placeholder --- */
/* The whole public site while pre-launch mode is on. Rendered without the
   nav, the footer or any of the shared assigns they need, so it carries
   its own layout — but it borrows the site's palette, type scale and hero
   gradient so the first thing a visitor sees is recognisably Islafy. */
.prelaunch {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 24px;
  background: linear-gradient(160deg, var(--color-primary-light) 0%, var(--color-sea-blue) 100%);
  font-family: var(--font-family);
  color: var(--color-text);
  line-height: var(--line-height-body);
}

.prelaunch__panel {
  max-width: 520px;
  text-align: center;
  animation: fadeInUp 0.7s ease-out;
}

.prelaunch__brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-primary-dark);
  margin-bottom: 28px;
}

.prelaunch__brand img {
  border-radius: 6px;
}

.prelaunch__title {
  font-size: 38px;
  line-height: 1.15;
  font-weight: 800;
  letter-spacing: -0.03em;
  margin-bottom: 14px;
}

.prelaunch__text {
  font-size: 17px;
  /* The panel sits on the mint-to-sea-blue gradient, where --color-text-muted
     falls to 4.26:1. --color-text-muted-strong holds 6.08:1 at the pale end. */
  color: var(--color-text-muted-strong);
  margin: 0 auto;
  max-width: 420px;
}

@media (max-width: 640px) {
  .prelaunch__title {
    font-size: 30px;
  }

  .prelaunch__text {
    font-size: 16px;
  }
}

/* --- Admin pre-launch notice --- */
/* Only rendered for a signed-in admin looking at the real site while the
   public sees the placeholder. Deliberately quiet, and never shown to
   anyone else — the assign behind it is set only after the admin session
   token has been checked against the database. */
.prelaunch-notice {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 900;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 12px;
  border-radius: 20px;
  border: 1px solid var(--color-primary-border);
  background: rgba(255, 255, 255, 0.94);
  box-shadow: var(--shadow-sm);
  font-size: 12px;
  font-weight: 600;
  color: var(--color-primary-dark);
  text-decoration: none;
}

.prelaunch-notice::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-primary);
  flex-shrink: 0;
}

.prelaunch-notice:hover {
  border-color: var(--color-primary);
}

@media (max-width: 768px) {
  .prelaunch-notice {
    bottom: 12px;
    left: 12px;
    padding: 6px 10px;
    font-size: 11px;
  }
}
