/* ==========================================================================
   Everything Gansbaai — design system
   Palette sampled from the logo: navy #043e66, teal #45c7c9, sand #ac958d.
   Direction: light, airy, coastal summer. White cards on warm sand-white,
   navy type, teal for anything interactive, coral reserved for "happening now".
   ========================================================================== */

/* ---- brand fonts ------------------------------------------------------- */
/* Served straight from OTF/TTF. Oliviar Sans is the brand face; the bold
   italic is the same cut as the HERMANUS wordmark, so headings echo the logo. */
@font-face {
  font-family: 'Oliviar Sans';
  src: url('/public/fonts/oliviar-sans-regular.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Artegra Display';
  src: url('/public/fonts/artegra-sans-alt-bold-italic.otf') format('opentype');
  font-weight: 700;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'Oliviar Display';
  src: url('/public/fonts/oliviar-sans-bold-italic.ttf') format('truetype');
  font-weight: 700;
  font-style: italic;
  font-display: swap;
}

:root {
  /* core brand — sampled from Logo.png */
  --navy: #043e66;
  --navy-deep: #032b47;
  --navy-soft: #3b6888;
  --teal: #45c7c9;
  --teal-deep: #379fa1;
  --teal-wash: #e9f8f9;
  --sand: #ac958d;
  --sand-deep: #8d7a74;
  --sand-wash: #f5f2f1;
  --charcoal: #032842;   /* hero text outline */

  /* extended — sampled from the sunset beach photograph, so the warm accents
     belong to the same world as the coastal blues rather than being invented */
  --coral: #c43d3d;          /* strongest warm — calls to action, tickets */
  --coral-soft: #d67777;
  --coral-wash: #f8e8e8;
  --gold: #d9a441;           /* ratings, awards, Blue Flag */
  --gold-wash: #faf4e8;
  --dusk: #4a7ca3;           /* periwinkle — events, Local Lowdown */
  --dusk-soft: #7da1bd;
  --dusk-wash: #e9eff4;
  --lilac: #7f8f6a;          /* accommodation, quieter accents */
  --lilac-wash: #f0f2ed;
  --rose: #9bb7cc;           /* gentle warm highlight */
  --rose-wash: #f3f6f9;
  --cream: #e6eef0;          /* warm band background */
  --sky: #a2e3e4;            /* light sea blue */
  --sky-wash: #f4fcfc;
  --seafoam: #9cb679;        /* open / available */
  --seafoam-wash: #f3f6ef;

  /* surfaces */
  --bg: #fbf8f4;
  --surface: #ffffff;
  --surface-tint: #f1f1ee;
  --line: #dde2e3;
  --line-soft: #eaebea;

  /* type */
  --ink: #12303f;
  --ink-soft: #596e79;
  --muted: #89989f;

  /* shape */
  --r-sm: 10px;
  --r: 16px;
  --r-lg: 24px;
  --r-pill: 999px;
  --shadow-sm: 0 1px 2px rgba(4, 62, 102, 0.05), 0 2px 8px rgba(4, 62, 102, 0.04);
  --shadow: 0 2px 6px rgba(4, 62, 102, 0.06), 0 12px 28px rgba(4, 62, 102, 0.08);
  --shadow-lg: 0 8px 20px rgba(4, 62, 102, 0.10), 0 24px 60px rgba(4, 62, 102, 0.12);

  --font-body: 'Oliviar Sans', ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-display: 'Oliviar Display', 'Oliviar Sans', ui-sans-serif, -apple-system, Georgia, serif;
  /* Heavier, wider italic — reserved for hero-scale moments so it stays special */
  --font-hero: 'Artegra Display', 'Oliviar Display', ui-sans-serif, -apple-system, Georgia, serif;

  --wrap: 1180px;
}
* { box-sizing: border-box; }

html { scroll-behavior: smooth; }
/* Hidden tooltip bubbles near the right edge (e.g. the pricing table's (i) tips)
   would otherwise make the whole page scroll sideways. clip, unlike hidden,
   doesn't create a scroll container, so the sticky header keeps working. */
html, body { overflow-x: clip; }

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 16.5px;
  color: var(--ink);
  background: var(--bg);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 22px; }

a { color: var(--teal-deep); text-decoration: none; }
a:hover { color: var(--navy); text-decoration: underline; }

h1, h2, h3 { font-family: var(--font-display); font-style: italic; color: var(--navy); line-height: 1.15; letter-spacing: -0.01em; }
h1 { font-size: clamp(2rem, 4.2vw, 2.9rem); margin: 0 0 10px; }
h2 { font-size: clamp(1.3rem, 2.4vw, 1.65rem); margin: 40px 0 16px; }
h3 { font-size: 1.1rem; margin: 0 0 6px; }

/* ---- type utilities ----------------------------------------------------
   Three faces doing three jobs: Artegra for hero-scale display, Oliviar
   Bold Italic for headings, Oliviar Regular for everything you read.
   The eyebrow gives a third voice without a fourth font. */

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

.display { font-family: var(--font-hero); font-style: italic; letter-spacing: -0.02em; line-height: 1.05; }

.eyebrow {
  display: block; font-family: var(--font-body); font-style: normal;
  font-size: 0.73rem; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--teal-deep); margin: 0 0 6px;
}
.eyebrow-coral { color: var(--coral); }
.eyebrow-dusk { color: var(--dusk); }
.eyebrow-sand { color: var(--sand-deep); }
.eyebrow-light {
  color: #fff;
  -webkit-text-stroke: 0.5px var(--charcoal);
  paint-order: stroke fill;
  text-shadow: 0 1px 8px rgba(0, 22, 38, 0.3);
}

/* A short rule under a heading — quiet structure without another border box */
.rule::after {
  content: ''; display: block; width: 54px; height: 3px; border-radius: 2px;
  background: var(--teal); margin-top: 12px;
}
.rule-coral::after { background: var(--coral); }
.rule-dusk::after { background: var(--dusk); }
.rule-gold::after { background: var(--gold); }

.num { font-family: var(--font-hero); font-style: italic; font-variant-numeric: tabular-nums; }

p { margin: 0 0 14px; }
.lede { color: var(--ink-soft); max-width: 62ch; font-size: 1.05rem; }
.muted { color: var(--muted); }

/* ---- header ------------------------------------------------------------ */

.site-header {
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: saturate(1.6) blur(12px);
  border-bottom: 1px solid var(--line-soft);
  position: sticky;
  top: 0;
  z-index: 40;
  /* No-op in an ordinary browser. In the app, the WebView draws full-bleed
     under the status bar / camera cutout on iOS (and Android, once its
     viewport reports the inset) -- this keeps the logo and menu button
     clear of it instead of sitting underneath. */
  padding-top: env(safe-area-inset-top, 0px);
}
.header-inner { display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 12px 22px; flex-wrap: wrap; }

.brand { display: flex; align-items: center; gap: 12px; color: var(--navy); }
.brand:hover { text-decoration: none; opacity: 0.85; }
.brand img { width: 46px; height: 46px; display: block; }
/* The mark now carries its own white background, so it is clipped to a disc —
   that way the white never shows as a square against the navy footer. */
.brand-mark { border-radius: 50%; background: #fff; }
.brand-text { display: flex; flex-direction: column; line-height: 1; }
.brand-eyebrow { font-size: 0.82rem; color: var(--ink-soft); letter-spacing: 0.04em; }
.brand-name { font-family: var(--font-display); font-style: italic; font-size: 1.5rem; color: var(--navy); letter-spacing: -0.01em; }

.nav { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.nav a { color: var(--ink-soft); font-size: 0.93rem; padding: 8px 13px; border-radius: var(--r-pill); }
.nav a:hover { background: var(--teal-wash); color: var(--navy); text-decoration: none; }
.nav a.active { background: var(--navy); color: #fff; }
.nav .nav-cta { background: var(--teal); color: #fff; font-weight: 600; }
.nav .nav-cta:hover { background: var(--teal-deep); color: #fff; }

/* Mobile-only "Menu" trigger — hidden on desktop, where the full nav shows inline. */
.nav-toggle {
  display: none; align-items: center; gap: 8px; cursor: pointer;
  background: none; border: 1px solid var(--line); border-radius: var(--r-pill);
  padding: 8px 14px 8px 12px; font: inherit; font-size: 0.86rem; font-weight: 600;
  color: var(--navy);
}
.nav-toggle-bars { display: flex; flex-direction: column; gap: 3px; }
.nav-toggle-bars span { display: block; width: 16px; height: 2px; border-radius: 1px; background: var(--navy); transition: transform .15s ease, opacity .15s ease; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

/* ---------- App shell (Capacitor apps only) ----------
   A bottom tab bar for the installed iOS/Android apps — logo + hamburger
   stay fixed up top via the ordinary sticky .site-header above, and this
   bar carries the most-used destinations within thumb reach, hiding on
   scroll-down and reappearing on scroll-up (Facebook/Instagram-style).
   Built and toggled entirely by public/js/app-shell.js, which is a no-op
   on the website — so this markup only ever exists inside the apps. */
.app-tabbar {
  display: none;
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 50;
  justify-content: space-around;
  align-items: stretch;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: saturate(1.6) blur(14px);
  border-top: 1px solid var(--line-soft);
  padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px));
  transform: translateY(0);
  transition: transform 0.25s ease;
}
body.is-app-shell .app-tabbar { display: flex; }
/* On tablets and foldables a bar stretched edge to edge looks wrong and puts
   the tabs far apart — keep it a centred, phone-width dock instead. */
@media (min-width: 700px) {
  .app-tabbar {
    max-width: 520px;
    margin: 0 auto;
    border-left: 1px solid var(--line-soft);
    border-right: 1px solid var(--line-soft);
    border-radius: 16px 16px 0 0;
  }
}
.app-tabbar.is-hidden { transform: translateY(100%); }

.app-tab {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 6px 2px 4px;
  color: var(--ink-soft);
  font-size: 0.66rem;
  font-weight: 600;
  border: none;
  background: none;
  font-family: inherit;
  cursor: pointer;
}
.app-tab svg { width: 22px; height: 22px; }
.app-tab:hover { text-decoration: none; color: var(--navy); }
.app-tab.active { color: var(--navy); }
.app-tab.active svg { color: var(--teal-deep); }

/* Room for the fixed bar so the footer's real links aren't hidden under it. */
body.is-app-shell { padding-bottom: calc(58px + env(safe-area-inset-bottom, 0px)); }

.main { padding: 34px 22px 80px; min-height: 60vh; }

/* ---- hero -------------------------------------------------------------- */

.hero {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  margin-bottom: 26px;
  background: var(--navy);
  isolation: isolate;
}
.hero-media { position: absolute; inset: 0; z-index: -2; }
/* width:100% is load-bearing. With aspect-ratio and min-height both set and no
   explicit width, the min-height wins and the ratio then drives the width from
   it — 430 x 2.6 = 1118px — which overflowed the content box and gave the whole
   home page a horizontal scrollbar on any viewport under about 1160px. Pinning
   the width makes the ratio govern height only; the hero still renders 430px
   tall, it just stops sticking out past the page. */
.hero { aspect-ratio: 2.6 / 1; min-height: 430px; width: 100%; display: flex; align-items: center; justify-content: center; }
.hero-media img { width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; }
.hero-inner {
  padding: clamp(24px, 4vw, 44px) clamp(22px, 5vw, 56px); color: #fff; width: 100%;
  display: flex; flex-direction: column; align-items: center; text-align: center;
}
.hero h1 {
  font-family: var(--font-hero); color: #fff; font-size: clamp(1.6rem, 6vw, 4rem);
  margin: 0 0 10px; letter-spacing: -0.025em; line-height: 1.02;
  -webkit-text-stroke: 1.2px var(--charcoal);
  paint-order: stroke fill;
  text-shadow: 0 2px 14px rgba(0, 22, 38, 0.28);
}
.hero-towns {
  color: #fff; font-size: clamp(0.72rem, 1.4vw, 0.86rem);
  letter-spacing: 0.2em; text-transform: uppercase; margin: 0 0 20px; font-weight: 700;
  -webkit-text-stroke: 0.6px var(--charcoal);
  paint-order: stroke fill;
  text-shadow: 0 1px 8px rgba(0, 22, 38, 0.3);
}
.hero-intro {
  color: #fff; font-size: clamp(0.92rem, 1.8vw, 1.05rem); max-width: 60ch; margin: 0 0 22px; line-height: 1.5;
  text-shadow: 0 1px 3px rgba(0, 22, 38, 0.75), 0 2px 16px rgba(0, 22, 38, 0.6);
}
.hero-tagline {
  color: #fff; font-size: clamp(1rem, 2vw, 1.2rem); max-width: 44ch; margin: 0 0 26px;
  text-shadow: 0 1px 3px rgba(0, 22, 38, 0.7), 0 2px 16px rgba(0, 22, 38, 0.6);
}

.search-box { margin-top: 4px; }
/* The hero centres its children, so the box must claim the width itself or the
   form collapses to its content and clips the placeholder. */
.hero .search-box { width: 100%; }
.search-box form { display: flex; gap: 10px; max-width: 620px; width: 100%; margin: 0 auto; }
.search-box input[type=text] {
  flex: 1; padding: 15px 20px; border-radius: var(--r-pill); border: none;
  font-size: 1rem; font-family: inherit; box-shadow: var(--shadow);
  color: var(--ink); background: #fff;
}
@media (max-width: 420px) {
  .search-box input[type=text] { font-size: 0.88rem; padding: 15px 16px; }
}
.search-box input[type=text]:focus { outline: 3px solid var(--teal); outline-offset: 2px; }
.search-box button {
  padding: 15px 26px; border-radius: var(--r-pill); border: none; cursor: pointer;
  background: var(--teal); color: #fff; font-weight: 700; font-size: 0.98rem; font-family: inherit;
  box-shadow: var(--shadow);
}
.search-box button:hover { background: #fff; color: var(--navy); }

.hero-quicklinks { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 16px; justify-content: center; }
.hero-quicklinks a {
  background: rgba(255, 255, 255, 0.9); border: 1px solid rgba(255, 255, 255, 0.9);
  color: var(--navy); font-size: 0.86rem; font-weight: 600; padding: 7px 15px;
  border-radius: var(--r-pill); box-shadow: 0 2px 10px rgba(0, 26, 44, 0.18);
}
.hero-quicklinks a:hover { background: #fff; color: var(--navy); text-decoration: none; }
/* Same red as the emergency page's own urgent card and eyebrow (#b4432f). */
.hero-quicklinks a.is-urgent { background: #b4432f; border-color: #b4432f; color: #fff; }
.hero-quicklinks a.is-urgent:hover { background: #96351f; border-color: #96351f; color: #fff; }

/* ---- hero badge (time-boxed promo, e.g. the Whale Festival) ------------ */
/* A single flat image (logo + "click here for everything" + wordmark, all
   baked in) on a translucent pill so its light outline text still reads
   against a bright hero photo. Below 860px the hero's own centred title
   block would otherwise run under this left-aligned badge, so the
   `:has()` rules push .hero-inner down to clear it instead of shrinking
   the badge to an illegible size — scoped to :has(.hero-badge) so the
   hero goes back to its normal layout once the time-boxed badge is gone. */
.hero-badge {
  position: absolute; top: 16px; left: 16px; z-index: 2;
  display: block; text-decoration: none;
  background: rgba(2, 34, 53, 0.28); padding: 10px 14px; border-radius: var(--r-sm);
  transition: transform .15s ease, background .15s ease;
}
.hero-badge:hover { transform: translateY(-2px); background: rgba(2, 34, 53, 0.4); text-decoration: none; }
.hero-badge img { width: 260px; height: auto; display: block; }
@media (max-width: 860px) {
  .hero:has(.hero-badge) .hero-inner { padding-top: 104px; }
}
@media (max-width: 640px) {
  .hero-badge { top: 10px; left: 10px; padding: 7px 10px; }
  .hero-badge img { width: 190px; }
  .hero:has(.hero-badge) .hero-inner { padding-top: 96px; }
}

/* ---- buttons ----------------------------------------------------------- */

.btn, .search-box button {
  font-family: inherit;
}
.btn {
  display: inline-block; padding: 12px 22px; border-radius: var(--r-pill); border: none;
  background: var(--navy); color: #fff; font-weight: 700; font-size: 0.94rem;
  cursor: pointer; text-align: center; transition: transform .12s ease, background .15s ease;
}
.btn:hover { background: var(--navy-soft); color: #fff; text-decoration: none; transform: translateY(-1px); }
a.btn { color: #fff; }
.btn-secondary { background: transparent; border: 1.5px solid var(--line); color: var(--navy); }
.btn-secondary:hover { background: var(--surface-tint); border-color: var(--sand); color: var(--navy); }
a.btn-secondary { color: var(--navy); }
.btn-small { padding: 7px 15px; font-size: 0.83rem; }
.btn-danger { background: #b4432f; }
.btn-danger:hover { background: #97361f; }
.ai-maintained { color: #b4432f; font-weight: 600; }
.info-tip { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; margin-left: 2px; border-radius: 50%; border: 1px solid currentColor; font-size: 0.68rem; line-height: 1; font-style: normal; font-weight: 600; color: var(--muted); cursor: help; vertical-align: middle; }
.info-tip .info-tip-bubble { position: absolute; bottom: 135%; left: 0; width: 210px; max-width: min(210px, 72vw); padding: 10px 12px; border-radius: 8px; background: var(--navy); color: #fff; font-size: 0.8rem; line-height: 1.4; font-weight: 400; text-align: left; opacity: 0; visibility: hidden; transition: opacity 0.15s ease; pointer-events: none; z-index: 5; }
.info-tip:hover .info-tip-bubble, .info-tip:focus .info-tip-bubble, .info-tip.is-open .info-tip-bubble { opacity: 1; visibility: visible; pointer-events: auto; }
.btn-tickets { background: var(--coral); font-size: 1.02rem; padding: 15px 30px; }
.btn-tickets:hover { background: #c95c38; }

/* ---- category tones -----------------------------------------------------
   One hook per category. Each sets --tone, and everything that needs to be
   tinted reads from it, so a card, a chip and an icon tile stay in step. */

.tone-teal    { --tone: #379fa1; --tone-wash: #e9f8f9; }
.tone-coral   { --tone: #c43d3d; --tone-wash: #f8e8e8; }
.tone-lilac   { --tone: #7f8f6a; --tone-wash: #f0f2ed; }
.tone-navy    { --tone: #3b6888; --tone-wash: #e9f0f4; }
.tone-rose    { --tone: #d98da2; --tone-wash: #f3f6f9; }
.tone-seafoam { --tone: #4fa87f; --tone-wash: #f3f6ef; }
.tone-sand    { --tone: #a8846f; --tone-wash: #f5f2f1; }
.tone-dusk    { --tone: #4a7ca3; --tone-wash: #e9eff4; }
.tone-gold    { --tone: #c9922f; --tone-wash: #faf4e8; }
.tone-sunset  { --tone: #d4694f; --tone-wash: #fdeee9; }
.tone-sky     { --tone: #4f93b5; --tone-wash: #f4fcfc; }
.tone-clay    { --tone: #b07a52; --tone-wash: #f7efe7; }
.tone-olive   { --tone: #7f9463; --tone-wash: #eff3e9; }

/* ---- cards & grid ------------------------------------------------------ */

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(264px, 1fr)); gap: 24px; margin-top: 12px; }

.card {
  background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r);
  display: flex; flex-direction: column; overflow: hidden; box-shadow: var(--shadow-sm);
  transition: box-shadow .2s ease, transform .2s ease, border-color .2s ease;
}
.card:hover { box-shadow: var(--shadow); transform: translateY(-3px); border-color: var(--line); text-decoration: none; }

.card-media { position: relative; aspect-ratio: 3 / 2; background: var(--surface-tint); overflow: hidden; }
/* `> img:not(.card-logo)` matters. This rule used to be plain `.card-media img`,
   which also caught the logo overlay — and at specificity (0,1,1) it beat
   `.card-logo` (0,1,0), stretching a wordmark to fill the tile and cropping it
   under object-fit: cover. Anything else laid over the photo would have hit the
   same trap. */
.card-media > img:not(.card-logo) { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .45s ease; }
.card:hover .card-media > img:not(.card-logo) { transform: scale(1.045); }
/* News cards mix real photos with municipal crests and paper logos — cropping
   a logo to fill a 3:2 photo box turns it into an illegible smear, so this
   content type is contained and padded instead of covered. */
.news-card .card-media > img { object-fit: contain; padding: 14px; }
.news-card:hover .card-media > img { transform: none; }

/* A soft scrim under the logo so a pale wordmark still reads against a bright
   photograph. Only where there is a logo to protect. */
.card-media:has(.card-logo)::before {
  content: ''; position: absolute; inset: auto 0 0 0; height: 46%; z-index: 1;
  background: linear-gradient(to top, rgba(12, 32, 46, 0.34), transparent);
  pointer-events: none;
}

/* No photograph yet: a tinted tile carrying the category mark, so the grid
   still looks composed and nothing pretends to be a picture of the place. */
.card-media.is-placeholder {
  display: grid; place-items: center;
  background:
    radial-gradient(120% 100% at 20% 0%, #fff 0%, transparent 60%),
    linear-gradient(150deg, var(--tone-wash, var(--surface-tint)) 0%, color-mix(in srgb, var(--tone, var(--navy-soft)) 22%, #fff) 100%);
}
.placeholder-icon { color: var(--tone, var(--navy-soft)); opacity: 0.72; }
/* Vary the light source slightly card to card, so a column of same-category
   placeholders reads as a set rather than a copy-paste. */
.grid > :nth-child(3n+2) .card-media.is-placeholder { background-position: 70% 0; }
.grid > :nth-child(3n+2) .placeholder-icon { transform: rotate(-4deg); }
.grid > :nth-child(3n+3) .card-media.is-placeholder { background-position: 40% 100%; }
.grid > :nth-child(3n+3) .placeholder-icon { transform: rotate(3deg) scale(1.04); }
.grid > :nth-child(4n+1) .card-media.is-placeholder::after { opacity: 0.6; }
.card-media.is-placeholder::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 34%;
  background: radial-gradient(120% 100% at 50% 100%, color-mix(in srgb, var(--tone, var(--navy-soft)) 16%, transparent), transparent 70%);
}

/* Sits inside the photo rather than straddling the fold, and stays small — the
   point of the card is the picture, the logo is only there to identify it. */
.card-media img.card-logo {
  position: absolute; left: 12px; bottom: 12px; z-index: 2;
  /* Height is fixed, width follows the logo's own proportions up to a limit.
     Most business logos are wide wordmarks: forced into a square they shrink to
     a few illegible pixels tall, which defeats the point of showing one. A
     square mark still comes out square. */
  height: 34px; width: auto; max-width: 132px; padding: 4px 7px;
  object-fit: contain; object-position: center;
  border-radius: 9px; background: #fff; border: 1px solid rgba(255, 255, 255, 0.85);
  box-shadow: 0 2px 8px rgba(12, 32, 46, 0.22);
  transition: transform .25s ease;
}
.card:hover img.card-logo { transform: translateY(-2px); }

.card-body { padding: 16px 18px 18px; display: flex; flex-direction: column; gap: 5px; flex: 1; }
.card h3 { margin: 0; font-size: 1.06rem; line-height: 1.25; }
/* Two lines is enough for a card; the full tagline is on the listing page. */
.card .tagline {
  color: var(--ink-soft); font-size: 0.9rem; margin: 0; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.card .meta { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin: 4px 0 0; }
/* Pinned to the bottom of the flex column so the pills line up across a row
   of cards regardless of how long each one's tagline/meta happens to be. */
.card-status { display: flex; gap: 6px; flex-wrap: wrap; margin: 6px 0 0; margin-top: auto; padding-top: 6px; align-items: center; }
.card-status .open-pill, .card-status .special-pill { margin: 0; }

.cat-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 0.73rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  padding: 4px 10px 4px 8px; border-radius: var(--r-pill);
  background: var(--tone-wash, var(--surface-tint)); color: var(--tone, var(--navy-soft));
}
.chip-icon { flex: 0 0 auto; }
.card-town { font-size: 0.82rem; color: var(--muted); }
.card-distance { font-size: 0.82rem; color: var(--navy-soft, var(--navy)); font-weight: 700; }

.badge {
  position: absolute; top: 12px; right: 12px;
  background: rgba(255,255,255,0.94); color: var(--navy); font-size: 0.68rem;
  font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 5px 11px; border-radius: var(--r-pill); box-shadow: var(--shadow-sm);
}

/* ---- category strip ---------------------------------------------------- */

.cat-strip { margin: 26px 0 8px; position: relative; }
.cat-strip-inner {
  display: flex; gap: 6px; overflow-x: auto; padding: 4px 2px 12px;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.cat-strip-inner::-webkit-scrollbar { display: none; }
/* Edge fades hint that the strip scrolls. The right-hand fade is visible by
   default — a reasonable assumption with this many categories, and a fallback
   if JS never runs — then cat-strip.js refines both edges against the user's
   actual scroll position as they reach either end. */
.cat-strip::before,
.cat-strip::after {
  position: absolute; top: 4px; bottom: 12px; width: 40px;
  pointer-events: none; z-index: 1; transition: opacity .2s ease;
  display: flex; align-items: center; font-size: 1.5rem; font-weight: 800; color: var(--muted);
}
.cat-strip::before {
  left: 0; opacity: 0; content: '‹'; justify-content: flex-start; padding-left: 2px;
  background: linear-gradient(to right, var(--bg), var(--bg) 45%, rgba(251, 248, 244, 0));
}
.cat-strip::after {
  right: 0; opacity: 1; content: '›'; justify-content: flex-end; padding-right: 2px;
  background: linear-gradient(to left, var(--bg), var(--bg) 45%, rgba(251, 248, 244, 0));
}
.cat-strip.has-scroll-left::before { opacity: 1; }
.cat-strip.no-scroll-right::after { opacity: 0; }

/* Spells out the fade-arrow hint in words, for the homepage category band —
   a lone "›" is an easy miss for first-time or older users who don't know
   to swipe. Hides itself the same way the arrow does, once there's nothing
   left to scroll to. */
.cat-strip-hint {
  margin: 2px 2px 0; font-size: 0.72rem; font-weight: 600; color: var(--muted);
  text-align: right; transition: opacity .2s ease;
}
.cat-strip.no-scroll-right .cat-strip-hint { opacity: 0; }
.cat-strip-hint-arrow { display: inline-block; animation: cat-strip-hint-nudge 1.4s ease-in-out infinite; }
@keyframes cat-strip-hint-nudge {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(4px); }
}
@media (prefers-reduced-motion: reduce) {
  .cat-strip-hint-arrow { animation: none; }
}

.cat-strip-item {
  flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: 7px;
  padding: 12px 16px 10px; border-radius: var(--r); min-width: 92px;
  color: var(--muted); font-size: 0.76rem; font-weight: 600; text-align: center;
  border-bottom: 2px solid transparent; transition: color .15s ease, background .15s ease;
}
.cat-strip-item svg { color: var(--muted); transition: color .15s ease, transform .2s ease; }
.cat-strip-item:hover { color: var(--navy); background: var(--surface); text-decoration: none; }
.cat-strip-item:hover svg { color: var(--tone, var(--navy-soft)); transform: translateY(-2px); }
.cat-strip-item.active { color: var(--navy); border-bottom-color: var(--tone, var(--navy-soft)); }
.cat-strip-item.active svg { color: var(--tone, var(--navy-soft)); }

/* Upcoming-events rail on Local Lowdown: the same scroll/fade strip as
   categories, just carrying event .card tiles instead of pills. */
.event-rail { margin-top: 14px; }
.event-rail .cat-strip-inner { gap: 16px; padding: 4px 2px 16px; align-items: stretch; }
.event-rail-card { flex: 0 0 240px; }
@media (max-width: 560px) {
  .event-rail-card { flex: 0 0 200px; }
}

/* "Search by location" rail on the home page and /near-me: four tiles in
   view at once on a typical desktop width, closest first, more of them
   peeking at the right edge to invite scrolling. */
.near-me-rail { margin-top: 18px; }
.near-me-rail .cat-strip-inner { gap: 16px; padding: 4px 2px 16px; align-items: stretch; }
.near-me-tile { flex: 0 0 240px; }

/* Home page bands (News, Specials, Featured, Local Lowdown, Beaches, Browse
   by category): the same scroll/fade rail as above, carrying whichever card
   each section already builds. Four tiles fetched per section (see
   renderHome in server.js) is exactly enough to bleed a peek of the fourth
   off the right edge on a typical phone width, inviting the swipe — on a
   wide desktop viewport all four usually fit and the fade hides itself,
   same as the near-me rail. */
.news-rail, .specials-rail, .featured-rail, .lowdown-rail, .beaches-rail, .category-rail { margin-top: 14px; }
.news-rail .cat-strip-inner,
.specials-rail .cat-strip-inner,
.featured-rail .cat-strip-inner,
.lowdown-rail .cat-strip-inner,
.beaches-rail .cat-strip-inner,
.category-rail .cat-strip-inner {
  gap: 16px; padding: 4px 2px 16px; align-items: stretch;
}
.news-rail .card, .specials-rail .card, .featured-rail .card, .lowdown-rail .card, .beaches-rail .card {
  flex: 0 0 240px;
}
.category-rail .cat-card { flex: 0 0 260px; }
@media (max-width: 560px) {
  .news-rail .card, .specials-rail .card, .featured-rail .card, .lowdown-rail .card, .beaches-rail .card {
    flex: 0 0 200px;
  }
  .category-rail .cat-card { flex: 0 0 220px; }
}
@media (max-width: 560px) {
  .near-me-tile { flex: 0 0 200px; }
}

/* ---- category cards ---------------------------------------------------- */

.cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(272px, 1fr)); gap: 18px; margin-top: 14px; }
.cat-card {
  display: flex; gap: 15px; align-items: flex-start;
  background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r);
  padding: 20px; box-shadow: var(--shadow-sm);
  transition: box-shadow .2s ease, transform .2s ease, border-color .2s ease;
}
.cat-card:hover { text-decoration: none; box-shadow: var(--shadow); transform: translateY(-2px); border-color: color-mix(in srgb, var(--tone, var(--navy-soft)) 35%, var(--line)); }
.cat-card-icon {
  flex: 0 0 auto; width: 50px; height: 50px; border-radius: 15px;
  display: grid; place-items: center; background: var(--tone-wash, var(--surface-tint)); color: var(--tone, var(--navy-soft));
}
.cat-card-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cat-card-text strong { color: var(--navy); font-size: 1.02rem; }
.cat-card-desc { font-size: 0.88rem; color: var(--ink-soft); }
.cat-card-count { font-size: 0.76rem; color: var(--tone, var(--navy-soft)); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; margin-top: 4px; }

/* category page header, tinted with that category's own colour */
.cat-hero {
  display: flex; gap: 20px; align-items: flex-start;
  background: linear-gradient(140deg, #fff 0%, var(--tone-wash, var(--surface-tint)) 130%);
  border: 1px solid color-mix(in srgb, var(--tone, var(--navy-soft)) 18%, var(--line-soft));
  border-radius: var(--r-lg); padding: 26px 28px; margin-bottom: 6px;
}
.cat-hero h1 { margin: 0 0 6px; }
.cat-hero .lede { margin: 0; }
.cat-hero .eyebrow { color: var(--tone, var(--navy-soft)); }
.cat-hero-icon {
  flex: 0 0 auto; width: 62px; height: 62px; border-radius: 18px;
  display: grid; place-items: center; background: #fff; color: var(--tone, var(--navy-soft));
  border: 1px solid color-mix(in srgb, var(--tone, var(--navy-soft)) 20%, var(--line-soft));
  box-shadow: var(--shadow-sm);
}

/* A slogan line — display face, sized between a heading and body copy so it
   reads as a statement rather than another paragraph. */
.slogan {
  font-family: var(--font-hero); font-style: italic;
  font-size: clamp(1.6rem, 3.4vw, 2.3rem); line-height: 1.1; letter-spacing: -0.02em;
  color: var(--teal-deep); margin: 4px 0 8px;
}

/* ---- section headers --------------------------------------------------- */
/* category page header, tinted with that category's own colour */
.cat-hero {
  display: flex; gap: 20px; align-items: flex-start;
  background: linear-gradient(140deg, #fff 0%, var(--tone-wash, var(--surface-tint)) 130%);
  border: 1px solid color-mix(in srgb, var(--tone, var(--navy-soft)) 18%, var(--line-soft));
  border-radius: var(--r-lg); padding: 26px 28px; margin-bottom: 6px;
}
.cat-hero h1 { margin: 0 0 6px; }
.cat-hero .lede { margin: 0; }
.cat-hero .eyebrow { color: var(--tone, var(--navy-soft)); }
.cat-hero-icon {
  flex: 0 0 auto; width: 62px; height: 62px; border-radius: 18px;
  display: grid; place-items: center; background: #fff; color: var(--tone, var(--navy-soft));
  border: 1px solid color-mix(in srgb, var(--tone, var(--navy-soft)) 20%, var(--line-soft));
  box-shadow: var(--shadow-sm);
}

/* A slogan line — display face, sized between a heading and body copy so it
   reads as a statement rather than another paragraph. */
.slogan {
  font-family: var(--font-hero); font-style: italic;
  font-size: clamp(1.6rem, 3.4vw, 2.3rem); line-height: 1.1; letter-spacing: -0.02em;
  color: var(--teal-deep); margin: 4px 0 8px;
}

/* ---- section headers --------------------------------------------------- */

.section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin: 46px 0 6px; }
.section-head h2 { margin: 0; }
.section-head .eyebrow { margin-bottom: 4px; }
.section-head > div { min-width: 0; }
.section-head a { font-size: 0.9rem; font-weight: 700; white-space: nowrap; }

/* ---- pills ------------------------------------------------------------- */

.open-pill {
  display: inline-block; font-size: 0.74rem; font-weight: 700; letter-spacing: 0.03em;
  padding: 4px 12px; border-radius: var(--r-pill); border: 1px solid transparent;
}
.open-pill.is-open { background: var(--teal-wash); color: var(--teal-deep); border-color: #bfe6ea; }
.open-pill.is-closed { background: var(--surface-tint); color: var(--muted); border-color: var(--line); }
.special-pill {
  display: inline-block; background: var(--coral-wash); color: #b4502e; border: 1px solid #f6d3c4;
  font-size: 0.72rem; font-weight: 700; padding: 4px 11px; border-radius: var(--r-pill);
}
.header-status { margin: 8px 0 0; font-size: 0.9rem; }
.header-status .muted { margin-left: 8px; }

/* ---- filters ----------------------------------------------------------- */

.filters { display: flex; flex-wrap: wrap; gap: 8px; margin: 16px 0 22px; }
.filters a {
  display: inline-block; padding: 8px 15px; border: 1px solid var(--line); border-radius: var(--r-pill);
  font-size: 0.86rem; background: var(--surface); color: var(--ink-soft);
}
.filters a:hover { border-color: var(--teal); color: var(--navy); text-decoration: none; }
.filters a.active { background: var(--navy); border-color: var(--navy); color: #fff; }

.refine { margin: 14px 0 22px; }
.refine-primary { margin: 0 0 8px; }
.refine-amenities summary { cursor: pointer; font-size: 0.87rem; color: var(--teal-deep); font-weight: 700; padding: 5px 0; }
.refine-amenities[open] summary { margin-bottom: 8px; }
.refine-amenities .filters { margin: 0 0 8px; }
.day-tabs { margin-bottom: 10px; }
.did-you-mean { background: var(--sand-wash); border: 1px solid var(--line); border-radius: var(--r); padding: 14px 18px; }

/* ---- Local Lowdown calendar --------------------------------------------- */

.calendar { margin: 6px 0 32px; }
.calendar-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.calendar-head h2 { margin: 0; }
.calendar-nav {
  display: grid; place-items: center; width: 38px; height: 38px; flex: 0 0 auto;
  border-radius: 50%; border: 1px solid var(--line); background: var(--surface); color: var(--navy); font-size: 1.1rem;
}
.calendar-nav:hover { background: var(--dusk-wash); border-color: var(--dusk); color: var(--dusk); text-decoration: none; }
.calendar-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; margin-bottom: 6px; }
.calendar-weekdays span {
  text-align: center; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
.calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; }
.calendar-day {
  position: relative; aspect-ratio: 1 / 1; display: flex; align-items: center; justify-content: center;
  border-radius: var(--r-sm); background: transparent; border: 1px solid transparent;
  color: var(--ink); font-size: 0.9rem; font-weight: 600; transition: background .15s ease, border-color .15s ease;
}
.calendar-day:hover { border-color: var(--dusk); background: var(--dusk-wash); text-decoration: none; }
.calendar-day.is-outside { color: var(--muted); font-weight: 400; }
.calendar-day.is-selected { background: var(--navy); border-color: var(--navy); color: #fff; }
.calendar-day.is-selected:hover { background: var(--navy-deep); border-color: var(--navy-deep); }
/* The number itself carries the "has events" / "is today" marks as a circle,
   so a plain day with nothing on keeps no background or border at all. */
.calendar-daynum {
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%; transition: background .15s ease, box-shadow .15s ease;
}
.calendar-day.is-today .calendar-daynum { box-shadow: inset 0 0 0 1.5px var(--dusk); }
.calendar-day.has-events .calendar-daynum { background: var(--dusk-wash); box-shadow: inset 0 0 0 1.5px var(--dusk); }
.calendar-day.is-selected .calendar-daynum { background: transparent; box-shadow: none; }
@media (max-width: 560px) {
  .calendar-day { font-size: 0.8rem; }
  .calendar-daynum { width: 26px; height: 26px; }
  .calendar-weekdays span { font-size: 0.62rem; }
}

/* ---- conditions band --------------------------------------------------- */

.conditions {
  background: linear-gradient(135deg, #ffffff 0%, var(--teal-wash) 100%);
  border: 1px solid #d9edf0; border-radius: var(--r-lg); padding: 22px 24px; margin: 22px 0 8px;
  box-shadow: var(--shadow-sm);
}
.cond-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.cond-head h2 { margin: 0; font-size: 1.05rem; }
.cond-stale { font-size: 0.72rem; color: var(--muted); background: rgba(255,255,255,0.7); border-radius: var(--r-pill); padding: 3px 11px; }
.cond-body { display: grid; grid-template-columns: 1.15fr 1fr; gap: 28px; margin-top: 16px; align-items: start; }
.cond-now { display: flex; align-items: center; gap: 16px; }
.cond-icon { font-size: 2.6rem; line-height: 1; }
.cond-temp { font-family: var(--font-hero); font-style: italic; font-size: 3.2rem; color: var(--navy); line-height: 1; letter-spacing: -0.02em; }
.cond-desc { display: flex; flex-direction: column; line-height: 1.4; }
.cond-desc strong { color: var(--navy); }
.cond-desc .muted { font-size: 0.84rem; }
.cond-facts { list-style: none; display: flex; flex-wrap: wrap; gap: 10px 26px; padding: 0; margin: 16px 0 0; }
.cond-facts li { display: flex; flex-direction: column; font-size: 0.92rem; color: var(--navy); font-weight: 600; }
.cond-facts span { color: var(--muted); font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 400; }
.cond-tides { border-left: 1px solid #cfe7ea; padding-left: 28px; }
.cond-tides h3 { margin: 0 0 12px; font-size: 0.95rem; }
.tide-list { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); gap: 9px; }
.tide-list li { background: rgba(255,255,255,0.8); border: 1px solid #d9edf0; border-radius: var(--r-sm); padding: 9px 12px; display: flex; flex-direction: column; gap: 2px; }
/* High tides in the same sand as the radio streaming boxes; the teal border is
   what still tells them apart from the lows. */
.tide-list li.tide-high { background: var(--bg, #fbf8f4); border-color: var(--teal); }
.tide-type { font-size: 0.68rem; font-weight: 700; letter-spacing: 0.05em; color: var(--teal-deep); text-transform: uppercase; }
.tide-time { font-size: 1.1rem; font-weight: 700; color: var(--navy); font-variant-numeric: tabular-nums; }
.tide-note { font-size: 0.72rem; margin: 12px 0 0; line-height: 1.45; }

/* ---- load shedding ----------------------------------------------------- */

.loadshedding { border-radius: var(--r); padding: 18px 22px; margin: 16px 0; border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow-sm); }
.loadshedding.is-active { border-color: #f0cdbb; background: var(--coral-wash); }
.ls-main { display: flex; align-items: center; gap: 16px; }
.ls-icon { font-size: 1.8rem; }
.ls-main strong { display: block; font-size: 1.05rem; color: var(--navy); }
.ls-main .muted { font-size: 0.86rem; }
.ls-slots { list-style: none; display: flex; gap: 10px; flex-wrap: wrap; padding: 0; margin: 14px 0 0; }
.ls-slots li { background: rgba(255,255,255,0.75); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 7px 13px; display: flex; flex-direction: column; }
.ls-slots .muted { font-size: 0.72rem; }
.ls-note { font-size: 0.72rem; margin: 12px 0 0; }
.ls-other { margin: 16px 0 0; padding: 14px 0 0; border-top: 1px solid var(--line); }
.ls-other h3 { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--teal-deep); margin: 0 0 8px; }
.ls-other-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
.ls-other-list li { font-size: 0.92rem; }
.ls-other-list .muted { font-size: 0.8rem; }
.ls-other-note { font-size: 0.82rem; margin: 3px 0 0; color: var(--ink-soft); }

/* ---- listing detail ---------------------------------------------------- */

.listing-detail .header { display: flex; justify-content: flex-start; align-items: flex-start; gap: 20px; flex-wrap: wrap; }
.listing-detail .header > div { flex: 1 1 240px; min-width: 0; }
.listing-logo { width: 96px; height: 96px; object-fit: contain; border-radius: var(--r); background: #fff; border: 1px solid var(--line-soft); padding: 9px; flex: 0 0 auto; box-shadow: var(--shadow-sm); }
.save-toggle-form { flex: 0 0 auto; }
.btn-save-toggle { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 999px; border: 1px solid var(--line-soft); background: #fff; color: var(--coral, #b4502e); font-size: 1.3rem; line-height: 1; cursor: pointer; box-shadow: var(--shadow-sm); flex: 0 0 auto; }
.btn-save-toggle.is-saved { background: var(--coral-wash, #fdeeea); }
.btn-remind { display: inline-block; margin: 10px 0 0; }
.btn-remind.is-active { background: var(--muted); }

.perk-card .card-body { gap: 8px; }
.perk-terms { font-size: 0.78rem; }
.perk-code { font-size: 1.05rem; color: var(--teal-deep, #22574c); }
.welcome-back { background: var(--surface-tint); border-radius: var(--r-sm); padding: 10px 16px; margin: 18px 0 0; font-size: 0.9rem; }
.rating { color: #d9a441; font-size: 1.12rem; }
.rating .count { color: var(--muted); font-size: 0.85rem; margin-left: 6px; }
.info-table { width: 100%; border-collapse: collapse; margin: 22px 0; }
.info-table td { padding: 11px 0; border-top: 1px solid var(--line-soft); vertical-align: top; }
/* padding-right is load-bearing: the label column had none, so a long label
   ("Municipal emergencies / 24-hour control room") ran straight into the value
   beside it with no gap at all. */
.info-table td:first-child { width: 130px; padding-right: 18px; color: var(--muted); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em; }

.panels { display: grid; grid-template-columns: repeat(auto-fit, minmax(310px, 1fr)); gap: 22px; margin: 28px 0 8px; align-items: start; }
.panel { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r); padding: 22px; box-shadow: var(--shadow-sm); }
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.panel-head h2 { margin: 0; font-size: 1.05rem; }

.hours-detail { margin: 10px 0 14px; color: var(--ink-soft); font-size: 0.9rem; }
.hours-table { width: 100%; border-collapse: collapse; font-size: 0.93rem; }
.hours-table th, .hours-table td { padding: 9px 0; border-top: 1px solid var(--line-soft); text-align: left; font-weight: 400; }
.hours-table tr:first-child th, .hours-table tr:first-child td { border-top: none; }
.hours-table td { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink-soft); }
.hours-table tr.today th, .hours-table tr.today td { font-weight: 700; color: var(--navy); }
.hours-table tr.closed td { color: var(--muted); }
.today-tag { background: var(--teal); color: #fff; font-size: 0.63rem; font-weight: 700; padding: 2px 8px; border-radius: var(--r-pill); margin-left: 7px; vertical-align: 1px; text-transform: uppercase; letter-spacing: 0.05em; }
.hours-note { margin: 14px 0 0; font-size: 0.88rem; color: var(--ink-soft); }
.tz-note { font-size: 0.74rem; margin: 8px 0 0; }

.location-panel .address { margin: 12px 0 14px; font-size: 0.97rem; }
.map-frame { position: relative; border-radius: var(--r-sm); overflow: hidden; border: 1px solid var(--line); background: var(--surface-tint); }
.map-frame iframe { display: block; width: 100%; height: 270px; border: 0; }
.map-overlay { position: absolute; inset: 0; display: flex; align-items: flex-start; justify-content: flex-start; padding: 14px; background: transparent; transition: background .15s; }
.map-overlay:hover, .map-overlay:focus-visible { background: rgba(4, 62, 102, 0.14); text-decoration: none; outline: none; }
.map-overlay-hint { background: rgba(0, 42, 69, 0.9); color: #fff; font-size: 0.8rem; font-weight: 700; padding: 8px 15px; border-radius: var(--r-pill); box-shadow: var(--shadow); }
.map-overlay:focus-visible .map-overlay-hint { outline: 2px solid #fff; outline-offset: 2px; }
.map-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.map-actions .btn { display: inline-block; }

/* ---- listing actions --------------------------------------------------- */

.listing-actions { display: flex; gap: 10px; flex-wrap: wrap; margin: 22px 0 4px; }
.btn-contact {
  display: inline-flex; align-items: center; gap: 9px;
  background: var(--teal); color: #fff;
}
.btn-contact:hover { background: var(--teal-deep); color: #fff; }
.btn-contact svg { flex: 0 0 auto; }
.map-approx { font-size: 0.76rem; margin: 10px 0 0; }

/* ---- map pin picker ---------------------------------------------------- */

.location-field { border: 1px solid var(--line); border-radius: var(--r); padding: 16px 18px 18px; margin: 0; background: var(--surface); }
.location-field legend { font-weight: 700; font-size: 0.9rem; padding: 0 7px; color: var(--navy); }

.map-picker { display: flex; flex-direction: column; gap: 10px; }
.map-picker-search { display: flex; gap: 8px; }
.map-picker-search input {
  flex: 1; padding: 10px 14px; border: 1px solid var(--line); border-radius: var(--r-pill);
  font-family: inherit; font-size: 0.92rem; background: #fff;
}
.map-picker-search input:focus { outline: 2px solid var(--teal); outline-offset: 1px; }
.map-picker-search .btn { flex: 0 0 auto; }

.map-picker-frame {
  position: relative; height: 320px; border-radius: var(--r); overflow: hidden;
  border: 1px solid var(--line); background: #dfe6e3; touch-action: none; user-select: none;
}
.map-picker-canvas { position: absolute; inset: 0; cursor: grab; }
.map-picker.is-dragging .map-picker-canvas { cursor: grabbing; }
.map-tile { position: absolute; width: 256px; height: 256px; pointer-events: none; }

/* The pin sits still at the centre and the map moves underneath — on a phone a
   fingertip would otherwise cover the exact thing being positioned. */
.map-picker-crosshair {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -100%);
  pointer-events: none; filter: drop-shadow(0 3px 6px rgba(0, 30, 50, 0.35));
  transition: transform .12s ease;
}
.map-picker.is-dragging .map-picker-crosshair { transform: translate(-50%, -108%); }
.map-picker.is-empty .map-picker-crosshair { opacity: 0.45; }
/* A small fixed dot marks the exact point the pin refers to. */
.map-picker-crosshair::after {
  content: ''; position: absolute; left: 50%; bottom: -3px; width: 6px; height: 6px;
  border-radius: 50%; background: rgba(0, 30, 50, 0.5); transform: translateX(-50%);
}

.map-picker-zoom { position: absolute; right: 10px; top: 10px; display: flex; flex-direction: column; gap: 4px; }
.map-picker-zoom button {
  width: 34px; height: 34px; border-radius: 9px; border: 1px solid var(--line);
  background: rgba(255,255,255,0.95); color: var(--navy); font-size: 1.15rem; font-weight: 700;
  cursor: pointer; line-height: 1; box-shadow: var(--shadow-sm);
}
.map-picker-zoom button:hover { background: #fff; border-color: var(--teal); }

.map-picker-attrib {
  position: absolute; right: 0; bottom: 0; margin: 0; padding: 2px 7px;
  background: rgba(255,255,255,0.82); font-size: 0.63rem; color: var(--muted); border-radius: 6px 0 0 0;
}
.map-picker-attrib a { color: var(--muted); }

.map-picker-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.map-picker-coords {
  font-family: var(--font-body); font-variant-numeric: tabular-nums; font-size: 0.88rem;
  font-weight: 700; color: var(--navy); background: var(--surface-tint);
  padding: 6px 13px; border-radius: var(--r-pill);
}
.map-picker.is-empty .map-picker-coords { color: var(--muted); font-weight: 400; }
.map-picker-buttons { display: flex; gap: 8px; flex-wrap: wrap; }
.map-picker-status { font-size: 0.82rem; margin: 0; min-height: 1.2em; color: var(--muted); }
.map-picker-status.is-ok { color: #2c7f5c; }
.map-picker-status.is-error { color: #b4432f; }

/* ---- whatsapp + social ------------------------------------------------- */

.btn-whatsapp { display: inline-flex; align-items: center; gap: 9px; background: #25a35a; color: #fff; }
.btn-whatsapp:hover { background: #1d8549; color: #fff; }
.btn-whatsapp svg { flex: 0 0 auto; }

.social-row { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin: 16px 0 4px; }
.social-link {
  width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-soft);
  transition: transform .15s ease, background .15s ease, color .15s ease, border-color .15s ease;
}
.social-link:hover { transform: translateY(-2px); color: #fff; text-decoration: none; }
.social-facebook:hover  { background: #1877f2; border-color: #1877f2; }
.social-x:hover         { background: #000;     border-color: #000; }
.social-instagram:hover { background: linear-gradient(45deg, #f09433, #dc2743 45%, #bc1888); border-color: #dc2743; }
.social-tiktok:hover    { background: #010101; border-color: #010101; }
.social-youtube:hover   { background: #ff0000; border-color: #ff0000; }

/* Labeled variant: a pill with icon + text rather than a bare circle — used
   on the connect band, where "Facebook" and "Facebook Group" are two
   different links and need to read as different at a glance, not just on
   hover-title. */
.social-link-labeled {
  width: auto; height: auto; display: inline-flex; align-items: center;
  border-radius: var(--r-pill); gap: 8px; padding: 9px 16px 9px 14px;
  font-size: 0.86rem; font-weight: 600;
}
.social-link-labeled svg { flex: 0 0 auto; }
.social-link-labeled:hover { color: var(--ink-soft); }
.social-facebook.social-link-labeled:hover  { background: var(--surface); border-color: #1877f2; color: #1877f2; }
.social-x.social-link-labeled:hover         { background: var(--surface); border-color: #000; color: #000; }
.social-instagram.social-link-labeled:hover { background: var(--surface); border-color: #dc2743; color: #dc2743; }
.social-youtube.social-link-labeled:hover   { background: var(--surface); border-color: #ff0000; color: #ff0000; }

.social-field { border: 1px solid var(--line); border-radius: var(--r); padding: 16px 18px; margin: 0; background: var(--surface); }
.social-field legend { font-weight: 700; font-size: 0.9rem; padding: 0 7px; color: var(--navy); }

/* ---- share ------------------------------------------------------------- */

.share-row { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin: 20px 0 6px; }
.share-label { font-size: 0.72rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.09em; }
.share-btn {
  display: inline-block; border: 1px solid var(--line); background: var(--surface); border-radius: var(--r-pill);
  padding: 8px 17px; font-size: 0.86rem; font-weight: 600; color: var(--navy); cursor: pointer; font-family: inherit;
}
.share-btn:hover { background: var(--surface-tint); text-decoration: none; border-color: var(--sand); }
.share-wa { border-color: #7fd6a2; color: #148a4d; background: #f2fcf6; }
.share-wa:hover { background: #e3f8ec; border-color: #25d366; }

/* ---- additional locations ---------------------------------------------- */

.other-locations { margin-top: 34px; }
.location-list { list-style: none; padding: 0; margin: 14px 0 0; display: grid; gap: 11px; }
.location-list li {
  background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r);
  padding: 15px 18px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  box-shadow: var(--shadow-sm);
}
.location-list strong { color: var(--navy); }
.location-address { color: var(--ink-soft); font-size: 0.92rem; }
.location-phone { font-size: 0.9rem; }
.location-directions { margin-left: auto; font-size: 0.85rem; font-weight: 700; white-space: nowrap; }

/* plan chips in the backend */
.plan-chip {
  display: inline-block; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; padding: 3px 10px; border-radius: var(--r-pill); margin-left: 6px;
}
.plan-free { background: var(--surface-tint); color: var(--muted); }
.plan-shark { background: var(--sky-wash); color: #3d7a95; }
.plan-whale { background: var(--teal-wash); color: var(--teal-deep); }
.plan-note { font-size: 0.83rem; color: var(--muted); margin: 6px 0 0; }
.locked-note {
  font-size: 0.82rem; color: var(--muted); background: var(--surface-tint);
  border-radius: var(--r-sm); padding: 9px 13px; margin: 8px 0 0;
}

@media (max-width: 640px) {
  .location-directions { margin-left: 0; }
}

/* ---- amenities --------------------------------------------------------- */

.amenities { margin-top: 34px; }
.amenity-grid { list-style: none; padding: 0; margin: 14px 0 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(186px, 1fr)); gap: 9px; }
.amenity-grid li { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r-sm); padding: 11px 15px; font-size: 0.9rem; color: var(--ink-soft); }

/* ---- gallery & lightbox ------------------------------------------------ */

.gallery { margin-top: 30px; }
.gallery-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; margin-top: 14px; }
.gallery-item { display: block; border-radius: var(--r); overflow: hidden; border: 1px solid var(--line-soft); background: var(--surface-tint); aspect-ratio: 4 / 3; box-shadow: var(--shadow-sm); }
.gallery-item img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .3s ease; }
.gallery-item:hover img { transform: scale(1.05); }
.gallery-count-1 { grid-template-columns: minmax(0, 560px); }

/* ---- estate agent tiles ------------------------------------------------ */

.agent-tile-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 14px; margin-top: 14px; }
.agent-tile { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; color: inherit; text-decoration: none; }
.agent-tile img, .agent-tile-placeholder { width: 84px; height: 84px; border-radius: 50%; object-fit: cover; background: var(--surface-tint); border: 1px solid var(--line-soft); }
.agent-tile-name { font-size: 0.85rem; font-weight: 600; }
.agent-tile:hover .agent-tile-name { text-decoration: underline; }
.photo-credits { margin: 12px 0 0; font-size: 0.75rem; color: var(--muted); line-height: 1.5; }
.photo-credit a { color: var(--muted); text-decoration: underline; text-underline-offset: 2px; }
.photo-credit a:hover { color: var(--teal-deep); }
/* Credit on a card image, small and out of the way but still present. */
.card-media .photo-credit {
  position: absolute; right: 8px; bottom: 6px; font-size: 0.6rem; color: rgba(255,255,255,0.86);
  text-shadow: 0 1px 3px rgba(0,0,0,0.6); pointer-events: none;
}

body.lightbox-open { overflow: hidden; }
.lightbox { position: fixed; inset: 0; z-index: 90; background: rgba(0, 30, 48, 0.94); display: flex; align-items: center; justify-content: center; gap: 10px; padding: 26px; }
.lightbox[hidden] { display: none; }
.lightbox-img { max-width: min(1040px, 88vw); max-height: 86vh; object-fit: contain; border-radius: var(--r-sm); }
.lightbox-close, .lightbox-nav { background: rgba(255,255,255,0.16); color: #fff; border: none; cursor: pointer; border-radius: 50%; width: 46px; height: 46px; font-size: 1.6rem; line-height: 1; flex: 0 0 auto; }
.lightbox-close:hover, .lightbox-nav:hover { background: var(--teal); }
.lightbox-close { position: absolute; top: 20px; right: 20px; font-size: 1.9rem; }

/* ---- specials ---------------------------------------------------------- */

.specials-section { margin-top: 36px; }
.specials-other { font-size: 0.95rem; margin: 24px 0 8px; color: var(--muted); font-family: var(--font-body); font-style: normal; }
.special-list { list-style: none; padding: 0; margin: 14px 0 0; display: grid; gap: 11px; }
.special-list li { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r); padding: 16px 18px; box-shadow: var(--shadow-sm); }
.special-list li.running { border-color: #f2cdbb; background: linear-gradient(180deg, #fffaf7 0%, #fff 60%); }
.special-list.muted-list li { background: transparent; box-shadow: none; }
.special-title { font-weight: 700; color: var(--navy); display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.special-price { margin-left: auto; background: var(--teal); color: #fff; font-size: 0.82rem; font-weight: 700; padding: 4px 13px; border-radius: var(--r-pill); }
.special-desc { margin: 7px 0 0; font-size: 0.92rem; color: var(--ink-soft); white-space: pre-line; }
.special-when { margin: 7px 0 0; font-size: 0.78rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.special-block { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r-lg); padding: 22px; margin-bottom: 18px; box-shadow: var(--shadow-sm); }
.special-head { display: flex; align-items: center; gap: 16px; }

/* ---- cinema showings ---------------------------------------------------- */

.cinema-showings { margin-top: 28px; }
.showing-list { list-style: none; padding: 0; margin: 14px 0 0; display: grid; gap: 12px; }
/* align-items: stretch (the default) makes the poster's height follow the
   text column's — i.e. its own content, ending at the ticket pills — rather
   than a fixed height, so it always reaches exactly that far and no further. */
.showing { display: flex; gap: 14px; background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r); padding: 14px; box-shadow: var(--shadow-sm); }
.showing-poster { width: 96px; flex: 0 0 auto; object-fit: cover; border-radius: 6px; background: var(--surface-tint); }
.showing-body { min-width: 0; }
.showing-body h3 { margin: 0; font-size: 1rem; }
.showing-meta { margin: 3px 0 0; font-size: 0.76rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.showing-desc { margin: 6px 0 0; font-size: 0.86rem; color: var(--ink-soft); }
.showing-times { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.showing-time-btn {
  display: inline-block; background: var(--coral); color: #fff; font-weight: 700; font-size: 0.8rem;
  padding: 6px 13px; border-radius: var(--r-pill); transition: background .15s ease;
}
.showing-time-btn:hover { background: #c95c38; color: #fff; text-decoration: none; }
@media (max-width: 480px) {
  .showing-poster { width: 76px; }
  .showing-body h3 { font-size: 0.94rem; }
}
.special-head h3 { margin: 0; font-size: 1.18rem; }
.special-head .meta { margin: 3px 0 0; font-size: 0.85rem; color: var(--muted); }
.special-logo { width: 56px; height: 56px; object-fit: contain; border-radius: 14px; background: #fff; border: 1px solid var(--line-soft); padding: 5px; flex: 0 0 auto; }
.special-block .special-list li { background: var(--bg); }

/* ---- menu -------------------------------------------------------------- */

.menu-section { margin-top: 36px; }
.menu-pdf-preview { width: 100%; height: 560px; border: 1px solid var(--line); border-radius: var(--r); background: #fff; display: block; margin-bottom: 14px; }
.menu-file-card { display: flex; align-items: center; gap: 15px; padding: 16px 18px; border: 1px solid var(--line-soft); border-radius: var(--r); background: var(--surface); max-width: 430px; box-shadow: var(--shadow-sm); }
.menu-file-card:hover { text-decoration: none; box-shadow: var(--shadow); }
.menu-file-icon { background: #b4432f; color: #fff; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.05em; padding: 9px 10px; border-radius: var(--r-sm); flex: 0 0 auto; }
.menu-file-text { display: flex; flex-direction: column; line-height: 1.35; }
.menu-file-text strong { color: var(--navy); font-size: 0.96rem; }
.menu-file-text .muted { font-size: 0.8rem; }
.menu-images { margin-top: 14px; }

/* ---- results map ------------------------------------------------------- */

.results-map { margin: 10px 0 20px; }
.results-map-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.results-map-head h2 { margin: 0; font-size: 1.05rem; }
.results-map-body { margin-top: 14px; border: 1px solid var(--line-soft); border-radius: var(--r); overflow: hidden; background: var(--surface); box-shadow: var(--shadow-sm); }
.results-map-body[hidden] { display: none; }
.results-map-body iframe { width: 100%; height: 350px; border: 0; display: block; }
.map-legend { margin: 0; padding: 14px 20px; display: grid; gap: 8px; list-style: none; }
.map-legend li { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 0.9rem; }
.map-legend-directions { font-size: 0.8rem; white-space: nowrap; }
.map-note { padding: 0 20px 16px; font-size: 0.76rem; margin: 0; }

/* ---- reviews ----------------------------------------------------------- */

.review { border-top: 1px solid var(--line-soft); padding: 18px 0; }
.review .rating { font-size: 0.98rem; }
.review .name { font-weight: 700; color: var(--navy); }
.review-reply { margin: 12px 0 0 20px; padding: 13px 17px; background: var(--teal-wash); border-left: 3px solid var(--teal); border-radius: 0 var(--r-sm) var(--r-sm) 0; }
.review-reply p { margin: 0 0 5px; font-size: 0.91rem; }
.reply-tag { background: var(--navy); color: #fff; font-size: 0.63rem; padding: 2px 8px; border-radius: var(--r-pill); margin-left: 5px; text-transform: uppercase; letter-spacing: 0.05em; }
.suggest-edit { margin-top: 32px; padding-top: 18px; border-top: 1px solid var(--line-soft); font-size: 0.88rem; color: var(--muted); }

/* ---- forms ------------------------------------------------------------- */

form.stacked { display: flex; flex-direction: column; gap: 16px; max-width: 620px; }
form.stacked label { font-weight: 700; font-size: 0.88rem; color: var(--navy); display: flex; flex-direction: column; gap: 7px; }
form.stacked input, form.stacked textarea, form.stacked select {
  padding: 12px 15px; border: 1px solid var(--line); border-radius: var(--r-sm);
  font-size: 0.97rem; font-family: inherit; font-weight: 400; color: var(--ink); background: #fff;
}
form.stacked input:focus, form.stacked textarea:focus, form.stacked select:focus { outline: 2px solid var(--teal); outline-offset: 1px; border-color: var(--teal); }
form.stacked textarea { min-height: 110px; resize: vertical; }

/* Type-to-filter combobox — progressive enhancement over a plain <select>,
   see public/js/searchable-select.js. The native select stays in the DOM
   (hidden) and still carries the form value. */
.searchable-select { position: relative; }
.searchable-select-native { display: none; }
.searchable-select-menu {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 20;
  max-height: 260px; overflow-y: auto; background: #fff; border: 1px solid var(--line);
  border-radius: var(--r-sm); box-shadow: 0 12px 28px -14px rgba(18, 48, 63, 0.35);
}
.searchable-select-option { padding: 9px 12px; font-size: 0.9rem; cursor: pointer; color: var(--ink); }
.searchable-select-option.is-active, .searchable-select-option:hover { background: var(--teal-wash); }
.searchable-select-option.is-selected { font-weight: 700; color: var(--navy); }
.searchable-select-empty { padding: 9px 12px; font-size: 0.85rem; color: var(--ink-soft); }

/* "This event repeats" + how often — greyed out until the checkbox is
   ticked, without needing any JS to keep the two in sync. */
.recur-row { display: flex; flex-direction: column; gap: 8px; }
.recur-row .recurrence-freq { gap: 8px; }
.recur-row .recurrence-freq select { max-width: 220px; }
.recur-row:has(input[name="recurring"]:not(:checked)) .recurrence-freq { opacity: 0.45; }
.recur-row:has(input[name="recurring"]:not(:checked)) .recurrence-freq select { pointer-events: none; }
.optional { font-weight: 400; color: var(--muted); font-size: 0.8rem; }
.field-help { font-size: 0.83rem; color: var(--muted); margin: 0 0 12px; }

fieldset { border: 1px solid var(--line); border-radius: var(--r); padding: 16px 18px 18px; margin: 0; background: var(--surface); }
legend { font-weight: 700; font-size: 0.9rem; padding: 0 7px; color: var(--navy); }

.notice { padding: 14px 18px; border-radius: var(--r-sm); margin-bottom: 22px; }
.notice.success { background: var(--teal-wash); color: #14606a; border: 1px solid #bfe6ea; }
.notice.error { background: #fdeeea; color: #93331d; border: 1px solid #f5cdc0; }
.notice-cta { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.notice-cta .btn { flex: none; }

.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.type-options { display: flex; gap: 10px; flex-wrap: wrap; }
form.stacked .type-option { flex-direction: row; align-items: center; gap: 9px; border: 1px solid var(--line); border-radius: var(--r-pill); padding: 9px 18px; background: #fff; cursor: pointer; }
form.stacked .type-option:has(input:checked) { background: var(--navy); border-color: var(--navy); color: #fff; }
.type-panel[hidden] { display: none; }

/* "How would you like to pay?" on the sign-up forms, and the billing panel on the owner dashboard. */
.pay-options { display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px; }
form.stacked .pay-option { flex-direction: row; align-items: flex-start; gap: 12px; border: 1px solid var(--line); border-radius: var(--r-sm); padding: 13px 16px; background: #fff; cursor: pointer; }
form.stacked .pay-option:has(input:checked) { border-color: var(--navy); box-shadow: 0 0 0 1px var(--navy); }
.pay-option input { margin-top: 4px; flex: none; }
.pay-option > span { display: flex; flex-direction: column; gap: 3px; }
.pay-title { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.pay-option small { color: var(--muted); font-size: 0.84rem; line-height: 1.4; }
.pay-code { margin: 4px 0 14px; }
.pay-code-toggle { background: none; border: 0; padding: 0; color: var(--navy); font: inherit; font-weight: 600; text-decoration: underline; cursor: pointer; }
.pay-code-entry { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.pay-code-entry input { flex: 1 1 180px; max-width: 260px; text-transform: uppercase; }
.pay-code-msg { flex-basis: 100%; margin: 0; font-size: 0.88rem; color: var(--muted); }
.pay-summary { background: var(--teal-wash); border: 1px solid #bfe6ea; color: #14606a; border-radius: var(--r-sm); padding: 12px 16px; margin: 0; font-size: 0.92rem; }
.pay-choice [hidden] { display: none; }
.billing-panel { margin: 14px 0 0; }
.billing-panel .notice { margin-bottom: 12px; }
.billing-actions { margin-left: 0; flex-wrap: wrap; align-items: flex-start; }
.cancel-sub summary { list-style: none; cursor: pointer; }
.cancel-sub summary::-webkit-details-marker { display: none; }
.cancel-sub-body { margin-top: 10px; padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff; max-width: 460px; }
.cancel-sub-body p { margin-top: 0; }
.type-panel { display: flex; flex-direction: column; gap: 16px; }
.date-inputs { display: flex; gap: 12px; flex-wrap: wrap; }
.date-inputs label { flex: 1; min-width: 165px; }
.form-footnote { font-size: 0.82rem; }
.coords-inputs { display: flex; gap: 12px; flex-wrap: wrap; }
.coords-inputs label { flex: 1; min-width: 145px; }

/* Visual rhythm for the long self-serve listing forms — these stay one
   continuous <form> (nothing about submission changes), this just breaks
   the wall of fieldsets into a sense of progress for anyone scrolling
   through it on a phone. */
.wizard-step {
  display: block; font-size: 0.73rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--teal-deep); margin: 28px 0 -6px;
  padding-top: 20px; border-top: 1px solid var(--line);
}
.wizard-step:first-of-type { margin-top: 18px; padding-top: 0; border-top: none; }

.hours-row { display: flex; align-items: center; gap: 9px; margin-bottom: 9px; flex-wrap: wrap; }
.hours-day { flex: 0 0 96px; font-size: 0.88rem; font-weight: 700; color: var(--navy); }
.hours-row input[type=time] { padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-sm); font-family: inherit; font-size: 0.9rem; }
.hours-sep { color: var(--muted); }
form.stacked .hours-closed { flex-direction: row; align-items: center; gap: 6px; font-weight: 400; font-size: 0.85rem; color: var(--muted); }
form.stacked .hours-closed input { margin: 0; }
.hours-field > label:last-child { margin-top: 12px; }
.media-field input[type=file], .menu-field input[type=file] { border: 1.5px dashed var(--line); border-radius: var(--r-sm); padding: 12px; background: var(--bg); font-size: 0.85rem; width: 100%; }
.menu-field[hidden], .specials-field[hidden] { display: none; }
.amenity-checks { display: grid; grid-template-columns: repeat(auto-fit, minmax(176px, 1fr)); gap: 7px; }
form.stacked .day-check { flex-direction: row; align-items: center; gap: 6px; font-weight: 400; font-size: 0.85rem; color: var(--ink-soft); }
.special-row { border: 1px solid var(--line); border-radius: var(--r-sm); padding: 14px 16px; margin-bottom: 13px; background: #fff; display: flex; flex-direction: column; gap: 11px; }
.special-row.empty { background: var(--bg); }
.special-row-main { display: flex; gap: 12px; flex-wrap: wrap; }
.special-row-main label:first-child { flex: 3; min-width: 200px; }
.special-row-main label:last-child { flex: 1; min-width: 105px; }
.special-days { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
.special-days-label { font-size: 0.85rem; font-weight: 700; color: var(--navy); }
.special-days .field-help { margin: 0; }
.media-existing-grid { display: flex; flex-wrap: wrap; gap: 11px; margin-bottom: 13px; }
form.stacked .media-existing { flex-direction: column; align-items: flex-start; gap: 6px; font-weight: 400; font-size: 0.78rem; background: #fff; border: 1px solid var(--line); border-radius: var(--r-sm); padding: 9px; }
.media-existing img { width: 94px; height: 70px; object-fit: cover; border-radius: 7px; }
.media-existing-label { color: var(--muted); }
.media-move { display: flex; align-items: center; gap: 4px; }
.media-move-btn {
  width: 24px; height: 24px; padding: 0; line-height: 1; font-size: 0.8rem;
  border: 1px solid var(--line); border-radius: 5px; background: #fff; cursor: pointer;
}
.media-move-btn:hover:not(:disabled) { background: var(--bg); }
.media-move-btn:disabled { opacity: 0.3; cursor: default; }
.media-remove { display: flex; align-items: center; gap: 5px; cursor: pointer; }

/* ---- emergency --------------------------------------------------------- */

.emergency-primary { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px; margin: 24px 0 32px; }
.emergency-card { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r); padding: 22px; display: flex; flex-direction: column; gap: 5px; text-align: center; box-shadow: var(--shadow-sm); }
.emergency-card:hover { text-decoration: none; box-shadow: var(--shadow); transform: translateY(-2px); }
.emergency-card.urgent { background: #b4432f; border-color: #b4432f; color: #fff; }
.emergency-card.urgent span { color: #fff; }
.emergency-number { font-family: var(--font-hero); font-style: italic; font-size: 2.3rem; color: var(--navy); line-height: 1.1; }
.emergency-group { margin-top: 28px; }

/* ---- stats & admin ----------------------------------------------------- */

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 16px; margin: 22px 0 30px; }
.stat-card { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r); padding: 20px; display: flex; flex-direction: column; gap: 3px; box-shadow: var(--shadow-sm); }
.stat-card:hover { text-decoration: none; box-shadow: var(--shadow); }
.stat-value { font-family: var(--font-hero); font-style: italic; font-size: 2.3rem; color: var(--navy); line-height: 1.1; letter-spacing: -0.02em; }
.stat-label { font-size: 0.9rem; color: var(--ink); }
.stat-note { font-size: 0.78rem; color: var(--muted); }
.stat-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); gap: 11px; margin: 14px 0 20px; }
.stat-cell { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r); padding: 14px 16px; display: flex; flex-direction: column; gap: 2px; }
.stat-cell-value { font-family: var(--font-hero); font-style: italic; font-size: 1.8rem; color: var(--navy); line-height: 1.1; }
.stat-cell-label { font-size: 0.82rem; }
.stat-cell-note { font-size: 0.73rem; color: var(--muted); }
.listing-stats { margin-bottom: 26px; }
.stats-history summary { cursor: pointer; font-size: 0.86rem; color: var(--teal-deep); font-weight: 700; }
.stats-heading { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); margin: 16px 0 0; font-family: var(--font-body); font-style: normal; }
.stat-inline { white-space: nowrap; font-variant-numeric: tabular-nums; }
.stats-empty { font-size: 0.88rem; }

.admin-bar { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; border-bottom: 1px solid var(--line); padding-bottom: 14px; margin-bottom: 28px; }
.admin-nav { display: flex; gap: 6px; flex-wrap: wrap; }
.admin-nav a { padding: 8px 16px; border-radius: var(--r-pill); font-size: 0.9rem; color: var(--ink-soft); }
.admin-nav a:hover { background: var(--surface-tint); text-decoration: none; }
.admin-nav a.active { background: var(--navy); color: #fff; }
.admin-count { display: inline-block; background: var(--coral); color: #fff; font-size: 0.7rem; font-weight: 700; border-radius: var(--r-pill); padding: 1px 8px; margin-left: 7px; }
.admin-nav a.active .admin-count { background: rgba(255,255,255,0.3); }

.listings-search { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.listings-search input[type=search] { flex: 1; min-width: 220px; padding: 9px 12px; border: 1px solid var(--line); border-radius: var(--r-sm); font-size: 0.9rem; }

table.admin-table { width: 100%; border-collapse: collapse; margin-top: 18px; background: var(--surface); border-radius: var(--r); overflow: hidden; box-shadow: var(--shadow-sm); }
table.admin-table th, table.admin-table td { text-align: left; padding: 13px 14px; border-bottom: 1px solid var(--line-soft); font-size: 0.9rem; }
table.admin-table th { background: var(--surface-tint); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
table.admin-table form { display: inline; }
table.admin-table th a.sort-link { color: inherit; text-decoration: none; }
table.admin-table th a.sort-link:hover { color: var(--ink); }
table.admin-table th a.sort-link.active { color: var(--ink); font-weight: 700; }
.stale-flag { color: #b4432f; font-weight: 700; }
.pill-status { display: inline-block; font-size: 0.72rem; padding: 3px 10px; border-radius: var(--r-pill); background: var(--surface-tint); color: var(--ink-soft); margin-left: 6px; }
.pill-status.pending, .pill-status.new { background: var(--teal-wash); color: var(--teal-deep); }
.pill-status.actioned, .pill-status.approved, .pill-status.active { background: #e8f1e9; color: #33684a; }
.pill-status.archived, .pill-status.rejected, .pill-status.paused { background: var(--surface-tint); color: var(--muted); }
.pill-status.featured { background: var(--sand); color: #fff; }
.pill-status.tickets { background: var(--coral-wash); color: #b4502e; }
.pill-status.overdue { background: #fdeeea; color: #93331d; }
.billing-cell .pill-status { margin-left: 0; }
.billing-due { display: block; font-size: 0.72rem; color: var(--muted); margin-top: 2px; }
.admin-media { white-space: nowrap; }
.admin-media img { width: 40px; height: 40px; object-fit: cover; border-radius: 7px; border: 1px solid var(--line); margin-right: 5px; vertical-align: middle; }
.admin-file { font-size: 0.78rem; margin-right: 7px; }
.admin-media-grid { display: flex; flex-wrap: wrap; gap: 13px; margin-top: 12px; }
.admin-media-grid a { display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 0.78rem; }
.admin-media-grid img { width: 100px; height: 74px; object-fit: cover; border-radius: var(--r-sm); border: 1px solid var(--line); }
.row-thumb { width: 32px; height: 32px; object-fit: cover; border-radius: 6px; border: 1px solid var(--line); margin-right: 9px; vertical-align: middle; }
.row-actions { white-space: nowrap; }
.row-actions a { margin-right: 9px; font-size: 0.85rem; }
.review-comment { max-width: 330px; font-size: 0.86rem; }
.mail-failed { color: #b4432f; font-size: 0.8rem; font-weight: 700; }
.danger-form { margin-top: 30px; padding-top: 20px; border-top: 1px solid var(--line); }
.inline-actions { display: inline-flex; gap: 7px; flex-wrap: wrap; }

.owner-who { display: flex; align-items: center; gap: 14px; }
.owner-listing { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r-lg); padding: 22px; margin-bottom: 18px; box-shadow: var(--shadow-sm); }
.owner-listing-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.owner-listing-head h2 { margin: 0; font-size: 1.2rem; }
.owner-listing-actions { margin-left: auto; display: flex; align-items: center; gap: 9px; }
.owner-review { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r); padding: 18px 20px; margin-bottom: 15px; box-shadow: var(--shadow-sm); }
.reply-form { margin-top: 14px; max-width: none; }
.reply-form textarea { min-height: 74px; }

/* ---- adverts ----------------------------------------------------------- */

.banner-slot { margin: 22px 0; text-align: center; }
.banner-slot img { max-width: 100%; height: auto; border-radius: var(--r); border: 1px solid var(--line-soft); display: block; margin: 0 auto; box-shadow: var(--shadow-sm); }
.banner-tag { display: block; font-size: 0.65rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; margin-top: 6px; }

.promo-ad { margin: 22px 0; }
.promo-ad-inner {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 10px;
  min-height: 220px;
  padding: 22px 26px;
  border-radius: var(--r);
  overflow: hidden;
  color: #fff;
  text-decoration: none;
  background: linear-gradient(100deg, rgba(0,42,69,0.92) 0%, rgba(0,42,69,0.78) 32%, rgba(0,42,69,0.25) 62%, rgba(0,42,69,0.05) 100%), url('/public/brand/hero-coast-1200.jpg') center/cover no-repeat;
  box-shadow: var(--shadow-sm);
}
.promo-ad-badge { position: absolute; top: 20px; left: 24px; width: 46px; height: 46px; border-radius: 50%; background: #fff; display: flex; align-items: center; justify-content: center; overflow: hidden; box-shadow: 0 1px 4px rgba(0,0,0,0.3); }
.promo-ad-badge img { width: 34px; height: 34px; object-fit: contain; }
.promo-ad-copy { max-width: 480px; margin-top: 44px; }
.promo-ad-headline { display: block; font-size: 1.35rem; font-style: italic; line-height: 1.25; }
.promo-ad-sub { display: block; margin-top: 6px; font-size: 0.85rem; opacity: 0.9; }
.promo-ad-cta { display: inline-block; align-self: flex-start; margin-top: 4px; padding: 11px 22px; border-radius: 999px; background: var(--coral); color: #fff; font-weight: 600; font-size: 0.92rem; }
@media (max-width: 640px) {
  .promo-ad-inner { min-height: 240px; padding: 18px; }
  .promo-ad-headline { font-size: 1.1rem; }
}

/* ---- events ------------------------------------------------------------ */

.event-poster { max-width: 100%; width: auto; max-height: 480px; border-radius: var(--r); border: 1px solid var(--line-soft); display: block; margin: 20px 0; box-shadow: var(--shadow-sm); }
.ticket-cta { margin: 24px 0; }

/* ---- footer ------------------------------------------------------------ */

.site-footer { background: var(--navy); color: #cfe2ea; padding: 46px 22px 34px; font-size: 0.9rem; margin-top: 64px; }
.footer-top { display: flex; gap: 30px; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; margin-bottom: 26px; }
/* Badges stay horizontal, in line with the brand mark, at every ordinary
   browser width; only a genuinely narrow frame (small phone viewport, or
   the Capacitor app's own webview width) drops them below it — see the
   560px override further down. */
.footer-top-brand-row { display: flex; align-items: center; justify-content: space-between; gap: 20px 28px; flex: 1 1 100%; flex-wrap: nowrap; }
.footer-brand { display: flex; align-items: center; gap: 14px; min-width: 0; }
.footer-app-badges { display: flex; align-items: center; gap: 10px; flex-wrap: nowrap; flex-shrink: 0; }
/* Someone already inside the installed app has no need to be told to
   download it — same reasoning as the QR below, same body.is-app-shell
   hook the bottom tab bar sets. */
body.is-app-shell .footer-app-badges { display: none; }
.footer-app-badges-stack { display: flex; flex-direction: column; gap: 6px; }
.app-badge-sm { padding: 6px 12px; gap: 8px; border: 1px solid rgba(255, 255, 255, 0.5); }
.app-badge-sm svg { width: 20px; height: 20px; flex-shrink: 0; }
.app-badge-sm .app-badge-text { font-size: 13px; }
@media (max-width: 560px) {
  .footer-top-brand-row { flex-wrap: wrap; }
}
.app-badge-sm .app-badge-text small { font-size: 9px; }
@media (max-width: 480px) { .footer-app-badges { flex-wrap: wrap; } }

/* ---- scan-to-download QR (desktop only, footer) -------------------------
   Sits beside the stacked App Store/Google Play badges in the footer. A
   phone browsing the mobile site is already the device you'd install on,
   and the Capacitor app has no need to advertise itself to someone already
   inside it — so this hides below 860px and inside the app shell
   (body.is-app-shell, the same hook the bottom tab bar uses) rather than
   relying on every call site to remember to check. */
.app-qr {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  text-decoration: none; flex-shrink: 0;
}
.app-qr img {
  display: block; border-radius: 10px; background: #fff; padding: 6px;
  box-shadow: var(--shadow-sm); border: 1px solid var(--line-soft);
}
@media (max-width: 860px) {
  .app-qr { display: none; }
}
body.is-app-shell .app-qr { display: none; }
.footer-brand img { width: 54px; height: 54px; border-radius: 50%; background: #fff; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18); }
.footer-brand-name { font-family: var(--font-display); font-style: italic; font-size: 1.35rem; color: #fff; display: block; line-height: 1.1; }
.footer-brand-towns { font-size: 0.78rem; letter-spacing: 0.06em; text-transform: uppercase; color: #8fb4c6; }
.site-footer p { margin: 5px 0; }
.footer-links { font-size: 0.88rem; display: flex; gap: 8px 18px; flex-wrap: wrap; }
.footer-links a { color: #cfe2ea; }
.footer-links a:hover { color: #fff; }
.footer-base { border-top: 1px solid rgba(255,255,255,0.13); padding-top: 20px; font-size: 0.82rem; color: #8fb4c6; }
.footer-base a { color: #cfe2ea; }

/* ---- about / advertise pages ------------------------------------------- */

.page-hero { position: relative; border-radius: var(--r-lg); overflow: hidden; margin-bottom: 32px; background: var(--navy); }
.page-hero img { width: 100%; height: 340px; object-fit: cover; display: block; }
.page-hero-text { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center; padding: clamp(22px, 5vw, 50px); }
/* Same stroke-and-shadow outline as the home hero's h1/hero-towns, so the type
   stays legible over the photo without dimming the image itself. */
.page-hero-text h1 {
  font-family: var(--font-hero); color: #fff; margin: 0 0 6px; letter-spacing: -0.02em;
  -webkit-text-stroke: 1.2px var(--charcoal);
  paint-order: stroke fill;
  text-shadow: 0 2px 18px rgba(0,30,50,0.45);
}
.page-hero-text p {
  color: #fff; margin: 0; max-width: 48ch;
  -webkit-text-stroke: 0.6px var(--charcoal);
  paint-order: stroke fill;
  text-shadow: 0 1px 8px rgba(0, 22, 38, 0.3);
}

.value-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; margin: 22px 0 8px; }
@media (max-width: 860px) { .value-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .value-grid { grid-template-columns: 1fr; } }
/* Advertise page's "What else do you get?" — same cards, two per row instead
   of three, since there are only four of them. */
.value-grid.value-grid-2col { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 560px) { .value-grid.value-grid-2col { grid-template-columns: 1fr; } }
.value-card { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r); padding: 22px; box-shadow: var(--shadow-sm); }
.value-card h3 { margin: 0 0 8px; font-size: 1.05rem; }
.value-card p { margin: 0; font-size: 0.93rem; color: var(--ink-soft); }
.value-icon { font-size: 1.5rem; display: block; margin-bottom: 10px; }

.package-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: 22px; margin: 24px 0; align-items: start; }
.package { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r-lg); padding: 28px; box-shadow: var(--shadow-sm); position: relative; }
.package.featured-pack { border-color: var(--teal); box-shadow: var(--shadow); }
.package-tag { position: absolute; top: -13px; right: 24px; background: var(--teal); color: #fff; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; padding: 5px 14px; border-radius: var(--r-pill); }
.package h3 { font-size: 1.5rem; margin: 0 0 4px; }
.package-price { font-family: var(--font-hero); font-style: italic; font-size: 2.7rem; color: var(--teal-deep); line-height: 1.1; letter-spacing: -0.02em; }
.package-price span { font-family: var(--font-body); font-style: normal; font-size: 0.9rem; color: var(--muted); }
.package-term { font-size: 0.86rem; color: var(--muted); margin: 2px 0 18px; }
.package ul { list-style: none; padding: 0; margin: 0 0 22px; display: grid; gap: 8px; }
.package li { font-size: 0.91rem; color: var(--ink-soft); padding-left: 26px; position: relative; }
.package li::before { content: '✓'; position: absolute; left: 0; color: var(--teal); font-weight: 700; }
.founding-banner { background: linear-gradient(160deg, #fff 0%, var(--gold-wash) 130%); border: 1px solid #f0e2bb; border-radius: var(--r-lg); padding: 14px 20px; margin: 0 0 6px; text-align: center; font-size: 0.96rem; }
.submit-alt { color: var(--muted); margin: 4px 0 0; }
.submit-alt-actions { display: flex; flex-wrap: wrap; gap: 10px; margin: 10px 0 26px; }
.founding-fineprint { font-size: 0.82rem; color: var(--muted); text-align: center; margin: -4px 0 30px; }
.package-tag-offer { background: var(--coral); left: auto; }
.package-tag-offer-left { right: auto; left: 24px; }
.price-was { font-size: 1.4rem; color: var(--muted); text-decoration: line-through; opacity: 0.7; margin-right: 6px; }

.rate-table { width: 100%; border-collapse: collapse; margin: 18px 0 8px; background: var(--surface); border-radius: var(--r); overflow: hidden; box-shadow: var(--shadow-sm); }
.rate-table th, .rate-table td { text-align: left; padding: 13px 16px; border-bottom: 1px solid var(--line-soft); font-size: 0.92rem; }
.rate-table th { background: var(--surface-tint); font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.rate-table td:last-child { text-align: right; font-weight: 700; color: var(--navy); white-space: nowrap; }

/* Full-width photo band — same width as the page hero. Photo and caption
   share one grid cell (a stack, not an overlay via position:absolute) so
   that on a narrow screen, where the overlaid copy needs more height than
   the photo's own ratio provides, the row grows to fit the text instead of
   clipping it — the photo (height:100%, object-fit:cover) just fills
   whatever height results. */
.coast-band {
  display: grid; grid-template-areas: "stack"; border-radius: var(--r-lg); overflow: hidden;
  margin: 34px 0; background: var(--navy); isolation: isolate;
}
.coast-band img { grid-area: stack; width: 100%; height: 100%; min-height: 0; object-fit: cover; display: block; }
.coast-band-text {
  grid-area: stack; align-self: end; z-index: 1; padding: clamp(20px, 5vw, 48px);
  background: linear-gradient(to top, rgba(0, 20, 34, 0.62) 0%, rgba(0, 20, 34, 0.32) 55%, transparent 100%);
}
.coast-band-text h2 {
  color: #fff; margin: 0 0 10px;
  -webkit-text-stroke: 1.2px var(--charcoal);
  paint-order: stroke fill;
  text-shadow: 0 2px 18px rgba(0, 30, 50, 0.45);
}
.coast-band-text p {
  color: #fff; margin: 0; max-width: 68ch;
  -webkit-text-stroke: 0.5px var(--charcoal);
  paint-order: stroke fill;
  text-shadow: 0 1px 8px rgba(0, 22, 38, 0.35);
}
.cta-band { background: linear-gradient(135deg, var(--navy) 0%, var(--navy-soft) 100%); color: #fff; border-radius: var(--r-lg); padding: clamp(28px, 5vw, 48px); margin: 40px 0 0; text-align: center; }
.cta-band h2 { color: #fff; margin: 0 0 10px; }
.cta-band p { color: rgba(255,255,255,0.9); max-width: 52ch; margin: 0 auto 22px; }
.cta-band p.cta-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; max-width: none; }
.cta-band .btn { background: var(--teal); }
.cta-band .btn:hover { background: #fff; color: var(--navy); }
.cta-band .btn-secondary { background: transparent; border-color: rgba(255,255,255,0.5); color: #fff; }
.cta-band .btn-secondary:hover { background: rgba(255,255,255,0.14); color: #fff; }

/* ---- "coming soon" app store badges ------------------------------------ */
.app-badges { display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center; margin: 28px 0; }
.app-badges-heading { margin: 0; font-weight: 700; color: var(--navy); }
.app-badge-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }
.app-badge { display: inline-flex; align-items: center; gap: 10px; background: #000; color: #fff; border-radius: var(--r-sm); padding: 8px 16px; text-decoration: none; }
.app-badge svg { flex-shrink: 0; }
.app-badge-text { display: flex; flex-direction: column; line-height: 1.2; text-align: left; font-size: 15px; font-weight: 600; }
.app-badge-text small { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.8; }

/* ---- colour-coded sections ---------------------------------------------
   Each part of the site gets its own accent so a page is readable at a
   glance: teal for the sea and everyday browsing, coral for what's on
   offer now, dusk for what's happening, gold for quality. Used as tints
   and small marks, never as large blocks — the site stays light. */

.band {
  border-radius: var(--r-lg); padding: 30px clamp(20px, 3vw, 34px); margin: 40px 0;
}
.band-cream { background: linear-gradient(160deg, #fff 0%, var(--cream) 130%); border: 1px solid #f2e2cf; }
.band-sky { background: linear-gradient(160deg, #fff 0%, var(--sky-wash) 120%); border: 1px solid #dceef6; }
.band-dusk { background: linear-gradient(160deg, #fff 0%, var(--dusk-wash) 130%); border: 1px solid #e2e5f4; }
.band-gold { background: linear-gradient(160deg, #fff 0%, var(--gold-wash) 130%); border: 1px solid #f0e2bb; }
/* Same wash as the weather-and-tides panel, so Local News reads as its
   sibling rather than borrowing Beaches' lighter sky-blue. */
.band-teal { background: linear-gradient(160deg, #fff 0%, var(--teal-wash) 130%); border: 1px solid #d9edf0; }
.band > h2:first-child, .band > .section-head:first-child { margin-top: 0; }

/* "Search by location" band: shared between the home page and the
   no-location state of /near-me itself. */
.near-me-band p { margin: 0 0 18px; max-width: 56ch; }
.near-me-band .near-me-status { margin: 12px 0 0; max-width: 56ch; }

/* section heads carry the accent of the thing they introduce */
.section-head.is-specials h2 { color: var(--coral); }
.section-head.is-events h2 { color: var(--dusk); }
.section-head.is-featured h2 { color: var(--sand-deep); }

/* ratings in sunset gold rather than a generic amber */
.rating { color: var(--gold); }

/* pills, in the accent of what they mean */
.open-pill.is-open { background: var(--seafoam-wash); color: #2c7f5c; border-color: #bfe6d3; }
.special-pill { background: var(--coral-wash); color: #b4502e; border-color: #f6d3c4; }
.pill-status.tickets { background: var(--dusk-wash); color: var(--dusk); }
.today-tag { background: var(--coral); }

/* events take the dusk accent throughout */
.btn-tickets { background: var(--dusk); }
.btn-tickets:hover { background: #46589a; }
.event-poster { border-color: #e2e5f4; }

/* specials keep coral */
.special-price { background: var(--coral); }
.special-list li.running { border-color: #f2cdbb; }

/* a warm divider for long pages */
.hr-shell { border: none; height: 1px; background: linear-gradient(90deg, transparent, var(--line), transparent); margin: 46px 0; }

/* ---- responsive -------------------------------------------------------- */

@media (max-width: 900px) {
  .cond-body { grid-template-columns: 1fr; gap: 20px; }
  .cond-tides { border-left: none; border-top: 1px solid #cfe7ea; padding-left: 0; padding-top: 18px; }
  /* This much copy doesn't fit "over the bottom half" of the photo below
     tablet widths without either clipping or crowding the busy logo art
     higher up the image — so the two stack instead: full photo, then the
     same white-on-navy heading and copy as a solid panel underneath. */
  .coast-band { display: block; }
  .coast-band img { width: 100%; height: auto; }
  .coast-band-text { background: var(--navy); }
}

@media (max-width: 640px) {
  body { font-size: 16px; }
  .header-inner { position: relative; padding: 10px 16px; gap: 8px; flex-wrap: nowrap; }
  .brand img { width: 38px; height: 38px; }
  .brand-name { font-size: 1.15rem; }
  .brand-eyebrow { font-size: 0.7rem; }
  /* A "Menu" button that expands into a full dropdown of every heading, rather
     than a scrolling row of pills or a nav block that pushes the hero off screen. */
  .nav-toggle { display: flex; }
  .nav {
    display: none; flex-direction: column; align-items: stretch; gap: 2px;
    position: absolute; left: 0; right: 0; top: 100%;
    background: var(--surface); border-bottom: 1px solid var(--line-soft);
    padding: 10px 16px 16px; box-shadow: var(--shadow);
  }
  .nav.is-open { display: flex; }
  .nav a { font-size: 0.98rem; padding: 12px 14px; border-radius: var(--r-sm); text-align: left; }
  .nav .nav-cta { margin-top: 6px; text-align: center; }
  .header-inner { align-items: center; }
  .main { padding: 22px 16px 60px; }
  .wrap { padding: 0 16px; }
  .hero { aspect-ratio: auto; min-height: 400px; }
  .search-box form { flex-direction: column; }
  .search-box button { width: 100%; }
  .panels { grid-template-columns: 1fr; }
  .map-frame iframe { height: 230px; }
  .listing-detail .header { gap: 14px; }
  .listing-logo { width: 68px; height: 68px; }
  .menu-pdf-preview { height: 420px; }
  .lightbox { padding: 14px; }
  .lightbox-nav { width: 40px; height: 40px; }
  .hours-day { flex: 0 0 100%; }
  .map-actions .btn { flex: 1; }
  .special-price { margin-left: 0; }
  .map-picker-frame { height: 260px; }
  .map-picker-bar { flex-direction: column; align-items: stretch; }
  .map-picker-buttons .btn { flex: 1; }
  .cat-hero { flex-direction: column; gap: 14px; padding: 20px; }
  .cat-hero-icon { width: 52px; height: 52px; }
  .grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 18px; }
  .cat-grid { grid-template-columns: 1fr; }
  .owner-listing-actions { margin-left: 0; width: 100%; }
  .stat-strip { grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); }
  .results-map-body iframe { height: 265px; }
  .map-legend li { flex-wrap: wrap; }
  .admin-table { font-size: 0.8rem; }
  .review-comment { max-width: none; }
  table.admin-table th, table.admin-table td { padding: 10px 9px; }
}

/* ---- listing form: plan gating ---- */

/* Fields the package closes off are hidden with the `hidden` attribute, which a
   component's own `display` rule would otherwise beat. Scoped to the gated
   elements so it can't affect anything else. */
[data-plan-needs][hidden],
[data-plan-locked][hidden] {
  display: none !important;
}

/* Publishing sits first on the form now, so it reads as the decision the rest
   of the form follows from. */
form.stacked .publish-field.is-first {
  border-color: var(--gold, #c9a227);
  background: rgba(201, 162, 39, 0.06);
}

.extraphone-field .special-row-main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: 0.6rem;
  margin-bottom: 0.6rem;
}
@media (max-width: 560px) {
  .extraphone-field .special-row-main { grid-template-columns: 1fr; }
}

/* ---- social feeds (Whale) ---- */

.social-feeds { margin: 2rem 0; }

.feed-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1rem;
}

.feed-card {
  --feed-tone: var(--navy-soft, #33556f);
  border: 1px solid var(--line, #e2dfd8);
  border-radius: var(--radius, 14px);
  background: var(--card, #fff);
  overflow: hidden;
  min-height: 220px;
  display: flex;
  flex-direction: column;
}
.feed-card.tone-facebook { --feed-tone: #1877f2; }
.feed-card.tone-x        { --feed-tone: #111; }
.feed-card.tone-tiktok   { --feed-tone: #d81f4a; }

.feed-facade {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 1.75rem 1.25rem;
  text-align: center;
}
.feed-icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  color: #fff;
  background: var(--feed-tone);
}
.feed-name { margin: 0; font-weight: 600; }
.feed-note { margin: 0; font-size: 0.8rem; color: var(--muted, #6b7280); }
.feed-open { font-size: 0.82rem; }

.feed-card.is-loaded { min-height: 0; }
.feed-card iframe { width: 100%; border: 0; display: block; min-height: 560px; }
.feed-card .twitter-timeline { width: 100%; }
.feed-foot { margin: 0; padding: 0.7rem 1rem; border-top: 1px solid var(--line, #e2dfd8); text-align: center; }
.feed-foot .feed-open { font-size: 0.82rem; }
.feed-card.is-loaded .feed-foot { background: var(--sand-soft, #faf8f4); }
.feed-failed { padding: 0.9rem 1rem; text-align: center; }
/* Once widgets.js has rendered the timeline, its placeholder anchor is noise. */
.feed-card:has(.twitter-timeline-rendered) a.twitter-timeline,
.feed-card a.twitter-timeline[hidden] { display: none; }

/* A loaded card keeps its network name on top. X and TikTok both throttle
   third-party embeds and can return an empty frame; when that happens the
   visitor should still be able to see whose feed failed and click through. */
.feed-head {
  display: none;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  padding: 0.6rem 1rem;
  border-bottom: 1px solid var(--line, #e2dfd8);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--feed-tone);
}
.feed-card.is-loaded .feed-head { display: flex; }
.feed-card.is-loaded { order: 0; }

/* Town tiles sit three to a row rather than reflowing to whatever fits.
   Drops to two, then one, on narrower screens. */
.town-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 860px) { .town-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .town-grid { grid-template-columns: 1fr; } }
/* Town blurbs run a full sentence longer than a typical card tagline, so
   these get a bit more room — taller body padding and a higher line-clamp —
   rather than clipping mid-sentence like the generic card does. */
.town-grid .card-body { padding: 20px 22px 22px; gap: 8px; }
.town-grid .card h3 { font-size: 1.15rem; }
.town-grid .tagline { -webkit-line-clamp: 5; font-size: 0.92rem; }

/* Tide times are rounded to the half hour and shown as estimates — the "≈" is
   the visible cue, with "about" read out to screen readers instead. */
.tide-approx { opacity: 0.7; font-weight: 400; }

/* ---- local radio bar ---- */

/* Plain white — the Local News band above it now carries the light-blue
   wash, and alternating the two keeps the stack from reading as one slab. */
.radio-bar {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  padding: 18px 22px 20px;
  margin: 16px 0;
}

/* The two local papers on /news — logo, one-line tagline, a button out to
   this week's e-edition, and a quieter link into their own listing page. */
.newspaper-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin: 16px 0 28px; }
.newspaper-tile {
  background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm); padding: 24px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
}
.newspaper-logo { max-width: 280px; max-height: 90px; width: auto; height: auto; object-fit: contain; margin-bottom: 4px; }
.newspaper-tile .tagline { color: var(--ink-soft); font-size: 0.9rem; margin: 0 0 10px; line-height: 1.4; }
.newspaper-tile .btn { margin-bottom: 6px; }
.newspaper-more { font-size: 0.86rem; }

.radio-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.radio-head-icon { font-size: 1.05rem; }
.radio-head h2 { margin: 0; font-size: 1.06rem; letter-spacing: 0.01em; }

/* 300px, not 260 — the logo eats horizontal space, and below this the station
   name starts wrapping mid-phrase. Better to drop to one column. */
.radio-stations { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 12px; }

.radio-station {
  display: flex;
  align-items: center;
  gap: 12px;
  /* Grid items default to min-width:auto and so refuse to shrink below their
     content. With the logo added that min-content width exceeds a narrow phone
     column and pushed the whole page sideways. Letting the tile shrink hands
     the squeeze to the labels, which are set to ellipsis. */
  min-width: 0;
  border: 1px solid var(--line-soft, #e8e4dc);
  border-radius: 10px;
  padding: 18px 18px 18px 16px;
  background: var(--bg, #fbf8f4);
}

.radio-play {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  background: none;
  border: 0;
  padding: 4px;
  margin: 0;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  border-radius: 8px;
  min-width: 0;
}
.radio-play:focus-visible { outline: 2px solid var(--teal, #2b8a8a); outline-offset: 2px; }

.radio-icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--navy, #123a5a);
  color: #fff;
  transition: background 0.15s ease;
}
.radio-play:hover .radio-icon { background: var(--teal, #2b8a8a); }

/* The station's own mark, sized for recognition rather than reading — the name
   sits right beside it. White-background marks get a hairline so they don't
   bleed into the tile. */
.radio-logo {
  flex: none;
  width: 88px;
  height: 88px;
  object-fit: contain;
  border-radius: 10px;
  background: #fff;
  border: 1px solid var(--line-soft, #e8e4dc);
  padding: 4px;
}

.radio-labels { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.radio-labels strong { font-size: 1.06rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.radio-labels .muted { font-size: 0.84rem; }

.radio-state { flex: none; margin-left: auto; font-size: 0.72rem; color: var(--muted, #6b7280); }
.radio-site { flex: none; font-size: 0.74rem; white-space: nowrap; }

/* Playing: the tile lifts so it is obvious which one is live. */
.radio-station[data-radio-state='playing'] { border-color: var(--teal, #2b8a8a); background: rgba(43, 138, 138, 0.07); }
.radio-station[data-radio-state='playing'] .radio-icon { background: var(--teal, #2b8a8a); }
.radio-station[data-radio-state='playing'] .radio-state { color: var(--teal, #2b8a8a); font-weight: 600; }

.radio-station[data-radio-state='error'] .radio-icon { background: var(--muted, #6b7280); }
.radio-station[data-radio-state='error'] .radio-logo { filter: grayscale(1); opacity: 0.65; }
.radio-station[data-radio-state='error'] .radio-state { color: var(--muted, #6b7280); }

@media (max-width: 560px) {
  .radio-stations { grid-template-columns: 1fr; }
  .radio-state { display: none; }
  /* A phone has no room for an 88px logo, a 40px play control, the station name
     and a link on one line — at 375px that left about 45px for the name and
     clipped it to "Cal…". The logo comes down and the station link drops to its
     own line, which gives the name the width it needs. */
  .radio-logo { width: 64px; height: 64px; }
  .radio-station { flex-wrap: wrap; padding: 14px; }
  .radio-play { flex: 1 1 100%; }
  .radio-site { margin-left: auto; }
}

/* Call and Email sit alongside WhatsApp and Save to contacts. WhatsApp keeps
   its brand green as the one people recognise; these two stay in the site
   palette so the row reads as one set of actions rather than four logos. */
.btn-call, .btn-email {
  display: inline-flex; align-items: center; gap: 9px;
  background: var(--navy); color: #fff; border: 1px solid var(--navy);
}
.btn-call:hover, .btn-email:hover { background: var(--navy-soft, #33556f); border-color: var(--navy-soft, #33556f); color: #fff; }
.btn-call svg, .btn-email svg { flex: 0 0 auto; }
/* Height only appears with a harmonic prediction — the model's heights are
   relative to mean sea level and not comparable to a tide table. */
.tide-height { display: block; font-size: 0.72rem; color: var(--muted, #6b7280); margin-top: 2px; }

/* Emergency contact names are longer than the labels this table was built for,
   so the label column gets more room on that page only. */
.emergency-group .info-table td:first-child { width: 210px; }
@media (max-width: 560px) {
  .emergency-group .info-table td:first-child { width: 130px; }
}

/* ---- home page: randomised sections ---- */
/* Local News, Today's Specials, Featured, Local Lowdown, Beaches and Browse
   by category all used to be fixed grids here (grid-one-row / cat-grid-home)
   — replaced by the scroll rails defined alongside .cat-strip above, so a
   phone-width viewport (including the Android/iOS app WebViews) gets a
   horizontal swipe instead of everything stacking into a long vertical
   column. */

/* ---------- Breadcrumbs and "back" ----------
   The full trail on wide screens; on phones a single "‹ Parent" link (the same
   trail, collapsed). public/js/back-nav.js turns that link into a real back step
   when the visitor came from the parent. In the app both are hidden and the
   header carries a back button instead. */
.crumbs { margin: 0 0 14px; font-size: 0.88rem; color: var(--ink-soft); }
.crumbs-trail { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 0; list-style: none; margin: 0; padding: 0; }
.crumbs-trail li { display: inline-flex; align-items: center; min-width: 0; }
.crumbs-trail li + li::before { content: '\203A'; margin: 0 8px; color: var(--muted); }
.crumbs-trail a { color: var(--teal-deep); }
.crumbs-trail [aria-current="page"] { color: var(--ink); font-weight: 600; max-width: 40ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.crumbs-back { display: none; align-items: center; gap: 4px; min-height: 44px; font-size: 0.95rem; font-weight: 600; color: var(--teal-deep); }
.crumbs-back span[aria-hidden] { font-size: 1.5rem; line-height: 1; margin-top: -2px; }
@media (max-width: 720px) {
  .crumbs { margin-bottom: 4px; }
  .crumbs-trail { display: none; }
  .crumbs-back { display: inline-flex; }
}
.back-link { color: var(--teal-deep); font-weight: 600; }
body.is-app-shell .crumbs { display: none; }

/* App: a back button at the left of the header, on every page except the four
   tab roots. The logo stays beside it; the Menu button stays pinned right. */
.app-back {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; padding: 0; cursor: pointer;
  background: none; border: 1px solid var(--line); border-radius: 50%;
  color: var(--navy); -webkit-tap-highlight-color: transparent;
}
.app-back:active { background: var(--teal-wash); }
body.is-app-shell .header-inner { justify-content: flex-start; gap: 10px; padding-left: 14px; padding-right: 14px; }
body.is-app-shell .nav-toggle { margin-left: auto; }

/* "Prefer not to type it all in yourself?" tick box on the List your business form */
form.stacked .assist-option { flex-direction: row; align-items: flex-start; gap: 10px; font-weight: 400; padding: 12px 14px; border: 1px solid var(--line-soft); border-radius: 8px; background: var(--surface); }
form.stacked .assist-option input { margin: 3px 0 0; flex: none; width: 20px; height: 20px; padding: 0; }
form.stacked .assist-option > span { min-width: 0; overflow-wrap: anywhere; }
form.stacked .assist-option .assist-option-body { font-weight: 400; }

/* Whale package: the verified business badge beside the price */
.package-price-row { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 16px; }
.package-price-row .package-price { margin: 0; }
.verified-badge { display: inline-flex; align-items: center; gap: 8px; }
.verified-badge img { width: 64px; height: 64px; flex: none; }
.verified-badge span { font-size: 0.85rem; font-weight: 700; color: var(--navy); line-height: 1.2; max-width: 8em; }

/* Verified business: a label at the bottom of a listing tile, and the badge between logo and name on the listing page */
.card-verified { margin: 0; margin-top: auto; padding-top: 10px; }
.card-status + .card-verified { margin-top: 0; }
.verified-pill { display: inline-flex; align-items: center; gap: 5px; font-size: 0.78rem; font-weight: 700; color: var(--teal-deep); background: var(--surface-tint); border: 1px solid var(--line-soft); border-radius: var(--r-pill); padding: 5px 11px; }
.listing-detail .header .verified-mark-page { display: flex; flex-direction: column; align-items: center; gap: 4px; flex: 0 0 auto; width: 84px; text-align: center; }
.listing-detail .header .verified-mark-page img { width: 44px; height: 44px; }
.listing-detail .header .verified-mark-page span { font-size: 0.72rem; font-weight: 700; line-height: 1.15; color: var(--navy); }
.save-toggle-wrap { display: flex; flex-direction: column; align-items: center; gap: 4px; flex: 0 0 auto; width: 84px; text-align: center; }
.save-toggle-label { font-size: 0.72rem; font-weight: 700; line-height: 1.15; color: var(--navy); }
